]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bootp.c
This commit was generated by cvs2svn to compensate for changes in r51292,
[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 #ifndef lint
24 static const char rcsid[] =
25     "@(#) $Header: print-bootp.c,v 1.46 98/07/18 13:33:58 leres Exp $ (LBL)";
26 #endif
27
28 #include <sys/param.h>
29 #include <sys/time.h>
30 #include <sys/socket.h>
31
32 #if __STDC__
33 struct mbuf;
34 struct rtentry;
35 #endif
36 #include <net/if.h>
37
38 #include <netinet/in.h>
39 #include <net/ethernet.h>
40
41 #include <ctype.h>
42 #ifdef HAVE_MEMORY_H
43 #include <memory.h>
44 #endif
45 #include <stdio.h>
46 #include <string.h>
47
48 #include "interface.h"
49 #include "addrtoname.h"
50 #include "bootp.h"
51
52 static void rfc1048_print(const u_char *, u_int);
53 static void cmu_print(const u_char *, u_int);
54
55 static char tstr[] = " [|bootp]";
56
57 /*
58  * Print bootp requests
59  */
60 void
61 bootp_print(register const u_char *cp, u_int length,
62             u_short sport, u_short dport)
63 {
64         register const struct bootp *bp;
65         static u_char vm_cmu[4] = VM_CMU;
66         static u_char vm_rfc1048[4] = VM_RFC1048;
67
68         bp = (struct bootp *)cp;
69         TCHECK(bp->bp_op);
70         switch (bp->bp_op) {
71
72         case BOOTREQUEST:
73                 /* Usually, a request goes from a client to a server */
74                 if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
75                         printf(" (request)");
76                 break;
77
78         case BOOTREPLY:
79                 /* Usually, a reply goes from a server to a client */
80                 if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
81                         printf(" (reply)");
82                 break;
83
84         default:
85                 printf(" bootp-#%d", bp->bp_op);
86         }
87
88         TCHECK(bp->bp_secs);
89
90         /* The usual hardware address type is 1 (10Mb Ethernet) */
91         if (bp->bp_htype != 1)
92                 printf(" htype-#%d", bp->bp_htype);
93
94         /* The usual length for 10Mb Ethernet address is 6 bytes */
95         if (bp->bp_htype != 1 || bp->bp_hlen != 6)
96                 printf(" hlen:%d", bp->bp_hlen);
97
98         /* Only print interesting fields */
99         if (bp->bp_hops)
100                 printf(" hops:%d", bp->bp_hops);
101         if (bp->bp_xid)
102                 printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid));
103         if (bp->bp_secs)
104                 printf(" secs:%d", ntohs(bp->bp_secs));
105
106         /* Client's ip address */
107         TCHECK(bp->bp_ciaddr);
108         if (bp->bp_ciaddr.s_addr)
109                 printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
110
111         /* 'your' ip address (bootp client) */
112         TCHECK(bp->bp_yiaddr);
113         if (bp->bp_yiaddr.s_addr)
114                 printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
115
116         /* Server's ip address */
117         TCHECK(bp->bp_siaddr);
118         if (bp->bp_siaddr.s_addr)
119                 printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
120
121         /* Gateway's ip address */
122         TCHECK(bp->bp_giaddr);
123         if (bp->bp_giaddr.s_addr)
124                 printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
125
126         /* Client's Ethernet address */
127         if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
128                 register const struct ether_header *eh;
129                 register const char *e;
130
131                 TCHECK2(bp->bp_chaddr[0], 6);
132                 eh = (struct ether_header *)packetp;
133                 if (bp->bp_op == BOOTREQUEST)
134                         e = (const char *)ESRC(eh);
135                 else if (bp->bp_op == BOOTREPLY)
136                         e = (const char *)EDST(eh);
137                 else
138                         e = 0;
139                 if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0)
140                         printf(" ether %s", etheraddr_string(bp->bp_chaddr));
141         }
142
143         TCHECK2(bp->bp_sname[0], 1);            /* check first char only */
144         if (*bp->bp_sname) {
145                 printf(" sname \"");
146                 if (fn_print(bp->bp_sname, snapend)) {
147                         putchar('"');
148                         fputs(tstr + 1, stdout);
149                         return;
150                 }
151                 putchar('"');
152         }
153         TCHECK2(bp->bp_sname[0], 1);            /* check first char only */
154         if (*bp->bp_file) {
155                 printf(" file \"");
156                 if (fn_print(bp->bp_file, snapend)) {
157                         putchar('"');
158                         fputs(tstr + 1, stdout);
159                         return;
160                 }
161                 putchar('"');
162         }
163
164         /* Decode the vendor buffer */
165         TCHECK(bp->bp_vend[0]);
166         length -= sizeof(*bp) - sizeof(bp->bp_vend);
167         if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
168                  sizeof(u_int32_t)) == 0)
169                 rfc1048_print(bp->bp_vend, length);
170         else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu,
171                       sizeof(u_int32_t)) == 0)
172                 cmu_print(bp->bp_vend, length);
173         else {
174                 u_int32_t ul;
175
176                 memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul));
177                 if (ul != 0)
178                         printf("vend-#0x%x", ul);
179         }
180
181         return;
182 trunc:
183         fputs(tstr, stdout);
184 }
185
186 /* The first character specifies the format to print */
187 static struct tok tag2str[] = {
188 /* RFC1048 tags */
189         { TAG_PAD,              " PAD" },
190         { TAG_SUBNET_MASK,      "iSM" },        /* subnet mask (RFC950) */
191         { TAG_TIME_OFFSET,      "lTZ" },        /* seconds from UTC */
192         { TAG_GATEWAY,          "iDG" },        /* default gateway */
193         { TAG_TIME_SERVER,      "iTS" },        /* time servers (RFC868) */
194         { TAG_NAME_SERVER,      "iIEN" },       /* IEN name servers (IEN116) */
195         { TAG_DOMAIN_SERVER,    "iNS" },        /* domain name (RFC1035) */
196         { TAG_LOG_SERVER,       "iLOG" },       /* MIT log servers */
197         { TAG_COOKIE_SERVER,    "iCS" },        /* cookie servers (RFC865) */
198         { TAG_LPR_SERVER,       "iLPR" },       /* lpr server (RFC1179) */
199         { TAG_IMPRESS_SERVER,   "iIM" },        /* impress servers (Imagen) */
200         { TAG_RLP_SERVER,       "iRL" },        /* resource location (RFC887) */
201         { TAG_HOSTNAME,         "aHN" },        /* ascii hostname */
202         { TAG_BOOTSIZE,         "sBS" },        /* 512 byte blocks */
203         { TAG_END,              " END" },
204 /* RFC1497 tags */
205         { TAG_DUMPPATH,         "aDP" },
206         { TAG_DOMAINNAME,       "aDN" },
207         { TAG_SWAP_SERVER,      "iSS" },
208         { TAG_ROOTPATH,         "aRP" },
209         { TAG_EXTPATH,          "aEP" },
210         { 0,                    NULL }
211 };
212
213 static void
214 rfc1048_print(register const u_char *bp, register u_int length)
215 {
216         register u_char tag;
217         register u_int len, size;
218         register const char *cp;
219         register char c;
220         int first;
221         u_int32_t ul;
222         u_short us;
223
224         printf(" vend-rfc1048");
225
226         /* Step over magic cookie */
227         bp += sizeof(int32_t);
228
229         /* Loop while we there is a tag left in the buffer */
230         while (bp + 1 < snapend) {
231                 tag = *bp++;
232                 if (tag == TAG_PAD)
233                         continue;
234                 if (tag == TAG_END)
235                         return;
236                 cp = tok2str(tag2str, "?T%d", tag);
237                 c = *cp++;
238                 printf(" %s:", cp);
239
240                 /* Get the length; check for truncation */
241                 if (bp + 1 >= snapend) {
242                         fputs(tstr, stdout);
243                         return;
244                 }
245                 len = *bp++;
246                 if (bp + len >= snapend) {
247                         fputs(tstr, stdout);
248                         return;
249                 }
250
251                 /* Print data */
252                 size = len;
253                 if (c == '?') {
254                         /* Base default formats for unknown tags on data size */
255                         if (size & 1)
256                                 c = 'b';
257                         else if (size & 2)
258                                 c = 's';
259                         else
260                                 c = 'l';
261                 }
262                 first = 1;
263                 switch (c) {
264
265                 case 'a':
266                         /* ascii strings */
267                         putchar('"');
268                         (void)fn_printn(bp, size, NULL);
269                         putchar('"');
270                         bp += size;
271                         size = 0;
272                         break;
273
274                 case 'i':
275                 case 'l':
276                         /* ip addresses/32-bit words */
277                         while (size >= sizeof(ul)) {
278                                 if (!first)
279                                         putchar(',');
280                                 memcpy((char *)&ul, (char *)bp, sizeof(ul));
281                                 if (c == 'i')
282                                         printf("%s", ipaddr_string(&ul));
283                                 else
284                                         printf("%u", ul);
285                                 bp += sizeof(ul);
286                                 size -= sizeof(ul);
287                                 first = 0;
288                         }
289                         break;
290
291                 case 's':
292                         /* shorts */
293                         while (size >= sizeof(us)) {
294                                 if (!first)
295                                         putchar(',');
296                                 memcpy((char *)&us, (char *)bp, sizeof(us));
297                                 printf("%d", us);
298                                 bp += sizeof(us);
299                                 size -= sizeof(us);
300                                 first = 0;
301                         }
302                         break;
303
304                 case 'b':
305                 default:
306                         /* Bytes */
307                         while (size > 0) {
308                                 if (!first)
309                                         putchar('.');
310                                 printf("%d", *bp);
311                                 ++bp;
312                                 --size;
313                                 first = 0;
314                         }
315                         break;
316                 }
317                 /* Data left over? */
318                 if (size)
319                         printf("[len %d]", len);
320         }
321 }
322
323 static void
324 cmu_print(register const u_char *bp, register u_int length)
325 {
326         register const struct cmu_vend *cmu;
327         char *fmt = " %s:%s";
328
329 #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \
330     if (cmu->m.s_addr != 0) \
331         printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
332
333         printf(" vend-cmu");
334         cmu = (struct cmu_vend *)bp;
335
336         /* Only print if there are unknown bits */
337         TCHECK(cmu->v_flags);
338         if ((cmu->v_flags & ~(VF_SMASK)) != 0)
339                 printf(" F:0x%x", cmu->v_flags);
340         PRINTCMUADDR(v_dgate, "DG");
341         PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
342         PRINTCMUADDR(v_dns1, "NS1");
343         PRINTCMUADDR(v_dns2, "NS2");
344         PRINTCMUADDR(v_ins1, "IEN1");
345         PRINTCMUADDR(v_ins2, "IEN2");
346         PRINTCMUADDR(v_ts1, "TS1");
347         PRINTCMUADDR(v_ts2, "TS2");
348         return;
349
350 trunc:
351         fputs(tstr, stdout);
352 #undef PRINTCMUADDR
353 }