]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bootp.c
This commit was generated by cvs2svn to compensate for changes in r96295,
[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.56 2000/12/04 00:00:08 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 *, u_int);
54 static void cmu_print(const u_char *, u_int);
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 u_char vm_cmu[4] = VM_CMU;
67         static u_char vm_rfc1048[4] = VM_RFC1048;
68
69         bp = (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 = (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((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         length -= sizeof(*bp) - sizeof(bp->bp_vend);
170         if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
171                  sizeof(u_int32_t)) == 0)
172                 rfc1048_print(bp->bp_vend, length);
173         else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu,
174                       sizeof(u_int32_t)) == 0)
175                 cmu_print(bp->bp_vend, length);
176         else {
177                 u_int32_t ul;
178
179                 ul = EXTRACT_32BITS(&bp->bp_vend);
180                 if (ul != 0)
181                         printf("vend-#0x%x", ul);
182         }
183
184         return;
185 trunc:
186         fputs(tstr, stdout);
187 }
188
189 /* The first character specifies the format to print */
190 static struct tok tag2str[] = {
191 /* RFC1048 tags */
192         { TAG_PAD,              " PAD" },
193         { TAG_SUBNET_MASK,      "iSM" },        /* subnet mask (RFC950) */
194         { TAG_TIME_OFFSET,      "LTZ" },        /* seconds from UTC */
195         { TAG_GATEWAY,          "iDG" },        /* default gateway */
196         { TAG_TIME_SERVER,      "iTS" },        /* time servers (RFC868) */
197         { TAG_NAME_SERVER,      "iIEN" },       /* IEN name servers (IEN116) */
198         { TAG_DOMAIN_SERVER,    "iNS" },        /* domain name (RFC1035) */
199         { TAG_LOG_SERVER,       "iLOG" },       /* MIT log servers */
200         { TAG_COOKIE_SERVER,    "iCS" },        /* cookie servers (RFC865) */
201         { TAG_LPR_SERVER,       "iLPR" },       /* lpr server (RFC1179) */
202         { TAG_IMPRESS_SERVER,   "iIM" },        /* impress servers (Imagen) */
203         { TAG_RLP_SERVER,       "iRL" },        /* resource location (RFC887) */
204         { TAG_HOSTNAME,         "aHN" },        /* ascii hostname */
205         { TAG_BOOTSIZE,         "sBS" },        /* 512 byte blocks */
206         { TAG_END,              " END" },
207 /* RFC1497 tags */
208         { TAG_DUMPPATH,         "aDP" },
209         { TAG_DOMAINNAME,       "aDN" },
210         { TAG_SWAP_SERVER,      "iSS" },
211         { TAG_ROOTPATH,         "aRP" },
212         { TAG_EXTPATH,          "aEP" },
213 /* RFC2132 tags */
214         { TAG_IP_FORWARD,       "BIPF" },
215         { TAG_NL_SRCRT,         "BSRT" },
216         { TAG_PFILTERS,         "pPF" },
217         { TAG_REASS_SIZE,       "sRSZ" },
218         { TAG_DEF_TTL,          "bTTL" },
219         { TAG_MTU_TIMEOUT,      "lMA" },
220         { TAG_MTU_TABLE,        "sMT" },
221         { TAG_INT_MTU,          "sMTU" },
222         { TAG_LOCAL_SUBNETS,    "BLSN" },
223         { TAG_BROAD_ADDR,       "iBR" },
224         { TAG_DO_MASK_DISC,     "BMD" },
225         { TAG_SUPPLY_MASK,      "BMS" },
226         { TAG_DO_RDISC,         "BRD" },
227         { TAG_RTR_SOL_ADDR,     "iRSA" },
228         { TAG_STATIC_ROUTE,     "pSR" },
229         { TAG_USE_TRAILERS,     "BUT" },
230         { TAG_ARP_TIMEOUT,      "lAT" },
231         { TAG_ETH_ENCAP,        "BIE" },
232         { TAG_TCP_TTL,          "bTT" },
233         { TAG_TCP_KEEPALIVE,    "lKI" },
234         { TAG_KEEPALIVE_GO,     "BKG" },
235         { TAG_NIS_DOMAIN,       "aYD" },
236         { TAG_NIS_SERVERS,      "iYS" },
237         { TAG_NTP_SERVERS,      "iNTP" },
238         { TAG_VENDOR_OPTS,      "bVO" },
239         { TAG_NETBIOS_NS,       "iWNS" },
240         { TAG_NETBIOS_DDS,      "iWDD" },
241         { TAG_NETBIOS_NODE,     "bWNT" },
242         { TAG_NETBIOS_SCOPE,    "aWSC" },
243         { TAG_XWIN_FS,          "iXFS" },
244         { TAG_XWIN_DM,          "iXDM" },
245         { TAG_NIS_P_DOMAIN,     "sN+D" },
246         { TAG_NIS_P_SERVERS,    "iN+S" },
247         { TAG_MOBILE_HOME,      "iMH" },
248         { TAG_SMPT_SERVER,      "iSMTP" },
249         { TAG_POP3_SERVER,      "iPOP3" },
250         { TAG_NNTP_SERVER,      "iNNTP" },
251         { TAG_WWW_SERVER,       "iWWW" },
252         { TAG_FINGER_SERVER,    "iFG" },
253         { TAG_IRC_SERVER,       "iIRC" },
254         { TAG_STREETTALK_SRVR,  "iSTS" },
255         { TAG_STREETTALK_STDA,  "iSTDA" },
256         { TAG_REQUESTED_IP,     "iRQ" },
257         { TAG_IP_LEASE,         "lLT" },
258         { TAG_OPT_OVERLOAD,     "bOO" },
259         { TAG_TFTP_SERVER,      "aTFTP" },
260         { TAG_BOOTFILENAME,     "aBF" },
261         { TAG_DHCP_MESSAGE,     " DHCP" },
262         { TAG_SERVER_ID,        "iSID" },
263         { TAG_PARM_REQUEST,     "bPR" },
264         { TAG_MESSAGE,          "aMSG" },
265         { TAG_MAX_MSG_SIZE,     "sMSZ" },
266         { TAG_RENEWAL_TIME,     "lRN" },
267         { TAG_REBIND_TIME,      "lRB" },
268         { TAG_VENDOR_CLASS,     "bVC" },
269         { TAG_CLIENT_ID,        "xCID" },
270 /* RFC 2485 */
271         { TAG_OPEN_GROUP_UAP,   "aUAP" },
272 /* RFC 2563 */
273         { TAG_DISABLE_AUTOCONF, "BNOAUTO" },
274 /* RFC 2610 */
275         { TAG_SLP_DA,           "bSLP-DA" },    /*"b" is a little wrong */
276         { TAG_SLP_SCOPE,        "bSLP-SCOPE" }, /*"b" is a little wrong */
277 /* RFC 2937 */
278         { TAG_NS_SEARCH,        "sNSSEARCH" },  /* XXX 's' */
279 /* RFC 3011 */
280         { TAG_IP4_SUBNET_SELECT, "iSUBNET" },
281 /* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */
282         { TAG_USER_CLASS,       "aCLASS" },
283         { TAG_SLP_NAMING_AUTH,  "aSLP-NA" },
284         { TAG_CLIENT_FQDN,      "bFQDN" },      /* XXX 'b' */
285         { TAG_AGENT_CIRCUIT,    "bACKT" },
286         { TAG_AGENT_REMOTE,     "bARMT" },
287         { TAG_AGENT_MASK,       "bAMSK" },
288         { TAG_TZ_STRING,        "aTZSTR" },
289         { TAG_FQDN_OPTION,      "bFQDNS" },     /* XXX 'b' */
290         { TAG_AUTH,             "bAUTH" },      /* XXX 'b' */
291         { TAG_VINES_SERVERS,    "iVINES" },
292         { TAG_SERVER_RANK,      "sRANK" },
293         { TAG_CLIENT_ARCH,      "sARCH" },
294         { TAG_CLIENT_NDI,       "bNDI" },       /* XXX 'b' */
295         { TAG_CLIENT_GUID,      "bGUID" },      /* XXX 'b' */
296         { TAG_LDAP_URL,         "aLDAP" },
297         { TAG_6OVER4,           "i6o4" },
298         { TAG_PRINTER_NAME,     "aPRTR" },
299         { TAG_MDHCP_SERVER,     "bMDHCP" },     /* XXX 'b' */
300         { TAG_IPX_COMPAT,       "bIPX" },       /* XXX 'b' */
301         { TAG_NETINFO_PARENT,   "iNI" },
302         { TAG_NETINFO_PARENT_TAG, "aNITAG" },
303         { TAG_URL,              "aURL" },
304         { TAG_FAILOVER,         "bFAIL" },      /* XXX 'b' */
305         { 0,                    NULL }
306 };
307 /* 2-byte extended tags */
308 static struct tok xtag2str[] = {
309         { 0,                    NULL }
310 };
311
312 static void
313 rfc1048_print(register const u_char *bp, register u_int length)
314 {
315         register u_char tag;
316         register u_int len, size;
317         register const char *cp;
318         register char c;
319         int first;
320         u_int32_t ul;
321         u_short us;
322
323         printf(" vend-rfc1048");
324
325         /* Step over magic cookie */
326         bp += sizeof(int32_t);
327
328         /* Loop while we there is a tag left in the buffer */
329         while (bp + 1 < snapend) {
330                 tag = *bp++;
331                 if (tag == TAG_PAD)
332                         continue;
333                 if (tag == TAG_END)
334                         return;
335                 if (tag == TAG_EXTENDED_OPTION) {
336                         TCHECK2(*(bp + 1), 2);
337                         tag = EXTRACT_16BITS(bp + 1);
338                         /* XXX we don't know yet if the IANA will
339                          * preclude overlap of 1-byte and 2-byte spaces.
340                          * If not, we need to offset tag after this step.
341                          */
342                         cp = tok2str(xtag2str, "?xT%d", tag);
343                 } else
344                         cp = tok2str(tag2str, "?T%d", tag);
345                 c = *cp++;
346                 printf(" %s:", cp);
347
348                 /* Get the length; check for truncation */
349                 if (bp + 1 >= snapend) {
350                         fputs(tstr, stdout);
351                         return;
352                 }
353                 len = *bp++;
354                 if (bp + len >= snapend) {
355                         fputs(tstr, stdout);
356                         return;
357                 }
358
359                 if (tag == TAG_DHCP_MESSAGE && len == 1) {
360                         c = *bp++;
361                         switch (c) {
362                         case DHCPDISCOVER:      printf("DISCOVER");     break;
363                         case DHCPOFFER:         printf("OFFER");        break;
364                         case DHCPREQUEST:       printf("REQUEST");      break;
365                         case DHCPDECLINE:       printf("DECLINE");      break;
366                         case DHCPACK:           printf("ACK");          break;
367                         case DHCPNAK:           printf("NACK");         break;
368                         case DHCPRELEASE:       printf("RELEASE");      break;
369                         case DHCPINFORM:        printf("INFORM");       break;
370                         default:                printf("%u", c);        break;
371                         }
372                         continue;
373                 }
374
375                 if (tag == TAG_PARM_REQUEST) {
376                         first = 1;
377                         while (len-- > 0) {
378                                 c = *bp++;
379                                 cp = tok2str(tag2str, "?T%d", c);
380                                 if (!first)
381                                         putchar('+');
382                                 printf("%s", cp + 1);
383                                 first = 0;
384                         }
385                         continue;
386                 }
387                 if (tag == TAG_EXTENDED_REQUEST) {
388                         first = 1;
389                         while (len > 1) {
390                                 len -= 2;
391                                 c = EXTRACT_16BITS(bp);
392                                 bp += 2;
393                                 cp = tok2str(xtag2str, "?xT%d", c);
394                                 if (!first)
395                                         putchar('+');
396                                 printf("%s", cp + 1);
397                                 first = 0;
398                         }
399                         continue;
400                 }
401
402                 /* Print data */
403                 size = len;
404                 if (c == '?') {
405                         /* Base default formats for unknown tags on data size */
406                         if (size & 1)
407                                 c = 'b';
408                         else if (size & 2)
409                                 c = 's';
410                         else
411                                 c = 'l';
412                 }
413                 first = 1;
414                 switch (c) {
415
416                 case 'a':
417                         /* ascii strings */
418                         putchar('"');
419                         (void)fn_printn(bp, size, NULL);
420                         putchar('"');
421                         bp += size;
422                         size = 0;
423                         break;
424
425                 case 'i':
426                 case 'l':
427                 case 'L':
428                         /* ip addresses/32-bit words */
429                         while (size >= sizeof(ul)) {
430                                 if (!first)
431                                         putchar(',');
432                                 ul = EXTRACT_32BITS(bp);
433                                 if (c == 'i') {
434                                         ul = htonl(ul);
435                                         printf("%s", ipaddr_string(&ul));
436                                 } else if (c == 'L')
437                                         printf("%d", ul);
438                                 else
439                                         printf("%u", ul);
440                                 bp += sizeof(ul);
441                                 size -= sizeof(ul);
442                                 first = 0;
443                         }
444                         break;
445
446                 case 'p':
447                         /* IP address pairs */
448                         while (size >= 2*sizeof(ul)) {
449                                 if (!first)
450                                         putchar(',');
451                                 memcpy((char *)&ul, (char *)bp, sizeof(ul));
452                                 printf("(%s:", ipaddr_string(&ul));
453                                 bp += sizeof(ul);
454                                 memcpy((char *)&ul, (char *)bp, sizeof(ul));
455                                 printf("%s)", ipaddr_string(&ul));
456                                 bp += sizeof(ul);
457                                 size -= 2*sizeof(ul);
458                                 first = 0;
459                         }
460                         break;
461
462                 case 's':
463                         /* shorts */
464                         while (size >= sizeof(us)) {
465                                 if (!first)
466                                         putchar(',');
467                                 us = EXTRACT_16BITS(bp);
468                                 printf("%d", us);
469                                 bp += sizeof(us);
470                                 size -= sizeof(us);
471                                 first = 0;
472                         }
473                         break;
474
475                 case 'B':
476                         /* boolean */
477                         while (size > 0) {
478                                 if (!first)
479                                         putchar(',');
480                                 switch (*bp) {
481                                 case 0:
482                                         putchar('N');
483                                         break;
484                                 case 1:
485                                         putchar('Y');
486                                         break;
487                                 default:
488                                         printf("%d?", *bp);
489                                         break;
490                                 }
491                                 ++bp;
492                                 --size;
493                                 first = 0;
494                         }
495                         break;
496
497                 case 'b':
498                 case 'x':
499                 default:
500                         /* Bytes */
501                         while (size > 0) {
502                                 if (!first)
503                                         putchar (c == 'x' ? ':' : '.');
504                                 printf (c == 'x' ? "%02x" : "%d", *bp);
505                                 ++bp;
506                                 --size;
507                                 first = 0;
508                         }
509                         break;
510                 }
511                 /* Data left over? */
512                 if (size)
513                         printf("[len %d]", len);
514         }
515         return;
516 trunc:
517         printf("|[rfc1048]");
518 }
519
520 static void
521 cmu_print(register const u_char *bp, register u_int length)
522 {
523         register const struct cmu_vend *cmu;
524         char *fmt = " %s:%s";
525
526 #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \
527     if (cmu->m.s_addr != 0) \
528         printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
529
530         printf(" vend-cmu");
531         cmu = (struct cmu_vend *)bp;
532
533         /* Only print if there are unknown bits */
534         TCHECK(cmu->v_flags);
535         if ((cmu->v_flags & ~(VF_SMASK)) != 0)
536                 printf(" F:0x%x", cmu->v_flags);
537         PRINTCMUADDR(v_dgate, "DG");
538         PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
539         PRINTCMUADDR(v_dns1, "NS1");
540         PRINTCMUADDR(v_dns2, "NS2");
541         PRINTCMUADDR(v_ins1, "IEN1");
542         PRINTCMUADDR(v_ins2, "IEN2");
543         PRINTCMUADDR(v_ts1, "TS1");
544         PRINTCMUADDR(v_ts2, "TS2");
545         return;
546
547 trunc:
548         fputs(tstr, stdout);
549 #undef PRINTCMUADDR
550 }