crip/ripv2/ripv2.go

87 lines
1.9 KiB
Go
Raw Normal View History

2024-04-09 22:20:07 +01:00
package ripv2
import (
"bytes"
"encoding/binary"
2024-04-10 13:59:01 +01:00
"errors"
2024-04-09 22:20:07 +01:00
"fmt"
"net"
)
2024-04-10 13:59:01 +01:00
func New() Message {
return Message{}
2024-04-09 22:20:07 +01:00
}
2024-04-10 13:59:01 +01:00
func (m *Message) MParse(b *[]byte, n int) error {
if n == 0 {
return errors.New("can't parse empty data")
}
2024-04-09 22:20:07 +01:00
2024-04-10 13:59:01 +01:00
if (n-4)/20 > 25 {
return errors.New("rip table exceeds limit")
}
2024-04-10 16:33:33 +01:00
m.Command = Command((*b)[0])
m.Version = Version((*b)[1])
2024-04-10 13:59:01 +01:00
if m.Version > RIPv2 {
return errors.New("unknown version")
}
var indexA, indexB = 4, 25
2024-04-10 16:33:33 +01:00
ripentry := (*b)[indexA:indexB]
2024-04-10 13:59:01 +01:00
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])
2024-04-10 16:33:33 +01:00
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])
2024-04-10 13:59:01 +01:00
m.RIP[i].Metric = binary.BigEndian.Uint32(ripentry[16:20])
indexA += 20
indexB += 20
2024-04-10 16:33:33 +01:00
ripentry = (*b)[indexA:indexB]
2024-04-10 13:59:01 +01:00
}
default:
return errors.New("unknown command type")
}
return nil
2024-04-09 22:20:07 +01:00
}
2024-04-10 13:59:01 +01:00
/* Basic parsing */
2024-04-09 22:20:07 +01:00
func (m *Message) Parse(b *[]byte) error {
if len(*b) == 0 {
return fmt.Errorf("can't parse empty data")
}
bytes := bytes.NewBuffer(*b)
2024-04-10 13:59:01 +01:00
if err := binary.Read(bytes, binary.BigEndian, m); err != nil {
2024-04-09 22:20:07 +01:00
return err
}
2024-04-10 09:50:56 +01:00
if m.Version != 2 {
return fmt.Errorf("version: %d", m.Version)
}
2024-04-09 22:20:07 +01:00
return nil
}
func (m *Message) Request(conn *net.UDPConn) ([]byte, error) {
2024-04-09 23:33:11 +01:00
var buffer = make([]byte, 24)
2024-04-09 22:20:07 +01:00
m.Command = REQUEST
m.Version = 2
2024-04-10 09:50:56 +01:00
m.RIP[0].Metric = 16
2024-04-09 22:20:07 +01:00
buff := bytes.NewBuffer(buffer)
buff.Reset()
2024-04-09 23:33:11 +01:00
if err := binary.Write(buff, binary.BigEndian, m); err != nil {
2024-04-09 22:20:07 +01:00
return []byte{}, err
}
return buffer, nil
}