xref: /plan9-contrib/sys/src/cmd/ip/snoopy/ip6.c (revision e6dcbf51e935975016093545b6eab69976b6e257)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
6 
7 typedef struct Hdr	Hdr;
8 struct Hdr
9 {
10 	uchar	vcf[4];			/* Version and header length */
11 	uchar	length[2];		/* packet length */
12 	uchar	proto;			/* Protocol */
13 	uchar	ttl;			/* Time to live */
14 	uchar	src[IPaddrlen];		/* IP source */
15 	uchar	dst[IPaddrlen];		/* IP destination */
16 };
17 
18 enum
19 {
20 	IP6HDR		= 40,		/* sizeof(Iphdr) */
21 	IP_VER		= 0x60,		/* Using IP version 4 */
22 	HBH_HDR		= 0,
23 	ROUT_HDR	= 43,
24 	FRAG_HDR	= 44,
25 	FRAG_HSZ	= 8, 		/* in bytes */
26 	DEST_HDR	= 60,
27 };
28 
29 static Mux p_mux[] =
30 {
31 	{ "igmp", 2, },
32 	{ "ggp", 3, },
33 	{ "ip", 4, },
34 	{ "st", 5, },
35 	{ "tcp", 6, },
36 	{ "ucl", 7, },
37 	{ "egp", 8, },
38 	{ "igp", 9, },
39 	{ "bbn-rcc-mon", 10, },
40 	{ "nvp-ii", 11, },
41 	{ "pup", 12, },
42 	{ "argus", 13, },
43 	{ "emcon", 14, },
44 	{ "xnet", 15, },
45 	{ "chaos", 16, },
46 	{ "udp", 17, },
47 	{ "mux", 18, },
48 	{ "dcn-meas", 19, },
49 	{ "hmp", 20, },
50 	{ "prm", 21, },
51 	{ "xns-idp", 22, },
52 	{ "trunk-1", 23, },
53 	{ "trunk-2", 24, },
54 	{ "leaf-1", 25, },
55 	{ "leaf-2", 26, },
56 	{ "rdp", 27, },
57 	{ "irtp", 28, },
58 	{ "iso-tp4", 29, },
59 	{ "netblt", 30, },
60 	{ "mfe-nsp", 31, },
61 	{ "merit-inp", 32, },
62 	{ "sep", 33, },
63 	{ "3pc", 34, },
64 	{ "idpr", 35, },
65 	{ "xtp", 36, },
66 	{ "ddp", 37, },
67 	{ "idpr-cmtp", 38, },
68 	{ "tp++", 39, },
69 	{ "il", 40, },
70 	{ "sip", 41, },
71 	{ "sdrp", 42, },
72 	{ "idrp", 45, },
73 	{ "rsvp", 46, },
74 	{ "gre", 47, },
75 	{ "mhrp", 48, },
76 	{ "bna", 49, },
77 	{ "sipp-esp", 50, },
78 	{ "sipp-ah", 51, },
79 	{ "i-nlsp", 52, },
80 	{ "swipe", 53, },
81 	{ "nhrp", 54, },
82 	{ "icmp6", 58, },
83 	{ "any", 61, },
84 	{ "cftp", 62, },
85 	{ "any", 63, },
86 	{ "sat-expak", 64, },
87 	{ "kryptolan", 65, },
88 	{ "rvd", 66, },
89 	{ "ippc", 67, },
90 	{ "any", 68, },
91 	{ "sat-mon", 69, },
92 	{ "visa", 70, },
93 	{ "ipcv", 71, },
94 	{ "cpnx", 72, },
95 	{ "cphb", 73, },
96 	{ "wsn", 74, },
97 	{ "pvp", 75, },
98 	{ "br-sat-mon", 76, },
99 	{ "sun-nd", 77, },
100 	{ "wb-mon", 78, },
101 	{ "wb-expak", 79, },
102 	{ "iso-ip", 80, },
103 	{ "vmtp", 81, },
104 	{ "secure-vmtp", 82, },
105 	{ "vines", 83, },
106 	{ "ttp", 84, },
107 	{ "nsfnet-igp", 85, },
108 	{ "dgp", 86, },
109 	{ "tcf", 87, },
110 	{ "igrp", 88, },
111 	{ "ospf", 89, },
112 	{ "sprite-rpc", 90, },
113 	{ "larp", 91, },
114 	{ "mtp", 92, },
115 	{ "ax.25", 93, },
116 	{ "ipip", 94, },
117 	{ "micp", 95, },
118 	{ "scc-sp", 96, },
119 	{ "etherip", 97, },
120 	{ "encap", 98, },
121 	{ "any", 99, },
122 	{ "gmtp", 100, },
123 	{ "rudp", 254, },
124 	{ 0 }
125 };
126 
127 enum
128 {
129 	Os,	/* source */
130 	Od,	/* destination */
131 	Osd,	/* source or destination */
132 	Ot,	/* type */
133 };
134 
135 static Field p_fields[] =
136 {
137 	{"s",	Fv6ip,	Os,	"source address",	} ,
138 	{"d",	Fv6ip,	Od,	"destination address",	} ,
139 	{"a",	Fv6ip,	Osd,	"source|destination address",} ,
140 	{"t",	Fnum,	Ot,	"sub protocol number",	} ,
141 	{0}
142 };
143 
144 static void
p_compile(Filter * f)145 p_compile(Filter *f)
146 {
147 	Mux *m;
148 
149 	if(f->op == '='){
150 		compile_cmp(ip6.name, f, p_fields);
151 		return;
152 	}
153 	for(m = p_mux; m->name != nil; m++)
154 		if(strcmp(f->s, m->name) == 0){
155 			f->pr = m->pr;
156 			f->ulv = m->val;
157 			f->subop = Ot;
158 			return;
159 		}
160 	sysfatal("unknown ip6 field or protocol: %s", f->s);
161 }
162 
163 static int
v6hdrlen(Hdr * h)164 v6hdrlen(Hdr *h)
165 {
166 	int plen, len = IP6HDR;
167 	int pktlen = IP6HDR + NetS(h->length);
168 	uchar nexthdr = h->proto;
169 	uchar *pkt = (uchar*) h;
170 
171 	pkt += len;
172 	plen = len;
173 
174 	while (nexthdr == HBH_HDR || nexthdr == ROUT_HDR ||
175 	    nexthdr == FRAG_HDR || nexthdr == DEST_HDR) {
176 		if (nexthdr == FRAG_HDR)
177 			len = FRAG_HSZ;
178 		else
179 			len = ((int)*(pkt+1) + 1) * 8;
180 
181 		if (plen + len > pktlen)
182 			return -1;
183 
184 		pkt += len;
185 		nexthdr = *pkt;
186 		plen += len;
187 	}
188 	return plen;
189 }
190 
191 static int
p_filter(Filter * f,Msg * m)192 p_filter(Filter *f, Msg *m)
193 {
194 	Hdr *h;
195 	int hlen;
196 
197 	if(m->pe - m->ps < IP6HDR)
198 		return 0;
199 
200 	h = (Hdr*)m->ps;
201 
202 	if ((hlen = v6hdrlen(h)) < 0)
203 		return 0;
204 	else
205 		m->ps += hlen;
206 	switch(f->subop){
207 	case Os:
208 		return memcmp(h->src, f->a, IPaddrlen) == 0;
209 	case Od:
210 		return memcmp(h->dst, f->a, IPaddrlen) == 0;
211 	case Osd:
212 		return memcmp(h->src, f->a, IPaddrlen) == 0 ||
213 			memcmp(h->dst, f->a, IPaddrlen) == 0;
214 	case Ot:
215 		return h->proto == f->ulv;
216 	}
217 	return 0;
218 }
219 
220 static int
v6hdr_seprint(Msg * m)221 v6hdr_seprint(Msg *m)
222 {
223 	int plen, len = IP6HDR;
224 	uchar *pkt = m->ps;
225 	Hdr *h = (Hdr *)pkt;
226 	int pktlen = IP6HDR + NetS(h->length);
227 	uchar nexthdr = h->proto;
228 
229 	pkt += len;
230 	plen = len;
231 
232 	while (nexthdr == HBH_HDR || nexthdr == ROUT_HDR ||
233 	    nexthdr == FRAG_HDR || nexthdr == DEST_HDR) {
234 		switch (nexthdr) {
235 		case FRAG_HDR:
236 			m->p = seprint(m->p, m->e, "\n	  xthdr=frag id=%d "
237 				"offset=%d pr=%d more=%d res1=%d res2=%d",
238 				NetL(pkt+4), NetS(pkt+2) & ~7, (int)*pkt,
239 				(int)(*(pkt+3) & 0x1), (int)*(pkt+1),
240 				(int)(*(pkt+3) & 0x6));
241 			len = FRAG_HSZ;
242 			break;
243 
244 		case HBH_HDR:
245 		case ROUT_HDR:
246 		case DEST_HDR:
247 			len = ((int)*(pkt+1) + 1) * 8;
248 			break;
249 		}
250 
251 		if (plen + len > pktlen) {
252 			m->p = seprint(m->p, m->e, "bad pkt");
253 			m->pr = &dump;
254 			return -1;
255 		}
256 		plen += len;
257 		pkt += len;
258 		nexthdr = *pkt;
259 	}
260 
261 	m->ps = pkt;
262 	return 1;
263 }
264 
265 static int
p_seprint(Msg * m)266 p_seprint(Msg *m)
267 {
268 	int len;
269 	Hdr *h;
270 
271 	if(m->pe - m->ps < IP6HDR)
272 		return -1;
273 	h = (Hdr*)m->ps;
274 
275 	demux(p_mux, h->proto, h->proto, m, &dump);
276 
277 	/* truncate the message if there's extra */
278 	len = NetS(h->length) + IP6HDR;
279 	if(len < m->pe - m->ps)
280 		m->pe = m->ps + len;
281 
282 	m->p = seprint(m->p, m->e, "s=%I d=%I ttl=%3d pr=%d ln=%d",
283 		h->src, h->dst, h->ttl, h->proto, NetS(h->length));
284 	v6hdr_seprint(m);
285 	return 0;
286 }
287 
288 Proto ip6 =
289 {
290 	"ip6",
291 	p_compile,
292 	p_filter,
293 	p_seprint,
294 	p_mux,
295 	"%lud",
296 	p_fields,
297 	defaultframer,
298 };
299