Forward from AURP to EtherTalk
This commit is contained in:
parent
0d92cd7ba6
commit
dbc3eaaf54
2 changed files with 99 additions and 3 deletions
98
main.go
98
main.go
|
@ -33,6 +33,7 @@ import (
|
|||
|
||||
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||
"gitea.drjosh.dev/josh/jrouter/atalk/aep"
|
||||
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
|
||||
"gitea.drjosh.dev/josh/jrouter/aurp"
|
||||
"github.com/google/gopacket/pcap"
|
||||
"github.com/sfiera/multitalk/pkg/ddp"
|
||||
|
@ -302,15 +303,72 @@ func main() {
|
|||
log.Printf("AURP: The packet parsed succesfully as a %T", pkt)
|
||||
|
||||
if apkt, ok := pkt.(*aurp.AppleTalkPacket); ok {
|
||||
var ddpkt ddp.ExtPacket
|
||||
if err := ddp.ExtUnmarshal(apkt.Data, &ddpkt); err != nil {
|
||||
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("AURP encapsulated DDP: src (%d.%d s %d) dst (%d.%d s %d) proto %d data len %d",
|
||||
log.Printf("DDP/AURP: Got src (%d.%d s %d) dst (%d.%d s %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 := handleNBPInAURP(pcapHandle, myHWAddr, ddpkt); err != nil {
|
||||
log.Printf("NBP/DDP/AURP: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Note: resolving AARP can block
|
||||
dstEth, err := aarpMachine.Resolve(ctx, ddp.Addr{Network: ddpkt.DstNet, Node: ddpkt.DstNode})
|
||||
if err != nil {
|
||||
log.Printf("DDP/AURP: couldn't resolve DDP dest %d.%d to an Ethernet address", ddpkt.DstNet, ddpkt.DstNode)
|
||||
continue
|
||||
}
|
||||
|
||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, *ddpkt)
|
||||
if err != nil {
|
||||
log.Printf("DDP/AURP: couldn't create output frame: %v", err)
|
||||
continue
|
||||
}
|
||||
outFrame.Dst = dstEth
|
||||
|
||||
outFrameRaw, err := ethertalk.Marshal(*outFrame)
|
||||
if err != nil {
|
||||
log.Printf("DDP/AURP: couldn't marshal output frame: %v", err)
|
||||
continue
|
||||
}
|
||||
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
|
||||
log.Printf("DDP/AURP: couldn't write output frame to device: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -346,6 +404,40 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
||||
if ddpkt.Proto != ddp.ProtoNBP {
|
||||
return fmt.Errorf("invalid DDP type %d on socket 2", ddpkt.Proto)
|
||||
}
|
||||
nbpkt, err := nbp.Unmarshal(ddpkt.Data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid NBP packet: %v", err)
|
||||
}
|
||||
if nbpkt.Function != nbp.FunctionFwdReq {
|
||||
// It's something else??
|
||||
return fmt.Errorf("can't handle %v", nbpkt.Function)
|
||||
}
|
||||
|
||||
// Convert it to a LkUp and broadcast on EtherTalk
|
||||
nbpkt.Function = nbp.FunctionLkUp
|
||||
nbpRaw, err := nbpkt.Marshal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't marshal LkUp: %v", err)
|
||||
}
|
||||
|
||||
ddpkt.DstNode = 0xFF // Broadcast node address within the dest network
|
||||
ddpkt.Data = nbpRaw
|
||||
|
||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, *ddpkt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outFrameRaw, err := ethertalk.Marshal(*outFrame)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pcapHandle.WritePacketData(outFrameRaw)
|
||||
}
|
||||
|
||||
func handleAEP(pcapHandle *pcap.Handle, src, dst ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
||||
if ddpkt.Proto != ddp.ProtoAEP {
|
||||
return fmt.Errorf("invalid DDP type %d on socket 4", ddpkt.Proto)
|
||||
|
|
4
nbp.go
4
nbp.go
|
@ -21,6 +21,10 @@ func (NBPMachine) Run(ctx context.Context, incoming <-chan *ddp.ExtPacket) error
|
|||
return ctx.Err()
|
||||
|
||||
case ddpkt := <-incoming:
|
||||
if ddpkt.Proto != ddp.ProtoNBP {
|
||||
log.Printf("NBP: invalid DDP type %d on socket 2", ddpkt.Proto)
|
||||
}
|
||||
|
||||
pkt, err := nbp.Unmarshal(ddpkt.Data)
|
||||
if err != nil {
|
||||
log.Printf("NBP: invalid packet: %v", err)
|
||||
|
|
Loading…
Reference in a new issue