1/* 2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include <sys/param.h> 29#include <netinet/in.h> 30#include <stdlib.h> 31#include <string.h> 32#include <stdio.h> 33#include <err.h> 34#include <sysexits.h> 35#include <unistd.h> 36#include <sys/uio.h> 37#include "pcapng_private.h" 38 39#include "pcap-int.h" 40#include "pcap-common.h" 41#include "sf-pcap-ng.h" 42#include "pcap-util.h" 43 44 45#define PAD_32BIT(x) ((x + 3) & ~3) 46#define PAD_64BIT(x) ((x + 7) & ~7) 47#define PADDED_OPTION_LEN(x) ((x) ? PAD_32BIT(x) + sizeof(struct pcapng_option_header) : 0) 48 49 50void * 51pcap_ng_block_header_ptr(pcapng_block_t block) 52{ 53 return (block->pcapng_bufptr); 54} 55 56void * 57pcap_ng_block_fields_ptr(pcapng_block_t block) 58{ 59 return (block->pcapng_bufptr + 60 sizeof(struct pcapng_block_header)); 61} 62 63void * 64pcap_ng_block_data_ptr(pcapng_block_t block) 65{ 66 if (block->pcapng_data_is_external) 67 return (block->pcapng_data_ptr); 68 else 69 return (block->pcapng_bufptr + 70 sizeof(struct pcapng_block_header) + 71 block->pcapng_fields_len); 72} 73 74void * 75pcap_ng_block_records_ptr(pcapng_block_t block) 76{ 77 if (block->pcapng_block_type != PCAPNG_BT_NRB) 78 return (NULL); 79 80 if (block->pcapng_data_is_external) 81 return (block->pcapng_bufptr + 82 sizeof(struct pcapng_block_header) + 83 block->pcapng_fields_len); 84 else 85 return (block->pcapng_bufptr + 86 sizeof(struct pcapng_block_header) + 87 block->pcapng_fields_len + 88 block->pcapng_data_len); 89} 90 91void * 92pcap_ng_block_options_ptr(pcapng_block_t block) 93{ 94 if (block->pcapng_block_type == PCAPNG_BT_SPB) 95 return (NULL); 96 97 if (block->pcapng_data_is_external) 98 return (block->pcapng_bufptr + 99 sizeof(struct pcapng_block_header) + 100 block->pcapng_fields_len + 101 block->pcapng_records_len); 102 else 103 return (block->pcapng_bufptr + 104 sizeof(struct pcapng_block_header) + 105 block->pcapng_fields_len + 106 block->pcapng_data_len + 107 block->pcapng_records_len); 108} 109 110void * 111pcap_ng_block_trailer_ptr(pcapng_block_t block) 112{ 113 if (block->pcapng_data_is_external) 114 return (block->pcapng_bufptr + 115 sizeof(struct pcapng_block_header) + 116 block->pcapng_fields_len + 117 block->pcapng_records_len + 118 block->pcapng_options_len); 119 else 120 return (block->pcapng_bufptr + 121 sizeof(struct pcapng_block_header) + 122 block->pcapng_fields_len + 123 block->pcapng_data_len + 124 block->pcapng_records_len + 125 block->pcapng_options_len); 126} 127 128pcapng_block_t 129pcap_ng_block_alloc(size_t len) 130{ 131 size_t totallen; 132 u_char *ptr; 133 struct pcapng_block *block; 134 135 /* 136 * The internal block structure is prepended 137 */ 138 totallen = PAD_64BIT(sizeof(struct pcapng_block)) + len; 139 ptr = malloc(totallen); 140 if (ptr == NULL) 141 return (NULL); 142 143 block = (struct pcapng_block *)ptr; 144 bzero(block, sizeof(struct pcapng_block)); 145 146 block->pcapng_bufptr = ptr + PAD_64BIT(sizeof(struct pcapng_block)); 147 block->pcapng_buflen = len; 148 149 150 return (block); 151} 152 153void 154pcap_ng_free_block(pcapng_block_t block) 155{ 156 free(block); 157} 158 159bpf_u_int32 160pcap_ng_block_get_type(pcapng_block_t block) 161{ 162 return (block->pcapng_block_type); 163} 164 165bpf_u_int32 166pcap_ng_block_get_len(pcapng_block_t block) 167{ 168 return (block->pcapng_block_len); 169} 170 171int 172pcap_ng_block_is_swapped(pcapng_block_t block) 173{ 174 return (block->pcapng_block_swapped); 175} 176 177int 178pcapng_update_block_length(pcapng_block_t block) 179{ 180 block->pcapng_block_len = sizeof(struct pcapng_block_header) + 181 block->pcapng_fields_len + 182 block->pcapng_data_len + 183 block->pcapng_records_len + 184 block->pcapng_options_len + 185 sizeof(struct pcapng_block_trailer); 186 187 if (block->pcapng_block_len > block->pcapng_buflen) { 188 errx(EX_SOFTWARE, "%s block len %lu greater than buffer size %lu", 189 __func__, block->pcapng_block_len, block->pcapng_buflen); 190 191 } 192 193 return (0); 194} 195 196int 197pcap_ng_block_reset(pcapng_block_t block, bpf_u_int32 type) 198{ 199 bzero(&block->block_fields_, sizeof(block->block_fields_)); 200 201 switch (type) { 202 case PCAPNG_BT_SHB: 203 block->pcapng_block_type = type; 204 205 block->pcap_ng_shb_fields.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC; 206 block->pcap_ng_shb_fields.major_version = PCAPNG_VERSION_MAJOR; 207 block->pcap_ng_shb_fields.minor_version = PCAPNG_VERSION_MINOR; 208 block->pcap_ng_shb_fields.section_length = (uint64_t)-1; 209 210 block->pcapng_fields_len = sizeof(struct pcapng_section_header_fields); 211 break; 212 213 case PCAPNG_BT_IDB: 214 block->pcapng_block_type = type; 215 216 block->pcapng_fields_len = sizeof(struct pcapng_interface_description_fields); 217 break; 218 219 case PCAPNG_BT_PB: 220 block->pcapng_block_type = type; 221 222 block->pcapng_fields_len = sizeof(struct pcapng_packet_fields); 223 224 break; 225 226 case PCAPNG_BT_SPB: 227 block->pcapng_block_type = type; 228 229 block->pcapng_fields_len = sizeof(struct pcapng_simple_packet_fields); 230 231 break; 232 233 case PCAPNG_BT_NRB: 234 block->pcapng_block_type = type; 235 236 block->pcapng_fields_len = 0; 237 break; 238 239 case PCAPNG_BT_ISB: 240 block->pcapng_block_type = type; 241 242 block->pcapng_fields_len = sizeof(struct pcapng_interface_statistics_fields); 243 break; 244 245 case PCAPNG_BT_EPB: 246 block->pcapng_block_type = type; 247 248 block->pcapng_fields_len = sizeof(struct pcapng_enhanced_packet_fields); 249 break; 250 251 case PCAPNG_BT_PIB: 252 block->pcapng_block_type = type; 253 254 block->pcapng_fields_len = sizeof(struct pcapng_process_information_fields); 255 break; 256 257 default: 258 return (PCAP_ERROR); 259 } 260 261 block->pcapng_data_ptr = NULL; 262 block->pcapng_data_len = 0; 263 block->pcapng_cap_len = 0; 264 block->pcapng_data_is_external = 0; 265 266 block->pcapng_records_len = 0; 267 268 block->pcapng_options_len = 0; 269 270 pcapng_update_block_length(block); 271 272 return (0); 273} 274 275struct pcapng_section_header_fields * 276pcap_ng_get_section_header_fields(pcapng_block_t block) 277{ 278 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_SHB) 279 return &block->pcap_ng_shb_fields; 280 else 281 return NULL; 282} 283 284struct pcapng_interface_description_fields * 285pcap_ng_get_interface_description_fields(pcapng_block_t block) 286{ 287 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_IDB) 288 return &block->pcap_ng_idb_fields; 289 else 290 return NULL; 291} 292 293struct pcapng_enhanced_packet_fields * 294pcap_ng_get_enhanced_packet_fields(pcapng_block_t block) 295{ 296 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_EPB) 297 return &block->pcap_ng_epb_fields; 298 else 299 return NULL; 300} 301 302struct pcapng_simple_packet_fields * 303pcap_ng_get_simple_packet_fields(pcapng_block_t block) 304{ 305 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_SPB) 306 return &block->pcap_ng_spb_fields; 307 else 308 return NULL; 309} 310 311struct pcapng_packet_fields * 312pcap_ng_get_packet_fields(pcapng_block_t block) 313{ 314 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_PB) 315 return &block->pcap_ng_opb_fields; 316 else 317 return NULL; 318} 319 320struct pcapng_interface_statistics_fields * 321pcap_ng_get_interface_statistics_fields(pcapng_block_t block) 322{ 323 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_ISB) 324 return &block->pcap_ng_isb_fields; 325 else 326 return NULL; 327} 328 329struct pcapng_process_information_fields * 330pcap_ng_get_process_information_fields(pcapng_block_t block) 331{ 332 if (block != NULL && block->pcapng_block_type == PCAPNG_BT_PIB) 333 return &block->pcap_ng_pib_fields; 334 else 335 return NULL; 336} 337 338int 339pcap_ng_block_does_support_data(pcapng_block_t block) 340{ 341 switch (block->pcapng_block_type) { 342 case PCAPNG_BT_PB: 343 case PCAPNG_BT_SPB: 344 case PCAPNG_BT_EPB: 345 return (1); 346 /* NOT REACHED */ 347 348 default: 349 break; 350 } 351 return (0); 352} 353 354void * 355pcap_ng_block_packet_get_data_ptr(pcapng_block_t block) 356{ 357 if (pcap_ng_block_does_support_data(block) == 0) 358 return (NULL); 359 360 return (block->pcapng_data_ptr); 361} 362 363bpf_u_int32 364pcap_ng_block_packet_get_data_len(pcapng_block_t block) 365{ 366 if (pcap_ng_block_does_support_data(block) == 0) 367 return (0); 368 369 return (block->pcapng_cap_len); 370} 371 372bpf_u_int32 373pcap_ng_block_packet_copy_data(pcapng_block_t block, const void *ptr, 374 bpf_u_int32 caplen) 375{ 376 bpf_u_int32 padding_len = PAD_32BIT(caplen) - caplen; 377 378 if (pcap_ng_block_does_support_data(block) == 0) 379 return (PCAP_ERROR); 380 381 if (block->pcapng_block_len + PAD_32BIT(caplen) > block->pcapng_buflen) { 382 warnx("%s block len %lu greater than buffer size %lu", 383 __func__, block->pcapng_block_len, block->pcapng_buflen); 384 return (PCAP_ERROR); 385 } 386 /* 387 * Move the name records and options if necessary 388 */ 389 if (block->pcapng_records_len > 0 || block->pcapng_options_len > 0) { 390 u_char *tmp = pcap_ng_block_records_ptr(block) ? 391 pcap_ng_block_records_ptr(block) : 392 pcap_ng_block_options_ptr(block); 393 size_t len = block->pcapng_records_len + block->pcapng_options_len; 394 int32_t offset = PAD_32BIT(caplen) - block->pcapng_data_len; 395 396 bcopy(tmp, tmp + offset, len); 397 } 398 399 /* 400 * TBD: if records or options exist, should move them or error out 401 */ 402 block->pcapng_data_is_external = 0; 403 block->pcapng_data_ptr = pcap_ng_block_data_ptr(block); 404 bcopy(ptr, block->pcapng_data_ptr, caplen); 405 if (padding_len > 0) 406 bzero(block->pcapng_data_ptr + caplen, padding_len); 407 block->pcapng_cap_len = caplen; 408 block->pcapng_data_len = PAD_32BIT(caplen); 409 410 pcapng_update_block_length(block); 411 412 return (0); 413} 414 415bpf_u_int32 416pcap_ng_block_packet_set_data(pcapng_block_t block, const void *ptr, 417 bpf_u_int32 caplen) 418{ 419 if (pcap_ng_block_does_support_data(block) == 0) 420 return (PCAP_ERROR); 421 422 block->pcapng_data_is_external = 1; 423 block->pcapng_data_ptr = (u_char *)ptr; 424 block->pcapng_cap_len = caplen; 425 block->pcapng_data_len = PAD_32BIT(caplen); 426 427 pcapng_update_block_length(block); 428 429 return (0); 430} 431 432int 433pcap_ng_block_add_option_with_value(pcapng_block_t block, u_short code, 434 const void *value, u_short value_len) 435{ 436 size_t optlen = sizeof(struct pcapng_option_header) + PAD_32BIT(value_len); 437 struct pcapng_option_header *opt_header; 438 bpf_u_int32 padding_len = PAD_32BIT(value_len) - value_len; 439 u_char *buffer; 440 u_char *block_option_ptr = pcap_ng_block_options_ptr(block); 441 442 if (block_option_ptr == NULL) { 443 warnx("%s options not supported for block type %u", 444 __func__, block->pcapng_block_type); 445 return (PCAP_ERROR); 446 } 447 448 if (optlen + block->pcapng_block_len > block->pcapng_buflen) { 449 warnx("%s block len %lu greater than buffer size %lu", 450 __func__, block->pcapng_block_len, block->pcapng_buflen); 451 return (PCAP_ERROR); 452 } 453 454 opt_header = (struct pcapng_option_header *)(block_option_ptr + block->pcapng_options_len); 455 /* Insert before the end of option */ 456 if (block->pcapng_options_len > 0) 457 opt_header -= 1; 458 opt_header->option_code = code; 459 opt_header->option_length = value_len; 460 461 buffer = (u_char *)(opt_header + 1); 462 463 bcopy(value, buffer, value_len); 464 465 if (padding_len > 0) 466 bzero(buffer + value_len, padding_len); 467 468 /* Add end of option when first option added */ 469 if (block->pcapng_options_len == 0) 470 block->pcapng_options_len = sizeof(struct pcapng_option_header); 471 472 block->pcapng_options_len += optlen; 473 474 /* Set the end of option at the end of the options */ 475 opt_header = (struct pcapng_option_header *)(block_option_ptr + block->pcapng_options_len); 476 opt_header -= 1; 477 opt_header->option_code = PCAPNG_OPT_ENDOFOPT; 478 opt_header->option_length = 0; 479 480 pcapng_update_block_length(block); 481 482 return (0); 483} 484 485int 486pcap_ng_block_add_option_with_string(pcapng_block_t block, u_short code, const char *str) 487{ 488 return (pcap_ng_block_add_option_with_value(block, code, str, strlen(str) + 1)); 489} 490 491int 492pcap_ng_block_get_option(pcapng_block_t block, u_short code, struct pcapng_option_info *option_info) 493{ 494 struct pcapng_option_header opthdr; 495 int swapped; 496 int num_of_options = 0; 497 struct block_cursor cursor; 498 499 if (option_info == NULL) 500 return (PCAP_ERROR); 501 if (block->pcapng_options_len == 0) 502 goto done; 503 504 swapped = block->pcapng_block_swapped; 505 506 cursor.block_type = block->pcapng_block_type; 507 cursor.data = pcap_ng_block_options_ptr(block); 508 cursor.data_remaining = block->pcapng_options_len; 509 510 while (get_opthdr_from_block_data(&opthdr, swapped, &cursor, NULL)) { 511 void *value = get_optvalue_from_block_data(&cursor, &opthdr, NULL); 512 513 /* 514 * If option is cut short we cannot parse it, give up 515 */ 516 if (opthdr.option_length != 0 && value == NULL) 517 break; 518 519 if (code == opthdr.option_code) { 520 option_info->code = opthdr.option_code; 521 option_info->length = opthdr.option_length; 522 option_info->value = value; 523 524 num_of_options = 1; 525 break; 526 } 527 /* 528 * Detect end of option delimiter 529 */ 530 if (opthdr.option_code == PCAPNG_OPT_ENDOFOPT) 531 break; 532 } 533 534done: 535 return (num_of_options); 536} 537 538int 539pcnapng_block_iterate_options(pcapng_block_t block, 540 pcapng_option_iterator_func opt_iterator_func, 541 void *context) 542{ 543 struct pcapng_option_header opthdr; 544 int swapped; 545 int num_of_options = 0; 546 struct block_cursor cursor; 547 548 if (block == NULL || opt_iterator_func == NULL) 549 return (PCAP_ERROR); 550 swapped = block->pcapng_block_swapped; 551 552 cursor.block_type = block->pcapng_block_type; 553 cursor.data = pcap_ng_block_options_ptr(block); 554 cursor.data_remaining = block->pcapng_options_len; 555 556 while (get_opthdr_from_block_data(&opthdr, swapped, &cursor, NULL)) { 557 void *value = get_optvalue_from_block_data(&cursor, &opthdr, NULL); 558 struct pcapng_option_info option_info; 559 560 /* 561 * If option is cut short we cannot parse it, give up 562 */ 563 if (opthdr.option_length != 0 && value == NULL) 564 break; 565 566 option_info.code = opthdr.option_code; 567 option_info.length = opthdr.option_length; 568 option_info.value = value; 569 570 num_of_options++; 571 572 opt_iterator_func(block, &option_info, context); 573 574 /* 575 * Detect end of option delimiter 576 */ 577 if (opthdr.option_code == PCAPNG_OPT_ENDOFOPT) 578 break; 579 } 580 581done: 582 return (num_of_options); 583} 584 585int 586pcnapng_block_iterate_name_records(pcapng_block_t block, 587 pcapng_name_record_iterator_func record_iterator_func, 588 void *context) 589{ 590 struct pcapng_record_header recordhdr; 591 int swapped; 592 int num_of_records = 0; 593 struct block_cursor cursor; 594 595 if (block == NULL || record_iterator_func == NULL) 596 return (PCAP_ERROR); 597 swapped = block->pcapng_block_swapped; 598 599 cursor.block_type = block->pcapng_block_type; 600 cursor.data = pcap_ng_block_records_ptr(block); 601 cursor.data_remaining = block->pcapng_records_len; 602 603 /* 604 * Note that we take advantage of the fact that name record headers 605 * have the same layout as option headers 606 */ 607 while (get_opthdr_from_block_data((struct pcapng_option_header *)&recordhdr, 608 swapped, &cursor, NULL)) { 609 struct pcapng_name_record_info record_info; 610 void *value = 611 get_optvalue_from_block_data(&cursor, 612 (struct pcapng_option_header *)&recordhdr, 613 NULL); 614 615 /* 616 * If record is cut short we cannot parse it, give up 617 */ 618 if (recordhdr.record_length != 0 && value == NULL) 619 break; 620 621 record_info.code = recordhdr.record_type; 622 record_info.length = recordhdr.record_length; 623 record_info.value = value; 624 625 num_of_records++; 626 627 /* 628 * Detect end of option delimiter 629 */ 630 if (record_info.code == PCAPNG_NRES_ENDOFRECORD) 631 break; 632 } 633 634done: 635 return (num_of_records); 636} 637 638int 639pcap_ng_block_add_name_record_common(pcapng_block_t block, uint32_t type, 640 size_t addrlen, void *addr, const char **names) 641{ 642 size_t names_len = 0; 643 int i; 644 const char *p; 645 size_t record_len = 0; 646 struct pcapng_record_header *record_hdr; 647 size_t padding_len; 648 u_char *buffer; 649 size_t offset; 650 u_char *block_records_ptr = pcap_ng_block_records_ptr(block); 651 652 if (block_records_ptr == NULL) 653 return (PCAP_ERROR); 654 655 for (i = 0; ; i++) { 656 p = names[i]; 657 if (p == NULL || *p == 0) 658 break; 659 names_len += strlen(p) + 1; 660 } 661 662 record_len = sizeof(struct pcapng_record_header) + addrlen + PAD_32BIT(names_len); 663 if (record_len + block->pcapng_block_len > block->pcapng_buflen) { 664 warnx("%s block len %lu greater than buffer size %lu", 665 __func__, block->pcapng_block_len, block->pcapng_buflen); 666 return (PCAP_ERROR); 667 } 668 669 /* 670 * Move the options if necessary 671 */ 672 if (block->pcapng_options_len > 0) { 673 u_char *tmp = pcap_ng_block_options_ptr(block); 674 675 bcopy(tmp, tmp + record_len, block->pcapng_options_len); 676 } 677 678 padding_len = PAD_32BIT(names_len) - names_len; 679 680 record_hdr = (struct pcapng_record_header*)(block_records_ptr + block->pcapng_records_len); 681 if (block->pcapng_records_len > 0) 682 record_hdr -= 1; 683 record_hdr->record_type = type; 684 record_hdr->record_length = addrlen + PAD_32BIT(names_len); 685 686 buffer = (u_char *)(record_hdr + 1); 687 bcopy(addr, buffer, addrlen); 688 offset = addrlen; 689 for (i = 0; ; i++) { 690 p = names[i]; 691 if (p == NULL || *p == 0) 692 break; 693 u_short slen = strlen(p) + 1; 694 bcopy(p, buffer, slen); 695 offset += slen; 696 } 697 if (padding_len > 0) 698 bzero(buffer + offset, padding_len); 699 700 block->pcapng_records_len += record_len; 701 702 pcapng_update_block_length(block); 703 704 return (0); 705} 706 707int 708pcap_ng_block_add_name_record_with_ip4(pcapng_block_t block, 709 struct in_addr *in4, 710 const char **names) 711{ 712 if (block->pcapng_block_type != PCAPNG_BT_NRB) 713 return (PCAP_ERROR); 714 715 return pcap_ng_block_add_name_record_common(block, 716 PCAPNG_NRES_IP4RECORD, 717 sizeof(struct in_addr), 718 in4, 719 names); 720} 721 722int 723pcap_ng_block_add_name_record_with_ip6(pcapng_block_t block, 724 struct in6_addr *in6, 725 const char **names) 726{ 727 if (block->pcapng_block_type != PCAPNG_BT_NRB) 728 return (PCAP_ERROR); 729 730 return pcap_ng_block_add_name_record_common(block, 731 PCAPNG_NRES_IP4RECORD, 732 sizeof(struct in6_addr), 733 in6, 734 names); 735} 736 737bpf_u_int32 738pcap_ng_externalize_block(void *buffer, size_t buflen, pcapng_block_t block) 739{ 740 struct pcapng_block_header block_header; 741 struct pcapng_block_trailer block_trailer; 742 bpf_u_int32 bytes_written = 0; 743 u_char *ptr; 744 745 if (buffer == NULL || buflen < block->pcapng_block_len) 746 return (0); 747 748 ptr = buffer; 749 block_header.block_type = block->pcapng_block_type; 750 block_header.total_length = block->pcapng_block_len; 751 bcopy(&block_header, ptr + bytes_written, sizeof(struct pcapng_block_header)); 752 bytes_written += sizeof(struct pcapng_block_header); 753 754 switch (block->pcapng_block_type) { 755 case PCAPNG_BT_SHB: 756 case PCAPNG_BT_IDB: 757 case PCAPNG_BT_PB: 758 case PCAPNG_BT_SPB: 759 case PCAPNG_BT_NRB: 760 case PCAPNG_BT_ISB: 761 case PCAPNG_BT_EPB: 762 case PCAPNG_BT_PIB: 763 if (block->pcapng_block_type == PCAPNG_BT_PB) { 764 if(block->pcap_ng_opb_fields.caplen == 0) 765 block->pcap_ng_opb_fields.caplen = block->pcapng_cap_len; 766 if(block->pcap_ng_opb_fields.len == 0) 767 block->pcap_ng_opb_fields.len = block->pcapng_cap_len; 768 } 769 if (block->pcapng_block_type == PCAPNG_BT_SPB) { 770 if(block->pcap_ng_spb_fields.len == 0) 771 block->pcap_ng_spb_fields.len = block->pcapng_cap_len; 772 } 773 if (block->pcapng_block_type == PCAPNG_BT_EPB) { 774 if(block->pcap_ng_epb_fields.caplen == 0) 775 block->pcap_ng_epb_fields.caplen = block->pcapng_cap_len; 776 if(block->pcap_ng_epb_fields.len == 0) 777 block->pcap_ng_epb_fields.len = block->pcapng_cap_len; 778 } 779 780 if (block->pcapng_fields_len > 0) { 781 bcopy(&block->pcap_ng_shb_fields, ptr + bytes_written, block->pcapng_fields_len); 782 bytes_written += block->pcapng_fields_len; 783 } 784 break; 785 default: 786 /* Unknown block */ 787 return (0); 788 break; 789 } 790 791 792 if (block->pcapng_data_len > 0) { 793 bpf_u_int32 padding_len = PAD_32BIT(block->pcapng_cap_len) - block->pcapng_cap_len; 794 795 bcopy(block->pcapng_data_ptr, ptr + bytes_written, block->pcapng_cap_len); 796 bytes_written += block->pcapng_cap_len; 797 798 if (padding_len > 0) { 799 bzero(ptr + bytes_written, padding_len); 800 bytes_written += padding_len; 801 } 802 } 803 804 if (block->pcapng_records_len > 0) { 805 bcopy(pcap_ng_block_records_ptr(block), ptr + bytes_written, block->pcapng_records_len); 806 bytes_written += block->pcapng_records_len; 807 } 808 if (block->pcapng_options_len > 0) { 809 bcopy(pcap_ng_block_options_ptr(block), ptr + bytes_written, block->pcapng_options_len); 810 bytes_written += block->pcapng_options_len; 811 } 812 813 block_trailer.total_length = block->pcapng_block_len; 814 bcopy(&block_trailer, ptr + bytes_written, bytes_written); 815 bytes_written += sizeof(struct pcapng_block_trailer); 816 817 return (bytes_written); 818} 819 820bpf_u_int32 821pcap_ng_dump_block(pcap_dumper_t *p, pcapng_block_t block) 822{ 823 struct pcapng_block_header *block_header; 824 struct pcapng_block_trailer *block_trailer; 825 bpf_u_int32 bytes_written = 0; 826 struct iovec iov[4]; 827 int iovcnt; 828 char data_padding[3] = { 0, 0, 0 }; 829 830 block_header = (struct pcapng_block_header *)pcap_ng_block_header_ptr(block); 831 block_header->block_type = block->pcapng_block_type; 832 block_header->total_length = block->pcapng_block_len; 833 834 switch (block->pcapng_block_type) { 835 case PCAPNG_BT_SHB: 836 case PCAPNG_BT_IDB: 837 case PCAPNG_BT_PB: 838 case PCAPNG_BT_SPB: 839 case PCAPNG_BT_NRB: 840 case PCAPNG_BT_ISB: 841 case PCAPNG_BT_EPB: 842 case PCAPNG_BT_PIB: 843 if (block->pcapng_block_type == PCAPNG_BT_PB) { 844 if(block->pcap_ng_opb_fields.caplen == 0) 845 block->pcap_ng_opb_fields.caplen = block->pcapng_cap_len; 846 if(block->pcap_ng_opb_fields.len == 0) 847 block->pcap_ng_opb_fields.len = block->pcapng_cap_len; 848 } 849 if (block->pcapng_block_type == PCAPNG_BT_SPB) { 850 if(block->pcap_ng_spb_fields.len == 0) 851 block->pcap_ng_spb_fields.len = block->pcapng_cap_len; 852 } 853 if (block->pcapng_block_type == PCAPNG_BT_EPB) { 854 if(block->pcap_ng_epb_fields.caplen == 0) 855 block->pcap_ng_epb_fields.caplen = block->pcapng_cap_len; 856 if(block->pcap_ng_epb_fields.len == 0) 857 block->pcap_ng_epb_fields.len = block->pcapng_cap_len; 858 } 859 860 if (block->pcapng_fields_len > 0) 861 bcopy(&block->pcap_ng_shb_fields, pcap_ng_block_fields_ptr(block), block->pcapng_fields_len); 862 break; 863 default: 864 /* Unknown block */ 865 return (0); 866 break; 867 } 868 869 block_trailer = pcap_ng_block_trailer_ptr(block); 870 block_trailer->total_length = block_header->total_length; 871 872 iovcnt = 0; 873 iov[iovcnt].iov_len = sizeof(struct pcapng_block_header) + block->pcapng_fields_len; 874 iov[iovcnt].iov_base = block->pcapng_bufptr; 875 iovcnt++; 876 877 if (block->pcapng_data_len > 0) { 878 bpf_u_int32 padding_len = PAD_32BIT(block->pcapng_cap_len) - block->pcapng_cap_len; 879 880 iov[iovcnt].iov_len = block->pcapng_cap_len; 881 iov[iovcnt].iov_base = block->pcapng_data_ptr; 882 iovcnt++; 883 884 /* This is suboptimal... */ 885 if (padding_len > 0) { 886 iov[iovcnt].iov_len = padding_len; 887 iov[iovcnt].iov_base = data_padding; 888 iovcnt++; 889 } 890 } 891 /* 892 * The name records, options and block trailer are contiguous 893 */ 894 iov[iovcnt].iov_len = block->pcapng_records_len + 895 block->pcapng_options_len + 896 sizeof(struct pcapng_block_trailer); 897 if (block->pcapng_records_len > 0) 898 iov[iovcnt].iov_base = pcap_ng_block_records_ptr(block); 899 else if (block->pcapng_options_len > 0) 900 iov[iovcnt].iov_base = pcap_ng_block_options_ptr(block); 901 else 902 iov[iovcnt].iov_base = block_trailer; 903 iovcnt++; 904 905 bytes_written += writev(((FILE *)p)->_file, iov, iovcnt); 906 907 return (bytes_written); 908} 909 910int 911pcap_ng_block_internalize_common(pcapng_block_t *pblock, pcap_t *p, u_char *raw_block) 912{ 913 pcapng_block_t block = NULL; 914 struct pcapng_block_header bh = *(struct pcapng_block_header *)raw_block; 915 struct block_cursor cursor; 916 int swapped = 0; 917 918 if (pblock == NULL || raw_block == NULL) 919 return (PCAP_ERROR); 920 921 if (p != NULL) 922 swapped = p->sf.swapped; 923 924 if (swapped) { 925 bh.block_type = SWAPLONG(bh.block_type); 926 bh.total_length = SWAPLONG(bh.total_length); 927 } 928 929 switch (bh.block_type) { 930 case PCAPNG_BT_SHB: 931 pcap_ng_init_section_info(p); 932 break; 933 case PCAPNG_BT_IDB: 934 case PCAPNG_BT_PB: 935 case PCAPNG_BT_SPB: 936 case PCAPNG_BT_NRB: 937 case PCAPNG_BT_ISB: 938 case PCAPNG_BT_EPB: 939 case PCAPNG_BT_PIB: 940 break; 941 default: 942 (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 943 "%s: Unknown block type length %u", 944 __func__, bh.block_type); 945 goto fail; 946 } 947 /* Check the length is reasonable, limit to 1 MBytes */ 948 if (bh.total_length > 1024 * 1024) { 949 (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 950 "%s: Block total length %u is greater than 16 MB", 951 __func__, bh.total_length); 952 goto fail; 953 } 954 955 /* 956 * Some ntar files from wireshark.org do not round up the total block length to 957 * a multiple of 4 bytes -- they must ignore the 32 bit alignment of the block body! 958 */ 959 bh.total_length = PAD_32BIT(bh.total_length); 960 961 if (*pblock == NULL) { 962 block = pcap_ng_block_alloc(bh.total_length); 963 if (block == NULL) { 964 (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 965 "%s: Unknown block type %u", 966 __func__, bh.block_type); 967 goto fail; 968 } 969 } else { 970 block = *pblock; 971 } 972 block->pcapng_bufptr = raw_block; 973 block->pcapng_buflen = bh.total_length; 974 block->pcapng_buf_is_external = 1; 975 pcap_ng_block_reset(block, bh.block_type); 976 block->pcapng_block_len = bh.total_length; 977 block->pcapng_block_swapped = swapped; 978 979 cursor.data = raw_block + sizeof(struct pcapng_block_header); 980 cursor.data_remaining = bh.total_length - 981 sizeof(struct pcapng_block_header) - 982 sizeof(struct pcapng_block_trailer); 983 cursor.block_type = bh.block_type; 984 985 switch (bh.block_type) { 986 case PCAPNG_BT_SHB: { 987 struct pcapng_section_header_fields *shbp = pcap_ng_get_section_header_fields(block); 988 struct pcapng_section_header_fields *rawshb; 989 990 rawshb = get_from_block_data(&cursor, sizeof(struct pcapng_section_header_fields), p->errbuf); 991 if (rawshb == NULL) 992 goto fail; 993 994 shbp->byte_order_magic = rawshb->byte_order_magic; 995 shbp->major_version = rawshb->major_version; 996 shbp->minor_version = rawshb->minor_version; 997 shbp->section_length = rawshb->section_length; 998 if (swapped) { 999 shbp->byte_order_magic = SWAPLONG(shbp->byte_order_magic); 1000 shbp->major_version = SWAPSHORT(shbp->major_version); 1001 shbp->minor_version = SWAPSHORT(shbp->minor_version); 1002 shbp->section_length = SWAPLONGLONG(shbp->section_length); 1003 } 1004 1005 break; 1006 } 1007 case PCAPNG_BT_IDB: { 1008 struct pcapng_interface_description_fields *idbp = pcap_ng_get_interface_description_fields(block); 1009 struct pcapng_interface_description_fields *rawidb; 1010 1011 rawidb = get_from_block_data(&cursor, sizeof(struct pcapng_interface_description_fields), p->errbuf); 1012 if (rawidb == NULL) 1013 goto fail; 1014 1015 idbp->linktype = rawidb->linktype; 1016 idbp->reserved = rawidb->reserved; 1017 idbp->snaplen = rawidb->snaplen; 1018 if (swapped) { 1019 idbp->linktype = SWAPSHORT(idbp->linktype); 1020 idbp->reserved = SWAPSHORT(idbp->reserved); 1021 idbp->snaplen = SWAPLONG(idbp->snaplen); 1022 } 1023 1024 break; 1025 } 1026 case PCAPNG_BT_ISB: { 1027 struct pcapng_interface_statistics_fields *isbp = pcap_ng_get_interface_statistics_fields(block); 1028 struct pcapng_interface_statistics_fields *rawisb; 1029 1030 rawisb = get_from_block_data(&cursor, sizeof(struct pcapng_interface_statistics_fields), p->errbuf); 1031 if (rawisb == NULL) 1032 goto fail; 1033 1034 isbp->interface_id = rawisb->interface_id; 1035 isbp->timestamp_high = rawisb->timestamp_high; 1036 isbp->timestamp_low = rawisb->timestamp_low; 1037 if (swapped) { 1038 isbp->interface_id = SWAPSHORT(isbp->interface_id); 1039 isbp->timestamp_high = SWAPLONG(isbp->timestamp_high); 1040 isbp->timestamp_low = SWAPLONG(isbp->timestamp_low); 1041 } 1042 1043 break; 1044 } 1045 case PCAPNG_BT_EPB: { 1046 struct pcapng_enhanced_packet_fields *epbp = pcap_ng_get_enhanced_packet_fields(block); 1047 struct pcapng_enhanced_packet_fields *rawepb; 1048 void *data; 1049 1050 rawepb = get_from_block_data(&cursor, sizeof(struct pcapng_enhanced_packet_fields), p->errbuf); 1051 if (rawepb == NULL) 1052 goto fail; 1053 1054 epbp->interface_id = rawepb->interface_id; 1055 epbp->timestamp_high = rawepb->timestamp_high; 1056 epbp->timestamp_low = rawepb->timestamp_low; 1057 epbp->caplen = rawepb->caplen; 1058 epbp->len = rawepb->len; 1059 if (swapped) { 1060 epbp->interface_id = SWAPLONG(epbp->interface_id); 1061 epbp->timestamp_high = SWAPLONG(epbp->timestamp_high); 1062 epbp->timestamp_low = SWAPLONG(epbp->timestamp_low); 1063 epbp->caplen = SWAPLONG(epbp->caplen); 1064 epbp->len = SWAPLONG(epbp->len); 1065 } 1066 data = get_from_block_data(&cursor, PAD_32BIT(epbp->caplen), p->errbuf); 1067 if (data == NULL) 1068 goto fail; 1069 block->pcapng_data_is_external = 0; 1070 block->pcapng_data_ptr = (u_char *)data; 1071 block->pcapng_cap_len = epbp->caplen; 1072 block->pcapng_data_len = PAD_32BIT(epbp->caplen); 1073 1074 break; 1075 } 1076 case PCAPNG_BT_SPB: { 1077 struct pcapng_simple_packet_fields *spbp = pcap_ng_get_simple_packet_fields(block); 1078 struct pcapng_simple_packet_fields *rawspb; 1079 void *data; 1080 uint32_t caplen; 1081 1082 rawspb = get_from_block_data(&cursor, sizeof(struct pcapng_simple_packet_fields), p->errbuf); 1083 if (rawspb == NULL) 1084 goto fail; 1085 1086 spbp->len = rawspb->len; 1087 if (swapped) { 1088 spbp->len = SWAPLONG(spbp->len); 1089 } 1090 caplen = bh.total_length - sizeof(struct pcapng_simple_packet_fields) - 1091 sizeof(struct pcapng_block_header) - sizeof(struct pcapng_block_trailer); 1092 if (caplen > spbp->len) 1093 caplen = spbp->len; 1094 data = get_from_block_data(&cursor, PAD_32BIT(caplen), p->errbuf); 1095 if (data == NULL) 1096 goto fail; 1097 block->pcapng_data_is_external = 0; 1098 block->pcapng_data_ptr = (u_char *)data; 1099 block->pcapng_cap_len = caplen; 1100 block->pcapng_data_len = PAD_32BIT(caplen); 1101 1102 break; 1103 } 1104 case PCAPNG_BT_PB: { 1105 struct pcapng_packet_fields *pbp = pcap_ng_get_packet_fields(block); 1106 struct pcapng_packet_fields *rawpb; 1107 void *data; 1108 1109 rawpb = get_from_block_data(&cursor, sizeof(struct pcapng_packet_fields), p->errbuf); 1110 if (rawpb == NULL) 1111 goto fail; 1112 1113 pbp->interface_id = rawpb->interface_id; 1114 pbp->drops_count = rawpb->drops_count; 1115 pbp->timestamp_high = rawpb->timestamp_high; 1116 pbp->timestamp_low = rawpb->timestamp_low; 1117 pbp->caplen = rawpb->caplen; 1118 pbp->len = rawpb->len; 1119 if (swapped) { 1120 /* these were written in opposite byte order */ 1121 pbp->interface_id = SWAPSHORT(pbp->interface_id); 1122 pbp->drops_count = SWAPSHORT(pbp->drops_count); 1123 pbp->timestamp_high = SWAPLONG(pbp->timestamp_high); 1124 pbp->timestamp_low = SWAPLONG(pbp->timestamp_low); 1125 pbp->caplen = SWAPLONG(pbp->caplen); 1126 pbp->len = SWAPLONG(pbp->len); 1127 } 1128 1129 data = get_from_block_data(&cursor, PAD_32BIT(pbp->caplen), p->errbuf); 1130 if (data == NULL) 1131 goto fail; 1132 block->pcapng_data_is_external = 0; 1133 block->pcapng_data_ptr = (u_char *)data; 1134 block->pcapng_cap_len = pbp->caplen; 1135 block->pcapng_data_len = PAD_32BIT(pbp->caplen); 1136 1137 break; 1138 } 1139 case PCAPNG_BT_PIB: { 1140 struct pcapng_process_information_fields *pibp = pcap_ng_get_process_information_fields(block); 1141 struct pcapng_process_information_fields *rawpib; 1142 1143 rawpib = get_from_block_data(&cursor, sizeof(struct pcapng_process_information_fields), p->errbuf); 1144 if (rawpib == NULL) 1145 goto fail; 1146 1147 pibp->process_id = rawpib->process_id; 1148 if (swapped) { 1149 pibp->process_id = SWAPSHORT(rawpib->process_id); 1150 } 1151 break; 1152 } 1153 case PCAPNG_BT_NRB: { 1154 struct pcapng_record_header *rh = (struct pcapng_record_header *)(block + 1); 1155 1156 while (1) { 1157 size_t record_len; 1158 1159 rh = get_from_block_data(&cursor, sizeof(struct pcapng_record_header), p->errbuf); 1160 if (rh == NULL) 1161 goto fail; 1162 1163 if (swapped) 1164 record_len = SWAPSHORT(rh->record_length); 1165 else 1166 record_len = rh->record_length; 1167 1168 if (get_from_block_data(&cursor, PCAPNG_ROUNDUP32(record_len), p->errbuf) == NULL) 1169 goto fail; 1170 1171 block->pcapng_records_len += sizeof(struct pcapng_record_header) + 1172 PCAPNG_ROUNDUP32(record_len); 1173 1174 if (rh->record_type == PCAPNG_NRES_ENDOFRECORD) 1175 break; 1176 } 1177 break; 1178 } 1179 default: 1180 goto fail; 1181 } 1182 1183 /* 1184 * Finally compute the length of the options as options come last in blocks 1185 */ 1186 while (1) { 1187 size_t optlen; 1188 struct pcapng_option_header *opt; 1189 1190 opt = get_from_block_data(&cursor, sizeof(struct pcapng_option_header), p->errbuf); 1191 /* 1192 * No, or no more options 1193 */ 1194 if (opt == NULL) 1195 break; 1196 1197 if (swapped) 1198 optlen = SWAPSHORT(opt->option_length); 1199 else 1200 optlen = opt->option_length; 1201 1202 if (get_from_block_data(&cursor, PCAPNG_ROUNDUP32(optlen), p->errbuf) == NULL) 1203 goto fail; 1204 1205 block->pcapng_options_len += sizeof(struct pcapng_option_header) + PCAPNG_ROUNDUP32(optlen); 1206 1207 if (opt->option_code == PCAPNG_OPT_ENDOFOPT) 1208 break; 1209 } 1210 1211 /* Success */ 1212 if (*pblock == NULL) 1213 *pblock = block; 1214 return (0); 1215 1216fail: 1217 if (*pblock == NULL && block != NULL) 1218 pcap_ng_free_block(block); 1219 return (PCAP_ERROR); 1220} 1221 1222int 1223pcap_ng_block_init_with_raw_block(pcapng_block_t block, pcap_t *p, u_char *raw_block) 1224{ 1225 return pcap_ng_block_internalize_common(&block, p, raw_block); 1226} 1227 1228pcapng_block_t 1229pcap_ng_block_alloc_with_raw_block(pcap_t *p, u_char *raw_block) 1230{ 1231 pcapng_block_t block = NULL; 1232 1233 if (pcap_ng_block_internalize_common(&block, p, raw_block) == 0) 1234 return (block); 1235 else 1236 return (NULL); 1237} 1238