]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
verify/warn icmpv6 checksum. from jinmei@kame
[tcpdump] / print-dhcp6.c
1 /*
2 * Copyright (C) 1998 and 1999 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 /*
30 * draft-ietf-dhc-dhcpv6-26.txt
31 */
32
33 #ifndef lint
34 static const char rcsid[] =
35 "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.24 2002-12-11 22:29:21 guy Exp $";
36 #endif
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include <tcpdump-stdinc.h>
43
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h"
50
51 /* lease duration */
52 #define DHCP6_DURATITION_INFINITE 0xffffffff
53
54 /* Error Values */
55 #define DH6ERR_FAILURE 16
56 #define DH6ERR_AUTHFAIL 17
57 #define DH6ERR_POORLYFORMED 18
58 #define DH6ERR_UNAVAIL 19
59 #define DH6ERR_OPTUNAVAIL 20
60
61 /* Message type */
62 #define DH6_SOLICIT 1
63 #define DH6_ADVERTISE 2
64 #define DH6_REQUEST 3
65 #define DH6_CONFIRM 4
66 #define DH6_RENEW 5
67 #define DH6_REBIND 6
68 #define DH6_REPLY 7
69 #define DH6_INFORM_REQ 11
70
71 /* DHCP6 base packet format */
72 struct dhcp6 {
73 union {
74 u_int8_t m;
75 u_int32_t x;
76 } dh6_msgtypexid;
77 /* options follow */
78 };
79 #define dh6_msgtype dh6_msgtypexid.m
80 #define dh6_xid dh6_msgtypexid.x
81 #define DH6_XIDMASK 0x00ffffff
82
83 /* option */
84 #define DH6OPT_CLIENTID 1
85 #define DH6OPT_SERVERID 2
86 #define DH6OPT_IA 3
87 #define DH6OPT_IA_TMP 4
88 #define DH6OPT_IADDR 5
89 #define DH6OPT_ORO 6
90 #define DH6OPT_PREFERENCE 7
91 # define DH6OPT_PREF_UNDEF -1
92 # define DH6OPT_PREF_MAX 255
93 #define DH6OPT_ELAPSED_TIME 8
94 #define DH6OPT_CLIENT_MSG 9
95 #define DH6OPT_SERVER_MSG 10
96 #define DH6OPT_AUTH 11
97 #define DH6OPT_UNICAST 12
98 #define DH6OPT_STATUS_CODE 13
99 # define DH6OPT_STCODE_SUCCESS 0
100 # define DH6OPT_STCODE_UNSPECFAIL 1
101 # define DH6OPT_STCODE_AUTHFAILED 2
102 # define DH6OPT_STCODE_ADDRUNAVAIL 3
103 # define DH6OPT_STCODE_NOADDRAVAIL 4
104 # define DH6OPT_STCODE_NOBINDING 5
105 # define DH6OPT_STCODE_CONFNOMATCH 6
106 # define DH6OPT_STCODE_NOTONLINK 7
107 # define DH6OPT_STCODE_USEMULTICAST 8
108 #define DH6OPT_RAPID_COMMIT 14
109 #define DH6OPT_USER_CLASS 15
110 #define DH6OPT_VENDOR_CLASS 16
111 #define DH6OPT_VENDOR_OPTS 17
112 #define DH6OPT_INTERFACE_ID 18
113 #define DH6OPT_RECONF_MSG 19
114
115 /*
116 * The option type has not been assigned for the following options.
117 * We temporarily adopt values used in the service specification document
118 * (200206xx version) by NTT Communications.
119 * Note that we'll change the following definitions if different type values
120 * are officially assigned.
121 */
122 #define DH6OPT_DNS 25
123 #define DH6OPT_PREFIX_DELEGATION 30
124 #define DH6OPT_PREFIX_INFORMATION 31
125 #define DH6OPT_PREFIX_REQUEST 32
126
127 struct dhcp6opt {
128 u_int16_t dh6opt_type;
129 u_int16_t dh6opt_len;
130 /* type-dependent data follows */
131 };
132
133 static const char *
134 dhcp6opt_name(int type)
135 {
136 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
137
138 if (type > 65535)
139 return "INVALID option";
140
141 switch(type) {
142 case DH6OPT_CLIENTID:
143 return "client ID";
144 case DH6OPT_SERVERID:
145 return "server ID";
146 case DH6OPT_ORO:
147 return "option request";
148 case DH6OPT_PREFERENCE:
149 return "preference";
150 case DH6OPT_STATUS_CODE:
151 return "status code";
152 case DH6OPT_RAPID_COMMIT:
153 return "rapid commit";
154 case DH6OPT_DNS:
155 return "DNS";
156 case DH6OPT_PREFIX_DELEGATION:
157 return "prefix delegation";
158 case DH6OPT_PREFIX_INFORMATION:
159 return "prefix information";
160 default:
161 sprintf(genstr, "opt_%d", type);
162 return(genstr);
163 }
164 }
165
166 static const char *
167 dhcp6stcode(int code)
168 {
169 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
170
171 if (code > 255)
172 return "INVALID code";
173
174 switch(code) {
175 case DH6OPT_STCODE_SUCCESS:
176 return "success";
177 case DH6OPT_STCODE_UNSPECFAIL:
178 return "unspec failure";
179 case DH6OPT_STCODE_AUTHFAILED:
180 return "auth fail";
181 case DH6OPT_STCODE_ADDRUNAVAIL:
182 return "address unavailable";
183 case DH6OPT_STCODE_NOADDRAVAIL:
184 return "no addresses";
185 case DH6OPT_STCODE_NOBINDING:
186 return "no binding";
187 case DH6OPT_STCODE_CONFNOMATCH:
188 return "confirm no match";
189 case DH6OPT_STCODE_NOTONLINK:
190 return "not on-link";
191 case DH6OPT_STCODE_USEMULTICAST:
192 return "use multicast";
193 default:
194 sprintf(genstr, "code%d", code);
195 return(genstr);
196 }
197 }
198
199 static void
200 dhcp6opt_print(u_char *cp, u_char *ep)
201 {
202 struct dhcp6opt *dh6o;
203 u_char *tp;
204 size_t i;
205 u_int16_t opttype;
206 size_t optlen;
207 u_int16_t val16;
208 u_int32_t val32;
209 struct in6_addr addr6;
210
211 if (cp == ep)
212 return;
213 while (cp < ep) {
214 if (ep < cp + sizeof(*dh6o))
215 goto trunc;
216 dh6o = (struct dhcp6opt *)cp;
217 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
218 if (ep < cp + sizeof(*dh6o) + optlen)
219 goto trunc;
220 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
221 printf(" (%s", dhcp6opt_name(opttype));
222 switch (opttype) {
223 case DH6OPT_CLIENTID:
224 case DH6OPT_SERVERID:
225 if (optlen < 2) {
226 /*(*/
227 printf(" ?)");
228 break;
229 }
230 tp = (u_char *)(dh6o + 1);
231 switch (EXTRACT_16BITS(tp)) {
232 case 1:
233 if (optlen >= 2 + 6) {
234 printf(" hwaddr/time type %u time %u ",
235 EXTRACT_16BITS(&tp[2]),
236 EXTRACT_32BITS(&tp[4]));
237 for (i = 8; i < optlen; i++)
238 printf("%02x", tp[i]);
239 /*(*/
240 printf(")");
241 } else {
242 /*(*/
243 printf(" ?)");
244 }
245 break;
246 case 2:
247 if (optlen >= 2 + 8) {
248 printf(" vid ");
249 for (i = 2; i < 2 + 8; i++)
250 printf("%02x", tp[i]);
251 /*(*/
252 printf(")");
253 } else {
254 /*(*/
255 printf(" ?)");
256 }
257 break;
258 case 3:
259 if (optlen >= 2 + 2) {
260 printf(" hwaddr type %u ",
261 EXTRACT_16BITS(&tp[2]));
262 for (i = 4; i < optlen; i++)
263 printf("%02x", tp[i]);
264 /*(*/
265 printf(")");
266 } else {
267 /*(*/
268 printf(" ?)");
269 }
270 break;
271 default:
272 printf(" type %d)", EXTRACT_16BITS(tp));
273 break;
274 }
275 break;
276 case DH6OPT_ORO:
277 if (optlen % 2) {
278 printf(" ?)");
279 break;
280 }
281 tp = (u_char *)(dh6o + 1);
282 for (i = 0; i < optlen; i += 2) {
283 u_int16_t opt;
284
285 memcpy(&opt, &tp[i], sizeof(opt));
286 printf(" %s", dhcp6opt_name(ntohs(opt)));
287 }
288 printf(")");
289 break;
290 case DH6OPT_PREFERENCE:
291 if (optlen != 1) {
292 printf(" ?)");
293 break;
294 }
295 printf(" %d)", *((u_char *)(dh6o + 1) + 1));
296 break;
297 case DH6OPT_RAPID_COMMIT: /* nothing todo */
298 printf(")");
299 break;
300 case DH6OPT_DNS:
301 if (optlen % 16) {
302 printf(" ?)");
303 break;
304 }
305 tp = (u_char *)(dh6o + 1);
306 for (i = 0; i < optlen; i += 16)
307 printf(" %s", ip6addr_string(&tp[i]));
308 printf(")");
309 break;
310 case DH6OPT_PREFIX_DELEGATION:
311 dhcp6opt_print((u_char *)(dh6o + 1),
312 (u_char *)(dh6o + 1) + optlen);
313 printf(")");
314 break;
315 case DH6OPT_PREFIX_INFORMATION:
316 if (optlen % 21)
317 printf(" ?)");
318 memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
319 sizeof(addr6));
320 printf(" %s/%d", ip6addr_string(&addr6),
321 (int)*((u_char *)(dh6o + 1) + 4));
322 memcpy(&val32, dh6o + 1, sizeof(val32));
323 val32 = ntohl(val32);
324 if (val32 == DHCP6_DURATITION_INFINITE)
325 printf(" lease-duration: infinite)");
326 else
327 printf(" lease-duration: %u)", val32);
328 break;
329 case DH6OPT_STATUS_CODE:
330 if (optlen < 2)
331 printf(" ?)");
332 memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
333 val16 = ntohs(val16);
334 printf(" %s)", dhcp6stcode(val16));
335 break;
336 default:
337 printf(")");
338 break;
339 }
340
341 cp += sizeof(*dh6o) + optlen;
342 }
343 return;
344
345 trunc:
346 printf("[|dhcp6ext]");
347 }
348
349 /*
350 * Print dhcp6 packets
351 */
352 void
353 dhcp6_print(register const u_char *cp, u_int length,
354 u_int16_t sport, u_int16_t dport)
355 {
356 struct dhcp6 *dh6;
357 u_char *ep;
358 u_char *extp;
359 const char *name;
360
361 printf("dhcp6");
362
363 ep = (u_char *)snapend;
364
365 dh6 = (struct dhcp6 *)cp;
366 TCHECK(dh6->dh6_xid);
367 switch (dh6->dh6_msgtype) {
368 case DH6_SOLICIT:
369 name = "solicit";
370 break;
371 case DH6_ADVERTISE:
372 name = "advertise";
373 break;
374 case DH6_REQUEST:
375 name = "request";
376 break;
377 case DH6_CONFIRM:
378 name = "confirm";
379 break;
380 case DH6_RENEW:
381 name = "renew";
382 break;
383 case DH6_REBIND:
384 name = "rebind";
385 break;
386 case DH6_REPLY:
387 name = "reply";
388 break;
389 case DH6_INFORM_REQ:
390 name= "inf-req";
391 break;
392 default:
393 name = NULL;
394 break;
395 }
396
397 if (!vflag) {
398 if (name)
399 printf(" %s", name);
400 else
401 printf(" msgtype-%u", dh6->dh6_msgtype);
402 return;
403 }
404
405 /* XXX relay agent messages have to be handled differently */
406
407 if (name)
408 printf(" %s (", name); /*)*/
409 else
410 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/
411 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
412 extp = (u_char *)(dh6 + 1);
413 dhcp6opt_print(extp, ep);
414 /*(*/
415 printf(")");
416 return;
417
418 trunc:
419 printf("[|dhcp6]");
420 }