Start massive refactor
This commit is contained in:
parent
c81c6002f8
commit
52b08a83f1
12 changed files with 213 additions and 160 deletions
83
main.go
83
main.go
|
@ -32,6 +32,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/jrouter/aurp"
|
"gitea.drjosh.dev/josh/jrouter/aurp"
|
||||||
|
"gitea.drjosh.dev/josh/jrouter/router"
|
||||||
|
|
||||||
"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"
|
||||||
|
@ -46,7 +48,7 @@ func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log.Println("jrouter")
|
log.Println("jrouter")
|
||||||
|
|
||||||
cfg, err := loadConfig(*configFilePath)
|
cfg, err := router.LoadConfig(*configFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Couldn't load configuration file: %v", err)
|
log.Fatalf("Couldn't load configuration file: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +82,7 @@ func main() {
|
||||||
|
|
||||||
log.Printf("EtherTalk configuration: %+v", cfg.EtherTalk)
|
log.Printf("EtherTalk configuration: %+v", cfg.EtherTalk)
|
||||||
|
|
||||||
peers := make(map[udpAddr]*peer)
|
peers := make(map[udpAddr]*router.Peer)
|
||||||
var nextConnID uint16
|
var nextConnID uint16
|
||||||
for nextConnID == 0 {
|
for nextConnID == 0 {
|
||||||
nextConnID = uint16(rand.IntN(0x10000))
|
nextConnID = uint16(rand.IntN(0x10000))
|
||||||
|
@ -131,17 +133,17 @@ func main() {
|
||||||
handlersWG.Wait()
|
handlersWG.Wait()
|
||||||
ln.Close()
|
ln.Close()
|
||||||
}()
|
}()
|
||||||
goPeerHandler := func(p *peer) {
|
goPeerHandler := func(p *router.Peer) {
|
||||||
handlersWG.Add(1)
|
handlersWG.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer handlersWG.Done()
|
defer handlersWG.Done()
|
||||||
p.handle(ctx)
|
p.Handle(ctx)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------- Tables --------------------------------
|
// -------------------------------- Tables --------------------------------
|
||||||
routing := NewRoutingTable()
|
routing := router.NewRoutingTable()
|
||||||
zones := NewZoneTable()
|
zones := router.NewZoneTable()
|
||||||
zones.Upsert(cfg.EtherTalk.NetStart, cfg.EtherTalk.ZoneName, true)
|
zones.Upsert(cfg.EtherTalk.NetStart, cfg.EtherTalk.ZoneName, true)
|
||||||
|
|
||||||
// ------------------------- Configured peer setup ------------------------
|
// ------------------------- Configured peer setup ------------------------
|
||||||
|
@ -156,18 +158,18 @@ func main() {
|
||||||
}
|
}
|
||||||
log.Printf("resolved %q to %v", peerStr, raddr)
|
log.Printf("resolved %q to %v", peerStr, raddr)
|
||||||
|
|
||||||
peer := &peer{
|
peer := &router.Peer{
|
||||||
cfg: cfg,
|
Config: cfg,
|
||||||
tr: &aurp.Transport{
|
Transport: &aurp.Transport{
|
||||||
LocalDI: localDI,
|
LocalDI: localDI,
|
||||||
RemoteDI: aurp.IPDomainIdentifier(raddr.IP),
|
RemoteDI: aurp.IPDomainIdentifier(raddr.IP),
|
||||||
LocalConnID: nextConnID,
|
LocalConnID: nextConnID,
|
||||||
},
|
},
|
||||||
conn: ln,
|
UDPConn: ln,
|
||||||
raddr: raddr,
|
RemoteAddr: raddr,
|
||||||
recv: make(chan aurp.Packet, 1024),
|
RecieveCh: make(chan aurp.Packet, 1024),
|
||||||
routingTable: routing,
|
RoutingTable: routing,
|
||||||
zoneTable: zones,
|
ZoneTable: zones,
|
||||||
}
|
}
|
||||||
aurp.Inc(&nextConnID)
|
aurp.Inc(&nextConnID)
|
||||||
peers[udpAddrFromNet(raddr)] = peer
|
peers[udpAddrFromNet(raddr)] = peer
|
||||||
|
@ -175,20 +177,30 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------- AARP ---------------------------------
|
// --------------------------------- AARP ---------------------------------
|
||||||
aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr)
|
aarpMachine := router.NewAARPMachine(cfg, pcapHandle, myHWAddr)
|
||||||
aarpCh := make(chan *ethertalk.Packet, 1024)
|
aarpCh := make(chan *ethertalk.Packet, 1024)
|
||||||
go aarpMachine.Run(ctx, aarpCh)
|
go aarpMachine.Run(ctx, aarpCh)
|
||||||
|
|
||||||
// --------------------------------- RTMP ---------------------------------
|
// --------------------------------- RTMP ---------------------------------
|
||||||
rtmpMachine := &RTMPMachine{
|
rtmpMachine := &router.RTMPMachine{
|
||||||
aarp: aarpMachine,
|
AARP: aarpMachine,
|
||||||
cfg: cfg,
|
Config: cfg,
|
||||||
pcapHandle: pcapHandle,
|
PcapHandle: pcapHandle,
|
||||||
routingTable: routing,
|
RoutingTable: routing,
|
||||||
}
|
}
|
||||||
rtmpCh := make(chan *ddp.ExtPacket, 1024)
|
rtmpCh := make(chan *ddp.ExtPacket, 1024)
|
||||||
go rtmpMachine.Run(ctx, rtmpCh)
|
go rtmpMachine.Run(ctx, rtmpCh)
|
||||||
|
|
||||||
|
// -------------------------------- Router --------------------------------
|
||||||
|
rooter := &router.Router{
|
||||||
|
Config: cfg,
|
||||||
|
PcapHandle: pcapHandle,
|
||||||
|
MyHWAddr: myHWAddr,
|
||||||
|
// MyDDPAddr: ...,
|
||||||
|
RouteTable: routing,
|
||||||
|
ZoneTable: zones,
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------- Raw AppleTalk/AARP inbound ----------------------
|
// ---------------------- Raw AppleTalk/AARP inbound ----------------------
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
@ -249,6 +261,7 @@ func main() {
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
rooter.MyDDPAddr = myAddr.Proto
|
||||||
|
|
||||||
// Our network?
|
// Our network?
|
||||||
// "The network number 0 is reserved to mean unknown; by default
|
// "The network number 0 is reserved to mean unknown; by default
|
||||||
|
@ -264,8 +277,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encap ethPacket.Payload into an AURP packet
|
// Encap ethPacket.Payload into an AURP packet
|
||||||
log.Printf("DDP: forwarding to AURP peer %v", rt.Peer.tr.RemoteDI)
|
log.Printf("DDP: forwarding to AURP peer %v", rt.Peer.Transport.RemoteDI)
|
||||||
if _, err := rt.Peer.send(rt.Peer.tr.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
|
if _, err := rt.Peer.Send(rt.Peer.Transport.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
|
||||||
log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
|
log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,17 +298,17 @@ func main() {
|
||||||
rtmpCh <- ddpkt
|
rtmpCh <- ddpkt
|
||||||
|
|
||||||
case 2: // The NIS (name information socket / NBP socket)
|
case 2: // The NIS (name information socket / NBP socket)
|
||||||
if err := handleNBP(pcapHandle, myHWAddr, ethFrame.Src, myAddr, zones, routing, cfg, ddpkt); err != nil {
|
if err := rooter.HandleNBP(ethFrame.Src, ddpkt); err != nil {
|
||||||
log.Printf("NBP: Couldn't handle: %v", err)
|
log.Printf("NBP: Couldn't handle: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: // The AEP socket
|
case 4: // The AEP socket
|
||||||
if err := handleAEP(pcapHandle, myHWAddr, ethFrame.Src, ddpkt); err != nil {
|
if err := rooter.HandleAEP(ethFrame.Src, ddpkt); err != nil {
|
||||||
log.Printf("AEP: Couldn't handle: %v", err)
|
log.Printf("AEP: Couldn't handle: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 6: // The ZIS (zone information socket / ZIP socket)
|
case 6: // The ZIS (zone information socket / ZIP socket)
|
||||||
if err := handleZIP(pcapHandle, ethFrame.Src, myHWAddr, myAddr, cfg, zones, ddpkt); err != nil {
|
if err := rooter.HandleZIP(ethFrame.Src, ddpkt); err != nil {
|
||||||
log.Printf("ZIP: couldn't handle: %v", err)
|
log.Printf("ZIP: couldn't handle: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +388,7 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// It's NBP
|
// It's NBP
|
||||||
if err := handleNBPInAURP(pcapHandle, myHWAddr, ddpkt); err != nil {
|
if err := rooter.HandleNBPInAURP(ddpkt); err != nil {
|
||||||
log.Printf("NBP/DDP/AURP: %v", err)
|
log.Printf("NBP/DDP/AURP: %v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -413,18 +426,18 @@ func main() {
|
||||||
pr := peers[ra]
|
pr := peers[ra]
|
||||||
if pr == nil {
|
if pr == nil {
|
||||||
// New peer!
|
// New peer!
|
||||||
pr = &peer{
|
pr = &router.Peer{
|
||||||
cfg: cfg,
|
Config: cfg,
|
||||||
tr: &aurp.Transport{
|
Transport: &aurp.Transport{
|
||||||
LocalDI: localDI,
|
LocalDI: localDI,
|
||||||
RemoteDI: dh.SourceDI, // platinum rule
|
RemoteDI: dh.SourceDI, // platinum rule
|
||||||
LocalConnID: nextConnID,
|
LocalConnID: nextConnID,
|
||||||
},
|
},
|
||||||
conn: ln,
|
UDPConn: ln,
|
||||||
raddr: raddr,
|
RemoteAddr: raddr,
|
||||||
recv: make(chan aurp.Packet, 1024),
|
RecieveCh: make(chan aurp.Packet, 1024),
|
||||||
routingTable: routing,
|
RoutingTable: routing,
|
||||||
zoneTable: zones,
|
ZoneTable: zones,
|
||||||
}
|
}
|
||||||
aurp.Inc(&nextConnID)
|
aurp.Inc(&nextConnID)
|
||||||
peers[ra] = pr
|
peers[ra] = pr
|
||||||
|
@ -433,7 +446,7 @@ func main() {
|
||||||
|
|
||||||
// Pass the packet to the goroutine in charge of this peer.
|
// Pass the packet to the goroutine in charge of this peer.
|
||||||
select {
|
select {
|
||||||
case pr.recv <- pkt:
|
case pr.RecieveCh <- pkt:
|
||||||
// That's it for us.
|
// That's it for us.
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -44,7 +44,7 @@ const (
|
||||||
type AARPMachine struct {
|
type AARPMachine struct {
|
||||||
*addressMappingTable
|
*addressMappingTable
|
||||||
|
|
||||||
cfg *config
|
cfg *Config
|
||||||
pcapHandle *pcap.Handle
|
pcapHandle *pcap.Handle
|
||||||
|
|
||||||
// The Run goroutine is responsible for all writes to myAddr.Proto and
|
// The Run goroutine is responsible for all writes to myAddr.Proto and
|
||||||
|
@ -58,7 +58,7 @@ type AARPMachine struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAARPMachine creates a new AARPMachine.
|
// NewAARPMachine creates a new AARPMachine.
|
||||||
func NewAARPMachine(cfg *config, pcapHandle *pcap.Handle, myHWAddr ethernet.Addr) *AARPMachine {
|
func NewAARPMachine(cfg *Config, pcapHandle *pcap.Handle, myHWAddr ethernet.Addr) *AARPMachine {
|
||||||
return &AARPMachine{
|
return &AARPMachine{
|
||||||
addressMappingTable: new(addressMappingTable),
|
addressMappingTable: new(addressMappingTable),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
|
@ -14,19 +14,18 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/aep"
|
"gitea.drjosh.dev/josh/jrouter/atalk/aep"
|
||||||
"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"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleAEP(pcapHandle *pcap.Handle, src, dst ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
func (rtr *Router) HandleAEP(src ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
||||||
if ddpkt.Proto != ddp.ProtoAEP {
|
if ddpkt.Proto != ddp.ProtoAEP {
|
||||||
return fmt.Errorf("invalid DDP type %d on socket 4", ddpkt.Proto)
|
return fmt.Errorf("invalid DDP type %d on socket 4", ddpkt.Proto)
|
||||||
}
|
}
|
||||||
|
@ -49,16 +48,16 @@ func handleAEP(pcapHandle *pcap.Handle, src, dst ethernet.Addr, ddpkt *ddp.ExtPa
|
||||||
ddpkt.DstSocket, ddpkt.SrcSocket = ddpkt.SrcSocket, ddpkt.DstSocket
|
ddpkt.DstSocket, ddpkt.SrcSocket = ddpkt.SrcSocket, ddpkt.DstSocket
|
||||||
ddpkt.Data[0] = byte(aep.EchoReply)
|
ddpkt.Data[0] = byte(aep.EchoReply)
|
||||||
|
|
||||||
ethFrame, err := ethertalk.AppleTalk(src, *ddpkt)
|
ethFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *ddpkt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ethFrame.Dst = dst
|
ethFrame.Dst = src
|
||||||
ethFrameRaw, err := ethertalk.Marshal(*ethFrame)
|
ethFrameRaw, err := ethertalk.Marshal(*ethFrame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return pcapHandle.WritePacketData(ethFrameRaw)
|
return rtr.PcapHandle.WritePacketData(ethFrameRaw)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid AEP function %d", ep.Function)
|
return fmt.Errorf("invalid AEP function %d", ep.Function)
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
@ -23,7 +23,7 @@ import (
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type Config struct {
|
||||||
// Optional: default is 387.
|
// Optional: default is 387.
|
||||||
ListenPort uint16 `yaml:"listen_port"`
|
ListenPort uint16 `yaml:"listen_port"`
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@ type config struct {
|
||||||
Peers []string `yaml:"peers"`
|
Peers []string `yaml:"peers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(cfgPath string) (*config, error) {
|
func LoadConfig(cfgPath string) (*Config, error) {
|
||||||
f, err := os.Open(cfgPath)
|
f, err := os.Open(cfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
c := new(config)
|
c := new(Config)
|
||||||
if err := yaml.NewDecoder(f).Decode(c); err != nil {
|
if err := yaml.NewDecoder(f).Decode(c); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -22,14 +22,12 @@ import (
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk"
|
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
|
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
|
||||||
"github.com/google/gopacket/pcap"
|
|
||||||
"github.com/sfiera/multitalk/pkg/aarp"
|
|
||||||
"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"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAddr aarp.AddrPair, zoneTable *ZoneTable, routeTable *RoutingTable, cfg *config, ddpkt *ddp.ExtPacket) error {
|
func (rtr *Router) HandleNBP(srcHWAddr ethernet.Addr, 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)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +49,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
if tuple.Type != "AppleRouter" && tuple.Type != "=" {
|
if tuple.Type != "AppleRouter" && tuple.Type != "=" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if tuple.Zone != cfg.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
|
if tuple.Zone != rtr.Config.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
respPkt := &nbp.Packet{
|
respPkt := &nbp.Packet{
|
||||||
|
@ -59,13 +57,13 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
NBPID: nbpkt.NBPID,
|
NBPID: nbpkt.NBPID,
|
||||||
Tuples: []nbp.Tuple{
|
Tuples: []nbp.Tuple{
|
||||||
{
|
{
|
||||||
Network: myAddr.Proto.Network,
|
Network: rtr.MyDDPAddr.Network,
|
||||||
Node: myAddr.Proto.Node,
|
Node: rtr.MyDDPAddr.Node,
|
||||||
Socket: 253,
|
Socket: 253,
|
||||||
Enumerator: 0,
|
Enumerator: 0,
|
||||||
Object: "jrouter",
|
Object: "jrouter",
|
||||||
Type: "AppleRouter",
|
Type: "AppleRouter",
|
||||||
Zone: cfg.EtherTalk.ZoneName,
|
Zone: rtr.Config.EtherTalk.ZoneName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -80,13 +78,13 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
DstNet: ddpkt.SrcNet,
|
DstNet: ddpkt.SrcNet,
|
||||||
DstNode: ddpkt.SrcNode,
|
DstNode: ddpkt.SrcNode,
|
||||||
DstSocket: ddpkt.SrcSocket,
|
DstSocket: ddpkt.SrcSocket,
|
||||||
SrcNet: myAddr.Proto.Network,
|
SrcNet: rtr.MyDDPAddr.Network,
|
||||||
SrcNode: myAddr.Proto.Node,
|
SrcNode: rtr.MyDDPAddr.Node,
|
||||||
SrcSocket: 2,
|
SrcSocket: 2,
|
||||||
},
|
},
|
||||||
Data: respRaw,
|
Data: respRaw,
|
||||||
}
|
}
|
||||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -95,7 +93,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return pcapHandle.WritePacketData(outFrameRaw)
|
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
||||||
|
|
||||||
case nbp.FunctionBrRq:
|
case nbp.FunctionBrRq:
|
||||||
// There must be 1!
|
// There must be 1!
|
||||||
|
@ -105,7 +103,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
ethDst = atalk.MulticastAddr(tuple.Zone)
|
ethDst = atalk.MulticastAddr(tuple.Zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
zones := zoneTable.LookupName(tuple.Zone)
|
zones := rtr.ZoneTable.LookupName(tuple.Zone)
|
||||||
for _, z := range zones {
|
for _, z := range zones {
|
||||||
if z.Local {
|
if z.Local {
|
||||||
// If it's for the local zone, translate it to a LkUp and broadcast it back
|
// If it's for the local zone, translate it to a LkUp and broadcast it back
|
||||||
|
@ -127,7 +125,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
outDDP.DstNode = 0xFF // Broadcast node address within the dest network
|
outDDP.DstNode = 0xFF // Broadcast node address within the dest network
|
||||||
outDDP.Data = nbpRaw
|
outDDP.Data = nbpRaw
|
||||||
|
|
||||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -136,14 +134,14 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
|
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
route := routeTable.LookupRoute(z.Network)
|
route := rtr.RouteTable.LookupRoute(z.Network)
|
||||||
if route == nil {
|
if route == nil {
|
||||||
return fmt.Errorf("no route for network %d", z.Network)
|
return fmt.Errorf("no route for network %d", z.Network)
|
||||||
}
|
}
|
||||||
|
@ -171,7 +169,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := peer.send(peer.tr.NewAppleTalkPacket(outDDPRaw)); err != nil {
|
if _, err := peer.Send(peer.Transport.NewAppleTalkPacket(outDDPRaw)); err != nil {
|
||||||
return fmt.Errorf("sending FwdReq on to peer: %w", err)
|
return fmt.Errorf("sending FwdReq on to peer: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -22,13 +22,11 @@ import (
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk"
|
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
|
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
|
||||||
"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/ethertalk"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
func (rtr *Router) HandleNBPInAURP(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)
|
||||||
}
|
}
|
||||||
|
@ -63,7 +61,7 @@ func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp
|
||||||
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(myHWAddr, *ddpkt)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *ddpkt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -74,5 +72,5 @@ func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return pcapHandle.WritePacketData(outFrameRaw)
|
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -75,28 +75,27 @@ func (ss senderState) String() string {
|
||||||
}[ss]
|
}[ss]
|
||||||
}
|
}
|
||||||
|
|
||||||
type peer struct {
|
type Peer struct {
|
||||||
cfg *config
|
Config *Config
|
||||||
tr *aurp.Transport
|
Transport *aurp.Transport
|
||||||
conn *net.UDPConn
|
UDPConn *net.UDPConn
|
||||||
raddr *net.UDPAddr
|
RemoteAddr *net.UDPAddr
|
||||||
recv chan aurp.Packet
|
RecieveCh chan aurp.Packet
|
||||||
|
RoutingTable *RoutingTable
|
||||||
routingTable *RoutingTable
|
ZoneTable *ZoneTable
|
||||||
zoneTable *ZoneTable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send encodes and sends pkt to the remote host.
|
// Send encodes and sends pkt to the remote host.
|
||||||
func (p *peer) send(pkt aurp.Packet) (int, error) {
|
func (p *Peer) Send(pkt aurp.Packet) (int, error) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if _, err := pkt.WriteTo(&b); err != nil {
|
if _, err := pkt.WriteTo(&b); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
log.Printf("Sending %T (len %d) to %v", pkt, b.Len(), p.raddr)
|
log.Printf("Sending %T (len %d) to %v", pkt, b.Len(), p.RemoteAddr)
|
||||||
return p.conn.WriteToUDP(b.Bytes(), p.raddr)
|
return p.UDPConn.WriteToUDP(b.Bytes(), p.RemoteAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handle(ctx context.Context) error {
|
func (p *Peer) Handle(ctx context.Context) error {
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
sstate := ssUnconnected
|
sstate := ssUnconnected
|
||||||
|
|
||||||
// Write an Open-Req packet
|
// Write an Open-Req packet
|
||||||
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
|
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
|
||||||
log.Printf("Couldn't send Open-Req packet: %v", err)
|
log.Printf("Couldn't send Open-Req packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -123,7 +122,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
// Send a best-effort Router Down before returning
|
// Send a best-effort Router Down before returning
|
||||||
if _, err := p.send(p.tr.NewRDPacket(aurp.ErrCodeNormalClose)); err != nil {
|
if _, err := p.Send(p.Transport.NewRDPacket(aurp.ErrCodeNormalClose)); err != nil {
|
||||||
log.Printf("Couldn't send RD packet: %v", err)
|
log.Printf("Couldn't send RD packet: %v", err)
|
||||||
}
|
}
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
|
@ -143,7 +142,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
// Send another Open-Req
|
// Send another Open-Req
|
||||||
sendRetries++
|
sendRetries++
|
||||||
lastSend = time.Now()
|
lastSend = time.Now()
|
||||||
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
|
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
|
||||||
log.Printf("Couldn't send Open-Req packet: %v", err)
|
log.Printf("Couldn't send Open-Req packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -153,7 +152,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
if time.Since(lastHeardFrom) <= lastHeardFromTimer {
|
if time.Since(lastHeardFrom) <= lastHeardFromTimer {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if _, err := p.send(p.tr.NewTicklePacket()); err != nil {
|
if _, err := p.Send(p.Transport.NewTicklePacket()); err != nil {
|
||||||
log.Printf("Couldn't send Tickle: %v", err)
|
log.Printf("Couldn't send Tickle: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -173,7 +172,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
|
|
||||||
sendRetries++
|
sendRetries++
|
||||||
lastSend = time.Now()
|
lastSend = time.Now()
|
||||||
if _, err := p.send(p.tr.NewTicklePacket()); err != nil {
|
if _, err := p.Send(p.Transport.NewTicklePacket()); err != nil {
|
||||||
log.Printf("Couldn't send Tickle: %v", err)
|
log.Printf("Couldn't send Tickle: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -185,7 +184,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
case pkt := <-p.recv:
|
case pkt := <-p.RecieveCh:
|
||||||
lastHeardFrom = time.Now()
|
lastHeardFrom = time.Now()
|
||||||
|
|
||||||
switch pkt := pkt.(type) {
|
switch pkt := pkt.(type) {
|
||||||
|
@ -195,25 +194,25 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The peer tells us their connection ID in Open-Req.
|
// The peer tells us their connection ID in Open-Req.
|
||||||
p.tr.RemoteConnID = pkt.ConnectionID
|
p.Transport.RemoteConnID = pkt.ConnectionID
|
||||||
|
|
||||||
// Formulate a response.
|
// Formulate a response.
|
||||||
var orsp *aurp.OpenRspPacket
|
var orsp *aurp.OpenRspPacket
|
||||||
switch {
|
switch {
|
||||||
case pkt.Version != 1:
|
case pkt.Version != 1:
|
||||||
// Respond with Open-Rsp with unknown version error.
|
// Respond with Open-Rsp with unknown version error.
|
||||||
orsp = p.tr.NewOpenRspPacket(0, int16(aurp.ErrCodeInvalidVersion), nil)
|
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeInvalidVersion), nil)
|
||||||
|
|
||||||
case len(pkt.Options) > 0:
|
case len(pkt.Options) > 0:
|
||||||
// Options? OPTIONS? We don't accept no stinkin' _options_
|
// Options? OPTIONS? We don't accept no stinkin' _options_
|
||||||
orsp = p.tr.NewOpenRspPacket(0, int16(aurp.ErrCodeOptionNegotiation), nil)
|
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeOptionNegotiation), nil)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Accept it I guess.
|
// Accept it I guess.
|
||||||
orsp = p.tr.NewOpenRspPacket(0, 1, nil)
|
orsp = p.Transport.NewOpenRspPacket(0, 1, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := p.send(orsp); err != nil {
|
if _, err := p.Send(orsp); err != nil {
|
||||||
log.Printf("Couldn't send Open-Rsp: %v", err)
|
log.Printf("Couldn't send Open-Rsp: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -225,7 +224,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
if rstate == rsUnconnected {
|
if rstate == rsUnconnected {
|
||||||
lastSend = time.Now()
|
lastSend = time.Now()
|
||||||
sendRetries = 0
|
sendRetries = 0
|
||||||
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
|
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
|
||||||
log.Printf("Couldn't send Open-Req packet: %v", err)
|
log.Printf("Couldn't send Open-Req packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -238,7 +237,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
if pkt.RateOrErrCode < 0 {
|
if pkt.RateOrErrCode < 0 {
|
||||||
// It's an error code.
|
// It's an error code.
|
||||||
log.Printf("Open-Rsp error code from peer %v: %d", p.raddr.IP, pkt.RateOrErrCode)
|
log.Printf("Open-Rsp error code from peer %v: %d", p.RemoteAddr.IP, pkt.RateOrErrCode)
|
||||||
rstate = rsUnconnected
|
rstate = rsUnconnected
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -246,7 +245,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
rstate = rsConnected
|
rstate = rsConnected
|
||||||
|
|
||||||
// Send an RI-Req
|
// Send an RI-Req
|
||||||
if _, err := p.send(p.tr.NewRIReqPacket()); err != nil {
|
if _, err := p.Send(p.Transport.NewRIReqPacket()); err != nil {
|
||||||
log.Printf("Couldn't send RI-Req packet: %v", err)
|
log.Printf("Couldn't send RI-Req packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -260,13 +259,13 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
nets := aurp.NetworkTuples{
|
nets := aurp.NetworkTuples{
|
||||||
{
|
{
|
||||||
Extended: true,
|
Extended: true,
|
||||||
RangeStart: uint16(p.cfg.EtherTalk.NetStart),
|
RangeStart: uint16(p.Config.EtherTalk.NetStart),
|
||||||
RangeEnd: uint16(p.cfg.EtherTalk.NetEnd),
|
RangeEnd: uint16(p.Config.EtherTalk.NetEnd),
|
||||||
Distance: 0,
|
Distance: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
p.tr.LocalSeq = 1
|
p.Transport.LocalSeq = 1
|
||||||
if _, err := p.send(p.tr.NewRIRspPacket(aurp.RoutingFlagLast, nets)); err != nil {
|
if _, err := p.Send(p.Transport.NewRIRspPacket(aurp.RoutingFlagLast, nets)); err != nil {
|
||||||
log.Printf("Couldn't send RI-Rsp packet: %v", err)
|
log.Printf("Couldn't send RI-Rsp packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -280,7 +279,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
log.Printf("Learned about these networks: %v", pkt.Networks)
|
log.Printf("Learned about these networks: %v", pkt.Networks)
|
||||||
|
|
||||||
for _, nt := range pkt.Networks {
|
for _, nt := range pkt.Networks {
|
||||||
p.routingTable.UpsertRoute(
|
p.RoutingTable.UpsertRoute(
|
||||||
nt.Extended,
|
nt.Extended,
|
||||||
ddp.Network(nt.RangeStart),
|
ddp.Network(nt.RangeStart),
|
||||||
ddp.Network(nt.RangeEnd),
|
ddp.Network(nt.RangeEnd),
|
||||||
|
@ -291,7 +290,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
|
|
||||||
// TODO: track which networks we don't have zone info for, and
|
// TODO: track which networks we don't have zone info for, and
|
||||||
// only set SZI for those ?
|
// only set SZI for those ?
|
||||||
if _, err := p.send(p.tr.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, aurp.RoutingFlagSendZoneInfo)); err != nil {
|
if _, err := p.Send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, aurp.RoutingFlagSendZoneInfo)); err != nil {
|
||||||
log.Printf("Couldn't send RI-Ack packet: %v", err)
|
log.Printf("Couldn't send RI-Ack packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -324,11 +323,11 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
if pkt.Flags&aurp.RoutingFlagSendZoneInfo != 0 {
|
if pkt.Flags&aurp.RoutingFlagSendZoneInfo != 0 {
|
||||||
zones := aurp.ZoneTuples{
|
zones := aurp.ZoneTuples{
|
||||||
{
|
{
|
||||||
Network: uint16(p.cfg.EtherTalk.NetStart),
|
Network: uint16(p.Config.EtherTalk.NetStart),
|
||||||
Name: p.cfg.EtherTalk.ZoneName,
|
Name: p.Config.EtherTalk.ZoneName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if _, err := p.send(p.tr.NewZIRspPacket(zones)); err != nil {
|
if _, err := p.Send(p.Transport.NewZIRspPacket(zones)); err != nil {
|
||||||
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
|
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +345,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
|
|
||||||
log.Printf("Router Down: error code %d %s", pkt.ErrorCode, pkt.ErrorCode)
|
log.Printf("Router Down: error code %d %s", pkt.ErrorCode, pkt.ErrorCode)
|
||||||
// Respond with RI-Ack
|
// Respond with RI-Ack
|
||||||
if _, err := p.send(p.tr.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, 0)); err != nil {
|
if _, err := p.Send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, 0)); err != nil {
|
||||||
log.Printf("Couldn't send RI-Ack: %v", err)
|
log.Printf("Couldn't send RI-Ack: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -358,11 +357,11 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
// ZI-Req
|
// ZI-Req
|
||||||
zones := aurp.ZoneTuples{
|
zones := aurp.ZoneTuples{
|
||||||
{
|
{
|
||||||
Network: uint16(p.cfg.EtherTalk.NetStart),
|
Network: uint16(p.Config.EtherTalk.NetStart),
|
||||||
Name: p.cfg.EtherTalk.ZoneName,
|
Name: p.Config.EtherTalk.ZoneName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if _, err := p.send(p.tr.NewZIRspPacket(zones)); err != nil {
|
if _, err := p.Send(p.Transport.NewZIRspPacket(zones)); err != nil {
|
||||||
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
|
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -370,11 +369,11 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
case *aurp.ZIRspPacket:
|
case *aurp.ZIRspPacket:
|
||||||
log.Printf("Learned about these zones: %v", pkt.Zones)
|
log.Printf("Learned about these zones: %v", pkt.Zones)
|
||||||
for _, zt := range pkt.Zones {
|
for _, zt := range pkt.Zones {
|
||||||
p.zoneTable.Upsert(ddp.Network(zt.Network), zt.Name, false)
|
p.ZoneTable.Upsert(ddp.Network(zt.Network), zt.Name, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *aurp.GDZLReqPacket:
|
case *aurp.GDZLReqPacket:
|
||||||
if _, err := p.send(p.tr.NewGDZLRspPacket(-1, nil)); err != nil {
|
if _, err := p.Send(p.Transport.NewGDZLRspPacket(-1, nil)); err != nil {
|
||||||
log.Printf("Couldn't send GDZL-Rsp packet: %v", err)
|
log.Printf("Couldn't send GDZL-Rsp packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -383,7 +382,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
log.Printf("Received a GDZL-Rsp, but I wouldn't have sent a GDZL-Req - that's weird")
|
log.Printf("Received a GDZL-Rsp, but I wouldn't have sent a GDZL-Req - that's weird")
|
||||||
|
|
||||||
case *aurp.GZNReqPacket:
|
case *aurp.GZNReqPacket:
|
||||||
if _, err := p.send(p.tr.NewGZNRspPacket(pkt.ZoneName, false, nil)); err != nil {
|
if _, err := p.Send(p.Transport.NewGZNRspPacket(pkt.ZoneName, false, nil)); err != nil {
|
||||||
log.Printf("Couldn't send GZN-Rsp packet: %v", err)
|
log.Printf("Couldn't send GZN-Rsp packet: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -393,7 +392,7 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
|
|
||||||
case *aurp.TicklePacket:
|
case *aurp.TicklePacket:
|
||||||
// Immediately respond with Tickle-Ack
|
// Immediately respond with Tickle-Ack
|
||||||
if _, err := p.send(p.tr.NewTickleAckPacket()); err != nil {
|
if _, err := p.Send(p.Transport.NewTickleAckPacket()); err != nil {
|
||||||
log.Printf("Couldn't send Tickle-Ack: %v", err)
|
log.Printf("Couldn't send Tickle-Ack: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -1,4 +1,20 @@
|
||||||
package main
|
/*
|
||||||
|
Copyright 2024 Josh Deprez
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -14,7 +30,7 @@ type Route struct {
|
||||||
Extended bool
|
Extended bool
|
||||||
NetStart ddp.Network
|
NetStart ddp.Network
|
||||||
NetEnd ddp.Network
|
NetEnd ddp.Network
|
||||||
Peer *peer
|
Peer *Peer
|
||||||
Distance uint8
|
Distance uint8
|
||||||
LastSeen time.Time
|
LastSeen time.Time
|
||||||
}
|
}
|
||||||
|
@ -56,7 +72,7 @@ func (rt *RoutingTable) LookupRoute(network ddp.Network) *Route {
|
||||||
return bestRoute
|
return bestRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *RoutingTable) UpsertRoute(extended bool, netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
|
func (rt *RoutingTable) UpsertRoute(extended bool, netStart, netEnd ddp.Network, peer *Peer, metric uint8) error {
|
||||||
if netStart > netEnd {
|
if netStart > netEnd {
|
||||||
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
|
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
|
||||||
}
|
}
|
32
router/router.go
Normal file
32
router/router.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 Josh Deprez
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
|
"github.com/sfiera/multitalk/pkg/ethernet"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Router struct {
|
||||||
|
Config *Config
|
||||||
|
PcapHandle *pcap.Handle
|
||||||
|
MyHWAddr ethernet.Addr
|
||||||
|
MyDDPAddr ddp.Addr
|
||||||
|
RouteTable *RoutingTable
|
||||||
|
ZoneTable *ZoneTable
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -33,17 +33,17 @@ import (
|
||||||
|
|
||||||
// RTMPMachine implements RTMP on an AppleTalk network attached to the router.
|
// RTMPMachine implements RTMP on an AppleTalk network attached to the router.
|
||||||
type RTMPMachine struct {
|
type RTMPMachine struct {
|
||||||
aarp *AARPMachine
|
AARP *AARPMachine
|
||||||
cfg *config
|
Config *Config
|
||||||
pcapHandle *pcap.Handle
|
PcapHandle *pcap.Handle
|
||||||
routingTable *RoutingTable
|
RoutingTable *RoutingTable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run executes the machine.
|
// Run executes the machine.
|
||||||
func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket) error {
|
func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket) error {
|
||||||
// Await local address assignment before doing anything
|
// Await local address assignment before doing anything
|
||||||
<-m.aarp.Assigned()
|
<-m.AARP.Assigned()
|
||||||
myAddr, ok := m.aarp.Address()
|
myAddr, ok := m.AARP.Address()
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("AARP machine closed Assigned channel but Address is not valid")
|
return fmt.Errorf("AARP machine closed Assigned channel but Address is not valid")
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be in the cache...
|
// should be in the cache...
|
||||||
theirHWAddr, err := m.aarp.Resolve(ctx, ddp.Addr{Network: pkt.SrcNet, Node: pkt.SrcNode})
|
theirHWAddr, err := m.AARP.Resolve(ctx, ddp.Addr{Network: pkt.SrcNet, Node: pkt.SrcNode})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("RTMP: Couldn't resolve %d.%d to a hardware address: %v", pkt.SrcNet, pkt.SrcNode, err)
|
log.Printf("RTMP: Couldn't resolve %d.%d to a hardware address: %v", pkt.SrcNet, pkt.SrcNode, err)
|
||||||
continue
|
continue
|
||||||
|
@ -88,8 +88,8 @@ func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket)
|
||||||
respPkt := &rtmp.ResponsePacket{
|
respPkt := &rtmp.ResponsePacket{
|
||||||
SenderAddr: myAddr.Proto,
|
SenderAddr: myAddr.Proto,
|
||||||
Extended: true,
|
Extended: true,
|
||||||
RangeStart: m.cfg.EtherTalk.NetStart,
|
RangeStart: m.Config.EtherTalk.NetStart,
|
||||||
RangeEnd: m.cfg.EtherTalk.NetEnd,
|
RangeEnd: m.Config.EtherTalk.NetEnd,
|
||||||
}
|
}
|
||||||
respPktRaw, err := respPkt.Marshal()
|
respPktRaw, err := respPkt.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +170,7 @@ func (m *RTMPMachine) send(src, dst ethernet.Addr, ddpPkt *ddp.ExtPacket) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return m.pcapHandle.WritePacketData(ethFrameRaw)
|
return m.PcapHandle.WritePacketData(ethFrameRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RTMPMachine) broadcastData(myAddr aarp.AddrPair) error {
|
func (m *RTMPMachine) broadcastData(myAddr aarp.AddrPair) error {
|
||||||
|
@ -209,13 +209,13 @@ func (m *RTMPMachine) dataPacket(myAddr ddp.Addr) *rtmp.DataPacket {
|
||||||
// to that network."
|
// to that network."
|
||||||
{
|
{
|
||||||
Extended: true,
|
Extended: true,
|
||||||
RangeStart: m.cfg.EtherTalk.NetStart,
|
RangeStart: m.Config.EtherTalk.NetStart,
|
||||||
RangeEnd: m.cfg.EtherTalk.NetEnd,
|
RangeEnd: m.Config.EtherTalk.NetEnd,
|
||||||
Distance: 0,
|
Distance: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, rt := range m.routingTable.ValidRoutes() {
|
for _, rt := range m.RoutingTable.ValidRoutes() {
|
||||||
p.NetworkTuples = append(p.NetworkTuples, rtmp.NetworkTuple{
|
p.NetworkTuples = append(p.NetworkTuples, rtmp.NetworkTuple{
|
||||||
Extended: rt.Extended,
|
Extended: rt.Extended,
|
||||||
RangeStart: rt.NetStart,
|
RangeStart: rt.NetStart,
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -23,14 +23,12 @@ import (
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk"
|
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/atp"
|
"gitea.drjosh.dev/josh/jrouter/atalk/atp"
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/zip"
|
"gitea.drjosh.dev/josh/jrouter/atalk/zip"
|
||||||
"github.com/google/gopacket/pcap"
|
|
||||||
"github.com/sfiera/multitalk/pkg/aarp"
|
|
||||||
"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"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAddr aarp.AddrPair, cfg *config, zones *ZoneTable, ddpkt *ddp.ExtPacket) error {
|
func (rtr *Router) HandleZIP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
|
||||||
switch ddpkt.Proto {
|
switch ddpkt.Proto {
|
||||||
case ddp.ProtoATP:
|
case ddp.ProtoATP:
|
||||||
atpkt, err := atp.UnmarshalPacket(ddpkt.Data)
|
atpkt, err := atp.UnmarshalPacket(ddpkt.Data)
|
||||||
|
@ -54,13 +52,13 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
|
|
||||||
switch gzl.Function {
|
switch gzl.Function {
|
||||||
case zip.FunctionGetZoneList:
|
case zip.FunctionGetZoneList:
|
||||||
resp.Zones = zones.AllNames()
|
resp.Zones = rtr.ZoneTable.AllNames()
|
||||||
|
|
||||||
case zip.FunctionGetLocalZones:
|
case zip.FunctionGetLocalZones:
|
||||||
resp.Zones = zones.LocalNames()
|
resp.Zones = rtr.ZoneTable.LocalNames()
|
||||||
|
|
||||||
case zip.FunctionGetMyZone:
|
case zip.FunctionGetMyZone:
|
||||||
resp.Zones = []string{cfg.EtherTalk.ZoneName}
|
resp.Zones = []string{rtr.Config.EtherTalk.ZoneName}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inside AppleTalk SE, pp 8-8
|
// Inside AppleTalk SE, pp 8-8
|
||||||
|
@ -101,14 +99,14 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
DstNet: ddpkt.SrcNet,
|
DstNet: ddpkt.SrcNet,
|
||||||
DstNode: ddpkt.SrcNode,
|
DstNode: ddpkt.SrcNode,
|
||||||
DstSocket: ddpkt.SrcSocket,
|
DstSocket: ddpkt.SrcSocket,
|
||||||
SrcNet: myAddr.Proto.Network,
|
SrcNet: rtr.MyDDPAddr.Network,
|
||||||
SrcNode: myAddr.Proto.Node,
|
SrcNode: rtr.MyDDPAddr.Node,
|
||||||
SrcSocket: 6,
|
SrcSocket: 6,
|
||||||
Proto: ddp.ProtoATP,
|
Proto: ddp.ProtoATP,
|
||||||
},
|
},
|
||||||
Data: ddpBody,
|
Data: ddpBody,
|
||||||
}
|
}
|
||||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, respDDP)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, respDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -117,7 +115,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return pcapHandle.WritePacketData(outFrameRaw)
|
return rtr.PcapHandle.WritePacketData(outFrameRaw)
|
||||||
|
|
||||||
case *atp.TResp:
|
case *atp.TResp:
|
||||||
return fmt.Errorf("TODO: support handling ZIP ATP replies?")
|
return fmt.Errorf("TODO: support handling ZIP ATP replies?")
|
||||||
|
@ -135,7 +133,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
switch zipkt := zipkt.(type) {
|
switch zipkt := zipkt.(type) {
|
||||||
case *zip.QueryPacket:
|
case *zip.QueryPacket:
|
||||||
log.Printf("ZIP: Got Query for networks %v", zipkt.Networks)
|
log.Printf("ZIP: Got Query for networks %v", zipkt.Networks)
|
||||||
networks := zones.Query(zipkt.Networks)
|
networks := rtr.ZoneTable.Query(zipkt.Networks)
|
||||||
|
|
||||||
sendReply := func(resp *zip.ReplyPacket) error {
|
sendReply := func(resp *zip.ReplyPacket) error {
|
||||||
respRaw, err := resp.Marshal()
|
respRaw, err := resp.Marshal()
|
||||||
|
@ -149,15 +147,15 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
DstNet: ddpkt.SrcNet,
|
DstNet: ddpkt.SrcNet,
|
||||||
DstNode: ddpkt.SrcNode,
|
DstNode: ddpkt.SrcNode,
|
||||||
DstSocket: ddpkt.SrcSocket,
|
DstSocket: ddpkt.SrcSocket,
|
||||||
SrcNet: myAddr.Proto.Network,
|
SrcNet: rtr.MyDDPAddr.Network,
|
||||||
SrcNode: myAddr.Proto.Node,
|
SrcNode: rtr.MyDDPAddr.Node,
|
||||||
SrcSocket: 6,
|
SrcSocket: 6,
|
||||||
Proto: ddp.ProtoZIP,
|
Proto: ddp.ProtoZIP,
|
||||||
},
|
},
|
||||||
Data: respRaw,
|
Data: respRaw,
|
||||||
}
|
}
|
||||||
|
|
||||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
|
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -167,7 +165,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
|
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
|
||||||
}
|
}
|
||||||
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
|
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
|
||||||
return fmt.Errorf("couldn't write packet data: %w", err)
|
return fmt.Errorf("couldn't write packet data: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -246,14 +244,14 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
|
|
||||||
// Only running a network with one zone for now.
|
// Only running a network with one zone for now.
|
||||||
resp := &zip.GetNetInfoReplyPacket{
|
resp := &zip.GetNetInfoReplyPacket{
|
||||||
ZoneInvalid: zipkt.ZoneName != cfg.EtherTalk.ZoneName,
|
ZoneInvalid: zipkt.ZoneName != rtr.Config.EtherTalk.ZoneName,
|
||||||
UseBroadcast: false,
|
UseBroadcast: false,
|
||||||
OnlyOneZone: true,
|
OnlyOneZone: true,
|
||||||
NetStart: cfg.EtherTalk.NetStart,
|
NetStart: rtr.Config.EtherTalk.NetStart,
|
||||||
NetEnd: cfg.EtherTalk.NetEnd,
|
NetEnd: rtr.Config.EtherTalk.NetEnd,
|
||||||
ZoneName: zipkt.ZoneName, // has to match request
|
ZoneName: zipkt.ZoneName, // has to match request
|
||||||
MulticastAddr: atalk.MulticastAddr(cfg.EtherTalk.ZoneName),
|
MulticastAddr: atalk.MulticastAddr(rtr.Config.EtherTalk.ZoneName),
|
||||||
DefaultZoneName: cfg.EtherTalk.ZoneName,
|
DefaultZoneName: rtr.Config.EtherTalk.ZoneName,
|
||||||
}
|
}
|
||||||
log.Printf("ZIP: Replying with GetNetInfo-Reply: %+v", resp)
|
log.Printf("ZIP: Replying with GetNetInfo-Reply: %+v", resp)
|
||||||
|
|
||||||
|
@ -277,8 +275,8 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
DstNet: ddpkt.SrcNet,
|
DstNet: ddpkt.SrcNet,
|
||||||
DstNode: ddpkt.SrcNode,
|
DstNode: ddpkt.SrcNode,
|
||||||
DstSocket: ddpkt.SrcSocket,
|
DstSocket: ddpkt.SrcSocket,
|
||||||
SrcNet: myAddr.Proto.Network,
|
SrcNet: rtr.MyDDPAddr.Network,
|
||||||
SrcNode: myAddr.Proto.Node,
|
SrcNode: rtr.MyDDPAddr.Node,
|
||||||
SrcSocket: 6,
|
SrcSocket: 6,
|
||||||
Proto: ddp.ProtoZIP,
|
Proto: ddp.ProtoZIP,
|
||||||
},
|
},
|
||||||
|
@ -291,7 +289,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
outDDP.DstNode = 0xFF
|
outDDP.DstNode = 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
|
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
|
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -303,7 +301,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
|
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
|
||||||
}
|
}
|
||||||
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
|
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
|
||||||
return fmt.Errorf("couldn't write packet data: %w", err)
|
return fmt.Errorf("couldn't write packet data: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
Loading…
Reference in a new issue