From 6c1c18203918e816ad94de2a77d114a1b7ace2d8 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 17 Jun 2013 11:20:58 -0400 Subject: [PATCH] [Listener] Adapt get_mac_addr() to build on BSD The get_mac_addr() function was the only real blocker that prevented building on BSD systems, as it used the Linux-specific SIOCGIFHWADDR ioctl. When compiling for Linux, we still use this ioctl, but for the BSD version we use sysctl(). This allows OwlPS Listener to build on BSD (tested on NetBSD, OpenBSD and DragonFly). That doesn't mean it will actually work when trying to capture packets though (that has to be tested on real hardware), but that's still a progress. --- CMakeLists.txt | 7 +-- INSTALL.t2t | 20 ++++---- TODO.t2t | 4 -- doc/owlps.t2t | 11 +++-- owlps-listener/owlps-listenerd.c | 81 ++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e648b3..76b0e24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,12 +161,7 @@ add_subdirectory(owlps-client) ## Listener ## -if (${CMAKE_SYSTEM_NAME} STREQUAL Linux) - add_subdirectory(owlps-listener) -else() - message(WARNING - "OwlPS Listener can be built only for Linux systems") -endif() +add_subdirectory(owlps-listener) ## Positioner ## diff --git a/INSTALL.t2t b/INSTALL.t2t index 047a4e4..d07d8a8 100644 --- a/INSTALL.t2t +++ b/INSTALL.t2t @@ -3,8 +3,9 @@ Compiling and installing OwlPS = Basics = -To fully build OwlPS, you need a GNU/Linux system (see “Compiling on BSD -systems” below) with the following development libraries installed: +The preferred platform to build and run OwlPS is a GNU/Linux system (see +“Compiling on BSD systems” below) with the following development +libraries installed: - //confuse// - //pcap// @@ -95,15 +96,14 @@ configuration as explained in the previous section. = Compiling on BSD systems = -The procedure is the same as on GNU/Linux systems, but keep in mind that -OwlPS Listener is deactivated on BSD, since it still contains some -Linux-specific code. (The positive effect is that you won't have to -install libpcap, heh.) +We try to write portable code and support BSD systems as much as +possible, but OwlPS is primarily developed and tested on GNU/Linux so +there can be more bugs on BSD (please report them!). -You may also need to edit the configuration (cf. “Tweaking” above), for -example to force a specific GCC version to be used. On OpenBSD, you need -to have the CXX variable set with the ``-fPIE`` flag when calling -``cmake``: +The building procedure is the same as on GNU/Linux systems, but you may +need to edit the configuration (cf. “Tweaking” above), for example to +force a specific GCC version to be used. On OpenBSD, you need to have +the CXX variable set with the ``-fPIE`` flag when calling ``cmake``: ``` CXX="eg++ -fPIE" cmake ../owlps diff --git a/TODO.t2t b/TODO.t2t index 92137fd..e9f1986 100644 --- a/TODO.t2t +++ b/TODO.t2t @@ -141,10 +141,6 @@ Work to do in OwlPS Currently the size is corrected only for data packets. -- BSD port - - http://www.unixgarden.com/index.php/programmation/introduction-a-la-programmation-wifi-en-c-sous-netbsd - diff --git a/doc/owlps.t2t b/doc/owlps.t2t index eeca411..2fe38f3 100644 --- a/doc/owlps.t2t +++ b/doc/owlps.t2t @@ -24,10 +24,11 @@ June 2013 **OwlPS** (//Owl Positioning System//) is a positioning (localization) system based on the IEEE 802.11 radio network (Wi-Fi). It targets mainly -UNIX-like operating systems and is currently fully usable only on -GNU/Linux. Originally developped at the University of Franche-Comté -(Université de Franche-Comté, France), it is released under the terms of -the CeCILL free software license (GNU GPL-compatible). +UNIX-like operating systems and is developed and tested primarily on +GNU/Linux, but it should work on BSD platforms as well. Originally +developed at the University of Franche-Comté (Université de +Franche-Comté, France), it is released under the terms of the CeCILL +free software license (GNU GPL-compatible). OwlPS uses an infrastructure-centred architecture, which means the infrastructure does the measurements and computes the mobile terminals' @@ -127,7 +128,7 @@ revision number is not mandatory, but it is allowed. For example: - owlps-positionerd.t2t -++ Developping with OwlPS libraries ++ +++ Developing with OwlPS libraries ++ - owlps.h (Doxygen-generated documentation) - owlps-client.h (Doxygen-generated documentation) diff --git a/owlps-listener/owlps-listenerd.c b/owlps-listener/owlps-listenerd.c index ea3632a..ecec872 100644 --- a/owlps-listener/owlps-listenerd.c +++ b/owlps-listener/owlps-listenerd.c @@ -50,6 +50,11 @@ #include #include +#ifndef __GLIBC__ +# include +# include +#endif // __GLIBC__ + #include @@ -881,6 +886,14 @@ void* keep_mode_monitor(void *iface) /* * Switches the IEEE 802.11 interface 'iface' to Monitor mode. + * + * This function uses iwlib, which is Linux-specific. In case we want + * this on BSD, there is some example code there: + * http://www.unixgarden.com/index.php/gnu-linux-magazine-hs/introduction-a-la-programmation-wifi-en-c-sous-netbsd#7-exemple-n°4-activer-et-utiliser-le-monitoring-aka-rf_mon + * The thing is that we would have to switch the interface down and up + * each time, so let's hope we will never need that. But even on Linux, + * this function was only needed with the buggy ipw2200 driver (for Intel + * BG2200 chips) and it hopefully won't be needed any more. */ int iface_mode_monitor(const char *const iface) { @@ -1103,6 +1116,13 @@ void read_packet(const struct pcap_pkthdr *pkt_header, memcpy(request.cp_mac_addr_bytes, my_mac_bytes, ETHER_ADDR_LEN) ; // Capture time is in the pcap header (host-endian): owl_timeval_to_timestamp(&pkt_header->ts, &request.capture_time) ; + /* Note on the line above: on OpenBSD, the ts field of struct + * pcap_pkthdr (defined in ) is a struct bpf_timeval* instead + * of a struct timeval*. struct bpf_timeval is defined in + * /usr/include/net/bpf.h and is a clone of struct timeval with + * fixed-size fields (u_int32_t). We *could* override the warning by + * casting, but I prefer to leave it as a reminder in case something + * went wrong at some point. */ owl_hton_timestamp(&request.capture_time) ; /* Active mode */ @@ -1240,6 +1260,9 @@ void extract_packet_numbers(const u_char *pkt_data, * header of 'pkt_data'. * Returns true if the antenna signal radiotap field was found, false * otherwhise. + * + * Ideas of improvement: + * http://www.unixgarden.com/index.php/gnu-linux-magazine-hs/introduction-a-la-programmation-wifi-en-c-sous-netbsd#8-exemple-n°5-radiotap */ bool extract_radiotap_ss(const u_char *pkt_data, owl_captured_request *request) @@ -1383,6 +1406,7 @@ void display_captured_request(owl_captured_request *request, */ void get_mac_addr(const char *const iface, uint8_t mac_bytes[ETHER_ADDR_LEN]) +#ifdef linux { struct ifreq ifr; int sockfd ; @@ -1399,6 +1423,7 @@ void get_mac_addr(const char *const iface, strncpy(ifr.ifr_name, iface, IFNAMSIZ) ; + // Note: the SIOCGIFHWADDR ioctl is Linux-specific if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl(SIOCGIFHWADDR) error getting MAC address") ; @@ -1407,7 +1432,63 @@ void get_mac_addr(const char *const iface, memcpy(mac_bytes, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN) ; } +#else // linux +{ + #define HWADDR_MIB_SIZE 6 + int mib[HWADDR_MIB_SIZE] ; + int ifindex ; // iface's index + char *buf = NULL ; + size_t buflen = 0 ; + // Empty mac_bytes: + memset(mac_bytes, 0, sizeof(uint8_t) * ETHER_ADDR_LEN) ; + + ifindex = if_nametoindex(iface) ; + if (ifindex == 0) + { + perror("Cannot get interface's index to get its MAC address") ; + return ; + } + + // See sysctl(7) for more information + mib[0] = CTL_NET ; // First level = the net subtree + mib[1] = PF_ROUTE ; // Second level = route + mib[2] = 0 ; // Third level = protocol (always 0) + mib[3] = AF_LINK ; // Fourth level = address family + mib[4] = NET_RT_IFLIST ; // Fifth level = type of info + mib[5] = ifindex ; /* sysctl(7) says there is no sixth level with + * NET_RT_IFLIST, but actually it has to be the + * interface's index */ + + // Get the size of the available data + if (sysctl(mib, HWADDR_MIB_SIZE, NULL, &buflen, NULL, 0)) + { + perror("sysctl() error getting MAC address") ; + return ; + } + + buf = malloc(buflen) ; + if (! buf) + { + perror("Cannot allocate memory") ; + return ; + } + + if (sysctl(mib, HWADDR_MIB_SIZE, buf, &buflen, NULL, 0)) + perror("sysctl() error getting MAC address") ; + else + { + struct if_msghdr *ifm = (struct if_msghdr*)buf ; + struct sockaddr_dl *sdl = (struct sockaddr_dl*)(ifm + 1) ; + unsigned char *hwaddr = (unsigned char*)(LLADDR(sdl)) ; + int i ; + for (i = 0 ; i < 6 ; ++i) + mac_bytes[i] = (uint8_t)hwaddr[i] ; + } + + free(buf) ; +} +#endif // linux /*