aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/icmp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/icmp6.c')
-rwxr-xr-xsrc/cmd/ip/snoopy/icmp6.c428
1 files changed, 428 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/icmp6.c b/src/cmd/ip/snoopy/icmp6.c
new file mode 100755
index 00000000..9c154f88
--- /dev/null
+++ b/src/cmd/ip/snoopy/icmp6.c
@@ -0,0 +1,428 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+typedef struct Hdr Hdr;
+struct Hdr
+{ uchar type;
+ uchar code;
+ uchar cksum[2]; /* Checksum */
+ uchar data[1];
+};
+
+enum
+{
+ ICMP6LEN= 4,
+};
+
+enum
+{
+ Ot, /* type */
+ Op, /* next protocol */};
+
+static Field p_fields[] =
+{
+ {"t", Fnum, Ot, "type", } ,
+ {0}
+};
+
+enum
+{
+ // ICMPv6 types
+ EchoReply = 0,
+ UnreachableV6 = 1,
+ PacketTooBigV6 = 2,
+ TimeExceedV6 = 3,
+ ParamProblemV6 = 4,
+ Redirect = 5,
+ EchoRequest = 8,
+ TimeExceed = 11,
+ InParmProblem = 12,
+ Timestamp = 13,
+ TimestampReply = 14,
+ InfoRequest = 15,
+ InfoReply = 16,
+ AddrMaskRequest = 17,
+ AddrMaskReply = 18,
+ EchoRequestV6 = 128,
+ EchoReplyV6 = 129,
+ RouterSolicit = 133,
+ RouterAdvert = 134,
+ NbrSolicit = 135,
+ NbrAdvert = 136,
+ RedirectV6 = 137,
+
+ Maxtype6 = 137,
+};
+
+static Mux p_mux[] =
+{
+ {"ip6", UnreachableV6, },
+ {"ip6", RedirectV6, },
+ {"ip6", TimeExceedV6, },
+ {0},
+};
+
+char *icmpmsg6[256] =
+{
+[EchoReply] "EchoReply",
+[UnreachableV6] "UnreachableV6",
+[PacketTooBigV6] "PacketTooBigV6",
+[TimeExceedV6] "TimeExceedV6",
+[Redirect] "Redirect",
+[EchoRequest] "EchoRequest",
+[TimeExceed] "TimeExceed",
+[InParmProblem] "InParmProblem",
+[Timestamp] "Timestamp",
+[TimestampReply] "TimestampReply",
+[InfoRequest] "InfoRequest",
+[InfoReply] "InfoReply",
+[AddrMaskRequest] "AddrMaskRequest",
+[AddrMaskReply] "AddrMaskReply",
+[EchoRequestV6] "EchoRequestV6",
+[EchoReplyV6] "EchoReplyV6",
+[RouterSolicit] "RouterSolicit",
+[RouterAdvert] "RouterAdvert",
+[NbrSolicit] "NbrSolicit",
+[NbrAdvert] "NbrAdvert",
+[RedirectV6] "RedirectV6",
+};
+
+static char *unreachcode[] =
+{
+[0] "no route to destination",
+[1] "comm with destination administratively prohibited",
+[2] "icmp unreachable: unassigned error code (2)",
+[3] "address unreachable",
+[4] "port unreachable",
+[5] "icmp unreachable: unknown code",
+};
+
+static char *timexcode[] =
+{
+[0] "hop limit exc",
+[1] "reassmbl time exc",
+[2] "icmp time exc: unknown code",
+};
+
+static char *parpcode[] =
+{
+[0] "erroneous header field encountered",
+[1] "unrecognized Next Header type encountered",
+[2] "unrecognized IPv6 option encountered",
+[3] "icmp par prob: unknown code",
+};
+enum
+{
+ sll = 1,
+ tll = 2,
+ pref = 3,
+ redir = 4,
+ mtu = 5,
+};
+
+static char *icmp6opts[256] =
+{
+[0] "unknown opt",
+[1] "sll_addr",
+[2] "tll_addr",
+[3] "pref_opt",
+[4] "redirect",
+[5] "mtu_opt",
+};
+
+static void
+p_compile(Filter *f)
+{
+ if(f->op == '='){
+ compile_cmp(icmp6.name, f, p_fields);
+ return;
+ }
+ if(strcmp(f->s, "ip6") == 0){
+ f->pr = p_mux->pr;
+ f->subop = Op;
+ return;
+ }
+ sysfatal("unknown icmp field or protocol: %s", f->s);
+}
+
+static int
+p_filter(Filter *f, Msg *m)
+{
+ Hdr *h;
+
+ if(m->pe - m->ps < ICMP6LEN)
+ return 0;
+
+ h = (Hdr*)m->ps;
+ m->ps += ICMP6LEN;
+
+ switch(f->subop){
+
+ case Ot:
+ if(h->type == f->ulv)
+ return 1;
+ break;
+ case Op:
+ switch(h->type){
+ case UnreachableV6:
+ case RedirectV6:
+ case TimeExceedV6:
+ m->ps += 4;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static char*
+opt_seprint(Msg *m)
+{
+ int otype, osz, pktsz;
+ uchar *a;
+ char *p = m->p;
+ char *e = m->e;
+ char *opt;
+ char optbuf[12];
+
+ pktsz = m->pe - m->ps;
+ a = m->ps;
+ while (pktsz > 0) {
+ otype = *a;
+ opt = icmp6opts[otype];
+ if(opt == nil){
+ sprint(optbuf, "0x%ux", otype);
+ opt = optbuf;
+ }
+ osz = (*(a+1)) * 8;
+
+ switch (otype) {
+ default:
+ p = seprint(p, e, "\n option=%s ", opt);
+ m->pr = &dump;
+ return p;
+
+ case sll:
+ case tll:
+ if ((pktsz < osz) || (osz != 8)) {
+ p = seprint(p, e, "\n option=%s bad size=%d", opt, osz);
+ m->pr = &dump;
+ return p;
+ }
+ p = seprint(p, e, "\n option=%s maddr=%E", opt, a+2);
+ pktsz -= osz;
+ a += osz;
+ break;
+
+ case pref:
+ if ((pktsz < osz) || (osz != 32)) {
+ p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
+ m->pr = &dump;
+ return p;
+ }
+
+ p = seprint(p, e, "\n option=%s pref=%I preflen=%3.3d lflag=%1.1d aflag=%1.1d unused1=%1.1d validlt=%d preflt=%d unused2=%1.1d",
+ opt,
+ a+16,
+ (int) (*(a+2)),
+ (*(a+3) & (1 << 7))!=0,
+ (*(a+3) & (1 << 6))!=0,
+ (*(a+3) & 63) != 0,
+ NetL(a+4),
+ NetL(a+8),
+ NetL(a+12)!=0);
+
+ pktsz -= osz;
+ a += osz;
+ break;
+
+ case redir:
+ if (pktsz < osz) {
+ p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
+ m->pr = &dump;
+ return p;
+ }
+
+ p = seprint(p, e, "\n option=%s len %d", opt, osz);
+ a += osz;
+ m->ps = a;
+ return p;
+ break;
+
+ case mtu:
+ if ((pktsz < osz) || (osz != 8)) {
+ p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
+ m->pr = &dump;
+ return p;
+ }
+
+ p = seprint(p, e, "\n option=%s unused=%1.1d mtu=%d", opt, NetL(a+2)!=0, NetL(a+4));
+ pktsz -= osz;
+ a += osz;
+ break;
+ }
+ }
+
+ m->ps = a;
+ return p;
+}
+
+static int
+p_seprint(Msg *m)
+{
+ Hdr *h;
+ char *tn;
+ char *p = m->p;
+ char *e = m->e;
+ int i;
+ uchar *a;
+// ushort cksum2, cksum;
+
+ h = (Hdr*)m->ps;
+ m->ps += ICMP6LEN;
+ m->pr = &dump;
+ a = m->ps;
+
+ if(m->pe - m->ps < ICMP6LEN)
+ return -1;
+
+ tn = icmpmsg6[h->type];
+ if(tn == nil)
+ p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
+ h->code, (ushort)NetS(h->cksum));
+ else
+ p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
+ h->code, (ushort)NetS(h->cksum));
+
+ /*
+ if(Cflag){
+ cksum = NetS(h->cksum);
+ h->cksum[0] = 0;
+ h->cksum[1] = 0;
+ cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMP6LEN) & 0xffff;
+ if(cksum != cksum2)
+ p = seprint(p,e, " !ck=%4.4ux", cksum2);
+ }
+ */
+
+ switch(h->type){
+
+ case UnreachableV6:
+ m->ps += 4;
+ m->pr = &ip6;
+ if (h->code >= nelem(unreachcode))
+ i = nelem(unreachcode)-1;
+ else
+ i = h->code;
+ p = seprint(p, e, " code=%s unused=%1.1d ", unreachcode[i], NetL(a)!=0);
+ break;
+
+ case PacketTooBigV6:
+ m->ps += 4;
+ m->pr = &ip6;
+ p = seprint(p, e, " mtu=%4.4d ", NetL(a));
+ break;
+
+ case TimeExceedV6:
+ m->ps += 4;
+ m->pr = &ip6;
+ if (h->code >= nelem(timexcode))
+ i = nelem(timexcode)-1;
+ else
+ i = h->code;
+ p = seprint(p, e, " code=%s unused=%1.1d ", timexcode[i], NetL(a)!=0);
+ break;
+
+ case ParamProblemV6:
+ m->ps += 4;
+ m->pr = &ip6;
+ if (h->code > nelem(parpcode))
+ i = nelem(parpcode)-1;
+ else
+ i = h->code;
+ p = seprint(p, e, " code=%s ptr=%2.2ux", parpcode[i], h->data[0]);
+ break;
+
+ case EchoReplyV6:
+ case EchoRequestV6:
+ m->ps += 4;
+ p = seprint(p, e, " id=%ux seq=%ux",
+ NetS(h->data), NetS(h->data+2));
+ break;
+
+ case RouterSolicit:
+ m->ps += 4;
+ m->pr = nil;
+ m->p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
+ p = opt_seprint(m);
+ break;
+
+ case RouterAdvert:
+ m->ps += 12;
+ m->pr = nil;
+ m->p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d unused=%1.1d routerlt=%8.8d reachtime=%d rxmtimer=%d",
+ (int) *a,
+ (*(a+1) & (1 << 7)) != 0,
+ (*(a+1) & (1 << 6)) != 0,
+ (*(a+1) & 63) != 0,
+ NetS(a+2),
+ NetL(a+4),
+ NetL(a+8));
+ p = opt_seprint(m);
+ break;
+
+ case NbrSolicit:
+ m->ps += 20;
+ m->pr = nil;
+ m->p = seprint(p, e, " unused=%1.1d targ %I", NetL(a)!=0, a+4);
+ p = opt_seprint(m);
+ break;
+
+ case NbrAdvert:
+ m->ps += 20;
+ m->pr = nil;
+ m->p = seprint(p, e, " rflag=%1.1d sflag=%1.1d oflag=%1.1d targ=%I",
+ (*a & (1 << 7)) != 0,
+ (*a & (1 << 6)) != 0,
+ (*a & (1 << 5)) != 0,
+ a+4);
+ p = opt_seprint(m);
+ break;
+
+ case RedirectV6:
+ m->ps += 36;
+ m->pr = &ip6;
+ m->p = seprint(p, e, " unused=%1.1d targ=%I dest=%I", NetL(a)!=0, a+4, a+20);
+ p = opt_seprint(m);
+ break;
+
+ case Timestamp:
+ case TimestampReply:
+ m->ps += 12;
+ p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
+ NetL(h->data), NetL(h->data+4),
+ NetL(h->data+8));
+ m->pr = nil;
+ break;
+
+ case InfoRequest:
+ case InfoReply:
+ break;
+
+ }
+ m->p = p;
+ return 0;
+}
+
+Proto icmp6 =
+{
+ "icmp6",
+ p_compile,
+ p_filter,
+ p_seprint,
+ p_mux,
+ p_fields,
+ defaultframer,
+};