]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bootp.c
This commit was generated by cvs2svn to compensate for changes in r156952,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-bootp.c
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Format and print bootp packets.
22  *
23  * $FreeBSD$
24  */
25 #ifndef lint
26 static const char rcsid[] _U_ =
27     "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.78.2.2 2005/05/06 04:19:39 guy Exp $ (LBL)";
28 #endif
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <tcpdump-stdinc.h>
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "interface.h"
40 #include "addrtoname.h"
41 #include "extract.h"
42 #include "ether.h"
43 #include "bootp.h"
44
45 static void rfc1048_print(const u_char *);
46 static void cmu_print(const u_char *);
47
48 static char tstr[] = " [|bootp]";
49
50 static const struct tok bootp_flag_values[] = {
51     { 0x8000,                   "Broadcast" },
52     { 0, NULL}
53 };
54
55 static const struct tok bootp_op_values[] = {
56     { BOOTPREQUEST,             "Request" },
57     { BOOTPREPLY,               "Reply" },
58     { 0, NULL}
59 };
60
61 /*
62  * Print bootp requests
63  */
64 void
65 bootp_print(register const u_char *cp, u_int length)
66 {
67         register const struct bootp *bp;
68         static const u_char vm_cmu[4] = VM_CMU;
69         static const u_char vm_rfc1048[4] = VM_RFC1048;
70
71         bp = (const struct bootp *)cp;
72         TCHECK(bp->bp_op);
73
74         printf("BOOTP/DHCP, %s",
75                tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op));
76
77         if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) {
78                 TCHECK2(bp->bp_chaddr[0], 6);
79                 printf(" from %s", etheraddr_string(bp->bp_chaddr));
80         }
81
82         printf(", length: %u", length);
83
84         if (!vflag)
85             return;
86
87         TCHECK(bp->bp_secs);
88
89         /* The usual hardware address type is 1 (10Mb Ethernet) */
90         if (bp->bp_htype != 1)
91                 printf(", htype-#%d", bp->bp_htype);
92
93         /* The usual length for 10Mb Ethernet address is 6 bytes */
94         if (bp->bp_htype != 1 || bp->bp_hlen != 6)
95                 printf(", hlen:%d", bp->bp_hlen);
96
97         /* Only print interesting fields */
98         if (bp->bp_hops)
99                 printf(", hops:%d", bp->bp_hops);
100         if (bp->bp_xid)
101                 printf(", xid:0x%x", EXTRACT_32BITS(&bp->bp_xid));
102         if (bp->bp_secs)
103                 printf(", secs:%d", EXTRACT_16BITS(&bp->bp_secs));
104
105         printf(", flags: [%s]",
106                bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)));
107         if (vflag>1)
108           printf( " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags));
109
110         /* Client's ip address */
111         TCHECK(bp->bp_ciaddr);
112         if (bp->bp_ciaddr.s_addr)
113                 printf("\n\t  Client IP: %s", ipaddr_string(&bp->bp_ciaddr));
114
115         /* 'your' ip address (bootp client) */
116         TCHECK(bp->bp_yiaddr);
117         if (bp->bp_yiaddr.s_addr)
118                 printf("\n\t  Your IP: %s", ipaddr_string(&bp->bp_yiaddr));
119
120         /* Server's ip address */
121         TCHECK(bp->bp_siaddr);
122         if (bp->bp_siaddr.s_addr)
123                 printf("\n\t  Server IP: %s", ipaddr_string(&bp->bp_siaddr));
124
125         /* Gateway's ip address */
126         TCHECK(bp->bp_giaddr);
127         if (bp->bp_giaddr.s_addr)
128                 printf("\n\t  Gateway IP: %s", ipaddr_string(&bp->bp_giaddr));
129
130         /* Client's Ethernet address */
131         if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
132                 TCHECK2(bp->bp_chaddr[0], 6);
133                 printf("\n\t  Client Ethernet Address: %s", etheraddr_string(bp->bp_chaddr));
134         }
135
136         TCHECK2(bp->bp_sname[0], 1);            /* check first char only */
137         if (*bp->bp_sname) {
138                 printf("\n\t  sname \"");
139                 if (fn_print(bp->bp_sname, snapend)) {
140                         putchar('"');
141                         fputs(tstr + 1, stdout);
142                         return;
143                 }
144                 putchar('"');
145         }
146         TCHECK2(bp->bp_file[0], 1);             /* check first char only */
147         if (*bp->bp_file) {
148                 printf("\n\t  file \"");
149                 if (fn_print(bp->bp_file, snapend)) {
150                         putchar('"');
151                         fputs(tstr + 1, stdout);
152                         return;
153                 }
154                 putchar('"');
155         }
156
157         /* Decode the vendor buffer */
158         TCHECK(bp->bp_vend[0]);
159         if (memcmp((const char *)bp->bp_vend, vm_rfc1048,
160                  sizeof(u_int32_t)) == 0)
161                 rfc1048_print(bp->bp_vend);
162         else if (memcmp((const char *)bp->bp_vend, vm_cmu,
163                       sizeof(u_int32_t)) == 0)
164                 cmu_print(bp->bp_vend);
165         else {
166                 u_int32_t ul;
167
168                 ul = EXTRACT_32BITS(&bp->bp_vend);
169                 if (ul != 0)
170                         printf("\n\t  Vendor-#0x%x", ul);
171         }
172
173         return;
174 trunc:
175         fputs(tstr, stdout);
176 }
177
178 /*
179  * The first character specifies the format to print:
180  *     i - ip address (32 bits)
181  *     p - ip address pairs (32 bits + 32 bits)
182  *     l - long (32 bits)
183  *     L - unsigned long (32 bits)
184  *     s - short (16 bits)
185  *     b - period-seperated decimal bytes (variable length)
186  *     x - colon-seperated hex bytes (variable length)
187  *     a - ascii string (variable length)
188  *     B - on/off (8 bits)
189  *     $ - special (explicit code to handle)
190  */
191 static struct tok tag2str[] = {
192 /* RFC1048 tags */
193         { TAG_PAD,              " PAD" },
194         { TAG_SUBNET_MASK,      "iSM" },        /* subnet mask (RFC950) */
195         { TAG_TIME_OFFSET,      "LTZ" },        /* seconds from UTC */
196         { TAG_GATEWAY,          "iDG" },        /* default gateway */
197         { TAG_TIME_SERVER,      "iTS" },        /* time servers (RFC868) */
198         { TAG_NAME_SERVER,      "iIEN" },       /* IEN name servers (IEN116) */
199         { TAG_DOMAIN_SERVER,    "iNS" },        /* domain name (RFC1035) */
200         { TAG_LOG_SERVER,       "iLOG" },       /* MIT log servers */
201         { TAG_COOKIE_SERVER,    "iCS" },        /* cookie servers (RFC865) */
202         { TAG_LPR_SERVER,       "iLPR" },       /* lpr server (RFC1179) */
203         { TAG_IMPRESS_SERVER,   "iIM" },        /* impress servers (Imagen) */
204         { TAG_RLP_SERVER,       "iRL" },        /* resource location (RFC887) */
205         { TAG_HOSTNAME,         "aHN" },        /* ascii hostname */
206         { TAG_BOOTSIZE,         "sBS" },        /* 512 byte blocks */
207         { TAG_END,              " END" },
208 /* RFC1497 tags */
209         { TAG_DUMPPATH,         "aDP" },
210         { TAG_DOMAINNAME,       "aDN" },
211         { TAG_SWAP_SERVER,      "iSS" },
212         { TAG_ROOTPATH,         "aRP" },
213         { TAG_EXTPATH,          "aEP" },
214 /* RFC2132 tags */
215         { TAG_IP_FORWARD,       "BIPF" },
216         { TAG_NL_SRCRT,         "BSRT" },
217         { TAG_PFILTERS,         "pPF" },
218         { TAG_REASS_SIZE,       "sRSZ" },
219         { TAG_DEF_TTL,          "bTTL" },
220         { TAG_MTU_TIMEOUT,      "lMA" },
221         { TAG_MTU_TABLE,        "sMT" },
222         { TAG_INT_MTU,          "sMTU" },
223         { TAG_LOCAL_SUBNETS,    "BLSN" },
224         { TAG_BROAD_ADDR,       "iBR" },
225         { TAG_DO_MASK_DISC,     "BMD" },
226         { TAG_SUPPLY_MASK,      "BMS" },
227         { TAG_DO_RDISC,         "BRD" },
228         { TAG_RTR_SOL_ADDR,     "iRSA" },
229         { TAG_STATIC_ROUTE,     "pSR" },
230         { TAG_USE_TRAILERS,     "BUT" },
231         { TAG_ARP_TIMEOUT,      "lAT" },
232         { TAG_ETH_ENCAP,        "BIE" },
233         { TAG_TCP_TTL,          "bTT" },
234         { TAG_TCP_KEEPALIVE,    "lKI" },
235         { TAG_KEEPALIVE_GO,     "BKG" },
236         { TAG_NIS_DOMAIN,       "aYD" },
237         { TAG_NIS_SERVERS,      "iYS" },
238         { TAG_NTP_SERVERS,      "iNTP" },
239         { TAG_VENDOR_OPTS,      "bVO" },
240         { TAG_NETBIOS_NS,       "iWNS" },
241         { TAG_NETBIOS_DDS,      "iWDD" },
242         { TAG_NETBIOS_NODE,     "$WNT" },
243         { TAG_NETBIOS_SCOPE,    "aWSC" },
244         { TAG_XWIN_FS,          "iXFS" },
245         { TAG_XWIN_DM,          "iXDM" },
246         { TAG_NIS_P_DOMAIN,     "sN+D" },
247         { TAG_NIS_P_SERVERS,    "iN+S" },
248         { TAG_MOBILE_HOME,      "iMH" },
249         { TAG_SMPT_SERVER,      "iSMTP" },
250         { TAG_POP3_SERVER,      "iPOP3" },
251         { TAG_NNTP_SERVER,      "iNNTP" },
252         { TAG_WWW_SERVER,       "iWWW" },
253         { TAG_FINGER_SERVER,    "iFG" },
254         { TAG_IRC_SERVER,       "iIRC" },
255         { TAG_STREETTALK_SRVR,  "iSTS" },
256         { TAG_STREETTALK_STDA,  "iSTDA" },
257         { TAG_REQUESTED_IP,     "iRQ" },
258         { TAG_IP_LEASE,         "lLT" },
259         { TAG_OPT_OVERLOAD,     "$OO" },
260         { TAG_TFTP_SERVER,      "aTFTP" },
261         { TAG_BOOTFILENAME,     "aBF" },
262         { TAG_DHCP_MESSAGE,     " DHCP" },
263         { TAG_SERVER_ID,        "iSID" },
264         { TAG_PARM_REQUEST,     "bPR" },
265         { TAG_MESSAGE,          "aMSG" },
266         { TAG_MAX_MSG_SIZE,     "sMSZ" },
267         { TAG_RENEWAL_TIME,     "lRN" },
268         { TAG_REBIND_TIME,      "lRB" },
269         { TAG_VENDOR_CLASS,     "aVC" },
270         { TAG_CLIENT_ID,        "$CID" },
271 /* RFC 2485 */
272         { TAG_OPEN_GROUP_UAP,   "aUAP" },
273 /* RFC 2563 */
274         { TAG_DISABLE_AUTOCONF, "BNOAUTO" },
275 /* RFC 2610 */
276         { TAG_SLP_DA,           "bSLP-DA" },    /*"b" is a little wrong */
277         { TAG_SLP_SCOPE,        "bSLP-SCOPE" }, /*"b" is a little wrong */
278 /* RFC 2937 */
279         { TAG_NS_SEARCH,        "sNSSEARCH" },  /* XXX 's' */
280 /* RFC 3011 */
281         { TAG_IP4_SUBNET_SELECT, "iSUBNET" },
282 /* http://www.iana.org/assignments/bootp-dhcp-extensions/index.htm */
283         { TAG_USER_CLASS,       "aCLASS" },
284         { TAG_SLP_NAMING_AUTH,  "aSLP-NA" },
285         { TAG_CLIENT_FQDN,      "$FQDN" },
286         { TAG_AGENT_CIRCUIT,    "bACKT" },
287         { TAG_AGENT_REMOTE,     "bARMT" },
288         { TAG_AGENT_MASK,       "bAMSK" },
289         { TAG_TZ_STRING,        "aTZSTR" },
290         { TAG_FQDN_OPTION,      "bFQDNS" },     /* XXX 'b' */
291         { TAG_AUTH,             "bAUTH" },      /* XXX 'b' */
292         { TAG_VINES_SERVERS,    "iVINES" },
293         { TAG_SERVER_RANK,      "sRANK" },
294         { TAG_CLIENT_ARCH,      "sARCH" },
295         { TAG_CLIENT_NDI,       "bNDI" },       /* XXX 'b' */
296         { TAG_CLIENT_GUID,      "bGUID" },      /* XXX 'b' */
297         { TAG_LDAP_URL,         "aLDAP" },
298         { TAG_6OVER4,           "i6o4" },
299         { TAG_PRINTER_NAME,     "aPRTR" },
300         { TAG_MDHCP_SERVER,     "bMDHCP" },     /* XXX 'b' */
301         { TAG_IPX_COMPAT,       "bIPX" },       /* XXX 'b' */
302         { TAG_NETINFO_PARENT,   "iNI" },
303         { TAG_NETINFO_PARENT_TAG, "aNITAG" },
304         { TAG_URL,              "aURL" },
305         { TAG_FAILOVER,         "bFAIL" },      /* XXX 'b' */
306         { 0,                    NULL }
307 };
308 /* 2-byte extended tags */
309 static struct tok xtag2str[] = {
310         { 0,                    NULL }
311 };
312
313 /* DHCP "options overload" types */
314 static struct tok oo2str[] = {
315         { 1,                    "file" },
316         { 2,                    "sname" },
317         { 3,                    "file+sname" },
318         { 0,                    NULL }
319 };
320
321 /* NETBIOS over TCP/IP node type options */
322 static struct tok nbo2str[] = {
323         { 0x1,                  "b-node" },
324         { 0x2,                  "p-node" },
325         { 0x4,                  "m-node" },
326         { 0x8,                  "h-node" },
327         { 0,                    NULL }
328 };
329
330 /* ARP Hardware types, for Client-ID option */
331 static struct tok arp2str[] = {
332         { 0x1,                  "ether" },
333         { 0x6,                  "ieee802" },
334         { 0x7,                  "arcnet" },
335         { 0xf,                  "frelay" },
336         { 0x17,                 "strip" },
337         { 0x18,                 "ieee1394" },
338         { 0,                    NULL }
339 };
340
341 static void
342 rfc1048_print(register const u_char *bp)
343 {
344         register u_int16_t tag;
345         register u_int len, size;
346         register const char *cp;
347         register char c;
348         int first;
349         u_int32_t ul;
350         u_int16_t us;
351         u_int8_t uc;
352
353         printf("\n\t  Vendor-rfc1048:");
354
355         /* Step over magic cookie */
356         bp += sizeof(int32_t);
357
358         /* Loop while we there is a tag left in the buffer */
359         while (bp + 1 < snapend) {
360                 tag = *bp++;
361                 if (tag == TAG_PAD)
362                         continue;
363                 if (tag == TAG_END)
364                         return;
365                 if (tag == TAG_EXTENDED_OPTION) {
366                         TCHECK2(*(bp + 1), 2);
367                         tag = EXTRACT_16BITS(bp + 1);
368                         /* XXX we don't know yet if the IANA will
369                          * preclude overlap of 1-byte and 2-byte spaces.
370                          * If not, we need to offset tag after this step.
371                          */
372                         cp = tok2str(xtag2str, "?xT%u", tag);
373                 } else
374                         cp = tok2str(tag2str, "?T%u", tag);
375                 c = *cp++;
376                 printf("\n\t    %s:", cp);
377
378                 /* Get the length; check for truncation */
379                 if (bp + 1 >= snapend) {
380                         fputs(tstr, stdout);
381                         return;
382                 }
383                 len = *bp++;
384                 if (bp + len >= snapend) {
385                         printf("[|bootp %u]", len);
386                         return;
387                 }
388
389                 if (tag == TAG_DHCP_MESSAGE && len == 1) {
390                         uc = *bp++;
391                         switch (uc) {
392                         case DHCPDISCOVER:      printf("DISCOVER");     break;
393                         case DHCPOFFER:         printf("OFFER");        break;
394                         case DHCPREQUEST:       printf("REQUEST");      break;
395                         case DHCPDECLINE:       printf("DECLINE");      break;
396                         case DHCPACK:           printf("ACK");          break;
397                         case DHCPNAK:           printf("NACK");         break;
398                         case DHCPRELEASE:       printf("RELEASE");      break;
399                         case DHCPINFORM:        printf("INFORM");       break;
400                         default:                printf("%u", uc);       break;
401                         }
402                         continue;
403                 }
404
405                 if (tag == TAG_PARM_REQUEST) {
406                         first = 1;
407                         while (len-- > 0) {
408                                 uc = *bp++;
409                                 cp = tok2str(tag2str, "?T%u", uc);
410                                 if (!first)
411                                         putchar('+');
412                                 printf("%s", cp + 1);
413                                 first = 0;
414                         }
415                         continue;
416                 }
417                 if (tag == TAG_EXTENDED_REQUEST) {
418                         first = 1;
419                         while (len > 1) {
420                                 len -= 2;
421                                 us = EXTRACT_16BITS(bp);
422                                 bp += 2;
423                                 cp = tok2str(xtag2str, "?xT%u", us);
424                                 if (!first)
425                                         putchar('+');
426                                 printf("%s", cp + 1);
427                                 first = 0;
428                         }
429                         continue;
430                 }
431
432                 /* Print data */
433                 size = len;
434                 if (c == '?') {
435                         /* Base default formats for unknown tags on data size */
436                         if (size & 1)
437                                 c = 'b';
438                         else if (size & 2)
439                                 c = 's';
440                         else
441                                 c = 'l';
442                 }
443                 first = 1;
444                 switch (c) {
445
446                 case 'a':
447                         /* ascii strings */
448                         putchar('"');
449                         if (fn_printn(bp, size, snapend)) {
450                                 putchar('"');
451                                 goto trunc;
452                         }
453                         putchar('"');
454                         bp += size;
455                         size = 0;
456                         break;
457
458                 case 'i':
459                 case 'l':
460                 case 'L':
461                         /* ip addresses/32-bit words */
462                         while (size >= sizeof(ul)) {
463                                 if (!first)
464                                         putchar(',');
465                                 ul = EXTRACT_32BITS(bp);
466                                 if (c == 'i') {
467                                         ul = htonl(ul);
468                                         printf("%s", ipaddr_string(&ul));
469                                 } else if (c == 'L')
470                                         printf("%d", ul);
471                                 else
472                                         printf("%u", ul);
473                                 bp += sizeof(ul);
474                                 size -= sizeof(ul);
475                                 first = 0;
476                         }
477                         break;
478
479                 case 'p':
480                         /* IP address pairs */
481                         while (size >= 2*sizeof(ul)) {
482                                 if (!first)
483                                         putchar(',');
484                                 memcpy((char *)&ul, (const char *)bp, sizeof(ul));
485                                 printf("(%s:", ipaddr_string(&ul));
486                                 bp += sizeof(ul);
487                                 memcpy((char *)&ul, (const char *)bp, sizeof(ul));
488                                 printf("%s)", ipaddr_string(&ul));
489                                 bp += sizeof(ul);
490                                 size -= 2*sizeof(ul);
491                                 first = 0;
492                         }
493                         break;
494
495                 case 's':
496                         /* shorts */
497                         while (size >= sizeof(us)) {
498                                 if (!first)
499                                         putchar(',');
500                                 us = EXTRACT_16BITS(bp);
501                                 printf("%u", us);
502                                 bp += sizeof(us);
503                                 size -= sizeof(us);
504                                 first = 0;
505                         }
506                         break;
507
508                 case 'B':
509                         /* boolean */
510                         while (size > 0) {
511                                 if (!first)
512                                         putchar(',');
513                                 switch (*bp) {
514                                 case 0:
515                                         putchar('N');
516                                         break;
517                                 case 1:
518                                         putchar('Y');
519                                         break;
520                                 default:
521                                         printf("%u?", *bp);
522                                         break;
523                                 }
524                                 ++bp;
525                                 --size;
526                                 first = 0;
527                         }
528                         break;
529
530                 case 'b':
531                 case 'x':
532                 default:
533                         /* Bytes */
534                         while (size > 0) {
535                                 if (!first)
536                                         putchar(c == 'x' ? ':' : '.');
537                                 if (c == 'x')
538                                         printf("%02x", *bp);
539                                 else
540                                         printf("%u", *bp);
541                                 ++bp;
542                                 --size;
543                                 first = 0;
544                         }
545                         break;
546
547                 case '$':
548                         /* Guys we can't handle with one of the usual cases */
549                         switch (tag) {
550
551                         case TAG_NETBIOS_NODE:
552                                 tag = *bp++;
553                                 --size;
554                                 fputs(tok2str(nbo2str, NULL, tag), stdout);
555                                 break;
556
557                         case TAG_OPT_OVERLOAD:
558                                 tag = *bp++;
559                                 --size;
560                                 fputs(tok2str(oo2str, NULL, tag), stdout);
561                                 break;
562
563                         case TAG_CLIENT_FQDN:
564                                 /* option 81 should be at least 4 bytes long */
565                                 if (len < 4)  {
566                                         printf("ERROR: options 81 len %u < 4 bytes", len);
567                                         break;
568                                 }
569                                 if (*bp++)
570                                         printf("[svrreg]");
571                                 if (*bp)
572                                         printf("%u/%u/", *bp, *(bp+1));
573                                 bp += 2;
574                                 putchar('"');
575                                 if (fn_printn(bp, size - 3, snapend)) {
576                                         putchar('"');
577                                         goto trunc;
578                                 }
579                                 putchar('"');
580                                 bp += size - 3;
581                                 size = 0;
582                                 break;
583
584                         case TAG_CLIENT_ID:
585                             {   int type = *bp++;
586                                 size--;
587                                 if (type == 0) {
588                                         putchar('"');
589                                         if (fn_printn(bp, size, snapend)) {
590                                                 putchar('"');
591                                                 goto trunc;
592                                         }
593                                         putchar('"');
594                                         bp += size;
595                                         size = 0;
596                                         break;
597                                 } else {
598                                         printf("[%s]", tok2str(arp2str, "type-%d", type));
599                                 }
600                                 while (size > 0) {
601                                         if (!first)
602                                                 putchar(':');
603                                         printf("%02x", *bp);
604                                         ++bp;
605                                         --size;
606                                         first = 0;
607                                 }
608                                 break;
609                             }
610
611                         default:
612                                 printf("[unknown special tag %u, size %u]",
613                                     tag, size);
614                                 bp += size;
615                                 size = 0;
616                                 break;
617                         }
618                         break;
619                 }
620                 /* Data left over? */
621                 if (size) {
622                         printf("[len %u]", len);
623                         bp += size;
624                 }
625         }
626         return;
627 trunc:
628         printf("|[rfc1048]");
629 }
630
631 static void
632 cmu_print(register const u_char *bp)
633 {
634         register const struct cmu_vend *cmu;
635
636 #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \
637     if (cmu->m.s_addr != 0) \
638         printf(" %s:%s", s, ipaddr_string(&cmu->m.s_addr)); }
639
640         printf(" vend-cmu");
641         cmu = (const struct cmu_vend *)bp;
642
643         /* Only print if there are unknown bits */
644         TCHECK(cmu->v_flags);
645         if ((cmu->v_flags & ~(VF_SMASK)) != 0)
646                 printf(" F:0x%x", cmu->v_flags);
647         PRINTCMUADDR(v_dgate, "DG");
648         PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
649         PRINTCMUADDR(v_dns1, "NS1");
650         PRINTCMUADDR(v_dns2, "NS2");
651         PRINTCMUADDR(v_ins1, "IEN1");
652         PRINTCMUADDR(v_ins2, "IEN2");
653         PRINTCMUADDR(v_ts1, "TS1");
654         PRINTCMUADDR(v_ts2, "TS2");
655         return;
656
657 trunc:
658         fputs(tstr, stdout);
659 #undef PRINTCMUADDR
660 }