1/* 2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 30#include "pcap-ng.h" 31#include <stdio.h> 32#include <err.h> 33#include <stdlib.h> 34#include <string.h> 35 36struct section_info { 37 struct section_info *next; 38 struct pcapng_section_header_fields shb; 39 pcap_t *pcap; 40 u_int32_t if_count; 41 struct interface_info *if_list; 42}; 43 44struct interface_info { 45 struct interface_info *next; 46 struct pcapng_interface_description_fields idb; 47 struct section_info *section_info; 48 u_int32_t interface_id; 49 char *if_name; 50 char *if_desc; 51}; 52 53struct section_info *section_list = NULL; 54struct section_info *current_section = NULL; 55 56int mode_raw = 0; 57int mode_block = 0; 58 59#define PAD32(x) (((x) + 3) & ~3) 60 61void hex_and_ascii_print(const char *, const void *, size_t, const char *); 62 63struct section_info * 64new_section_info(pcap_t *pcap, struct pcapng_section_header_fields *shb) 65{ 66 struct section_info *section_info = calloc(1, sizeof(struct section_info)); 67 68 if (section_info == NULL) 69 return NULL; 70 71 section_info->pcap = pcap; 72 section_info->shb = *shb; 73 74 if (section_list == NULL) { 75 section_list = section_info; 76 } else { 77 section_info->next = section_list; 78 section_list = section_info; 79 } 80 current_section = section_info; 81 82 return section_info; 83} 84 85 86void 87interface_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context) 88{ 89 struct interface_info *interface_info = (struct interface_info *)context; 90 91 switch (option_info->code) { 92 case 0: 93 break; 94 95 case 1: 96 break; 97 98 case 2: 99 interface_info->if_name = malloc(option_info->length + 1); 100 if (interface_info->if_name == NULL) 101 break; 102 snprintf(interface_info->if_name, option_info->length + 1, "%s", option_info->value); 103 break; 104 case 3: 105 interface_info->if_desc = malloc(option_info->length + 1); 106 if (interface_info->if_desc == NULL) 107 break; 108 snprintf(interface_info->if_desc, option_info->length + 1, "%s", option_info->value); 109 break; 110 case 4: 111 break; 112 case 5: 113 break; 114 case 6: 115 break; 116 case 7: 117 break; 118 case 8: 119 break; 120 case 9: 121 break; 122 case 10: 123 break; 124 case 11: 125 break; 126 case 12: 127 break; 128 case 13: 129 break; 130 case 14: 131 break; 132 default: 133 break; 134 } 135} 136 137struct interface_info * 138new_interface_info(struct section_info *section_info, pcapng_block_t block) 139{ 140 struct interface_info *interface_info = calloc(1, sizeof(struct interface_info)); 141 142 if (interface_info == NULL) 143 return NULL; 144 145 interface_info->section_info = section_info; 146 interface_info->interface_id = section_info->if_count; 147 section_info->if_count++; 148 if (section_info->if_list == NULL) { 149 section_info->if_list = interface_info; 150 } else { 151 interface_info->next = section_info->if_list; 152 section_info->if_list = interface_info; 153 } 154 (void) pcnapng_block_iterate_options(block, 155 interface_option_iterator, 156 interface_info); 157 158 return interface_info; 159} 160 161struct interface_info * 162find_interface_info_by_id(u_int16_t interface_id) 163{ 164 struct interface_info *interface_info; 165 166 if (current_section == NULL) 167 return (NULL); 168 169 if (interface_id + 1 > current_section->if_count) 170 return (NULL); 171 172 for (interface_info = current_section->if_list; 173 interface_info != NULL; 174 interface_info = interface_info->next) { 175 if (interface_info->interface_id == interface_id) 176 return (interface_info); 177 } 178 return (NULL); 179} 180 181void 182block_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context) 183{ 184 printf(" block_type %u context %p option_code %u value_len %u value_ptr %p\n", 185 pcap_ng_block_get_type(block), context, 186 option_info->code, option_info->length, 187 option_info->value 188 ); 189 switch (option_info->code) { 190 case 0: 191 printf(" opt_endofopt\n"); 192 break; 193 194 case 1: 195 printf(" opt_comment: %-*s\n", 196 option_info->length, option_info->value); 197 break; 198 199 default: 200 /* 201 * Each block type has its own option code space 202 */ 203 switch (pcap_ng_block_get_type(block)) { 204 case PCAPNG_BT_SHB: 205 switch (option_info->code) { 206 case 2: 207 printf(" shb_hardware: %-*s\n", 208 option_info->length, option_info->value); 209 break; 210 case 3: 211 printf(" shb_os: %-*s\n", 212 option_info->length, option_info->value); 213 break; 214 case 4: 215 printf(" shb_userappl: %-*s\n", 216 option_info->length, option_info->value); 217 break; 218 default: 219 printf(" <unkown shb option>\n"); 220 break; 221 } 222 break; 223 224 case PCAPNG_BT_IDB: 225 switch (option_info->code) { 226 case 2: 227 printf(" if_name: %-*s\n", 228 option_info->length, option_info->value); 229 break; 230 case 3: 231 printf(" if_desc: %-*s\n", 232 option_info->length, option_info->value); 233 break; 234 case 4: 235 printf(" if_IPv4addr\n"); 236 break; 237 case 5: 238 printf(" if_IPv6addr\n"); 239 break; 240 case 6: 241 printf(" if_MACaddr\n"); 242 break; 243 case 7: 244 printf(" if_EUIaddr\n"); 245 break; 246 case 8: 247 printf(" if_speed\n"); 248 break; 249 case 9: 250 printf(" if_tsresol\n"); 251 break; 252 case 10: 253 printf(" if_tzone\n"); 254 break; 255 case 11: 256 printf(" if_filter %-*s\n", 257 option_info->length, option_info->value); 258 break; 259 case 12: 260 printf(" if_os %-*s\n", 261 option_info->length, option_info->value); 262 break; 263 case 13: 264 printf(" if_fcslen\n"); 265 break; 266 case 14: 267 printf(" if_tsoffset\n"); 268 break; 269 default: 270 printf(" <unkown idb option>\n"); 271 break; 272 } 273 break; 274 275 case PCAPNG_BT_EPB: 276 switch (option_info->code) { 277 case 2: 278 printf(" epb_flags\n"); 279 break; 280 case 3: 281 printf(" epb_hash\n"); 282 break; 283 case 4: 284 printf(" epb_dropcount\n"); 285 break; 286 case PCAPNG_EPB_PIB_INDEX: 287 printf(" epb_pib\n"); 288 break; 289 case PCAPNG_EPB_SVC: 290 printf(" epb_svc\n"); 291 break; 292 default: 293 printf(" <unkown epb option>\n"); 294 break; 295 } 296 break; 297 298 case PCAPNG_BT_SPB: 299 printf(" <invalid spb option>\n"); 300 break; 301 302 case PCAPNG_BT_PB: 303 switch (option_info->code) { 304 case 2: 305 printf(" pack_flags\n"); 306 break; 307 case 3: 308 printf(" pack_hash\n"); 309 break; 310 default: 311 printf(" <unkown pb option>\n"); 312 break; 313 } 314 break; 315 316 case PCAPNG_BT_PIB: { 317 switch (option_info->code) { 318 case 2: 319 printf(" proc_name\n"); 320 break; 321 case 3: 322 printf(" proc_path\n"); 323 break; 324 default: 325 printf(" <unkown pib option>\n"); 326 break; 327 } 328 break; 329 } 330 case PCAPNG_BT_ISB: { 331 break; 332 } 333 case PCAPNG_BT_NRB: { 334 break; 335 } 336 default: 337 break; 338 } 339 break; 340 } 341 if (option_info->value) { 342 hex_and_ascii_print(" ", option_info->value, option_info->length, "\n"); 343 } 344} 345 346void 347read_callback(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes) 348{ 349 pcap_t *pcap = (pcap_t *)user; 350 struct pcapng_option_info option_info; 351 u_char *optptr = NULL; 352 353 /* Access the raw block */ 354 if (mode_raw) { 355 struct pcapng_block_header *block_header = (struct pcapng_block_header*)bytes; 356 357 printf("raw hdr caplen %u len %u\n", hdr->caplen, hdr->len); 358 359 printf("#\n# user %p hdr.caplen %u hdr.len %u block_header.blocktype 0x%x block_header.totallength %u\n", 360 user, hdr->caplen, hdr->len, 361 block_header->block_type, block_header->total_length); 362 363 hex_and_ascii_print("", bytes, block_header->total_length, "\n"); 364 365 switch (block_header->block_type) { 366 case PCAPNG_BT_SHB: { 367 struct pcapng_section_header_fields *shb = (struct pcapng_section_header_fields *)(block_header + 1); 368 printf("# Section Header Block\n"); 369 printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n", 370 shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length); 371 372 hex_and_ascii_print("", shb, sizeof(struct pcapng_section_header_fields), "\n"); 373 374 optptr = (u_char *)(shb + 1); 375 376 break; 377 } 378 case PCAPNG_BT_IDB: { 379 struct pcapng_interface_description_fields *idb = (struct pcapng_interface_description_fields *)(block_header + 1); 380 printf("# Interface Description Block\n"); 381 printf(" linktype %u reserved %u snaplen %u\n", 382 idb->linktype, idb->reserved, idb->snaplen); 383 384 hex_and_ascii_print("", idb, sizeof(struct pcapng_interface_description_fields), "\n"); 385 optptr = (u_char *)(idb + 1); 386 387 break; 388 } 389 case PCAPNG_BT_EPB: { 390 struct pcapng_enhanced_packet_fields *epb = (struct pcapng_enhanced_packet_fields *)(block_header + 1); 391 printf("# Enhanced Packet Block\n"); 392 printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n", 393 epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len); 394 395 hex_and_ascii_print("", epb, sizeof(struct pcapng_enhanced_packet_fields), "\n"); 396 hex_and_ascii_print("", epb + 1, epb->caplen, "\n"); 397 398 optptr = (u_char *)(epb + 1); 399 optptr += PAD32(epb->caplen); 400 401 break; 402 } 403 case PCAPNG_BT_SPB: { 404 struct pcapng_simple_packet_fields *spb = (struct pcapng_simple_packet_fields *)(block_header + 1); 405 printf("# Simple Packet Block\n"); 406 printf(" len %u\n", 407 spb->len); 408 409 hex_and_ascii_print("", spb, sizeof(struct pcapng_simple_packet_fields), "\n"); 410 hex_and_ascii_print("", spb + 1, spb->len, "\n"); 411 break; 412 } 413 case PCAPNG_BT_PB: { 414 struct pcapng_packet_fields *pb = (struct pcapng_packet_fields *)(block_header + 1); 415 printf("# Packet Block\n"); 416 printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n", 417 pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len); 418 419 hex_and_ascii_print("", pb, sizeof(struct pcapng_packet_fields), "\n"); 420 421 hex_and_ascii_print("", pb + 1, pb->caplen, "\n"); 422 423 break; 424 } 425 case PCAPNG_BT_PIB: { 426 struct pcapng_process_information_fields *pib = (struct pcapng_process_information_fields *)(block_header + 1); 427 printf("# Process Information Block\n"); 428 printf(" process_id %u\n", 429 pib->process_id); 430 hex_and_ascii_print("", pib, sizeof(struct pcapng_process_information_fields), "\n"); 431 break; 432 } 433 case PCAPNG_BT_ISB: { 434 printf("# Interface Statistics Block\n"); 435 break; 436 } 437 case PCAPNG_BT_NRB: { 438 printf("# Name Record Block\n"); 439 break; 440 } 441 default: 442 printf("# Unknown Block\n"); 443 break; 444 } 445 if (optptr) { 446 size_t optlen = block_header->total_length - (optptr - bytes); 447 448 hex_and_ascii_print("", optptr, optlen, "\n"); 449 } 450 451 } 452 /* Create block object */ 453 if (mode_block) { 454 pcapng_block_t block = pcap_ng_block_alloc_with_raw_block(pcap, (u_char *)bytes); 455 456 if (block == NULL) { 457 printf(" pcap_ng_block_alloc_with_raw_block() failed: %s\n", pcap_geterr(pcap)); 458 return; 459 } 460 461 switch (pcap_ng_block_get_type(block)) { 462 case PCAPNG_BT_SHB: { 463 struct pcapng_section_header_fields *shb = pcap_ng_get_section_header_fields(block); 464 printf("# Section Header Block\n"); 465 printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n", 466 shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length); 467 468 (void)new_section_info(pcap, shb); 469 break; 470 } 471 case PCAPNG_BT_IDB: { 472 struct pcapng_interface_description_fields *idb = pcap_ng_get_interface_description_fields(block); 473 printf("# Interface Description Block\n"); 474 printf(" linktype %u reserved %u snaplen %u\n", 475 idb->linktype, idb->reserved, idb->snaplen); 476 if (pcap_ng_block_get_option(block, PCAPNG_IF_NAME, &option_info) == 1) 477 if (option_info.value) 478 printf(" interface name: %s\n", option_info.value); 479 480 (void)new_interface_info(current_section, block); 481 break; 482 } 483 case PCAPNG_BT_EPB: { 484 struct pcapng_enhanced_packet_fields *epb = pcap_ng_get_enhanced_packet_fields(block); 485 printf("# Enhanced Packet Block\n"); 486 printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n", 487 epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len); 488 break; 489 } 490 case PCAPNG_BT_SPB: { 491 struct pcapng_simple_packet_fields *spb = pcap_ng_get_simple_packet_fields(block); 492 printf("# Simple Packet Block\n"); 493 printf(" len %u\n", 494 spb->len); 495 break; 496 } 497 case PCAPNG_BT_PB: { 498 struct pcapng_packet_fields *pb = pcap_ng_get_packet_fields(block); 499 printf("# Packet Block\n"); 500 printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n", 501 pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len); 502 break; 503 } 504 case PCAPNG_BT_PIB: { 505 struct pcapng_process_information_fields *pib = pcap_ng_get_process_information_fields(block); 506 printf("# Process Information Block\n"); 507 printf(" process_id %u\n", 508 pib->process_id); 509 510 if (pcap_ng_block_get_option(block, PCAPNG_PIB_NAME, &option_info) == 1) 511 if (option_info.value) 512 printf(" process name: %s\n", option_info.value); 513 break; 514 } 515 case PCAPNG_BT_ISB: { 516 printf("# Interface Statistics Block\n"); 517 break; 518 } 519 case PCAPNG_BT_NRB: { 520 printf("# Name Record Block\n"); 521 break; 522 } 523 default: 524 printf("# Unknown Block\n"); 525 break; 526 } 527 pcnapng_block_iterate_options(block, block_option_iterator, NULL); 528 } 529} 530 531#define SWAPLONG(y) \ 532((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) 533#define SWAPSHORT(y) \ 534( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) ) 535#define SWAPLONGLONG(y) \ 536(SWAPLONG((unsigned long)(y)) << 32 | SWAPLONG((unsigned long)((y) >> 32))) 537 538void 539test_pcap_ng_fopen_offline(const char *filename, char *errbuf) 540{ 541 FILE *fp = fopen(filename, "r"); 542 off_t offset; 543 544 if (fp == NULL) { 545 warn("fopen(%s) failed", filename); 546 return; 547 } 548 offset = ftello(fp); 549 pcap_t *pcap = pcap_ng_fopen_offline(fp, errbuf); 550 if (pcap == NULL) { 551 warnx("pcap_ng_fopen_offline(%s) failed: %s\n", 552 filename, errbuf); 553 if (ftello(fp) != offset) 554 warnx("pcap_ng_fopen_offline(%s) ftello(fp) (%llu) != offset (%llu)", 555 filename, ftello(fp), offset); 556 } else { 557 pcap_close(pcap); 558 } 559 fclose(fp); 560 561} 562 563 564int main(int argc, const char * argv[]) 565{ 566 int i; 567 char errbuf[PCAP_ERRBUF_SIZE]; 568 569#if 0 570 u_int64_t section_length; 571 572 section_length = 0x0004000300020001; 573 printf("section_length %llx\n", section_length); 574 575 u_int32_t lowlong = (u_int32_t)section_length; 576 printf("lowlong %x\n", lowlong); 577 578 u_int32_t hilong = (u_int32_t)(section_length >> 32); 579 printf("hilong %x\n", hilong); 580 581 u_int64_t swapped = SWAPLONGLONG(section_length); 582 printf("swapped %llx\n", swapped); 583 584 int nums[11] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5 }; 585 for (i = 0; i < 11; i++) { 586 printf("PCAPNG_ROUNDUP32(%d): %d\n", nums[i], PCAPNG_ROUNDUP32(nums[i])); 587 } 588#endif 589 for (i = 1; i < argc; i++) { 590 if (strcmp(argv[i], "-raw") == 0) { 591 mode_raw = 1; 592 continue; 593 } 594 if (strcmp(argv[i], "-block") == 0) { 595 mode_block = 1; 596 continue; 597 } 598 if (mode_block == 0 && mode_raw == 0) 599 mode_block = 1; 600 601 printf("#\n# opening %s\n#\n", argv[i]); 602 603 pcap_t *pcap = pcap_ng_open_offline(argv[i], errbuf); 604 if (pcap == NULL) { 605 warnx("pcap_ng_open_offline(%s) failed: %s\n", 606 argv[i], errbuf); 607 test_pcap_ng_fopen_offline(argv[i], errbuf); 608 continue; 609 } 610 int result = pcap_dispatch(pcap, -1, read_callback, (u_char *)pcap); 611 if (result < 0) { 612 warnx("pcap_dispatch failed: %s\n", 613 pcap_statustostr(result)); 614 } else { 615 printf("# read %d packets\n", result); 616 } 617 pcap_close(pcap); 618 } 619 return 0; 620} 621 622