diff options
Diffstat (limited to 'pkg/protocol.go')
-rw-r--r-- | pkg/protocol.go | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/pkg/protocol.go b/pkg/protocol.go new file mode 100644 index 0000000..10cf058 --- /dev/null +++ b/pkg/protocol.go @@ -0,0 +1,183 @@ +package protocol + +import ( + "net" + "net/netip" + "fmt" + "os" + "bufio" + "time" + "github.com/brown-cs1680-f23/iptcp-jailpt2/pkg/lnxconfig" +) + +const ( + MAX_IP_PACKET_SIZE = 1400 +) + +type Interface struct { + Name string + AssignedIP netip.Addr + AssignedPrefix netip.Prefix + + UDPAddr netip.AddrPort + State uint8_t +} + + +type Neighbor struct{ + DestAddr netip.Addr + UDPAddr netip.AddrPort + + InterfaceName string +} + +type RIPMessage struct { + command uint8_t; + numEntries uint8_t; + entries []RIPEntry; +} + +type RIPEntry struct { + addr netip.Addr; + cost uint16_t; + mask netip.Prefix; +} + +myInterfaces := make([]Interface); +myNeighbors := make(map[string]Neighbor) +myRIPNeighbors := make(map[string]Neighbor) +protocolHandlers := make(map[uint16]HandlerFunc) +// routingTable := make(map[Address]Routing) + +func Initialize(config IpConfig) (error) { + if len(os.Args) != 2 { + fmt.Printf("Usage: %s <configFile>\n", os.Args[0]) + os.Exit(1) + } + fileName := os.Args[1] + + // Parse the file + lnxConfig, err := lnxconfig.ParseConfig(fileName) + if err != nil { + panic(err) + } + + // populate routing table + for _, iface := range lnxConfig.Interfaces { + myInterfaces = append(myInterfaces, Interface{iface.Name, iface.AssignedIP, iface.AssignedPrefix, iface.UDPAddr, 0}) + } + + for _, neighbor := range lnxConfig.Neighbors { + myNeighbors[neighbor.DestAddr.String()] = Neighbor{neighbor.DestAddr, neighbor.UDPAddr, neighbor.InterfaceName} + } + + // add RIP neighbors + for _, neighbor := range lnxConfig.RipNeighbors { + myRIPNeighbors[neighbor.DestAddr.String()] = Neighbor{neighbor.DestAddr, neighbor.UDPAddr, neighbor.InterfaceName} + } +} + +func RecvIp(data []byte) (error) { + // deconstruct packet + + // check ip checksum + checksum := netip.Checksum(data) + if checksum != 0 { + return errors.Errorf("Checksum failed: %d", checksum) + } + + // check ttl + ttl := data[8] + if ttl == 0 { + return errors.Errorf("TTL is 0") + } + + destAddr := netip.AddrFrom(data[16:20]) + protocolNum := data[9] + + // 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 + + SendIp(destAddr, protocolNum, data) +} + +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 + } + } + + 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() + // } + + // // send to toHop interface + // for _, iface := range myInterfaces { + // if iface.addr == toHop { + // iface.udp.Write(data) + // break + // } + // } +} + +type HandlerFunc = func help(*Packet, []interface{}) (error) { + + // do smth with packet +} + +func AddRecvHandler(protocolNum uint8, callbackFunc HandlerFunc) (error) { + if protocolHandlers[protocolNum] != nil { + fmt.Printf("Warning: Handler for protocol %d already exists", protocolNum) + } + protocolHandlers[protocolNum] = callbackFunc + return nil +} + +func RemoveRecvHandler(protocolNum uint8) (error) { + // consider error + if protocolHandlers[protocolNum] == nil { + return errors.Errorf("No handler for protocol %d", protocolNum) + } + delete(protocolHandlers, protocolNum) + 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 PrintNeighbors() { + for _, iface := range myNeighbors { + fmt.Printf("%s\n", iface.addr.String()) + } +} + +func PrintInterfaces() { + for _, iface := range myInterfaces { + fmt.Printf("%s\n", iface.addr.String()) + } +} +func GetNeighbors() ([]netip.Addr) { + return myNeighbors +} + |