87 lines
1.9 KiB
Go
87 lines
1.9 KiB
Go
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
|
|
}
|