diff options
Diffstat (limited to 'pkg/protocol.go')
-rw-r--r-- | pkg/protocol.go | 226 |
1 files changed, 171 insertions, 55 deletions
diff --git a/pkg/protocol.go b/pkg/protocol.go index 10cf058..9358099 100644 --- a/pkg/protocol.go +++ b/pkg/protocol.go @@ -7,7 +7,10 @@ import ( "os" "bufio" "time" - "github.com/brown-cs1680-f23/iptcp-jailpt2/pkg/lnxconfig" + "github.com/pkg/errors" + ipv4header "github.com/brown-csci1680/iptcp-headers" + "github.com/google/netstack/tcpip/header" + "github.com/brown-csci1680/ipstack-utils" ) const ( @@ -21,8 +24,20 @@ type Interface struct { UDPAddr netip.AddrPort State uint8_t + neighbors map[netip.AddrPort]netip.AddrPort } +// type Host struct { +// Interface Interface +// Neighbors []Neighbor +// } + +// type Router struct { +// Interfaces []Interface +// Neighbors []Neighbor +// RIPNeighbors []Neighbor +// } + type Neighbor struct{ DestAddr netip.Addr @@ -62,7 +77,7 @@ func Initialize(config IpConfig) (error) { panic(err) } - // populate routing table + // populate routing table??? for _, iface := range lnxConfig.Interfaces { myInterfaces = append(myInterfaces, Interface{iface.Name, iface.AssignedIP, iface.AssignedPrefix, iface.UDPAddr, 0}) } @@ -77,63 +92,164 @@ func Initialize(config IpConfig) (error) { } } -func RecvIp(data []byte) (error) { - // deconstruct packet +func ListerToInterfaces() { + for _, iface := range myInterfaces { + go RecvIp(iface) + } +} + +func RecvIp(iface Interface) (error) { + for { + buffer := make([]byte, MAX_IP_PACKET_SIZE) + _, sourceAddr, err := iface.udp.ReadFrom(buffer) + if err != nil { + log.Panicln("Error reading from UDP socket ", err) + } + + hdr, err := ipv4header.ParseHeader(buffer) + + if err != nil { + fmt.Println("Error parsing header", err) + continue + } + + headerSize := hdr.Len + headerBytes := buffer[:headerSize] + + checksumFromHeader := uint16(hdr.Checksum) + computedChecksum := ValidateChecksum(headerBytes, checksumFromHeader) + + var checksumState string + if computedChecksum == checksumFromHeader { + checksumState = "OK" + } else { + checksumState = "FAIL" + continue + } + + // check ttl + ttl := data[8] + if ttl == 0 { + fmt.Println("TTL is 0") + continue + } + + + destAddr := netip.AddrFrom(data[16:20]) + protocolNum := data[9] + + if destAddr == iface.addr { + // send to handler + protocolHandlers[protocolNum](data) + // message := buffer[headerSize:] + + // fmt.Printf("Received IP packet from %s\nHeader: %v\nChecksum: %s\nMessage: %s\n", + // sourceAddr.String(), hdr, checksumState, string(message)) + } else { + // decrement ttl and update checksum + data[8] = ttl - 1 + data[10] = 0 + data[11] = 0 + newChecksum := int(ComputeChecksum(data[:headerSize])) + data[10] = newChecksum >> 8 + data[11] = newChecksum & 0xff + + // check neighbors + for _, neighbor := range iface.neighbors { + if neighbor == destAddr { + // send to neighbor + // SendIp(destAddr, protocolNum, data) + } + } + + // check forwarding table + + } + + } +} + +func ValidateChecksum(b []byte, fromHeader uint16) uint16 { + checksum := header.Checksum(b, fromHeader) + + return checksum +} - // check ip checksum - checksum := netip.Checksum(data) - if checksum != 0 { - return errors.Errorf("Checksum failed: %d", checksum) +func SendIp(dst netip.Addr, port uint16, protocolNum uint16, data []byte, iface Interface) (error) { + bindLocalAddr, err := net.ResolveUDPAddr("udp4", iface.UDPAddr.String()) + if err != nil { + log.Panicln("Error resolving address: ", err) } - // check ttl - ttl := data[8] - if ttl == 0 { - return errors.Errorf("TTL is 0") + addrString := fmt.Sprintf("%s:%s", dst, port) + remoteAddr, err := net.ResolveUDPAddr("udp4", addrString) + if err != nil { + log.Panicln("Error resolving address: ", err) } - destAddr := netip.AddrFrom(data[16:20]) - protocolNum := data[9] + fmt.Printf("Sending to %s:%d\n", + remoteAddr.IP.String(), remoteAddr.Port) - // decrement ttl and update checksum - data[8] = ttl - 1 - data[10] = 0 - data[11] = 0 - newChecksum := netip.Checksum(data) - data[10] = newChecksum >> 8 - data[11] = newChecksum & 0xff + // Bind on the local UDP port: this sets the source port + // and creates a conn + conn, err := net.ListenUDP("udp4", bindLocalAddr) + if err != nil { + log.Panicln("Dial: ", err) + } - SendIp(destAddr, protocolNum, data) -} + // Start filling in the header + message := data[20:] + hdr := ipv4header.IPv4Header{ + Version: data[0] >> 4, + Len: 20, // Header length is always 20 when no IP options + TOS: data[1], + TotalLen: ipv4header.HeaderLen + len(message), + ID: data[4], + Flags: data[6] >> 5, + FragOff: data[6] & 0x1f, + TTL: data[8], + Protocol: data[9], + Checksum: 0, // Should be 0 until checksum is computed + Src: netip.MustParseAddr(iface.addr.String()), + Dst: netip.MustParseAddr(dst.String()), + Options: []byte{}, + } -func SendIp(dst netip.Addr, protocolNum uint16, data []byte) (error) { - // check if dst is local - islocal := false - for _, iface := range myNeighbors { - if iface.addr == dst { - islocal = true - break - } + // Assemble the header into a byte array + headerBytes, err := hdr.Marshal() + if err != nil { + log.Fatalln("Error marshalling header: ", err) } - if islocal { - // send to local handler - protocolHandlers[protocolNum](data) - } else { - // send to forwarding table - // lookup forwarding table - // toHop, err := lookupForwardingTable(dst) - // if err != nil { - // routeRip() - // } + // Compute the checksum (see below) + // Cast back to an int, which is what the Header structure expects + hdr.Checksum = int(ComputeChecksum(headerBytes)) - // // send to toHop interface - // for _, iface := range myInterfaces { - // if iface.addr == toHop { - // iface.udp.Write(data) - // break - // } - // } + headerBytes, err = hdr.Marshal() + if err != nil { + log.Fatalln("Error marshalling header: ", err) + } + + bytesToSend := make([]byte, 0, len(headerBytes)+len(message)) + bytesToSend = append(bytesToSend, headerBytes...) + bytesToSend = append(bytesToSend, []byte(message)...) + + // Send the message to the "link-layer" addr:port on UDP + bytesWritten, err := conn.WriteToUDP(bytesToSend, remoteAddr) + if err != nil { + log.Panicln("Error writing to socket: ", err) + } + fmt.Printf("Sent %d bytes\n", bytesWritten) +} + +func ComputeChecksum(b []byte) uint16 { + checksum := header.Checksum(b, 0) + checksumInv := checksum ^ 0xffff + + return checksumInv +} + +func ForwardIP(data []byte) (error) { } type HandlerFunc = func help(*Packet, []interface{}) (error) { @@ -158,13 +274,13 @@ func RemoveRecvHandler(protocolNum uint8) (error) { return nil } -func routeRip(data []byte) (error) { - // deconstruct packet - newRIPMessage := RIPMessage{} - newRIPMessage.command = data[0] - newRIPMessage.numEntries = data[1] - newRIPMessage.entries = make([]RIPEntry, newRIPMessage.numEntries) -} +// func routeRip(data []byte) (error) { +// // deconstruct packet +// newRIPMessage := RIPMessage{} +// newRIPMessage.command = data[0] +// newRIPMessage.numEntries = data[1] +// newRIPMessage.entries = make([]RIPEntry, newRIPMessage.numEntries) +// } func PrintNeighbors() { for _, iface := range myNeighbors { |