diff options
Diffstat (limited to 'lib/libpcap/libpcap/tests')
-rw-r--r-- | lib/libpcap/libpcap/tests/hex_and_ascii_print.c | 64 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c | 700 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1 | 79 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c | 702 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1 | 79 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c | 710 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/nonblocktest.c | 226 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/offlinereadtest.c | 95 | ||||
-rw-r--r-- | lib/libpcap/libpcap/tests/shb-option-too-long.pcapng | bin | 0 -> 180 bytes |
9 files changed, 2655 insertions, 0 deletions
diff --git a/lib/libpcap/libpcap/tests/hex_and_ascii_print.c b/lib/libpcap/libpcap/tests/hex_and_ascii_print.c new file mode 100644 index 0000000..6ee836e --- /dev/null +++ b/lib/libpcap/libpcap/tests/hex_and_ascii_print.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include <stdio.h> +#include <ctype.h> + +#define MAXBUF 16 + +void +hex_and_ascii_print(const char *prefix, const void *data, + size_t len, const char *suffix) +{ + size_t i, j, k; + unsigned char *ptr = (unsigned char *)data; + unsigned char hexbuf[3 * MAXBUF + 1]; + unsigned char asciibuf[MAXBUF + 1]; + + for (i = 0; i < len; i += MAXBUF) { + for (j = i, k = 0; j < i + MAXBUF && j < len; j++) { + unsigned char msnbl = ptr[j] >> 4; + unsigned char lsnbl = ptr[j] & 0x0f; + + if (isprint(ptr[j])) + asciibuf[j % MAXBUF] = ptr[j]; + else + asciibuf[j % MAXBUF] = '.'; + asciibuf[(j % MAXBUF) + 1] = 0; + + hexbuf[k++] = msnbl < 10 ? msnbl + '0' : msnbl + 'a' - 10; + hexbuf[k++] = lsnbl < 10 ? lsnbl + '0' : lsnbl + 'a' - 10; + if ((j % 2) == 1) + hexbuf[k++] = ' '; + } + for (; j < i + MAXBUF;j++) { + hexbuf[k++] = ' '; + hexbuf[k++] = ' '; + if ((j % 2) == 1) + hexbuf[k++] = ' '; + } + hexbuf[k] = 0; + printf("%s%s %s%s", prefix, hexbuf, asciibuf, suffix); + } +} diff --git a/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c b/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c new file mode 100644 index 0000000..6d95e35 --- /dev/null +++ b/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#include <net/bpf.h> +#include <net/pktap.h> + +#include <assert.h> +#include <err.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> +#include <uuid/uuid.h> + +#include "pcap/pcap-ng.h" +#include "pcap-util.h" +#include "pcap-pktap.h" + +bool capture_done = false; +bool cap_pktap_v2 = false; +bool dump_pktap_v1 = true; +bool dump_pktap_v2 = false; +const char *filename = "pktap.pcapng"; +const char *ifname = "pktap"; +bool truncation = false; +int max_count = INT_MAX; +int verbosity = 0; +size_t max_length = 0; +uint32_t snap_len = 0; +bool want_pktap = true; + +struct dump_info { + pcap_t *p_cap; + + char *ifname_v1; + pcap_dumper_t *dumper_v1; + char *filename_v1; + int packet_count_v1; + size_t total_pktap_header_space; + size_t total_bpf_length_v1; + + char *ifname_v2; + pcap_dumper_t *dumper_v2; + char *filename_v2; + int packet_count_v2; + size_t total_pktap_v2_hdr_space; + size_t total_bpf_length_v2; +}; + +#define MAX_PACKET_LEN 65535 + +static u_char temp_buffer[1024 * 1024]; + +static void +print_pktap_header(const struct pktap_header *pktp_hdr) +{ + uuid_string_t uuidstr, euuidstr; + + fprintf(stderr, "pth_length %u (sizeof(struct pktap_header) %lu)\n", + pktp_hdr->pth_length, sizeof(struct pktap_header)); + fprintf(stderr, "pth_type_next %u\n", pktp_hdr->pth_type_next); + fprintf(stderr, "pth_dlt %u\n", pktp_hdr->pth_dlt); + fprintf(stderr, "pth_ifname %s pth_iftype %d\n", pktp_hdr->pth_ifname, pktp_hdr->pth_iftype); + fprintf(stderr, "pth_flags 0x%x\n", pktp_hdr->pth_flags); + fprintf(stderr, "pth_protocol_family %u\n", pktp_hdr->pth_protocol_family); + fprintf(stderr, "pth_frame_pre_length %u pth_frame_post_length %u\n", + pktp_hdr->pth_frame_pre_length, pktp_hdr->pth_frame_post_length); + fprintf(stderr, "pth_svc %u\n", pktp_hdr->pth_svc); + fprintf(stderr, "pth_flowid %u\n", pktp_hdr->pth_flowid); + fprintf(stderr, "pth_ipproto %u\n", pktp_hdr->pth_ipproto); + fprintf(stderr, "pth_pid %u pth_epid %u\n", pktp_hdr->pth_pid, pktp_hdr->pth_epid); + fprintf(stderr, "pth_comm %s pth_ecomm %s\n", pktp_hdr->pth_comm, pktp_hdr->pth_ecomm); + uuid_unparse(pktp_hdr->pth_uuid, uuidstr); + uuid_unparse(pktp_hdr->pth_euuid, euuidstr); + fprintf(stderr, "pth_uuid %s pth_euuid %s\n", + uuid_is_null(pktp_hdr->pth_uuid) ? "" : uuidstr, + uuid_is_null(pktp_hdr->pth_euuid) ? "" : euuidstr); +} + +static void +print_pktap_v2_hdr(const struct pktap_v2_hdr *pktp_hdr) +{ + uuid_string_t uuidstr, euuidstr; + char *ptr = (char *)pktp_hdr; + + fprintf(stderr, "pth2_length %u (sizeof(struct pktap_v2_hdr) %lu)\n", + pktp_hdr->pth_length, sizeof(struct pktap_v2_hdr)); + fprintf(stderr, "pth2_dlt %u\n", pktp_hdr->pth_dlt); + fprintf(stderr, "pth2_ifname %s pth2_iftype %d\n", + pktp_hdr->pth_ifname_offset != 0 ? ptr + pktp_hdr->pth_ifname_offset : "", + pktp_hdr->pth_iftype); + fprintf(stderr, "pth2_flags 0x%x\n", pktp_hdr->pth_flags); + fprintf(stderr, "pth2_protocol_family %u\n", pktp_hdr->pth_protocol_family); + fprintf(stderr, "pth2_frame_pre_length %u pth2_frame_post_length %u\n", + pktp_hdr->pth_frame_pre_length, pktp_hdr->pth_frame_post_length); + fprintf(stderr, "pth2_svc %u\n", pktp_hdr->pth_svc); + fprintf(stderr, "pth2_flowid %u\n", pktp_hdr->pth_flowid); + fprintf(stderr, "pth2_ipproto %u\n", pktp_hdr->pth_ipproto); + fprintf(stderr, "pth2_pid %u pth2_e_pid %u\n", pktp_hdr->pth_pid, pktp_hdr->pth_e_pid); + + fprintf(stderr, "pth2_comm %s pth2_ecomm %s\n", + pktp_hdr->pth_comm_offset != 0 ? ptr + pktp_hdr->pth_comm_offset : "", + pktp_hdr->pth_e_comm_offset != 0 ? ptr + pktp_hdr->pth_e_comm_offset : ""); + if (pktp_hdr->pth_uuid_offset != 0) + uuid_unparse(*(const uuid_t *)(ptr + pktp_hdr->pth_uuid_offset), uuidstr); + if (pktp_hdr->pth_e_uuid_offset != 0) + uuid_unparse(*(const uuid_t *)(ptr + pktp_hdr->pth_e_uuid_offset), euuidstr); + fprintf(stderr, "pth2_uuid %s pth2_euuid %s\n", + pktp_hdr->pth_uuid_offset == 0 ? "" : uuidstr, + pktp_hdr->pth_e_uuid_offset == 0 ? "" : euuidstr); +} +static size_t +convert_pktap_header_to_v2(const struct pktap_header *pktp_hdr, struct pktap_v2_hdr_space *pktap_v2_hdr_space) +{ + struct pktap_v2_hdr *pktap_v2_hdr; + + pktap_v2_hdr = &pktap_v2_hdr_space->pth_hdr; + + COPY_PKTAP_COMMON_FIELDS_TO_V2(pktap_v2_hdr, pktp_hdr); + + if (!uuid_is_null(pktp_hdr->pth_uuid)) { + size_t len = sizeof(uuid_t); + uint8_t *ptr; + + pktap_v2_hdr->pth_uuid_offset = pktap_v2_hdr->pth_length; + ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_uuid_offset; + uuid_copy(*(uuid_t *)ptr, pktp_hdr->pth_uuid); + + pktap_v2_hdr->pth_length += len; + assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space)); + } + + if (!uuid_is_null(pktp_hdr->pth_euuid)) { + size_t len = sizeof(uuid_t); + uint8_t *ptr; + + pktap_v2_hdr->pth_e_uuid_offset = pktap_v2_hdr->pth_length; + ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_e_uuid_offset; + uuid_copy(*(uuid_t *)ptr, pktp_hdr->pth_euuid); + + pktap_v2_hdr->pth_length += len; + assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space)); + } + + if (strlen(pktp_hdr->pth_ifname) > 0) { + size_t len; + uint8_t *ptr; + + pktap_v2_hdr->pth_ifname_offset = pktap_v2_hdr->pth_length; + ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_ifname_offset; + len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_ifname, sizeof(pktap_v2_hdr_space->pth_ifname)); + + pktap_v2_hdr->pth_length += len; + assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space)); + } + + if (strlen(pktp_hdr->pth_comm) > 0) { + size_t len; + uint8_t *ptr; + + pktap_v2_hdr->pth_comm_offset = pktap_v2_hdr->pth_length; + ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_comm_offset; + len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_comm, sizeof(pktap_v2_hdr_space->pth_comm)); + + pktap_v2_hdr->pth_length += len; + assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space)); + } + + if (strlen(pktp_hdr->pth_ecomm) > 0) { + size_t len; + uint8_t *ptr; + + pktap_v2_hdr->pth_e_comm_offset = pktap_v2_hdr->pth_length; + ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_e_comm_offset; + len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_ecomm, sizeof(pktap_v2_hdr_space->pth_e_comm)); + + pktap_v2_hdr->pth_length += len; + assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space)); + } + + return (pktap_v2_hdr->pth_length); +} + +static size_t +convert_v2_to_pktap_header(const struct pktap_v2_hdr *pktap_v2_hdr_src, struct pktap_header *pktap_header_dst) +{ + uint8_t *ptr = (uint8_t *)pktap_v2_hdr_src; + + pktap_header_dst->pth_length = sizeof(struct pktap_header); + pktap_header_dst->pth_type_next = PTH_TYPE_PACKET; + pktap_header_dst->pth_dlt = pktap_v2_hdr_src->pth_dlt; + pktap_header_dst->pth_frame_pre_length = pktap_v2_hdr_src->pth_frame_pre_length; + pktap_header_dst->pth_frame_pre_length = pktap_v2_hdr_src->pth_frame_pre_length; + pktap_header_dst->pth_iftype = pktap_v2_hdr_src->pth_iftype; + pktap_header_dst->pth_ipproto = pktap_v2_hdr_src->pth_ipproto; + pktap_header_dst->pth_protocol_family = pktap_v2_hdr_src->pth_protocol_family; + pktap_header_dst->pth_svc = pktap_v2_hdr_src->pth_svc; + pktap_header_dst->pth_flowid = pktap_v2_hdr_src->pth_flowid; + pktap_header_dst->pth_pid = pktap_v2_hdr_src->pth_pid; + pktap_header_dst->pth_epid = pktap_v2_hdr_src->pth_e_pid; + pktap_header_dst->pth_flags = pktap_v2_hdr_src->pth_flags; + pktap_header_dst->pth_flags &= ~PTH_FLAG_V2_HDR; + + if (pktap_v2_hdr_src->pth_uuid_offset != 0) + uuid_copy(pktap_header_dst->pth_uuid, (ptr + pktap_v2_hdr_src->pth_uuid_offset)); + + if (pktap_v2_hdr_src->pth_e_uuid_offset != 0) + uuid_copy(pktap_header_dst->pth_euuid, (ptr + pktap_v2_hdr_src->pth_e_uuid_offset)); + + if (pktap_v2_hdr_src->pth_ifname_offset != 0) + strlcpy(pktap_header_dst->pth_ifname, (char *)(ptr + pktap_v2_hdr_src->pth_ifname_offset), sizeof(pktap_header_dst->pth_ifname)); + + if (pktap_v2_hdr_src->pth_comm_offset != 0) + strlcpy(pktap_header_dst->pth_comm, (char *)(ptr + pktap_v2_hdr_src->pth_comm_offset), sizeof(pktap_header_dst->pth_comm)); + + if (pktap_v2_hdr_src->pth_e_comm_offset != 0) + strlcpy(pktap_header_dst->pth_ecomm, (char *)(ptr + pktap_v2_hdr_src->pth_e_comm_offset), sizeof(pktap_header_dst->pth_ecomm)); + + return (sizeof(struct pktap_header)); +} + +static bool +save_pktap_v1(struct dump_info *dump_info, const struct pcap_pkthdr *h, const u_char *bytes) +{ + int status; + struct pcap_pkthdr pcap_pkthdr; + + memcpy(&pcap_pkthdr, h, sizeof(struct pcap_pkthdr)); + + if (snap_len > 0 && pcap_pkthdr.caplen > snap_len) { + pcap_pkthdr.caplen = snap_len; + } + if (((struct pktap_v2_hdr *)bytes)->pth_flags & PTH_FLAG_V2_HDR) { + const struct pktap_v2_hdr *pktap_v2_hdr = (struct pktap_v2_hdr *)bytes; + struct pktap_header pktap_header_space; + struct pktap_header pktap_header_space_bis; + size_t v1_hdr_len; + struct pktap_v2_hdr_space pktap_v2_hdr_space; + size_t v2_hdr_len; + + memset(&pktap_header_space, 0, sizeof(struct pktap_header)); + memset(&pktap_header_space_bis, 0, sizeof(struct pktap_header)); + memset(&pktap_v2_hdr_space, 0, sizeof(struct pktap_v2_hdr_space)); + + + v1_hdr_len = convert_v2_to_pktap_header(pktap_v2_hdr, &pktap_header_space); + assert(v1_hdr_len == sizeof(struct pktap_header)); + + if (verbosity > 1) { + print_pktap_v2_hdr(pktap_v2_hdr); + print_pktap_header(&pktap_header_space); + } + v2_hdr_len = convert_pktap_header_to_v2(&pktap_header_space, &pktap_v2_hdr_space); + + /* + * The conversion is not symetrical because the strings in the pktap_v2_hdr + * are of variable length and null uuid and empty string are omitted + * Note that BPF may pass empty string and null uuid + * We can compare the conversion to pktap_header + */ + (void) convert_v2_to_pktap_header(&pktap_v2_hdr_space.pth_hdr, &pktap_header_space_bis); + assert(memcmp(&pktap_header_space, &pktap_header_space_bis, v1_hdr_len) == 0); + + assert(pcap_pkthdr.caplen + sizeof(struct pktap_header) - pktap_v2_hdr->pth_length <= sizeof(temp_buffer)); + + memcpy(temp_buffer, &pktap_header_space, sizeof(struct pktap_header)); + memcpy(temp_buffer + sizeof(struct pktap_header), bytes + pktap_v2_hdr->pth_length, + pcap_pkthdr.caplen - pktap_v2_hdr->pth_length); + + pcap_pkthdr.caplen += sizeof(struct pktap_header) - pktap_v2_hdr->pth_length; + pcap_pkthdr.len += sizeof(struct pktap_header) - pktap_v2_hdr->pth_length; + + status = pcap_ng_dump_pktap(dump_info->p_cap, dump_info->dumper_v1, + &pcap_pkthdr, temp_buffer); + if (status == 0) { + warnx("%s: pcap_ng_dump_pktap: %s\n", + __func__, pcap_geterr(dump_info->p_cap)); + return (false); + } + } else if (((struct pktap_header *)bytes)->pth_type_next == PTH_TYPE_PACKET) { + status = pcap_ng_dump_pktap(dump_info->p_cap, dump_info->dumper_v1, + &pcap_pkthdr, bytes); + if (status == 0) { + warnx("%s: pcap_ng_dump_pktap: %s\n", + __func__, pcap_geterr(dump_info->p_cap)); + return (false); + } + } else { + warnx("%s: unkwnown pktap_header type\n", + __func__); + return (false); + } + + dump_info->packet_count_v1++; + dump_info->total_bpf_length_v1 += sizeof(struct bpf_hdr) + pcap_pkthdr.caplen; + dump_info->total_pktap_header_space += sizeof(struct pktap_header); + + if (verbosity > 0) { + fprintf(stderr, "%s: v1 packet count: %d total bpf length: %lu\n", + __func__, dump_info->packet_count_v1, dump_info->total_bpf_length_v1); + } + + return (true); +} + +static void +zero_out_unused_pktap_header_fields_for_v2(struct pktap_header *pktp_hdr) +{ + pktp_hdr->pth_ifunit = 0; + pktp_hdr->pth_tstamp.tv_sec = 0; + pktp_hdr->pth_tstamp.tv_usec = 0; +} + +static bool +save_pktap_v2(struct dump_info *dump_info, const struct pcap_pkthdr *h, const u_char *bytes) +{ + int status; + struct pcap_pkthdr pcap_pkthdr; + + memcpy(&pcap_pkthdr, h, sizeof(struct pcap_pkthdr)); + + if (snap_len > 0 && pcap_pkthdr.caplen > snap_len) { + pcap_pkthdr.caplen = snap_len; + } + + if (((struct pktap_v2_hdr *)bytes)->pth_flags & PTH_FLAG_V2_HDR) { + const struct pktap_v2_hdr *pktap_v2_hdr = (struct pktap_v2_hdr *)bytes; + struct pktap_header pktap_header_space; + size_t v1_hdr_len; + + v1_hdr_len = convert_v2_to_pktap_header(pktap_v2_hdr, &pktap_header_space); + assert(v1_hdr_len == sizeof(struct pktap_header)); + + dump_info->total_pktap_v2_hdr_space += pktap_v2_hdr->pth_length; + + status = pcap_ng_dump_pktap_v2(dump_info->p_cap, dump_info->dumper_v2, + &pcap_pkthdr, bytes, NULL); + if (status == 0) { + warnx("%s: pcap_ng_dump_pktap_v2: %s\n", + __func__, pcap_geterr(dump_info->p_cap)); + pcap_breakloop(dump_info->p_cap); + } + } else if (((struct pktap_header *)bytes)->pth_type_next == PTH_TYPE_PACKET) { + const struct pktap_header *pktp_hdr = (struct pktap_header *)bytes; + struct pktap_header pktap_header_space; + size_t v1_hdr_len; + struct pktap_v2_hdr_space pktap_v2_hdr_space; + size_t v2_hdr_len; + size_t offset; + u_char *new_bytes; + struct pktap_header pktap_header_copy; + + memset(&pktap_header_space, 0, sizeof(struct pktap_header)); + memset(&pktap_header_copy, 0, sizeof(struct pktap_header)); + + /* + * Zero out the fields in the pktap_header we do not care about + */ + memcpy(&pktap_header_copy, pktp_hdr, sizeof(struct pktap_header)); + zero_out_unused_pktap_header_fields_for_v2(&pktap_header_copy); + + v2_hdr_len = convert_pktap_header_to_v2(&pktap_header_copy, &pktap_v2_hdr_space); + + if (verbosity > 1) { + print_pktap_header(&pktap_header_copy); + print_pktap_v2_hdr(&pktap_v2_hdr_space.pth_hdr); + } + dump_info->total_pktap_v2_hdr_space += pktap_v2_hdr_space.pth_hdr.pth_length; + + v1_hdr_len = convert_v2_to_pktap_header(&pktap_v2_hdr_space.pth_hdr, &pktap_header_space); + assert(v1_hdr_len == sizeof(struct pktap_header)); + assert(memcmp(&pktap_header_copy, &pktap_header_space, sizeof(struct pktap_header)) == 0); + + offset = sizeof(struct pktap_header) - v2_hdr_len; + new_bytes = (u_char *)bytes + offset; + memcpy(new_bytes, &pktap_v2_hdr_space, v2_hdr_len); + + pcap_pkthdr.caplen -= offset; + pcap_pkthdr.len -= offset; + status = pcap_ng_dump_pktap_v2(dump_info->p_cap, dump_info->dumper_v2, + &pcap_pkthdr, new_bytes, NULL); + if (status == 0) { + warnx("%s: pcap_ng_dump_pktap_v2: %s\n", + __func__, pcap_geterr(dump_info->p_cap)); + return (false); + } + } else { + warnx("%s: unkwnown pktap header type\n", + __func__); + return (false); + } + + dump_info->packet_count_v2++; + dump_info->total_bpf_length_v2 += sizeof(struct bpf_hdr) + pcap_pkthdr.caplen; + + if (verbosity > 0) { + fprintf(stderr, "%s: v2 packet count: %d total bpf length: %lu\n", + __func__, dump_info->packet_count_v2, dump_info->total_bpf_length_v2); + } + + return (true); +} + + +static void +readcallback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) +{ + struct dump_info *dump_info = (struct dump_info *) user; + bool v1_done = false; + bool v2_done = false; + + if (dump_pktap_v1) { + if ((max_count != 0 && dump_info->packet_count_v1 > max_count) || + (max_length != 0 && dump_info->total_bpf_length_v1 >= max_length)) { + v1_done = true; + } else if (!save_pktap_v1(dump_info, h, bytes)) { + v1_done = true; + v2_done = true; + } + } else { + v1_done = true; + } + + if (dump_pktap_v2) { + if ((max_count != 0 && dump_info->packet_count_v2 > max_count) || + (max_length != 0 && dump_info->total_bpf_length_v2 >= max_length)) { + v2_done = true; + } else if (!save_pktap_v2(dump_info, h, bytes)) { + v2_done = true; + } + } else { + v2_done = true; + } + + if (capture_done || (v1_done && v2_done)) { + if (verbosity > 0) { + fprintf(stderr, "%s: done\n", + __func__); + } + pcap_breakloop(dump_info->p_cap); + } +} + +static void +usage(void) +{ +#define OPTION_FMT " %-20s %s\n" + printf("# usage: %s [-c 1|2] [-d 1|-1|2|-2] [-f filename] [-h] [-i ifname] [-l max_length] [-n max_count] [-s snap_len] [-t 0|1] [-v]\n", + getprogname()); + printf(OPTION_FMT, "-c 1|2", "capture version 1 'struct pktap_header' or version 2 'struct pktap_hdr_v2' (v1 by default)"); + printf(OPTION_FMT, "-d 1|-1|2|-2", "dump using version 1 pcap_ng_dump_pktap() and/or version 2 pcap_ng_dump_pktap_v2() (v1 by default)"); + printf(OPTION_FMT, "-f filename", "file name for dump file (to be prefixed with 'v1_' or 'v2'"); + printf(OPTION_FMT, "-h", "display this help"); + printf(OPTION_FMT, "-i ifname", "capture interface name (pktap by default)"); + printf(OPTION_FMT, "-l max_length", "maximum length of packet captured (unlimited by default"); + printf(OPTION_FMT, "-n max_count", "maximum number of packet to capture (unlimited by default"); + printf(OPTION_FMT, "-s snap_len", "snap len (unlimited by default)"); + printf(OPTION_FMT, "-t 0|1", "truncation mode (off by default)"); + printf(OPTION_FMT, "-v", "increase versbosity"); +} + +void +parse_command_line(int argc, char * const argv[]) +{ + int ch; + + if (argc == 1) { + usage(); + exit(EX_OK); + } + while ((ch = getopt(argc, argv, "c:d:f:hi:l:n:qs:t:vw:")) != -1) { + switch (ch) { + case 'c': + if (strcmp(optarg, "1") == 0) { + cap_pktap_v2 = false; + } else if (strcmp(optarg, "2") == 0) { + cap_pktap_v2 = true; + } else { + warnx("bad parameter '%s' for option '-%c'", optarg, ch); + usage(); + exit(EX_USAGE); + } + break; + + case 'd': + if (strcmp(optarg, "1") == 0) { + dump_pktap_v1 = true; + } else if (strcmp(optarg, "-1") == 0) { + dump_pktap_v1 = false; + } else if (strcmp(optarg, "2") == 0) { + dump_pktap_v2 = true; + } else if (strcmp(optarg, "-2") == 0) { + dump_pktap_v2 = false; + } else { + warnx("bad parameter '%s' for option '-%c'", optarg, ch); + usage(); + exit(EX_USAGE); + } + break; + + case 'f': + filename = optarg; + break; + + case 'h': + usage(); + exit(EX_OK); + + case 'i': + ifname = optarg; + break; + + case 'l': + max_length = strtoul(optarg, NULL, 0); + break; + + case 'n': + max_count = atoi(optarg); + break; + + case 'q': + verbosity--; + break; + + case 's': + snap_len = (uint32_t) strtoul(optarg, NULL, 0); + break; + + case 't': + truncation = !!atoi(optarg); + break; + + case 'v': + verbosity++; + break; + + case 'w': + want_pktap = !!atoi(optarg); + break; + + default: + usage(); + exit(EX_USAGE); + } + } +} + +void +signal_handler(int sig) +{ + capture_done = true; +} + +int +main(int argc, char * const argv[]) { + char ebuf[PCAP_ERRBUF_SIZE]; + int status; + struct dump_info dump_info = {}; + + parse_command_line(argc, argv); + + dump_info.ifname_v1 = pcap_setup_pktap_interface(ifname, ebuf); + if (dump_info.ifname_v1 == NULL) { + errx(EX_OSERR, "pcap_setup_pktap_interface(%s) fail - %s", + ifname, ebuf); + } + dump_info.ifname_v2 = pcap_setup_pktap_interface(ifname, ebuf); + if (dump_info.ifname_v2 == NULL) { + errx(EX_OSERR, "pcap_setup_pktap_interface(pktap) fail - %s", + ebuf); + } + + dump_info.p_cap = pcap_create(ifname, ebuf); + if (dump_info.p_cap == NULL) { + errx(EX_OSERR, "pcap_create(%s) fail - %s", + ifname, ebuf); + } + status = pcap_set_timeout(dump_info.p_cap, 1000); + if (status != 0) { + errx(EX_OSERR, "pcap_create(%s) fail - %s", + ifname, pcap_statustostr(status)); + } + + /* + * Must be called before pcap_activate() + */ + pcap_set_want_pktap(dump_info.p_cap, want_pktap); + pcap_set_pktap_hdr_v2(dump_info.p_cap, cap_pktap_v2); + pcap_set_truncation_mode(dump_info.p_cap, truncation); + if (snap_len > 0) + pcap_set_snaplen(dump_info.p_cap, snap_len); + + status = pcap_activate(dump_info.p_cap); + if (status < 0) { + if (status == PCAP_ERROR) { + errx(EX_OSERR, "pcap_activate(%s) fail - %s", + ifname, pcap_geterr(dump_info.p_cap)); + } else { + errx(EX_OSERR, "pcap_activate(%s) fail - %s %s", + ifname, pcap_statustostr(status), pcap_geterr(dump_info.p_cap)); + } + } + + if (verbosity) { + int dlt = pcap_datalink(dump_info.p_cap); + const char *dltname = pcap_datalink_val_to_name(dlt); + int n_dlts, i; + int *dlts = 0; + + fprintf(stderr, "wantpktap %d\n", want_pktap); + + fprintf(stderr, "pcap_datalink: %d name: %s\n", dlt, dltname); + + n_dlts = pcap_list_datalinks(dump_info.p_cap, &dlts); + + for (i = 0; i < n_dlts; i++) { + dltname = pcap_datalink_val_to_name(dlts[i]); + fprintf(stderr, "pcap_list_datalinks[%d]: %d name: %s\n", i, dlts[i], dltname); + } + pcap_free_datalinks(dlts); + } + + if (dump_pktap_v1) { + dump_info.filename_v1 = malloc(PATH_MAX); + snprintf(dump_info.filename_v1, PATH_MAX, "v1_%s", filename); + dump_info.dumper_v1 = pcap_ng_dump_open(dump_info.p_cap, dump_info.filename_v1); + if (dump_info.dumper_v1 == NULL) { + errx(EX_OSERR, "pcap_ng_dump_open(%s) fail - %s", + dump_info.filename_v1, pcap_geterr(dump_info.p_cap)); + } + } + + if (dump_pktap_v2) { + dump_info.filename_v2 = malloc(PATH_MAX); + snprintf(dump_info.filename_v2, PATH_MAX, "v2_%s", filename); + dump_info.dumper_v2 = pcap_ng_dump_open(dump_info.p_cap, dump_info.filename_v2); + if (dump_info.dumper_v2 == NULL) { + errx(EX_OSERR, "pcap_ng_dump_open(%s) fail - %s", + dump_info.filename_v2, pcap_geterr(dump_info.p_cap)); + } + } + + /* to stop the capture */ + signal(SIGINT, signal_handler); + + while (true) { + status = pcap_dispatch(dump_info.p_cap, -1, readcallback, (u_char *) &dump_info); + if (status == -1) { + errx(EX_OSERR, "pcap_dispatch(%s) fail - %s", + ifname, pcap_geterr(dump_info.p_cap)); + } else if (status == -2) { + /* pcap_breakloop() called */ + break; + } + } + + if (dump_pktap_v1) { + pcap_dump_close(dump_info.dumper_v1); + fprintf(stderr, "v1 file: %s packet count: %d total bpf length: %lu pktap header space %lu\n", + dump_info.filename_v1, dump_info.packet_count_v1, + dump_info.total_bpf_length_v1, dump_info.total_pktap_header_space); + } + if (dump_pktap_v2) { + pcap_dump_close(dump_info.dumper_v2); + fprintf(stderr, "v2 file: %s packet count: %d total bpf length: %lu pktap v2 hdr space %lu\n", + dump_info.filename_v2, dump_info.packet_count_v2, + dump_info.total_bpf_length_v2, dump_info.total_pktap_v2_hdr_space); + } + pcap_close(dump_info.p_cap); + + exit(EX_OK); +} diff --git a/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1 b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1 new file mode 100644 index 0000000..e2420e5 --- /dev/null +++ b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 10/12/12 \" DATE
+.Dt ngdumptest 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm ngdumptest,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file diff --git a/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c new file mode 100644 index 0000000..e9fbcc7 --- /dev/null +++ b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2012-2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#include <stdio.h> +#include <err.h> +#include <sysexits.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/kern_event.h> +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <uuid/uuid.h> +#include <net/pktap.h> + +#include "pcap/bpf.h" + +#include "pcap/pcap-ng.h" +#include "pcap-util.h" + +enum { + SIMPLE_PACKET = 0, + ENHANCED_PACKET = 1, + OBSOLETE_PACKET = 2, + PKTAP_PACKET = 3 +}; + +const char *if_name = NULL; +int type_of_packet = ENHANCED_PACKET; +char *proc_name = NULL; +uint32_t proc_pid = -1; +uuid_t proc_uuid; +int32_t proc_index = -1; +const char *comment = NULL; +pcap_t *pcap = NULL; +pcap_dumper_t *dumper = NULL; +size_t ext_len = 65536; +void *ext_buffer = NULL; +int first_comment = 0; +unsigned char *packet_data = NULL; +size_t packet_length = 0; +unsigned long num_data_blocks = 1; +int copy_data_buffer = 0; +int verbose = 0; + +void hex_and_ascii_print(const char *, const void *, size_t, const char *); + +void +help(const char *str) +{ + printf("# usage: %s options...\n", str); + printf("# options in order of dependency:\n"); + printf(" %-36s # %s\n", "-4 ipv4:name[:name...]", "IPv4 name resolution record"); + printf(" %-36s # %s\n", "-6 ipv6:name[:name...]", "IPv6 name resolution record"); + printf(" %-36s # %s\n", "-C", "copy data packet from data buffer"); + printf(" %-36s # %s\n", "-c string", "comment option"); + printf(" %-36s # %s\n", "-D length", "packet data length"); + printf(" %-36s # %s\n", "-d string", "packet data as a string"); + printf(" %-36s # %s\n", "-f", "first comment option"); + printf(" %-36s # %s\n", "-k len", "kernel event of given len"); + printf(" %-36s # %s\n", "-i name", "interface name"); + printf(" %-36s # %s\n", "-n num_data", "number of data blocks"); + printf(" %-36s # %s\n", "-p name:pid:uuid", "process name, pid and uuid"); + printf(" %-36s # %s\n", "-p type:data", "secrets type (number), secrets data (string)"); + printf(" %-36s # %s\n", "-t (simple|enhanced|obsolote|pktap)", "type of packet"); + printf(" %-36s # %s\n", " ", "note obsolete is not implemented"); + printf(" %-36s # %s\n", "-w name", "packet capture file name"); + printf(" %-36s # %s\n", "-x [buffer_length]", "externalize in buffer of given length"); +} + +void +write_block(pcapng_block_t block) +{ + bpf_u_int32 n; + + if (dumper != NULL) { + n = pcap_ng_dump_block(dumper, block); + if (n != pcap_ng_block_get_len(block)) + printf("%s: block len %u != pcap_ng_block_get_len() %u\n", + __func__, pcap_ng_block_get_len(block), n); + } + if (ext_buffer != NULL) { + n = pcap_ng_externalize_block(ext_buffer, ext_len, block); + hex_and_ascii_print("", ext_buffer, pcap_ng_block_get_len(block), "\n"); + if (n != pcap_ng_block_get_len(block)) + printf("%s: block len %u != pcap_ng_externalize_block() %u\n", + __func__, pcap_ng_block_get_len(block), n); + } +} + +void +make_interface_description_block(const char *name) +{ + struct pcapng_interface_description_fields *idb_fields; + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + pcap_ng_block_reset(block, PCAPNG_BT_IDB); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + idb_fields = pcap_ng_get_interface_description_fields(block); + idb_fields->idb_linktype = DLT_RAW; + idb_fields->idb_snaplen = 65536; + + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + pcap_ng_block_add_option_with_string(block, PCAPNG_IF_NAME, name); + + write_block(block); + + pcap_ng_free_block(block); + +} + +void +make_process_information_block(const char *name, uint32_t pid, const uuid_t uu) +{ + struct pcapng_process_information_fields *pib_fields; + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + pcap_ng_block_reset(block, PCAPNG_BT_PIB); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + pib_fields = pcap_ng_get_process_information_fields(block); + pib_fields->process_id = pid; + + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + if (name != NULL) + pcap_ng_block_add_option_with_string(block, PCAPNG_PIB_NAME, name); + + if (uuid_is_null(uu) == 0) + pcap_ng_block_add_option_with_uuid(block, PCAPNG_PIB_UUID, uu); + + write_block(block); + + pcap_ng_free_block(block); +} + +void +make_kern_event_block(struct kern_event_msg *event) +{ + struct pcapng_os_event_fields *osev_fields; + struct timeval ts; + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + gettimeofday(&ts, NULL); + + pcap_ng_block_reset(block, PCAPNG_BT_OSEV); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + osev_fields = pcap_ng_get_os_event_fields(block); + osev_fields->type = PCAPNG_OSEV_KEV; + osev_fields->timestamp_high = (bpf_u_int32)ts.tv_sec; + osev_fields->timestamp_low = ts.tv_usec; + osev_fields->len = event->total_size; + + if (copy_data_buffer) + pcap_ng_block_packet_copy_data(block, event, event->total_size); + else + pcap_ng_block_packet_set_data(block, event, event->total_size); + + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + write_block(block); + + pcap_ng_free_block(block); +} + +void +make_decryption_secrets_block(uint32_t type, size_t len, uint8_t *data) +{ + struct pcapng_decryption_secrets_fields *dsb_fields; + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + pcap_ng_block_reset(block, PCAPNG_BT_DSB); + + if (first_comment && comment) { + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + } + + dsb_fields = pcap_ng_get_decryption_secrets_fields(block); + dsb_fields->secrets_type = type; + dsb_fields->secrets_length = (uint32_t)len; + + if (copy_data_buffer) { + pcap_ng_block_packet_copy_data(block, data, dsb_fields->secrets_length); + } else { + pcap_ng_block_packet_set_data(block, data, dsb_fields->secrets_length); + } + if (!first_comment && comment) { + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + } + write_block(block); + + pcap_ng_free_block(block); +} + +void +make_data_block(const void *data, size_t len) +{ + unsigned int i; + + for (i = 0; i < num_data_blocks; i++) { + if (verbose) + printf("%s\n", __func__); + + switch (type_of_packet) { + case SIMPLE_PACKET: { + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + pcap_ng_block_reset(block, PCAPNG_BT_SPB); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + if (copy_data_buffer) + pcap_ng_block_packet_copy_data(block, data, (bpf_u_int32)len); + else + pcap_ng_block_packet_set_data(block, data, (bpf_u_int32)len); + + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + write_block(block); + + pcap_ng_free_block(block); + break; + } + case ENHANCED_PACKET: { + struct pcapng_enhanced_packet_fields *epb_fields; + uint32_t pktflags = PCAPNG_PBF_DIR_OUTBOUND | PCAPNG_PBF_DIR_INBOUND; + uint32_t pmdflags = PCAPNG_EPB_PMDF_NEW_FLOW | PCAPNG_EPB_PMDF_REXMIT | + PCAPNG_EPB_PMDF_KEEP_ALIVE | PCAPNG_EPB_PMDF_SOCKET | PCAPNG_EPB_PMDF_NEXUS_CHANNEL; + + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + pcap_ng_block_reset(block, PCAPNG_BT_EPB); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + epb_fields = pcap_ng_get_enhanced_packet_fields(block); + epb_fields->caplen = (bpf_u_int32)len; + epb_fields->len = (bpf_u_int32)len; + epb_fields->interface_id = 0; + epb_fields->timestamp_high = 10000; + epb_fields->timestamp_low = 2000; + + if (copy_data_buffer) + pcap_ng_block_packet_copy_data(block, data, (bpf_u_int32)len); + else + pcap_ng_block_packet_set_data(block, data, (bpf_u_int32)len); + + if (proc_name != NULL) { + pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PIB_INDEX, &proc_index, sizeof(proc_index)); + } + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_FLAGS , &pktflags, 4); + + pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PMD_FLAGS, &pmdflags, 4); + + write_block(block); + + pcap_ng_free_block(block); + break; + } + case PKTAP_PACKET: { + struct pcap_pkthdr h; + u_char *buffer = malloc(sizeof(struct pktap_header) + len); + struct pktap_header *pktp_hdr; + + bzero(&h, sizeof(struct pcap_pkthdr)); + h.ts.tv_sec = 10000; + h.ts.tv_usec = 2000; + h.caplen = (bpf_u_int32) (sizeof(struct pktap_header) + len); + h.len = (bpf_u_int32) (sizeof(struct pktap_header) + len); + + pktp_hdr = (struct pktap_header *)buffer; + bzero(pktp_hdr, sizeof(struct pktap_header)); + bcopy(data, pktp_hdr + 1, len); + pktp_hdr->pth_length = sizeof(struct pktap_header); + snprintf(pktp_hdr->pth_ifname, sizeof(pktp_hdr->pth_ifname), "%s", if_name); + pktp_hdr->pth_pid = proc_pid; + pktp_hdr->pth_epid = -1; + if (proc_name != NULL) { + snprintf(pktp_hdr->pth_comm, sizeof(pktp_hdr->pth_comm), "%s", proc_name); + } + uuid_copy(pktp_hdr->pth_uuid, proc_uuid); + + if (comment != NULL) { + if (pcap_ng_dump_pktap_comment(pcap, dumper, &h, buffer, comment) == 0) + warnx("pcap_ng_dump_pktap() error %s\n", pcap_geterr(pcap)); + } else { + if (pcap_ng_dump_pktap(pcap, dumper, &h, buffer) == 0) + warnx("pcap_ng_dump_pktap() error %s\n", pcap_geterr(pcap)); + } + break; + } + default: + break; + } + } +} + +void +make_section_header_block() +{ + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + pcap_ng_block_reset(block, PCAPNG_BT_SHB); + + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, + "section header block"); + + write_block(block); + + pcap_ng_free_block(block); +} + +void +make_name_resolution_record(int af, void *addr, char **names) +{ + pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max()); + + if (verbose) + printf("%s\n", __func__); + + pcap_ng_block_reset(block, PCAPNG_BT_NRB); + + if (first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + if (af == AF_INET) { + pcap_ng_block_add_name_record_with_ip4(block, (struct in_addr *)addr, (const char **)names); + } else { + pcap_ng_block_add_name_record_with_ip6(block, (struct in6_addr *)addr, (const char **)names); + } + + if (!first_comment && comment) + pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment); + + write_block(block); + + pcap_ng_free_block(block); +} + +int +main(int argc, char * const argv[]) +{ + int ch; + const char *file_name = NULL; + int kevid = 0; + + if (argc == 1) { + help(argv[0]); + return (0); + } + + /* + * Loop through argument to build PCAP-NG block + * Optionally write to file + */ + while ((ch = getopt(argc, argv, "4:6:Cc:D:d:fk:hi:n:p:s:t:w:xv")) != -1) { + switch (ch) { + case 'C': + copy_data_buffer = 1; + break; + + case 'c': + comment = optarg; + break; + + case 'D': { + int i; + + packet_length = strtoul(optarg, NULL, 0); + packet_data = malloc(packet_length); + for (i = 0; i < packet_length; i++) { + packet_data[i] = i % 256; + } + + make_data_block(packet_data, packet_length); + free(packet_data); + break; + } + case 'd': + packet_length = strlen(optarg); + packet_data = (unsigned char *)optarg; + make_data_block(packet_data, packet_length); + break; + + case 'f': + first_comment = 1; + break; + + case 'k': { + struct kern_event_msg *kevmsg = NULL; + u_long len; + + len = strtoul(optarg, NULL, 0); + if (len < sizeof(struct kern_event_msg)) { + fprintf(stderr, "malformed arguments for option 'n'\n"); + help(argv[0]); + return (0); + } + kevmsg = (struct kern_event_msg *)calloc(1, len); + kevmsg->total_size = (u_int32_t)len; + kevmsg->vendor_code = KEV_VENDOR_APPLE; + kevmsg->kev_class = KEV_NETWORK_CLASS; + kevmsg->kev_subclass = KEV_DL_SUBCLASS; + kevmsg->id = kevid++; + kevmsg->event_code = KEV_DL_LINK_QUALITY_METRIC_CHANGED; + + make_kern_event_block(kevmsg); + free(kevmsg); + break; + } + case 'h': + help(argv[0]); + return (0); + + case 'i': + if_name = optarg; + + make_interface_description_block(if_name); + + break; + + case '4': + case '6': { + int af; + int name_count = 0; + char *ptr = strchr(optarg, ':'); + char **names = NULL; + int i; + struct in_addr ina; + struct in6_addr in6a; + int retval; + + + if (ptr == NULL) { + fprintf(stderr, "malformed arguments for option 'n'\n"); + help(argv[0]); + return (0); + } + do { + ptr++; + name_count += 1; + } while ((ptr = strchr(ptr, ':')) != NULL); + + names = calloc(name_count +1, sizeof(char *)); + + ptr = strchr(optarg, ':'); + *ptr = '\0'; + + if (ch == '4') { + af = AF_INET; + retval = inet_pton(af, optarg, &ina); + } else { + af = AF_INET6; + retval = inet_pton(af, optarg, &in6a); + } + if (retval == 0) + errx(1, "This is not an %s address: '%s'\n", + af == AF_INET ? "IPv4" : "IPv6", + optarg); + else if (retval == -1) + err(1, "inet_pton(%s) failed\n", optarg); + + for (i = 0; i < name_count; i++) { + char *end; + ptr++; + end = strchr(ptr, ':'); + if (end != NULL) + *end = '\0'; + + names[i] = strdup(ptr); + if (end != NULL) + ptr = end; + } + + if (af == AF_INET) + make_name_resolution_record(af, &ina, names); + else + make_name_resolution_record(af, &in6a, names); + break; + } + + case 'n': { + num_data_blocks = strtoul(optarg, NULL, 0); + break; + } + + case 'p': { + char *ptr; + char *tofree; + + tofree = strdup(optarg); + if (tofree == NULL) + errx(1, "### strdup() failed"); + ptr = tofree; + + if (proc_name != NULL) { + free(proc_name); + proc_name = NULL; + } + proc_pid = -1; + uuid_clear(proc_uuid); + + do { + char *str; + + if ((str = strsep(&ptr, ":")) == NULL) + errx(1, "-p argument missing"); + + if (*str != 0) + proc_name = strdup(str); + + if ((str = strsep(&ptr, ":")) == NULL) + break; + if (*str != 0) { + char *ep; + + proc_pid = (uint32_t)strtoul(str, &ep, 0); + if (*ep || ep == optarg) { + fprintf(stderr, "malformed pid for option 'p'\n"); + help(argv[0]); + exit (0); + } + } + if ((str = strsep(&ptr, ":")) == NULL) + break; + if (*str != 0) { + if (uuid_parse(str, proc_uuid) != 0) { + fprintf(stderr, "malformed uuid for option 'p'\n"); + help(argv[0]); + return (0); + } + } + } while (0); + free(proc_name); + free(tofree); + + proc_index += 1; + + make_process_information_block(proc_name, proc_pid, proc_uuid); + + break; + } + case 's': { + char *ptr; + char *tofree; + char *str; + size_t len; + + uint32_t secrets_type = 0; + uint32_t secrets_length = 0; + uint8_t *secrets_data = NULL; + + tofree = strdup(optarg); + if (tofree == NULL) + errx(1, "### strdup() failed"); + ptr = tofree; + + if ((str = strsep(&ptr, ":")) == NULL) + errx(1, "-p argument missing"); + + secrets_type = (uint32_t)strtoul(str, NULL, 0); + + if ((str = strsep(&ptr, ":")) == NULL) + errx(1, "-p argument missing"); + + /* replace the final '\0' by '\n' */ + len = strlen(str); + secrets_length = (uint32_t)(len + 1); + secrets_data = calloc(secrets_length, 1); + if (secrets_data == NULL) { + err(EX_OSERR, "calloc()"); + } + memcpy(secrets_data, str, len); + secrets_data[len] = '\n'; + free(secrets_data); + free(tofree); + + make_decryption_secrets_block(secrets_type, secrets_length, secrets_data); + break; + } + case 't': + if (*optarg == 's') + type_of_packet = SIMPLE_PACKET; + else if (*optarg == 'e') + type_of_packet = ENHANCED_PACKET; + else if (*optarg == 'o') + type_of_packet = OBSOLETE_PACKET; + else if (*optarg == 'p') + type_of_packet = PKTAP_PACKET; + break; + + case 'v': + verbose++; + break; + + case 'w': + file_name = optarg; + + if (dumper != NULL) + pcap_ng_dump_close(dumper); + + if (pcap == NULL) { + pcap = pcap_open_dead(DLT_PCAPNG, 65536); + if (pcap == NULL) + err(EX_OSERR, "pcap_open_dead(DLT_PCAPNG, 65536) failed\n"); + } + dumper = pcap_ng_dump_open(pcap, file_name); + if (pcap == NULL) + err(EX_OSERR, "pcap_ng_dump_open(%s) failed\n", file_name); + + + make_section_header_block(); + break; + + case 'x': + if (optind < argc) { + if (argv[optind][0] != '-') { + char *endptr; + unsigned long num = strtoul(argv[optind], &endptr, 0); + if (endptr != NULL && *endptr == '\0') { + optind++; + ext_len = num; + } + } + } + ext_buffer = malloc(ext_len); + if (ext_buffer == NULL) + errx(EX_OSERR, "malloc(%lu) failed", ext_len); + break; + default: + help(argv[0]); + return (0); + } + } + + if (dumper != NULL) + pcap_ng_dump_close(dumper); + + return (0); +} diff --git a/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1 b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1 new file mode 100644 index 0000000..38132a6 --- /dev/null +++ b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 9/4/12 \" DATE
+.Dt ngofflinereadtest 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm ngofflinereadtest,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file diff --git a/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c new file mode 100644 index 0000000..7dbb0e9 --- /dev/null +++ b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2012-2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#include "pcap/pcap-ng.h" +#include <stdio.h> +#include <err.h> +#include <stdlib.h> +#include <string.h> +#include <libgen.h> +#include <sysexits.h> + +struct section_info { + struct section_info *next; + struct pcapng_section_header_fields shb; + pcap_t *pcap; + u_int32_t if_count; + struct interface_info *if_list; +}; + +struct interface_info { + struct interface_info *next; + struct pcapng_interface_description_fields idb; + struct section_info *section_info; + u_int32_t interface_id; + char *if_name; + char *if_desc; +}; + +struct section_info *section_list = NULL; +struct section_info *current_section = NULL; + +int mode_raw = 0; +int mode_block = 0; +int mode_pcap = 0; +int mode_test = 0; + +#define PAD32(x) (((x) + 3) & ~3) + +void hex_and_ascii_print(const char *, const void *, size_t, const char *); + +struct section_info * +new_section_info(pcap_t *pcap, struct pcapng_section_header_fields *shb) +{ + struct section_info *section_info = calloc(1, sizeof(struct section_info)); + + if (section_info == NULL) + return NULL; + + section_info->pcap = pcap; + section_info->shb = *shb; + + if (section_list == NULL) { + section_list = section_info; + } else { + section_info->next = section_list; + section_list = section_info; + } + current_section = section_info; + + return section_info; +} + +void +interface_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context) +{ + struct interface_info *interface_info = (struct interface_info *)context; + + switch (option_info->code) { + case 0: + break; + + case 1: + break; + + case 2: + interface_info->if_name = malloc(option_info->length + 1); + if (interface_info->if_name == NULL) + break; + snprintf(interface_info->if_name, option_info->length + 1, "%s", option_info->value); + break; + case 3: + interface_info->if_desc = malloc(option_info->length + 1); + if (interface_info->if_desc == NULL) + break; + snprintf(interface_info->if_desc, option_info->length + 1, "%s", option_info->value); + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + case 12: + break; + case 13: + break; + case 14: + break; + default: + break; + } +} + +struct interface_info * +new_interface_info(struct section_info *section_info, pcapng_block_t block) +{ + if (section_info == NULL) + return NULL; + + struct interface_info *interface_info = calloc(1, sizeof(struct interface_info)); + + if (interface_info == NULL) + return NULL; + + interface_info->section_info = section_info; + interface_info->interface_id = section_info->if_count; + section_info->if_count++; + if (section_info->if_list == NULL) { + section_info->if_list = interface_info; + } else { + interface_info->next = section_info->if_list; + section_info->if_list = interface_info; + } + (void) pcnapng_block_iterate_options(block, + interface_option_iterator, + interface_info); + + return interface_info; +} + +struct interface_info * +find_interface_info_by_id(u_int16_t interface_id) +{ + struct interface_info *interface_info; + + if (current_section == NULL) + return (NULL); + + if (interface_id + 1 > current_section->if_count) + return (NULL); + + for (interface_info = current_section->if_list; + interface_info != NULL; + interface_info = interface_info->next) { + if (interface_info->interface_id == interface_id) + return (interface_info); + } + return (NULL); +} + +void +block_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context) +{ + printf(" block_type %u context %p option_code %u value_len %u value_ptr %p\n", + pcap_ng_block_get_type(block), context, + option_info->code, option_info->length, + option_info->value + ); + switch (option_info->code) { + case 0: + printf(" opt_endofopt\n"); + break; + + case 1: + printf(" opt_comment: %-*s\n", + option_info->length, option_info->value); + break; + + default: + /* + * Each block type has its own option code space + */ + switch (pcap_ng_block_get_type(block)) { + case PCAPNG_BT_SHB: + switch (option_info->code) { + case 2: + printf(" shb_hardware: %-*s\n", + option_info->length, option_info->value); + break; + case 3: + printf(" shb_os: %-*s\n", + option_info->length, option_info->value); + break; + case 4: + printf(" shb_userappl: %-*s\n", + option_info->length, option_info->value); + break; + default: + printf(" <unkown shb option>\n"); + break; + } + break; + + case PCAPNG_BT_IDB: + switch (option_info->code) { + case 2: + printf(" if_name: %-*s\n", + option_info->length, option_info->value); + break; + case 3: + printf(" if_desc: %-*s\n", + option_info->length, option_info->value); + break; + case 4: + printf(" if_IPv4addr\n"); + break; + case 5: + printf(" if_IPv6addr\n"); + break; + case 6: + printf(" if_MACaddr\n"); + break; + case 7: + printf(" if_EUIaddr\n"); + break; + case 8: + printf(" if_speed\n"); + break; + case 9: + printf(" if_tsresol\n"); + break; + case 10: + printf(" if_tzone\n"); + break; + case 11: + printf(" if_filter %-*s\n", + option_info->length, option_info->value); + break; + case 12: + printf(" if_os %-*s\n", + option_info->length, option_info->value); + break; + case 13: + printf(" if_fcslen\n"); + break; + case 14: + printf(" if_tsoffset\n"); + break; + default: + printf(" <unkown idb option>\n"); + break; + } + break; + + case PCAPNG_BT_EPB: + switch (option_info->code) { + case 2: + printf(" epb_flags\n"); + break; + case 3: + printf(" epb_hash\n"); + break; + case 4: + printf(" epb_dropcount\n"); + break; + case PCAPNG_EPB_PIB_INDEX: + printf(" epb_pib\n"); + break; + case PCAPNG_EPB_SVC: + printf(" epb_svc\n"); + break; + case PCAPNG_EPB_PMD_FLAGS: + printf(" epb_pmd_flags\n"); + break; + default: + printf(" <unkown epb option>\n"); + break; + } + break; + + case PCAPNG_BT_SPB: + printf(" <invalid spb option>\n"); + break; + + case PCAPNG_BT_PB: + switch (option_info->code) { + case 2: + printf(" pack_flags\n"); + break; + case 3: + printf(" pack_hash\n"); + break; + default: + printf(" <unkown pb option>\n"); + break; + } + break; + + case PCAPNG_BT_PIB: { + switch (option_info->code) { + case 2: + printf(" proc_name\n"); + break; + case 3: + printf(" proc_path\n"); + break; + case 4: + printf(" proc_uuid\n"); + break; + default: + printf(" <unkown pib option>\n"); + break; + } + break; + } + case PCAPNG_BT_ISB: { + break; + } + case PCAPNG_BT_NRB: { + break; + } + default: + break; + } + break; + } + if (option_info->value) { + hex_and_ascii_print(" ", option_info->value, option_info->length, "\n"); + } +} + +void +read_callback(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes) +{ + pcap_t *pcap = (pcap_t *)user; + struct pcapng_option_info option_info; + u_char *optptr = NULL; + + /* Access the raw block */ + if (mode_raw) { + struct pcapng_block_header *block_header = (struct pcapng_block_header*)bytes; + + printf("raw hdr caplen %u len %u\n", hdr->caplen, hdr->len); + + printf("#\n# user %p hdr.caplen %u hdr.len %u block_header.blocktype 0x%x block_header.totallength %u\n", + user, hdr->caplen, hdr->len, + block_header->block_type, block_header->total_length); + + hex_and_ascii_print("", bytes, block_header->total_length, "\n"); + + switch (block_header->block_type) { + case PCAPNG_BT_SHB: { + struct pcapng_section_header_fields *shb = (struct pcapng_section_header_fields *)(block_header + 1); + printf("# Section Header Block\n"); + printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n", + shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length); + + hex_and_ascii_print("", shb, sizeof(struct pcapng_section_header_fields), "\n"); + + optptr = (u_char *)(shb + 1); + + break; + } + case PCAPNG_BT_IDB: { + struct pcapng_interface_description_fields *idb = (struct pcapng_interface_description_fields *)(block_header + 1); + printf("# Interface Description Block\n"); + printf(" linktype %u reserved %u snaplen %u\n", + idb->idb_linktype, idb->idb_reserved, idb->idb_snaplen); + + hex_and_ascii_print("", idb, sizeof(struct pcapng_interface_description_fields), "\n"); + optptr = (u_char *)(idb + 1); + + break; + } + case PCAPNG_BT_EPB: { + struct pcapng_enhanced_packet_fields *epb = (struct pcapng_enhanced_packet_fields *)(block_header + 1); + printf("# Enhanced Packet Block\n"); + printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n", + epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len); + + hex_and_ascii_print("", epb, sizeof(struct pcapng_enhanced_packet_fields), "\n"); + hex_and_ascii_print("", epb + 1, epb->caplen, "\n"); + + optptr = (u_char *)(epb + 1); + optptr += PAD32(epb->caplen); + + break; + } + case PCAPNG_BT_SPB: { + struct pcapng_simple_packet_fields *spb = (struct pcapng_simple_packet_fields *)(block_header + 1); + printf("# Simple Packet Block\n"); + printf(" len %u\n", + spb->len); + + hex_and_ascii_print("", spb, sizeof(struct pcapng_simple_packet_fields), "\n"); + hex_and_ascii_print("", spb + 1, spb->len, "\n"); + break; + } + case PCAPNG_BT_PB: { + struct pcapng_packet_fields *pb = (struct pcapng_packet_fields *)(block_header + 1); + printf("# Packet Block\n"); + printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n", + pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len); + + hex_and_ascii_print("", pb, sizeof(struct pcapng_packet_fields), "\n"); + + hex_and_ascii_print("", pb + 1, pb->caplen, "\n"); + + break; + } + case PCAPNG_BT_PIB: { + struct pcapng_process_information_fields *pib = (struct pcapng_process_information_fields *)(block_header + 1); + printf("# Process Information Block\n"); + printf(" process_id %u\n", + pib->process_id); + hex_and_ascii_print("", pib, sizeof(struct pcapng_process_information_fields), "\n"); + break; + } + case PCAPNG_BT_ISB: { + printf("# Interface Statistics Block\n"); + break; + } + case PCAPNG_BT_NRB: { + printf("# Name Record Block\n"); + break; + } + case PCAPNG_BT_OSEV: { + printf("# Name Record Block\n"); + break; + } + case PCAPNG_BT_DSB: { + printf("# Decryption Secrets Block\n"); + break; + } + default: + printf("# Unknown Block\n"); + break; + } + if (optptr) { + size_t optlen = block_header->total_length - (optptr - bytes); + + hex_and_ascii_print("", optptr, optlen, "\n"); + } + + } + /* Create block object */ + if (mode_block) { + pcapng_block_t block = pcap_ng_block_alloc_with_raw_block(pcap, (u_char *)bytes); + + if (block == NULL) { + printf(" pcap_ng_block_alloc_with_raw_block() failed: %s\n", pcap_geterr(pcap)); + return; + } + + switch (pcap_ng_block_get_type(block)) { + case PCAPNG_BT_SHB: { + struct pcapng_section_header_fields *shb = pcap_ng_get_section_header_fields(block); + printf("# Section Header Block\n"); + printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n", + shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length); + + (void)new_section_info(pcap, shb); + break; + } + case PCAPNG_BT_IDB: { + struct pcapng_interface_description_fields *idb = pcap_ng_get_interface_description_fields(block); + printf("# Interface Description Block\n"); + printf(" linktype %u reserved %u snaplen %u\n", + idb->idb_linktype, idb->idb_reserved, idb->idb_snaplen); + if (pcap_ng_block_get_option(block, PCAPNG_IF_NAME, &option_info) == 1) + if (option_info.value) + printf(" interface name: %s\n", option_info.value); + + (void)new_interface_info(current_section, block); + break; + } + case PCAPNG_BT_EPB: { + struct pcapng_enhanced_packet_fields *epb = pcap_ng_get_enhanced_packet_fields(block); + printf("# Enhanced Packet Block\n"); + printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n", + epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len); + break; + } + case PCAPNG_BT_SPB: { + struct pcapng_simple_packet_fields *spb = pcap_ng_get_simple_packet_fields(block); + printf("# Simple Packet Block\n"); + printf(" len %u\n", + spb->len); + break; + } + case PCAPNG_BT_PB: { + struct pcapng_packet_fields *pb = pcap_ng_get_packet_fields(block); + printf("# Packet Block\n"); + printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n", + pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len); + break; + } + case PCAPNG_BT_PIB: { + struct pcapng_process_information_fields *pib = pcap_ng_get_process_information_fields(block); + printf("# Process Information Block\n"); + printf(" process_id %u\n", + pib->process_id); + + if (pcap_ng_block_get_option(block, PCAPNG_PIB_NAME, &option_info) == 1) { + if (option_info.value) + printf(" process name: %s\n", option_info.value); + } + if (pcap_ng_block_get_option(block, PCAPNG_PIB_UUID, &option_info) == 1) { + if (option_info.value) { + uuid_string_t uu_str; + + uuid_unparse_lower(option_info.value, uu_str); + + printf(" process uuid: %s\n", uu_str); + } + } +break; + } + case PCAPNG_BT_ISB: { + printf("# Interface Statistics Block\n"); + break; + } + case PCAPNG_BT_NRB: { + printf("# Name Record Block\n"); + break; + } + case PCAPNG_BT_OSEV: { + struct pcapng_os_event_fields *osev_fields; + + printf("# OS Event Block\n"); + + osev_fields = pcap_ng_get_os_event_fields(block); + + printf(" type %u timestamp_high %u timestamp_low %u len %u\n", + osev_fields->type, + osev_fields->timestamp_high, + osev_fields->timestamp_low, + osev_fields->len); + break; + } + case PCAPNG_BT_DSB: { + struct pcapng_decryption_secrets_fields *dsb_fields; + + printf("# Decryption Secrets Block\n"); + + dsb_fields = pcap_ng_get_decryption_secrets_fields(block); + + printf(" secrets_type 0x%x secrets_length %u\n", + dsb_fields->secrets_type, + dsb_fields->secrets_length); + + break; + } + default: + printf("# Unknown Block\n"); + break; + } + if (pcap_ng_block_does_support_data(block)) { + hex_and_ascii_print("", pcap_ng_block_packet_get_data_ptr(block), pcap_ng_block_packet_get_data_len(block), "\n"); + } + + pcnapng_block_iterate_options(block, block_option_iterator, NULL); + } +} + +#define SWAPLONG(y) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ +( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) ) +#define SWAPLONGLONG(y) \ +(SWAPLONG((unsigned long)(y)) << 32 | SWAPLONG((unsigned long)((y) >> 32))) + +void +test_pcap_ng_fopen_offline(const char *filename, char *errbuf) +{ + FILE *fp; + off_t offset; + pcap_t *pcap; + + fp = fopen(filename, "r"); + if (fp == NULL) { + warn("fopen(%s) failed", filename); + return; + } + offset = ftello(fp); + + pcap = pcap_ng_fopen_offline(fp, errbuf); + if (pcap == NULL) { + warnx("pcap_ng_fopen_offline(%s) failed: %s\n", + filename, errbuf); + if (ftello(fp) != offset) + errx(EX_OSERR, "pcap_ng_fopen_offline(%s) ftello(fp) (%llu) != offset (%llu)", + filename, ftello(fp), offset); + } else { + pcap_close(pcap); + } + + fp = fopen(filename, "r"); + if (fp == NULL) { + warn("fopen(%s) failed", filename); + return; + } + offset = ftello(fp); + + pcap = pcap_fopen_offline(fp, errbuf); + if (pcap == NULL) { + warnx("pcap_fopen_offline(%s) failed: %s\n", + filename, errbuf); + if (ftello(fp) != offset) + errx(EX_OSERR, "pcap_fopen_offline(%s) ftello(fp) (%llu) != offset (%llu)", + filename, ftello(fp), offset); + } else { + pcap_close(pcap); + } + + fclose(fp); + + fprintf(stderr, "TEST PASSED\n"); +} + +int +main(int argc, const char * argv[]) +{ + int i; + char errbuf[PCAP_ERRBUF_SIZE]; + + for (i = 1; i < argc; i++) { + pcap_t *pcap; + + if (strcmp(argv[i], "-h") == 0) { + char *path = strdup((argv[0])); + printf("# usage: %s [-raw] [-block] [-pcap] [-test] file\n", getprogname()); + if (path != NULL) + free(path); + exit(0); + } else if (strcmp(argv[i], "-raw") == 0) { + mode_raw = 1; + continue; + } else if (strcmp(argv[i], "-block") == 0) { + mode_block = 1; + continue; + } else if (strcmp(argv[i], "-pcap") == 0) { + mode_pcap = 1; + continue; + } else if (strcmp(argv[i], "-test") == 0) { + mode_test = 1; + continue; + } + + printf("#\n# opening %s\n#\n", argv[i]); + + if (mode_test != 0) { + test_pcap_ng_fopen_offline(argv[i], errbuf); + continue; + } + + if (mode_block == 0 && mode_raw == 0) { + mode_block = 1; + } + if (mode_pcap == 0) { + pcap = pcap_ng_open_offline(argv[i], errbuf); + if (pcap == NULL) { + warnx("pcap_ng_open_offline(%s) failed: %s\n", + argv[i], errbuf); + continue; + } + } else { + pcap = pcap_open_offline(argv[i], errbuf); + if (pcap == NULL) { + warnx("pcap_open_offline(%s) failed: %s\n", + argv[i], errbuf); + continue; + } + } + int result = pcap_dispatch(pcap, -1, read_callback, (u_char *)pcap); + if (result < 0) { + warnx("pcap_dispatch failed: %s\n", + pcap_statustostr(result)); + } else { + printf("# read %d packets\n", result); + } + pcap_close(pcap); + } + return 0; +} diff --git a/lib/libpcap/libpcap/tests/nonblocktest.c b/lib/libpcap/libpcap/tests/nonblocktest.c new file mode 100644 index 0000000..70a6bfd --- /dev/null +++ b/lib/libpcap/libpcap/tests/nonblocktest.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char copyright[] = + "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ +The Regents of the University of California. All rights reserved.\n"; +#endif + +#include <pcap.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/select.h> +#include <poll.h> + +char *program_name; + +/* Forwards */ +static void countme(u_char *, const struct pcap_pkthdr *, const u_char *); +static void usage(void) __attribute__((noreturn)); +static void error(const char *, ...); +static void warning(const char *, ...); +static char *copy_argv(char **); + +static pcap_t *pd; + +extern int optind; +extern int opterr; +extern char *optarg; + +int +main(int argc, char **argv) +{ + register int op; + bpf_u_int32 localnet, netmask; + register char *cp, *cmdbuf, *device; + struct bpf_program fcode; + char ebuf[PCAP_ERRBUF_SIZE]; + int status; + int packet_count; + + device = NULL; + if ((cp = strrchr(argv[0], '/')) != NULL) + program_name = cp + 1; + else + program_name = argv[0]; + + opterr = 0; + while ((op = getopt(argc, argv, "i:")) != -1) { + switch (op) { + + case 'i': + device = optarg; + break; + + default: + usage(); + /* NOTREACHED */ + } + } + + if (device == NULL) { + device = pcap_lookupdev(ebuf); + if (device == NULL) + error("%s", ebuf); + } + *ebuf = '\0'; + pd = pcap_open_live(device, 65535, 0, 1000, ebuf); + if (pd == NULL) + error("%s", ebuf); + else if (*ebuf) + warning("%s", ebuf); + if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { + localnet = 0; + netmask = 0; + warning("%s", ebuf); + } + cmdbuf = copy_argv(&argv[optind]); + + if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0) + error("%s", pcap_geterr(pd)); + + if (pcap_setfilter(pd, &fcode) < 0) + error("%s", pcap_geterr(pd)); + if (pcap_setnonblock(pd, 1, ebuf) == -1) + error("pcap_setnonblock failed: %s", ebuf); + printf("Listening on %s\n", device); + for (;;) { + packet_count = 0; + status = pcap_dispatch(pd, -1, countme, + (u_char *)&packet_count); + if (status < 0) + break; + if (status != 0) { + printf("%d packets seen, %d packets counted after pcap_dispatch returns\n", + status, packet_count); + } + } + if (status == -2) { + /* + * We got interrupted, so perhaps we didn't + * manage to finish a line we were printing. + * Print an extra newline, just in case. + */ + putchar('\n'); + } + (void)fflush(stdout); + if (status == -1) { + /* + * Error. Report it. + */ + (void)fprintf(stderr, "%s: pcap_loop: %s\n", + program_name, pcap_geterr(pd)); + } + pcap_close(pd); + exit(status == -1 ? 1 : 0); +} + +static void +countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +{ + int *counterp = (int *)user; + + (*counterp)++; +} + +static void +usage(void) +{ + (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n", + program_name); + exit(1); +} + +/* VARARGS */ +static void +error(const char *fmt, ...) +{ + va_list ap; + + (void)fprintf(stderr, "%s: ", program_name); + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + if (*fmt) { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } + exit(1); + /* NOTREACHED */ +} + +/* VARARGS */ +static void +warning(const char *fmt, ...) +{ + va_list ap; + + (void)fprintf(stderr, "%s: WARNING: ", program_name); + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + if (*fmt) { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } +} + +/* + * Copy arg vector into a new buffer, concatenating arguments with spaces. + */ +static char * +copy_argv(register char **argv) +{ + register char **p; + register u_int len = 0; + char *buf; + char *src, *dst; + + p = argv; + if (*p == 0) + return 0; + + while (*p) + len += strlen(*p++) + 1; + + buf = (char *)malloc(len); + if (buf == NULL) + error("copy_argv: malloc"); + + p = argv; + dst = buf; + while ((src = *p++) != NULL) { + while ((*dst++ = *src++) != '\0') + ; + dst[-1] = ' '; + } + dst[-1] = '\0'; + + return buf; +} diff --git a/lib/libpcap/libpcap/tests/offlinereadtest.c b/lib/libpcap/libpcap/tests/offlinereadtest.c new file mode 100644 index 0000000..f5f23fe --- /dev/null +++ b/lib/libpcap/libpcap/tests/offlinereadtest.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + + +#include <pcap.h> +#include <stdio.h> +#include <err.h> +#include <stdlib.h> +#include <string.h> +#include <libgen.h> + + +#define PAD32(x) (((x) + 3) & ~3) +#define SWAPLONG(y) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ +( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) ) +#define SWAPLONGLONG(y) \ +(SWAPLONG((unsigned long)(y)) << 32 | SWAPLONG((unsigned long)((y) >> 32))) + +void hex_and_ascii_print(const char *, const void *, size_t, const char *); + +void +read_callback(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes) +{ + fprintf(stderr, "pcap_pkthdr ts %ld.%06d caplen %u len %u\n", + hdr->ts.tv_sec, + hdr->ts.tv_usec, + hdr->caplen, + hdr->len); + + hex_and_ascii_print("", bytes, hdr->caplen, "\n"); +} + +int +main(int argc, const char * argv[]) +{ + int i; + char errbuf[PCAP_ERRBUF_SIZE]; + + for (i = 1; i < argc; i++) { + pcap_t *pcap; + + if (strcmp(argv[i], "-h") == 0) { + char *path = strdup((argv[0])); + printf("# usage: %s file...\n", getprogname()); + if (path != NULL) + free(path); + exit(0); + } + + printf("#\n# opening %s\n#\n", argv[i]); + + pcap = pcap_open_offline(argv[i], errbuf); + if (pcap == NULL) { + warnx("pcap_open_offline(%s) failed: %s\n", + argv[i], errbuf); + continue; + } + int result = pcap_loop(pcap, -1, read_callback, (u_char *)pcap); + if (result < 0) { + warnx("pcap_dispatch failed: %s\n", + pcap_statustostr(result)); + } else { + printf("# read %d packets\n", result); + } + pcap_close(pcap); + } + return 0; +} diff --git a/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng b/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng Binary files differnew file mode 100644 index 0000000..f773974 --- /dev/null +++ b/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng |