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()
|
||||
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
|
||||
var handlersWG sync.WaitGroup
|
||||
defer func() {
|
||||
log.Print("Waiting for handlers to return...")
|
||||
handlersWG.Wait()
|
||||
ln.Close()
|
||||
}()
|
||||
defer handlersWG.Wait()
|
||||
// defer func() {
|
||||
// // log.Print("Waiting for handlers to return...")
|
||||
// // handlersWG.Wait()
|
||||
// // ln.Close()
|
||||
// }()
|
||||
goPeerHandler := func(p *router.Peer) {
|
||||
handlersWG.Add(1)
|
||||
go func() {
|
||||
|
@ -244,9 +245,9 @@ func main() {
|
|||
}
|
||||
|
||||
rawPkt, _, err := pcapHandle.ReadPacketData()
|
||||
if errors.Is(err, pcap.NextErrorTimeoutExpired) {
|
||||
continue
|
||||
}
|
||||
// if errors.Is(err, pcap.NextErrorTimeoutExpired) {
|
||||
// continue
|
||||
// }
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, pcap.NextErrorNoMorePackets) {
|
||||
return
|
||||
}
|
||||
|
@ -357,132 +358,134 @@ func main() {
|
|||
}()
|
||||
|
||||
// ----------------------------- AURP inbound -----------------------------
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
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():
|
||||
go func() {
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
// ln.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
pktbuf := make([]byte, 4096)
|
||||
pktlen, raddr, readErr := ln.ReadFromUDP(pktbuf)
|
||||
|
||||
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)
|
||||
// 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
|
||||
}
|
||||
|
||||
// Route or otherwise handle the encapsulated AppleTalk traffic
|
||||
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
|
||||
if readErr != nil {
|
||||
log.Printf("AURP: Failed to read packet: %v", readErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 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
|
||||
log.Printf("AURP: Got %T from %v (%v)", pkt, raddr, dh.SourceDI)
|
||||
|
||||
// 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)
|
||||
// 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
|
||||
}
|
||||
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
|
||||
}
|
||||
// It's NBP
|
||||
if err := rooter.HandleNBPInAURP(pr, ddpkt); err != nil {
|
||||
log.Printf("NBP/DDP/AURP: %v", err)
|
||||
|
||||
// Route or otherwise handle the encapsulated AppleTalk traffic
|
||||
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
|
||||
}
|
||||
|
||||
// Note: resolving AARP can block
|
||||
if err := rooter.SendEtherTalkDDP(ctx, ddpkt); err != nil {
|
||||
log.Printf("DDP/AURP: couldn't send Ethertalk out: %v", err)
|
||||
default:
|
||||
log.Printf("AURP: Got unknown packet type %v", dh.PacketType)
|
||||
}
|
||||
continue
|
||||
|
||||
default:
|
||||
log.Printf("AURP: Got unknown packet type %v", dh.PacketType)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Hashable net.UDPAddr
|
||||
|
|
Loading…
Reference in a new issue