From 842b059322c3cc02ebfe98e65edc9fe9206035ea Mon Sep 17 00:00:00 2001 From: Emmanuel Roullit Date: Sat, 8 May 2010 15:03:12 +0000 Subject: [PATCH] Fixed promiscuous mode. Now saves NIC flags and restores them when the program exits. git-svn-id: http://netsniff-ng.googlecode.com/svn/trunk@358 21e0ff64-9a0b-11de-825e-994487f65616 --- netsniff-ng/include/netsniff-ng/config.h | 1 + netsniff-ng/include/netsniff-ng/netdev.h | 2 + netsniff-ng/lib/bootstrap.c | 11 ++++-- netsniff-ng/lib/netdev.c | 66 ++++++++++++++------------------ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/netsniff-ng/include/netsniff-ng/config.h b/netsniff-ng/include/netsniff-ng/config.h index 8103d7f6..46c50f6c 100644 --- a/netsniff-ng/include/netsniff-ng/config.h +++ b/netsniff-ng/include/netsniff-ng/config.h @@ -59,6 +59,7 @@ typedef struct system_data { char *rulefile; /* Ethernet device */ char *dev; + short prev_nic_flags; int pcap_fd; struct sock_filter *bpf; void (*print_pkt) (ring_buff_bytes_t *, const struct tpacket_hdr *); diff --git a/netsniff-ng/include/netsniff-ng/netdev.h b/netsniff-ng/include/netsniff-ng/netdev.h index 1852a142..0c7682fb 100644 --- a/netsniff-ng/include/netsniff-ng/netdev.h +++ b/netsniff-ng/include/netsniff-ng/netdev.h @@ -38,6 +38,8 @@ struct in6_ifreq { extern int get_device_bitrate_generic(const char *ifname); extern int get_device_bitrate_generic_cable(const char *ifname); extern short get_nic_flags(const char *dev); +extern void set_nic_flags(const char *dev, const short flag_to_set); +extern void unset_nic_flags(const char *dev, const short flag_to_set); extern void print_device_info(void); extern void put_dev_into_promisc_mode(const char *dev); extern void inject_kernel_bpf(int sock, struct sock_filter *bpf, int len); diff --git a/netsniff-ng/lib/bootstrap.c b/netsniff-ng/lib/bootstrap.c index f436c657..8f8d4388 100644 --- a/netsniff-ng/lib/bootstrap.c +++ b/netsniff-ng/lib/bootstrap.c @@ -215,10 +215,13 @@ static void __init_stage_mode_common(system_data_t * sd, int *sock, ring_buff_t memset((*rb), 0, sizeof(**rb)); /* - * Some further common init stuff + * Save previous nic flags to be able + * restore them at exit time. */ + sd->prev_nic_flags = get_nic_flags(sd->dev); - put_dev_into_promisc_mode(sd->dev); + /* Activate promiscuous mode */ + set_nic_flags(sd->dev, sd->prev_nic_flags | IFF_PROMISC); } static void __init_stage_bpf(system_data_t * sd, int *sock, ring_buff_t ** rb, struct pollfd *pfd) @@ -436,7 +439,9 @@ static void __exit_stage_mode_common(system_data_t * sd, int *sock, ring_buff_t assert(sd); assert(sock); assert(rb); - /* NOP */ + + /* Restore flags which were set at program start */ + set_nic_flags(sd->dev, sd->prev_nic_flags); } static void __exit_stage_bpf(system_data_t * sd, int *sock, ring_buff_t ** rb) diff --git a/netsniff-ng/lib/netdev.c b/netsniff-ng/lib/netdev.c index 44837dab..137dc32b 100644 --- a/netsniff-ng/lib/netdev.c +++ b/netsniff-ng/lib/netdev.c @@ -396,7 +396,6 @@ static int get_mtu(const char *dev) /** * get_nic_flags - Fetches device flags - * @sock: socket * @dev: device name */ short get_nic_flags(const char *dev) @@ -424,6 +423,35 @@ short get_nic_flags(const char *dev) } /** + * set_nic_flags - Set flags attached to a network device + * @dev: device name + * @mac: Flags to set + */ +void set_nic_flags(const char * dev, const short nic_flags) +{ + int ret; + int sock; + struct ifreq ethreq; + + assert_dev_name(dev); + + sock = get_af_socket(AF_INET); + + memset(ðreq, 0, sizeof(ethreq)); + strncpy(ethreq.ifr_name, dev, IFNAMSIZ); + ethreq.ifr_flags = nic_flags; + + ret = ioctl(sock, SIOCSIFFLAGS, ðreq); + if (ret < 0) { + err("ioctl: cannot determine dev number for %s", ethreq.ifr_name); + close(sock); + exit(EXIT_FAILURE); + } + + close(sock); +} + +/** * get_nic_mac - Fetches device MAC address * @dev: device name * @mac: Output buffer @@ -639,42 +667,6 @@ void print_device_info(void) } /** - * put_dev_into_promisc_mode - Puts network device into promiscuous mode - * @sock: socket - * @ifindex: device number - */ -void put_dev_into_promisc_mode(const char *dev) -{ - int ret; - int sock; - struct packet_mreq mr; - - assert(dev); - - sock = get_pf_socket(); - - memset(&mr, 0, sizeof(mr)); - mr.mr_ifindex = ethdev_to_ifindex(dev); - mr.mr_type = PACKET_MR_PROMISC; - - /* This is better than ioctl(), because the kernel now manages the - promisc flag for itself via internal counters. If the socket will - be closed the kernel decrements the counters automatically which - will not work with ioctl(). There, you have to manage things - manually ... */ - - ret = setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)); - if (ret < 0) { - err("setsockopt: cannot set dev %s to promisc mode", dev); - - close(sock); - exit(EXIT_FAILURE); - } - - close(sock); -} - -/** * inject_kernel_bpf - Binds filter code to socket * @sock: socket * @bpf: Berkeley Packet Filter code -- 2.11.4.GIT