aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2023-10-23 03:08:27 -0400
committersotech117 <michael_foiani@brown.edu>2023-10-23 03:08:27 -0400
commit7ec4f310ec01100f648a42dd52cb0ac635ac0b10 (patch)
treeee73018b8018b68201456a4d953f13463fdf0f4d
parent8f5877a04b3c82f5c298b87f6a0f6356d2acffcd (diff)
fix wireshark rip packets being malformed
-rw-r--r--pkg/ipstack/ipstack.go415
-rwxr-xr-xvhostbin3105111 -> 3104785 bytes
-rwxr-xr-xvrouterbin3105159 -> 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
diff --git a/vhost b/vhost
index 1c1151c..633b625 100755
--- a/vhost
+++ b/vhost
Binary files differ
diff --git a/vrouter b/vrouter
index 7f788d0..bb36ec9 100755
--- a/vrouter
+++ b/vrouter
Binary files differ