Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/libexec/bootpd/tools/bootptest/print-bootp.c
34874 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1988-1990
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that:
9
* 1. Source code distributions retain the above copyright
10
* notice and this paragraph in its entirety
11
* 2. Distributions including binary code include the above copyright
12
* notice and this paragraph in its entirety in the documentation
13
* or other materials provided with the distribution, and
14
* 3. Neither the name of the University nor the names of its contributors
15
* may be used to endorse or promote products derived from this software
16
* without specific prior written permission.
17
*
18
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21
*
22
* Format and print bootp packets.
23
*
24
* This file was copied from tcpdump-2.1.1 and modified.
25
* There is an e-mail list for tcpdump: <[email protected]>
26
*/
27
28
#include <stdio.h>
29
30
#include <sys/param.h>
31
#include <sys/types.h>
32
#include <sys/socket.h>
33
34
#include <sys/time.h> /* for struct timeval in net/if.h */
35
#include <net/if.h>
36
#include <netinet/in.h>
37
38
#include <string.h>
39
#include <ctype.h>
40
41
#include "bootp.h"
42
#include "bootptest.h"
43
44
/* These decode the vendor data. */
45
static void rfc1048_print(u_char *bp, int length);
46
static void cmu_print(u_char *bp, int length);
47
static void other_print(u_char *bp, int length);
48
static void dump_hex(u_char *bp, int len);
49
50
/*
51
* Print bootp requests
52
*/
53
void
54
bootp_print(struct bootp *bp, int length, u_short sport, u_short dport)
55
{
56
static char tstr[] = " [|bootp]";
57
static unsigned char vm_cmu[4] = VM_CMU;
58
static unsigned char vm_rfc1048[4] = VM_RFC1048;
59
u_char *ep;
60
int vdlen;
61
62
#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
63
64
/* Note funny sized packets */
65
if (length != sizeof(struct bootp))
66
(void) printf(" [len=%d]", length);
67
68
/* 'ep' points to the end of available data. */
69
ep = (u_char *) snapend;
70
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
/* 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_hlen != 6)
95
printf(" hlen:%d", bp->bp_hlen);
96
97
/* Client's Hardware address */
98
if (bp->bp_hlen) {
99
struct ether_header *eh;
100
char *e;
101
102
TCHECK(bp->bp_chaddr[0], 6);
103
eh = (struct ether_header *) packetp;
104
if (bp->bp_op == BOOTREQUEST)
105
e = (char *) ESRC(eh);
106
else if (bp->bp_op == BOOTREPLY)
107
e = (char *) EDST(eh);
108
else
109
e = NULL;
110
if (e == NULL || bcmp((char *) bp->bp_chaddr, e, 6))
111
dump_hex(bp->bp_chaddr, bp->bp_hlen);
112
}
113
/* Only print interesting fields */
114
if (bp->bp_hops)
115
printf(" hops:%d", bp->bp_hops);
116
117
if (bp->bp_xid)
118
printf(" xid:%ld", (long)ntohl(bp->bp_xid));
119
120
if (bp->bp_secs)
121
printf(" secs:%d", ntohs(bp->bp_secs));
122
123
/* Client's ip address */
124
TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
125
if (bp->bp_ciaddr.s_addr)
126
printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
127
128
/* 'your' ip address (bootp client) */
129
TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
130
if (bp->bp_yiaddr.s_addr)
131
printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
132
133
/* Server's ip address */
134
TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
135
if (bp->bp_siaddr.s_addr)
136
printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
137
138
/* Gateway's ip address */
139
TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
140
if (bp->bp_giaddr.s_addr)
141
printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
142
143
TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));
144
if (*bp->bp_sname) {
145
printf(" sname:");
146
if (printfn(bp->bp_sname, ep)) {
147
fputs(tstr + 1, stdout);
148
return;
149
}
150
}
151
TCHECK(bp->bp_file[0], sizeof(bp->bp_file));
152
if (*bp->bp_file) {
153
printf(" file:");
154
if (printfn(bp->bp_file, ep)) {
155
fputs(tstr + 1, stdout);
156
return;
157
}
158
}
159
/* Don't try to decode the vendor buffer unless we're verbose */
160
if (vflag <= 0)
161
return;
162
163
vdlen = sizeof(bp->bp_vend);
164
/* Vendor data can extend to the end of the packet. */
165
if (vdlen < (ep - bp->bp_vend))
166
vdlen = (ep - bp->bp_vend);
167
168
TCHECK(bp->bp_vend[0], vdlen);
169
printf(" vend");
170
if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_int32)))
171
rfc1048_print(bp->bp_vend, vdlen);
172
else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_int32)))
173
cmu_print(bp->bp_vend, vdlen);
174
else
175
other_print(bp->bp_vend, vdlen);
176
177
return;
178
trunc:
179
fputs(tstr, stdout);
180
#undef TCHECK
181
}
182
183
/*
184
* Option description data follows.
185
* These are described in: RFC-1048, RFC-1395, RFC-1497, RFC-1533
186
*
187
* The first char of each option string encodes the data format:
188
* ?: unknown
189
* a: ASCII
190
* b: byte (8-bit)
191
* i: inet address
192
* l: int32
193
* s: short (16-bit)
194
*/
195
char *
196
rfc1048_opts[] = {
197
/* Originally from RFC-1048: */
198
"?PAD", /* 0: Padding - special, no data. */
199
"iSM", /* 1: subnet mask (RFC950)*/
200
"lTZ", /* 2: time offset, seconds from UTC */
201
"iGW", /* 3: gateways (or routers) */
202
"iTS", /* 4: time servers (RFC868) */
203
"iINS", /* 5: IEN name servers (IEN116) */
204
"iDNS", /* 6: domain name servers (RFC1035)(1034?) */
205
"iLOG", /* 7: MIT log servers */
206
"iCS", /* 8: cookie servers (RFC865) */
207
"iLPR", /* 9: lpr server (RFC1179) */
208
"iIPS", /* 10: impress servers (Imagen) */
209
"iRLP", /* 11: resource location servers (RFC887) */
210
"aHN", /* 12: host name (ASCII) */
211
"sBFS", /* 13: boot file size (in 512 byte blocks) */
212
213
/* Added by RFC-1395: */
214
"aDUMP", /* 14: Merit Dump File */
215
"aDNAM", /* 15: Domain Name (for DNS) */
216
"iSWAP", /* 16: Swap Server */
217
"aROOT", /* 17: Root Path */
218
219
/* Added by RFC-1497: */
220
"aEXTF", /* 18: Extensions Path (more options) */
221
222
/* Added by RFC-1533: (many, many options...) */
223
#if 1 /* These might not be worth recognizing by name. */
224
225
/* IP Layer Parameters, per-host (RFC-1533, sect. 4) */
226
"bIP-forward", /* 19: IP Forwarding flag */
227
"bIP-srcroute", /* 20: IP Source Routing Enable flag */
228
"iIP-filters", /* 21: IP Policy Filter (addr pairs) */
229
"sIP-maxudp", /* 22: IP Max-UDP reassembly size */
230
"bIP-ttlive", /* 23: IP Time to Live */
231
"lIP-pmtuage", /* 24: IP Path MTU aging timeout */
232
"sIP-pmtutab", /* 25: IP Path MTU plateau table */
233
234
/* IP parameters, per-interface (RFC-1533, sect. 5) */
235
"sIP-mtu-sz", /* 26: IP MTU size */
236
"bIP-mtu-sl", /* 27: IP MTU all subnets local */
237
"bIP-bcast1", /* 28: IP Broadcast Addr ones flag */
238
"bIP-mask-d", /* 29: IP do mask discovery */
239
"bIP-mask-s", /* 30: IP do mask supplier */
240
"bIP-rt-dsc", /* 31: IP do router discovery */
241
"iIP-rt-sa", /* 32: IP router solicitation addr */
242
"iIP-routes", /* 33: IP static routes (dst,router) */
243
244
/* Link Layer parameters, per-interface (RFC-1533, sect. 6) */
245
"bLL-trailer", /* 34: do trailer encapsulation */
246
"lLL-arp-tmo", /* 35: ARP cache timeout */
247
"bLL-ether2", /* 36: Ethernet version 2 (IEEE 802.3) */
248
249
/* TCP parameters (RFC-1533, sect. 7) */
250
"bTCP-def-ttl", /* 37: default time to live */
251
"lTCP-KA-tmo", /* 38: keepalive time interval */
252
"bTCP-KA-junk", /* 39: keepalive sends extra junk */
253
254
/* Application and Service Parameters (RFC-1533, sect. 8) */
255
"aNISDOM", /* 40: NIS Domain (Sun YP) */
256
"iNISSRV", /* 41: NIS Servers */
257
"iNTPSRV", /* 42: NTP (time) Servers (RFC 1129) */
258
"?VSINFO", /* 43: Vendor Specific Info (encapsulated) */
259
"iNBiosNS", /* 44: NetBIOS Name Server (RFC-1001,1..2) */
260
"iNBiosDD", /* 45: NetBIOS Datagram Dist. Server. */
261
"bNBiosNT", /* 46: NetBIOS Note Type */
262
"?NBiosS", /* 47: NetBIOS Scope */
263
"iXW-FS", /* 48: X Window System Font Servers */
264
"iXW-DM", /* 49: X Window System Display Managers */
265
266
/* DHCP extensions (RFC-1533, sect. 9) */
267
#endif
268
};
269
#define KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))
270
271
static void
272
rfc1048_print(u_char *bp, int length)
273
{
274
u_char tag;
275
u_char *ep;
276
int len;
277
u_int32 ul;
278
u_short us;
279
struct in_addr ia;
280
char *optstr;
281
282
printf("-rfc1395");
283
284
/* Step over magic cookie */
285
bp += sizeof(int32);
286
/* Setup end pointer */
287
ep = bp + length;
288
while (bp < ep) {
289
tag = *bp++;
290
/* Check for tags with no data first. */
291
if (tag == TAG_PAD)
292
continue;
293
if (tag == TAG_END)
294
return;
295
if (tag < KNOWN_OPTIONS) {
296
optstr = rfc1048_opts[tag];
297
printf(" %s:", optstr + 1);
298
} else {
299
printf(" T%d:", tag);
300
optstr = "?";
301
}
302
/* Now scan the length byte. */
303
len = *bp++;
304
if (bp + len > ep) {
305
/* truncated option */
306
printf(" |(%d>%td)", len, ep - bp);
307
return;
308
}
309
/* Print the option value(s). */
310
switch (optstr[0]) {
311
312
case 'a': /* ASCII string */
313
printfn(bp, bp + len);
314
bp += len;
315
len = 0;
316
break;
317
318
case 's': /* Word formats */
319
while (len >= 2) {
320
bcopy((char *) bp, (char *) &us, 2);
321
printf("%d", ntohs(us));
322
bp += 2;
323
len -= 2;
324
if (len) printf(",");
325
}
326
if (len) printf("(junk=%d)", len);
327
break;
328
329
case 'l': /* Long words */
330
while (len >= 4) {
331
bcopy((char *) bp, (char *) &ul, 4);
332
printf("%ld", (long)ntohl(ul));
333
bp += 4;
334
len -= 4;
335
if (len) printf(",");
336
}
337
if (len) printf("(junk=%d)", len);
338
break;
339
340
case 'i': /* INET addresses */
341
while (len >= 4) {
342
bcopy((char *) bp, (char *) &ia, 4);
343
printf("%s", ipaddr_string(&ia));
344
bp += 4;
345
len -= 4;
346
if (len) printf(",");
347
}
348
if (len) printf("(junk=%d)", len);
349
break;
350
351
case 'b':
352
default:
353
break;
354
355
} /* switch */
356
357
/* Print as characters, if appropriate. */
358
if (len) {
359
dump_hex(bp, len);
360
if (isascii(*bp) && isprint(*bp)) {
361
printf("(");
362
printfn(bp, bp + len);
363
printf(")");
364
}
365
bp += len;
366
len = 0;
367
}
368
} /* while bp < ep */
369
}
370
371
static void
372
cmu_print(u_char *bp, int length)
373
{
374
struct cmu_vend *v;
375
376
printf("-cmu");
377
378
v = (struct cmu_vend *) bp;
379
if (length < sizeof(*v)) {
380
printf(" |L=%d", length);
381
return;
382
}
383
384
/* Subnet mask */
385
if (v->v_flags & VF_SMASK) {
386
printf(" SM:%s", ipaddr_string(&v->v_smask));
387
}
388
/* Default gateway */
389
if (v->v_dgate.s_addr)
390
printf(" GW:%s", ipaddr_string(&v->v_dgate));
391
392
/* Domain name servers */
393
if (v->v_dns1.s_addr)
394
printf(" DNS1:%s", ipaddr_string(&v->v_dns1));
395
if (v->v_dns2.s_addr)
396
printf(" DNS2:%s", ipaddr_string(&v->v_dns2));
397
398
/* IEN-116 name servers */
399
if (v->v_ins1.s_addr)
400
printf(" INS1:%s", ipaddr_string(&v->v_ins1));
401
if (v->v_ins2.s_addr)
402
printf(" INS2:%s", ipaddr_string(&v->v_ins2));
403
404
/* Time servers */
405
if (v->v_ts1.s_addr)
406
printf(" TS1:%s", ipaddr_string(&v->v_ts1));
407
if (v->v_ts2.s_addr)
408
printf(" TS2:%s", ipaddr_string(&v->v_ts2));
409
410
}
411
412
413
/*
414
* Print out arbitrary, unknown vendor data.
415
*/
416
417
static void
418
other_print(u_char *bp, int length)
419
{
420
u_char *ep; /* end pointer */
421
u_char *zp; /* points one past last non-zero byte */
422
423
/* Setup end pointer */
424
ep = bp + length;
425
426
/* Find the last non-zero byte. */
427
for (zp = ep; zp > bp; zp--) {
428
if (zp[-1] != 0)
429
break;
430
}
431
432
/* Print the all-zero case in a compact representation. */
433
if (zp == bp) {
434
printf("-all-zero");
435
return;
436
}
437
printf("-unknown");
438
439
/* Are there enough trailing zeros to make "00..." worthwhile? */
440
if (zp + 2 > ep)
441
zp = ep; /* print them all normally */
442
443
/* Now just print all the non-zero data. */
444
while (bp < zp) {
445
printf(".%02X", *bp);
446
bp++;
447
}
448
449
if (zp < ep)
450
printf(".00...");
451
452
return;
453
}
454
455
static void
456
dump_hex(u_char *bp, int len)
457
{
458
while (len > 0) {
459
printf("%02X", *bp);
460
bp++;
461
len--;
462
if (len) printf(".");
463
}
464
}
465
466
/*
467
* Local Variables:
468
* tab-width: 4
469
* c-indent-level: 4
470
* c-argdecl-indent: 4
471
* c-continued-statement-offset: 4
472
* c-continued-brace-offset: -4
473
* c-label-offset: -4
474
* c-brace-offset: 0
475
* End:
476
*/
477
478