This commit is contained in:
Josh Deprez 2024-04-14 21:36:35 +10:00
parent 2afb879573
commit 0c86aa6194
Signed by: josh
SSH key fingerprint: SHA256:zZji7w1Ilh2RuUpbQcqkLPrqmRwpiCSycbF2EfKm6Kw
2 changed files with 68 additions and 33 deletions

83
zip.go
View file

@ -100,10 +100,23 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
if err != nil { if err != nil {
return err return err
} }
var resp interface {
Marshal() ([]byte, error)
}
switch zipkt := zipkt.(type) { switch zipkt := zipkt.(type) {
case *zip.QueryPacket:
// TODO: multiple packets
resp = &zip.ReplyPacket{
Extended: false,
Networks: zones.Query(zipkt.Networks),
}
// TODO: direct to queryer
case *zip.GetNetInfoPacket: case *zip.GetNetInfoPacket:
// 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 != cfg.EtherTalk.ZoneName,
UseBroadcast: true, // TODO: add multicast addr computation UseBroadcast: true, // TODO: add multicast addr computation
OnlyOneZone: true, OnlyOneZone: true,
@ -113,43 +126,47 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
MulticastAddr: ethertalk.AppleTalkBroadcast, MulticastAddr: ethertalk.AppleTalkBroadcast,
DefaultZoneName: cfg.EtherTalk.ZoneName, DefaultZoneName: cfg.EtherTalk.ZoneName,
} }
respRaw, err := resp.Marshal()
if err != nil {
return fmt.Errorf("couldn't marshal GetNetInfoReplyPacket: %w", err)
}
// TODO: fix
// "In cases where a node's provisional address is
// invalid, routers will not be able to respond to
// the node in a directed manner. An address is
// invalid if the network number is neither in the
// startup range nor in the network number range
// assigned to the node's network. In these cases,
// if the request was sent via a broadcast, the
// routers should respond with a broadcast."
ddpkt.DstNet, ddpkt.DstNode, ddpkt.DstSocket = 0x0000, 0xFF, ddpkt.SrcSocket
ddpkt.SrcNet = myAddr.Proto.Network
ddpkt.SrcNode = myAddr.Proto.Node
ddpkt.SrcSocket = 6
ddpkt.Data = respRaw
outFrame, err := ethertalk.AppleTalk(myHWAddr, *ddpkt)
if err != nil {
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
}
outFrame.Dst = srcHWAddr
outFrameRaw, err := ethertalk.Marshal(*outFrame)
if err != nil {
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
}
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
return fmt.Errorf("couldn't write packet data: %w", err)
}
return nil
default: default:
return fmt.Errorf("TODO: handle type %T", zipkt) return fmt.Errorf("TODO: handle type %T", zipkt)
} }
if resp == nil {
return nil
}
respRaw, err := resp.Marshal()
if err != nil {
return fmt.Errorf("couldn't marshal %T: %w", resp, err)
}
// TODO: fix
// "In cases where a node's provisional address is
// invalid, routers will not be able to respond to
// the node in a directed manner. An address is
// invalid if the network number is neither in the
// startup range nor in the network number range
// assigned to the node's network. In these cases,
// if the request was sent via a broadcast, the
// routers should respond with a broadcast."
ddpkt.DstNet, ddpkt.DstNode, ddpkt.DstSocket = 0x0000, 0xFF, ddpkt.SrcSocket
ddpkt.SrcNet = myAddr.Proto.Network
ddpkt.SrcNode = myAddr.Proto.Node
ddpkt.SrcSocket = 6
ddpkt.Data = respRaw
outFrame, err := ethertalk.AppleTalk(myHWAddr, *ddpkt)
if err != nil {
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
}
outFrame.Dst = srcHWAddr
outFrameRaw, err := ethertalk.Marshal(*outFrame)
if err != nil {
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
}
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
return fmt.Errorf("couldn't write packet data: %w", err)
}
return nil
default: default:
return fmt.Errorf("invalid DDP type %d on socket 6", ddpkt.Proto) return fmt.Errorf("invalid DDP type %d on socket 6", ddpkt.Proto)
} }

View file

@ -17,6 +17,7 @@
package main package main
import ( import (
"slices"
"sort" "sort"
"sync" "sync"
"time" "time"
@ -67,6 +68,23 @@ func (zt *ZoneTable) Upsert(network ddp.Network, name string, local bool) {
} }
} }
func (zt *ZoneTable) Query(ns []ddp.Network) map[ddp.Network][]string {
slices.Sort(ns)
zs := make(map[ddp.Network][]string)
zt.mu.Lock()
defer zt.mu.Unlock()
for _, z := range zt.zones {
if time.Since(z.LastSeen) > maxZoneAge {
continue
}
if _, ok := slices.BinarySearch(ns, z.Network); ok {
zs[z.Network] = append(zs[z.Network], z.Name)
}
}
return zs
}
func (zt *ZoneTable) LocalNames() []string { func (zt *ZoneTable) LocalNames() []string {
zt.mu.Lock() zt.mu.Lock()
seen := make(map[string]struct{}) seen := make(map[string]struct{})