Fix NBP replies for the router itself
This commit is contained in:
parent
5103850d6e
commit
3953511438
4 changed files with 146 additions and 97 deletions
90
main.go
90
main.go
|
@ -266,9 +266,6 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: filter ethFrame.Dst to myHWAddr, the broadcast address,
|
|
||||||
// or the relevant zone multicast address
|
|
||||||
|
|
||||||
switch ethFrame.SNAPProto {
|
switch ethFrame.SNAPProto {
|
||||||
case ethertalk.AARPProto:
|
case ethertalk.AARPProto:
|
||||||
// log.Print("Got an AARP frame")
|
// log.Print("Got an AARP frame")
|
||||||
|
@ -385,7 +382,54 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if apkt, ok := pkt.(*aurp.AppleTalkPacket); ok {
|
log.Printf("AURP: Got %T from %v", pkt, 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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route or otherwise handle the encapsulated AppleTalk traffic
|
||||||
ddpkt := new(ddp.ExtPacket)
|
ddpkt := new(ddp.ExtPacket)
|
||||||
if err := ddp.ExtUnmarshal(apkt.Data, ddpkt); err != nil {
|
if err := ddp.ExtUnmarshal(apkt.Data, ddpkt); err != nil {
|
||||||
log.Printf("AURP: Couldn't unmarshal encapsulated DDP packet: %v", err)
|
log.Printf("AURP: Couldn't unmarshal encapsulated DDP packet: %v", err)
|
||||||
|
@ -424,7 +468,7 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// It's NBP
|
// It's NBP
|
||||||
if err := rooter.HandleNBPInAURP(ddpkt); err != nil {
|
if err := rooter.HandleNBPInAURP(pr, ddpkt); err != nil {
|
||||||
log.Printf("NBP/DDP/AURP: %v", err)
|
log.Printf("NBP/DDP/AURP: %v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -453,41 +497,9 @@ func main() {
|
||||||
log.Printf("DDP/AURP: couldn't write output frame to device: %v", err)
|
log.Printf("DDP/AURP: couldn't write output frame to device: %v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("AURP: Got %T from %v", pkt, dh.SourceDI)
|
default:
|
||||||
|
log.Printf("AURP: Got unknown packet type %v", dh.PacketType)
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
110
router/nbp.go
110
router/nbp.go
|
@ -42,62 +42,16 @@ func (rtr *Router) HandleNBP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) erro
|
||||||
switch nbpkt.Function {
|
switch nbpkt.Function {
|
||||||
case nbp.FunctionLkUp:
|
case nbp.FunctionLkUp:
|
||||||
// when in AppleTalk, do as Apple Internet Router does...
|
// when in AppleTalk, do as Apple Internet Router does...
|
||||||
tuple := nbpkt.Tuples[0]
|
outDDP, err := rtr.helloWorldThisIsMe(ddpkt, nbpkt.NBPID, &nbpkt.Tuples[0])
|
||||||
if tuple.Object != "jrouter" && tuple.Object != "=" {
|
if err != nil || outDDP == nil {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if tuple.Type != "AppleRouter" && tuple.Type != "=" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if tuple.Zone != rtr.Config.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
respPkt := &nbp.Packet{
|
|
||||||
Function: nbp.FunctionLkUpReply,
|
|
||||||
NBPID: nbpkt.NBPID,
|
|
||||||
Tuples: []nbp.Tuple{
|
|
||||||
{
|
|
||||||
Network: rtr.MyDDPAddr.Network,
|
|
||||||
Node: rtr.MyDDPAddr.Node,
|
|
||||||
Socket: 253,
|
|
||||||
Enumerator: 0,
|
|
||||||
Object: "jrouter",
|
|
||||||
Type: "AppleRouter",
|
|
||||||
Zone: rtr.Config.EtherTalk.ZoneName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
respRaw, err := respPkt.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("couldn't marshal LkUp-Reply: %v", err)
|
|
||||||
}
|
|
||||||
outDDP := ddp.ExtPacket{
|
|
||||||
ExtHeader: ddp.ExtHeader{
|
|
||||||
Size: uint16(len(respRaw)) + atalk.DDPExtHeaderSize,
|
|
||||||
Cksum: 0,
|
|
||||||
DstNet: ddpkt.SrcNet,
|
|
||||||
DstNode: ddpkt.SrcNode,
|
|
||||||
DstSocket: ddpkt.SrcSocket,
|
|
||||||
SrcNet: rtr.MyDDPAddr.Network,
|
|
||||||
SrcNode: rtr.MyDDPAddr.Node,
|
|
||||||
SrcSocket: 2,
|
|
||||||
},
|
|
||||||
Data: respRaw,
|
|
||||||
}
|
|
||||||
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
outFrame.Dst = srcHWAddr
|
return rtr.sendEtherTalkDDP(srcHWAddr, outDDP)
|
||||||
outFrameRaw, err := ethertalk.Marshal(*outFrame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
|
||||||
|
|
||||||
case nbp.FunctionBrRq:
|
case nbp.FunctionBrRq:
|
||||||
// There must be 1!
|
// There must be 1!
|
||||||
tuple := &nbpkt.Tuples[0]
|
tuple := &nbpkt.Tuples[0]
|
||||||
|
|
||||||
ethDst := ethertalk.AppleTalkBroadcast
|
ethDst := ethertalk.AppleTalkBroadcast
|
||||||
if tuple.Zone != "*" && tuple.Zone != "" {
|
if tuple.Zone != "*" && tuple.Zone != "" {
|
||||||
ethDst = atalk.MulticastAddr(tuple.Zone)
|
ethDst = atalk.MulticastAddr(tuple.Zone)
|
||||||
|
@ -138,6 +92,18 @@ func (rtr *Router) HandleNBP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// But also...if we match the query, reply as though it was a LkUp
|
||||||
|
outDDP2, err := rtr.helloWorldThisIsMe(ddpkt, nbpkt.NBPID, tuple)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if outDDP2 == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := rtr.sendEtherTalkDDP(srcHWAddr, outDDP2); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,3 +146,47 @@ func (rtr *Router) HandleNBP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) erro
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rtr *Router) helloWorldThisIsMe(ddpkt *ddp.ExtPacket, nbpID uint8, tuple *nbp.Tuple) (*ddp.ExtPacket, error) {
|
||||||
|
if tuple.Object != "jrouter" && tuple.Object != "=" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if tuple.Type != "AppleRouter" && tuple.Type != "=" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if tuple.Zone != rtr.Config.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
respPkt := &nbp.Packet{
|
||||||
|
Function: nbp.FunctionLkUpReply,
|
||||||
|
NBPID: nbpID,
|
||||||
|
Tuples: []nbp.Tuple{
|
||||||
|
{
|
||||||
|
Network: rtr.MyDDPAddr.Network,
|
||||||
|
Node: rtr.MyDDPAddr.Node,
|
||||||
|
Socket: 253,
|
||||||
|
Enumerator: 0,
|
||||||
|
Object: "jrouter",
|
||||||
|
Type: "AppleRouter",
|
||||||
|
Zone: rtr.Config.EtherTalk.ZoneName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
respRaw, err := respPkt.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't marshal LkUp-Reply: %v", err)
|
||||||
|
}
|
||||||
|
return &ddp.ExtPacket{
|
||||||
|
ExtHeader: ddp.ExtHeader{
|
||||||
|
Size: uint16(len(respRaw)) + atalk.DDPExtHeaderSize,
|
||||||
|
Cksum: 0,
|
||||||
|
DstNet: ddpkt.SrcNet,
|
||||||
|
DstNode: ddpkt.SrcNode,
|
||||||
|
DstSocket: ddpkt.SrcSocket,
|
||||||
|
SrcNet: rtr.MyDDPAddr.Network,
|
||||||
|
SrcNode: rtr.MyDDPAddr.Node,
|
||||||
|
SrcSocket: 2,
|
||||||
|
},
|
||||||
|
Data: respRaw,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/sfiera/multitalk/pkg/ethertalk"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rtr *Router) HandleNBPInAURP(ddpkt *ddp.ExtPacket) error {
|
func (rtr *Router) HandleNBPInAURP(peer *Peer, ddpkt *ddp.ExtPacket) error {
|
||||||
if ddpkt.Proto != ddp.ProtoNBP {
|
if ddpkt.Proto != ddp.ProtoNBP {
|
||||||
return fmt.Errorf("invalid DDP type %d on socket 2", ddpkt.Proto)
|
return fmt.Errorf("invalid DDP type %d on socket 2", ddpkt.Proto)
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,12 @@ func (rtr *Router) HandleNBPInAURP(ddpkt *ddp.ExtPacket) error {
|
||||||
}
|
}
|
||||||
tuple := &nbpkt.Tuples[0]
|
tuple := &nbpkt.Tuples[0]
|
||||||
|
|
||||||
|
if tuple.Zone != rtr.Config.EtherTalk.ZoneName {
|
||||||
|
return fmt.Errorf("FwdReq querying zone %q, which is not our zone", tuple.Zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Route the FwdReq to another router if it's not our zone
|
||||||
|
|
||||||
log.Printf("NBP/DDP/AURP: Converting FwdReq to LkUp (%v)", tuple)
|
log.Printf("NBP/DDP/AURP: Converting FwdReq to LkUp (%v)", tuple)
|
||||||
|
|
||||||
// Convert it to a LkUp and broadcast on EtherTalk
|
// Convert it to a LkUp and broadcast on EtherTalk
|
||||||
|
@ -61,16 +67,23 @@ func (rtr *Router) HandleNBPInAURP(ddpkt *ddp.ExtPacket) error {
|
||||||
ddpkt.DstNode = 0xFF // Broadcast node address within the dest network
|
ddpkt.DstNode = 0xFF // Broadcast node address within the dest network
|
||||||
ddpkt.Data = nbpRaw
|
ddpkt.Data = nbpRaw
|
||||||
|
|
||||||
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *ddpkt)
|
dstEth := ethertalk.AppleTalkBroadcast
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if tuple.Zone != "*" && tuple.Zone != "" {
|
if tuple.Zone != "*" && tuple.Zone != "" {
|
||||||
outFrame.Dst = atalk.MulticastAddr(tuple.Zone)
|
dstEth = atalk.MulticastAddr(tuple.Zone)
|
||||||
}
|
}
|
||||||
outFrameRaw, err := ethertalk.Marshal(*outFrame)
|
if err := rtr.sendEtherTalkDDP(dstEth, ddpkt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// But also... if it matches us, reply directly with a LkUp-Reply of our own
|
||||||
|
outDDP, err := rtr.helloWorldThisIsMe(ddpkt, nbpkt.NBPID, tuple)
|
||||||
|
if err != nil || outDDP == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outDDPRaw, err := ddp.ExtMarshal(*outDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
_, err = peer.Send(peer.Transport.NewAppleTalkPacket(outDDPRaw))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
"github.com/sfiera/multitalk/pkg/ddp"
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
"github.com/sfiera/multitalk/pkg/ethernet"
|
"github.com/sfiera/multitalk/pkg/ethernet"
|
||||||
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
|
@ -30,3 +31,16 @@ type Router struct {
|
||||||
RouteTable *RoutingTable
|
RouteTable *RoutingTable
|
||||||
ZoneTable *ZoneTable
|
ZoneTable *ZoneTable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rtr *Router) sendEtherTalkDDP(dstEth ethernet.Addr, pkt *ddp.ExtPacket) error {
|
||||||
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *pkt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outFrame.Dst = dstEth
|
||||||
|
outFrameRaw, err := ethertalk.Marshal(*outFrame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue