--- a/pcap-linux.c +++ b/pcap-linux.c @@ -414,7 +414,7 @@ static int iface_get_id(int fd, const ch static int iface_get_mtu(int fd, const char *device, char *ebuf); static int iface_get_arptype(int fd, const char *device, char *ebuf); #ifdef HAVE_PF_PACKET_SOCKETS -static int iface_bind(int fd, int ifindex, char *ebuf); +static int iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto); #ifdef IW_MODE_MONITOR static int has_wext(int sock_fd, const char *device, char *ebuf); #endif /* IW_MODE_MONITOR */ @@ -1028,7 +1028,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle) * (We assume that if we have Wireless Extensions support * we also have PF_PACKET support.) */ - sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + sock_fd = socket(PF_PACKET, SOCK_RAW, p->opt.proto); if (sock_fd == -1) { (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); @@ -1337,6 +1337,9 @@ pcap_activate_linux(pcap_t *handle) handle->read_op = pcap_read_linux; handle->stats_op = pcap_stats_linux; + if (handle->opt.proto < 0) + handle->opt.proto = (int) htons(ETH_P_ALL); + /* * The "any" device is a special device which causes us not * to bind to a particular device and thus to look at all @@ -3160,8 +3163,8 @@ activate_new(pcap_t *handle) * try a SOCK_RAW socket for the raw interface. */ sock_fd = is_any_device ? - socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : - socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + socket(PF_PACKET, SOCK_DGRAM, handle->opt.proto) : + socket(PF_PACKET, SOCK_RAW, handle->opt.proto); if (sock_fd == -1) { if (errno == EINVAL || errno == EAFNOSUPPORT) { @@ -3279,7 +3282,7 @@ activate_new(pcap_t *handle) return PCAP_ERROR; } sock_fd = socket(PF_PACKET, SOCK_DGRAM, - htons(ETH_P_ALL)); + handle->opt.proto); if (sock_fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); @@ -3343,7 +3346,7 @@ activate_new(pcap_t *handle) } if ((err = iface_bind(sock_fd, handlep->ifindex, - handle->errbuf)) != 1) { + handle->errbuf, handle->opt.proto)) != 1) { close(sock_fd); if (err < 0) return err; @@ -5050,7 +5053,7 @@ iface_get_id(int fd, const char *device, * or a PCAP_ERROR_ value on a hard error. */ static int -iface_bind(int fd, int ifindex, char *ebuf) +iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto) { struct sockaddr_ll sll; int err; @@ -5059,7 +5062,7 @@ iface_bind(int fd, int ifindex, char *eb memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; - sll.sll_protocol = htons(ETH_P_ALL); + sll.sll_protocol = proto; if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { if (errno == ENETDOWN) { @@ -6049,7 +6052,7 @@ activate_old(pcap_t *handle) /* Open the socket */ - handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); + handle->fd = socket(PF_INET, SOCK_PACKET, handle->opt.proto); if (handle->fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); --- a/pcap.c +++ b/pcap.c @@ -562,6 +562,7 @@ pcap_create_common(const char *source, c p->opt.promisc = 0; p->opt.rfmon = 0; p->opt.immediate = 0; + p->opt.proto = -1; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; @@ -725,6 +726,15 @@ pcap_get_tstamp_precision(pcap_t *p) } int +pcap_set_protocol(pcap_t *p, unsigned short proto) +{ + if (pcap_check_activated(p)) + return PCAP_ERROR_ACTIVATED; + p->opt.proto = proto; + return 0; +} + +int pcap_activate(pcap_t *p) { int status; --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -66,6 +66,7 @@ extern "C" { #define PCAP_VERSION_MINOR 4 #define PCAP_ERRBUF_SIZE 256 +#define HAS_PROTO_EXTENSION /* * Compatibility for systems that have a bpf.h that @@ -283,6 +284,7 @@ int pcap_set_timeout(pcap_t *, int); int pcap_set_tstamp_type(pcap_t *, int); int pcap_set_immediate_mode(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); +int pcap_set_protocol(pcap_t *, unsigned short); int pcap_set_tstamp_precision(pcap_t *, int); int pcap_get_tstamp_precision(pcap_t *); int pcap_activate(pcap_t *); --- a/pcap-int.h +++ b/pcap-int.h @@ -109,6 +109,7 @@ struct pcap_opt { char *source; int timeout; /* timeout for buffering */ int buffer_size; + int proto; /* protocol for packet socket (linux) */ int promisc; int rfmon; /* monitor mode */ int immediate; /* immediate mode - deliver packets as soon as they arrive */