diff options
author | sotech117 <michael_foiani@brown.edu> | 2023-10-23 03:08:27 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2023-10-23 03:08:27 -0400 |
commit | 7ec4f310ec01100f648a42dd52cb0ac635ac0b10 (patch) | |
tree | ee73018b8018b68201456a4d953f13463fdf0f4d | |
parent | 8f5877a04b3c82f5c298b87f6a0f6356d2acffcd (diff) |
fix wireshark rip packets being malformed
-rw-r--r-- | pkg/ipstack/ipstack.go | 415 | ||||
-rwxr-xr-x | vhost | bin | 3105111 -> 3104785 bytes | |||
-rwxr-xr-x | vrouter | bin | 3105159 -> 3104857 bytes |
3 files changed, 227 insertions, 188 deletions
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go index 9aaee28..8983ef8 100644 --- a/pkg/ipstack/ipstack.go +++ b/pkg/ipstack/ipstack.go @@ -21,10 +21,10 @@ const ( LOCAL_COST uint32 = 0 STATIC_COST uint32 = 4294967295 // 2^32 - 1 MaxEntries = 64 - INFINITY = 15 + INFINITY = 16 SIZE_OF_RIP_ENTRY = 12 SIZE_OF_RIP_MESSAGE = 6 - RIP_PROTOCOL = 12 + RIP_PROTOCOL = 200 TEST_PROTOCOL = 0 ) @@ -45,16 +45,14 @@ type Neighbor struct { UdpAddr netip.AddrPort } -type RIPMessage struct { - command uint8 - numEntries uint8 - entries []RIPEntry +type RIPHeader struct { + command uint16 + numEntries uint16 } type RIPEntry struct { - address uint32 - cost uint32 - mask uint32 + prefix netip.Prefix + cost uint32 } type Hop struct { @@ -471,6 +469,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // Read on the UDP port // Too much printing so I commented it out // fmt.Println("wating to read from UDP socket") + // TODO: this is erroring here!! _, _, err := conn.ReadFromUDP(buffer) if err != nil { return err @@ -587,6 +586,35 @@ func RecvIP(iface *Interface, isOpen *bool) error { // ************************************** RIP Routines ******************************************************* +func makeRipMessage(command uint16, entries []RIPEntry) []byte { + SIZE_OF_RIP_HEADER := 2 * 2 // 2 uint16s + if command == 1 { // request message + buf := make([]byte, SIZE_OF_RIP_HEADER) + binary.BigEndian.PutUint16(buf[0:2], command) + binary.BigEndian.PutUint16(buf[2:4], uint16(0)) + return buf + } + // else, command == 2, response message + + bufLen := SIZE_OF_RIP_HEADER + // sizeof uint16 is 2, we have two of them + len(entries)*SIZE_OF_RIP_ENTRY // each entry is 12 + + buf := make([]byte, bufLen) + + binary.BigEndian.PutUint16(buf[0:2], command) + binary.BigEndian.PutUint16(buf[2:4], uint16(len(entries))) + + mask := netip.MustParseAddr("255.255.255.0") + for i, entry := range entries { + offset := 2*2 + i*SIZE_OF_RIP_ENTRY + binary.BigEndian.PutUint32(buf[offset:offset+4], entry.cost) // 0-3 = 4 bytes + copy(buf[offset+4:offset+8], entry.prefix.Addr().AsSlice()) // 4-7 = 4 bytes + copy(buf[offset+8:offset+12], mask.AsSlice()) // 8-11 = 4 bytes + } + + return buf +} + func periodicUpdateRoutine() { for { // for each periodic update, we want to send our nodes in the table @@ -602,6 +630,7 @@ func periodicUpdateRoutine() { entries := make([]RIPEntry, len(routingTable)) for prefix, hop := range routingTable { // implement split horizon + poison reverse at entry level + fmt.Println("prefix: ", prefix) var cost uint32 if hop.VIP == n.VipAddr { cost = INFINITY @@ -610,14 +639,14 @@ func periodicUpdateRoutine() { } entries = append(entries, RIPEntry{ - address: ConvertIPToUint32(prefix.Addr().String()), - mask: uint32(prefix.Bits()), - cost: cost, + prefix: prefix, + cost: cost, }) } - message := NewRIPMessage(2, entries) - err := SendRIPMessage(*iface, n, message) + message := makeRipMessage(2, entries) + addr := iface.IpPrefix.Addr() + err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) if err != nil { fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String()) continue @@ -647,6 +676,7 @@ func manageTimeoutsRoutine() { if timeoutTable[p] == MAX_TIMEOUT { delete(routingTable, p) delete(timeoutTable, p) + // TODO: send triggered update } wg.Done() @@ -669,8 +699,9 @@ func startRipRoutines() { continue } // send a request - message := NewRIPMessage(1, nil) - err := SendRIPMessage(*iface, neighbor, message) + message := makeRipMessage(1, nil) + addr := iface.IpPrefix.Addr() + err := SendIP(&addr, neighbor, RIP_PROTOCOL, message, neighbor.VipAddr.String(), nil) if err != nil { return } @@ -702,35 +733,43 @@ func RegisterProtocolHandler(protocolNum int) bool { } func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error { - command := message[0] + // parse the RIP message + SIZE_OF_RIP_HEADER := 2 * 2 + command := int(binary.BigEndian.Uint16(message[0:2])) switch command { case 1: // request // SendUpdates() break case 2: - numEntries := message[1] + numEntries := int(binary.BigEndian.Uint16(message[2:4])) + fmt.Println("Received RIP response with", numEntries, "entries") // parse the entries entries := make([]RIPEntry, 0, numEntries) - for i := 0; i < int(numEntries); i++ { - offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY + for i := 0; i < numEntries; i++ { + offset := SIZE_OF_RIP_HEADER + i*SIZE_OF_RIP_ENTRY // each field is 4 bytes - address := binary.BigEndian.Uint32(message[offset : offset+4]) - mask := binary.BigEndian.Uint32(message[offset+4 : offset+8]) - cost := binary.BigEndian.Uint32(message[offset+8 : offset+12]) - + cost := binary.BigEndian.Uint32(message[offset : offset+4]) + address, _ := netip.AddrFromSlice(message[offset+4 : offset+8]) + mask, _ := netip.AddrFromSlice(message[offset+8 : offset+12]) + // TODO: fix the mask with the correct calculation + if mask != netip.MustParseAddr("255.255.255.0") { + fmt.Println("mask error") + } // add to entries - entries = append(entries, RIPEntry{address: address, mask: mask, cost: cost}) + prefix := netip.PrefixFrom(address, 24) + entries = append(entries, RIPEntry{prefix, cost}) + + fmt.Println("Received RIP update: ", prefix.String(), cost) } // add to routing table for _, entry := range entries { - address := fmt.Sprintf("%d.%d.%d.%d", byte(entry.address>>24), byte(entry.address>>16), byte(entry.address>>8), byte(entry.address)) // fmt.Printf("Received RIP update: %s\t%d\t%d\n", address, entry.mask, entry.cost) - if address == "0.0.0.0" { // TODO: investigate this + if entry.prefix.Addr() == netip.MustParseAddr("0.0.0.0") { // TODO: investigate this continue } @@ -738,7 +777,7 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I // potentially, may have to apply mask first // fmt.Println(address) - prefix := netip.PrefixFrom(netip.MustParseAddr(address), int(entry.mask)) + prefix := entry.prefix // fmt.Println(prefix.String()) // check if the entry is already in the routing table and update if need be @@ -802,77 +841,77 @@ func LongestPrefix(src netip.Addr) (Hop, error) { return Hop{}, errors.Errorf("No route to ip %s on table.", src) } -func NewRIPMessage(command uint8, entries []RIPEntry) *RIPMessage { - return &RIPMessage{ - command: command, - numEntries: uint8(len(entries)), - entries: entries, - } -} - -func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error { - hdr := ipv4header.IPv4Header{ - Version: 4, - Len: 20, // Header length is always 20 when no IP options - TOS: 0, - TotalLen: ipv4header.HeaderLen + 4 + 1 + 1 + len(message.entries)*12, - ID: 0, - Flags: 0, - FragOff: 0, - TTL: 32, - Protocol: 12, - Checksum: 0, // Should be 0 until checksum is computed - Src: src.IpPrefix.Addr(), - Dst: netip.MustParseAddr(dest.VipAddr.String()), - Options: []byte{}, - } - - headerBytes, err := hdr.Marshal() - if err != nil { - return err - } - - hdr.Checksum = int(ComputeChecksum(headerBytes)) - - headerBytes, err = hdr.Marshal() - if err != nil { - log.Fatalln("Error marshalling header: ", err) - } - - bytesToSend := make([]byte, 0, len(headerBytes)+4+1+1+len(message.entries)*12) - bytesToSend = append(bytesToSend, headerBytes...) - - // make the RIP message - buf := make([]byte, SIZE_OF_RIP_MESSAGE+len(message.entries)*SIZE_OF_RIP_ENTRY) - buf[0] = message.command - buf[1] = message.numEntries - - for i, entry := range message.entries { - offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY - // each field is 4 bytes - binary.BigEndian.PutUint32(buf[offset:offset+4], entry.address) - binary.BigEndian.PutUint32(buf[offset+4:offset+8], entry.mask) - binary.BigEndian.PutUint32(buf[offset+8:offset+12], entry.cost) - } - - bytesToSend = append(bytesToSend, buf...) - - // send RIP message - sendAddr, err := net.ResolveUDPAddr("udp4", dest.UdpAddr.String()) - // tmpConn, err := net.DialUDP("udp4", nil, sendAddr) - if err != nil { - return errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String()) - } - - iface, err := GetInterfaceByName(dest.Name) - //_, err = tmpConn.Write(bytesToSend) - _, err = iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr) - if err != nil { - return err - } - - return nil -} +// +//func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error { +// hdr := ipv4header.IPv4Header{ +// Version: 4, +// Len: 20, // Header length is always 20 when no IP options +// TOS: 0, +// TotalLen: ipv4header.HeaderLen + 4 + len(message.entries)*SIZE_OF_RIP_ENTRY, +// ID: 0, +// Flags: 0, +// FragOff: 0, +// TTL: 32, +// Protocol: RIP_PROTOCOL, +// Checksum: 0, // Should be 0 until checksum is computed +// Src: src.IpPrefix.Addr(), +// Dst: netip.MustParseAddr(dest.VipAddr.String()), +// Options: []byte{}, +// } +// +// headerBytes, err := hdr.Marshal() +// if err != nil { +// return err +// } +// +// hdr.Checksum = int(ComputeChecksum(headerBytes)) +// +// headerBytes, err = hdr.Marshal() +// if err != nil { +// log.Fatalln("Error marshalling header: ", err) +// } +// +// bytesToSend := make([]byte, 0) +// bytesToSend = append(bytesToSend, headerBytes...) +// +// // make the RIP message +// //buf := make([]byte, SIZE_OF_RIP_MESSAGE+len(message.entries)*SIZE_OF_RIP_ENTRY) +// //buf[0] = message.command +// //buf[1] = message.numEntries +// +// buf := make([]byte, 4) +// binary.BigEndian.PutUint16(buf[0:2], message.command) +// binary.BigEndian.PutUint16(buf[2:], message.numEntries) +// +// bytesToSend = append(bytesToSend, buf...) +// +// for _, entry := range message.entries { +// // offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY +// // each field is 4 bytes +// buf := make([]byte, SIZE_OF_RIP_ENTRY) +// binary.BigEndian.PutUint32(buf, entry.address) // 0-3 = 4 bytes +// binary.BigEndian.PutUint32(buf[3:8], entry.mask) // 4-7 = 4 bytes +// binary.BigEndian.PutUint32(buf[8:], entry.cost) // 8-11 = 4 bytes +// +// bytesToSend = append(bytesToSend, buf...) +// } +// +// // send RIP message +// sendAddr, err := net.ResolveUDPAddr("udp4", dest.UdpAddr.String()) +// // tmpConn, err := net.DialUDP("udp4", nil, sendAddr) +// if err != nil { +// return errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String()) +// } +// +// iface, err := GetInterfaceByName(dest.Name) +// //_, err = tmpConn.Write(bytesToSend) +// _, err = iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr) +// if err != nil { +// return err +// } +// +// return nil +//} //func RequestRip() { // // create RIP message @@ -896,96 +935,96 @@ func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error { // } // } //} +// +//func BroadcastPeriodicUpdates() { +// // for each periodic update, we want to send our nodes in the table +// entries := make([]RIPEntry, len(routingTable)) +// for prefix, hop := range routingTable { +// entries = append(entries, +// RIPEntry{ +// address: ConvertIPToUint32(prefix.Addr().String()), +// mask: uint32(prefix.Bits()), +// cost: hop.Cost, +// }) +// } +// message := NewRIPMessage(2, entries) +// +// // send to each neighbor +// for _, iface := range myInterfaces { +// for _, n := range myNeighbors[iface.Name] { +// err := SendRIPMessage(*iface, n, message) +// if err != nil { +// fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String()) +// continue +// } +// } +// } +// +//} -func BroadcastPeriodicUpdates() { - // for each periodic update, we want to send our nodes in the table - entries := make([]RIPEntry, len(routingTable)) - for prefix, hop := range routingTable { - entries = append(entries, - RIPEntry{ - address: ConvertIPToUint32(prefix.Addr().String()), - mask: uint32(prefix.Bits()), - cost: hop.Cost, - }) - } - message := NewRIPMessage(2, entries) - - // send to each neighbor - for _, iface := range myInterfaces { - for _, n := range myNeighbors[iface.Name] { - err := SendRIPMessage(*iface, n, message) - if err != nil { - fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String()) - continue - } - } - } - -} - -// THIS MIGHT BE WRONG... -func SendUpdates() { - entries := make([]RIPEntry, len(routingTable)) - // create RIP entries from its interfaces to one another - for _, iface := range myInterfaces { - for _, iface2 := range myInterfaces { - if iface.Name == iface2.Name { - continue - } - // TODO @ MICHAEL: fix this - // hardcoded way to get cost to 0, fix if you want a better way - entry := &RIPEntry{ - address: ConvertIPToUint32(iface2.IpPrefix.Addr().String()), - cost: 17, - mask: ConvertIPToUint32(iface.IpPrefix.Addr().String()), - } - entries = append(entries, *entry) - - entry = &RIPEntry{ - address: ConvertIPToUint32(iface.IpPrefix.Addr().String()), - cost: 17, - mask: ConvertIPToUint32(iface2.IpPrefix.Addr().String()), - } - entries = append(entries, *entry) - } - } - - // create RIP entries from its neighbors - for _, neighbors := range myNeighbors { - for _, neighbor := range neighbors { - ipUint32 := ConvertIPToUint32(neighbor.VipAddr.String()) - var neighborUint32 uint32 - for _, interfaces := range myInterfaces { - if ifaceContainsIP(*interfaces, neighbor.VipAddr) { - neighborUint32 = ConvertIPToUint32(interfaces.IpPrefix.Addr().String()) - break - } - } - - // create RIP entry - entry := &RIPEntry{ - address: ipUint32, - cost: LOCAL_COST, - mask: neighborUint32, - } - - // add to entries and create RIP message - entries = append(entries, *entry) - message := NewRIPMessage(2, entries) - - // send RIP message - for _, Interfaces := range myInterfaces { - if Interfaces.Name == neighbor.Name { - err := SendRIPMessage(myVIP, neighbor, message) - if err != nil { - continue - } - } - } - - } - } -} +//// THIS MIGHT BE WRONG... +//func SendUpdates() { +// entries := make([]RIPEntry, len(routingTable)) +// // create RIP entries from its interfaces to one another +// for _, iface := range myInterfaces { +// for _, iface2 := range myInterfaces { +// if iface.Name == iface2.Name { +// continue +// } +// // TODO @ MICHAEL: fix this +// // hardcoded way to get cost to 0, fix if you want a better way +// entry := &RIPEntry{ +// address: ConvertIPToUint32(iface2.IpPrefix.Addr().String()), +// cost: 17, +// mask: ConvertIPToUint32(iface.IpPrefix.Addr().String()), +// } +// entries = append(entries, *entry) +// +// entry = &RIPEntry{ +// address: ConvertIPToUint32(iface.IpPrefix.Addr().String()), +// cost: 17, +// mask: ConvertIPToUint32(iface2.IpPrefix.Addr().String()), +// } +// entries = append(entries, *entry) +// } +// } +// +// // create RIP entries from its neighbors +// for _, neighbors := range myNeighbors { +// for _, neighbor := range neighbors { +// ipUint32 := ConvertIPToUint32(neighbor.VipAddr.String()) +// var neighborUint32 uint32 +// for _, interfaces := range myInterfaces { +// if ifaceContainsIP(*interfaces, neighbor.VipAddr) { +// neighborUint32 = ConvertIPToUint32(interfaces.IpPrefix.Addr().String()) +// break +// } +// } +// +// // create RIP entry +// entry := &RIPEntry{ +// address: ipUint32, +// cost: LOCAL_COST, +// mask: neighborUint32, +// } +// +// // add to entries and create RIP message +// entries = append(entries, *entry) +// message := NewRIPMessage(2, entries) +// +// // send RIP message +// for _, Interfaces := range myInterfaces { +// if Interfaces.Name == neighbor.Name { +// err := SendRIPMessage(myVIP, neighbor, message) +// if err != nil { +// continue +// } +// } +// } +// +// } +// } +//} func ifaceContainsIP(iface Interface, ip netip.Addr) bool { // check if the ip is in the interface's prefix Binary files differBinary files differ |