xref: /plan9-contrib/sys/src/cmd/ip/snoopy/icmp6.c (revision e6dcbf51e935975016093545b6eab69976b6e257)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "protos.h"
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier typedef struct Hdr	Hdr;
89a747e4fSDavid du Colombier struct Hdr
99a747e4fSDavid du Colombier {	uchar	type;
109a747e4fSDavid du Colombier 	uchar	code;
119a747e4fSDavid du Colombier 	uchar	cksum[2];	/* Checksum */
129a747e4fSDavid du Colombier 	uchar	data[1];
139a747e4fSDavid du Colombier };
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier enum
169a747e4fSDavid du Colombier {
179a747e4fSDavid du Colombier 	ICMP6LEN=	4,
189a747e4fSDavid du Colombier };
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier enum
219a747e4fSDavid du Colombier {
229a747e4fSDavid du Colombier 	Ot,	/* type */
23*e6dcbf51SDavid du Colombier 	Op,	/* next protocol */
24*e6dcbf51SDavid du Colombier };
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier static Field p_fields[] =
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier 	{"t",		Fnum,	Ot,	"type",	} ,
299a747e4fSDavid du Colombier 	{0}
309a747e4fSDavid du Colombier };
319a747e4fSDavid du Colombier 
329a747e4fSDavid du Colombier enum
339a747e4fSDavid du Colombier {
34*e6dcbf51SDavid du Colombier 	/* ICMPv6 types */
359a747e4fSDavid du Colombier 	EchoReply	= 0,
369a747e4fSDavid du Colombier 	UnreachableV6	= 1,
379a747e4fSDavid du Colombier 	PacketTooBigV6	= 2,
389a747e4fSDavid du Colombier 	TimeExceedV6	= 3,
399a747e4fSDavid du Colombier 	ParamProblemV6	= 4,
409a747e4fSDavid du Colombier 	Redirect	= 5,
419a747e4fSDavid du Colombier 	EchoRequest	= 8,
429a747e4fSDavid du Colombier 	TimeExceed	= 11,
439a747e4fSDavid du Colombier 	InParmProblem	= 12,
449a747e4fSDavid du Colombier 	Timestamp	= 13,
459a747e4fSDavid du Colombier 	TimestampReply	= 14,
469a747e4fSDavid du Colombier 	InfoRequest	= 15,
479a747e4fSDavid du Colombier 	InfoReply	= 16,
489a747e4fSDavid du Colombier 	AddrMaskRequest = 17,
499a747e4fSDavid du Colombier 	AddrMaskReply   = 18,
509a747e4fSDavid du Colombier 	EchoRequestV6	= 128,
519a747e4fSDavid du Colombier 	EchoReplyV6	= 129,
529a747e4fSDavid du Colombier 	RouterSolicit	= 133,
539a747e4fSDavid du Colombier 	RouterAdvert	= 134,
549a747e4fSDavid du Colombier 	NbrSolicit	= 135,
559a747e4fSDavid du Colombier 	NbrAdvert	= 136,
569a747e4fSDavid du Colombier 	RedirectV6	= 137,
579a747e4fSDavid du Colombier 
589a747e4fSDavid du Colombier 	Maxtype6	= 137,
599a747e4fSDavid du Colombier };
609a747e4fSDavid du Colombier 
619a747e4fSDavid du Colombier static Mux p_mux[] =
629a747e4fSDavid du Colombier {
639a747e4fSDavid du Colombier 	{"ip6",	UnreachableV6, },
649a747e4fSDavid du Colombier 	{"ip6",	RedirectV6, },
659a747e4fSDavid du Colombier 	{"ip6",	TimeExceedV6, },
669a747e4fSDavid du Colombier 	{0},
679a747e4fSDavid du Colombier };
689a747e4fSDavid du Colombier 
693ff48bf5SDavid du Colombier char *icmpmsg6[256] =
709a747e4fSDavid du Colombier {
719a747e4fSDavid du Colombier [EchoReply]		"EchoReply",
729a747e4fSDavid du Colombier [UnreachableV6]		"UnreachableV6",
739a747e4fSDavid du Colombier [PacketTooBigV6]	"PacketTooBigV6",
749a747e4fSDavid du Colombier [TimeExceedV6]		"TimeExceedV6",
759a747e4fSDavid du Colombier [Redirect]		"Redirect",
769a747e4fSDavid du Colombier [EchoRequest]		"EchoRequest",
779a747e4fSDavid du Colombier [TimeExceed]		"TimeExceed",
789a747e4fSDavid du Colombier [InParmProblem]		"InParmProblem",
799a747e4fSDavid du Colombier [Timestamp]		"Timestamp",
809a747e4fSDavid du Colombier [TimestampReply]	"TimestampReply",
819a747e4fSDavid du Colombier [InfoRequest]		"InfoRequest",
829a747e4fSDavid du Colombier [InfoReply]		"InfoReply",
839a747e4fSDavid du Colombier [AddrMaskRequest]	"AddrMaskRequest",
849a747e4fSDavid du Colombier [AddrMaskReply]		"AddrMaskReply",
859a747e4fSDavid du Colombier [EchoRequestV6]		"EchoRequestV6",
869a747e4fSDavid du Colombier [EchoReplyV6]		"EchoReplyV6",
879a747e4fSDavid du Colombier [RouterSolicit]		"RouterSolicit",
889a747e4fSDavid du Colombier [RouterAdvert]		"RouterAdvert",
899a747e4fSDavid du Colombier [NbrSolicit]		"NbrSolicit",
909a747e4fSDavid du Colombier [NbrAdvert]		"NbrAdvert",
919a747e4fSDavid du Colombier [RedirectV6]		"RedirectV6",
929a747e4fSDavid du Colombier };
939a747e4fSDavid du Colombier 
949a747e4fSDavid du Colombier static char *unreachcode[] =
959a747e4fSDavid du Colombier {
969a747e4fSDavid du Colombier [0]	"no route to destination",
979a747e4fSDavid du Colombier [1]	"comm with destination administratively prohibited",
989a747e4fSDavid du Colombier [2]	"icmp unreachable: unassigned error code (2)",
999a747e4fSDavid du Colombier [3]	"address unreachable",
1009a747e4fSDavid du Colombier [4]	"port unreachable",
1019a747e4fSDavid du Colombier [5]	"icmp unreachable: unknown code",
1029a747e4fSDavid du Colombier };
1039a747e4fSDavid du Colombier 
1049a747e4fSDavid du Colombier static char *timexcode[] =
1059a747e4fSDavid du Colombier {
1069a747e4fSDavid du Colombier [0]	"hop limit exc",
1079a747e4fSDavid du Colombier [1]	"reassmbl time exc",
1089a747e4fSDavid du Colombier [2]	"icmp time exc: unknown code",
1099a747e4fSDavid du Colombier };
1109a747e4fSDavid du Colombier 
1119a747e4fSDavid du Colombier static char *parpcode[] =
1129a747e4fSDavid du Colombier {
1139a747e4fSDavid du Colombier [0]	"erroneous header field encountered",
1149a747e4fSDavid du Colombier [1]	"unrecognized Next Header type encountered",
1159a747e4fSDavid du Colombier [2]	"unrecognized IPv6 option encountered",
1169a747e4fSDavid du Colombier [3]	"icmp par prob: unknown code",
1179a747e4fSDavid du Colombier };
1189a747e4fSDavid du Colombier enum
1199a747e4fSDavid du Colombier {
1209a747e4fSDavid du Colombier 	sll	= 1,
1219a747e4fSDavid du Colombier 	tll	= 2,
1229a747e4fSDavid du Colombier 	pref	= 3,
1239a747e4fSDavid du Colombier 	redir	= 4,
1249a747e4fSDavid du Colombier 	mtu	= 5,
1259a747e4fSDavid du Colombier };
1269a747e4fSDavid du Colombier 
1273ff48bf5SDavid du Colombier static char *icmp6opts[256] =
1289a747e4fSDavid du Colombier {
1299a747e4fSDavid du Colombier [0]	"unknown opt",
1309a747e4fSDavid du Colombier [1]	"sll_addr",
1319a747e4fSDavid du Colombier [2]	"tll_addr",
1329a747e4fSDavid du Colombier [3]	"pref_opt",
1339a747e4fSDavid du Colombier [4]	"redirect",
1349a747e4fSDavid du Colombier [5]	"mtu_opt",
1359a747e4fSDavid du Colombier };
1369a747e4fSDavid du Colombier 
1379a747e4fSDavid du Colombier static void
p_compile(Filter * f)1389a747e4fSDavid du Colombier p_compile(Filter *f)
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier 	if(f->op == '='){
1419a747e4fSDavid du Colombier 		compile_cmp(icmp6.name, f, p_fields);
1429a747e4fSDavid du Colombier 		return;
1439a747e4fSDavid du Colombier 	}
1449a747e4fSDavid du Colombier 	if(strcmp(f->s, "ip6") == 0){
1459a747e4fSDavid du Colombier 		f->pr = p_mux->pr;
1469a747e4fSDavid du Colombier 		f->subop = Op;
1479a747e4fSDavid du Colombier 		return;
1489a747e4fSDavid du Colombier 	}
1499a747e4fSDavid du Colombier 	sysfatal("unknown icmp field or protocol: %s", f->s);
1509a747e4fSDavid du Colombier }
1519a747e4fSDavid du Colombier 
1529a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)1539a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
1549a747e4fSDavid du Colombier {
1559a747e4fSDavid du Colombier 	Hdr *h;
1569a747e4fSDavid du Colombier 
1579a747e4fSDavid du Colombier 	if(m->pe - m->ps < ICMP6LEN)
1589a747e4fSDavid du Colombier 		return 0;
1599a747e4fSDavid du Colombier 
1609a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
1619a747e4fSDavid du Colombier 	m->ps += ICMP6LEN;
1629a747e4fSDavid du Colombier 
1639a747e4fSDavid du Colombier 	switch(f->subop){
1649a747e4fSDavid du Colombier 
1659a747e4fSDavid du Colombier 	case Ot:
1669a747e4fSDavid du Colombier 		if(h->type == f->ulv)
1679a747e4fSDavid du Colombier 			return 1;
1689a747e4fSDavid du Colombier 		break;
1699a747e4fSDavid du Colombier 	case Op:
1709a747e4fSDavid du Colombier 		switch(h->type){
1719a747e4fSDavid du Colombier 		case UnreachableV6:
1729a747e4fSDavid du Colombier 		case RedirectV6:
1739a747e4fSDavid du Colombier 		case TimeExceedV6:
1749a747e4fSDavid du Colombier 			m->ps += 4;
1759a747e4fSDavid du Colombier 			return 1;
1769a747e4fSDavid du Colombier 		}
1779a747e4fSDavid du Colombier 	}
1789a747e4fSDavid du Colombier 	return 0;
1799a747e4fSDavid du Colombier }
1809a747e4fSDavid du Colombier 
1819a747e4fSDavid du Colombier static char*
opt_seprint(Msg * m)1829a747e4fSDavid du Colombier opt_seprint(Msg *m)
1839a747e4fSDavid du Colombier {
1849a747e4fSDavid du Colombier 	int otype, osz, pktsz;
1859a747e4fSDavid du Colombier 	uchar *a;
1869a747e4fSDavid du Colombier 	char *p = m->p;
1879a747e4fSDavid du Colombier 	char *e = m->e;
1883ff48bf5SDavid du Colombier 	char *opt;
1893ff48bf5SDavid du Colombier 	char optbuf[12];
1909a747e4fSDavid du Colombier 
1919a747e4fSDavid du Colombier 	pktsz = m->pe - m->ps;
1929a747e4fSDavid du Colombier 	a = m->ps;
1939a747e4fSDavid du Colombier 	while (pktsz > 0) {
1949a747e4fSDavid du Colombier 		otype = *a;
1953ff48bf5SDavid du Colombier 		opt = icmp6opts[otype];
1963ff48bf5SDavid du Colombier 		if(opt == nil){
1973ff48bf5SDavid du Colombier 			sprint(optbuf, "0x%ux", otype);
1983ff48bf5SDavid du Colombier 			opt = optbuf;
1993ff48bf5SDavid du Colombier 		}
2009a747e4fSDavid du Colombier 		osz = (*(a+1)) * 8;
2019a747e4fSDavid du Colombier 
2029a747e4fSDavid du Colombier 		switch (otype) {
2039a747e4fSDavid du Colombier 		default:
2043ff48bf5SDavid du Colombier 			p = seprint(p, e, "\n	  option=%s ", opt);
2059a747e4fSDavid du Colombier 			m->pr = &dump;
2069a747e4fSDavid du Colombier 			return p;
2079a747e4fSDavid du Colombier 
2089a747e4fSDavid du Colombier 		case sll:
2099a747e4fSDavid du Colombier 		case tll:
210*e6dcbf51SDavid du Colombier 			if (pktsz < osz || osz != 8) {
211*e6dcbf51SDavid du Colombier 				p = seprint(p, e, "\n	  option=%s bad size=%d",
212*e6dcbf51SDavid du Colombier 					opt, osz);
2139a747e4fSDavid du Colombier 				m->pr = &dump;
2149a747e4fSDavid du Colombier 				return p;
2159a747e4fSDavid du Colombier 			}
2163ff48bf5SDavid du Colombier 			p = seprint(p, e, "\n	  option=%s maddr=%E", opt, a+2);
2179a747e4fSDavid du Colombier 			pktsz -= osz;
2189a747e4fSDavid du Colombier 			a += osz;
2199a747e4fSDavid du Colombier 			break;
2209a747e4fSDavid du Colombier 
2219a747e4fSDavid du Colombier 		case pref:
2229a747e4fSDavid du Colombier 			if ((pktsz < osz) || (osz != 32)) {
223*e6dcbf51SDavid du Colombier 				p = seprint(p, e, "\n	  option=%s: bad size=%d",
224*e6dcbf51SDavid du Colombier 					opt, osz);
2259a747e4fSDavid du Colombier 				m->pr = &dump;
2269a747e4fSDavid du Colombier 				return p;
2279a747e4fSDavid du Colombier 			}
2289a747e4fSDavid du Colombier 
229*e6dcbf51SDavid du Colombier 			p = seprint(p, e, "\n	  option=%s pref=%I "
230*e6dcbf51SDavid du Colombier 				"preflen=%3.3d lflag=%1.1d aflag=%1.1d "
231*e6dcbf51SDavid du Colombier 				"unused1=%1.1d validlt=%d preflt=%d unused2=%1.1d",
2323ff48bf5SDavid du Colombier 				opt,
2339a747e4fSDavid du Colombier 				a+16,
2349a747e4fSDavid du Colombier 				(int) (*(a+2)),
2359a747e4fSDavid du Colombier 				(*(a+3) & (1 << 7)) != 0,
2369a747e4fSDavid du Colombier 				(*(a+3) & (1 << 6)) != 0,
2379a747e4fSDavid du Colombier 				(*(a+3) & 63) != 0,
2389a747e4fSDavid du Colombier 				NetL(a+4),
2399a747e4fSDavid du Colombier 				NetL(a+8),
2409a747e4fSDavid du Colombier 				NetL(a+12)!=0);
2419a747e4fSDavid du Colombier 
2429a747e4fSDavid du Colombier 			pktsz -= osz;
2439a747e4fSDavid du Colombier 			a += osz;
2449a747e4fSDavid du Colombier 			break;
2459a747e4fSDavid du Colombier 
2469a747e4fSDavid du Colombier 		case redir:
2479a747e4fSDavid du Colombier 			if (pktsz < osz) {
248*e6dcbf51SDavid du Colombier 				p = seprint(p, e, "\n	  option=%s: bad size=%d",
249*e6dcbf51SDavid du Colombier 					opt, osz);
2509a747e4fSDavid du Colombier 				m->pr = &dump;
2519a747e4fSDavid du Colombier 				return p;
2529a747e4fSDavid du Colombier 			}
2539a747e4fSDavid du Colombier 
2543ff48bf5SDavid du Colombier 			p = seprint(p, e, "\n	  option=%s len %d", opt, osz);
2559a747e4fSDavid du Colombier 			a += osz;
2569a747e4fSDavid du Colombier 			m->ps = a;
2579a747e4fSDavid du Colombier 			return p;
2589a747e4fSDavid du Colombier 
2599a747e4fSDavid du Colombier 		case mtu:
260*e6dcbf51SDavid du Colombier 			if (pktsz < osz || osz != 8) {
261*e6dcbf51SDavid du Colombier 				p = seprint(p, e, "\n	  option=%s: bad size=%d",
262*e6dcbf51SDavid du Colombier 					opt, osz);
2639a747e4fSDavid du Colombier 				m->pr = &dump;
2649a747e4fSDavid du Colombier 				return p;
2659a747e4fSDavid du Colombier 			}
2669a747e4fSDavid du Colombier 
267*e6dcbf51SDavid du Colombier 			p = seprint(p, e, "\n	  option=%s unused=%1.1d mtu=%d",
268*e6dcbf51SDavid du Colombier 				opt, NetL(a+2) != 0, NetL(a+4));
2699a747e4fSDavid du Colombier 			pktsz -= osz;
2709a747e4fSDavid du Colombier 			a += osz;
2719a747e4fSDavid du Colombier 			break;
2729a747e4fSDavid du Colombier 		}
2739a747e4fSDavid du Colombier 	}
2749a747e4fSDavid du Colombier 
2759a747e4fSDavid du Colombier 	m->ps = a;
2769a747e4fSDavid du Colombier 	return p;
2779a747e4fSDavid du Colombier }
2789a747e4fSDavid du Colombier 
2799a747e4fSDavid du Colombier static int
p_seprint(Msg * m)2809a747e4fSDavid du Colombier p_seprint(Msg *m)
2819a747e4fSDavid du Colombier {
282*e6dcbf51SDavid du Colombier 	int i;
283*e6dcbf51SDavid du Colombier //	ushort cksum2, cksum;
2849a747e4fSDavid du Colombier 	char *tn;
2859a747e4fSDavid du Colombier 	char *p = m->p;
2869a747e4fSDavid du Colombier 	char *e = m->e;
2879a747e4fSDavid du Colombier 	uchar *a;
288*e6dcbf51SDavid du Colombier 	Hdr *h;
2899a747e4fSDavid du Colombier 
2909a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
2919a747e4fSDavid du Colombier 	m->ps += ICMP6LEN;
2929a747e4fSDavid du Colombier 	m->pr = &dump;
2939a747e4fSDavid du Colombier 	a = m->ps;
2949a747e4fSDavid du Colombier 
2959a747e4fSDavid du Colombier 	if(m->pe - m->ps < ICMP6LEN)
2969a747e4fSDavid du Colombier 		return -1;
2979a747e4fSDavid du Colombier 
2989a747e4fSDavid du Colombier 	tn = icmpmsg6[h->type];
2999a747e4fSDavid du Colombier 	if(tn == nil)
3009a747e4fSDavid du Colombier 		p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
3019a747e4fSDavid du Colombier 			h->code, (ushort)NetS(h->cksum));
3029a747e4fSDavid du Colombier 	else
3039a747e4fSDavid du Colombier 		p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
3049a747e4fSDavid du Colombier 			h->code, (ushort)NetS(h->cksum));
3059a747e4fSDavid du Colombier 
3069a747e4fSDavid du Colombier /*
3079a747e4fSDavid du Colombier 	if(Cflag){
3089a747e4fSDavid du Colombier 		cksum = NetS(h->cksum);
3099a747e4fSDavid du Colombier 		h->cksum[0] = 0;
3109a747e4fSDavid du Colombier 		h->cksum[1] = 0;
3119a747e4fSDavid du Colombier 		cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMP6LEN) & 0xffff;
3129a747e4fSDavid du Colombier 		if(cksum != cksum2)
3139a747e4fSDavid du Colombier 			p = seprint(p,e, " !ck=%4.4ux", cksum2);
3149a747e4fSDavid du Colombier 	}
3159a747e4fSDavid du Colombier  */
3169a747e4fSDavid du Colombier 
3179a747e4fSDavid du Colombier 	switch(h->type){
3189a747e4fSDavid du Colombier 
3199a747e4fSDavid du Colombier 	case UnreachableV6:
3209a747e4fSDavid du Colombier 		m->ps += 4;
3219a747e4fSDavid du Colombier 		m->pr = &ip6;
3223ff48bf5SDavid du Colombier 		if (h->code >= nelem(unreachcode))
3233ff48bf5SDavid du Colombier 			i = nelem(unreachcode)-1;
3249a747e4fSDavid du Colombier 		else
3259a747e4fSDavid du Colombier 			i = h->code;
326*e6dcbf51SDavid du Colombier 		p = seprint(p, e, " code=%s unused=%1.1d ", unreachcode[i],
327*e6dcbf51SDavid du Colombier 			NetL(a) != 0);
3289a747e4fSDavid du Colombier 		break;
3299a747e4fSDavid du Colombier 
3309a747e4fSDavid du Colombier 	case PacketTooBigV6:
3319a747e4fSDavid du Colombier 		m->ps += 4;
3329a747e4fSDavid du Colombier 		m->pr = &ip6;
3339a747e4fSDavid du Colombier 		p = seprint(p, e, " mtu=%4.4d ", NetL(a));
3349a747e4fSDavid du Colombier 		break;
3359a747e4fSDavid du Colombier 
3369a747e4fSDavid du Colombier 	case TimeExceedV6:
3379a747e4fSDavid du Colombier 		m->ps += 4;
3389a747e4fSDavid du Colombier 		m->pr = &ip6;
3393ff48bf5SDavid du Colombier 		if (h->code >= nelem(timexcode))
3403ff48bf5SDavid du Colombier 			i = nelem(timexcode)-1;
3419a747e4fSDavid du Colombier 		else
3429a747e4fSDavid du Colombier 			i = h->code;
343*e6dcbf51SDavid du Colombier 		p = seprint(p, e, " code=%s unused=%1.1d ", timexcode[i],
344*e6dcbf51SDavid du Colombier 			NetL(a) != 0);
3459a747e4fSDavid du Colombier 		break;
3469a747e4fSDavid du Colombier 
3479a747e4fSDavid du Colombier 	case ParamProblemV6:
3489a747e4fSDavid du Colombier 		m->ps += 4;
3499a747e4fSDavid du Colombier 		m->pr = &ip6;
3503ff48bf5SDavid du Colombier 		if (h->code > nelem(parpcode))
3513ff48bf5SDavid du Colombier 			i = nelem(parpcode)-1;
3529a747e4fSDavid du Colombier 		else
3539a747e4fSDavid du Colombier 			i = h->code;
3549a747e4fSDavid du Colombier 		p = seprint(p, e, " code=%s ptr=%2.2ux", parpcode[i], h->data[0]);
3559a747e4fSDavid du Colombier 		break;
3569a747e4fSDavid du Colombier 
3579a747e4fSDavid du Colombier 	case EchoReplyV6:
3589a747e4fSDavid du Colombier 	case EchoRequestV6:
3599a747e4fSDavid du Colombier 		m->ps += 4;
3609a747e4fSDavid du Colombier 		p = seprint(p, e, " id=%ux seq=%ux",
3619a747e4fSDavid du Colombier 			NetS(h->data), NetS(h->data+2));
3629a747e4fSDavid du Colombier 		break;
3639a747e4fSDavid du Colombier 
3649a747e4fSDavid du Colombier 	case RouterSolicit:
3659a747e4fSDavid du Colombier 		m->ps += 4;
3669a747e4fSDavid du Colombier 		m->pr = nil;
3679a747e4fSDavid du Colombier 		m->p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
3689a747e4fSDavid du Colombier 		p = opt_seprint(m);
3699a747e4fSDavid du Colombier 		break;
3709a747e4fSDavid du Colombier 
3719a747e4fSDavid du Colombier 	case RouterAdvert:
3729a747e4fSDavid du Colombier 		m->ps += 12;
3739a747e4fSDavid du Colombier 		m->pr = nil;
374*e6dcbf51SDavid du Colombier 		m->p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d "
375*e6dcbf51SDavid du Colombier 			"unused=%1.1d routerlt=%8.8d reachtime=%d rxmtimer=%d",
3769a747e4fSDavid du Colombier 			(int) *a,
3779a747e4fSDavid du Colombier 			(*(a+1) & (1 << 7)) != 0,
3789a747e4fSDavid du Colombier 			(*(a+1) & (1 << 6)) != 0,
3799a747e4fSDavid du Colombier 			(*(a+1) & 63) != 0,
3809a747e4fSDavid du Colombier 			NetS(a+2),
3819a747e4fSDavid du Colombier 			NetL(a+4),
3829a747e4fSDavid du Colombier 			NetL(a+8));
3839a747e4fSDavid du Colombier 		p = opt_seprint(m);
3849a747e4fSDavid du Colombier 		break;
3859a747e4fSDavid du Colombier 
3869a747e4fSDavid du Colombier 	case NbrSolicit:
3879a747e4fSDavid du Colombier 		m->ps += 20;
3889a747e4fSDavid du Colombier 		m->pr = nil;
3899a747e4fSDavid du Colombier 		m->p = seprint(p, e, " unused=%1.1d targ %I", NetL(a) != 0, a+4);
3909a747e4fSDavid du Colombier 		p = opt_seprint(m);
3919a747e4fSDavid du Colombier 		break;
3929a747e4fSDavid du Colombier 
3939a747e4fSDavid du Colombier 	case NbrAdvert:
3949a747e4fSDavid du Colombier 		m->ps += 20;
3959a747e4fSDavid du Colombier 		m->pr = nil;
3969a747e4fSDavid du Colombier 		m->p = seprint(p, e, " rflag=%1.1d sflag=%1.1d oflag=%1.1d targ=%I",
3979a747e4fSDavid du Colombier 			(*a & (1 << 7)) != 0,
3989a747e4fSDavid du Colombier 			(*a & (1 << 6)) != 0,
3999a747e4fSDavid du Colombier 			(*a & (1 << 5)) != 0,
4009a747e4fSDavid du Colombier 			a+4);
4019a747e4fSDavid du Colombier 		p = opt_seprint(m);
4029a747e4fSDavid du Colombier 		break;
4039a747e4fSDavid du Colombier 
4049a747e4fSDavid du Colombier 	case RedirectV6:
4059a747e4fSDavid du Colombier 		m->ps += 36;
4069a747e4fSDavid du Colombier 		m->pr = &ip6;
407*e6dcbf51SDavid du Colombier 		m->p = seprint(p, e, " unused=%1.1d targ=%I dest=%I",
408*e6dcbf51SDavid du Colombier 			NetL(a) != 0, a+4, a+20);
4099a747e4fSDavid du Colombier 		p = opt_seprint(m);
4109a747e4fSDavid du Colombier 		break;
4119a747e4fSDavid du Colombier 
4129a747e4fSDavid du Colombier 	case Timestamp:
4139a747e4fSDavid du Colombier 	case TimestampReply:
4149a747e4fSDavid du Colombier 		m->ps += 12;
4159a747e4fSDavid du Colombier 		p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
416*e6dcbf51SDavid du Colombier 			NetL(h->data), NetL(h->data+4), NetL(h->data+8));
4179a747e4fSDavid du Colombier 		m->pr = nil;
4189a747e4fSDavid du Colombier 		break;
4199a747e4fSDavid du Colombier 
4209a747e4fSDavid du Colombier 	case InfoRequest:
4219a747e4fSDavid du Colombier 	case InfoReply:
4229a747e4fSDavid du Colombier 		break;
4239a747e4fSDavid du Colombier 
4249a747e4fSDavid du Colombier 	}
4259a747e4fSDavid du Colombier 	m->p = p;
4269a747e4fSDavid du Colombier 	return 0;
4279a747e4fSDavid du Colombier }
4289a747e4fSDavid du Colombier 
4299a747e4fSDavid du Colombier Proto icmp6 =
4309a747e4fSDavid du Colombier {
4319a747e4fSDavid du Colombier 	"icmp6",
4329a747e4fSDavid du Colombier 	p_compile,
4339a747e4fSDavid du Colombier 	p_filter,
4349a747e4fSDavid du Colombier 	p_seprint,
4359a747e4fSDavid du Colombier 	p_mux,
436ed397113SDavid du Colombier 	"%lud",
4379a747e4fSDavid du Colombier 	p_fields,
4383ff48bf5SDavid du Colombier 	defaultframer,
4399a747e4fSDavid du Colombier };
440