1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
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 * Support for splitting captures into multiple files with a maximum
22 * file size:
23 *
24 * Copyright (c) 2001
25 * Seth Webster <swebster@sst.ll.mit.edu>
26 */
27
28 #include <sys/cdefs.h>
29 #ifndef lint
30 __RCSID("$NetBSD: print.c,v 1.6 2024/09/02 16:15:33 christos Exp $");
31 #endif
32
33 #include <config.h>
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <setjmp.h>
38
39 #include "netdissect-stdinc.h"
40
41 #include "netdissect.h"
42 #include "addrtoname.h"
43 #include "print.h"
44 #include "netdissect-alloc.h"
45
46 #include "pcap-missing.h"
47
48 struct printer {
49 if_printer f;
50 int type;
51 };
52
53 static const struct printer printers[] = {
54 #ifdef DLT_APPLE_IP_OVER_IEEE1394
55 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 },
56 #endif
57 { arcnet_if_print, DLT_ARCNET },
58 #ifdef DLT_ARCNET_LINUX
59 { arcnet_linux_if_print, DLT_ARCNET_LINUX },
60 #endif
61 { atm_if_print, DLT_ATM_RFC1483 },
62 #ifdef DLT_DSA_TAG_BRCM
63 { brcm_tag_if_print, DLT_DSA_TAG_BRCM },
64 #endif
65 #ifdef DLT_DSA_TAG_BRCM_PREPEND
66 { brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND },
67 #endif
68 #ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR
69 { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
70 #endif
71 #ifdef DLT_C_HDLC
72 { chdlc_if_print, DLT_C_HDLC },
73 #endif
74 #ifdef DLT_HDLC
75 { chdlc_if_print, DLT_HDLC },
76 #endif
77 #ifdef DLT_ATM_CLIP
78 { cip_if_print, DLT_ATM_CLIP },
79 #endif
80 #ifdef DLT_CIP
81 { cip_if_print, DLT_CIP },
82 #endif
83 #ifdef DLT_DSA_TAG_DSA
84 { dsa_if_print, DLT_DSA_TAG_DSA },
85 #endif
86 #ifdef DLT_DSA_TAG_EDSA
87 { edsa_if_print, DLT_DSA_TAG_EDSA },
88 #endif
89 #ifdef DLT_ENC
90 { enc_if_print, DLT_ENC },
91 #endif
92 { ether_if_print, DLT_EN10MB },
93 { fddi_if_print, DLT_FDDI },
94 #ifdef DLT_FR
95 { fr_if_print, DLT_FR },
96 #endif
97 #ifdef DLT_FRELAY
98 { fr_if_print, DLT_FRELAY },
99 #endif
100 #ifdef DLT_IEEE802_11
101 { ieee802_11_if_print, DLT_IEEE802_11},
102 #endif
103 #ifdef DLT_IEEE802_11_RADIO_AVS
104 { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS },
105 #endif
106 #ifdef DLT_IEEE802_11_RADIO
107 { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO },
108 #endif
109 #ifdef DLT_IEEE802_15_4
110 { ieee802_15_4_if_print, DLT_IEEE802_15_4 },
111 #endif
112 #ifdef DLT_IEEE802_15_4_NOFCS
113 { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
114 #endif
115 #ifdef DLT_IEEE802_15_4_TAP
116 { ieee802_15_4_tap_if_print, DLT_IEEE802_15_4_TAP },
117 #endif
118 #ifdef DLT_IP_OVER_FC
119 { ipfc_if_print, DLT_IP_OVER_FC },
120 #endif
121 #ifdef DLT_IPNET
122 { ipnet_if_print, DLT_IPNET },
123 #endif
124 #ifdef DLT_IPOIB
125 { ipoib_if_print, DLT_IPOIB },
126 #endif
127 #ifdef DLT_JUNIPER_ATM1
128 { juniper_atm1_if_print, DLT_JUNIPER_ATM1 },
129 #endif
130 #ifdef DLT_JUNIPER_ATM2
131 { juniper_atm2_if_print, DLT_JUNIPER_ATM2 },
132 #endif
133 #ifdef DLT_JUNIPER_CHDLC
134 { juniper_chdlc_if_print, DLT_JUNIPER_CHDLC },
135 #endif
136 #ifdef DLT_JUNIPER_ES
137 { juniper_es_if_print, DLT_JUNIPER_ES },
138 #endif
139 #ifdef DLT_JUNIPER_ETHER
140 { juniper_ether_if_print, DLT_JUNIPER_ETHER },
141 #endif
142 #ifdef DLT_JUNIPER_FRELAY
143 { juniper_frelay_if_print, DLT_JUNIPER_FRELAY },
144 #endif
145 #ifdef DLT_JUNIPER_GGSN
146 { juniper_ggsn_if_print, DLT_JUNIPER_GGSN },
147 #endif
148 #ifdef DLT_JUNIPER_MFR
149 { juniper_mfr_if_print, DLT_JUNIPER_MFR },
150 #endif
151 #ifdef DLT_JUNIPER_MLFR
152 { juniper_mlfr_if_print, DLT_JUNIPER_MLFR },
153 #endif
154 #ifdef DLT_JUNIPER_MLPPP
155 { juniper_mlppp_if_print, DLT_JUNIPER_MLPPP },
156 #endif
157 #ifdef DLT_JUNIPER_MONITOR
158 { juniper_monitor_if_print, DLT_JUNIPER_MONITOR },
159 #endif
160 #ifdef DLT_JUNIPER_PPP
161 { juniper_ppp_if_print, DLT_JUNIPER_PPP },
162 #endif
163 #ifdef DLT_JUNIPER_PPPOE_ATM
164 { juniper_pppoe_atm_if_print, DLT_JUNIPER_PPPOE_ATM },
165 #endif
166 #ifdef DLT_JUNIPER_PPPOE
167 { juniper_pppoe_if_print, DLT_JUNIPER_PPPOE },
168 #endif
169 #ifdef DLT_JUNIPER_SERVICES
170 { juniper_services_if_print, DLT_JUNIPER_SERVICES },
171 #endif
172 #ifdef DLT_LTALK
173 { ltalk_if_print, DLT_LTALK },
174 #endif
175 #ifdef DLT_MFR
176 { mfr_if_print, DLT_MFR },
177 #endif
178 #ifdef DLT_NETANALYZER
179 { netanalyzer_if_print, DLT_NETANALYZER },
180 #endif
181 #ifdef DLT_NETANALYZER_TRANSPARENT
182 { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
183 #endif
184 #ifdef DLT_NFLOG
185 { nflog_if_print, DLT_NFLOG},
186 #endif
187 { null_if_print, DLT_NULL },
188 #ifdef DLT_LOOP
189 { null_if_print, DLT_LOOP },
190 #endif
191 #ifdef DLT_PFLOG
192 { pflog_if_print, DLT_PFLOG },
193 #endif
194 #ifdef DLT_PKTAP
195 { pktap_if_print, DLT_PKTAP },
196 #endif
197 #ifdef DLT_PPI
198 { ppi_if_print, DLT_PPI },
199 #endif
200 #ifdef DLT_PPP_BSDOS
201 { ppp_bsdos_if_print, DLT_PPP_BSDOS },
202 #endif
203 #ifdef DLT_PPP_SERIAL
204 { ppp_hdlc_if_print, DLT_PPP_SERIAL },
205 #endif
206 { ppp_if_print, DLT_PPP },
207 #ifdef DLT_PPP_PPPD
208 { ppp_if_print, DLT_PPP_PPPD },
209 #endif
210 #ifdef DLT_PPP_ETHER
211 { pppoe_if_print, DLT_PPP_ETHER },
212 #endif
213 #ifdef DLT_PRISM_HEADER
214 { prism_if_print, DLT_PRISM_HEADER },
215 #endif
216 { raw_if_print, DLT_RAW },
217 #ifdef DLT_IPV4
218 { raw_if_print, DLT_IPV4 },
219 #endif
220 #ifdef DLT_IPV6
221 { raw_if_print, DLT_IPV6 },
222 #endif
223 #ifdef DLT_SLIP_BSDOS
224 { sl_bsdos_if_print, DLT_SLIP_BSDOS },
225 #endif
226 { sl_if_print, DLT_SLIP },
227 #ifdef DLT_LINUX_SLL
228 { sll_if_print, DLT_LINUX_SLL },
229 #endif
230 #ifdef DLT_LINUX_SLL2
231 { sll2_if_print, DLT_LINUX_SLL2 },
232 #endif
233 #ifdef DLT_SUNATM
234 { sunatm_if_print, DLT_SUNATM },
235 #endif
236 #ifdef DLT_SYMANTEC_FIREWALL
237 { symantec_if_print, DLT_SYMANTEC_FIREWALL },
238 #endif
239 { token_if_print, DLT_IEEE802 },
240 #ifdef DLT_USB_LINUX
241 { usb_linux_48_byte_if_print, DLT_USB_LINUX},
242 #endif /* DLT_USB_LINUX */
243 #ifdef DLT_USB_LINUX_MMAPPED
244 { usb_linux_64_byte_if_print, DLT_USB_LINUX_MMAPPED},
245 #endif /* DLT_USB_LINUX_MMAPPED */
246 #ifdef DLT_VSOCK
247 { vsock_if_print, DLT_VSOCK },
248 #endif
249 #ifdef DLT_PFSYNC
250 { pfsync_if_print, DLT_PFSYNC },
251 #endif
252 { NULL, 0 },
253 };
254
255 static void ndo_default_print(netdissect_options *ndo, const u_char *bp,
256 u_int length);
257
258 static void NORETURN ndo_error(netdissect_options *ndo,
259 status_exit_codes_t status,
260 FORMAT_STRING(const char *fmt), ...)
261 PRINTFLIKE(3, 4);
262 static void ndo_warning(netdissect_options *ndo,
263 FORMAT_STRING(const char *fmt), ...)
264 PRINTFLIKE(2, 3);
265
266 static int ndo_printf(netdissect_options *ndo,
267 FORMAT_STRING(const char *fmt), ...)
268 PRINTFLIKE(2, 3);
269
270 void
init_print(netdissect_options * ndo,uint32_t localnet,uint32_t mask)271 init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask)
272 {
273 init_addrtoname(ndo, localnet, mask);
274 }
275
276 if_printer
lookup_printer(int type)277 lookup_printer(int type)
278 {
279 const struct printer *p;
280
281 for (p = printers; p->f; ++p)
282 if (type == p->type)
283 return p->f;
284
285 #if defined(DLT_USER2) && defined(DLT_PKTAP)
286 /*
287 * Apple incorrectly chose to use DLT_USER2 for their PKTAP
288 * header.
289 *
290 * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
291 * based OSes or the same value as LINKTYPE_PKTAP as it is on
292 * other OSes, to LINKTYPE_PKTAP, so files written with
293 * this version of libpcap for a DLT_PKTAP capture have a link-
294 * layer header type of LINKTYPE_PKTAP.
295 *
296 * However, files written on OS X Mavericks for a DLT_PKTAP
297 * capture have a link-layer header type of LINKTYPE_USER2.
298 * If we don't have a printer for DLT_USER2, and type is
299 * DLT_USER2, we look up the printer for DLT_PKTAP and use
300 * that.
301 */
302 if (type == DLT_USER2) {
303 for (p = printers; p->f; ++p)
304 if (DLT_PKTAP == p->type)
305 return p->f;
306 }
307 #endif
308
309 return NULL;
310 /* NOTREACHED */
311 }
312
313 int
has_printer(int type)314 has_printer(int type)
315 {
316 return (lookup_printer(type) != NULL);
317 }
318
319 if_printer
get_if_printer(int type)320 get_if_printer(int type)
321 {
322 if_printer printer;
323
324 printer = lookup_printer(type);
325 if (printer == NULL)
326 printer = unsupported_if_print;
327 return printer;
328 }
329
330 #ifdef ENABLE_INSTRUMENT_FUNCTIONS
331 extern int profile_func_level;
332 static int pretty_print_packet_level = -1;
333 #endif
334
335 void
pretty_print_packet(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * sp,u_int packets_captured)336 pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
337 const u_char *sp, u_int packets_captured)
338 {
339 u_int hdrlen = 0;
340 int invalid_header = 0;
341
342 #ifdef ENABLE_INSTRUMENT_FUNCTIONS
343 if (pretty_print_packet_level == -1)
344 pretty_print_packet_level = profile_func_level;
345 #endif
346
347 if (ndo->ndo_packet_number)
348 ND_PRINT("%5u ", packets_captured);
349
350 /* Sanity checks on packet length / capture length */
351 if (h->caplen == 0) {
352 invalid_header = 1;
353 ND_PRINT("[Invalid header: caplen==0");
354 }
355 if (h->len == 0) {
356 if (!invalid_header) {
357 invalid_header = 1;
358 ND_PRINT("[Invalid header:");
359 } else
360 ND_PRINT(",");
361 ND_PRINT(" len==0");
362 } else if (h->len < h->caplen) {
363 if (!invalid_header) {
364 invalid_header = 1;
365 ND_PRINT("[Invalid header:");
366 } else
367 ND_PRINT(",");
368 ND_PRINT(" len(%u) < caplen(%u)", h->len, h->caplen);
369 }
370 if (h->caplen > MAXIMUM_SNAPLEN) {
371 if (!invalid_header) {
372 invalid_header = 1;
373 ND_PRINT("[Invalid header:");
374 } else
375 ND_PRINT(",");
376 ND_PRINT(" caplen(%u) > %u", h->caplen, MAXIMUM_SNAPLEN);
377 }
378 if (h->len > MAXIMUM_SNAPLEN) {
379 if (!invalid_header) {
380 invalid_header = 1;
381 ND_PRINT("[Invalid header:");
382 } else
383 ND_PRINT(",");
384 ND_PRINT(" len(%u) > %u", h->len, MAXIMUM_SNAPLEN);
385 }
386 if (invalid_header) {
387 ND_PRINT("]\n");
388 return;
389 }
390
391 /*
392 * At this point:
393 * capture length != 0,
394 * packet length != 0,
395 * capture length <= MAXIMUM_SNAPLEN,
396 * packet length <= MAXIMUM_SNAPLEN,
397 * packet length >= capture length.
398 *
399 * Currently, there is no D-Bus printer, thus no need for
400 * bigger lengths.
401 */
402
403 /*
404 * The header /usr/include/pcap/pcap.h in OpenBSD declares h->ts as
405 * struct bpf_timeval, not struct timeval. The former comes from
406 * /usr/include/net/bpf.h and uses 32-bit unsigned types instead of
407 * the types used in struct timeval.
408 */
409 struct timeval tvbuf;
410 tvbuf.tv_sec = h->ts.tv_sec;
411 tvbuf.tv_usec = h->ts.tv_usec;
412 ts_print(ndo, &tvbuf);
413
414 /*
415 * Printers must check that they're not walking off the end of
416 * the packet.
417 * Rather than pass it all the way down, we set this member
418 * of the netdissect_options structure.
419 */
420 ndo->ndo_snapend = sp + h->caplen;
421 ndo->ndo_packetp = sp;
422
423 ndo->ndo_protocol = "";
424 ndo->ndo_ll_hdr_len = 0;
425 switch (setjmp(ndo->ndo_early_end)) {
426 case 0:
427 /* Print the packet. */
428 (ndo->ndo_if_printer)(ndo, h, sp);
429 break;
430 case ND_TRUNCATED:
431 /* A printer quit because the packet was truncated; report it */
432 nd_print_trunc(ndo);
433 /* Print the full packet */
434 ndo->ndo_ll_hdr_len = 0;
435 #ifdef ENABLE_INSTRUMENT_FUNCTIONS
436 /* truncation => reassignment */
437 profile_func_level = pretty_print_packet_level;
438 #endif
439 break;
440 }
441 hdrlen = ndo->ndo_ll_hdr_len;
442
443 /*
444 * Empty the stack of packet information, freeing all pushed buffers;
445 * if we got here by a printer quitting, we need to release anything
446 * that didn't get released because we longjmped out of the code
447 * before it popped the packet information.
448 */
449 nd_pop_all_packet_info(ndo);
450
451 /*
452 * Restore the originals snapend and packetp, as a printer
453 * might have changed them.
454 *
455 * XXX - nd_pop_all_packet_info() should have restored the
456 * original values, but, just in case....
457 */
458 ndo->ndo_snapend = sp + h->caplen;
459 ndo->ndo_packetp = sp;
460 if (ndo->ndo_Xflag) {
461 /*
462 * Print the raw packet data in hex and ASCII.
463 */
464 if (ndo->ndo_Xflag > 1) {
465 /*
466 * Include the link-layer header.
467 */
468 hex_and_ascii_print(ndo, "\n\t", sp, h->caplen);
469 } else {
470 /*
471 * Don't include the link-layer header - and if
472 * we have nothing past the link-layer header,
473 * print nothing.
474 */
475 if (h->caplen > hdrlen)
476 hex_and_ascii_print(ndo, "\n\t", sp + hdrlen,
477 h->caplen - hdrlen);
478 }
479 } else if (ndo->ndo_xflag) {
480 /*
481 * Print the raw packet data in hex.
482 */
483 if (ndo->ndo_xflag > 1) {
484 /*
485 * Include the link-layer header.
486 */
487 hex_print(ndo, "\n\t", sp, h->caplen);
488 } else {
489 /*
490 * Don't include the link-layer header - and if
491 * we have nothing past the link-layer header,
492 * print nothing.
493 */
494 if (h->caplen > hdrlen)
495 hex_print(ndo, "\n\t", sp + hdrlen,
496 h->caplen - hdrlen);
497 }
498 } else if (ndo->ndo_Aflag) {
499 /*
500 * Print the raw packet data in ASCII.
501 */
502 if (ndo->ndo_Aflag > 1) {
503 /*
504 * Include the link-layer header.
505 */
506 ascii_print(ndo, sp, h->caplen);
507 } else {
508 /*
509 * Don't include the link-layer header - and if
510 * we have nothing past the link-layer header,
511 * print nothing.
512 */
513 if (h->caplen > hdrlen)
514 ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen);
515 }
516 }
517
518 ND_PRINT("\n");
519 nd_free_all(ndo);
520 }
521
522 /*
523 * By default, print the specified data out in hex and ASCII.
524 */
525 static void
ndo_default_print(netdissect_options * ndo,const u_char * bp,u_int length)526 ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length)
527 {
528 hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */
529 }
530
531 /* VARARGS */
532 static void
ndo_error(netdissect_options * ndo,status_exit_codes_t status,const char * fmt,...)533 ndo_error(netdissect_options *ndo, status_exit_codes_t status,
534 const char *fmt, ...)
535 {
536 va_list ap;
537
538 if (ndo->program_name)
539 (void)fprintf(stderr, "%s: ", ndo->program_name);
540 va_start(ap, fmt);
541 (void)vfprintf(stderr, fmt, ap);
542 va_end(ap);
543 if (*fmt) {
544 fmt += strlen(fmt);
545 if (fmt[-1] != '\n')
546 (void)fputc('\n', stderr);
547 }
548 nd_cleanup();
549 exit(status);
550 /* NOTREACHED */
551 }
552
553 /* VARARGS */
554 static void
ndo_warning(netdissect_options * ndo,const char * fmt,...)555 ndo_warning(netdissect_options *ndo, const char *fmt, ...)
556 {
557 va_list ap;
558
559 if (ndo->program_name)
560 (void)fprintf(stderr, "%s: ", ndo->program_name);
561 (void)fprintf(stderr, "WARNING: ");
562 va_start(ap, fmt);
563 (void)vfprintf(stderr, fmt, ap);
564 va_end(ap);
565 if (*fmt) {
566 fmt += strlen(fmt);
567 if (fmt[-1] != '\n')
568 (void)fputc('\n', stderr);
569 }
570 }
571
572 static int
ndo_printf(netdissect_options * ndo,const char * fmt,...)573 ndo_printf(netdissect_options *ndo, const char *fmt, ...)
574 {
575 va_list args;
576 int ret;
577
578 va_start(args, fmt);
579 ret = vfprintf(stdout, fmt, args);
580 va_end(args);
581
582 if (ret < 0)
583 ndo_error(ndo, S_ERR_ND_WRITE_FILE,
584 "Unable to write output: %s", pcap_strerror(errno));
585 return (ret);
586 }
587
588 void
ndo_set_function_pointers(netdissect_options * ndo)589 ndo_set_function_pointers(netdissect_options *ndo)
590 {
591 ndo->ndo_default_print=ndo_default_print;
592 ndo->ndo_printf=ndo_printf;
593 ndo->ndo_error=ndo_error;
594 ndo->ndo_warning=ndo_warning;
595 }
596