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 \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 }