From 25d838ae91fcd694c50e31d7050d31ec9d62deec Mon Sep 17 00:00:00 2001 From: pouriyajamshidi Date: Fri, 8 Nov 2024 16:40:56 +0100 Subject: [PATCH] implement IP and port filtering --- internal/probe/probe.go | 16 +++++++++++++--- internal/probe/probe_bpfeb.o | Bin 7696 -> 7376 bytes internal/probe/probe_bpfel.o | Bin 7704 -> 7384 bytes 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/probe/probe.go b/internal/probe/probe.go index ce82d37..9eab5df 100755 --- a/internal/probe/probe.go +++ b/internal/probe/probe.go @@ -8,6 +8,7 @@ import ( "github.com/pouriyajamshidi/flat/clsact" "github.com/pouriyajamshidi/flat/internal/flowtable" "github.com/pouriyajamshidi/flat/internal/packet" + "github.com/pouriyajamshidi/flat/internal/types" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" ) @@ -180,7 +181,7 @@ func (p *probe) Close() error { // Run attaches the probe, reads from the eBPF map // as well as calculating and displaying the flow latencies -func Run(ctx context.Context, iface netlink.Link) error { +func Run(ctx context.Context, userInput types.UserInput) error { log.Println("Starting up the probe") if err := setRlimit(); err != nil { @@ -196,7 +197,7 @@ func Run(ctx context.Context, iface netlink.Link) error { } }() - probe, err := newProbe(iface) + probe, err := newProbe(userInput.Interface) if err != nil { return err @@ -235,7 +236,16 @@ func Run(ctx context.Context, iface netlink.Link) error { log.Printf("Could not unmarshall packet: %+v", pkt) continue } - packet.CalcLatency(packetAttrs, flowtable) + if !userInput.IP.IsValid() && userInput.Port == 0 { + packet.CalcLatency(packetAttrs, flowtable) + // FIXME: + // } else if (userInput.Port == packetAttrs.DstPort || userInput.Port == packetAttrs.SrcPort) && (userInput.IP == packetAttrs.DstIP.Unmap() || userInput.IP == packetAttrs.SrcIP.Unmap()) { + // packet.CalcLatency(packetAttrs, flowtable) + } else if userInput.IP == packetAttrs.DstIP.Unmap() || userInput.IP == packetAttrs.SrcIP.Unmap() { + packet.CalcLatency(packetAttrs, flowtable) + } else if userInput.Port == packetAttrs.DstPort || userInput.Port == packetAttrs.SrcPort { + packet.CalcLatency(packetAttrs, flowtable) + } } } } diff --git a/internal/probe/probe_bpfeb.o b/internal/probe/probe_bpfeb.o index f6d34e4a380b47b362450022e084fff6154fc77f..03f8ccc687cc4684d2b50691bdf19f44884958c6 100644 GIT binary patch literal 7376 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 diff --git a/internal/probe/probe_bpfel.o b/internal/probe/probe_bpfel.o index 909e6c6d19b5eaeb8558f3dc1d3a9097f8bda846..b1915a00707a866d5e2bf6accf505fb76d36ebf0 100644 GIT binary patch literal 7384 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 JrsGTZ>c12~1=;`r literal 7704 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 I&Di$;0hrf9CjbBd