mirror of
https://github.com/lucheng0127/virtuallan.git
synced 2025-09-27 04:55:51 +08:00
87 lines
2.0 KiB
Go
87 lines
2.0 KiB
Go
package packet
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/lucheng0127/virtuallan/pkg/utils"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
MULTICAST_ADDR = "224.0.0.1"
|
|
MULTICAST_PORT = 9999
|
|
MAX_DATA_SIZE = 8192
|
|
|
|
ROUTES_PREFIX = uint16(0x2b00 | 0x01)
|
|
)
|
|
|
|
func MulticastStream(data []byte) error {
|
|
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", MULTICAST_ADDR, MULTICAST_PORT))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
conn, err := net.DialUDP("udp", nil, udpAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := conn.Write(data); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func MonitorRouteMulticast(iface *net.Interface, tapIP string) error {
|
|
// Monitor route multicast will run as a goruntine in client so log error but don't exit
|
|
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", MULTICAST_ADDR, MULTICAST_PORT))
|
|
if err != nil {
|
|
return fmt.Errorf("parse multicast addr %s", err.Error())
|
|
}
|
|
|
|
// Listen multicast on tap interface
|
|
ln, err := net.ListenMulticastUDP("udp", iface, udpAddr)
|
|
if err != nil {
|
|
return fmt.Errorf("listen multicast address %s", err.Error())
|
|
}
|
|
|
|
// Read data from udp
|
|
for {
|
|
buf := make([]byte, MAX_DATA_SIZE)
|
|
|
|
n, srcAddr, err := ln.ReadFromUDP(buf)
|
|
if err != nil {
|
|
log.Errorf("read from multicast %s", err.Error())
|
|
continue
|
|
}
|
|
|
|
log.Debugf("read multicast from %s", srcAddr.String())
|
|
// XXX: Check source addr same cidr with enpoint ip maybe
|
|
|
|
// Strip route prefix
|
|
if n < 2 {
|
|
// Not validate stream
|
|
continue
|
|
}
|
|
|
|
streamPrefix := binary.BigEndian.Uint16(buf[:2])
|
|
if streamPrefix != ROUTES_PREFIX {
|
|
// Not route stream
|
|
continue
|
|
}
|
|
|
|
// Parse route stream
|
|
routes := utils.ParseRoutesStream(buf[2:])
|
|
log.Debugf("receive route multicast:\n%+v", routes)
|
|
|
|
// TODO: Implement in windows
|
|
// Sync routes, use flag replace, for unknow ip need delete
|
|
if err := utils.SyncRoutesForIface(iface.Name, tapIP, routes); err != nil {
|
|
return fmt.Errorf("sync route for %s %s", iface.Name, err.Error())
|
|
}
|
|
}
|
|
}
|