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