Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 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 | #ifdef HAVE_CONFIG_H |
| 29 | #include "config.h" |
| 30 | #endif |
| 31 | |
| 32 | #include <stdlib.h> |
| 33 | #include <string.h> |
| 34 | |
| 35 | #include <netdissect-stdinc.h> |
| 36 | |
| 37 | #include "netdissect.h" |
| 38 | #include "addrtoname.h" |
| 39 | #include "print.h" |
| 40 | |
| 41 | struct printer { |
| 42 | if_printer f; |
| 43 | int type; |
| 44 | }; |
| 45 | |
| 46 | static const struct printer printers[] = { |
| 47 | { ether_if_print, DLT_EN10MB }, |
| 48 | #ifdef DLT_IPNET |
| 49 | { ipnet_if_print, DLT_IPNET }, |
| 50 | #endif |
| 51 | #ifdef DLT_IEEE802_15_4 |
| 52 | { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, |
| 53 | #endif |
| 54 | #ifdef DLT_IEEE802_15_4_NOFCS |
| 55 | { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, |
| 56 | #endif |
| 57 | #ifdef DLT_PPI |
| 58 | { ppi_if_print, DLT_PPI }, |
| 59 | #endif |
| 60 | #ifdef DLT_NETANALYZER |
| 61 | { netanalyzer_if_print, DLT_NETANALYZER }, |
| 62 | #endif |
| 63 | #ifdef DLT_NETANALYZER_TRANSPARENT |
| 64 | { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, |
| 65 | #endif |
| 66 | #if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) |
| 67 | { nflog_if_print, DLT_NFLOG}, |
| 68 | #endif |
| 69 | #ifdef DLT_CIP |
| 70 | { cip_if_print, DLT_CIP }, |
| 71 | #endif |
| 72 | #ifdef DLT_ATM_CLIP |
| 73 | { cip_if_print, DLT_ATM_CLIP }, |
| 74 | #endif |
| 75 | #ifdef DLT_IP_OVER_FC |
| 76 | { ipfc_if_print, DLT_IP_OVER_FC }, |
| 77 | #endif |
| 78 | { null_if_print, DLT_NULL }, |
| 79 | #ifdef DLT_LOOP |
| 80 | { null_if_print, DLT_LOOP }, |
| 81 | #endif |
| 82 | #ifdef DLT_APPLE_IP_OVER_IEEE1394 |
| 83 | { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, |
| 84 | #endif |
| 85 | #if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) |
| 86 | { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, |
| 87 | #endif |
| 88 | #ifdef DLT_LANE8023 |
| 89 | { lane_if_print, DLT_LANE8023 }, |
| 90 | #endif |
| 91 | { arcnet_if_print, DLT_ARCNET }, |
| 92 | #ifdef DLT_ARCNET_LINUX |
| 93 | { arcnet_linux_if_print, DLT_ARCNET_LINUX }, |
| 94 | #endif |
| 95 | { raw_if_print, DLT_RAW }, |
| 96 | #ifdef DLT_IPV4 |
| 97 | { raw_if_print, DLT_IPV4 }, |
| 98 | #endif |
| 99 | #ifdef DLT_IPV6 |
| 100 | { raw_if_print, DLT_IPV6 }, |
| 101 | #endif |
| 102 | #ifdef HAVE_PCAP_USB_H |
| 103 | #ifdef DLT_USB_LINUX |
| 104 | { usb_linux_48_byte_print, DLT_USB_LINUX}, |
| 105 | #endif /* DLT_USB_LINUX */ |
| 106 | #ifdef DLT_USB_LINUX_MMAPPED |
| 107 | { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, |
| 108 | #endif /* DLT_USB_LINUX_MMAPPED */ |
| 109 | #endif /* HAVE_PCAP_USB_H */ |
| 110 | #ifdef DLT_SYMANTEC_FIREWALL |
| 111 | { symantec_if_print, DLT_SYMANTEC_FIREWALL }, |
| 112 | #endif |
| 113 | #ifdef DLT_C_HDLC |
| 114 | { chdlc_if_print, DLT_C_HDLC }, |
| 115 | #endif |
| 116 | #ifdef DLT_HDLC |
| 117 | { chdlc_if_print, DLT_HDLC }, |
| 118 | #endif |
| 119 | #ifdef DLT_PPP_ETHER |
| 120 | { pppoe_if_print, DLT_PPP_ETHER }, |
| 121 | #endif |
| 122 | #if defined(DLT_PFLOG) && defined(HAVE_NET_IF_PFLOG_H) |
| 123 | { pflog_if_print, DLT_PFLOG }, |
| 124 | #endif |
| 125 | { token_if_print, DLT_IEEE802 }, |
| 126 | { fddi_if_print, DLT_FDDI }, |
| 127 | #ifdef DLT_LINUX_SLL |
| 128 | { sll_if_print, DLT_LINUX_SLL }, |
| 129 | #endif |
| 130 | #ifdef DLT_FR |
| 131 | { fr_if_print, DLT_FR }, |
| 132 | #endif |
| 133 | #ifdef DLT_FRELAY |
| 134 | { fr_if_print, DLT_FRELAY }, |
| 135 | #endif |
| 136 | #ifdef DLT_MFR |
| 137 | { mfr_if_print, DLT_MFR }, |
| 138 | #endif |
| 139 | { atm_if_print, DLT_ATM_RFC1483 }, |
| 140 | #ifdef DLT_SUNATM |
| 141 | { sunatm_if_print, DLT_SUNATM }, |
| 142 | #endif |
| 143 | #ifdef DLT_ENC |
| 144 | { enc_if_print, DLT_ENC }, |
| 145 | #endif |
| 146 | { sl_if_print, DLT_SLIP }, |
| 147 | #ifdef DLT_SLIP_BSDOS |
| 148 | { sl_bsdos_if_print, DLT_SLIP_BSDOS }, |
| 149 | #endif |
| 150 | #ifdef DLT_LTALK |
| 151 | { ltalk_if_print, DLT_LTALK }, |
| 152 | #endif |
| 153 | #ifdef DLT_JUNIPER_ATM1 |
| 154 | { juniper_atm1_print, DLT_JUNIPER_ATM1 }, |
| 155 | #endif |
| 156 | #ifdef DLT_JUNIPER_ATM2 |
| 157 | { juniper_atm2_print, DLT_JUNIPER_ATM2 }, |
| 158 | #endif |
| 159 | #ifdef DLT_JUNIPER_MFR |
| 160 | { juniper_mfr_print, DLT_JUNIPER_MFR }, |
| 161 | #endif |
| 162 | #ifdef DLT_JUNIPER_MLFR |
| 163 | { juniper_mlfr_print, DLT_JUNIPER_MLFR }, |
| 164 | #endif |
| 165 | #ifdef DLT_JUNIPER_MLPPP |
| 166 | { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, |
| 167 | #endif |
| 168 | #ifdef DLT_JUNIPER_PPPOE |
| 169 | { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, |
| 170 | #endif |
| 171 | #ifdef DLT_JUNIPER_PPPOE_ATM |
| 172 | { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, |
| 173 | #endif |
| 174 | #ifdef DLT_JUNIPER_GGSN |
| 175 | { juniper_ggsn_print, DLT_JUNIPER_GGSN }, |
| 176 | #endif |
| 177 | #ifdef DLT_JUNIPER_ES |
| 178 | { juniper_es_print, DLT_JUNIPER_ES }, |
| 179 | #endif |
| 180 | #ifdef DLT_JUNIPER_MONITOR |
| 181 | { juniper_monitor_print, DLT_JUNIPER_MONITOR }, |
| 182 | #endif |
| 183 | #ifdef DLT_JUNIPER_SERVICES |
| 184 | { juniper_services_print, DLT_JUNIPER_SERVICES }, |
| 185 | #endif |
| 186 | #ifdef DLT_JUNIPER_ETHER |
| 187 | { juniper_ether_print, DLT_JUNIPER_ETHER }, |
| 188 | #endif |
| 189 | #ifdef DLT_JUNIPER_PPP |
| 190 | { juniper_ppp_print, DLT_JUNIPER_PPP }, |
| 191 | #endif |
| 192 | #ifdef DLT_JUNIPER_FRELAY |
| 193 | { juniper_frelay_print, DLT_JUNIPER_FRELAY }, |
| 194 | #endif |
| 195 | #ifdef DLT_JUNIPER_CHDLC |
| 196 | { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, |
| 197 | #endif |
| 198 | #ifdef DLT_PKTAP |
| 199 | { pktap_if_print, DLT_PKTAP }, |
| 200 | #endif |
| 201 | #ifdef DLT_IEEE802_11_RADIO |
| 202 | { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, |
| 203 | #endif |
| 204 | #ifdef DLT_IEEE802_11 |
| 205 | { ieee802_11_if_print, DLT_IEEE802_11}, |
| 206 | #endif |
| 207 | #ifdef DLT_IEEE802_11_RADIO_AVS |
| 208 | { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, |
| 209 | #endif |
| 210 | #ifdef DLT_PRISM_HEADER |
| 211 | { prism_if_print, DLT_PRISM_HEADER }, |
| 212 | #endif |
| 213 | { ppp_if_print, DLT_PPP }, |
| 214 | #ifdef DLT_PPP_WITHDIRECTION |
| 215 | { ppp_if_print, DLT_PPP_WITHDIRECTION }, |
| 216 | #endif |
| 217 | #ifdef DLT_PPP_BSDOS |
| 218 | { ppp_bsdos_if_print, DLT_PPP_BSDOS }, |
| 219 | #endif |
| 220 | #ifdef DLT_PPP_SERIAL |
| 221 | { ppp_hdlc_if_print, DLT_PPP_SERIAL }, |
| 222 | #endif |
| 223 | { NULL, 0 }, |
| 224 | }; |
| 225 | |
| 226 | static void ndo_default_print(netdissect_options *ndo, const u_char *bp, |
| 227 | u_int length); |
| 228 | |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 229 | static void ndo_error(netdissect_options *ndo, |
| 230 | FORMAT_STRING(const char *fmt), ...) |
| 231 | NORETURN PRINTFLIKE(2, 3); |
| 232 | static void ndo_warning(netdissect_options *ndo, |
| 233 | FORMAT_STRING(const char *fmt), ...) |
| 234 | PRINTFLIKE(2, 3); |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 235 | |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 236 | static int ndo_printf(netdissect_options *ndo, |
| 237 | FORMAT_STRING(const char *fmt), ...) |
| 238 | PRINTFLIKE(2, 3); |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 239 | |
| 240 | void |
| 241 | init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask, |
| 242 | uint32_t timezone_offset) |
| 243 | { |
| 244 | |
| 245 | thiszone = timezone_offset; |
| 246 | init_addrtoname(ndo, localnet, mask); |
| 247 | init_checksum(); |
| 248 | } |
| 249 | |
| 250 | if_printer |
| 251 | lookup_printer(int type) |
| 252 | { |
| 253 | const struct printer *p; |
| 254 | |
| 255 | for (p = printers; p->f; ++p) |
| 256 | if (type == p->type) |
| 257 | return p->f; |
| 258 | |
| 259 | #if defined(DLT_USER2) && defined(DLT_PKTAP) |
| 260 | /* |
| 261 | * Apple incorrectly chose to use DLT_USER2 for their PKTAP |
| 262 | * header. |
| 263 | * |
| 264 | * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin- |
| 265 | * based OSes or the same value as LINKTYPE_PKTAP as it is on |
| 266 | * other OSes, to LINKTYPE_PKTAP, so files written with |
| 267 | * this version of libpcap for a DLT_PKTAP capture have a link- |
| 268 | * layer header type of LINKTYPE_PKTAP. |
| 269 | * |
| 270 | * However, files written on OS X Mavericks for a DLT_PKTAP |
| 271 | * capture have a link-layer header type of LINKTYPE_USER2. |
| 272 | * If we don't have a printer for DLT_USER2, and type is |
| 273 | * DLT_USER2, we look up the printer for DLT_PKTAP and use |
| 274 | * that. |
| 275 | */ |
| 276 | if (type == DLT_USER2) { |
| 277 | for (p = printers; p->f; ++p) |
| 278 | if (DLT_PKTAP == p->type) |
| 279 | return p->f; |
| 280 | } |
| 281 | #endif |
| 282 | |
| 283 | return NULL; |
| 284 | /* NOTREACHED */ |
| 285 | } |
| 286 | |
| 287 | int |
| 288 | has_printer(int type) |
| 289 | { |
| 290 | return (lookup_printer(type) != NULL); |
| 291 | } |
| 292 | |
| 293 | if_printer |
| 294 | get_if_printer(netdissect_options *ndo, int type) |
| 295 | { |
| 296 | const char *dltname; |
| 297 | if_printer printer; |
| 298 | |
| 299 | printer = lookup_printer(type); |
| 300 | if (printer == NULL) { |
| 301 | dltname = pcap_datalink_val_to_name(type); |
| 302 | if (dltname != NULL) |
| 303 | (*ndo->ndo_error)(ndo, |
| 304 | "packet printing is not supported for link type %s: use -w", |
| 305 | dltname); |
| 306 | else |
| 307 | (*ndo->ndo_error)(ndo, |
| 308 | "packet printing is not supported for link type %d: use -w", type); |
| 309 | } |
| 310 | return printer; |
| 311 | } |
| 312 | |
| 313 | void |
| 314 | pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h, |
| 315 | const u_char *sp, u_int packets_captured) |
| 316 | { |
| 317 | u_int hdrlen; |
| 318 | |
| 319 | if(ndo->ndo_packet_number) |
| 320 | ND_PRINT((ndo, "%5u ", packets_captured)); |
| 321 | |
| 322 | ts_print(ndo, &h->ts); |
| 323 | |
| 324 | /* |
| 325 | * Some printers want to check that they're not walking off the |
| 326 | * end of the packet. |
| 327 | * Rather than pass it all the way down, we set this member |
| 328 | * of the netdissect_options structure. |
| 329 | */ |
| 330 | ndo->ndo_snapend = sp + h->caplen; |
| 331 | |
| 332 | hdrlen = (ndo->ndo_if_printer)(ndo, h, sp); |
| 333 | |
| 334 | /* |
| 335 | * Restore the original snapend, as a printer might have |
| 336 | * changed it. |
| 337 | */ |
| 338 | ndo->ndo_snapend = sp + h->caplen; |
| 339 | if (ndo->ndo_Xflag) { |
| 340 | /* |
| 341 | * Print the raw packet data in hex and ASCII. |
| 342 | */ |
| 343 | if (ndo->ndo_Xflag > 1) { |
| 344 | /* |
| 345 | * Include the link-layer header. |
| 346 | */ |
| 347 | hex_and_ascii_print(ndo, "\n\t", sp, h->caplen); |
| 348 | } else { |
| 349 | /* |
| 350 | * Don't include the link-layer header - and if |
| 351 | * we have nothing past the link-layer header, |
| 352 | * print nothing. |
| 353 | */ |
| 354 | if (h->caplen > hdrlen) |
| 355 | hex_and_ascii_print(ndo, "\n\t", sp + hdrlen, |
| 356 | h->caplen - hdrlen); |
| 357 | } |
| 358 | } else if (ndo->ndo_xflag) { |
| 359 | /* |
| 360 | * Print the raw packet data in hex. |
| 361 | */ |
| 362 | if (ndo->ndo_xflag > 1) { |
| 363 | /* |
| 364 | * Include the link-layer header. |
| 365 | */ |
| 366 | hex_print(ndo, "\n\t", sp, h->caplen); |
| 367 | } else { |
| 368 | /* |
| 369 | * Don't include the link-layer header - and if |
| 370 | * we have nothing past the link-layer header, |
| 371 | * print nothing. |
| 372 | */ |
| 373 | if (h->caplen > hdrlen) |
| 374 | hex_print(ndo, "\n\t", sp + hdrlen, |
| 375 | h->caplen - hdrlen); |
| 376 | } |
| 377 | } else if (ndo->ndo_Aflag) { |
| 378 | /* |
| 379 | * Print the raw packet data in ASCII. |
| 380 | */ |
| 381 | if (ndo->ndo_Aflag > 1) { |
| 382 | /* |
| 383 | * Include the link-layer header. |
| 384 | */ |
| 385 | ascii_print(ndo, sp, h->caplen); |
| 386 | } else { |
| 387 | /* |
| 388 | * Don't include the link-layer header - and if |
| 389 | * we have nothing past the link-layer header, |
| 390 | * print nothing. |
| 391 | */ |
| 392 | if (h->caplen > hdrlen) |
| 393 | ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen); |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | ND_PRINT((ndo, "\n")); |
| 398 | } |
| 399 | |
| 400 | /* |
| 401 | * By default, print the specified data out in hex and ASCII. |
| 402 | */ |
| 403 | static void |
| 404 | ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) |
| 405 | { |
| 406 | hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ |
| 407 | } |
| 408 | |
| 409 | /* VARARGS */ |
| 410 | static void |
| 411 | ndo_error(netdissect_options *ndo, const char *fmt, ...) |
| 412 | { |
| 413 | va_list ap; |
| 414 | |
| 415 | if(ndo->program_name) |
| 416 | (void)fprintf(stderr, "%s: ", ndo->program_name); |
| 417 | va_start(ap, fmt); |
| 418 | (void)vfprintf(stderr, fmt, ap); |
| 419 | va_end(ap); |
| 420 | if (*fmt) { |
| 421 | fmt += strlen(fmt); |
| 422 | if (fmt[-1] != '\n') |
| 423 | (void)fputc('\n', stderr); |
| 424 | } |
| 425 | nd_cleanup(); |
| 426 | exit(1); |
| 427 | /* NOTREACHED */ |
| 428 | } |
| 429 | |
| 430 | /* VARARGS */ |
| 431 | static void |
| 432 | ndo_warning(netdissect_options *ndo, const char *fmt, ...) |
| 433 | { |
| 434 | va_list ap; |
| 435 | |
| 436 | if(ndo->program_name) |
| 437 | (void)fprintf(stderr, "%s: ", ndo->program_name); |
| 438 | (void)fprintf(stderr, "WARNING: "); |
| 439 | va_start(ap, fmt); |
| 440 | (void)vfprintf(stderr, fmt, ap); |
| 441 | va_end(ap); |
| 442 | if (*fmt) { |
| 443 | fmt += strlen(fmt); |
| 444 | if (fmt[-1] != '\n') |
| 445 | (void)fputc('\n', stderr); |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | static int |
| 450 | ndo_printf(netdissect_options *ndo, const char *fmt, ...) |
| 451 | { |
| 452 | va_list args; |
| 453 | int ret; |
| 454 | |
| 455 | va_start(args, fmt); |
| 456 | ret = vfprintf(stdout, fmt, args); |
| 457 | va_end(args); |
| 458 | |
| 459 | if (ret < 0) |
| 460 | ndo_error(ndo, "Unable to write output: %s", pcap_strerror(errno)); |
| 461 | return (ret); |
| 462 | } |
| 463 | |
| 464 | void |
| 465 | ndo_set_function_pointers(netdissect_options *ndo) |
| 466 | { |
| 467 | ndo->ndo_default_print=ndo_default_print; |
| 468 | ndo->ndo_printf=ndo_printf; |
| 469 | ndo->ndo_error=ndo_error; |
| 470 | ndo->ndo_warning=ndo_warning; |
| 471 | } |
| 472 | /* |
| 473 | * Local Variables: |
| 474 | * c-style: whitesmith |
| 475 | * c-basic-offset: 8 |
| 476 | * End: |
| 477 | */ |