| 1 | --- a/pcap-int.h |
| 2 | +++ b/pcap-int.h |
| 3 | @@ -209,6 +209,7 @@ struct pcap_opt { |
| 4 | char *source; |
| 5 | int promisc; |
| 6 | int rfmon; |
| 7 | + int proto; /* protocol for packet socket (linux) */ |
| 8 | }; |
| 9 | |
| 10 | /* |
| 11 | --- a/pcap-linux.c |
| 12 | +++ b/pcap-linux.c |
| 13 | @@ -335,7 +335,7 @@ static int iface_get_id(int fd, const ch |
| 14 | static int iface_get_mtu(int fd, const char *device, char *ebuf); |
| 15 | static int iface_get_arptype(int fd, const char *device, char *ebuf); |
| 16 | #ifdef HAVE_PF_PACKET_SOCKETS |
| 17 | -static int iface_bind(int fd, int ifindex, char *ebuf); |
| 18 | +static int iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto); |
| 19 | #ifdef IW_MODE_MONITOR |
| 20 | static int has_wext(int sock_fd, const char *device, char *ebuf); |
| 21 | #endif /* IW_MODE_MONITOR */ |
| 22 | @@ -881,7 +881,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle) |
| 23 | * (We assume that if we have Wireless Extensions support |
| 24 | * we also have PF_PACKET support.) |
| 25 | */ |
| 26 | - sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
| 27 | + sock_fd = socket(PF_PACKET, SOCK_RAW, p->opt.proto); |
| 28 | if (sock_fd == -1) { |
| 29 | (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, |
| 30 | "socket: %s", pcap_strerror(errno)); |
| 31 | @@ -1128,6 +1128,9 @@ pcap_activate_linux(pcap_t *handle) |
| 32 | handle->read_op = pcap_read_linux; |
| 33 | handle->stats_op = pcap_stats_linux; |
| 34 | |
| 35 | + if (handle->opt.proto < 0) |
| 36 | + handle->opt.proto = (int) htons(ETH_P_ALL); |
| 37 | + |
| 38 | /* |
| 39 | * The "any" device is a special device which causes us not |
| 40 | * to bind to a particular device and thus to look at all |
| 41 | @@ -2684,8 +2687,8 @@ activate_new(pcap_t *handle) |
| 42 | * try a SOCK_RAW socket for the raw interface. |
| 43 | */ |
| 44 | sock_fd = is_any_device ? |
| 45 | - socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : |
| 46 | - socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
| 47 | + socket(PF_PACKET, SOCK_DGRAM, handle->opt.proto) : |
| 48 | + socket(PF_PACKET, SOCK_RAW, handle->opt.proto); |
| 49 | |
| 50 | if (sock_fd == -1) { |
| 51 | snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", |
| 52 | @@ -2783,7 +2786,7 @@ activate_new(pcap_t *handle) |
| 53 | return PCAP_ERROR; |
| 54 | } |
| 55 | sock_fd = socket(PF_PACKET, SOCK_DGRAM, |
| 56 | - htons(ETH_P_ALL)); |
| 57 | + handle->opt.proto); |
| 58 | if (sock_fd == -1) { |
| 59 | snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, |
| 60 | "socket: %s", pcap_strerror(errno)); |
| 61 | @@ -2835,7 +2838,7 @@ activate_new(pcap_t *handle) |
| 62 | } |
| 63 | |
| 64 | if ((err = iface_bind(sock_fd, handle->md.ifindex, |
| 65 | - handle->errbuf)) != 1) { |
| 66 | + handle->errbuf, handle->opt.proto)) != 1) { |
| 67 | close(sock_fd); |
| 68 | if (err < 0) |
| 69 | return err; |
| 70 | @@ -3640,7 +3643,7 @@ iface_get_id(int fd, const char *device, |
| 71 | * or a PCAP_ERROR_ value on a hard error. |
| 72 | */ |
| 73 | static int |
| 74 | -iface_bind(int fd, int ifindex, char *ebuf) |
| 75 | +iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto) |
| 76 | { |
| 77 | struct sockaddr_ll sll; |
| 78 | int err; |
| 79 | @@ -3649,7 +3652,7 @@ iface_bind(int fd, int ifindex, char *eb |
| 80 | memset(&sll, 0, sizeof(sll)); |
| 81 | sll.sll_family = AF_PACKET; |
| 82 | sll.sll_ifindex = ifindex; |
| 83 | - sll.sll_protocol = htons(ETH_P_ALL); |
| 84 | + sll.sll_protocol = proto; |
| 85 | |
| 86 | if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { |
| 87 | if (errno == ENETDOWN) { |
| 88 | @@ -4359,7 +4362,7 @@ activate_old(pcap_t *handle) |
| 89 | |
| 90 | /* Open the socket */ |
| 91 | |
| 92 | - handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); |
| 93 | + handle->fd = socket(PF_INET, SOCK_PACKET, handle->opt.proto); |
| 94 | if (handle->fd == -1) { |
| 95 | snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, |
| 96 | "socket: %s", pcap_strerror(errno)); |
| 97 | --- a/pcap.c |
| 98 | +++ b/pcap.c |
| 99 | @@ -258,6 +258,8 @@ pcap_create_common(const char *source, c |
| 100 | pcap_set_snaplen(p, 65535); /* max packet size */ |
| 101 | p->opt.promisc = 0; |
| 102 | p->opt.buffer_size = 0; |
| 103 | + p->opt.proto = -1; |
| 104 | + |
| 105 | return (p); |
| 106 | } |
| 107 | |
| 108 | @@ -317,6 +319,15 @@ pcap_set_buffer_size(pcap_t *p, int buff |
| 109 | return 0; |
| 110 | } |
| 111 | |
| 112 | +int |
| 113 | +pcap_set_protocol(pcap_t *p, unsigned short proto) |
| 114 | +{ |
| 115 | + if (pcap_check_activated(p)) |
| 116 | + return PCAP_ERROR_ACTIVATED; |
| 117 | + p->opt.proto = proto; |
| 118 | + return 0; |
| 119 | +} |
| 120 | + |
| 121 | int |
| 122 | pcap_activate(pcap_t *p) |
| 123 | { |
| 124 | --- a/pcap/pcap.h |
| 125 | +++ b/pcap/pcap.h |
| 126 | @@ -68,6 +68,7 @@ extern "C" { |
| 127 | #define PCAP_VERSION_MINOR 4 |
| 128 | |
| 129 | #define PCAP_ERRBUF_SIZE 256 |
| 130 | +#define HAS_PROTO_EXTENSION |
| 131 | |
| 132 | /* |
| 133 | * Compatibility for systems that have a bpf.h that |
| 134 | @@ -276,6 +277,7 @@ int pcap_can_set_rfmon(pcap_t *); |
| 135 | int pcap_set_rfmon(pcap_t *, int); |
| 136 | int pcap_set_timeout(pcap_t *, int); |
| 137 | int pcap_set_buffer_size(pcap_t *, int); |
| 138 | +int pcap_set_protocol(pcap_t *, unsigned short); |
| 139 | int pcap_activate(pcap_t *); |
| 140 | |
| 141 | pcap_t *pcap_open_live(const char *, int, int, int, char *); |
| 142 | |