diff options
author | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
---|---|---|
committer | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
commit | 740b30688bd745a527f96f9116c19acb3480971a (patch) | |
tree | 2709a3f4dba11c174aa9e1ba3612e30c578e76a9 /src/transport/gnunet-helper-transport-wlan.c | |
parent | 2b81464a43485fcc8ce079fafdee7b7a171835f4 (diff) |
Imported Upstream version 0.9.3upstream/0.9.3
Diffstat (limited to 'src/transport/gnunet-helper-transport-wlan.c')
-rw-r--r-- | src/transport/gnunet-helper-transport-wlan.c | 1453 |
1 files changed, 884 insertions, 569 deletions
diff --git a/src/transport/gnunet-helper-transport-wlan.c b/src/transport/gnunet-helper-transport-wlan.c index 582df7c..363925c 100644 --- a/src/transport/gnunet-helper-transport-wlan.c +++ b/src/transport/gnunet-helper-transport-wlan.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2010, 2011 Christian Grothoff (and other contributing authors) + (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) Copyright (c) 2007, 2008, Andy Green <andy@warmcat.com> Copyright (C) 2009 Thomas d'Otreppe @@ -21,12 +21,48 @@ */ /** * @file src/transport/gnunet-helper-transport-wlan.c - * @brief wlan layer two server; must run as root (SUID will do) + * @brief mediator between the wlan interface and gnunet; must run as root (SUID will do) * This code will work under GNU/Linux only. * @author David Brodski + * @author Christian Grothoff * - * This program serves as the mediator between the wlan interface and - * gnunet + * This program will allow receiving and sending traffic from the WLAN + * interface. It will force traffic to be in 'ad-hoc' mode, use the + * proper MAC address of the WLAN interface and use a GNUnet-specific + * SSID (and a GNUnet-specific SNAP header). It only takes a single + * argument, which is the name of the WLAN interface to use. The + * program detects if the interface is not a WLAN interface and exits + * with an error in that case. + * + * Once initialized, the program will first send a 'struct + * GNUNET_TRANSPORT_WLAN_HelperControlMessage' to 'stdout'. That + * message contains the MAC address of the WLAN interface. It will + * then read messages from the WLAN interface and send them together + * with performance information as 'struct + * GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage' messages to 'stdout'. + * Furthermore, it will read a stream of messages from 'stdin' that + * have the format from 'struct + * GNUNET_TRANSPORT_WLAN_RadiotapSendMessage'. Those messages will + * then be sent via the WLAN interface; however, the sender MAC + * address will be forced to be the correct address from our WLAN + * card. If 'stdin' closes, receiving from the WLAN interface will + * continue. If 'stdout' causes a SIGPIPE, the process dies from the + * signal. Errors cause an error message to be reported to 'stderr', + * in most cases the process also exits (with status code '1'). The + * program never terminates normally; it is safe to kill the + * process with SIGTERM or SIGKILL at any time. + * + * Since it uses RAW sockets, the binary must be installed SUID or run + * as 'root'. In order to keep the security risk of the resulting + * SUID binary minimal, the program ONLY opens the RAW socket with + * root privileges, then drops them and only then starts to process + * command line arguments. The code also does not link against any + * shared libraries (except libc) and is strictly minimal (except for + * checking for errors). The following list of people have reviewed + * this code and considered it safe since the last modification (if + * you reviewed it, please have your name added to the list): + * + * - Christian Grothoff (Apr 3rd 2012) */ /*- @@ -70,10 +106,10 @@ * Modifications to fit into the linux IEEE 802.11 stack, * Mike Kershaw (dragorn@kismetwireless.net) */ - -/** +/* * parts taken from aircrack-ng, parts changend. */ + #define _GNU_SOURCE #include <sys/socket.h> #include <sys/ioctl.h> @@ -102,183 +138,429 @@ #include "gnunet_protocols.h" #include "plugin_transport_wlan.h" +/** + * Packet format type for the messages we receive from + * the kernel. This is for plain messages (with no + * performance information included). + */ #define ARPHRD_IEEE80211 801 + +/** + * Packet format type for the messages we receive from + * the kernel. This is for the PRISM format. + */ #define ARPHRD_IEEE80211_PRISM 802 -#define ARPHRD_IEEE80211_FULL 803 /** - * size of 802.11 address + * Packet format type for the messages we receive from + * the kernel. This is for messages with a + * 'struct Ieee80211RadiotapHeader' (see below). */ -#define IEEE80211_ADDR_LEN 6 +#define ARPHRD_IEEE80211_FULL 803 + /** - * Maximum size of a message allowed in either direction. + * Maximum size of a message allowed in either direction + * (used for our receive and sent buffers). */ #define MAXLINE 4096 -#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK 0x80000000 +/* ********* structure of messages of type ARPHRD_IEEE80211_PRISM *********** */ -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT __le64 microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS __le16 see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data - * - * Number of unicast retries a transmitted frame used. - * +/** + * Device name length in PRISM frames. + * (In the kernel, this is "WLAN_DEVNAMELEN_MAX") + */ +#define PRISM_DEVICE_NAME_LENGTH 16 + +/** + * Monitor Frame (indicator that we have a 'struct PrismHeader'). + */ +#define PRISM_MSGCODE_MONITOR 0x0041 + +/** + * Mac time element. In micro-seconds. + * Drivers appear to use a 64bit counter to hold mactime internal + * the then fill the prism header with the lower 32 bits + */ +#define PRISM_DID_MACTIME 0x2041 + +/** + * Channel element + */ +#define PRISM_DID_CHANNEL 0x3041 + +/** + * Signal element. Should be the signal strength in dbm, some people + * suggest that instead "100 - (strength in dbm)" is used (to make this + * a positive integer). + */ +#define PRISM_DID_SIGNAL 0x6041 + +/** + * Noise element + */ +#define PRISM_DID_NOISE 0x7041 + +/** + * Rate element, in units/multiples of 500Khz + */ +#define PRISM_DID_RATE 0x8041 + + +/** + * Value is set (supplied) + */ +#define PRISM_STATUS_OK 0 + +/** + * Value not supplied. + */ +#define PRISM_STATUS_NO_VALUE 1 + + +/** + * Values in the 'struct PrismHeader'. All in host byte order (!). + */ +struct PrismValue +{ + /** + * This has a different ID for each parameter, see + * PRISM_DID_* constants. + */ + uint32_t did; + + /** + * See PRISM_STATUS_*-constants. Note that they are unusual: 0 = set; 1 = not set + */ + uint16_t status; + + /** + * length of data (which is always a uint32_t, but presumably this can be used + * to specify that fewer bytes are used (with values in 'len' from 0-4). We + * ignore this field. + */ + uint16_t len; + + /** + * The data value + */ + uint32_t data; + +} __attribute__ ((packed)); + + +/** + * Prism header format ('struct p80211msg' in Linux). All in host byte order (!). + */ +struct PrismHeader +{ + /** + * We expect this to be a PRISM_MSGCODE_*. + */ + uint32_t msgcode; + + /** + * The length of the entire header. + */ + uint32_t msglen; + + /** + * Name of the device that captured the packet. + */ + char devname[PRISM_DEVICE_NAME_LENGTH]; + + /* followed by 'struct PrismValue's. Documentation suggests that these + are typically the hosttime, mactime, channel, rssi, sq, signal, noise, + rate, istx and frmlen values, but documentation is sparse. So we + will use the 'did' fields to find out what we actually got. */ + +} __attribute__ ((packed)); + + +/* ****** end of structure of messages of type ARPHRD_IEEE80211_PRISM ******* */ + +/* ********** structure of messages of type ARPHRD_IEEE80211_FULL *********** */ + +/** + * Bits in the 'it_present' bitmask from the 'struct + * Ieee80211RadiotapHeader'. For each value, we give the name, data + * type, unit and then a description below. Note that the actual size + * of the extension can be bigger as arguments must be padded so that + * args of a given length must begin at a boundary of that length. + * However, note that compound args are allowed (eg, 2 x uint16_t for + * IEEE80211_RADIOTAP_CHANNEL) so total argument length is not a + * reliable indicator of alignment requirement. See also + * 'man 9 ieee80211_radiotap'. */ enum RadiotapType { + + /** + * IEEE80211_RADIOTAP_TSFT __le64 microseconds + * + * Value in microseconds of the MAC's 64-bit 802.11 Time + * Synchronization Function timer when the first bit of the + * MPDU arrived at the MAC. For received frames, only. + */ IEEE80211_RADIOTAP_TSFT = 0, + + /** + * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap + * + * Properties of transmitted and received frames. See flags + * defined below. + */ IEEE80211_RADIOTAP_FLAGS = 1, + + /** + * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s + * + * Tx/Rx data rate + */ IEEE80211_RADIOTAP_RATE = 2, + + /** + * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap + * + * Tx/Rx frequency in MHz, followed by flags (see below). + */ IEEE80211_RADIOTAP_CHANNEL = 3, + /** + * IEEE80211_RADIOTAP_FHSS __le16 see below + * + * For frequency-hopping radios, the hop set (first byte) + * and pattern (second byte). + */ IEEE80211_RADIOTAP_FHSS = 4, + + /** + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from + * one milliwatt (dBm) + * + * RF signal power at the antenna, decibel difference from + * one milliwatt. + */ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + + /** + * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from + * one milliwatt (dBm) + * + * RF noise power at the antenna, decibel difference from one + * milliwatt. + */ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + + /** + * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless + * + * Quality of Barker code lock. Unitless. Monotonically + * nondecreasing with "better" lock strength. Called "Signal + * Quality" in datasheets. (Is there a standard way to measure + * this?) + */ IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + + /** + * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless + * + * Transmit power expressed as unitless distance from max + * power set at factory calibration. 0 is max power. + * Monotonically nondecreasing with lower power levels. + */ IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + + /** + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB) + * + * Transmit power expressed as decibel distance from max power + * set at factory calibration. 0 is max power. Monotonically + * nondecreasing with lower power levels. + */ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + + /** + * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from + * one milliwatt (dBm) + * + * Transmit power expressed as dBm (decibels from a 1 milliwatt + * reference). This is the absolute power level measured at + * the antenna port. + */ IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + + /** + * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index + * + * Unitless indication of the Rx/Tx antenna for this packet. + * The first antenna is antenna 0. + */ IEEE80211_RADIOTAP_ANTENNA = 11, + + /** + * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) + * + * RF signal power at the antenna, decibel difference from an + * arbitrary, fixed reference. + */ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + + /** + * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) + * + * RF noise power at the antenna, decibel difference from an + * arbitrary, fixed reference point. + */ IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + + /** + * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap + * + * Properties of received frames. See flags defined below. + */ IEEE80211_RADIOTAP_RX_FLAGS = 14, + + /** + * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap + * + * Properties of transmitted frames. See flags defined below. + */ IEEE80211_RADIOTAP_TX_FLAGS = 15, + + /** + * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data + * + * Number of rts retries a transmitted frame used. + */ IEEE80211_RADIOTAP_RTS_RETRIES = 16, + + /** + * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data + * + * Number of unicast retries a transmitted frame used. + */ IEEE80211_RADIOTAP_DATA_RETRIES = 17, + + /** + * Extension bit, used to indicate that more bits are needed for + * the bitmask. + */ IEEE80211_RADIOTAP_EXT = 31 }; -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ -#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* frame should not be ACKed */ -#define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010 /* sequence number handled - * by userspace */ +/** + * Bitmask indicating an extension of the bitmask is used. + * (Mask corresponding to IEEE80211_RADIOTAP_EXT). + */ +#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK (1 << IEEE80211_RADIOTAP_EXT) + + + +/** + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. + * + * Frame was sent/received during CFP (Contention Free Period) + */ +#define IEEE80211_RADIOTAP_F_CFP 0x01 +/** + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. + * + * Frame was sent/received with short preamble + */ +#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 + +/** + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. + * + * Frame was sent/received with WEP encryption + */ +#define IEEE80211_RADIOTAP_F_WEP 0x04 /** - * A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. + * Frame was sent/received with fragmentation + */ +#define IEEE80211_RADIOTAP_F_FRAG 0x08 + +/** + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. + * + * Frame includes FCS (CRC at the end that needs to be removeD). + */ +#define IEEE80211_RADIOTAP_F_FCS 0x10 + +/** + * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get + * as part of a 'struct Ieee80211RadiotapHeader' extension + * if the IEEE80211_RADIOTAP_FLAGS bit is set in + * 'it_present'). The radiotap flags are an 8-bit field. + * + * Frame has padding between 802.11 header and payload + * (to 32-bit boundary) + */ +#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 + + +/** + * For IEEE80211_RADIOTAP_RX_FLAGS: + * frame failed crc check + */ +#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 + +/** + * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): + * failed due to excessive retries + */ +#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 + +/** + * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): + * used cts 'protection' + */ +#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 + +/** + * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): + * used rts/cts handshake + */ +#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 + +/** + * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): + * frame should not be ACKed + */ +#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 + +/** + * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): + * sequence number handled by userspace + */ +#define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010 + + +/** + * Generic header for radiotap messages (receiving and sending). A + * bit mask (it_present) determines which specific records follow. * * I am trying to describe precisely what the application programmer * should expect in the following, and for that reason I tell the @@ -290,13 +572,17 @@ enum RadiotapType * The radio capture header precedes the 802.11 header. * All data in the header is little endian on all platforms. */ -struct ieee80211_radiotap_header +struct Ieee80211RadiotapHeader { /** * Version 0. Only increases for drastic changes, introduction of * compatible new fields does not count. */ uint8_t it_version; + + /** + * Padding. Set to 0. + */ uint8_t it_pad; /** @@ -313,89 +599,106 @@ struct ieee80211_radiotap_header uint32_t it_present; }; + /** - * + * Format of the header we need to prepend to messages to be sent to the + * Kernel. */ -struct RadioTapheader +struct RadiotapTransmissionHeader { + /** - * + * First we begin with the 'generic' header we also get when receiving + * messages. */ - struct ieee80211_radiotap_header header; + struct Ieee80211RadiotapHeader header; /** - * + * Transmission rate (we use 0, kernel makes up its mind anyway). */ uint8_t rate; /** - * + * Padding (we use 0). There is a requirement to pad args, so that + * args of a given length must begin at a boundary of that length. + * As our next argument is the 'it_len' with 2 bytes, we need 1 byte + * of padding. */ uint8_t pad1; /** - * + * Transmission flags from on the IEEE80211_RADIOTAP_F_TX_* constant family. */ uint16_t txflags; + }; +/** + * The above 'struct RadiotapTransmissionHeader' should have the + * following value for 'header.it_present' based on the presence of + * the 'rate' and 'txflags' in the overall struct. + */ +#define IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK ((1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_TX_FLAGS)) + + /** - * IO buffer used for buffering data in transit (to wireless or to stdout). + * struct Ieee80211RadiotapHeaderIterator - tracks walk through present radiotap arguments + * in the radiotap header. Used when we parse radiotap packets received from the kernel. */ -struct SendBuffer +struct Ieee80211RadiotapHeaderIterator { /** - * How many bytes of data are stored in 'buf' for transmission right now? - * Data always starts at offset 0 and extends to 'size'. + * pointer to the radiotap header we are walking through */ - size_t size; + const struct Ieee80211RadiotapHeader *rtheader; /** - * How many bytes that were stored in 'buf' did we already write to the - * destination? Always smaller than 'size'. + * pointer to current radiotap arg */ - size_t pos; - + const uint8_t *this_arg; + /** - * Buffered data; twice the maximum allowed message size as we add some - * headers. + * internal next argument pointer */ - char buf[MAXLINE * 2]; -}; + const uint8_t *arg; -/** - * Buffer for data read from stdin to be transmitted to the wirless card. - */ -static struct SendBuffer write_pout; + /** + * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used). + */ + const uint32_t *next_bitmap; -/** - * Buffer for data read from the wireless card to be transmitted to stdout. - */ -static struct SendBuffer write_std; + /** + * length of radiotap header in host byte ordering + */ + size_t max_length; + /** + * internal shifter for current uint32_t bitmap, (it_present in host byte order), + * If bit 0 is set, the 'arg_index' argument is present. + */ + uint32_t bitmap_shifter; -GNUNET_NETWORK_STRUCT_BEGIN + /** + * IEEE80211_RADIOTAP_... index of current arg + */ + unsigned int this_arg_index; + + /** + * internal next argument index + */ + unsigned int arg_index; + +}; -/** - * generic definitions for IEEE 802.11 frames - */ -struct ieee80211_frame -{ - uint8_t i_fc[2]; - uint8_t i_dur[2]; - uint8_t i_addr1[IEEE80211_ADDR_LEN]; - uint8_t i_addr2[IEEE80211_ADDR_LEN]; - uint8_t i_addr3[IEEE80211_ADDR_LEN]; - uint8_t i_seq[2]; - /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ - /* see below */ -} GNUNET_PACKED; -GNUNET_NETWORK_STRUCT_END +/* ************** end of structure of ARPHRD_IEEE80211_FULL ************** */ + +/* ************************** our globals ******************************* */ /** - * struct for storing the information of the hardware + * struct for storing the information of the hardware. There is only + * one of these. */ struct HardwareInfos { @@ -424,56 +727,48 @@ struct HardwareInfos /** - * struct ieee80211_radiotap_iterator - tracks walk through present radiotap arguments - * in the radiotap header. + * IO buffer used for buffering data in transit (to wireless or to stdout). */ -struct ieee80211_radiotap_iterator +struct SendBuffer { /** - * pointer to the radiotap header we are walking through - */ - const struct ieee80211_radiotap_header *rtheader; - - /** - * length of radiotap header in cpu byte ordering - */ - size_t max_length; - - /** - * IEEE80211_RADIOTAP_... index of current arg + * How many bytes of data are stored in 'buf' for transmission right now? + * Data always starts at offset 0 and extends to 'size'. */ - unsigned int this_arg_index; + size_t size; /** - * pointer to current radiotap arg + * How many bytes that were stored in 'buf' did we already write to the + * destination? Always smaller than 'size'. */ - uint8_t *this_arg; - + size_t pos; + /** - * internal next argument index + * Buffered data; twice the maximum allowed message size as we add some + * headers. */ - unsigned int arg_index; + char buf[MAXLINE * 2]; +}; - /** - * internal next argument pointer - */ - uint8_t *arg; - /** - * internal pointer to next present uint32_t - */ - uint32_t *next_bitmap; +/** + * Buffer for data read from stdin to be transmitted to the wirless card. + */ +static struct SendBuffer write_pout; - /** - * internal shifter for curr uint32_t bitmap, b0 set == arg present - */ - uint32_t bitmap_shifter; -}; +/** + * Buffer for data read from the wireless card to be transmitted to stdout. + */ +static struct SendBuffer write_std; -/* specialized version of server_mst.c begins here */ +/* *********** specialized version of server_mst.c begins here ********** */ +/** + * To what multiple do we align messages? 8 byte should suffice for everyone + * for now. + */ #define ALIGN_FACTOR 8 /** @@ -533,7 +828,6 @@ struct MessageStreamTokenizer }; - /** * Create a message stream tokenizer. * @@ -549,10 +843,16 @@ mst_create (MessageTokenizerCallback cb, ret = malloc (sizeof (struct MessageStreamTokenizer)); if (NULL == ret) + { + fprintf (stderr, "Failed to allocate buffer for tokenizer\n"); exit (1); + } ret->hdr = malloc (MIN_BUFFER_SIZE); if (NULL == ret->hdr) - exit (2); + { + fprintf (stderr, "Failed to allocate buffer for alignment\n"); + exit (1); + } ret->curr_buf = MIN_BUFFER_SIZE; ret->cb = cb; ret->cb_cls = cb_cls; @@ -613,8 +913,9 @@ do_align: want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { - // GNUNET_break_op (0); - return GNUNET_SYSERR; + fprintf (stderr, + "Received invalid message from stdin\n"); + exit (1); } if (mst->curr_buf - mst->off < want) { @@ -627,7 +928,10 @@ do_align: { mst->hdr = realloc (mst->hdr, want); if (NULL == mst->hdr) - exit (3); + { + fprintf (stderr, "Failed to allocate buffer for alignment\n"); + exit (1); + } ibuf = (char *) mst->hdr; mst->curr_buf = want; } @@ -666,9 +970,9 @@ do_align: want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { - // GNUNET_break_op (0); - mst->off = 0; - return GNUNET_SYSERR; + fprintf (stderr, + "Received invalid message from stdin\n"); + exit (1); } if (size < want) break; /* or not, buffer incomplete, so copy to private buffer... */ @@ -689,11 +993,19 @@ do_align: { mst->hdr = realloc (mst->hdr, size + mst->pos); if (NULL == mst->hdr) - exit (4); + { + fprintf (stderr, "Failed to allocate buffer for alignment\n"); + exit (1); + } ibuf = (char *) mst->hdr; mst->curr_buf = size + mst->pos; } - // GNUNET_assert (mst->pos + size <= mst->curr_buf); + if (mst->pos + size > mst->curr_buf) + { + fprintf (stderr, + "Assertion failed\n"); + exit (1); + } memcpy (&ibuf[mst->pos], buf, size); mst->pos += size; } @@ -713,16 +1025,16 @@ mst_destroy (struct MessageStreamTokenizer *mst) free (mst); } -/* end of server_mst.c copy */ - +/* ***************** end of server_mst.c clone ***************** **/ +/* ************** code for handling of ARPHRD_IEEE80211_FULL ************** */ /** * Radiotap header iteration * * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator - * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) + * struct Ieee80211RadiotapHeaderIterator (no need to init the struct beforehand) * then loop calling __ieee80211_radiotap_iterator_next()... it returns -1 * if there are no more args in the header, or the next argument type index * that is present. The iterator's this_arg member points to the start of the @@ -736,9 +1048,8 @@ mst_destroy (struct MessageStreamTokenizer *mst) * @return 0 on success, -1 on error */ static int -ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator, - const struct ieee80211_radiotap_header - *radiotap_header, +ieee80211_radiotap_iterator_init (struct Ieee80211RadiotapHeaderIterator *iterator, + const struct Ieee80211RadiotapHeader *radiotap_header, size_t max_length) { if ( (iterator == NULL) || @@ -750,26 +1061,22 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator, return -1; /* sanity check for allowed length and radiotap length field */ - if ( (max_length < sizeof (struct ieee80211_radiotap_header)) || + if ( (max_length < sizeof (struct Ieee80211RadiotapHeader)) || (max_length < (GNUNET_le16toh (radiotap_header->it_len))) ) return -1; + memset (iterator, 0, sizeof (struct Ieee80211RadiotapHeaderIterator)); iterator->rtheader = radiotap_header; iterator->max_length = GNUNET_le16toh (radiotap_header->it_len); - iterator->arg_index = 0; iterator->bitmap_shifter = GNUNET_le32toh (radiotap_header->it_present); - iterator->arg = - ((uint8_t *) radiotap_header) + sizeof (struct ieee80211_radiotap_header); - iterator->this_arg = 0; + iterator->arg = ((uint8_t *) radiotap_header) + sizeof (struct Ieee80211RadiotapHeader); /* find payload start allowing for extended bitmap(s) */ - if ((iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)) + if (0 != (iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)) { - while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & - IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK) + while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK) { iterator->arg += sizeof (uint32_t); - /* * check for insanity where the present bitmaps * keep claiming to extend up to or even beyond the @@ -791,7 +1098,7 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator, /** - * @brief ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg + * Returns the next radiotap parser iterator arg. * * This function returns the next radiotap arg index (IEEE80211_RADIOTAP_...) * and sets iterator->this_arg to point to the payload for the arg. It takes @@ -800,13 +1107,11 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator, * format. * * @param iterator: radiotap_iterator to move to next arg (if any) - * * @return next present arg index on success or -1 if no more or error */ static int -ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *iterator) +ieee80211_radiotap_iterator_next (struct Ieee80211RadiotapHeaderIterator *iterator) { - /* * small length lookup table for all radiotap types we heard of * starting from b0 in the bitmap, so we can walk the payload @@ -851,120 +1156,103 @@ ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *iterator) * for every radiotap entry we can at * least skip (by knowing the length)... */ - while (iterator->arg_index < sizeof (rt_sizes)) { - int hit = 0; - - if (!(iterator->bitmap_shifter & 1)) - goto next_entry; /* arg not present */ - - /* - * arg is present, account for alignment padding - * 8-bit args can be at any alignment - * 16-bit args must start on 16-bit boundary - * 32-bit args must start on 32-bit boundary - * 64-bit args must start on 64-bit boundary - * - * note that total arg size can differ from alignment of - * elements inside arg, so we use upper nybble of length - * table to base alignment on - * - * also note: these alignments are ** relative to the - * start of the radiotap header **. There is no guarantee - * that the radiotap header itself is aligned on any - * kind of boundary. - */ - - if ((((void *) iterator->arg) - - ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4) - - 1)) - iterator->arg_index += - (rt_sizes[iterator->arg_index] >> 4) - - ((((void *) iterator->arg) - - ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> - 4) - 1)); - - /* - * this is what we will return to user, but we need to - * move on first so next call has something fresh to test - */ - - iterator->this_arg_index = iterator->arg_index; - iterator->this_arg = iterator->arg; - hit = 1; - - /* internally move on the size of this arg */ - - iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; - - /* - * check for insanity where we are given a bitmap that - * claims to have more arg content than the length of the - * radiotap section. We will normally end up equalling this - * max_length on the last arg, never exceeding it. - */ - - if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > - iterator->max_length) - return -1; + int hit = (0 != (iterator->bitmap_shifter & 1)); -next_entry: + if (hit) + { + unsigned int wanted_alignment; + unsigned int unalignment; + /* + * arg is present, account for alignment padding + * 8-bit args can be at any alignment + * 16-bit args must start on 16-bit boundary + * 32-bit args must start on 32-bit boundary + * 64-bit args must start on 64-bit boundary + * + * note that total arg size can differ from alignment of + * elements inside arg, so we use upper nybble of length table + * to base alignment on. First, 'wanted_alignment' is set to be + * 1 for 8-bit, 2 for 16-bit, 4 for 32-bit and 8 for 64-bit + * arguments. Then, we calculate the 'unalignment' (how many + * bytes we are over by taking the difference of 'arg' and the + * overall starting point modulo the desired alignment. As + * desired alignments are powers of two, we can do modulo with + * binary "&" (and also avoid the possibility of a division by + * zero if the 'rt_sizes' table contains bogus entries). + * + * also note: these alignments are relative to the start of the + * radiotap header. There is no guarantee that the radiotap + * header itself is aligned on any kind of boundary, thus we + * need to really look at the delta here. + */ + wanted_alignment = rt_sizes[iterator->arg_index] >> 4; + unalignment = (((void *) iterator->arg) - ((void *) iterator->rtheader)) & (wanted_alignment - 1); + if (0 != unalignment) + { + /* need padding (by 'wanted_alignment - unalignment') */ + iterator->arg_index += wanted_alignment - unalignment; + } + + /* + * this is what we will return to user, but we need to + * move on first so next call has something fresh to test + */ + iterator->this_arg_index = iterator->arg_index; + iterator->this_arg = iterator->arg; + + /* internally move on the size of this arg (using lower nybble from + the table) */ + iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; + + /* + * check for insanity where we are given a bitmap that + * claims to have more arg content than the length of the + * radiotap section. We will normally end up equalling this + * max_length on the last arg, never exceeding it. + */ + if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > iterator->max_length) + return -1; + } + /* Now, move on to next bit / next entry */ iterator->arg_index++; - if (((iterator->arg_index & 31) == 0)) + + if (0 == (iterator->arg_index % 32)) { /* completed current uint32_t bitmap */ - if (iterator->bitmap_shifter & 1) + if (0 != (iterator->bitmap_shifter & 1)) { - /* b31 was set, there is more */ - /* move to next uint32_t bitmap */ + /* bit 31 was set, there is more; move to next uint32_t bitmap */ iterator->bitmap_shifter = GNUNET_le32toh (*iterator->next_bitmap); iterator->next_bitmap++; } else { - /* no more bitmaps: end */ + /* no more bitmaps: end (by setting arg_index to high, unsupported value) */ iterator->arg_index = sizeof (rt_sizes); } } else - { /* just try the next bit */ + { + /* just try the next bit (while loop will move on) */ iterator->bitmap_shifter >>= 1; } /* if we found a valid arg earlier, return it now */ - if (hit) return iterator->this_arg_index; - } - /* we don't know how to handle any more args, we're done */ + /* we don't know how to handle any more args (or there are no more), + so we're done (this is not an error) */ return -1; } /** - * Return the channel from the frequency (in Mhz) - * @param frequency of the channel - * @return number of the channel - */ -static int -get_channel_from_frequency (int frequency) -{ - if (frequency >= 2412 && frequency <= 2472) - return (frequency - 2407) / 5; - if (frequency == 2484) - return 14; - if (frequency >= 5000 && frequency <= 6100) - return (frequency - 5000) / 5; - return -1; -} - - -/** - * function to calculate the crc, the start of the calculation + * Calculate crc32, the start of the calculation * * @param buf buffer to calc the crc * @param len len of the buffer @@ -1049,7 +1337,7 @@ calc_crc_osdep (const unsigned char *buf, size_t len) /** - * Function to calculate and check crc of the wlan packet + * Calculate and check crc of the wlan packet * * @param buf buffer of the packet, with len + 4 bytes of data, * the last 4 bytes being the checksum @@ -1070,6 +1358,30 @@ check_crc_buf_osdep (const unsigned char *buf, size_t len) } +/* ************end of code for handling of ARPHRD_IEEE80211_FULL ************** */ + + +/* ************beginning of code for reading packets from kernel ************** */ + +/** + * Return the channel from the frequency (in Mhz) + * + * @param frequency of the channel + * @return number of the channel + */ +static int +get_channel_from_frequency (int32_t frequency) +{ + if (frequency >= 2412 && frequency <= 2472) + return (frequency - 2407) / 5; + if (frequency == 2484) + return 14; + if (frequency >= 5000 && frequency <= 6100) + return (frequency - 5000) / 5; + return -1; +} + + /** * Get the channel used by our WLAN interface. * @@ -1080,46 +1392,46 @@ static int linux_get_channel (const struct HardwareInfos *dev) { struct iwreq wrq; - int fd; - int frequency; - int chan; + int32_t frequency; memset (&wrq, 0, sizeof (struct iwreq)); strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ); - fd = dev->fd_raw; - if (0 > ioctl (fd, SIOCGIWFREQ, &wrq)) + if (0 > ioctl (dev->fd_raw, SIOCGIWFREQ, &wrq)) return -1; - - frequency = wrq.u.freq.m; + frequency = wrq.u.freq.m; /* 'iw_freq' defines 'm' as '__s32', so we keep it signed */ if (100000000 < frequency) frequency /= 100000; else if (1000000 < frequency) frequency /= 1000; if (1000 < frequency) - chan = get_channel_from_frequency (frequency); - else - chan = frequency; - return chan; + return get_channel_from_frequency (frequency); + return frequency; } /** - * function to read from a wlan card + * Read from the raw socket (the wlan card), parse the packet and + * put the result into the buffer for transmission to 'stdout'. + * * @param dev pointer to the struct of the wlan card - * @param buf buffer to read to + * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame', + * followed by the actual payload * @param buf_size size of the buffer - * @param ri radiotap_rx info - * @return size read from the buffer + * @param ri where to write radiotap_rx info + * @return number of bytes written to 'buf' */ static ssize_t -linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size, - struct Radiotap_rx *ri) +linux_read (struct HardwareInfos *dev, + unsigned char *buf, size_t buf_size, + struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri) { unsigned char tmpbuf[buf_size]; ssize_t caplen; - int n, got_signal, got_noise, got_channel, fcs_removed; - - n = got_signal = got_noise = got_channel = fcs_removed = 0; + size_t n; + int got_signal = 0; + int got_noise = 0; + int got_channel = 0; + int fcs_removed = 0; caplen = read (dev->fd_raw, tmpbuf, buf_size); if (0 > caplen) @@ -1130,171 +1442,181 @@ linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size, return -1; } - memset (buf, 0, buf_size); - memset (ri, 0, sizeof (*ri)); - + memset (ri, 0, sizeof (*ri)); switch (dev->arptype_in) { case ARPHRD_IEEE80211_PRISM: - { - /* skip the prism header */ - if (tmpbuf[7] == 0x40) { - /* prism54 uses a different format */ - ri->ri_power = tmpbuf[0x33]; - ri->ri_noise = *(unsigned int *) (tmpbuf + 0x33 + 12); - ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x33 + 24)) * 500000; - got_signal = 1; - got_noise = 1; - n = 0x40; - } - else - { - ri->ri_mactime = *(uint64_t *) (tmpbuf + 0x5C - 48); - ri->ri_channel = *(unsigned int *) (tmpbuf + 0x5C - 36); - ri->ri_power = *(unsigned int *) (tmpbuf + 0x5C); - ri->ri_noise = *(unsigned int *) (tmpbuf + 0x5C + 12); - ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x5C + 24)) * 500000; - got_channel = 1; - got_signal = 1; - got_noise = 1; - n = *(int *) (tmpbuf + 4); + const struct PrismHeader *ph; + + ph = (const struct PrismHeader*) tmpbuf; + n = ph->msglen; + if ( (n < 8) || (n >= caplen) ) + return 0; /* invalid format */ + if ( (PRISM_MSGCODE_MONITOR == ph->msgcode) && + (n >= sizeof (struct PrismHeader)) ) + { + const char *pos; + size_t left; + struct PrismValue pv; + + left = n - sizeof (struct PrismHeader); + pos = (const char *) &ph[1]; + while (left > sizeof (struct PrismValue)) + { + left -= sizeof (struct PrismValue); + memcpy (&pv, pos, sizeof (struct PrismValue)); + pos += sizeof (struct PrismValue); + + switch (pv.did) + { + case PRISM_DID_NOISE: + if (PRISM_STATUS_OK == pv.status) + { + ri->ri_noise = pv.data; + got_noise = 1; + } + break; + case PRISM_DID_RATE: + if (PRISM_STATUS_OK == pv.status) + ri->ri_rate = pv.data * 500000; + break; + case PRISM_DID_CHANNEL: + if (PRISM_STATUS_OK == pv.status) + { + ri->ri_channel = pv.data; + got_channel = 1; + } + break; + case PRISM_DID_MACTIME: + if (PRISM_STATUS_OK == pv.status) + ri->ri_mactime = pv.data; + break; + case PRISM_DID_SIGNAL: + if (PRISM_STATUS_OK == pv.status) + { + ri->ri_power = pv.data; + got_signal = 1; + } + break; + } + } + } + if ( (n < 8) || (n >= caplen) ) + return 0; /* invalid format */ } - - if ( (n < 8) || (n >= caplen) ) - return 0; - } break; - case ARPHRD_IEEE80211_FULL: - { - struct ieee80211_radiotap_iterator iterator; - struct ieee80211_radiotap_header *rthdr; - - rthdr = (struct ieee80211_radiotap_header *) tmpbuf; - - if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen)) - return 0; - - /* go through the radiotap arguments we have been given - * by the driver - */ - - while (ieee80211_radiotap_iterator_next (&iterator) >= 0) { - - switch (iterator.this_arg_index) + struct Ieee80211RadiotapHeaderIterator iterator; + struct Ieee80211RadiotapHeader *rthdr; + + memset (&iterator, 0, sizeof (iterator)); + rthdr = (struct Ieee80211RadiotapHeader *) tmpbuf; + n = GNUNET_le16toh (rthdr->it_len); + if ( (n < sizeof (struct Ieee80211RadiotapHeader)) || (n >= caplen)) + return 0; /* invalid 'it_len' */ + if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen)) + return 0; + /* go through the radiotap arguments we have been given by the driver */ + while (0 <= ieee80211_radiotap_iterator_next (&iterator)) { - - case IEEE80211_RADIOTAP_TSFT: - ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg)); - break; - - case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: - if (!got_signal) - { - if (*iterator.this_arg < 127) - ri->ri_power = *iterator.this_arg; - else - ri->ri_power = *iterator.this_arg - 255; - - got_signal = 1; - } - break; - - case IEEE80211_RADIOTAP_DB_ANTSIGNAL: - if (!got_signal) - { - if (*iterator.this_arg < 127) - ri->ri_power = *iterator.this_arg; - else - ri->ri_power = *iterator.this_arg - 255; - - got_signal = 1; - } - break; - - case IEEE80211_RADIOTAP_DBM_ANTNOISE: - if (!got_noise) - { - if (*iterator.this_arg < 127) - ri->ri_noise = *iterator.this_arg; - else - ri->ri_noise = *iterator.this_arg - 255; - - got_noise = 1; - } - break; - - case IEEE80211_RADIOTAP_DB_ANTNOISE: - if (!got_noise) - { - if (*iterator.this_arg < 127) - ri->ri_noise = *iterator.this_arg; - else - ri->ri_noise = *iterator.this_arg - 255; - - got_noise = 1; - } - break; - - case IEEE80211_RADIOTAP_ANTENNA: - ri->ri_antenna = *iterator.this_arg; - break; - - case IEEE80211_RADIOTAP_CHANNEL: - ri->ri_channel = *iterator.this_arg; - got_channel = 1; - break; - - case IEEE80211_RADIOTAP_RATE: - ri->ri_rate = (*iterator.this_arg) * 500000; - break; - - case IEEE80211_RADIOTAP_FLAGS: - /* is the CRC visible at the end? - * remove - */ - if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) - { - fcs_removed = 1; - caplen -= 4; - } - - if (*iterator.this_arg & IEEE80211_RADIOTAP_F_RX_BADFCS) - return (0); - - break; - } - } - n = GNUNET_le16toh (rthdr->it_len); - if (n <= 0 || n >= caplen) - return 0; - } + switch (iterator.this_arg_index) + { + case IEEE80211_RADIOTAP_TSFT: + ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg)); + break; + case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: + if (!got_signal) + { + ri->ri_power = * ((int8_t*) iterator.this_arg); + got_signal = 1; + } + break; + case IEEE80211_RADIOTAP_DB_ANTSIGNAL: + if (!got_signal) + { + ri->ri_power = * ((int8_t*) iterator.this_arg); + got_signal = 1; + } + break; + case IEEE80211_RADIOTAP_DBM_ANTNOISE: + if (!got_noise) + { + ri->ri_noise = * ((int8_t*) iterator.this_arg); + got_noise = 1; + } + break; + case IEEE80211_RADIOTAP_DB_ANTNOISE: + if (!got_noise) + { + ri->ri_noise = * ((int8_t*) iterator.this_arg); + got_noise = 1; + } + break; + case IEEE80211_RADIOTAP_ANTENNA: + ri->ri_antenna = *iterator.this_arg; + break; + case IEEE80211_RADIOTAP_CHANNEL: + ri->ri_channel = *iterator.this_arg; + got_channel = 1; + break; + case IEEE80211_RADIOTAP_RATE: + ri->ri_rate = (*iterator.this_arg) * 500000; + break; + case IEEE80211_RADIOTAP_FLAGS: + { + uint8_t flags = *iterator.this_arg; + /* is the CRC visible at the end? if so, remove */ + if (0 != (flags & IEEE80211_RADIOTAP_F_FCS)) + { + fcs_removed = 1; + caplen -= sizeof (uint32_t); + } + break; + } + case IEEE80211_RADIOTAP_RX_FLAGS: + { + uint16_t flags = ntohs (* ((uint16_t *) iterator.this_arg)); + if (0 != (flags & IEEE80211_RADIOTAP_F_RX_BADFCS)) + return 0; + } + break; + } /* end of 'switch' */ + } /* end of the 'while' loop */ + } break; case ARPHRD_IEEE80211: - /* do nothing? */ + n = 0; /* no header */ break; default: - errno = ENOTSUP; + errno = ENOTSUP; /* unsupported format */ return -1; } - caplen -= n; + if (! got_channel) + ri->ri_channel = linux_get_channel (dev); - //detect fcs at the end, even if the flag wasn't set and remove it - if ((0 == fcs_removed) && (0 == check_crc_buf_osdep (tmpbuf + n, caplen - 4))) + /* detect CRC32 at the end, even if the flag wasn't set and remove it */ + if ( (0 == fcs_removed) && + (0 == check_crc_buf_osdep (tmpbuf + n, caplen - sizeof (uint32_t))) ) { - caplen -= 4; + /* NOTE: this heuristic can of course fail if there happens to + be a matching checksum at the end. Would be good to have + some data to see how often this heuristic actually works. */ + caplen -= sizeof (uint32_t); } + /* copy payload to target buffer */ memcpy (buf, tmpbuf + n, caplen); - if (!got_channel) - ri->ri_channel = linux_get_channel (dev); - return caplen; } +/* ************end of code for reading packets from kernel ************** */ + +/* ************other helper functions for main start here ************** */ + + /** * Open the wireless network interface for reading/writing. * @@ -1400,11 +1722,12 @@ open_device_raw (struct HardwareInfos *dev) setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof (mr))) { - fprintf (stderr, "Failed to enable promiscuous mode on interface `%.*s'\n", - IFNAMSIZ, dev->iface); + fprintf (stderr, + "Failed to enable promiscuous mode on interface `%.*s'\n", + IFNAMSIZ, + dev->iface); return 1; } - return 0; } @@ -1423,106 +1746,101 @@ test_wlan_interface (const char *iface) struct stat sbuf; int ret; - /* mac80211 stack detection */ - ret = - snprintf (strbuf, sizeof (strbuf), "/sys/class/net/%s/phy80211/subsystem", - iface); + ret = snprintf (strbuf, sizeof (strbuf), + "/sys/class/net/%s/phy80211/subsystem", + iface); if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf))) { - fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", iface); - return 1; + fprintf (stderr, + "Did not find 802.11 interface `%s'. Exiting.\n", + iface); + exit (1); } return 0; } /** - * Function to test incoming packets mac for being our own. + * Test incoming packets mac for being our own. * - * @param uint8_taIeeeHeader buffer of the packet + * @param taIeeeHeader buffer of the packet * @param dev the Hardware_Infos struct * @return 0 if mac belongs to us, 1 if mac is for another target */ static int -mac_test (const struct ieee80211_frame *uint8_taIeeeHeader, +mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { - if (0 != memcmp (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE)) - return 1; - if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &dev->pl_mac, MAC_ADDR_SIZE)) - return 0; - if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &bc_all_mac, MAC_ADDR_SIZE)) - return 0; - return 1; + if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE)) + return 1; /* not a GNUnet ad-hoc package */ + if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) || + (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) ) + return 0; /* for us, or broadcast */ + return 1; /* not for us */ } /** - * function to set the wlan header to make attacks more difficult - * @param uint8_taIeeeHeader pointer to the header of the packet + * Set the wlan header to sane values to make attacks more difficult + * + * @param taIeeeHeader pointer to the header of the packet * @param dev pointer to the Hardware_Infos struct */ static void -mac_set (struct ieee80211_frame *uint8_taIeeeHeader, +mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { - uint8_taIeeeHeader->i_fc[0] = 0x08; - uint8_taIeeeHeader->i_fc[1] = 0x00; - memcpy (uint8_taIeeeHeader->i_addr2, &dev->pl_mac, MAC_ADDR_SIZE); - memcpy (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE); + taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA); + taIeeeHeader->addr2 = dev->pl_mac; + taIeeeHeader->addr3 = mac_bssid_gnunet; } /** - * function to process the data from the stdin - * @param cls pointer to the device struct + * Process data from the stdin. Takes the message, prepends the + * radiotap transmission header, forces the sender MAC to be correct + * and puts it into our buffer for transmission to the kernel. + * + * @param cls pointer to the device struct ('struct HardwareInfos*') * @param hdr pointer to the start of the packet */ static void stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) { struct HardwareInfos *dev = cls; - struct Radiotap_Send *header = (struct Radiotap_Send *) &hdr[1]; - struct ieee80211_frame *wlanheader; + const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header; + struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader; size_t sendsize; - struct RadioTapheader rtheader; - - rtheader.header.it_version = 0; /* radiotap version */ - rtheader.header.it_len = GNUNET_htole16 (0x0c); /* radiotap header length */ - rtheader.header.it_present = GNUNET_le16toh (0x00008004); /* our bitmap */ - rtheader.rate = 0x00; - rtheader.pad1 = 0x00; - rtheader.txflags = - GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ); + struct RadiotapTransmissionHeader rtheader; sendsize = ntohs (hdr->size); - if (sendsize < - sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader)) + if ( (sendsize < + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) || + (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ) { - fprintf (stderr, "Function stdin_send_hw: malformed packet (too small)\n"); + fprintf (stderr, "Received malformed message\n"); exit (1); } - sendsize -= - sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader); - + sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)); if (MAXLINE < sendsize) { - fprintf (stderr, "Function stdin_send_hw: Packet too big for buffer\n"); - exit (1); - } - if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type)) - { - fprintf (stderr, "Function stdin_send_hw: wrong packet type\n"); + fprintf (stderr, "Packet too big for buffer\n"); exit (1); } - + header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; + rtheader.header.it_version = 0; + rtheader.header.it_pad = 0; rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader)); - rtheader.rate = header->rate; + rtheader.header.it_present = GNUNET_htole16 (IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK); + rtheader.rate = header->rate; + rtheader.pad1 = 0; + rtheader.txflags = GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ); memcpy (write_pout.buf, &rtheader, sizeof (rtheader)); - memcpy (write_pout.buf + sizeof (rtheader), &header[1], sendsize); + memcpy (&write_pout.buf[sizeof (rtheader)], &header->frame, sendsize); + wlanheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf[sizeof (rtheader)]; + /* payload contains MAC address, but we don't trust it, so we'll - * overwrite it with OUR MAC address again to prevent mischief */ - wlanheader = (struct ieee80211_frame *) (write_pout.buf + sizeof (rtheader)); + * overwrite it with OUR MAC address to prevent mischief */ mac_set (wlanheader, dev); write_pout.size = sendsize + sizeof (rtheader); } @@ -1721,33 +2039,30 @@ main (int argc, char *argv[]) if (FD_ISSET (dev.fd_raw, &rfds)) { - struct GNUNET_MessageHeader *header; - struct Radiotap_rx *rxinfo; - struct ieee80211_frame *datastart; + struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm; ssize_t ret; - header = (struct GNUNET_MessageHeader *) write_std.buf; - rxinfo = (struct Radiotap_rx *) &header[1]; - datastart = (struct ieee80211_frame *) &rxinfo[1]; + rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf; ret = - linux_read (&dev, (unsigned char *) datastart, - sizeof (write_std.buf) - sizeof (struct Radiotap_rx) - - sizeof (struct GNUNET_MessageHeader), rxinfo); + linux_read (&dev, (unsigned char *) &rrm->frame, + sizeof (write_std.buf) + - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame), + rrm); if (0 > ret) { fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno)); break; } - if ((0 < ret) && (0 == mac_test (datastart, &dev))) + if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev))) { - write_std.size = - ret + sizeof (struct GNUNET_MessageHeader) + - sizeof (struct Radiotap_rx); - header->size = htons (write_std.size); - header->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); + write_std.size = ret + + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame); + rrm->header.size = htons (write_std.size); + rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER); } } - } /* Error handling, try to clean up a bit at least */ mst_destroy (stdin_mst); |