[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.
This commit is contained in:
Matteo Cypriani 2013-06-17 11:20:58 -04:00
parent 7d3650fb5d
commit 6c1c182039
5 changed files with 98 additions and 25 deletions

View File

@ -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 ##

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -50,6 +50,11 @@
#include <netinet/ip.h>
#include <arpa/inet.h>
#ifndef __GLIBC__
# include <sys/sysctl.h>
# include <net/if_dl.h>
#endif // __GLIBC__
#include <assert.h>
@ -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 <pcap.h>) 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
/*