add the 'y' and 'Y' options to ps, and add the 'iac' keyword. The 'y'
[dragonfly.git] / contrib / tcpdump-3.8.3 / 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  * RFC3315: DHCPv6
31  * supported DHCPv6 options: 
32  *  RFC3319,
33  *  draft-ietf-dhc-dhcpv6-opt-dnsconfig-04.txt,
34  *  draft-ietf-dhc-dhcpv6-opt-prefix-delegation-05.txt
35  *  draft-ietf-dhc-dhcpv6-opt-timeconfig-02.txt,
36  */
37
38 #ifndef lint
39 static const char rcsid[] _U_ =
40     "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.27.2.4 2003/11/18 23:26:14 guy Exp $";
41 #endif
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include <tcpdump-stdinc.h>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #include "interface.h"
53 #include "addrtoname.h"
54 #include "extract.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_RELEASE     8
75 #define DH6_DECLINE     9
76 #define DH6_RECONFIGURE 10
77 #define DH6_INFORM_REQ  11
78 #define DH6_RELAY_FORW  12
79 #define DH6_RELAY_REPLY 13
80
81 /* DHCP6 base packet format */
82 struct dhcp6 {
83         union {
84                 u_int8_t m;
85                 u_int32_t x;
86         } dh6_msgtypexid;
87         /* options follow */
88 };
89 #define dh6_msgtype     dh6_msgtypexid.m
90 #define dh6_xid         dh6_msgtypexid.x
91 #define DH6_XIDMASK     0x00ffffff
92
93 /* DHCPv6 relay messages */
94 struct dhcp6_relay {
95         u_int8_t dh6relay_msgtype;
96         u_int8_t dh6relay_hcnt;
97         u_int8_t dh6relay_linkaddr[16]; /* XXX: badly aligned */
98         u_int8_t dh6relay_peeraddr[16];
99         /* options follow */
100 };
101
102 /* options */
103 #define DH6OPT_CLIENTID 1
104 #define DH6OPT_SERVERID 2
105 #define DH6OPT_IA_NA 3
106 #define DH6OPT_IA_TMP 4
107 #define DH6OPT_IADDR 5
108 #define DH6OPT_ORO 6
109 #define DH6OPT_PREFERENCE 7
110 #  define DH6OPT_PREF_UNDEF -1
111 #  define DH6OPT_PREF_MAX 255
112 #define DH6OPT_ELAPSED_TIME 8
113 #define DH6OPT_RELAY_MSG 9
114 /*#define DH6OPT_SERVER_MSG 10 deprecated */
115 #define DH6OPT_AUTH 11
116 #define DH6OPT_UNICAST 12
117 #define DH6OPT_STATUS_CODE 13
118 #  define DH6OPT_STCODE_SUCCESS 0
119 #  define DH6OPT_STCODE_UNSPECFAIL 1
120 #  define DH6OPT_STCODE_NOADDRAVAIL 2
121 #  define DH6OPT_STCODE_NOBINDING 3
122 #  define DH6OPT_STCODE_NOTONLINK 4
123 #  define DH6OPT_STCODE_USEMULTICAST 5
124 #  define DH6OPT_STCODE_NOPREFIXAVAIL 6
125 #define DH6OPT_RAPID_COMMIT 14
126 #define DH6OPT_USER_CLASS 15
127 #define DH6OPT_VENDOR_CLASS 16
128 #define DH6OPT_VENDOR_OPTS 17
129 #define DH6OPT_INTERFACE_ID 18
130 #define DH6OPT_RECONF_MSG 19
131 #define DH6OPT_RECONF_ACCEPT 20
132 #define DH6OPT_SIP_SERVER_D 21
133 #define DH6OPT_SIP_SERVER_A 22
134 #define DH6OPT_DNS 23
135 #define DH6OPT_DNSNAME 24
136
137 /*
138  * The option type has not been assigned for the following options.
139  * We temporarily adopt values used in the service specification document
140  * (200206xx version) by NTT Communications.
141  * Note that we'll change the following definitions if different type values
142  * are officially assigned.
143  */
144 #define DH6OPT_PREFIX_DELEGATION 30
145 #define DH6OPT_PREFIX_INFORMATION 31
146 #define DH6OPT_PREFIX_REQUEST 32
147
148 /*
149  * The followings are also unassigned numbers.
150  * We temporarily use values as of KAME snap 20031013.
151  */
152 #define DH6OPT_IA_PD 33
153 #define DH6OPT_IA_PD_PREFIX 34
154 #define DH6OPT_NTP_SERVERS 35
155
156 struct dhcp6opt {
157         u_int16_t dh6opt_type;
158         u_int16_t dh6opt_len;
159         /* type-dependent data follows */
160 };
161
162 struct dhcp6_ia {
163         u_int16_t dh6opt_ia_type;
164         u_int16_t dh6opt_ia_len;
165         u_int32_t dh6opt_ia_iaid;
166         u_int32_t dh6opt_ia_t1;
167         u_int32_t dh6opt_ia_t2;
168 };
169
170 struct dhcp6_ia_prefix {
171         u_int16_t dh6opt_ia_prefix_type;
172         u_int16_t dh6opt_ia_prefix_len;
173         u_int32_t dh6opt_ia_prefix_pltime;
174         u_int32_t dh6opt_ia_prefix_vltime;
175         u_int8_t dh6opt_ia_prefix_plen;
176         struct in6_addr dh6opt_ia_prefix_addr;
177 }  __attribute__ ((__packed__));
178
179 static const char *
180 dhcp6opt_name(int type)
181 {
182         static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
183
184         if (type > 65535)
185                 return "INVALID option";
186
187         switch(type) {
188         case DH6OPT_CLIENTID:
189                 return "client ID";
190         case DH6OPT_SERVERID:
191                 return "server ID";
192         case DH6OPT_IA_NA:
193                 return "IA_NA";
194         case DH6OPT_ORO:
195                 return "option request";
196         case DH6OPT_PREFERENCE:
197                 return "preference";
198         case DH6OPT_ELAPSED_TIME:
199                 return "elapsed time";
200         case DH6OPT_RELAY_MSG:
201                 return "relay message";
202         case DH6OPT_STATUS_CODE:
203                 return "status code";
204         case DH6OPT_RAPID_COMMIT:
205                 return "rapid commit";
206         case DH6OPT_INTERFACE_ID:
207                 return "interface ID";
208         case DH6OPT_RECONF_MSG:
209                 return "reconfigure message";
210         case DH6OPT_RECONF_ACCEPT:
211                 return "reconfigure accept";
212         case DH6OPT_SIP_SERVER_D:
213                 return "SIP Servers Domain";
214         case DH6OPT_SIP_SERVER_A:
215                 return "SIP Servers Address";
216         case DH6OPT_DNS:
217                 return "DNS";
218         case DH6OPT_PREFIX_DELEGATION:
219                 return "prefix delegation";
220         case DH6OPT_PREFIX_INFORMATION:
221                 return "prefix information";
222         case DH6OPT_IA_PD:
223                 return "IA_PD";
224         case DH6OPT_IA_PD_PREFIX:
225                 return "IA_PD prefix";
226         case DH6OPT_NTP_SERVERS:
227                 return "NTP Server";
228         default:
229                 snprintf(genstr, sizeof(genstr), "opt_%d", type);
230                 return(genstr);
231         }
232 }
233
234 static const char *
235 dhcp6stcode(int code)
236 {
237         static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
238
239         if (code > 255)
240                 return "INVALID code";
241
242         switch(code) {
243         case DH6OPT_STCODE_SUCCESS:
244                 return "success";
245         case DH6OPT_STCODE_UNSPECFAIL:
246                 return "unspec failure";
247         case DH6OPT_STCODE_NOADDRAVAIL:
248                 return "no addresses";
249         case DH6OPT_STCODE_NOBINDING:
250                 return "no binding";
251         case DH6OPT_STCODE_NOTONLINK:
252                 return "not on-link";
253         case DH6OPT_STCODE_USEMULTICAST:
254                 return "use multicast";
255         case DH6OPT_STCODE_NOPREFIXAVAIL:
256                 return "no prefixes";
257         default:
258                 snprintf(genstr, sizeof(genstr), "code%d", code);
259                 return(genstr);
260         }
261 }
262
263 static void
264 dhcp6opt_print(const u_char *cp, const u_char *ep)
265 {
266         struct dhcp6opt *dh6o;
267         u_char *tp;
268         size_t i;
269         u_int16_t opttype;
270         size_t optlen;
271         u_int16_t val16;
272         u_int32_t val32;
273         struct in6_addr addr6;
274         struct dhcp6_ia ia;
275         struct dhcp6_ia_prefix ia_prefix;
276
277         if (cp == ep)
278                 return;
279         while (cp < ep) {
280                 if (ep < cp + sizeof(*dh6o))
281                         goto trunc;
282                 dh6o = (struct dhcp6opt *)cp;
283                 optlen = EXTRACT_16BITS(&dh6o->dh6opt_len);
284                 if (ep < cp + sizeof(*dh6o) + optlen)
285                         goto trunc;
286                 opttype = EXTRACT_16BITS(&dh6o->dh6opt_type);
287                 printf(" (%s", dhcp6opt_name(opttype));
288                 switch (opttype) {
289                 case DH6OPT_CLIENTID:
290                 case DH6OPT_SERVERID:
291                         if (optlen < 2) {
292                                 /*(*/
293                                 printf(" ?)");
294                                 break;
295                         }
296                         tp = (u_char *)(dh6o + 1);
297                         switch (EXTRACT_16BITS(tp)) {
298                         case 1:
299                                 if (optlen >= 2 + 6) {
300                                         printf(" hwaddr/time type %u time %u ",
301                                             EXTRACT_16BITS(&tp[2]),
302                                             EXTRACT_32BITS(&tp[4]));
303                                         for (i = 8; i < optlen; i++)
304                                                 printf("%02x", tp[i]);
305                                         /*(*/
306                                         printf(")");
307                                 } else {
308                                         /*(*/
309                                         printf(" ?)");
310                                 }
311                                 break;
312                         case 2:
313                                 if (optlen >= 2 + 8) {
314                                         printf(" vid ");
315                                         for (i = 2; i < 2 + 8; i++)
316                                                 printf("%02x", tp[i]);
317                                         /*(*/
318                                         printf(")");
319                                 } else {
320                                         /*(*/
321                                         printf(" ?)");
322                                 }
323                                 break;
324                         case 3:
325                                 if (optlen >= 2 + 2) {
326                                         printf(" hwaddr type %u ",
327                                             EXTRACT_16BITS(&tp[2]));
328                                         for (i = 4; i < optlen; i++)
329                                                 printf("%02x", tp[i]);
330                                         /*(*/
331                                         printf(")");
332                                 } else {
333                                         /*(*/
334                                         printf(" ?)");
335                                 }
336                                 break;
337                         default:
338                                 printf(" type %d)", EXTRACT_16BITS(tp));
339                                 break;
340                         }
341                         break;
342                 case DH6OPT_ORO:
343                         if (optlen % 2) {
344                                 printf(" ?)");
345                                 break;
346                         }
347                         tp = (u_char *)(dh6o + 1);
348                         for (i = 0; i < optlen; i += 2) {
349                                 u_int16_t opt;
350
351                                 memcpy(&opt, &tp[i], sizeof(opt));
352                                 printf(" %s", dhcp6opt_name(ntohs(opt)));
353                         }
354                         printf(")");
355                         break;
356                 case DH6OPT_PREFERENCE:
357                         if (optlen != 1) {
358                                 printf(" ?)");
359                                 break;
360                         }
361                         printf(" %d)", *((u_char *)(dh6o + 1) + 1));
362                         break;
363                 case DH6OPT_ELAPSED_TIME:
364                         if (optlen != 2) {
365                                 printf(" ?)");
366                                 break;
367                         }
368                         memcpy(&val16, dh6o + 1, sizeof(val16));
369                         val16 = ntohs(val16);
370                         printf(" %d)", (int)val16);
371                         break;
372                 case DH6OPT_RELAY_MSG:
373                         printf(" (");
374                         dhcp6_print((const u_char *)(dh6o + 1), optlen);
375                         printf(")");
376                         break;
377                 case DH6OPT_RAPID_COMMIT: /* nothing todo */
378                         printf(")");
379                         break;
380                 case DH6OPT_INTERFACE_ID:
381                         /*
382                          * Since we cannot predict the encoding, print hex dump
383                          * at most 10 characters.
384                          */
385                         for (i = 0; i < optlen && i < 10; i++)
386                                 printf("%02x", ((u_char *)(dh6o + 1))[i]);
387                         break;
388                 case DH6OPT_RECONF_MSG:
389                         tp = (u_char *)(dh6o + 1);
390                         switch (*tp) {
391                         case DH6_RENEW:
392                                 printf(" for renew)");
393                                 break;
394                         case DH6_INFORM_REQ:
395                                 printf(" for inf-req)");
396                                 break;
397                         default:
398                                 printf(" for ?\?\?(%02x))", *tp);
399                                 break;
400                         }
401                         break;
402                 case DH6OPT_RECONF_ACCEPT: /* nothing todo */
403                         printf(")");
404                         break;
405                 case DH6OPT_SIP_SERVER_A:
406                 case DH6OPT_DNS:
407                 case DH6OPT_NTP_SERVERS:
408                         if (optlen % 16) {
409                                 printf(" ?)");
410                                 break;
411                         }
412                         tp = (u_char *)(dh6o + 1);
413                         for (i = 0; i < optlen; i += 16)
414                                 printf(" %s", ip6addr_string(&tp[i]));
415                         printf(")");
416                         break;
417                 case DH6OPT_PREFIX_DELEGATION:
418                         dhcp6opt_print((u_char *)(dh6o + 1),
419                             (u_char *)(dh6o + 1) + optlen);
420                         printf(")");
421                         break;
422                 case DH6OPT_PREFIX_INFORMATION:
423                         if (optlen % 21)
424                                 printf(" ?)");
425                         memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
426                             sizeof(addr6));
427                         printf(" %s/%d", ip6addr_string(&addr6),
428                             (int)*((u_char *)(dh6o + 1) + 4));
429                         memcpy(&val32, dh6o + 1, sizeof(val32));
430                         val32 = ntohl(val32);
431                         if (val32 == DHCP6_DURATITION_INFINITE)
432                                 printf(" lease-duration: infinite)");
433                         else
434                                 printf(" lease-duration: %u)", val32);
435                         break;
436                 case DH6OPT_STATUS_CODE:
437                         if (optlen < 2) {
438                                 printf(" ?)");
439                                 break;
440                         }
441                         memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
442                         val16 = ntohs(val16);
443                         printf(" %s)", dhcp6stcode(val16));
444                         break;
445                 case DH6OPT_IA_NA:
446                 case DH6OPT_IA_PD:
447                         if (optlen < sizeof(ia) - 4) {
448                                 printf(" ?)");
449                                 break;
450                         }
451                         memcpy(&ia, (u_char *)dh6o, sizeof(ia));
452                         ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid);
453                         ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1);
454                         ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2);
455                         printf(" IAID:%lu T1:%lu T2:%lu",
456                             (unsigned long)ia.dh6opt_ia_iaid,
457                             (unsigned long)ia.dh6opt_ia_t1,
458                             (unsigned long)ia.dh6opt_ia_t2);
459                         if (optlen > sizeof(ia) - 4) {
460                                 /* there are sub-options */
461                                 dhcp6opt_print((u_char *)dh6o + sizeof(ia),
462                                     (u_char *)(dh6o + 1) + optlen);
463                         }
464                         printf(")");
465                         break;
466                 case DH6OPT_IA_PD_PREFIX:
467                         if (optlen < sizeof(ia_prefix) - 4) {
468                                 printf(" ?)");
469                                 break;
470                         }
471                         memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix));
472                         printf(" %s/%d",
473                             ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr),
474                             ia_prefix.dh6opt_ia_prefix_plen);
475                         ia_prefix.dh6opt_ia_prefix_pltime =
476                             ntohl(ia_prefix.dh6opt_ia_prefix_pltime);
477                         ia_prefix.dh6opt_ia_prefix_vltime =
478                             ntohl(ia_prefix.dh6opt_ia_prefix_vltime);
479                         printf(" pltime:%lu vltime:%lu",
480                             (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime,
481                             (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime);
482                         if (optlen > sizeof(ia_prefix) - 4) {
483                                 /* there are sub-options */
484                                 dhcp6opt_print((u_char *)dh6o +
485                                     sizeof(ia_prefix),
486                                     (u_char *)(dh6o + 1) + optlen);
487                         }
488                         printf(")");
489                         break;
490                 default:
491                         printf(")");
492                         break;
493                 }
494
495                 cp += sizeof(*dh6o) + optlen;
496         }
497         return;
498
499 trunc:
500         printf("[|dhcp6ext]");
501 }
502
503 /*
504  * Print dhcp6 packets
505  */
506 void
507 dhcp6_print(const u_char *cp, u_int length)
508 {
509         struct dhcp6 *dh6;
510         struct dhcp6_relay *dh6relay;
511         const u_char *ep;
512         u_char *extp;
513         const char *name;
514
515         printf("dhcp6");
516
517         ep = (u_char *)snapend;
518         if (cp + length < ep)
519                 ep = cp + length;
520
521         dh6 = (struct dhcp6 *)cp;
522         dh6relay = (struct dhcp6_relay *)cp;
523         TCHECK(dh6->dh6_xid);
524         switch (dh6->dh6_msgtype) {
525         case DH6_SOLICIT:
526                 name = "solicit";
527                 break;
528         case DH6_ADVERTISE:
529                 name = "advertise";
530                 break;
531         case DH6_REQUEST:
532                 name = "request";
533                 break;
534         case DH6_CONFIRM:
535                 name = "confirm";
536                 break;
537         case DH6_RENEW:
538                 name = "renew";
539                 break;
540         case DH6_REBIND:
541                 name = "rebind";
542                 break;
543         case DH6_REPLY:
544                 name = "reply";
545                 break;
546         case DH6_RELEASE:
547                 name = "release";
548                 break;
549         case DH6_DECLINE:
550                 name = "decline";
551                 break;
552         case DH6_RECONFIGURE:
553                 name = "reconfigure";
554                 break;
555         case DH6_INFORM_REQ:
556                 name= "inf-req";
557                 break;
558         case DH6_RELAY_FORW:
559                 name= "relay-fwd";
560                 break;
561         case DH6_RELAY_REPLY:
562                 name= "relay-reply";
563                 break;
564         default:
565                 name = NULL;
566                 break;
567         }
568
569         if (!vflag) {
570                 if (name)
571                         printf(" %s", name);
572                 else if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
573                     dh6->dh6_msgtype != DH6_RELAY_REPLY) {
574                         printf(" msgtype-%u", dh6->dh6_msgtype);
575                 }
576                 return;
577         }
578
579         /* XXX relay agent messages have to be handled differently */
580
581         if (name)
582                 printf(" %s (", name);  /*)*/
583         else
584                 printf(" msgtype-%u (", dh6->dh6_msgtype);      /*)*/
585         if (dh6->dh6_msgtype != DH6_RELAY_FORW &&
586             dh6->dh6_msgtype != DH6_RELAY_REPLY) {
587                 printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK);
588                 extp = (u_char *)(dh6 + 1);
589                 dhcp6opt_print(extp, ep);
590         } else {                /* relay messages */
591                 struct in6_addr addr6;
592
593                 TCHECK(dh6relay->dh6relay_peeraddr);
594
595                 memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6));
596                 printf("linkaddr=%s", ip6addr_string(&addr6));
597
598                 memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6));
599                 printf(" peeraddr=%s", ip6addr_string(&addr6));
600
601                 dhcp6opt_print((u_char *)(dh6relay + 1), ep);
602         }
603         /*(*/
604         printf(")");
605         return;
606
607 trunc:
608         printf("[|dhcp6]");
609 }