crip/ripv2/ripv2.go

121 lines
2.4 KiB
Go
Raw Normal View History

2024-04-09 22:20:07 +01:00
package ripv2
import (
"encoding/binary"
2024-04-10 13:59:01 +01:00
"errors"
2024-04-09 22:20:07 +01:00
"fmt"
2024-04-16 12:55:08 +01:00
"log"
2024-04-09 22:20:07 +01:00
"net"
2024-04-16 12:55:08 +01:00
"os"
"os/signal"
"syscall"
"github.com/crip/config"
2024-04-09 22:20:07 +01:00
)
2024-04-10 13:59:01 +01:00
func New() Message {
return Message{
RIP: make([]RIP, 25),
}
2024-04-09 22:20:07 +01:00
}
/* Parse the raw data packet
* Store the serialised data in the Message slice
*/
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-25 14:19:28 +01:00
m.RIP[i].Addr = binary.BigEndian.Uint32(ripentry[4:8])
m.RIP[i].Subnet = binary.BigEndian.Uint32(ripentry[8:12])
2024-04-25 14:39:46 +01:00
m.RIP[i].NextHop = binary.BigEndian.Uint32(ripentry[12:16])
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
}
/* Listen for network packets */
2024-04-25 14:39:46 +01:00
func (m *Message) Run(c *config.Config, callback func(*Routes)) error {
2024-04-16 12:55:08 +01:00
iface := net.Interface{
Name: c.MulticastInterface,
Flags: net.FlagMulticast,
}
addr := net.UDPAddr{
2024-04-16 13:12:48 +01:00
IP: net.ParseIP(c.IP),
2024-04-16 12:55:08 +01:00
Port: c.Port,
2024-04-09 22:20:07 +01:00
}
2024-04-16 12:55:08 +01:00
conn, err := net.ListenMulticastUDP("udp4", &iface, &addr)
if err != nil {
2024-04-25 14:39:46 +01:00
return err
2024-04-16 12:55:08 +01:00
}
2024-04-25 14:39:46 +01:00
defer func() {
if err := conn.Close(); err != nil {
log.Println(err)
}
}()
2024-04-09 22:20:07 +01:00
2024-04-16 12:55:08 +01:00
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
2024-04-09 22:20:07 +01:00
2024-04-16 12:55:08 +01:00
buffer := make([]byte, 484)
routes := Init()
2024-04-09 22:20:07 +01:00
2024-04-16 12:55:08 +01:00
for {
go func() {
2024-04-25 14:39:46 +01:00
log.Println("Running")
<-sigs
log.Println("exit")
2024-04-16 12:55:08 +01:00
os.Exit(0)
}()
2024-04-10 09:50:56 +01:00
2024-04-16 12:55:08 +01:00
n, UDPAddr, err := conn.ReadFromUDP(buffer)
if err != nil {
2024-04-25 14:39:46 +01:00
if err = conn.Close(); err != nil {
log.Println(err)
}
2024-04-16 12:55:08 +01:00
log.Fatal("unable to read from socket")
}
2024-04-09 22:20:07 +01:00
2024-04-16 12:55:08 +01:00
if n < 24 {
log.Println("packet length")
}
2024-04-09 22:20:07 +01:00
2024-04-16 12:55:08 +01:00
if err := m.MParse(&buffer, n); err != nil {
log.Fatalln(err)
}
routes.ParseRoutes(*UDPAddr, &m.RIP)
for _, v := range routes.Routes {
2024-04-25 14:39:46 +01:00
fmt.Printf("Route:%s\tSubnet:%s\tNexthop:%s\tMetric:%d\tTime: %v\n", v.Addr.String(), v.Subnet.String(), v.NextHop.String(), v.Metric, v.TTL.Unix())
2024-04-16 12:55:08 +01:00
}
2024-04-25 14:39:46 +01:00
callback(routes)
2024-04-16 12:55:08 +01:00
}
2024-04-09 22:20:07 +01:00
}