--- a/pcap-int.h +++ b/pcap-int.h @@ -187,6 +187,7 @@ struct pcap_opt { char *source; int promisc; int rfmon; + int proto; /* protocol for packet socket (linux) */ }; /* --- a/pcap-linux.c +++ b/pcap-linux.c @@ -273,7 +273,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); static int has_wext(int sock_fd, const char *device, char *ebuf); static int enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device); @@ -362,7 +362,7 @@ pcap_can_set_rfmon_linux(pcap_t *p) * (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(p->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); @@ -522,6 +522,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 @@ -1673,8 +1676,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) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", @@ -1763,7 +1766,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)); @@ -1815,7 +1818,7 @@ activate_new(pcap_t *handle) } if ((err = iface_bind(sock_fd, handle->md.ifindex, - handle->errbuf)) != 1) { + handle->errbuf, handle->opt.proto)) != 1) { close(sock_fd); if (err < 0) return err; @@ -2440,7 +2443,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; @@ -2449,7 +2452,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) { @@ -3119,7 +3122,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 @@ -152,6 +152,8 @@ pcap_create_common(const char *source, c pcap_set_snaplen(p, 65535); /* max packet size */ p->opt.promisc = 0; p->opt.buffer_size = 0; + p->opt.proto = -1; + return (p); } @@ -212,6 +214,15 @@ pcap_set_buffer_size(pcap_t *p, int buff } 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 @@ -61,6 +61,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 @@ -263,6 +264,7 @@ int pcap_can_set_rfmon(pcap_t *); int pcap_set_rfmon(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); +int pcap_set_protocol(pcap_t *, unsigned short); int pcap_activate(pcap_t *); pcap_t *pcap_open_live(const char *, int, int, int, char *);