mirror of
https://github.com/soypat/lneto.git
synced 2026-08-07 16:33:40 +00:00
119 lines
2.9 KiB
Go
119 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"net/netip"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/soypat/lneto"
|
|
"github.com/soypat/lneto/internal"
|
|
"github.com/soypat/lneto/internal/ltesto"
|
|
"github.com/soypat/lneto/internet/pcap"
|
|
"github.com/soypat/lneto/tcp"
|
|
)
|
|
|
|
func main() {
|
|
err := run()
|
|
if err != nil {
|
|
log.Fatalln("failed:", err)
|
|
}
|
|
fmt.Println("finished")
|
|
|
|
}
|
|
|
|
func run() error {
|
|
var (
|
|
flagInterface = "tap0"
|
|
)
|
|
flag.StringVar(&flagInterface, "i", flagInterface, "Interface to select. tap* creates a tap interface. Any other name will create a bridge to the name of the interface i.e: 'enp7s0', 'wlp8s0', 'lo'")
|
|
var (
|
|
flagNet = "192.168.10.1/24"
|
|
flagiface = "tap0"
|
|
flagPacketQueueSize = 2048
|
|
)
|
|
var iface ltesto.Interface
|
|
if strings.HasPrefix(flagInterface, "tap") {
|
|
pfx, err := netip.ParsePrefix(flagNet)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tap, err := internal.NewTap(flagiface, pfx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
iface = tap
|
|
} else {
|
|
br, err := internal.NewBridge(flagInterface)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
iface = br
|
|
}
|
|
|
|
sv, err := ltesto.NewHTTPTapServer(iface, flagPacketQueueSize, flagPacketQueueSize)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer sv.Close()
|
|
var cap pcap.PacketBreakdown
|
|
sv.OnTransfer(func(channel int, pkt []byte) {
|
|
captime := time.Now()
|
|
frames, err := cap.CaptureEthernet(nil, pkt, 0)
|
|
if err == nil {
|
|
flags, src, dst := getTCPData(frames, pkt)
|
|
if src != 0 {
|
|
if flags != 0 {
|
|
fmt.Println(channel, captime.Format("15:04:05.000"), frames, flags.String(), src, "->", dst)
|
|
} else {
|
|
fmt.Println(channel, captime.Format("15:04:05.000"), frames, src, "->", dst)
|
|
}
|
|
} else {
|
|
fmt.Println(channel, captime.Format("15:04:05.000"), frames)
|
|
}
|
|
} else {
|
|
fmt.Println(channel, captime.Format("15:04:05.000"), "ERR", frames, err.Error())
|
|
}
|
|
})
|
|
hwaddr, err := sv.HardwareAddress6()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("listening on http://127.0.0.1:7070/recv and http://127.0.0.1:7070/send on hwaddr:", net.HardwareAddr(hwaddr[:]).String())
|
|
http.ListenAndServe(":7070", sv)
|
|
return errors.New("finished")
|
|
}
|
|
|
|
func getTCPData(frames []pcap.Frame, pkt []byte) (flags tcp.Flags, src, dst uint16) {
|
|
for i := range frames {
|
|
proto := frames[i].Protocol
|
|
if proto == lneto.IPProtoTCP {
|
|
return tcp.Flags(getFrameClassUint(frames[i], pkt, pcap.FieldClassFlags)),
|
|
uint16(getFrameClassUint(frames[i], pkt, pcap.FieldClassSrc)),
|
|
uint16(getFrameClassUint(frames[i], pkt, pcap.FieldClassDst))
|
|
} else if proto == lneto.IPProtoUDP {
|
|
return 0,
|
|
uint16(getFrameClassUint(frames[i], pkt, pcap.FieldClassSrc)),
|
|
uint16(getFrameClassUint(frames[i], pkt, pcap.FieldClassDst))
|
|
}
|
|
}
|
|
return 0, 0, 0
|
|
}
|
|
|
|
func getFrameClassUint(frame pcap.Frame, pkt []byte, class pcap.FieldClass) uint64 {
|
|
iflags, err := frame.FieldByClass(class)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
v, err := frame.FieldAsUint(iflags, pkt)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return v
|
|
}
|