code: plan9front

Download patch

ref: 373daa759c0548af932a49d1806eb6c937459e02
parent: 73c37d2db941b91006fb10b7bc76dfbbe1ad72ba
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Sep 18 08:35:47 EDT 2022

snoopy: add "ippkt" protocol to demux ip packet interfaces without media header.

When using a packet interface, such as /net/ipifc/x as the
packet-soucre, there is no media header and the ip protocol
version has to be determined from the first byte.

The ippkt protocol solves this, allowing one to decode
both ipv4 and ipv6, such as:

snoopy -h ippkt /net/ipifc/2

--- a/sys/man/8/snoopy
+++ b/sys/man/8/snoopy
@@ -174,6 +174,11 @@
 protocol.
 The default is
 .LR ether .
+For packet interfaces without a media header, use
+.B ippkt
+as the
+.I first-header
+type to decode ipv4 and ipv6 packets.
 .SH EXAMPLES
 To display only
 .SM BOOTP
@@ -209,7 +214,3 @@
 Ethernet device
 .SH SOURCE
 .B /sys/src/cmd/ip/snoopy
-.SH BUGS
-.I Snoopy
-only dumps ethernet packets, because there's
-no device to get IP packets without a media header.
--- /dev/null
+++ b/sys/src/cmd/ip/snoopy/ippkt.c
@@ -1,0 +1,82 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+static Mux p_mux[] =
+{
+	{"ip",		0x40, },
+	{"ip6", 	0x60, },
+	{0}
+};
+
+enum
+{
+	Ot,	/* ip type */
+};
+
+static Field p_fields[] =
+{
+	{"t",	Fnum,	Ot,	"ip type" },
+	{0}
+};
+
+static void
+p_compile(Filter *f)
+{
+	Mux *m;
+
+	if(f->op == '='){
+		compile_cmp(ippkt.name, f, p_fields);
+		return;
+	}
+	for(m = p_mux; m->name != nil; m++)
+		if(strcmp(f->s, m->name) == 0){
+			f->pr = m->pr;
+			f->ulv = m->val;
+			f->subop = Ot;
+			return;
+		}
+	sysfatal("unknown ippkt field or protocol: %s", f->s);
+}
+
+static int
+p_filter(Filter *f, Msg *m)
+{
+	if(m->ps >= m->pe)
+		return 0;
+
+	switch(f->subop){
+	case Ot:
+		return (m->ps[0]&0xF0) == f->ulv;
+	}
+	return 0;
+}
+
+static int
+p_seprint(Msg *m)
+{
+	uint t;
+
+	if(m->ps >= m->pe)
+		return -1;
+
+	t = m->ps[0]&0xF0;
+	demux(p_mux, t, t, m, &dump);
+
+	m->p = seprint(m->p, m->e, "t=%2.2ux", t);
+	return 0;
+}
+
+Proto ippkt =
+{
+	"ippkt",
+	p_compile,
+	p_filter,
+	p_seprint,
+	p_mux,
+	"%#.2lux",
+	p_fields,
+	defaultframer
+};
--- a/sys/src/cmd/ip/snoopy/mkfile
+++ b/sys/src/cmd/ip/snoopy/mkfile
@@ -20,6 +20,7 @@
 	eapol_key\
 	ether\
 	ipmux\
+	ippkt\
 	gre\
 	hdlc\
 	icmp6\