ticmp6.c - plan9port - [fork] Plan 9 from user space
HTML git clone git://src.adamsgaard.dk/plan9port
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
ticmp6.c (7718B)
---
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 { uchar type;
10 uchar code;
11 uchar cksum[2]; /* Checksum */
12 uchar data[1];
13 };
14
15 enum
16 {
17 ICMP6LEN= 4
18 };
19
20 enum
21 {
22 Ot, /* type */
23 Op, /* next protocol */};
24
25 static Field p_fields[] =
26 {
27 {"t", Fnum, Ot, "type", } ,
28 {0}
29 };
30
31 enum
32 {
33 /* ICMPv6 types */
34 EchoReply = 0,
35 UnreachableV6 = 1,
36 PacketTooBigV6 = 2,
37 TimeExceedV6 = 3,
38 ParamProblemV6 = 4,
39 Redirect = 5,
40 EchoRequest = 8,
41 TimeExceed = 11,
42 InParmProblem = 12,
43 Timestamp = 13,
44 TimestampReply = 14,
45 InfoRequest = 15,
46 InfoReply = 16,
47 AddrMaskRequest = 17,
48 AddrMaskReply = 18,
49 EchoRequestV6 = 128,
50 EchoReplyV6 = 129,
51 RouterSolicit = 133,
52 RouterAdvert = 134,
53 NbrSolicit = 135,
54 NbrAdvert = 136,
55 RedirectV6 = 137,
56
57 Maxtype6 = 137
58 };
59
60 static Mux p_mux[] =
61 {
62 {"ip6", UnreachableV6, },
63 {"ip6", RedirectV6, },
64 {"ip6", TimeExceedV6, },
65 {0}
66 };
67
68 char *icmpmsg6[256] =
69 {
70 [EchoReply] "EchoReply",
71 [UnreachableV6] "UnreachableV6",
72 [PacketTooBigV6] "PacketTooBigV6",
73 [TimeExceedV6] "TimeExceedV6",
74 [Redirect] "Redirect",
75 [EchoRequest] "EchoRequest",
76 [TimeExceed] "TimeExceed",
77 [InParmProblem] "InParmProblem",
78 [Timestamp] "Timestamp",
79 [TimestampReply] "TimestampReply",
80 [InfoRequest] "InfoRequest",
81 [InfoReply] "InfoReply",
82 [AddrMaskRequest] "AddrMaskRequest",
83 [AddrMaskReply] "AddrMaskReply",
84 [EchoRequestV6] "EchoRequestV6",
85 [EchoReplyV6] "EchoReplyV6",
86 [RouterSolicit] "RouterSolicit",
87 [RouterAdvert] "RouterAdvert",
88 [NbrSolicit] "NbrSolicit",
89 [NbrAdvert] "NbrAdvert",
90 [RedirectV6] "RedirectV6"
91 };
92
93 static char *unreachcode[] =
94 {
95 [0] "no route to destination",
96 [1] "comm with destination administratively prohibited",
97 [2] "icmp unreachable: unassigned error code (2)",
98 [3] "address unreachable",
99 [4] "port unreachable",
100 [5] "icmp unreachable: unknown code"
101 };
102
103 static char *timexcode[] =
104 {
105 [0] "hop limit exc",
106 [1] "reassmbl time exc",
107 [2] "icmp time exc: unknown code"
108 };
109
110 static char *parpcode[] =
111 {
112 [0] "erroneous header field encountered",
113 [1] "unrecognized Next Header type encountered",
114 [2] "unrecognized IPv6 option encountered",
115 [3] "icmp par prob: unknown code"
116 };
117 enum
118 {
119 sll = 1,
120 tll = 2,
121 pref = 3,
122 redir = 4,
123 mtu = 5
124 };
125
126 static char *icmp6opts[256] =
127 {
128 [0] "unknown opt",
129 [1] "sll_addr",
130 [2] "tll_addr",
131 [3] "pref_opt",
132 [4] "redirect",
133 [5] "mtu_opt"
134 };
135
136 static void
137 p_compile(Filter *f)
138 {
139 if(f->op == '='){
140 compile_cmp(icmp6.name, f, p_fields);
141 return;
142 }
143 if(strcmp(f->s, "ip6") == 0){
144 f->pr = p_mux->pr;
145 f->subop = Op;
146 return;
147 }
148 sysfatal("unknown icmp field or protocol: %s", f->s);
149 }
150
151 static int
152 p_filter(Filter *f, Msg *m)
153 {
154 Hdr *h;
155
156 if(m->pe - m->ps < ICMP6LEN)
157 return 0;
158
159 h = (Hdr*)m->ps;
160 m->ps += ICMP6LEN;
161
162 switch(f->subop){
163
164 case Ot:
165 if(h->type == f->ulv)
166 return 1;
167 break;
168 case Op:
169 switch(h->type){
170 case UnreachableV6:
171 case RedirectV6:
172 case TimeExceedV6:
173 m->ps += 4;
174 return 1;
175 }
176 }
177 return 0;
178 }
179
180 static char*
181 opt_seprint(Msg *m)
182 {
183 int otype, osz, pktsz;
184 uchar *a;
185 char *p = m->p;
186 char *e = m->e;
187 char *opt;
188 char optbuf[12];
189
190 pktsz = m->pe - m->ps;
191 a = m->ps;
192 while (pktsz > 0) {
193 otype = *a;
194 opt = icmp6opts[otype];
195 if(opt == nil){
196 sprint(optbuf, "0x%ux", otype);
197 opt = optbuf;
198 }
199 osz = (*(a+1)) * 8;
200
201 switch (otype) {
202 default:
203 p = seprint(p, e, "\n option=%s ", opt);
204 m->pr = &dump;
205 return p;
206
207 case sll:
208 case tll:
209 if ((pktsz < osz) || (osz != 8)) {
210 p = seprint(p, e, "\n option=%s bad size=%d", opt, osz);
211 m->pr = &dump;
212 return p;
213 }
214 p = seprint(p, e, "\n option=%s maddr=%E", opt, a+2);
215 pktsz -= osz;
216 a += osz;
217 break;
218
219 case pref:
220 if ((pktsz < osz) || (osz != 32)) {
221 p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
222 m->pr = &dump;
223 return p;
224 }
225
226 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",
227 opt,
228 a+16,
229 (int) (*(a+2)),
230 (*(a+3) & (1 << 7))!=0,
231 (*(a+3) & (1 << 6))!=0,
232 (*(a+3) & 63) != 0,
233 NetL(a+4),
234 NetL(a+8),
235 NetL(a+12)!=0);
236
237 pktsz -= osz;
238 a += osz;
239 break;
240
241 case redir:
242 if (pktsz < osz) {
243 p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
244 m->pr = &dump;
245 return p;
246 }
247
248 p = seprint(p, e, "\n option=%s len %d", opt, osz);
249 a += osz;
250 m->ps = a;
251 return p;
252 break;
253
254 case mtu:
255 if ((pktsz < osz) || (osz != 8)) {
256 p = seprint(p, e, "\n option=%s: bad size=%d", opt, osz);
257 m->pr = &dump;
258 return p;
259 }
260
261 p = seprint(p, e, "\n option=%s unused=%1.1d mtu=%d", opt, NetL(a+2)!=0, NetL(a+4));
262 pktsz -= osz;
263 a += osz;
264 break;
265 }
266 }
267
268 m->ps = a;
269 return p;
270 }
271
272 static int
273 p_seprint(Msg *m)
274 {
275 Hdr *h;
276 char *tn;
277 char *p = m->p;
278 char *e = m->e;
279 int i;
280 uchar *a;
281 /* ushort cksum2, cksum; */
282
283 h = (Hdr*)m->ps;
284 m->ps += ICMP6LEN;
285 m->pr = &dump;
286 a = m->ps;
287
288 if(m->pe - m->ps < ICMP6LEN)
289 return -1;
290
291 tn = icmpmsg6[h->type];
292 if(tn == nil)
293 p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
294 h->code, (ushort)NetS(h->cksum));
295 else
296 p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
297 h->code, (ushort)NetS(h->cksum));
298
299 /*
300 if(Cflag){
301 cksum = NetS(h->cksum);
302 h->cksum[0] = 0;
303 h->cksum[1] = 0;
304 cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMP6LEN) & 0xffff;
305 if(cksum != cksum2)
306 p = seprint(p,e, " !ck=%4.4ux", cksum2);
307 }
308 */
309
310 switch(h->type){
311
312 case UnreachableV6:
313 m->ps += 4;
314 m->pr = &ip6;
315 if (h->code >= nelem(unreachcode))
316 i = nelem(unreachcode)-1;
317 else
318 i = h->code;
319 p = seprint(p, e, " code=%s unused=%1.1d ", unreachcode[i], NetL(a)!=0);
320 break;
321
322 case PacketTooBigV6:
323 m->ps += 4;
324 m->pr = &ip6;
325 p = seprint(p, e, " mtu=%4.4d ", NetL(a));
326 break;
327
328 case TimeExceedV6:
329 m->ps += 4;
330 m->pr = &ip6;
331 if (h->code >= nelem(timexcode))
332 i = nelem(timexcode)-1;
333 else
334 i = h->code;
335 p = seprint(p, e, " code=%s unused=%1.1d ", timexcode[i], NetL(a)!=0);
336 break;
337
338 case ParamProblemV6:
339 m->ps += 4;
340 m->pr = &ip6;
341 if (h->code > nelem(parpcode))
342 i = nelem(parpcode)-1;
343 else
344 i = h->code;
345 p = seprint(p, e, " code=%s ptr=%2.2ux", parpcode[i], h->data[0]);
346 break;
347
348 case EchoReplyV6:
349 case EchoRequestV6:
350 m->ps += 4;
351 p = seprint(p, e, " id=%ux seq=%ux",
352 NetS(h->data), NetS(h->data+2));
353 break;
354
355 case RouterSolicit:
356 m->ps += 4;
357 m->pr = nil;
358 m->p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
359 p = opt_seprint(m);
360 break;
361
362 case RouterAdvert:
363 m->ps += 12;
364 m->pr = nil;
365 m->p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d unused=%1.1d routerlt=%8.8d reachtime=%d rxmtimer=%d",
366 (int) *a,
367 (*(a+1) & (1 << 7)) != 0,
368 (*(a+1) & (1 << 6)) != 0,
369 (*(a+1) & 63) != 0,
370 NetS(a+2),
371 NetL(a+4),
372 NetL(a+8));
373 p = opt_seprint(m);
374 break;
375
376 case NbrSolicit:
377 m->ps += 20;
378 m->pr = nil;
379 m->p = seprint(p, e, " unused=%1.1d targ %I", NetL(a)!=0, a+4);
380 p = opt_seprint(m);
381 break;
382
383 case NbrAdvert:
384 m->ps += 20;
385 m->pr = nil;
386 m->p = seprint(p, e, " rflag=%1.1d sflag=%1.1d oflag=%1.1d targ=%I",
387 (*a & (1 << 7)) != 0,
388 (*a & (1 << 6)) != 0,
389 (*a & (1 << 5)) != 0,
390 a+4);
391 p = opt_seprint(m);
392 break;
393
394 case RedirectV6:
395 m->ps += 36;
396 m->pr = &ip6;
397 m->p = seprint(p, e, " unused=%1.1d targ=%I dest=%I", NetL(a)!=0, a+4, a+20);
398 p = opt_seprint(m);
399 break;
400
401 case Timestamp:
402 case TimestampReply:
403 m->ps += 12;
404 p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
405 NetL(h->data), NetL(h->data+4),
406 NetL(h->data+8));
407 m->pr = nil;
408 break;
409
410 case InfoRequest:
411 case InfoReply:
412 break;
413
414 }
415 m->p = p;
416 return 0;
417 }
418
419 Proto icmp6 =
420 {
421 "icmp6",
422 p_compile,
423 p_filter,
424 p_seprint,
425 p_mux,
426 "%lud",
427 p_fields,
428 defaultframer
429 };