Try this
This commit is contained in:
parent
1b33388e2a
commit
74936edbdd
1 changed files with 123 additions and 120 deletions
243
main.go
243
main.go
|
@ -127,15 +127,16 @@ func main() {
|
||||||
pcapHandle.Close()
|
pcapHandle.Close()
|
||||||
log.Fatalf("Couldn't set BPF filter on packet capture: %v", err)
|
log.Fatalf("Couldn't set BPF filter on packet capture: %v", err)
|
||||||
}
|
}
|
||||||
defer pcapHandle.Close()
|
// defer pcapHandle.Close()
|
||||||
|
|
||||||
// Wait until all peer handlers have finished before closing the port
|
// Wait until all peer handlers have finished before closing the port
|
||||||
var handlersWG sync.WaitGroup
|
var handlersWG sync.WaitGroup
|
||||||
defer func() {
|
defer handlersWG.Wait()
|
||||||
log.Print("Waiting for handlers to return...")
|
// defer func() {
|
||||||
handlersWG.Wait()
|
// // log.Print("Waiting for handlers to return...")
|
||||||
ln.Close()
|
// // handlersWG.Wait()
|
||||||
}()
|
// // ln.Close()
|
||||||
|
// }()
|
||||||
goPeerHandler := func(p *router.Peer) {
|
goPeerHandler := func(p *router.Peer) {
|
||||||
handlersWG.Add(1)
|
handlersWG.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -244,9 +245,9 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
rawPkt, _, err := pcapHandle.ReadPacketData()
|
rawPkt, _, err := pcapHandle.ReadPacketData()
|
||||||
if errors.Is(err, pcap.NextErrorTimeoutExpired) {
|
// if errors.Is(err, pcap.NextErrorTimeoutExpired) {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
if errors.Is(err, io.EOF) || errors.Is(err, pcap.NextErrorNoMorePackets) {
|
if errors.Is(err, io.EOF) || errors.Is(err, pcap.NextErrorNoMorePackets) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -357,132 +358,134 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// ----------------------------- AURP inbound -----------------------------
|
// ----------------------------- AURP inbound -----------------------------
|
||||||
for {
|
go func() {
|
||||||
if ctx.Err() != nil {
|
for {
|
||||||
return
|
if ctx.Err() != nil {
|
||||||
}
|
|
||||||
ln.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
|
||||||
pktbuf := make([]byte, 4096)
|
|
||||||
pktlen, raddr, readErr := ln.ReadFromUDP(pktbuf)
|
|
||||||
|
|
||||||
var operr *net.OpError
|
|
||||||
if errors.As(readErr, &operr) && operr.Timeout() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// log.Printf("AURP: Received packet of length %d from %v", pktlen, raddr)
|
|
||||||
|
|
||||||
dh, pkt, parseErr := aurp.ParsePacket(pktbuf[:pktlen])
|
|
||||||
if parseErr != nil {
|
|
||||||
log.Printf("AURP: Failed to parse packet: %v", parseErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if readErr != nil {
|
|
||||||
log.Printf("AURP: Failed to read packet: %v", readErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("AURP: Got %T from %v (%v)", pkt, raddr, dh.SourceDI)
|
|
||||||
|
|
||||||
// Existing peer?
|
|
||||||
ra := udpAddrFromNet(raddr)
|
|
||||||
pr := peers[ra]
|
|
||||||
if pr == nil {
|
|
||||||
// New peer!
|
|
||||||
pr = &router.Peer{
|
|
||||||
Config: cfg,
|
|
||||||
Transport: &aurp.Transport{
|
|
||||||
LocalDI: localDI,
|
|
||||||
RemoteDI: dh.SourceDI, // platinum rule
|
|
||||||
LocalConnID: nextConnID,
|
|
||||||
},
|
|
||||||
UDPConn: ln,
|
|
||||||
RemoteAddr: raddr,
|
|
||||||
RecieveCh: make(chan aurp.Packet, 1024),
|
|
||||||
RoutingTable: routes,
|
|
||||||
ZoneTable: zones,
|
|
||||||
Reconnect: false,
|
|
||||||
}
|
|
||||||
aurp.Inc(&nextConnID)
|
|
||||||
peers[ra] = pr
|
|
||||||
goPeerHandler(pr)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch dh.PacketType {
|
|
||||||
case aurp.PacketTypeRouting:
|
|
||||||
// It's AURP routing data.
|
|
||||||
// Pass the packet to the goroutine in charge of this peer.
|
|
||||||
select {
|
|
||||||
case pr.RecieveCh <- pkt:
|
|
||||||
// That's it for us.
|
|
||||||
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
continue
|
// ln.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||||
|
pktbuf := make([]byte, 4096)
|
||||||
|
pktlen, raddr, readErr := ln.ReadFromUDP(pktbuf)
|
||||||
|
|
||||||
case aurp.PacketTypeAppleTalk:
|
// var operr *net.OpError
|
||||||
apkt, ok := pkt.(*aurp.AppleTalkPacket)
|
// if errors.As(readErr, &operr) && operr.Timeout() {
|
||||||
if !ok {
|
// continue
|
||||||
log.Printf("AURP: Got %T but domain header packet type was %v ?", pkt, dh.PacketType)
|
// }
|
||||||
|
|
||||||
|
// log.Printf("AURP: Received packet of length %d from %v", pktlen, raddr)
|
||||||
|
|
||||||
|
dh, pkt, parseErr := aurp.ParsePacket(pktbuf[:pktlen])
|
||||||
|
if parseErr != nil {
|
||||||
|
log.Printf("AURP: Failed to parse packet: %v", parseErr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if readErr != nil {
|
||||||
// Route or otherwise handle the encapsulated AppleTalk traffic
|
log.Printf("AURP: Failed to read packet: %v", readErr)
|
||||||
ddpkt := new(ddp.ExtPacket)
|
return
|
||||||
if err := ddp.ExtUnmarshal(apkt.Data, ddpkt); err != nil {
|
|
||||||
log.Printf("AURP: Couldn't unmarshal encapsulated DDP packet: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Printf("DDP/AURP: Got %d.%d.%d -> %d.%d.%d proto %d data len %d",
|
|
||||||
ddpkt.SrcNet, ddpkt.SrcNode, ddpkt.SrcSocket,
|
|
||||||
ddpkt.DstNet, ddpkt.DstNode, ddpkt.DstSocket,
|
|
||||||
ddpkt.Proto, len(ddpkt.Data))
|
|
||||||
|
|
||||||
// "Route" the packet
|
|
||||||
// Since for now there's only one local network, the routing
|
|
||||||
// decision is pretty easy
|
|
||||||
// TODO: Fix this to support other AppleTalk routers
|
|
||||||
if ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd {
|
|
||||||
log.Print("DDP/AURP: dropping packet not addressed to our EtherTalk range")
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and adjust the Hop Count
|
log.Printf("AURP: Got %T from %v (%v)", pkt, raddr, dh.SourceDI)
|
||||||
// Note the ddp package doesn't make this simple
|
|
||||||
hopCount := (ddpkt.Size & 0x3C00) >> 10
|
|
||||||
if hopCount >= 15 {
|
|
||||||
log.Printf("DDP/AURP: hop count exceeded (%d >= 15)", hopCount)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hopCount++
|
|
||||||
ddpkt.Size &^= 0x3C00
|
|
||||||
ddpkt.Size |= hopCount << 10
|
|
||||||
|
|
||||||
// Is it addressed to me? Is it NBP?
|
// Existing peer?
|
||||||
if ddpkt.DstNode == 0 { // Node 0 = the router for the network
|
ra := udpAddrFromNet(raddr)
|
||||||
if ddpkt.DstSocket != 2 {
|
pr := peers[ra]
|
||||||
// Something else?? TODO
|
if pr == nil {
|
||||||
log.Printf("DDP/AURP: I don't have anything 'listening' on socket %d", ddpkt.DstSocket)
|
// New peer!
|
||||||
|
pr = &router.Peer{
|
||||||
|
Config: cfg,
|
||||||
|
Transport: &aurp.Transport{
|
||||||
|
LocalDI: localDI,
|
||||||
|
RemoteDI: dh.SourceDI, // platinum rule
|
||||||
|
LocalConnID: nextConnID,
|
||||||
|
},
|
||||||
|
UDPConn: ln,
|
||||||
|
RemoteAddr: raddr,
|
||||||
|
RecieveCh: make(chan aurp.Packet, 1024),
|
||||||
|
RoutingTable: routes,
|
||||||
|
ZoneTable: zones,
|
||||||
|
Reconnect: false,
|
||||||
|
}
|
||||||
|
aurp.Inc(&nextConnID)
|
||||||
|
peers[ra] = pr
|
||||||
|
goPeerHandler(pr)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch dh.PacketType {
|
||||||
|
case aurp.PacketTypeRouting:
|
||||||
|
// It's AURP routing data.
|
||||||
|
// Pass the packet to the goroutine in charge of this peer.
|
||||||
|
select {
|
||||||
|
case pr.RecieveCh <- pkt:
|
||||||
|
// That's it for us.
|
||||||
|
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
case aurp.PacketTypeAppleTalk:
|
||||||
|
apkt, ok := pkt.(*aurp.AppleTalkPacket)
|
||||||
|
if !ok {
|
||||||
|
log.Printf("AURP: Got %T but domain header packet type was %v ?", pkt, dh.PacketType)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// It's NBP
|
|
||||||
if err := rooter.HandleNBPInAURP(pr, ddpkt); err != nil {
|
// Route or otherwise handle the encapsulated AppleTalk traffic
|
||||||
log.Printf("NBP/DDP/AURP: %v", err)
|
ddpkt := new(ddp.ExtPacket)
|
||||||
|
if err := ddp.ExtUnmarshal(apkt.Data, ddpkt); err != nil {
|
||||||
|
log.Printf("AURP: Couldn't unmarshal encapsulated DDP packet: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("DDP/AURP: Got %d.%d.%d -> %d.%d.%d proto %d data len %d",
|
||||||
|
ddpkt.SrcNet, ddpkt.SrcNode, ddpkt.SrcSocket,
|
||||||
|
ddpkt.DstNet, ddpkt.DstNode, ddpkt.DstSocket,
|
||||||
|
ddpkt.Proto, len(ddpkt.Data))
|
||||||
|
|
||||||
|
// "Route" the packet
|
||||||
|
// Since for now there's only one local network, the routing
|
||||||
|
// decision is pretty easy
|
||||||
|
// TODO: Fix this to support other AppleTalk routers
|
||||||
|
if ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd {
|
||||||
|
log.Print("DDP/AURP: dropping packet not addressed to our EtherTalk range")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and adjust the Hop Count
|
||||||
|
// Note the ddp package doesn't make this simple
|
||||||
|
hopCount := (ddpkt.Size & 0x3C00) >> 10
|
||||||
|
if hopCount >= 15 {
|
||||||
|
log.Printf("DDP/AURP: hop count exceeded (%d >= 15)", hopCount)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hopCount++
|
||||||
|
ddpkt.Size &^= 0x3C00
|
||||||
|
ddpkt.Size |= hopCount << 10
|
||||||
|
|
||||||
|
// Is it addressed to me? Is it NBP?
|
||||||
|
if ddpkt.DstNode == 0 { // Node 0 = the router for the network
|
||||||
|
if ddpkt.DstSocket != 2 {
|
||||||
|
// Something else?? TODO
|
||||||
|
log.Printf("DDP/AURP: I don't have anything 'listening' on socket %d", ddpkt.DstSocket)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// It's NBP
|
||||||
|
if err := rooter.HandleNBPInAURP(pr, ddpkt); err != nil {
|
||||||
|
log.Printf("NBP/DDP/AURP: %v", err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: resolving AARP can block
|
||||||
|
if err := rooter.SendEtherTalkDDP(ctx, ddpkt); err != nil {
|
||||||
|
log.Printf("DDP/AURP: couldn't send Ethertalk out: %v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
|
|
||||||
// Note: resolving AARP can block
|
default:
|
||||||
if err := rooter.SendEtherTalkDDP(ctx, ddpkt); err != nil {
|
log.Printf("AURP: Got unknown packet type %v", dh.PacketType)
|
||||||
log.Printf("DDP/AURP: couldn't send Ethertalk out: %v", err)
|
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
|
|
||||||
default:
|
|
||||||
log.Printf("AURP: Got unknown packet type %v", dh.PacketType)
|
|
||||||
}
|
}
|
||||||
}
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hashable net.UDPAddr
|
// Hashable net.UDPAddr
|
||||||
|
|
Loading…
Reference in a new issue