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