diff options
Diffstat (limited to 'pcap-linux.c')
| -rw-r--r-- | pcap-linux.c | 654 |
1 files changed, 401 insertions, 253 deletions
diff --git a/pcap-linux.c b/pcap-linux.c index 13bd8529f65c..e0fe1d3e0237 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -70,9 +70,7 @@ #define _GNU_SOURCE -#ifdef HAVE_CONFIG_H #include <config.h> -#endif #include <errno.h> #include <stdio.h> @@ -81,6 +79,7 @@ #include <fcntl.h> #include <string.h> #include <limits.h> +#include <endian.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/ioctl.h> @@ -98,6 +97,7 @@ #include <sys/eventfd.h> #include "pcap-int.h" +#include "pcap-util.h" #include "pcap/sll.h" #include "pcap/vlan.h" #include "pcap/can_socketcan.h" @@ -111,7 +111,7 @@ #error "Libpcap will only work if TPACKET_V2 is supported; you must build for a 2.6.27 or later kernel" #endif -/* check for memory mapped access avaibility. We assume every needed +/* check for memory mapped access availability. We assume every needed * struct is defined if the macro TPACKET_HDRLEN is defined, because it * uses many ring related structs and macros */ #ifdef TPACKET3_HDRLEN @@ -221,10 +221,10 @@ struct pcap_linux { */ static int get_if_flags(const char *, bpf_u_int32 *, char *); static int is_wifi(const char *); -static void map_arphrd_to_dlt(pcap_t *, int, const char *, int); +static int map_arphrd_to_dlt(pcap_t *, int, const char *, int); static int pcap_activate_linux(pcap_t *); static int setup_socket(pcap_t *, int); -static int setup_mmapped(pcap_t *, int *); +static int setup_mmapped(pcap_t *); static int pcap_can_set_rfmon_linux(pcap_t *); static int pcap_inject_linux(pcap_t *, const void *, int); static int pcap_stats_linux(pcap_t *, struct pcap_stat *); @@ -245,7 +245,7 @@ union thdr { #define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset) static void destroy_ring(pcap_t *handle); -static int create_ring(pcap_t *handle, int *status); +static int create_ring(pcap_t *handle); static int prepare_tpacket_socket(pcap_t *handle); static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *); #ifdef HAVE_TPACKET3 @@ -253,7 +253,7 @@ static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *); #endif static int pcap_setnonblock_linux(pcap_t *p, int nonblock); static int pcap_getnonblock_linux(pcap_t *p); -static void pcap_oneshot_linux(u_char *user, const struct pcap_pkthdr *h, +static void pcapint_oneshot_linux(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); /* @@ -287,7 +287,7 @@ static void pcap_oneshot_linux(u_char *user, const struct pcap_pkthdr *h, #else /* * This is being compiled on a system that lacks TP_STATUS_VLAN_VALID, - * so we testwith the value it has in the 3.0 and later kernels, so + * so we test with the value it has in the 3.0 and later kernels, so * we can test it if we're running on a system that has it. (If we're * running on a system that doesn't have it, it won't be set in the * tp_status field, so the tests of it will always fail; that means @@ -336,7 +336,7 @@ static struct sock_fprog total_fcode static int iface_dsa_get_proto_info(const char *device, pcap_t *handle); pcap_t * -pcap_create_interface(const char *device, char *ebuf) +pcapint_create_interface(const char *device, char *ebuf) { pcap_t *handle; @@ -365,7 +365,7 @@ pcap_create_interface(const char *device, char *ebuf) */ handle->tstamp_precision_list = malloc(2 * sizeof(u_int)); if (handle->tstamp_precision_list == NULL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc"); pcap_close(handle); return NULL; @@ -374,8 +374,12 @@ pcap_create_interface(const char *device, char *ebuf) handle->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO; handle->tstamp_precision_count = 2; + /* + * Start out with the breakloop handle not open; we don't + * need it until we're activated and ready to capture. + */ struct pcap_linux *handlep = handle->priv; - handlep->poll_breakloop_fd = eventfd(0, EFD_NONBLOCK); + handlep->poll_breakloop_fd = -1; return handle; } @@ -461,7 +465,7 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path, free(pathstr); return 0; } - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "%s: Can't readlink %s", device, pathstr); free(pathstr); return PCAP_ERROR; @@ -618,7 +622,7 @@ DIAG_ON_NARROWING */ handlep->mondevice = strdup(mondevice); if (handlep->mondevice == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "strdup"); /* * Get rid of the monitor device. @@ -742,7 +746,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle) * * Compared to /proc/net/dev this avoids counting software drops, * but may be unimplemented and just return 0. - * The author has found no straigthforward way to check for support. + * The author has found no straightforward way to check for support. */ static long long int linux_get_stat(const char * if_name, const char * stat) { @@ -817,7 +821,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) * Take this pcap out of the list of pcaps for which we * have to take the interface out of some mode. */ - pcap_remove_from_pcaps_to_close(handle); + pcapint_remove_from_pcaps_to_close(handle); } if (handle->fd != -1) { @@ -846,7 +850,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) close(handlep->poll_breakloop_fd); handlep->poll_breakloop_fd = -1; } - pcap_cleanup_live_common(handle); + pcapint_cleanup_live_common(handle); } #ifdef HAVE_TPACKET3 @@ -939,13 +943,20 @@ set_poll_timeout(struct pcap_linux *handlep) static void pcap_breakloop_linux(pcap_t *handle) { - pcap_breakloop_common(handle); + pcapint_breakloop_common(handle); struct pcap_linux *handlep = handle->priv; uint64_t value = 1; - /* XXX - what if this fails? */ - if (handlep->poll_breakloop_fd != -1) + + if (handlep->poll_breakloop_fd != -1) { + /* + * XXX - pcap_breakloop() doesn't have a return value, + * so we can't indicate an error. + */ +DIAG_OFF_WARN_UNUSED_RESULT (void)write(handlep->poll_breakloop_fd, &value, sizeof(value)); +DIAG_ON_WARN_UNUSED_RESULT + } } /* @@ -996,13 +1007,17 @@ pcap_activate_linux(pcap_t *handle) const char *device; int is_any_device; struct ifreq ifr; - int status = 0; - int status2 = 0; + int status; int ret; device = handle->opt.device; /* + * Start out assuming no warnings. + */ + status = 0; + + /* * Make sure the name we were handed will fit into the ioctls we * might perform on the device; if not, return a "No such device" * indication, as the Linux kernel shouldn't support creating @@ -1036,7 +1051,7 @@ pcap_activate_linux(pcap_t *handle) handlep->device = strdup(device); if (handlep->device == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "strdup"); status = PCAP_ERROR; goto fail; @@ -1084,22 +1099,57 @@ pcap_activate_linux(pcap_t *handle) status = ret; goto fail; } + if (ret > 0) { + /* + * We got a warning; return that, as handle->errbuf + * might have been overwritten by this warning. + */ + status = ret; + } + /* - * Success. + * Success (possibly with a warning). + * + * First, try to allocate an event FD for breakloop, if + * we're not going to start in non-blocking mode. + */ + if (!handle->opt.nonblock) { + handlep->poll_breakloop_fd = eventfd(0, EFD_NONBLOCK); + if (handlep->poll_breakloop_fd == -1) { + /* + * Failed. + */ + pcapint_fmt_errmsg_for_errno(handle->errbuf, + PCAP_ERRBUF_SIZE, errno, "could not open eventfd"); + status = PCAP_ERROR; + goto fail; + } + } + + /* + * Succeeded. * Try to set up memory-mapped access. */ - ret = setup_mmapped(handle, &status); - if (ret == -1) { + ret = setup_mmapped(handle); + if (ret < 0) { /* * We failed to set up to use it, or the * kernel supports it, but we failed to - * enable it. status has been set to the + * enable it. The return value is the * error status to return and, if it's * PCAP_ERROR, handle->errbuf contains * the error message. */ + status = ret; goto fail; } + if (ret > 0) { + /* + * We got a warning; return that, as handle->errbuf + * might have been overwritten by this warning. + */ + status = ret; + } /* * We succeeded. status has been set to the status to return, @@ -1109,9 +1159,9 @@ pcap_activate_linux(pcap_t *handle) * Now that we have activated the mmap ring, we can * set the correct protocol. */ - if ((status2 = iface_bind(handle->fd, handlep->ifindex, + if ((ret = iface_bind(handle->fd, handlep->ifindex, handle->errbuf, pcap_protocol(handle))) != 0) { - status = status2; + status = ret; goto fail; } @@ -1136,7 +1186,7 @@ pcap_activate_linux(pcap_t *handle) break; #endif } - handle->oneshot_callback = pcap_oneshot_linux; + handle->oneshot_callback = pcapint_oneshot_linux; handle->selectable_fd = handle->fd; return status; @@ -1245,7 +1295,7 @@ device_still_exists(pcap_t *handle) /* * Error - report an error and return -1. */ - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "getsockname failed"); return (-1); } @@ -1272,7 +1322,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, int size) /* * We don't support sending on the "any" device. */ - pcap_strlcpy(handle->errbuf, + pcapint_strlcpy(handle->errbuf, "Sending packets isn't supported on the \"any\" device", PCAP_ERRBUF_SIZE); return (-1); @@ -1286,7 +1336,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, int size) * socket? * Is a "sendto()" required there? */ - pcap_strlcpy(handle->errbuf, + pcapint_strlcpy(handle->errbuf, "Sending packets isn't supported in cooked mode", PCAP_ERRBUF_SIZE); return (-1); @@ -1294,7 +1344,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, int size) ret = (int)send(handle->fd, buf, size, 0); if (ret == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "send"); return (-1); } @@ -1425,17 +1475,12 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) return 0; } - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "failed to get statistics from socket"); return -1; } /* - * Description string for the "any" device. - */ -static const char any_descr[] = "Pseudo-device that captures on all interfaces"; - -/* * A PF_PACKET socket can be bound to any network interface. */ static int @@ -1587,7 +1632,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) sock = get_if_ioctl_socket(); if (sock == -1) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "Can't create socket to get ethtool information for %s", name); return -1; @@ -1667,7 +1712,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) #ifdef ETHTOOL_GLINK memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); info.cmd = ETHTOOL_GLINK; /* * XXX - while Valgrind handles SIOCETHTOOL and knows that @@ -1715,7 +1760,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) /* * Other error. */ - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, save_errno, "%s: SIOCETHTOOL(ETHTOOL_GLINK) ioctl failed", name); @@ -1745,24 +1790,19 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) } int -pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) +pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) { /* * Get the list of regular interfaces first. */ - if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound, + if (pcapint_findalldevs_interfaces(devlistp, errbuf, can_be_bound, get_if_flags) == -1) return (-1); /* failure */ /* * Add the "any" device. - * As it refers to all network devices, not to any particular - * network device, the notion of "connected" vs. "disconnected" - * doesn't apply. */ - if (add_dev(devlistp, "any", - PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, - any_descr, errbuf) == NULL) + if (pcap_add_any_dev(devlistp, errbuf) == NULL) return (-1); return (0); @@ -1825,9 +1865,11 @@ is_wifi(const char *device) * to pick some type that works in raw mode, or fail. * * Sets the link type to -1 if unable to map the type. + * + * Returns 0 on success or a PCAP_ERROR_ value on error. */ -static void map_arphrd_to_dlt(pcap_t *handle, int arptype, - const char *device, int cooked_ok) +static int map_arphrd_to_dlt(pcap_t *handle, int arptype, + const char *device, int cooked_ok) { static const char cdma_rmnet[] = "cdma_rmnet"; @@ -1848,7 +1890,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, */ if (strncmp(device, cdma_rmnet, sizeof cdma_rmnet - 1) == 0) { handle->linktype = DLT_RAW; - return; + return 0; } /* @@ -1878,7 +1920,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, */ ret = iface_dsa_get_proto_info(device, handle); if (ret < 0) - return; + return ret; if (ret == 1) { /* @@ -1895,14 +1937,14 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, * It's not a Wi-Fi device; offer DOCSIS. */ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - /* - * If that fails, just leave the list empty. - */ - if (handle->dlt_list != NULL) { - handle->dlt_list[0] = DLT_EN10MB; - handle->dlt_list[1] = DLT_DOCSIS; - handle->dlt_count = 2; + if (handle->dlt_list == NULL) { + pcapint_fmt_errmsg_for_errno(handle->errbuf, + PCAP_ERRBUF_SIZE, errno, "malloc"); + return (PCAP_ERROR); } + handle->dlt_list[0] = DLT_EN10MB; + handle->dlt_list[1] = DLT_DOCSIS; + handle->dlt_count = 2; } /* FALLTHROUGH */ @@ -2191,17 +2233,17 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, * IP-over-FC on which somebody wants to capture * packets. */ + handle->linktype = DLT_FC_2; handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 3); - /* - * If that fails, just leave the list empty. - */ - if (handle->dlt_list != NULL) { - handle->dlt_list[0] = DLT_FC_2; - handle->dlt_list[1] = DLT_FC_2_WITH_FRAME_DELIMS; - handle->dlt_list[2] = DLT_IP_OVER_FC; - handle->dlt_count = 3; + if (handle->dlt_list == NULL) { + pcapint_fmt_errmsg_for_errno(handle->errbuf, + PCAP_ERRBUF_SIZE, errno, "malloc"); + return (PCAP_ERROR); } - handle->linktype = DLT_FC_2; + handle->dlt_list[0] = DLT_FC_2; + handle->dlt_list[1] = DLT_FC_2_WITH_FRAME_DELIMS; + handle->dlt_list[2] = DLT_IP_OVER_FC; + handle->dlt_count = 3; break; #ifndef ARPHRD_IRDA @@ -2271,29 +2313,13 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, handle->linktype = -1; break; } -} - -static void -set_dlt_list_cooked(pcap_t *handle) -{ - /* - * Support both DLT_LINUX_SLL and DLT_LINUX_SLL2. - */ - handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - - /* - * If that failed, just leave the list empty. - */ - if (handle->dlt_list != NULL) { - handle->dlt_list[0] = DLT_LINUX_SLL; - handle->dlt_list[1] = DLT_LINUX_SLL2; - handle->dlt_count = 2; - } + return (0); } /* * Try to set up a PF_PACKET socket. - * Returns 0 on success and a PCAP_ERROR_ value on failure. + * Returns 0 or a PCAP_WARNING_ value on success and a PCAP_ERROR_ value + * on failure. */ static int setup_socket(pcap_t *handle, int is_any_device) @@ -2333,13 +2359,23 @@ setup_socket(pcap_t *handle, int is_any_device) status = PCAP_ERROR_PERM_DENIED; snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Attempt to create packet socket failed - CAP_NET_RAW may be required"); + } else if (errno == EAFNOSUPPORT) { + /* + * PF_PACKET sockets not supported. + * Perhaps we're running on the WSL1 module + * in the Windows NT kernel rather than on + * a real Linux kernel. + */ + status = PCAP_ERROR_CAPTURE_NOTSUP; + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "PF_PACKET sockets not supported - is this WSL1?"); } else { /* * Other error. */ status = PCAP_ERROR; } - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "socket"); return status; } @@ -2391,6 +2427,7 @@ setup_socket(pcap_t *handle, int is_any_device) * on. */ close(sock_fd); + return PCAP_ERROR_RFMON_NOTSUP; } @@ -2408,7 +2445,11 @@ setup_socket(pcap_t *handle, int is_any_device) close(sock_fd); return arptype; } - map_arphrd_to_dlt(handle, arptype, device, 1); + status = map_arphrd_to_dlt(handle, arptype, device, 1); + if (status < 0) { + close(sock_fd); + return status; + } if (handle->linktype == -1 || handle->linktype == DLT_LINUX_SLL || handle->linktype == DLT_LINUX_IRDA || @@ -2431,7 +2472,7 @@ setup_socket(pcap_t *handle, int is_any_device) * warning message. */ if (close(sock_fd) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "close"); return PCAP_ERROR; } @@ -2445,7 +2486,7 @@ setup_socket(pcap_t *handle, int is_any_device) * any failure is a "this shouldn't * happen" case. */ - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "socket"); return PCAP_ERROR; } @@ -2460,7 +2501,6 @@ setup_socket(pcap_t *handle, int is_any_device) free(handle->dlt_list); handle->dlt_list = NULL; handle->dlt_count = 0; - set_dlt_list_cooked(handle); } if (handle->linktype == -1) { @@ -2476,6 +2516,7 @@ setup_socket(pcap_t *handle, int is_any_device) "falling back to cooked " "socket", arptype); + status = PCAP_WARNING; } /* @@ -2487,12 +2528,6 @@ setup_socket(pcap_t *handle, int is_any_device) handle->linktype != DLT_LINUX_LAPD && handle->linktype != DLT_NETLINK) handle->linktype = DLT_LINUX_SLL; - if (handle->linktype == -1) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "unknown arptype %d, defaulting to cooked mode", - arptype); - status = PCAP_WARNING; - } } handlep->ifindex = iface_get_id(sock_fd, device, @@ -2521,12 +2556,19 @@ setup_socket(pcap_t *handle, int is_any_device) /* * It uses cooked mode. + * Support both DLT_LINUX_SLL and DLT_LINUX_SLL2. */ handlep->cooked = 1; handle->linktype = DLT_LINUX_SLL; - handle->dlt_list = NULL; - handle->dlt_count = 0; - set_dlt_list_cooked(handle); + handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); + if (handle->dlt_list == NULL) { + pcapint_fmt_errmsg_for_errno(handle->errbuf, + PCAP_ERRBUF_SIZE, errno, "malloc"); + return (PCAP_ERROR); + } + handle->dlt_list[0] = DLT_LINUX_SLL; + handle->dlt_list[1] = DLT_LINUX_SLL2; + handle->dlt_count = 2; /* * We're not bound to a device. @@ -2566,7 +2608,7 @@ setup_socket(pcap_t *handle, int is_any_device) mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)"); close(sock_fd); return PCAP_ERROR; @@ -2585,7 +2627,7 @@ setup_socket(pcap_t *handle, int is_any_device) val = 1; if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val)) == -1 && errno != ENOPROTOOPT) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_AUXDATA)"); close(sock_fd); return PCAP_ERROR; @@ -2651,17 +2693,17 @@ setup_socket(pcap_t *handle, int is_any_device) /* * Attempt to setup memory-mapped access. * - * On success, returns 1, and sets *status to 0 if there are no warnings - * or to a PCAP_WARNING_ code if there is a warning. + * On success, returns 0 if there are no warnings or a PCAP_WARNING_ code + * if there is a warning. * - * On error, returns -1, and sets *status to the appropriate error code; - * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. + * On error, returns the appropriate error code; if that is PCAP_ERROR, + * sets handle->errbuf to the appropriate message. */ static int -setup_mmapped(pcap_t *handle, int *status) +setup_mmapped(pcap_t *handle) { struct pcap_linux *handlep = handle->priv; - int ret; + int status; /* * Attempt to allocate a buffer to hold the contents of one @@ -2669,36 +2711,34 @@ setup_mmapped(pcap_t *handle, int *status) */ handlep->oneshot_buffer = malloc(handle->snapshot); if (handlep->oneshot_buffer == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't allocate oneshot buffer"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } if (handle->opt.buffer_size == 0) { /* by default request 2M for the ring buffer */ handle->opt.buffer_size = 2*1024*1024; } - ret = prepare_tpacket_socket(handle); - if (ret == -1) { + status = prepare_tpacket_socket(handle); + if (status == -1) { free(handlep->oneshot_buffer); handlep->oneshot_buffer = NULL; - *status = PCAP_ERROR; - return ret; + return PCAP_ERROR; } - ret = create_ring(handle, status); - if (ret == -1) { + status = create_ring(handle); + if (status < 0) { /* * Error attempting to enable memory-mapped capture; - * fail. create_ring() has set *status. + * fail. The return value is the status to return. */ free(handlep->oneshot_buffer); handlep->oneshot_buffer = NULL; - return -1; + return status; } /* - * Success. *status has been set either to 0 if there are no + * Success. status has been set either to 0 if there are no * warnings or to a PCAP_WARNING_ value if there is a warning. * * handle->offset is used to get the current position into the rx ring. @@ -2710,7 +2750,7 @@ setup_mmapped(pcap_t *handle, int *status) */ set_poll_timeout(handlep); - return 1; + return status; } /* @@ -2761,7 +2801,7 @@ init_tpacket(pcap_t *handle, int version, const char *version_str) /* * Some unexpected error. */ - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't get %s header len on packet socket", version_str); } @@ -2772,7 +2812,7 @@ init_tpacket(pcap_t *handle, int version, const char *version_str) val = version; if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't activate %s on packet socket", version_str); return -1; } @@ -2859,14 +2899,14 @@ prepare_tpacket_socket(pcap_t *handle) /* * Attempt to set up memory-mapped access. * - * On success, returns 1, and sets *status to 0 if there are no warnings - * or to a PCAP_WARNING_ code if there is a warning. + * On success, returns 0 if there are no warnings or to a PCAP_WARNING_ code + * if there is a warning. * - * On error, returns -1, and sets *status to the appropriate error code; - * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. + * On error, returns the appropriate error code; if that is PCAP_ERROR, + * sets handle->errbuf to the appropriate message. */ static int -create_ring(pcap_t *handle, int *status) +create_ring(pcap_t *handle) { struct pcap_linux *handlep = handle->priv; unsigned i, j, frames_per_block; @@ -2883,11 +2923,12 @@ create_ring(pcap_t *handle, int *status) socklen_t len; unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff; unsigned int frame_size; + int status; /* - * Start out assuming no warnings or errors. + * Start out assuming no warnings. */ - *status = 0; + status = 0; /* * Reserve space for VLAN tag reconstruction. @@ -2919,11 +2960,10 @@ create_ring(pcap_t *handle, int *status) len = sizeof(tp_reserve); if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, len) < 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_RESERVE)"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } switch (handlep->tp_version) { @@ -2968,15 +3008,11 @@ create_ring(pcap_t *handle, int *status) mtu = iface_get_mtu(handle->fd, handle->opt.device, handle->errbuf); - if (mtu == -1) { - *status = PCAP_ERROR; - return -1; - } + if (mtu == -1) + return PCAP_ERROR; offload = iface_get_offload(handle); - if (offload == -1) { - *status = PCAP_ERROR; - return -1; - } + if (offload == -1) + return PCAP_ERROR; if (offload) max_frame_len = MAX(mtu, 65535); else @@ -2993,10 +3029,9 @@ create_ring(pcap_t *handle, int *status) len = sizeof(sk_type); if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_TYPE)"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE; /* XXX: in the kernel maclen is calculated from @@ -3061,8 +3096,7 @@ create_ring(pcap_t *handle, int *status) snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Internal error: unknown TPACKET_ value %u", handlep->tp_version); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } /* compute the minimum block size that will handle this frame. @@ -3111,7 +3145,7 @@ create_ring(pcap_t *handle, int *status) hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); ifr.ifr_data = (void *)&hwconfig; /* @@ -3128,10 +3162,9 @@ create_ring(pcap_t *handle, int *status) * and, if they can't, shouldn't * try requesting hardware time stamps. */ - *status = PCAP_ERROR_PERM_DENIED; snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Attempt to set hardware timestamp failed - CAP_NET_ADMIN may be required"); - return -1; + return PCAP_ERROR_PERM_DENIED; case EOPNOTSUPP: case ERANGE: @@ -3149,15 +3182,14 @@ create_ring(pcap_t *handle, int *status) * We'll just fall back on the standard * host time stamps. */ - *status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP; + status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP; break; default: - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "SIOCSHWTSTAMP failed"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } } else { /* @@ -3181,11 +3213,10 @@ create_ring(pcap_t *handle, int *status) } if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP, (void *)×ource, sizeof(timesource))) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't set PACKET_TIMESTAMP"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } } } @@ -3244,10 +3275,9 @@ retry: req.tp_frame_nr -= req.tp_frame_nr/20; goto retry; } - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't create rx ring on packet socket"); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } /* memory map the rx ring */ @@ -3255,25 +3285,23 @@ retry: handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); if (handlep->mmapbuf == MAP_FAILED) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't mmap rx ring"); /* clear the allocated ring on error*/ destroy_ring(handle); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } /* allocate a ring for each frame header pointer*/ handle->cc = req.tp_frame_nr; handle->buffer = malloc(handle->cc * sizeof(union thdr *)); if (!handle->buffer) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't allocate ring of frame headers"); destroy_ring(handle); - *status = PCAP_ERROR; - return -1; + return PCAP_ERROR; } /* fill the header ring with proper frame ptr*/ @@ -3288,7 +3316,7 @@ retry: handle->bufsize = req.tp_frame_size; handle->offset = 0; - return 1; + return status; } /* free all ring related resources*/ @@ -3334,7 +3362,7 @@ destroy_ring(pcap_t *handle) * pcap_next() or pcap_next_ex(). */ static void -pcap_oneshot_linux(u_char *user, const struct pcap_pkthdr *h, +pcapint_oneshot_linux(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct oneshot_userdata *sp = (struct oneshot_userdata *)user; @@ -3361,10 +3389,10 @@ pcap_setnonblock_linux(pcap_t *handle, int nonblock) struct pcap_linux *handlep = handle->priv; /* - * Set the file descriptor to non-blocking mode, as we use + * Set the file descriptor to the requested mode, as we use * it for sending packets. */ - if (pcap_setnonblock_fd(handle, nonblock) == -1) + if (pcapint_setnonblock_fd(handle, nonblock) == -1) return -1; /* @@ -3372,6 +3400,9 @@ pcap_setnonblock_linux(pcap_t *handle, int nonblock) * preserve the timeout value provided with pcap_set_timeout. */ if (nonblock) { + /* + * We're setting the mode to non-blocking mode. + */ if (handlep->timeout >= 0) { /* * Indicate that we're switching to @@ -3385,14 +3416,15 @@ pcap_setnonblock_linux(pcap_t *handle, int nonblock) handlep->poll_breakloop_fd = -1; } } else { + /* + * We're setting the mode to blocking mode. + */ if (handlep->poll_breakloop_fd == -1) { /* If we did not have an eventfd, open one now that we are blocking. */ if ( ( handlep->poll_breakloop_fd = eventfd(0, EFD_NONBLOCK) ) == -1 ) { - int save_errno = errno; - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Could not open eventfd: %s", - strerror(errno)); - errno = save_errno; + pcapint_fmt_errmsg_for_errno(handle->errbuf, + PCAP_ERRBUF_SIZE, errno, + "could not open eventfd"); return -1; } } @@ -3527,7 +3559,7 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) * Error. If it's not EINTR, report it. */ if (errno != EINTR) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't poll on packet socket"); return PCAP_ERROR; @@ -3629,7 +3661,7 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) "Error condition on packet socket: Reported error was 0"); return PCAP_ERROR; } else { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, err, "Error condition on packet socket"); @@ -3651,7 +3683,7 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) nread = read(handlep->poll_breakloop_fd, &value, sizeof(value)); if (nread == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Error reading from event FD"); @@ -3738,7 +3770,7 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) * The device still exists; try to see if it's up. */ memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, handlep->device, + pcapint_strlcpy(ifr.ifr_name, handlep->device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { if (errno == ENXIO || errno == ENODEV) { @@ -3752,7 +3784,7 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) "The interface disappeared"); return PCAP_ERROR; } else { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "%s: Can't get flags", handlep->device); @@ -3803,7 +3835,6 @@ static int pcap_handle_packet_mmap( unsigned char *bp; struct sockaddr_ll *sll; struct pcap_pkthdr pcaphdr; - pcap_can_socketcan_hdr *canhdr; unsigned int snaplen = tp_snaplen; struct utsname utsname; @@ -3932,56 +3963,173 @@ static int pcap_handle_packet_mmap( * DLT_CAN_SOCKETCAN is expected to provide. */ if (sll->sll_hatype == ARPHRD_CAN) { - /* - * DLT_CAN_SOCKETCAN is specified as having the - * CAN ID and flags in network byte order, but - * capturing on a CAN device provides it in host - * byte order. Convert it to network byte order. - */ - canhdr = (pcap_can_socketcan_hdr *)bp; - canhdr->can_id = htonl(canhdr->can_id); + pcap_can_socketcan_hdr *canhdr = (pcap_can_socketcan_hdr *)bp; + uint16_t protocol = ntohs(sll->sll_protocol); /* - * In addition, set the CANFD_FDF flag if - * the protocol is LINUX_SLL_P_CANFD, as - * the protocol field itself isn't in - * the packet to indicate that it's a - * CAN FD packet. + * Check the protocol field from the sll header. + * If it's one of the known CAN protocol types, + * make sure the appropriate flags are set, so + * that a program can tell what type of frame + * it is. + * + * The two flags are: + * + * CANFD_FDF, which is in the fd_flags field + * of the CAN classic/CAN FD header; + * + * CANXL_XLF, which is in the flags field + * of the CAN XL header, which overlaps + * the payload_length field of the CAN + * classic/CAN FD header. */ - uint16_t protocol = ntohs(sll->sll_protocol); - if (protocol == LINUX_SLL_P_CANFD) { + switch (protocol) { + + case LINUX_SLL_P_CAN: + /* + * CAN classic. + * + * Zero out the fd_flags and reserved + * fields, in case they're uninitialized + * crap, and clear the CANXL_XLF bit in + * the payload_length field. + * + * This means that the CANFD_FDF flag isn't + * set in the fd_flags field, and that + * the CANXL_XLF bit isn't set in the + * payload_length field, so this frame + * will appear to be a CAN classic frame. + */ + canhdr->payload_length &= ~CANXL_XLF; + canhdr->fd_flags = 0; + canhdr->reserved1 = 0; + canhdr->reserved2 = 0; + break; + + case LINUX_SLL_P_CANFD: + /* + * Set CANFD_FDF in the fd_flags field, + * and clear the CANXL_XLF bit in the + * payload_length field, so this frame + * will appear to be a CAN FD frame. + */ + canhdr->payload_length &= ~CANXL_XLF; canhdr->fd_flags |= CANFD_FDF; /* - * Zero out all the unknown bits in - * fd_flags and clear the reserved - * fields, so that a program reading - * this can assume that CANFD_FDF - * is set because we set it, not - * because some uninitialized crap - * was provided in the fd_flags - * field. + * Zero out all the unknown bits in fd_flags + * and clear the reserved fields, so that + * a program reading this can assume that + * CANFD_FDF is set because we set it, not + * because some uninitialized crap was + * provided in the fd_flags field. * * (At least some LINKTYPE_CAN_SOCKETCAN - * files attached to Wireshark bugs - * had uninitialized junk there, so it - * does happen.) + * files attached to Wireshark bugs had + * uninitialized junk there, so it does + * happen.) * - * Update this if Linux adds more flag - * bits to the fd_flags field or uses - * either of the reserved fields for - * FD frames. + * Update this if Linux adds more flag bits + * to the fd_flags field or uses either of + * the reserved fields for FD frames. */ - canhdr->fd_flags &= ~(CANFD_FDF|CANFD_ESI|CANFD_BRS); + canhdr->fd_flags &= (CANFD_FDF|CANFD_ESI|CANFD_BRS); canhdr->reserved1 = 0; canhdr->reserved2 = 0; + break; + + case LINUX_SLL_P_CANXL: + /* + * CAN XL frame. + * + * Make sure the CANXL_XLF bit is set in + * the payload_length field, so that + * this frame will appear to be a + * CAN XL frame. + */ + canhdr->payload_length |= CANXL_XLF; + break; + } + + /* + * Put multi-byte header fields in a byte-order + *-independent format. + */ + if (canhdr->payload_length & CANXL_XLF) { + /* + * This is a CAN XL frame. + * + * DLT_CAN_SOCKETCAN is specified as having + * the Priority ID/VCID field in big-- + * endian byte order, and the payload length + * and Acceptance Field in little-endian byte + * order. but capturing on a CAN device + * provides them in host byte order. + * Convert them to the appropriate byte + * orders. + * + * The reason we put the first field + * into big-endian byte order is that + * older libpcap code, ignorant of + * CAN XL, treated it as the CAN ID + * field and put it into big-endian + * byte order, and we don't want to + * break code that understands CAN XL + * headers, and treats that field as + * being big-endian. + * + * The other fields are put in little- + * endian byte order is that older + * libpcap code, ignorant of CAN XL, + * left those fields alone, and the + * processors on which the CAN XL + * frames were captured are likely + * to be little-endian processors. + */ + pcap_can_socketcan_xl_hdr *canxl_hdr = (pcap_can_socketcan_xl_hdr *)bp; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* + * We're capturing on a little-endian + * machine, so we put the priority/VCID + * field into big-endian byte order, and + * leave the payload length and acceptance + * field in little-endian byte order. + */ + /* Byte-swap priority/VCID. */ + canxl_hdr->priority_vcid = SWAPLONG(canxl_hdr->priority_vcid); +#elif __BYTE_ORDER == __BIG_ENDIAN + /* + * We're capturing on a big-endian + * machine, so we want to leave the + * priority/VCID field alone, and byte-swap + * the payload length and acceptance + * fields to little-endian. + */ + /* Byte-swap the payload length */ + canxl_hdr->payload_length = SWAPSHORT(canxl_hdr->payload_length); + + /* + * Byte-swap the acceptance field. + * + * XXX - is it just a 4-octet string, + * not in any byte order? + */ + canxl_hdr->acceptance_field = SWAPLONG(canxl_hdr->acceptance_field); +#else +#error "Unknown byte order" +#endif } else { /* - * Clear CANFD_FDF if it's set (probably - * again meaning that this field is - * uninitialized junk). + * CAN or CAN FD frame. + * + * DLT_CAN_SOCKETCAN is specified as having + * the CAN ID and flags in network byte + * order, but capturing on a CAN device + * provides it in host byte order. Convert + * it to network byte order. */ - canhdr->fd_flags &= ~CANFD_FDF; + canhdr->can_id = htonl(canhdr->can_id); } } } @@ -3992,7 +4140,7 @@ static int pcap_handle_packet_mmap( aux_data.vlan_tag_present = tp_vlan_tci_valid; aux_data.vlan_tag = tp_vlan_tci & 0x0fff; - if (pcap_filter_with_aux_data(handle->fcode.bf_insns, + if (pcapint_filter_with_aux_data(handle->fcode.bf_insns, bp, tp_len, snaplen, @@ -4324,7 +4472,7 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) if (!handle) return -1; if (!filter) { - pcap_strlcpy(handle->errbuf, "setfilter: No filter specified", + pcapint_strlcpy(handle->errbuf, "setfilter: No filter specified", PCAP_ERRBUF_SIZE); return -1; } @@ -4333,8 +4481,8 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) /* Make our private copy of the filter */ - if (install_bpf_program(handle, filter) < 0) - /* install_bpf_program() filled in errbuf */ + if (pcapint_install_bpf_program(handle, filter) < 0) + /* pcapint_install_bpf_program() filled in errbuf */ return -1; /* @@ -4471,7 +4619,7 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) */ if (handlep->filter_in_userland) { if (reset_kernel_filter(handle) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't remove kernel filter"); err = -2; /* fatal error */ @@ -4558,10 +4706,10 @@ iface_get_id(int fd, const char *device, char *ebuf) struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFINDEX"); return -1; } @@ -4605,7 +4753,7 @@ iface_bind(int fd, int ifindex, char *ebuf, int protocol) ret = PCAP_ERROR_NO_SUCH_DEVICE; } else { ret = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "bind"); } return ret; @@ -4614,7 +4762,7 @@ iface_bind(int fd, int ifindex, char *ebuf, int protocol) /* Any pending errors, e.g., network is down? */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_ERROR)"); return PCAP_ERROR; } @@ -4629,7 +4777,7 @@ iface_bind(int fd, int ifindex, char *ebuf, int protocol) */ return PCAP_ERROR_IFACE_NOT_UP; } else if (err > 0) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, err, "bind"); return PCAP_ERROR; } @@ -4719,7 +4867,7 @@ added: * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ - if (!pcap_do_addexit(handle)) { + if (!pcapint_do_addexit(handle)) { /* * "atexit()" failed; don't put the interface * in rfmon mode, just give up. @@ -4734,9 +4882,9 @@ added: * Now configure the monitor interface up. */ memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name)); if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "%s: Can't get flags for %s", device, handlep->mondevice); del_mon_if(handle, sock_fd, &nlstate, device, @@ -4746,7 +4894,7 @@ added: } ifr.ifr_flags |= IFF_UP|IFF_RUNNING; if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags for %s", device, handlep->mondevice); del_mon_if(handle, sock_fd, &nlstate, device, @@ -4769,7 +4917,7 @@ added: /* * Add this to the list of pcaps to close when we exit. */ - pcap_add_to_pcaps_to_close(handle); + pcapint_add_to_pcaps_to_close(handle); return 1; } @@ -4808,7 +4956,7 @@ iface_set_all_ts_types(pcap_t *handle, char *ebuf) handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int)); if (handle->tstamp_type_list == NULL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc"); return -1; } @@ -4848,13 +4996,13 @@ iface_get_ts_types(const char *device, pcap_t *handle, char *ebuf) */ fd = get_if_ioctl_socket(); if (fd < 0) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)"); return -1; } memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); memset(&info, 0, sizeof(info)); info.cmd = ETHTOOL_GET_TS_INFO; ifr.ifr_data = (caddr_t)&info; @@ -4889,7 +5037,7 @@ iface_get_ts_types(const char *device, pcap_t *handle, char *ebuf) /* * Other error. */ - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, save_errno, "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed", device); @@ -4925,7 +5073,7 @@ iface_get_ts_types(const char *device, pcap_t *handle, char *ebuf) if (num_ts_types != 0) { handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int)); if (handle->tstamp_type_list == NULL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc"); return -1; } @@ -5006,7 +5154,7 @@ iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname, struct ethtool_value eval; memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); eval.cmd = cmd; eval.data = 0; ifr.ifr_data = (caddr_t)&eval; @@ -5021,7 +5169,7 @@ iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname, */ return 0; } - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "%s: SIOCETHTOOL(%s) ioctl failed", handle->opt.device, cmdname); return -1; @@ -5153,7 +5301,7 @@ iface_dsa_get_proto_info(const char *device, pcap_t *handle) fd = asprintf(&pathstr, "/sys/class/net/%s/dsa/tagging", device); if (fd < 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, fd, "asprintf"); return PCAP_ERROR; } @@ -5168,7 +5316,7 @@ iface_dsa_get_proto_info(const char *device, pcap_t *handle) r = read(fd, buf, sizeof(buf) - 1); if (r <= 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "read"); close(fd); return PCAP_ERROR; @@ -5213,10 +5361,10 @@ iface_get_mtu(int fd, const char *device, char *ebuf) return BIGGER_THAN_ALL_MTUS; memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFMTU"); return -1; } @@ -5234,7 +5382,7 @@ iface_get_arptype(int fd, const char *device, char *ebuf) int ret; memset(&ifr, 0, sizeof(ifr)); - pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { if (errno == ENODEV) { @@ -5248,7 +5396,7 @@ iface_get_arptype(int fd, const char *device, char *ebuf) ebuf[0] = '\0'; } else { ret = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFHWADDR"); } return ret; @@ -5275,7 +5423,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode) len = handle->fcode.bf_len; f = (struct bpf_insn *)malloc(prog_size); if (f == NULL) { - pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); return -1; } @@ -5467,13 +5615,13 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) */ save_mode = fcntl(handle->fd, F_GETFL, 0); if (save_mode == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't get FD flags when changing filter"); return -2; } if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't set nonblocking mode when changing filter"); return -2; @@ -5490,13 +5638,13 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) */ (void)fcntl(handle->fd, F_SETFL, save_mode); (void)reset_kernel_filter(handle); - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, save_errno, "recv failed when changing filter"); return -2; } if (fcntl(handle->fd, F_SETFL, save_mode) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't restore FD flags when changing filter"); return -2; @@ -5527,7 +5675,7 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) * Report it as a fatal error. */ if (reset_kernel_filter(handle) == -1) { - pcap_fmt_errmsg_for_errno(handle->errbuf, + pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "can't remove kernel total filter"); return -2; /* fatal error */ @@ -5567,7 +5715,7 @@ reset_kernel_filter(pcap_t *handle) int pcap_set_protocol_linux(pcap_t *p, int protocol) { - if (pcap_check_activated(p)) + if (pcapint_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->opt.protocol = protocol; return (0); |
