From: Christian Grothoff Date: Fri, 16 Mar 2012 20:52:52 +0000 (+0000) Subject: -fixing misc. bugs and making wlan helper auditable, resolving #1939 X-Git-Tag: initial-import-from-subversion-38251~14210 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=dc2e456d8e2689e212366260ffa2f09f86e9420b;p=oweals%2Fgnunet.git -fixing misc. bugs and making wlan helper auditable, resolving #1939 --- diff --git a/src/transport/gnunet-helper-transport-wlan.c b/src/transport/gnunet-helper-transport-wlan.c index 2ed81a24d..0169a2da1 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 Copyright (C) 2009 Thomas d'Otreppe @@ -21,12 +21,27 @@ */ /** * @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 interface to use. Since it uses + * RAW sockets, it 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 (Mar 16th 2012) */ /*- @@ -102,179 +117,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 + +/** + * Packet format type for the messages we receive from + * the kernel. This is for messages with a + * 'struct Ieee80211RadiotapHeader' (see below). + */ #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) + /** - * 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 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 + +/** + * 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 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 @@ -286,7 +551,7 @@ 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 @@ -295,7 +560,7 @@ struct ieee80211_radiotap_header uint8_t it_version; /** - * + * Padding. Set to 0. */ uint8_t it_pad; @@ -313,60 +578,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; + + /** + * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used). + */ + const uint32_t *next_bitmap; + + /** + * 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; + + /** + * IEEE80211_RADIOTAP_... index of current arg + */ + unsigned int this_arg_index; + + /** + * internal next argument index + */ + unsigned int arg_index; + }; +/* ************** 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 { @@ -395,50 +706,27 @@ 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 - */ - unsigned int this_arg_index; - - /** - * pointer to current radiotap arg - */ - uint8_t *this_arg; - - /** - * internal next argument index - */ - unsigned int arg_index; - - /** - * internal next argument pointer + * How many bytes of data are stored in 'buf' for transmission right now? + * Data always starts at offset 0 and extends to 'size'. */ - uint8_t *arg; + size_t size; /** - * internal pointer to next present uint32_t + * How many bytes that were stored in 'buf' did we already write to the + * destination? Always smaller than 'size'. */ - uint32_t *next_bitmap; - + size_t pos; + /** - * internal shifter for curr uint32_t bitmap, b0 set == arg present + * Buffered data; twice the maximum allowed message size as we add some + * headers. */ - uint32_t bitmap_shifter; + char buf[MAXLINE * 2]; }; @@ -454,8 +742,12 @@ 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 /** @@ -530,10 +822,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; @@ -594,8 +892,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) { @@ -608,7 +907,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; } @@ -647,9 +949,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... */ @@ -670,11 +972,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; } @@ -694,16 +1004,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 @@ -717,9 +1027,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) || @@ -731,26 +1040,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 @@ -772,7 +1077,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 @@ -781,13 +1086,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 @@ -832,120 +1135,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 */ + int hit = (0 != (iterator->bitmap_shifter & 1)); - /* - * 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; - -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 */ - 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; + /* 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; } /** - * 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 @@ -1030,7 +1316,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 @@ -1051,6 +1337,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. * @@ -1061,36 +1371,33 @@ 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 where to write radiotap_rx info - * @return size read from the buffer + * @return number of bytes written to 'buf' */ static ssize_t linux_read (struct HardwareInfos *dev, @@ -1099,9 +1406,11 @@ linux_read (struct HardwareInfos *dev, { 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) @@ -1112,172 +1421,181 @@ linux_read (struct HardwareInfos *dev, 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; - - memset (&iterator, 0, sizeof (iterator)); - 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. * @@ -1383,11 +1701,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; } @@ -1406,21 +1725,22 @@ 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 taIeeeHeader buffer of the packet * @param dev the Hardware_Infos struct @@ -1431,17 +1751,17 @@ mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE)) - return 1; - if (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) - return 0; - if (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) - return 0; - return 1; + 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 + * 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 */ @@ -1449,15 +1769,18 @@ static void mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { - taIeeeHeader->frame_control = ntohs (0x08); // FIXME: need to shift by 8? + 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 @@ -1467,7 +1790,7 @@ stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header; struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader; size_t sendsize; - struct RadioTapheader rtheader; + struct RadiotapTransmissionHeader rtheader; sendsize = ntohs (hdr->size); if ( (sendsize < @@ -1484,20 +1807,19 @@ stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) exit (1); } header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; - rtheader.header.it_version = 0; /* radiotap version */ - rtheader.header.it_len = GNUNET_htole16 (0x0c); /* radiotap header length */ - rtheader.header.it_present = GNUNET_htole16 (0x00008004); /* our bitmap */ - rtheader.rate = 0x00; - rtheader.pad1 = 0x00; - rtheader.txflags = GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ); + 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->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 */ + * overwrite it with OUR MAC address to prevent mischief */ mac_set (wlanheader, dev); write_pout.size = sendsize + sizeof (rtheader); } diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c index 7b709ce9d..0c60bd68c 100644 --- a/src/transport/plugin_transport_wlan.c +++ b/src/transport/plugin_transport_wlan.c @@ -93,6 +93,7 @@ * max messages in in queue */ #define MESSAGES_IN_QUEUE_SIZE 10 + /** * max messages in in queue per session/client */ @@ -106,17 +107,6 @@ #define WLAN_LLC_SSAP_FIELD 0x1f -#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ - -#define IEEE80211_FC0_VERSION_MASK 0x03 -#define IEEE80211_FC0_VERSION_SHIFT 0 -#define IEEE80211_FC0_VERSION_0 0x00 -#define IEEE80211_FC0_TYPE_MASK 0x0c -#define IEEE80211_FC0_TYPE_SHIFT 2 -#define IEEE80211_FC0_TYPE_MGT 0x00 -#define IEEE80211_FC0_TYPE_CTL 0x04 -#define IEEE80211_FC0_TYPE_DATA 0x08 - /** * Encapsulation of all of the state of the plugin. @@ -1266,7 +1256,7 @@ getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header, { const int rate = 11000000; - Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); // FIXME: check: might need to shift by 8? + Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); Header->addr1 = *to_mac_addr; Header->addr2 = plugin->mac_address; Header->addr3 = mac_bssid_gnunet; diff --git a/src/transport/plugin_transport_wlan.h b/src/transport/plugin_transport_wlan.h index 3f8e82404..96aa434ee 100644 --- a/src/transport/plugin_transport_wlan.h +++ b/src/transport/plugin_transport_wlan.h @@ -34,6 +34,25 @@ */ #define MAC_ADDR_SIZE 6 +/** + * Value for "Management" in the 'frame_control' field of the + * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. + */ +#define IEEE80211_FC0_TYPE_MGT 0x00 + +/** + * Value for "Control" in the 'frame_control' field of the + * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. + */ +#define IEEE80211_FC0_TYPE_CTL 0x04 + +/** + * Value for DATA in the 'frame_control' field of the + * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. + */ +#define IEEE80211_FC0_TYPE_DATA 0x08 + + GNUNET_NETWORK_STRUCT_BEGIN /** @@ -68,7 +87,13 @@ struct GNUNET_TRANSPORT_WLAN_HelperControlMessage struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame { /** - * 802.11 Frame Control field, + * 802.11 Frame Control field. A bitmask. The overall field is a + * 16-bit mask of the respecitve fields. The lowest two bits should + * be 0, then comes the "type" (2 bits, see IEEE80211_FC0_TYPE_* + * constants), followed by 4-bit subtype (all zeros for ad-hoc), + * followed by various flags (to DS, from DS, more frag, retry, + * power management, more data, WEP, strict), all of which we also + * keep at zero. */ uint16_t frame_control GNUNET_PACKED; @@ -93,7 +118,8 @@ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame struct GNUNET_TRANSPORT_WLAN_MacAddress addr3; /** - * 802.11 sequence control field. + * 802.11 sequence control field; contains fragment number an sequence + * number (we set this to all zeros). */ uint16_t sequence_control GNUNET_PACKED; @@ -162,46 +188,46 @@ struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage struct GNUNET_MessageHeader header; /** - * FIXME: not initialized properly so far. (supposed to contain - * information about which of the fields below are actually valid). + * Information about which of the fields below are actually valid. + * 0 for none. FIXME: not properly initialized so far (always zero). */ uint32_t ri_present GNUNET_PACKED; /** - * IEEE80211_RADIOTAP_TSFT + * IEEE80211_RADIOTAP_TSFT, 0 if unknown. */ uint64_t ri_mactime GNUNET_PACKED; /** * from radiotap * either IEEE80211_RADIOTAP_DBM_ANTSIGNAL - * or IEEE80211_RADIOTAP_DB_ANTSIGNAL + * or IEEE80211_RADIOTAP_DB_ANTSIGNAL, 0 if unknown. */ int32_t ri_power GNUNET_PACKED; /** * either IEEE80211_RADIOTAP_DBM_ANTNOISE - * or IEEE80211_RADIOTAP_DB_ANTNOISE + * or IEEE80211_RADIOTAP_DB_ANTNOISE, 0 if unknown. */ int32_t ri_noise GNUNET_PACKED; /** - * IEEE80211_RADIOTAP_CHANNEL + * IEEE80211_RADIOTAP_CHANNEL, 0 if unknown. */ uint32_t ri_channel GNUNET_PACKED; /** - * Frequency we use. FIXME: not properly initialized so far! + * Frequency we use. 0 if unknown. */ uint32_t ri_freq GNUNET_PACKED; /** - * IEEE80211_RADIOTAP_RATE * 50000 + * IEEE80211_RADIOTAP_RATE * 50000, 0 if unknown. */ uint32_t ri_rate GNUNET_PACKED; /** - * IEEE80211_RADIOTAP_ANTENNA + * IEEE80211_RADIOTAP_ANTENNA, 0 if unknown. */ uint32_t ri_antenna GNUNET_PACKED;