summaryrefslogtreecommitdiffstats
path: root/lib/libpcap/libpcap/pcap-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpcap/libpcap/pcap-util.c')
-rw-r--r--lib/libpcap/libpcap/pcap-util.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/lib/libpcap/libpcap/pcap-util.c b/lib/libpcap/libpcap/pcap-util.c
new file mode 100644
index 0000000..f028414
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-util.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2012-2013 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@
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "pcap-int.h"
+#include "pcap-util.h"
+
+static int null_uu_inited = 0;
+static uuid_t null_uu;
+
+void
+pcap_if_info_set_clear(struct pcap_if_info_set *if_info_set)
+{
+ int i;
+
+ if (if_info_set->if_infos != NULL) {
+ for (i = 0; i < if_info_set->if_info_count; i++)
+ pcap_if_info_set_free(if_info_set, if_info_set->if_infos[i]);
+
+ free(if_info_set->if_infos);
+ if_info_set->if_infos = NULL;
+ }
+ if_info_set->if_info_count = 0;
+ if_info_set->if_dump_id = 0;
+}
+
+struct pcap_if_info *
+pcap_if_info_set_find_by_name(struct pcap_if_info_set *if_info_set, const char *name)
+{
+ int i;
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (strcmp(name, if_info_set->if_infos[i]->if_name) == 0)
+ return (if_info_set->if_infos[i]);
+ }
+ return (NULL);
+}
+
+struct pcap_if_info *
+pcap_if_info_set_find_by_id(struct pcap_if_info_set *if_info_set, int if_id)
+{
+ int i;
+
+ if (if_id == -1)
+ return (NULL);
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (if_id == if_info_set->if_infos[i]->if_id)
+ return (if_info_set->if_infos[i]);
+ }
+ return (NULL);
+}
+
+void
+pcap_if_info_set_free(struct pcap_if_info_set *if_info_set, struct pcap_if_info *if_info)
+{
+ if (if_info != NULL) {
+ int i;
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (if_info_set->if_infos[i] == if_info) {
+ if_info_set->if_infos[i] = NULL;
+ break;
+ }
+ }
+
+ pcap_freecode(&if_info->if_filter_program);
+ free(if_info);
+ }
+}
+
+struct pcap_if_info *
+pcap_if_info_set_add(struct pcap_if_info_set *if_info_set, const char *name,
+ int if_id, int linktype, int snaplen,
+ const char *filter_str, char *errbuf)
+{
+ struct pcap_if_info *if_info = NULL;
+ size_t ifname_len = strlen(name);
+ struct pcap_if_info **newarray;
+
+ /*
+ * Stash the interface name after the structure
+ */
+ if_info = calloc(1, sizeof(struct pcap_if_info) + ifname_len + 1);
+ if (if_info == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: calloc() failed", __func__);
+ }
+ return (NULL);
+ }
+ if_info->if_name = (char *)(if_info + 1);
+ if (ifname_len > 0)
+ bcopy(name, if_info->if_name, ifname_len);
+ if_info->if_name[ifname_len] = 0;
+ if (if_id == -1)
+ if_info->if_id = if_info_set->if_info_count;
+ else
+ if_info->if_id = if_id;
+ if_info->if_linktype = linktype;
+ if_info->if_snaplen = snaplen;
+
+ /*
+ * The compilation of a BPF filter expression depends on
+ * the DLT so we store the program in the if_info
+ */
+ if (filter_str != NULL && *filter_str != 0) {
+ if (pcap_compile_nopcap(if_info->if_snaplen,
+ if_info->if_linktype,
+ &if_info->if_filter_program,
+ filter_str, 0, PCAP_NETMASK_UNKNOWN) == -1) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_compile_nopcap() failed", __func__);
+ }
+ free(if_info);
+ return (NULL);
+ }
+ }
+
+ /*
+ * Resize pointer array
+ */
+ newarray = realloc(if_info_set->if_infos,
+ (if_info_set->if_info_count + 1) * sizeof(struct pcap_if_info *));
+ if (newarray == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: realloc() failed", __func__);
+ }
+ pcap_if_info_set_free(if_info_set, if_info);
+ return (NULL);
+ }
+ if_info_set->if_infos = newarray;
+ if_info_set->if_infos[if_info_set->if_info_count] = if_info;
+ if_info_set->if_info_count += 1;
+
+ return (if_info);
+}
+
+void
+pcap_clear_if_infos(pcap_t * pcap)
+{
+ pcap_if_info_set_clear(&pcap->if_info_set);
+}
+
+struct pcap_if_info *
+pcap_find_if_info_by_name(pcap_t * pcap, const char *name)
+{
+ return (pcap_if_info_set_find_by_name(&pcap->if_info_set, name));
+}
+
+struct pcap_if_info *
+pcap_find_if_info_by_id(pcap_t * pcap, int if_id)
+{
+ return (pcap_if_info_set_find_by_id(&pcap->if_info_set, if_id));
+}
+
+void
+pcap_free_if_info(pcap_t * pcap, struct pcap_if_info *if_info)
+{
+ pcap_if_info_set_free(&pcap->if_info_set, if_info);
+}
+
+struct pcap_if_info *
+pcap_add_if_info(pcap_t * pcap, const char *name,
+ int if_id, int linktype, int snaplen)
+{
+ struct pcap_if_info *if_info = NULL;
+
+ pcap->cleanup_extra_op = pcap_ng_init_section_info;
+
+ if_info = pcap_if_info_set_add(&pcap->if_info_set,
+ name, if_id, linktype, snaplen,
+ pcap->filter_str, pcap->errbuf);
+
+ return (if_info);
+}
+
+void
+pcap_proc_info_set_clear(struct pcap_proc_info_set *proc_info_set)
+{
+ int i;
+
+ if (proc_info_set->proc_infos != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++)
+ pcap_proc_info_set_free(proc_info_set, proc_info_set->proc_infos[i]);
+
+ free(proc_info_set->proc_infos);
+ proc_info_set->proc_infos = NULL;
+ }
+ proc_info_set->proc_info_count = 0;
+ proc_info_set->proc_dump_index = 0;
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name)
+{
+ return (pcap_proc_info_set_find_uuid(proc_info_set, pid, name, NULL));
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu)
+{
+ int i;
+
+ if (name != NULL && uu != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ strcmp(name, proc_info->proc_name) == 0 &&
+ uuid_compare(uu, proc_info->proc_uuid) == 0)
+ return (proc_info);
+ }
+ } else if (name != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ strcmp(name, proc_info->proc_name) == 0)
+ return (proc_info);
+ }
+ } else if (uu != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ uuid_compare(uu, proc_info->proc_uuid) == 0)
+ return (proc_info);
+ }
+ }
+ return (NULL);
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find_by_index(struct pcap_proc_info_set *proc_info_set,
+ uint32_t index)
+{
+ int i;
+
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (index == proc_info->proc_index)
+ return (proc_info);
+ }
+ return (NULL);
+}
+
+void
+pcap_proc_info_set_free(struct pcap_proc_info_set *proc_info_set,
+ struct pcap_proc_info *proc_info)
+{
+
+ if (proc_info != NULL) {
+ int i;
+
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ if (proc_info_set->proc_infos[i] == proc_info) {
+ proc_info_set->proc_infos[i] = NULL;
+ break;
+ }
+ }
+ free(proc_info);
+ }
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_add_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu, char *errbuf)
+{
+ struct pcap_proc_info *proc_info = NULL;
+ size_t name_len = name != NULL ? strlen(name) : 0;
+ struct pcap_proc_info **newarray;
+ uuid_string_t uu_str;
+
+ if (uu == NULL && null_uu_inited == 0) {
+ uuid_clear(null_uu);
+ null_uu_inited = 1;
+ }
+
+ /*
+ * Stash the process name after the structure
+ */
+ proc_info = calloc(1, sizeof(struct pcap_proc_info) + name_len + 1);
+ if (proc_info == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: calloc() failed", __func__);
+ }
+ return (NULL);
+ }
+ proc_info->proc_name = (char *)(proc_info + 1);
+ if (name_len > 0)
+ bcopy(name, proc_info->proc_name, name_len);
+ proc_info->proc_name[name_len] = 0;
+ proc_info->proc_pid = pid;
+ proc_info->proc_index = proc_info_set->proc_info_count;
+ uuid_copy(proc_info->proc_uuid, uu != NULL ? uu : null_uu);
+
+ uuid_unparse_lower(proc_info->proc_uuid, uu_str);
+
+ /*
+ * Resize pointer array
+ */
+ newarray = realloc(proc_info_set->proc_infos,
+ (proc_info_set->proc_info_count + 1) * sizeof(struct pcap_proc_info *));
+ if (newarray == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: malloc() failed", __func__);
+ }
+ free(proc_info);
+ return (NULL);
+ }
+ proc_info_set->proc_infos = newarray;
+ proc_info_set->proc_infos[proc_info_set->proc_info_count] = proc_info;
+ proc_info_set->proc_info_count += 1;
+
+ return (proc_info);
+}
+
+void
+pcap_clear_proc_infos(pcap_t * pcap)
+{
+ pcap_proc_info_set_clear(&pcap->proc_info_set);
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info(pcap_t * pcap, uint32_t pid, const char *name)
+{
+ return (pcap_proc_info_set_find(&pcap->proc_info_set, pid, name));
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info_uuid(pcap_t * pcap, uint32_t pid, const char *name, const uuid_t uu)
+{
+ return (pcap_proc_info_set_find_uuid(&pcap->proc_info_set, pid, name, uu));
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info_by_index(pcap_t * pcap, uint32_t index)
+{
+ return (pcap_proc_info_set_find_by_index(&pcap->proc_info_set, index));
+}
+
+void
+pcap_free_proc_info(pcap_t * pcap, struct pcap_proc_info *proc_info)
+{
+ pcap_proc_info_set_free(&pcap->proc_info_set, proc_info);
+}
+
+struct pcap_proc_info *
+pcap_add_proc_info_uuid(pcap_t * pcap, uint32_t pid, const char *name, const uuid_t uu)
+{
+ struct pcap_proc_info *proc_info = NULL;
+
+ pcap->cleanup_extra_op = pcap_ng_init_section_info;
+
+ proc_info = pcap_proc_info_set_add_uuid(&pcap->proc_info_set,
+ pid, name,
+ uu,
+ pcap->errbuf);
+
+ return (proc_info);
+}
+
+
+struct pcap_proc_info *
+pcap_add_proc_info(pcap_t * pcap, uint32_t pid, const char *name)
+{
+ return (pcap_add_proc_info_uuid(pcap, pid, name, NULL));
+}
+
+int
+pcap_set_filter_info(pcap_t *pcap, const char *str, int optimize, bpf_u_int32 netmask)
+{
+ if (pcap->filter_str != NULL)
+ free(pcap->filter_str);
+
+ if (str == NULL) {
+ pcap->filter_str = NULL;
+ } else {
+ pcap->filter_str = strdup(str);
+ if (pcap->filter_str == NULL)
+ return (PCAP_ERROR);
+ }
+
+ return (0);
+}
+
+void
+pcap_ng_init_section_info(pcap_t *p)
+{
+ p->shb_added = 0;
+ pcap_clear_if_infos(p);
+ pcap_clear_proc_infos(p);
+}
+