]> The Tcpdump Group git mirrors - tcpdump/blob - print-dhcp6.c
avoid trigraph
[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.20 2002-06-15 02:49:54 itojun Exp $";
36 #endif
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include <sys/param.h>
43 #include <sys/time.h>
44 #include <sys/socket.h>
45
46 #include <netinet/in.h>
47
48 #include <ctype.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <arpa/inet.h>
52
53 #include "interface.h"
54 #include "addrtoname.h"
55
56 /* lease duration */
57 #define DHCP6_DURATITION_INFINITE 0xffffffff
58
59 /* Error Values */
60 #define DH6ERR_FAILURE 16
61 #define DH6ERR_AUTHFAIL 17
62 #define DH6ERR_POORLYFORMED 18
63 #define DH6ERR_UNAVAIL 19
64 #define DH6ERR_OPTUNAVAIL 20
65
66 /* Message type */
67 #define DH6_SOLICIT 1
68 #define DH6_ADVERTISE 2
69 #define DH6_REQUEST 3
70 #define DH6_CONFIRM 4
71 #define DH6_RENEW 5
72 #define DH6_REBIND 6
73 #define DH6_REPLY 7
74 #define DH6_INFORM_REQ 11
75
76 /* DHCP6 base packet format */
77 struct dhcp6 {
78 union {
79 u_int8_t m;
80 u_int32_t x;
81 } dh6_msgtypexid;
82 /* options follow */
83 } __attribute__ ((__packed__));
84 #define dh6_msgtype dh6_msgtypexid.m
85 #define dh6_xid dh6_msgtypexid.x
86 #define DH6_XIDMASK 0x00ffffff
87
88 /* option */
89 #define DH6OPT_CLIENTID 1
90 #define DH6OPT_SERVERID 2
91 #define DH6OPT_IA 3
92 #define DH6OPT_IA_TMP 4
93 #define DH6OPT_IADDR 5
94 #define DH6OPT_ORO 6
95 #define DH6OPT_PREFERENCE 7
96 # define DH6OPT_PREF_UNDEF -1
97 # define DH6OPT_PREF_MAX 255
98 #define DH6OPT_ELAPSED_TIME 8
99 #define DH6OPT_CLIENT_MSG 9
100 #define DH6OPT_SERVER_MSG 10
101 #define DH6OPT_AUTH 11
102 #define DH6OPT_UNICAST 12
103 #define DH6OPT_STATUS_CODE 13
104 # define DH6OPT_STCODE_SUCCESS 0
105 # define DH6OPT_STCODE_UNSPECFAIL 1
106 # define DH6OPT_STCODE_AUTHFAILED 2
107 # define DH6OPT_STCODE_ADDRUNAVAIL 3
108 # define DH6OPT_STCODE_NOADDRAVAIL 4
109 # define DH6OPT_STCODE_NOBINDING 5
110 # define DH6OPT_STCODE_CONFNOMATCH 6
111 # define DH6OPT_STCODE_NOTONLINK 7
112 # define DH6OPT_STCODE_USEMULTICAST 8
113 #define DH6OPT_RAPID_COMMIT 14
114 #define DH6OPT_USER_CLASS 15
115 #define DH6OPT_VENDOR_CLASS 16
116 #define DH6OPT_VENDOR_OPTS 17
117 #define DH6OPT_INTERFACE_ID 18
118 #define DH6OPT_RECONF_MSG 19
119
120 /*
121 * The option type has not been assigned for the following options.
122 * We temporarily adopt values used in the service specification document
123 * (200206xx version) by NTT Communications.
124 * Note that we'll change the following definitions if different type values
125 * are officially assigned.
126 */
127 #define DH6OPT_DNS 25
128 #define DH6OPT_PREFIX_DELEGATION 30
129 #define DH6OPT_PREFIX_INFORMATION 31
130 #define DH6OPT_PREFIX_REQUEST 32
131
132 struct dhcp6opt {
133 u_int16_t dh6opt_type;
134 u_int16_t dh6opt_len;
135 /* type-dependent data follows */
136 } __attribute__ ((__packed__));
137
138 static char *
139 dhcp6opt_name(int type)
140 {
141 static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
142
143 if (type > 65535)
144 return "INVALID option";
145
146 switch(type) {
147 case DH6OPT_CLIENTID:
148 return "client ID";
149 case DH6OPT_SERVERID:
150 return "server ID";
151 case DH6OPT_ORO:
152 return "option request";
153 case DH6OPT_PREFERENCE:
154 return "preference";
155 case DH6OPT_STATUS_CODE:
156 return "status code";
157 case DH6OPT_RAPID_COMMIT:
158 return "rapid commit";
159 case DH6OPT_DNS:
160 return "DNS";
161 case DH6OPT_PREFIX_DELEGATION:
162 return "prefix delegation";
163 case DH6OPT_PREFIX_INFORMATION:
164 return "prefix information";
165 default:
166 sprintf(genstr, "opt_%d", type);
167 return(genstr);
168 }
169 }
170
171 static char *
172 dhcp6stcode(int code)
173 {
174 static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
175
176 if (code > 255)
177 return "INVALID code";
178
179 switch(code) {
180 case DH6OPT_STCODE_SUCCESS:
181 return "success";
182 case DH6OPT_STCODE_UNSPECFAIL:
183 return "unspec failure";
184 case DH6OPT_STCODE_AUTHFAILED:
185 return "auth fail";
186 case DH6OPT_STCODE_ADDRUNAVAIL:
187 return "address unavailable";
188 case DH6OPT_STCODE_NOADDRAVAIL:
189 return "no addresses";
190 case DH6OPT_STCODE_NOBINDING:
191 return "no binding";
192 case DH6OPT_STCODE_CONFNOMATCH:
193 return "confirm no match";
194 case DH6OPT_STCODE_NOTONLINK:
195 return "not on-link";
196 case DH6OPT_STCODE_USEMULTICAST:
197 return "use multicast";
198 default:
199 sprintf(genstr, "code%d", code);
200 return(genstr);
201 }
202 }
203
204 static void
205 dhcp6opt_print(u_char *cp, u_char *ep)
206 {
207 struct dhcp6opt *dh6o;
208 u_char *tp;
209 int i, opttype;
210 size_t optlen;
211 u_int16_t val16;
212 u_int32_t val32;
213 struct in6_addr addr6;
214
215 if (cp == ep)
216 return;
217 while (cp < ep) {
218 if (ep - cp < sizeof(*dh6o))
219 goto trunc;
220 dh6o = (struct dhcp6opt *)cp;
221 optlen = ntohs(dh6o->dh6opt_len);
222 if (ep - cp < sizeof(*dh6o) + optlen)
223 goto trunc;
224 opttype = ntohs(dh6o->dh6opt_type);
225 printf(" (%s", dhcp6opt_name(opttype));
226 switch (opttype) {
227 case DH6OPT_CLIENTID:
228 case DH6OPT_SERVERID:
229 if (optlen < 2) {
230 /*(*/
231 printf(" ?)");
232 break;
233 }
234 tp = (u_char *)(dh6o + 1);
235 switch (ntohs(*(u_int16_t *)tp)) {
236 case 1:
237 if (optlen >= 2 + 6) {
238 printf(" hwaddr/time type %u time %u ",
239 ntohs(*(u_int16_t *)&tp[2]),
240 ntohl(*(u_int32_t *)&tp[4]));
241 for (i = 8; i < optlen; i++)
242 printf("%02x", tp[i]);
243 /*(*/
244 printf(")");
245 } else {
246 /*(*/
247 printf(" ?)");
248 }
249 break;
250 case 2:
251 if (optlen >= 2 + 8) {
252 printf(" vid ");
253 for (i = 2; i < 2 + 8; i++)
254 printf("%02x", tp[i]);
255 /*(*/
256 printf(")");
257 } else {
258 /*(*/
259 printf(" ?)");
260 }
261 break;
262 case 3:
263 if (optlen >= 2 + 2) {
264 printf(" hwaddr type %u ",
265 ntohs(*(u_int16_t *)&tp[2]));
266 for (i = 4; i < optlen; i++)
267 printf("%02x", tp[i]);
268 /*(*/
269 printf(")");
270 } else {
271 /*(*/
272 printf(" ?)");
273 }
274 break;
275 default:
276 printf(" type %d)", ntohs(*(u_int16_t *)tp));
277 break;
278 }
279 break;
280 case DH6OPT_ORO:
281 if (optlen % 2) {
282 printf(" ?)");
283 break;
284 }
285 tp = (u_char *)(dh6o + 1);
286 for (i = 0; i < optlen; i += 2) {
287 u_int16_t opt;
288
289 memcpy(&opt, &tp[i], sizeof(opt));
290 printf(" %s", dhcp6opt_name(ntohs(opt)));
291 }
292 printf(")");
293 break;
294 case DH6OPT_PREFERENCE:
295 if (optlen != 1) {
296 printf(" ?)");
297 break;
298 }
299 printf(" %d)", *((u_char *)(dh6o + 1) + 1));
300 break;
301 case DH6OPT_RAPID_COMMIT: /* nothing todo */
302 printf(")");
303 break;
304 case DH6OPT_DNS:
305 if (optlen % 16) {
306 printf(" ?)");
307 break;
308 }
309 tp = (u_char *)(dh6o + 1);
310 for (i = 0; i < optlen; i += 16)
311 printf(" %s", ip6addr_string(&tp[i]));
312 printf(")");
313 break;
314 case DH6OPT_PREFIX_DELEGATION:
315 dhcp6opt_print((u_char *)(dh6o + 1),
316 (u_char *)(dh6o + 1) + optlen);
317 printf(")");
318 break;
319 case DH6OPT_PREFIX_INFORMATION:
320 if (optlen % 21)
321 printf(" ?)");
322 memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
323 sizeof(addr6));
324 printf(" %s/%d", ip6addr_string(&addr6),
325 (int)*((u_char *)(dh6o + 1) + 4));
326 memcpy(&val32, dh6o + 1, sizeof(val32));
327 val32 = ntohl(val32);
328 if (val32 == DHCP6_DURATITION_INFINITE)
329 printf(" lease-duration: infinite)");
330 else
331 printf(" lease-duration: %u)", val32);
332 break;
333 case DH6OPT_STATUS_CODE:
334 if (optlen < 2)
335 printf(" ?)");
336 memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
337 val16 = ntohs(val16);
338 printf(" %s)", dhcp6stcode(val16));
339 break;
340 default:
341 printf(")", ntohs(dh6o->dh6opt_type));
342 break;
343 }
344
345 cp += sizeof(*dh6o) + optlen;
346 }
347 return;
348
349 trunc:
350 printf("[|dhcp6ext]");
351 }
352
353 /*
354 * Print dhcp6 packets
355 */
356 void
357 dhcp6_print(register const u_char *cp, u_int length,
358 u_int16_t sport, u_int16_t dport)
359 {
360 struct dhcp6 *dh6;
361 u_char *ep;
362 u_char *extp;
363 const char *name;
364
365 printf("dhcp6");
366
367 ep = (u_char *)snapend;
368
369 dh6 = (struct dhcp6 *)cp;
370 TCHECK(dh6->dh6_xid);
371 switch (dh6->dh6_msgtype) {
372 case DH6_SOLICIT:
373 name = "solicit";
374 break;
375 case DH6_ADVERTISE:
376 name = "advertise";
377 break;
378 case DH6_REQUEST:
379 name = "request";
380 break;
381 case DH6_CONFIRM:
382 name = "confirm";
383 break;
384 case DH6_RENEW:
385 name = "renew";
386 break;
387 case DH6_REBIND:
388 name = "rebind";
389 break;
390 case DH6_REPLY:
391 name = "reply";
392 break;
393 case DH6_INFORM_REQ:
394 name= "inf-req";
395 break;
396 default:
397 name = NULL;
398 break;
399 }
400
401 if (!vflag) {
402 if (name)
403 printf(" %s", name);
404 else
405 printf(" msgtype-%u", dh6->dh6_msgtype);
406 return;
407 }
408
409 /* XXX relay agent messages have to be handled differently */
410
411 if (name)
412 printf(" %s (", name); /*)*/
413 else
414 printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/
415 printf("xid=%x", ntohl(dh6->dh6_xid) & DH6_XIDMASK);
416 extp = (u_char *)(dh6 + 1);
417 dhcp6opt_print(extp, ep);
418 /*(*/
419 printf(")");
420 return;
421
422 trunc:
423 printf("[|dhcp6]");
424 }