Fix ZIP ATP replies
This commit is contained in:
parent
e95df3db20
commit
c1efd9f91b
5 changed files with 56 additions and 7 deletions
|
@ -22,8 +22,9 @@ Things I plan to fix Real Soon Now:
|
||||||
interface. I haven't tested it with netatalk or tashrouter on the same
|
interface. I haven't tested it with netatalk or tashrouter on the same
|
||||||
host, but I think using a distinct Ethernet address would help them coexist.
|
host, but I think using a distinct Ethernet address would help them coexist.
|
||||||
* It doesn't do any of the required packet splitting to keep packets under the
|
* It doesn't do any of the required packet splitting to keep packets under the
|
||||||
AppleTalk size limits. In particular ZIP GetZoneList Replies are incorrect
|
AppleTalk size limits. ~~In particular ZIP GetZoneList Replies are incorrect
|
||||||
when the zone list would exceed the limit.
|
when the zone list would exceed the limit.~~ GetZoneList is now fixed, but
|
||||||
|
various others need fixing.
|
||||||
* It logs a lot and has no other monitoring or observability capability. I plan
|
* It logs a lot and has no other monitoring or observability capability. I plan
|
||||||
to add a Prometheus metrics endpoint and at least add log levels / verbosity
|
to add a Prometheus metrics endpoint and at least add log levels / verbosity
|
||||||
flag.
|
flag.
|
||||||
|
|
|
@ -20,6 +20,13 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HeaderSize = 8
|
||||||
|
MaxDataSize = atalk.DDPMaxDataSize - HeaderSize // 578
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -50,6 +57,9 @@ func (p *TReq) Marshal() ([]byte, error) {
|
||||||
if p.TRelTimeoutIndicator > 4 {
|
if p.TRelTimeoutIndicator > 4 {
|
||||||
return nil, fmt.Errorf("invalid TRel timeout indicator [%d > 4]", p.TRelTimeoutIndicator)
|
return nil, fmt.Errorf("invalid TRel timeout indicator [%d > 4]", p.TRelTimeoutIndicator)
|
||||||
}
|
}
|
||||||
|
if len(p.Data) > MaxDataSize {
|
||||||
|
return nil, fmt.Errorf("%w [%d > %d]", atalk.ErrDataTooBig, len(p.Data), MaxDataSize)
|
||||||
|
}
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
b := bytes.NewBuffer(nil)
|
||||||
ci := byte(ciFuncTReq)
|
ci := byte(ciFuncTReq)
|
||||||
|
|
|
@ -16,4 +16,11 @@
|
||||||
|
|
||||||
package atalk
|
package atalk
|
||||||
|
|
||||||
const DDPExtHeaderSize = 13
|
import "errors"
|
||||||
|
|
||||||
|
const (
|
||||||
|
DDPExtHeaderSize = 13
|
||||||
|
DDPMaxDataSize = 586
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrDataTooBig = errors.New("data too big")
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.drjosh.dev/josh/jrouter/atalk"
|
||||||
"gitea.drjosh.dev/josh/jrouter/atalk/atp"
|
"gitea.drjosh.dev/josh/jrouter/atalk/atp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,6 +79,9 @@ func (p *GetZonesReplyPacket) MarshalTResp() (*atp.TResp, error) {
|
||||||
b.WriteString(z)
|
b.WriteString(z)
|
||||||
}
|
}
|
||||||
r.Data = b.Bytes()
|
r.Data = b.Bytes()
|
||||||
|
if len(r.Data) > atp.MaxDataSize {
|
||||||
|
return nil, fmt.Errorf("%w [%d > %d]", atalk.ErrDataTooBig, len(r.Data), atp.MaxDataSize)
|
||||||
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
zip.go
35
zip.go
|
@ -32,7 +32,7 @@ import (
|
||||||
|
|
||||||
func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAddr aarp.AddrPair, cfg *config, zones *ZoneTable, ddpkt *ddp.ExtPacket) error {
|
func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAddr aarp.AddrPair, cfg *config, zones *ZoneTable, ddpkt *ddp.ExtPacket) error {
|
||||||
switch ddpkt.Proto {
|
switch ddpkt.Proto {
|
||||||
case 3: // ATP
|
case ddp.ProtoATP:
|
||||||
atpkt, err := atp.UnmarshalPacket(ddpkt.Data)
|
atpkt, err := atp.UnmarshalPacket(ddpkt.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -43,11 +43,15 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO: handle this in a more transactiony way
|
if gzl.StartIndex == 0 {
|
||||||
|
return fmt.Errorf("ZIP ATP: received request with StartIndex = 0 (invalid)")
|
||||||
|
}
|
||||||
|
|
||||||
resp := &zip.GetZonesReplyPacket{
|
resp := &zip.GetZonesReplyPacket{
|
||||||
TID: gzl.TID,
|
TID: gzl.TID,
|
||||||
LastFlag: true, // TODO: support multiple response packets
|
LastFlag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch gzl.Function {
|
switch gzl.Function {
|
||||||
case zip.FunctionGetZoneList:
|
case zip.FunctionGetZoneList:
|
||||||
resp.Zones = zones.AllNames()
|
resp.Zones = zones.AllNames()
|
||||||
|
@ -59,6 +63,29 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
resp.Zones = []string{cfg.EtherTalk.ZoneName}
|
resp.Zones = []string{cfg.EtherTalk.ZoneName}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inside AppleTalk SE, pp 8-8
|
||||||
|
if int(gzl.StartIndex) > len(resp.Zones) {
|
||||||
|
// "Note: A 0-byte response will be returned by a router if the
|
||||||
|
// index specified in the request is greater than the index of
|
||||||
|
// the last zone in the list (and the user bytes field will
|
||||||
|
// indicate no more zones)."
|
||||||
|
resp.Zones = nil
|
||||||
|
} else {
|
||||||
|
// Trim the zones list
|
||||||
|
// "zone names in the router are assumed to be numbered starting
|
||||||
|
// with 1"
|
||||||
|
resp.Zones = resp.Zones[gzl.StartIndex-1:]
|
||||||
|
size := 0
|
||||||
|
for i, z := range resp.Zones {
|
||||||
|
size += 1 + len(z) // length prefix plus string
|
||||||
|
if size > atp.MaxDataSize {
|
||||||
|
resp.LastFlag = false
|
||||||
|
resp.Zones = resp.Zones[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
respATP, err := resp.MarshalTResp()
|
respATP, err := resp.MarshalTResp()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -99,7 +126,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
|
||||||
return fmt.Errorf("unsupported ATP packet type %T for ZIP", atpkt)
|
return fmt.Errorf("unsupported ATP packet type %T for ZIP", atpkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 6: // ZIP
|
case ddp.ProtoZIP:
|
||||||
zipkt, err := zip.UnmarshalPacket(ddpkt.Data)
|
zipkt, err := zip.UnmarshalPacket(ddpkt.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in a new issue