diff --git a/main.go b/main.go index 55140ee..05b4006 100644 --- a/main.go +++ b/main.go @@ -25,42 +25,25 @@ func main() { defer conn.Close() buff := make([]byte, 1024) - /* - bytes, err := rip.Request(conn) + log.Println("waiting") + for { + n, UDPAddr, err := conn.ReadFromUDP(buff) if err != nil { log.Fatalln(err) } + _ = UDPAddr - fmt.Println(bytes) + if err := rip.MParse(&buff, n); err != nil { + log.Fatalln(err) + } - - RipAddr := net.UDPAddr{ - Port: 520, - IP: net.ParseIP("224.0.0.9"), + /* Just testing the parsing output */ + for i := 0; i < 24; i++ { + if rip.RIP[i].Metric == 0 { + break } - bw, err := conn.WriteToUDP(bytes, &RipAddr) - if err != nil { - log.Fatalln(err) - } - - log.Printf("wrote %d bytes\n", bw) - - */ - log.Println("waiting") - n, UDPAddr, err := conn.ReadFromUDP(buff) - if err != nil { - log.Fatalln(err) - } - _ = UDPAddr - if n == 0 { - log.Fatalln("empty") - } - - if err := rip.Parse(&buff); err != nil { - log.Fatalln(err) - } - for i := 0; i < 24; i++ { - ipa := net.IPv4(byte(rip.RIP[i].Addr), byte(rip.RIP[i].Addr>>8), byte(rip.RIP[i].Addr>>16), byte(rip.RIP[i].Addr>>24)) - fmt.Printf("Command %d\n%s\t%d\n", rip.Command, ipa.String(), rip.RIP[i].Metric) + fmt.Printf("%d\t%s\t%s\t%s\t%d\n", rip.RIP[i].AFI, rip.RIP[i].Addr.String(), rip.RIP[i].Subnet.String(), rip.RIP[i].Nexthop.String(), rip.RIP[i].Metric) + } + fmt.Println("") } } diff --git a/ripv2/constants.go b/ripv2/constants.go deleted file mode 100644 index 0dcd568..0000000 --- a/ripv2/constants.go +++ /dev/null @@ -1,7 +0,0 @@ -package ripv2 - -const ( - ZERO = iota - REQUEST - RESPONSE -) diff --git a/ripv2/ripv2.go b/ripv2/ripv2.go index 4abd30c..e4b2977 100644 --- a/ripv2/ripv2.go +++ b/ripv2/ripv2.go @@ -3,29 +3,57 @@ package ripv2 import ( "bytes" "encoding/binary" + "errors" "fmt" "net" ) -type Message struct { - Command uint8 - Version uint8 - Zero uint16 - RIP [25]RIP -} - -type RIP struct { - AFI uint16 - Zero uint16 - Addr uint32 - Packing uint64 - Metric uint32 -} - func New() Message { return Message{} } +func (m *Message) MParse(b *[]byte, n int) error { + if n == 0 { + return errors.New("can't parse empty data") + } + + if (n-4)/20 > 25 { + return errors.New("rip table exceeds limit") + } + + data := (*b) + m.Command = Command(data[0]) + m.Version = Version(data[1]) + + if m.Version > RIPv2 { + return errors.New("unknown version") + } + + var indexA, indexB = 4, 25 + ripentry := data[indexA:indexB] + switch m.Command { + case REQUEST: + return nil + case RESPONSE: + for i := 0; i < (n-4)/20; i++ { + m.RIP[i].AFI = binary.BigEndian.Uint16(ripentry[0:2]) + m.RIP[i].RouteTag = binary.BigEndian.Uint16(ripentry[2:4]) + m.RIP[i].Addr = net.IPv4(ripentry[4], ripentry[5], ripentry[6], ripentry[7]) + m.RIP[i].Subnet = net.IPv4Mask(ripentry[8], ripentry[9], ripentry[10], ripentry[11]) + m.RIP[i].Nexthop = net.IPv4(ripentry[12], ripentry[13], ripentry[14], ripentry[15]) + m.RIP[i].Metric = binary.BigEndian.Uint32(ripentry[16:20]) + indexA += 20 + indexB += 20 + ripentry = data[indexA:indexB] + } + default: + return errors.New("unknown command type") + } + + return nil +} + +/* Basic parsing */ func (m *Message) Parse(b *[]byte) error { if len(*b) == 0 { return fmt.Errorf("can't parse empty data") @@ -33,7 +61,7 @@ func (m *Message) Parse(b *[]byte) error { bytes := bytes.NewBuffer(*b) - if err := binary.Read(bytes, binary.LittleEndian, m); err != nil { + if err := binary.Read(bytes, binary.BigEndian, m); err != nil { return err } diff --git a/ripv2/types.go b/ripv2/types.go new file mode 100644 index 0000000..fbed13d --- /dev/null +++ b/ripv2/types.go @@ -0,0 +1,33 @@ +package ripv2 + +import "net" + +type Command uint8 +type Version uint8 + +const ( + ZERO Command = iota + REQUEST + RESPONSE +) + +const ( + RIPv1 Version = iota + 1 + RIPv2 +) + +type Message struct { + Command Command + Version Version + Zero uint16 + RIP [25]RIP +} + +type RIP struct { + AFI uint16 + RouteTag uint16 + Addr net.IP + Subnet net.IPMask + Nexthop net.IP + Metric uint32 +}