package ripv2 import ( "bytes" "encoding/binary" "errors" "fmt" "net" ) 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") } m.Command = Command((*b)[0]) m.Version = Version((*b)[1]) if m.Version > RIPv2 { return errors.New("unknown version") } var indexA, indexB = 4, 25 ripentry := (*b)[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 = binary.BigEndian.Uint32(ripentry[4:8]) //net.IPv4(ripentry[4], ripentry[5], ripentry[6], ripentry[7]) m.RIP[i].Subnet = binary.BigEndian.Uint32(ripentry[8:12]) //net.IPv4Mask(ripentry[8], ripentry[9], ripentry[10], ripentry[11]) m.RIP[i].Nexthop = binary.BigEndian.Uint32(ripentry[12:16]) //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 = (*b)[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") } bytes := bytes.NewBuffer(*b) if err := binary.Read(bytes, binary.BigEndian, m); err != nil { return err } if m.Version != 2 { return fmt.Errorf("version: %d", m.Version) } return nil } func (m *Message) Request(conn *net.UDPConn) ([]byte, error) { var buffer = make([]byte, 24) m.Command = REQUEST m.Version = 2 m.RIP[0].Metric = 16 buff := bytes.NewBuffer(buffer) buff.Reset() if err := binary.Write(buff, binary.BigEndian, m); err != nil { return []byte{}, err } return buffer, nil }