/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2023 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
xdr "github.com/davecgh/go-xdr/xdr2"
"github.com/klauspost/compress/zstd"
- "go.cypherpunks.ru/nncp/v5"
+ "go.cypherpunks.ru/nncp/v8"
)
func usage() {
- fmt.Fprintf(os.Stderr, nncp.UsageHeader())
- fmt.Fprintf(os.Stderr, "nncp-pkt -- parse raw packet\n\n")
+ fmt.Fprint(os.Stderr, nncp.UsageHeader())
+ fmt.Fprint(os.Stderr, "nncp-pkt -- parse raw packet\n\n")
fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "Packet is read from stdin.")
}
+func doPlain(ctx *nncp.Ctx, pkt nncp.Pkt, dump, decompress bool) {
+ if dump {
+ bufW := bufio.NewWriter(os.Stdout)
+ var r io.Reader
+ r = bufio.NewReader(os.Stdin)
+ if decompress {
+ decompressor, err := zstd.NewReader(r)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ r = decompressor
+ }
+ if _, err := io.Copy(bufW, r); err != nil {
+ log.Fatalln(err)
+ }
+ if err := bufW.Flush(); err != nil {
+ log.Fatalln(err)
+ }
+ return
+ }
+ payloadType := "unknown"
+ switch pkt.Type {
+ case nncp.PktTypeFile:
+ payloadType = "file"
+ case nncp.PktTypeFreq:
+ payloadType = "file request"
+ case nncp.PktTypeExec:
+ payloadType = "exec compressed"
+ case nncp.PktTypeTrns:
+ payloadType = "transitional"
+ case nncp.PktTypeExecFat:
+ payloadType = "exec uncompressed"
+ case nncp.PktTypeArea:
+ payloadType = "area"
+ case nncp.PktTypeACK:
+ payloadType = "acknowledgement"
+ }
+ var path string
+ switch pkt.Type {
+ case nncp.PktTypeExec, nncp.PktTypeExecFat:
+ path = string(bytes.Replace(
+ pkt.Path[:pkt.PathLen], []byte{0}, []byte(" "), -1,
+ ))
+ case nncp.PktTypeTrns:
+ path = nncp.Base32Codec.EncodeToString(pkt.Path[:pkt.PathLen])
+ node, err := ctx.FindNode(path)
+ if err == nil {
+ path = fmt.Sprintf("%s (%s)", path, node.Name)
+ }
+ case nncp.PktTypeArea:
+ path = nncp.Base32Codec.EncodeToString(pkt.Path[:pkt.PathLen])
+ if areaId, err := nncp.AreaIdFromString(path); err == nil {
+ path = fmt.Sprintf("%s (%s)", path, ctx.AreaName(areaId))
+ }
+ case nncp.PktTypeACK:
+ path = nncp.Base32Codec.EncodeToString(pkt.Path[:pkt.PathLen])
+ default:
+ path = string(pkt.Path[:pkt.PathLen])
+ }
+ fmt.Printf(
+ "Packet type: plain\nPayload type: %s\nNiceness: %s (%d)\nPath: %s\n",
+ payloadType, nncp.NicenessFmt(pkt.Nice), pkt.Nice, path,
+ )
+}
+
+func doEncrypted(
+ ctx *nncp.Ctx,
+ pktEnc nncp.PktEnc,
+ dump bool,
+ beginning []byte,
+) {
+ senderName := "unknown"
+ senderNode := ctx.Neigh[*pktEnc.Sender]
+ if senderNode != nil {
+ senderName = senderNode.Name
+ }
+
+ recipientName := "unknown"
+ var area *nncp.Area
+ recipientNode := ctx.Neigh[*pktEnc.Recipient]
+ if recipientNode == nil {
+ area = ctx.AreaId2Area[nncp.AreaId(*pktEnc.Recipient)]
+ if area != nil {
+ recipientName = "area " + area.Name
+ }
+ } else {
+ recipientName = recipientNode.Name
+ }
+
+ if !dump {
+ fmt.Printf(`Packet type: encrypted
+Niceness: %s (%d)
+Sender: %s (%s)
+Recipient: %s (%s)
+`,
+ nncp.NicenessFmt(pktEnc.Nice), pktEnc.Nice,
+ pktEnc.Sender, senderName,
+ pktEnc.Recipient, recipientName,
+ )
+ return
+ }
+ if ctx.Self == nil {
+ log.Fatalln("Config lacks private keys")
+ }
+ bufW := bufio.NewWriter(os.Stdout)
+ var err error
+ if area == nil {
+ _, _, _, err = nncp.PktEncRead(
+ ctx.Self, ctx.Neigh,
+ io.MultiReader(bytes.NewReader(beginning), bufio.NewReader(os.Stdin)),
+ bufW, senderNode != nil, nil,
+ )
+ } else {
+ areaNode := nncp.NodeOur{Id: new(nncp.NodeId), ExchPrv: new([32]byte)}
+ copy(areaNode.Id[:], area.Id[:])
+ copy(areaNode.ExchPrv[:], area.Prv[:])
+ _, _, _, err = nncp.PktEncRead(
+ &areaNode, ctx.Neigh,
+ io.MultiReader(bytes.NewReader(beginning), bufio.NewReader(os.Stdin)),
+ bufW, senderNode != nil, nil,
+ )
+ }
+ if err != nil {
+ log.Fatalln(err)
+ }
+ if err = bufW.Flush(); err != nil {
+ log.Fatalln(err)
+ }
+}
+
func main() {
var (
overheads = flag.Bool("overheads", false, "Print packet overheads")
version = flag.Bool("version", false, "Print version information")
warranty = flag.Bool("warranty", false, "Print warranty information")
)
+ log.SetFlags(log.Lshortfile)
flag.Usage = usage
flag.Parse()
if *warranty {
return
}
+ ctx, err := nncp.CtxFromCmdline(*cfgPath, "", "", false, false, false, false)
+ if err != nil {
+ log.Fatalln("Error during initialization:", err)
+ }
+
if *overheads {
fmt.Printf(
"Plain: %d\nEncrypted: %d\nSize: %d\n",
return
}
- var err error
beginning := make([]byte, nncp.PktOverhead)
- if _, err = io.ReadFull(os.Stdin, beginning); err != nil {
+ if _, err := io.ReadFull(os.Stdin, beginning[:nncp.PktEncOverhead]); err != nil {
log.Fatalln("Not enough data to read")
}
- var pkt nncp.Pkt
- _, err = xdr.Unmarshal(bytes.NewReader(beginning), &pkt)
- if err == nil && pkt.Magic == nncp.MagicNNCPPv3 {
- if *dump {
- bufW := bufio.NewWriter(os.Stdout)
- var r io.Reader
- r = bufio.NewReader(os.Stdin)
- if *decompress {
- decompressor, err := zstd.NewReader(r)
- if err != nil {
- log.Fatalln(err)
- }
- r = decompressor
- }
- if _, err = io.Copy(bufW, r); err != nil {
- log.Fatalln(err)
- }
- if err = bufW.Flush(); err != nil {
- log.Fatalln(err)
- }
+ var pktEnc nncp.PktEnc
+ if _, err := xdr.Unmarshal(bytes.NewReader(beginning), &pktEnc); err == nil {
+ switch pktEnc.Magic {
+ case nncp.MagicNNCPEv1.B:
+ log.Fatalln(nncp.MagicNNCPEv1.TooOld())
+ case nncp.MagicNNCPEv2.B:
+ log.Fatalln(nncp.MagicNNCPEv2.TooOld())
+ case nncp.MagicNNCPEv3.B:
+ log.Fatalln(nncp.MagicNNCPEv3.TooOld())
+ case nncp.MagicNNCPEv4.B:
+ log.Fatalln(nncp.MagicNNCPEv4.TooOld())
+ case nncp.MagicNNCPEv5.B:
+ log.Fatalln(nncp.MagicNNCPEv5.TooOld())
+ case nncp.MagicNNCPEv6.B:
+ doEncrypted(ctx, pktEnc, *dump, beginning[:nncp.PktEncOverhead])
return
}
- payloadType := "unknown"
- switch pkt.Type {
- case nncp.PktTypeFile:
- payloadType = "file"
- case nncp.PktTypeFreq:
- payloadType = "file request"
- case nncp.PktTypeExec:
- payloadType = "exec"
- case nncp.PktTypeTrns:
- payloadType = "transitional"
- }
- var path string
- switch pkt.Type {
- case nncp.PktTypeExec:
- path = string(bytes.Replace(
- pkt.Path[:pkt.PathLen],
- []byte{0},
- []byte(" "),
- -1,
- ))
- case nncp.PktTypeTrns:
- path = nncp.Base32Codec.EncodeToString(pkt.Path[:pkt.PathLen])
- default:
- path = string(pkt.Path[:pkt.PathLen])
- }
- fmt.Printf(
- "Packet type: plain\nPayload type: %s\nNiceness: %s (%d)\nPath: %s\n",
- payloadType, nncp.NicenessFmt(pkt.Nice), pkt.Nice, path,
- )
- return
}
- var pktEnc nncp.PktEnc
- _, err = xdr.Unmarshal(bytes.NewReader(beginning), &pktEnc)
- if err == nil && pktEnc.Magic == nncp.MagicNNCPEv4 {
- if *dump {
- ctx, err := nncp.CtxFromCmdline(*cfgPath, "", "", false, false, false, false)
- if err != nil {
- log.Fatalln("Error during initialization:", err)
- }
- if ctx.Self == nil {
- log.Fatalln("Config lacks private keys")
- }
- bufW := bufio.NewWriter(os.Stdout)
- if _, _, err = nncp.PktEncRead(
- ctx.Self,
- ctx.Neigh,
- io.MultiReader(
- bytes.NewReader(beginning),
- bufio.NewReader(os.Stdin),
- ),
- bufW,
- ); err != nil {
- log.Fatalln(err)
- }
- if err = bufW.Flush(); err != nil {
- log.Fatalln(err)
- }
+
+ if _, err := io.ReadFull(os.Stdin, beginning[nncp.PktEncOverhead:]); err != nil {
+ log.Fatalln("Not enough data to read")
+ }
+ var pkt nncp.Pkt
+ if _, err := xdr.Unmarshal(bytes.NewReader(beginning), &pkt); err == nil {
+ switch pkt.Magic {
+ case nncp.MagicNNCPPv1.B:
+ log.Fatalln(nncp.MagicNNCPPv1.TooOld())
+ case nncp.MagicNNCPPv2.B:
+ log.Fatalln(nncp.MagicNNCPPv2.TooOld())
+ case nncp.MagicNNCPPv3.B:
+ doPlain(ctx, pkt, *dump, *decompress)
return
}
- fmt.Printf(
- "Packet type: encrypted\nNiceness: %s (%d)\nSender: %s\nRecipient: %s\n",
- nncp.NicenessFmt(pktEnc.Nice), pktEnc.Nice, pktEnc.Sender, pktEnc.Recipient,
- )
- return
}
log.Fatalln("Unable to determine packet type")
}