mirror of
https://github.com/soypat/lneto.git
synced 2026-09-10 08:39:30 +00:00
add stringer methods
This commit is contained in:
@@ -27,4 +27,11 @@ go mod download github.com/soypat/lneto@latest
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Developing (linux)
|
||||||
|
|
||||||
|
- [`tap`](./examples/tap) (linux only, root privilidges required) Program opens a TAP interface and assigns an IP address to it and exposes the interface via a HTTP interface. This program is run with root privilidges to facilitate debugging of lneto since no root privilidges are required to interact with the HTTP interface exposed.
|
||||||
|
- `POST http://127.0.0.1:7070/send`: Receives a POST with request body containing JSON string of data to send over TAP interface. Response contains only status code.
|
||||||
|
- `GET http://127.0.0.1:7070/recv`: Receives a GET request. Response contains a JSON string of oldest unread TAP interface packet. If string is empty then there is no more data to read.
|
||||||
|
|
||||||
|
- [`stack`](./examples/stack) Contains stack implementation which can interact with `tap` program. No root privilidges required.
|
||||||
|
- Can expose a HTTP server.
|
||||||
@@ -394,6 +394,7 @@ func (ts *TCPStack) Recv(ipFrame []byte, tcpOff int) error {
|
|||||||
case 4:
|
case 4:
|
||||||
ifrm, _ := ipv4.NewFrame(ipFrame)
|
ifrm, _ := ipv4.NewFrame(ipFrame)
|
||||||
ifrm.CRCWriteTCPPseudo(&ts.crc)
|
ifrm.CRCWriteTCPPseudo(&ts.crc)
|
||||||
|
ts.log.Info("tcpStack:recv", slog.String("ipfrm", ifrm.String()), slog.String("frame", tfrm.String()))
|
||||||
case 6:
|
case 6:
|
||||||
i6frm, _ := ipv6.NewFrame(ipFrame)
|
i6frm, _ := ipv6.NewFrame(ipFrame)
|
||||||
i6frm.CRCWritePseudo(&ts.crc)
|
i6frm.CRCWritePseudo(&ts.crc)
|
||||||
@@ -435,6 +436,7 @@ func (ts *TCPStack) Handle(ipFrame []byte, tcpOff int) (n int, err error) {
|
|||||||
}
|
}
|
||||||
// TCP packet written.
|
// TCP packet written.
|
||||||
tfrm, _ := tcp.NewFrame(ipFrame[tcpOff : tcpOff+n])
|
tfrm, _ := tcp.NewFrame(ipFrame[tcpOff : tcpOff+n])
|
||||||
|
|
||||||
ts.validator.ResetErr()
|
ts.validator.ResetErr()
|
||||||
tfrm.ValidateSize(&ts.validator) // Perform basic validation.
|
tfrm.ValidateSize(&ts.validator) // Perform basic validation.
|
||||||
if err = ts.validator.Err(); err != nil {
|
if err = ts.validator.Err(); err != nil {
|
||||||
@@ -445,6 +447,7 @@ func (ts *TCPStack) Handle(ipFrame []byte, tcpOff int) (n int, err error) {
|
|||||||
case 4:
|
case 4:
|
||||||
ifrm, _ := ipv4.NewFrame(ipFrame)
|
ifrm, _ := ipv4.NewFrame(ipFrame)
|
||||||
ifrm.CRCWriteTCPPseudo(&ts.crc)
|
ifrm.CRCWriteTCPPseudo(&ts.crc)
|
||||||
|
ts.log.Info("tcpStack:send", slog.String("ipfrm", ifrm.String()), slog.String("frame", tfrm.String()))
|
||||||
case 6:
|
case 6:
|
||||||
i6frm, _ := ipv6.NewFrame(ipFrame)
|
i6frm, _ := ipv6.NewFrame(ipFrame)
|
||||||
i6frm.CRCWritePseudo(&ts.crc)
|
i6frm.CRCWritePseudo(&ts.crc)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package ipv4
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/soypat/lneto/lneto2"
|
"github.com/soypat/lneto/lneto2"
|
||||||
)
|
)
|
||||||
@@ -218,3 +220,16 @@ func (ifrm Frame) ValidateExceptCRC(v *lneto2.Validator) {
|
|||||||
v.AddError(errEvil)
|
v.AddError(errEvil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ifrm Frame) String() string {
|
||||||
|
dst := netip.AddrFrom4(*ifrm.DestinationAddr())
|
||||||
|
src := netip.AddrFrom4(*ifrm.SourceAddr())
|
||||||
|
|
||||||
|
hl := ifrm.HeaderLength()
|
||||||
|
tl := int(ifrm.TotalLength())
|
||||||
|
ttl := ifrm.TTL()
|
||||||
|
id := ifrm.ID()
|
||||||
|
proto := ifrm.Protocol()
|
||||||
|
tos := ifrm.ToS()
|
||||||
|
return fmt.Sprintf("IP %s SRC=%s DST=%s LEN=%d OPT=%d TTL=%d ID=%d ToS=0x%x", proto.String(), src.String(), dst.String(), tl, tl-hl, ttl, id, tos)
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ func (seg Segment) isFirstSYN() bool {
|
|||||||
return seg.Flags == FlagSYN && seg.ACK == 0 && seg.DATALEN == 0 && seg.WND > 0
|
return seg.Flags == FlagSYN && seg.ACK == 0 && seg.DATALEN == 0 && seg.WND > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (seg Segment) String() string {
|
||||||
|
if seg.DATALEN == 0 {
|
||||||
|
return fmt.Sprintf("SEG %s ACK=%d SEQ=%d WND=%d", seg.Flags, seg.ACK, seg.SEQ, seg.WND)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("SEG %s ACK=%d SEQ=%d WND=%d DATALEN=%d", seg.Flags, seg.ACK, seg.SEQ, seg.WND, seg.DATALEN)
|
||||||
|
}
|
||||||
|
|
||||||
// ClientSynSegment is a the first packet sent over a TCP connection to a server. Typically the client
|
// ClientSynSegment is a the first packet sent over a TCP connection to a server. Typically the client
|
||||||
// will call ClientSynSegment to generate a new SYN packet to send over to the server to initiate communications:
|
// will call ClientSynSegment to generate a new SYN packet to send over to the server to initiate communications:
|
||||||
//
|
//
|
||||||
|
|||||||
+3
-1
@@ -174,8 +174,10 @@ func (frm Frame) ClearHeader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tfrm Frame) String() string {
|
func (tfrm Frame) String() string {
|
||||||
|
src := tfrm.SourcePort()
|
||||||
|
dst := tfrm.DestinationPort()
|
||||||
seg := tfrm.Segment(len(tfrm.Payload()))
|
seg := tfrm.Segment(len(tfrm.Payload()))
|
||||||
return fmt.Sprintf("%+v", seg)
|
return fmt.Sprintf("TCP :%d -> :%d %s", src, dst, seg.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
+8
-3
@@ -11,7 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errMismatchedPort = errors.New("mismatched port")
|
errMismatchedSrcPort = errors.New("source port mismatch")
|
||||||
|
errMismatchedDstPort = errors.New("destination port mismatch")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler is a low level TCP handling data structure. It implements logic
|
// Handler is a low level TCP handling data structure. It implements logic
|
||||||
@@ -120,13 +121,14 @@ func (h *Handler) Recv(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
remotePort := tfrm.SourcePort()
|
remotePort := tfrm.SourcePort()
|
||||||
if h.remotePort != 0 && remotePort != h.remotePort {
|
if h.remotePort != 0 && remotePort != h.remotePort {
|
||||||
return errMismatchedPort
|
return errMismatchedSrcPort
|
||||||
}
|
}
|
||||||
dstPort := tfrm.DestinationPort()
|
dstPort := tfrm.DestinationPort()
|
||||||
if h.localPort != dstPort {
|
if h.localPort != dstPort {
|
||||||
return errMismatchedPort
|
return errMismatchedDstPort
|
||||||
}
|
}
|
||||||
payload := tfrm.Payload()
|
payload := tfrm.Payload()
|
||||||
if len(payload) > h.bufRx.Free() {
|
if len(payload) > h.bufRx.Free() {
|
||||||
@@ -160,6 +162,9 @@ func (h *Handler) Recv(b []byte) error {
|
|||||||
h.debug("tcp.Handler:rx-remoteport-set", slog.Uint64("port", uint64(h.localPort)), slog.Uint64("remoteport", uint64(remotePort)))
|
h.debug("tcp.Handler:rx-remoteport-set", slog.Uint64("port", uint64(h.localPort)), slog.Uint64("remoteport", uint64(remotePort)))
|
||||||
h.remotePort = remotePort
|
h.remotePort = remotePort
|
||||||
}
|
}
|
||||||
|
if h.logenabled(internal.LevelTrace) {
|
||||||
|
h.trace("tcp.Handler:rx-done", slog.Uint64("port", uint64(h.localPort)), slog.Uint64("remoteport", uint64(remotePort)), slog.String("seg", segIncoming.String()))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user