diff options
author | Xin LI <delphij@FreeBSD.org> | 2013-05-30 06:41:26 +0000 |
---|---|---|
committer | Xin LI <delphij@FreeBSD.org> | 2013-05-30 06:41:26 +0000 |
commit | 59ed76438047aa730b3a617abd873b84457fc4fd (patch) | |
tree | dcf9aa60c012e16ad8a4bb83641d382d572050f8 /pcap-linux.c | |
parent | 3ca61f8b14e648b24f10072d662c12fb35fc4b44 (diff) | |
download | src-59ed76438047aa730b3a617abd873b84457fc4fd.tar.gz src-59ed76438047aa730b3a617abd873b84457fc4fd.zip |
Vendor import of libpcap 1.4.0.vendor/libpcap/1.4.0
Notes
Notes:
svn path=/vendor/libpcap/dist/; revision=251125
svn path=/vendor/libpcap/1.4.0/; revision=251126; tag=vendor/libpcap/1.4.0
Diffstat (limited to 'pcap-linux.c')
-rw-r--r-- | pcap-linux.c | 299 |
1 files changed, 114 insertions, 185 deletions
diff --git a/pcap-linux.c b/pcap-linux.c index 8168e474778d..988e47b7ba41 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -127,11 +127,13 @@ static const char rcsid[] _U_ = #include <fcntl.h> #include <string.h> #include <limits.h> +#include <sys/stat.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/utsname.h> #include <sys/mman.h> #include <linux/if.h> +#include <linux/if_packet.h> #include <netinet/in.h> #include <linux/if_ether.h> #include <net/if_arp.h> @@ -142,38 +144,6 @@ static const char rcsid[] _U_ = #include "pcap/sll.h" #include "pcap/vlan.h" -#ifdef HAVE_DAG_API -#include "pcap-dag.h" -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API -#include "pcap-septel.h" -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API -#include "pcap-snf.h" -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_USB -#include "pcap-usb-linux.h" -#endif - -#ifdef PCAP_SUPPORT_BT -#include "pcap-bt-linux.h" -#endif - -#ifdef PCAP_SUPPORT_CAN -#include "pcap-can-linux.h" -#endif - -#if PCAP_SUPPORT_CANUSB -#include "pcap-canusb-linux.h" -#endif - -#ifdef PCAP_SUPPORT_NETFILTER -#include "pcap-netfilter-linux.h" -#endif - /* * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET * sockets rather than SOCK_PACKET sockets. @@ -387,66 +357,10 @@ static struct sock_fprog total_fcode #endif /* SO_ATTACH_FILTER */ pcap_t * -pcap_create(const char *device, char *ebuf) +pcap_create_interface(const char *device, char *ebuf) { pcap_t *handle; - /* - * A null device name is equivalent to the "any" device. - */ - if (device == NULL) - device = "any"; - -#ifdef HAVE_DAG_API - if (strstr(device, "dag")) { - return dag_create(device, ebuf); - } -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API - if (strstr(device, "septel")) { - return septel_create(device, ebuf); - } -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API - handle = snf_create(device, ebuf); - if (strstr(device, "snf") || handle != NULL) - return handle; - -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_BT - if (strstr(device, "bluetooth")) { - return bt_create(device, ebuf); - } -#endif - -#if PCAP_SUPPORT_CANUSB - if (strstr(device, "canusb")) { - return canusb_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_CAN - if ((strncmp(device, "can", 3) == 0 && isdigit(device[3])) || - (strncmp(device, "vcan", 4) == 0 && isdigit(device[4]))) { - return can_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_USB - if (strstr(device, "usbmon")) { - return usb_create(device, ebuf); - } -#endif - -#ifdef PCAP_SUPPORT_NETFILTER - if (strncmp(device, "nflog", strlen("nflog")) == 0) { - return nflog_create(device, ebuf); - } -#endif - handle = pcap_create_common(device, ebuf); if (handle == NULL) return NULL; @@ -564,7 +478,7 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path, return 1; } -#ifdef HAVE_LIBNL_2_x +#ifdef HAVE_LIBNL_SOCKETS #define get_nl_errmsg nl_geterror #else /* libnl 2.x compatibility code */ @@ -595,7 +509,7 @@ __genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache) return 0; } #define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache -#endif /* !HAVE_LIBNL_2_x */ +#endif /* !HAVE_LIBNL_SOCKETS */ struct nl80211_state { struct nl_sock *nl_sock; @@ -680,7 +594,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) { -#ifdef HAVE_LIBNL_2_x +#if defined HAVE_LIBNL_NLE if (err == -NLE_FAILURE) { #else if (err == -ENFILE) { @@ -708,7 +622,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, } err = nl_wait_for_ack(state->nl_sock); if (err < 0) { -#ifdef HAVE_LIBNL_2_x +#if defined HAVE_LIBNL_NLE if (err == -NLE_FAILURE) { #else if (err == -ENFILE) { @@ -1618,32 +1532,40 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - struct tpacket_auxdata *aux; - unsigned int len; - struct vlan_tag *tag; - - if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) || - cmsg->cmsg_level != SOL_PACKET || - cmsg->cmsg_type != PACKET_AUXDATA) - continue; + if (handle->md.vlan_offset != -1) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + struct tpacket_auxdata *aux; + unsigned int len; + struct vlan_tag *tag; - aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); - if (aux->tp_vlan_tci == 0) - continue; + if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) || + cmsg->cmsg_level != SOL_PACKET || + cmsg->cmsg_type != PACKET_AUXDATA) + continue; - len = packet_len > iov.iov_len ? iov.iov_len : packet_len; - if (len < 2 * ETH_ALEN) - break; + aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); +#if defined(TP_STATUS_VLAN_VALID) + if ((aux->tp_vlan_tci == 0) && !(aux->tp_status & TP_STATUS_VLAN_VALID)) +#else + if (aux->tp_vlan_tci == 0) /* this is ambigious but without the + TP_STATUS_VLAN_VALID flag, there is + nothing that we can do */ +#endif + continue; - bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + len = packet_len > iov.iov_len ? iov.iov_len : packet_len; + if (len < (unsigned int) handle->md.vlan_offset) + break; - tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); - tag->vlan_tpid = htons(ETH_P_8021Q); - tag->vlan_tci = htons(aux->tp_vlan_tci); + bp -= VLAN_TAG_LEN; + memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); + + tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); + tag->vlan_tpid = htons(ETH_P_8021Q); + tag->vlan_tci = htons(aux->tp_vlan_tci); - packet_len += VLAN_TAG_LEN; + packet_len += VLAN_TAG_LEN; + } } #endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */ #endif /* HAVE_PF_PACKET_SOCKETS */ @@ -1951,6 +1873,8 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf) DIR *sys_class_net_d; int fd; struct dirent *ent; + char subsystem_path[PATH_MAX+1]; + struct stat statb; char *p; char name[512]; /* XXX - pick a size */ char *q, *saveq; @@ -1995,12 +1919,43 @@ scan_sys_class_net(pcap_if_t **devlistp, char *errbuf) } /* - * Ignore directories (".", "..", and any subdirectories). + * Ignore "." and "..". + */ + if (strcmp(ent->d_name, ".") == 0 || + strcmp(ent->d_name, "..") == 0) + continue; + + /* + * Ignore plain files; they do not have subdirectories + * and thus have no attributes. */ - if (ent->d_type == DT_DIR) + if (ent->d_type == DT_REG) continue; /* + * Is there an "ifindex" file under that name? + * (We don't care whether it's a directory or + * a symlink; older kernels have directories + * for devices, newer kernels have symlinks to + * directories.) + */ + snprintf(subsystem_path, sizeof subsystem_path, + "/sys/class/net/%s/ifindex", ent->d_name); + if (lstat(subsystem_path, &statb) != 0) { + /* + * Stat failed. Either there was an error + * other than ENOENT, and we don't know if + * this is an interface, or it's ENOENT, + * and either some part of "/sys/class/net/{if}" + * disappeared, in which case it probably means + * the interface disappeared, or there's no + * "ifindex" file, which means it's not a + * network interface. + */ + continue; + } + + /* * Get the interface name. */ p = &ent->d_name[0]; @@ -2265,56 +2220,6 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0) return (-1); -#ifdef HAVE_DAG_API - /* - * Add DAG devices. - */ - if (dag_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_DAG_API */ - -#ifdef HAVE_SEPTEL_API - /* - * Add Septel devices. - */ - if (septel_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_SEPTEL_API */ - -#ifdef HAVE_SNF_API - if (snf_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif /* HAVE_SNF_API */ - -#ifdef PCAP_SUPPORT_BT - /* - * Add Bluetooth devices. - */ - if (bt_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#ifdef PCAP_SUPPORT_USB - /* - * Add USB devices. - */ - if (usb_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#ifdef PCAP_SUPPORT_NETFILTER - /* - * Add netfilter devices. - */ - if (netfilter_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - -#if PCAP_SUPPORT_CANUSB - if (canusb_platform_finddevs(alldevsp, errbuf) < 0) - return (-1); -#endif - return (0); } @@ -3181,6 +3086,24 @@ activate_new(pcap_t *handle) } handle->bufsize = handle->snapshot; + /* + * Set the offset at which to insert VLAN tags. + */ + switch (handle->linktype) { + + case DLT_EN10MB: + handle->md.vlan_offset = 2 * ETH_ALEN; + break; + + case DLT_LINUX_SLL: + handle->md.vlan_offset = 14; + break; + + default: + handle->md.vlan_offset = -1; /* unknown */ + break; + } + /* Save the socket FD in the pcap structure */ handle->fd = sock_fd; @@ -3732,27 +3655,21 @@ pcap_getnonblock_mmap(pcap_t *p, char *errbuf) static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf) { - /* map each value to the corresponding 2's complement, to - * preserve the timeout value provided with pcap_set_timeout */ + /* + * Map each value to their corresponding negation to + * preserve the timeout value provided with pcap_set_timeout. + */ if (nonblock) { if (p->md.timeout >= 0) { /* - * Timeout is non-negative, so we're not already - * in non-blocking mode; set it to the 2's - * complement, to make it negative, as an - * indication that we're in non-blocking mode. + * Indicate that we're switching to + * non-blocking mode. */ - p->md.timeout = p->md.timeout*-1 - 1; + p->md.timeout = ~p->md.timeout; } } else { if (p->md.timeout < 0) { - /* - * Timeout is negative, so we're not already - * in blocking mode; reverse the previous - * operation, to make the timeout non-negative - * again. - */ - p->md.timeout = (p->md.timeout+1)*-1; + p->md.timeout = ~p->md.timeout; } } return 0; @@ -4020,14 +3937,20 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, } #ifdef HAVE_TPACKET2 - if (handle->md.tp_version == TPACKET_V2 && h.h2->tp_vlan_tci && - tp_snaplen >= 2 * ETH_ALEN) { + if ((handle->md.tp_version == TPACKET_V2) && +#if defined(TP_STATUS_VLAN_VALID) + (h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)) && +#else + h.h2->tp_vlan_tci && +#endif + handle->md.vlan_offset != -1 && + tp_snaplen >= (unsigned int) handle->md.vlan_offset) { struct vlan_tag *tag; bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN); + memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); - tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN); + tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); tag->vlan_tpid = htons(ETH_P_8021Q); tag->vlan_tci = htons(h.h2->tp_vlan_tci); @@ -4935,7 +4858,7 @@ iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname) eval.cmd = cmd; ifr.ifr_data = (caddr_t)&eval; if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) { - if (errno == EOPNOTSUPP) { + if (errno == EOPNOTSUPP || errno == EINVAL) { /* * OK, let's just return 0, which, in our * case, either means "no, what we're asking @@ -5213,6 +5136,12 @@ activate_old(pcap_t *handle) */ handle->offset = 0; + /* + * SOCK_PACKET sockets don't supply information from + * stripped VLAN tags. + */ + handle->md.vlan_offset = -1; /* unknown */ + return 1; } |