X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-helper-transport-wlan.c;h=cbe0dae77ea349b645a2832a1cbb5a051425ba6c;hb=d72d8e05401ace44b57432463f136bcfe55cee03;hp=72314beb231e9523f1abee91c1dbb87f99ec37e9;hpb=c4f0fe3ea5a5ca3ce1f7dfecef719da631e4c6ac;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-helper-transport-wlan.c b/src/transport/gnunet-helper-transport-wlan.c index 72314beb2..cbe0dae77 100644 --- a/src/transport/gnunet-helper-transport-wlan.c +++ b/src/transport/gnunet-helper-transport-wlan.c @@ -1,8 +1,8 @@ /* This file is part of GNUnet. - (C) 2010, 2011 Christian Grothoff (and other contributing authors) + Copyright (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) Copyright (c) 2007, 2008, Andy Green - Copyright (C) 2009 Thomas d'Otreppe + Copyright Copyright (C) 2009 Thomas d'Otreppe GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -16,9 +16,55 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ +/** + * @file src/transport/gnunet-helper-transport-wlan.c + * @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 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) + */ + /*- * we use our local copy of ieee80211_radiotap.h * @@ -60,21 +106,12 @@ * Modifications to fit into the linux IEEE 802.11 stack, * Mike Kershaw (dragorn@kismetwireless.net) */ - -/** - * @file src/transport/gnunet-helper-transport-wlan.c - * @brief wlan layer two server; must run as root (SUID will do) - * This code will work under GNU/Linux only. - * @author David Brodski - * - * This program serves as the mediator between the wlan interface and - * gnunet - */ - -/** +/* * parts taken from aircrack-ng, parts changend. */ -#define _GNU_SOURCE +#include "gnunet_config.h" +#define SOCKTYPE int +#define FDTYPE int #include #include #include @@ -102,179 +139,438 @@ #include "gnunet_protocols.h" #include "plugin_transport_wlan.h" +/** + * Packet format type for the messages we receive from + * the kernel. This is for Ethernet 10Mbps format (no + * performance information included). + */ +#define ARPHRD_ETHER 1 + + +/** + * 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 + * (used for our receive and sent buffers). + */ #define MAXLINE 4096 -#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK 0x80000000 -/* 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. - * +/* ********* structure of messages of type ARPHRD_IEEE80211_PRISM *********** */ + +/** + * 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,13 +582,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; /** @@ -309,147 +609,176 @@ struct ieee80211_radiotap_header uint32_t it_present; }; -struct RadioTapheader + +/** + * Format of the header we need to prepend to messages to be sent to the + * Kernel. + */ +struct RadiotapTransmissionHeader { - struct ieee80211_radiotap_header header; + + /** + * First we begin with the 'generic' header we also get when receiving + * messages. + */ + 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; -}; +}; /** - * FIXME. + * 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. */ -struct SendBuffer -{ - unsigned int pos; - unsigned int size; - char buf[MAXLINE * 2]; -}; +#define IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK ((1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_TX_FLAGS)) -GNUNET_NETWORK_STRUCT_BEGIN -/** - * 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 /** - * struct for storing the information of the hardware + * struct Ieee80211RadiotapHeaderIterator - tracks walk through present radiotap arguments + * in the radiotap header. Used when we parse radiotap packets received from the kernel. */ -struct HardwareInfos +struct Ieee80211RadiotapHeaderIterator { + /** + * pointer to the radiotap header we are walking through + */ + const struct Ieee80211RadiotapHeader *rtheader; /** - * send buffer + * pointer to current radiotap arg */ - struct SendBuffer write_pout; + const uint8_t *this_arg; /** - * file descriptor for the raw socket + * internal next argument pointer */ - int fd_raw; + const uint8_t *arg; - int arptype_in; + /** + * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used). + */ + const uint32_t *next_bitmap; /** - * Name of the interface, not necessarily 0-terminated (!). + * length of radiotap header in host byte ordering */ - char iface[IFNAMSIZ]; + size_t max_length; - struct MacAddress pl_mac; -}; + /** + * 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; +}; - /* *INDENT-OFF* */ -#define ___my_swab16(x) \ -((u_int16_t)( \ - (((u_int16_t)(x) & (u_int16_t)0x00ffU) << 8) | \ - (((u_int16_t)(x) & (u_int16_t)0xff00U) >> 8) )) -#define ___my_swab32(x) \ -((u_int32_t)( \ - (((u_int32_t)(x) & (u_int32_t)0x000000ffUL) << 24) | \ - (((u_int32_t)(x) & (u_int32_t)0x0000ff00UL) << 8) | \ - (((u_int32_t)(x) & (u_int32_t)0x00ff0000UL) >> 8) | \ - (((u_int32_t)(x) & (u_int32_t)0xff000000UL) >> 24) )) -#define ___my_swab64(x) \ -((u_int64_t)( \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x00000000000000ffULL) << 56) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x000000000000ff00ULL) << 40) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x0000000000ff0000ULL) << 24) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x00000000ff000000ULL) << 8) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x000000ff00000000ULL) >> 8) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x0000ff0000000000ULL) >> 24) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0x00ff000000000000ULL) >> 40) | \ - (u_int64_t)(((u_int64_t)(x) & (u_int64_t)0xff00000000000000ULL) >> 56) )) - /* *INDENT-ON* */ +/* ************** end of structure of ARPHRD_IEEE80211_FULL ************** */ +/* ************************** our globals ******************************* */ /** - * struct ieee80211_radiotap_iterator - tracks walk through present radiotap args + * struct for storing the information of the hardware. There is only + * one of these. */ -struct ieee80211_radiotap_iterator +struct HardwareInfos { - /** - * pointer to the radiotap header we are walking through - */ - const struct ieee80211_radiotap_header *rtheader; /** - * length of radiotap header in cpu byte ordering + * file descriptor for the raw socket */ - size_t max_length; + int fd_raw; /** - * IEEE80211_RADIOTAP_... index of current arg + * Which format has the header that we're getting when receiving packets? + * Some ARPHRD_IEEE80211_XXX-value. */ - unsigned int this_arg_index; + int arptype_in; /** - * pointer to current radiotap arg + * Name of the interface, not necessarily 0-terminated (!). */ - uint8_t *this_arg; + char iface[IFNAMSIZ]; /** - * internal next argument index + * MAC address of our own WLAN interface. */ - unsigned int arg_index; + struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac; +}; + +/** + * IO buffer used for buffering data in transit (to wireless or to stdout). + */ +struct SendBuffer +{ /** - * 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]; }; +/** + * Buffer for data read from stdin to be transmitted to the wirless card. + */ +static struct SendBuffer write_pout; + +/** + * 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 /** @@ -465,7 +794,7 @@ struct ieee80211_radiotap_iterator * @param cls closure * @param message the actual message */ -typedef void (*MessageTokenizerCallback) (void *cls, +typedef void (*MessageTokenizerCallback) (void *cls, const struct GNUNET_MessageHeader * message); @@ -509,7 +838,6 @@ struct MessageStreamTokenizer }; - /** * Create a message stream tokenizer. * @@ -525,10 +853,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; @@ -589,8 +923,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) { @@ -603,7 +938,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; } @@ -642,9 +980,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... */ @@ -665,11 +1003,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; } @@ -689,16 +1035,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 @@ -709,50 +1055,45 @@ mst_destroy (struct MessageStreamTokenizer *mst) * @param iterator iterator to initialize * @param radiotap_header message to parse * @param max_length number of valid bytes in radiotap_header - * @return 0 on success + * @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) || (radiotap_header == NULL) ) - return -EINVAL; + return -1; /* Linux only supports version 0 radiotap format */ if (0 != radiotap_header->it_version) - return -EINVAL; + 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 -EINVAL; + 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 * stated radiotap header length */ if (iterator->arg - ((uint8_t*) iterator->rtheader) > iterator->max_length) - return -EINVAL; + return -1; } iterator->arg += sizeof (uint32_t); /* @@ -767,7 +1108,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 @@ -776,13 +1117,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 negative if no more or error + * @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 @@ -827,139 +1166,104 @@ 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)); + int hit = (0 != (iterator->bitmap_shifter & 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; + 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; + } - /* - * 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. - */ + /* + * 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; - if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > - iterator->max_length) - return -EINVAL; + /* internally move on the size of this arg (using lower nybble from + the table) */ + iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; -next_entry: + /* + * 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; -} - - -/** - * function to create GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL message for plugin - * @param buffer pointer to buffer for the message - * @param mac pointer to the mac address - * @return number of bytes written - */ -static int -send_mac_to_plugin (char *buffer, struct MacAddress *mac) -{ - struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; - - memcpy (&macmsg.mac, (char *) mac, sizeof (struct MacAddress)); - macmsg.hdr.size = htons (sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)); - macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); - memcpy (buffer, &macmsg, sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)); - return sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage); -} - - -/** - * 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 * @return crc sum @@ -1043,75 +1347,101 @@ calc_crc_osdep (const unsigned char *buf, size_t len) /** - * Function to check crc of the wlan packet - * @param buf buffer of the packet - * @param len len of the data - * @return crc sum of the data + * 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 + * @param len length of the payload in data + * @return 0 on success (checksum matches), 1 on error */ static int check_crc_buf_osdep (const unsigned char *buf, size_t len) { unsigned long crc; - if (0 > len) - return 0; - crc = calc_crc_osdep (buf, len); buf += len; - return (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && - ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3]); + if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && + ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3]) + return 0; + return 1; +} + + +/* ************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; } /** - * function to get the channel of a specific wlan card + * Get the channel used by our WLAN interface. + * * @param dev pointer to the dev struct of the card - * @return channel number + * @return channel number, -1 on error */ 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) @@ -1122,173 +1452,193 @@ linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size, return -1; } - memset (buf, 0, buf_size); 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 (ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen) < 0) - 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; - } + 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 */ } - n = GNUNET_le16toh (rthdr->it_len); - if (n <= 0 || n >= caplen) - return 0; - } break; case ARPHRD_IEEE80211: - /* do nothing? */ + n = 0; /* no header */ break; + case ARPHRD_ETHER: + { + if (sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) > caplen) + return 0; /* invalid */ + memcpy (&buf[sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)], + tmpbuf + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame), + caplen - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) - 4 /* 4 byte FCS */); + return caplen - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) - 4; + } 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) && (1 == 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 ************** */ + + /** - * function to open the device for read/write + * Open the wireless network interface for reading/writing. + * * @param dev pointer to the device struct * @return 0 on success */ @@ -1321,6 +1671,16 @@ open_device_raw (struct HardwareInfos *dev) IFNAMSIZ, dev->iface, strerror (errno)); return 1; } + if (((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && + (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && + (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) && + (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) ) + { + fprintf (stderr, "Error: interface `%.*s' is not using a supported hardware address family (got %d)\n", + IFNAMSIZ, dev->iface, + ifr.ifr_hwaddr.sa_family); + return 1; + } /* lookup iw mode */ memset (&wrq, 0, sizeof (struct iwreq)); @@ -1332,13 +1692,12 @@ open_device_raw (struct HardwareInfos *dev) wrq.u.mode = IW_MODE_MONITOR; } - if (((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && - (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) && - (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) || - (wrq.u.mode != IW_MODE_MONITOR)) + if ( (wrq.u.mode != IW_MODE_MONITOR) && + (wrq.u.mode != IW_MODE_ADHOC) ) { - fprintf (stderr, "Error: interface `%.*s' is not in monitor mode\n", - IFNAMSIZ, dev->iface); + fprintf (stderr, "Error: interface `%.*s' is not in monitor or ad-hoc mode (got %d)\n", + IFNAMSIZ, dev->iface, + wrq.u.mode); return 1; } @@ -1374,7 +1733,8 @@ open_device_raw (struct HardwareInfos *dev) memcpy (&dev->pl_mac, ifr.ifr_hwaddr.sa_data, MAC_ADDR_SIZE); dev->arptype_in = ifr.ifr_hwaddr.sa_family; - if ((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && + if ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && + (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) { @@ -1391,191 +1751,205 @@ 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; } /** - * function to prepare the helper, e.g. sockets, device... - * @param dev struct for the device + * Test if the given interface name really corresponds to a wireless + * device. + * * @param iface name of the interface - * @return 0 on success + * @return 0 on success, 1 on error */ static int -wlan_initialize (struct HardwareInfos *dev, const char *iface) +test_wlan_interface (const char *iface) { char strbuf[512]; struct stat sbuf; int ret; - if (dev->fd_raw >= FD_SETSIZE) - { - fprintf (stderr, "File descriptor too large for select (%d > %d)\n", - dev->fd_raw, FD_SETSIZE); - close (dev->fd_raw); - return 1; - } - - /* 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); - close (dev->fd_raw); - return 1; - } - strncpy (dev->iface, iface, IFNAMSIZ); - if (0 != open_device_raw (dev)) - { - close (dev->fd_raw); - 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; + static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros; + + if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) || + (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) ) + return 0; /* some drivers set no Macs, then assume it is all for us! */ + + 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 SendBuffer *write_pout = &dev->write_pout; - 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; + struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame etheader; 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"); + fprintf (stderr, "Packet too big for buffer\n"); exit (1); } - if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type)) + header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; + switch (dev->arptype_in) { - fprintf (stderr, "Function stdin_send_hw: wrong packet type\n"); - exit (1); + case ARPHRD_IEEE80211_PRISM: + case ARPHRD_IEEE80211_FULL: + case ARPHRD_IEEE80211: + rtheader.header.it_version = 0; + rtheader.header.it_pad = 0; + rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader)); + 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 to prevent mischief */ + mac_set (wlanheader, dev); + write_pout.size = sendsize + sizeof (rtheader); + break; + case ARPHRD_ETHER: + etheader.dst = header->frame.addr1; + /* etheader.src = header->frame.addr2; --- untrusted input */ + etheader.src = dev->pl_mac; + etheader.type = htons (ETH_P_IP); + memcpy (write_pout.buf, ðeader, sizeof (etheader)); + memcpy (&write_pout.buf[sizeof (etheader)], &header[1], sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)); + write_pout.size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame) + sizeof (etheader); + break; + default: + fprintf (stderr, + "Unsupported ARPTYPE!\n"); + break; } - - rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader)); - rtheader.rate = header->rate; - memcpy (write_pout->buf, &rtheader, sizeof (rtheader)); - memcpy (write_pout->buf + sizeof (rtheader), &header[1], sendsize); - /* 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)); - mac_set (wlanheader, dev); - write_pout->size = sendsize + sizeof (rtheader); } /** - * main function of the helper - * @param argc number of arguments - * @param argv arguments - * @return 0 on success, 1 on error + * Main function of the helper. This code accesses a WLAN interface + * in monitoring mode (layer 2) and then forwards traffic in both + * directions between the WLAN interface and stdin/stdout of this + * process. Error messages are written to stdout. + * + * @param argc number of arguments, must be 2 + * @param argv arguments only argument is the name of the interface (i.e. 'mon0') + * @return 0 on success (never happens, as we don't return unless aborted), 1 on error */ int main (int argc, char *argv[]) { - uid_t uid; struct HardwareInfos dev; char readbuf[MAXLINE]; - struct SendBuffer write_std; - ssize_t ret; int maxfd; fd_set rfds; fd_set wfds; - int retval; int stdin_open; struct MessageStreamTokenizer *stdin_mst; int raw_eno; - dev.fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL)); - raw_eno = errno; /* remember for later */ - uid = getuid (); -#ifdef HAVE_SETRESUID - if (0 != setresuid (uid, uid, uid)) + /* assert privs so we can modify the firewall rules! */ { - fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); - if (-1 != dev.fd_raw) - (void) close (dev.fd_raw); - return 1; - } +#ifdef HAVE_SETRESUID + uid_t uid = getuid (); + + if (0 != setresuid (uid, 0, 0)) + { + fprintf (stderr, + "Failed to setresuid to root: %s\n", + strerror (errno)); + return 254; + } #else - if (0 != (setuid (uid) | seteuid (uid))) - { - fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); - if (-1 != dev.fd_raw) - (void) close (dev.fd_raw); - return 1; - } + if (0 != seteuid (0)) + { + fprintf (stderr, + "Failed to seteuid back to root: %s\n", strerror (errno)); + return 254; + } #endif + } + + /* make use of SGID capabilities on POSIX */ + memset (&dev, 0, sizeof (dev)); + dev.fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL)); + raw_eno = errno; /* remember for later */ /* now that we've dropped root rights, we can do error checking */ if (2 != argc) @@ -1592,22 +1966,66 @@ main (int argc, char *argv[]) fprintf (stderr, "Failed to create raw socket: %s\n", strerror (raw_eno)); return 1; } - if (0 != wlan_initialize (&dev, argv[1])) + if (dev.fd_raw >= FD_SETSIZE) + { + fprintf (stderr, "File descriptor too large for select (%d > %d)\n", + dev.fd_raw, FD_SETSIZE); + (void) close (dev.fd_raw); + return 1; + } + if (0 != test_wlan_interface (argv[1])) + { + (void) close (dev.fd_raw); + return 1; + } + strncpy (dev.iface, argv[1], IFNAMSIZ); + if (0 != open_device_raw (&dev)) + { + (void) close (dev.fd_raw); return 1; - dev.write_pout.size = 0; - dev.write_pout.pos = 0; - stdin_mst = mst_create (&stdin_send_hw, &dev); + } - /* send mac to STDOUT first */ - write_std.pos = 0; - write_std.size = send_mac_to_plugin ((char *) &write_std.buf, &dev.pl_mac); - stdin_open = 1; + /* drop privs */ + { + uid_t uid = getuid (); +#ifdef HAVE_SETRESUID + if (0 != setresuid (uid, uid, uid)) + { + fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); + if (-1 != dev.fd_raw) + (void) close (dev.fd_raw); + return 1; + } +#else + if (0 != (setuid (uid) | seteuid (uid))) + { + fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); + if (-1 != dev.fd_raw) + (void) close (dev.fd_raw); + return 1; + } +#endif + } + + + /* send MAC address of the WLAN interface to STDOUT first */ + { + struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; + macmsg.hdr.size = htons (sizeof (macmsg)); + macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); + memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); + memcpy (write_std.buf, &macmsg, sizeof (macmsg)); + write_std.size = sizeof (macmsg); + } + + stdin_mst = mst_create (&stdin_send_hw, &dev); + stdin_open = 1; while (1) { maxfd = -1; FD_ZERO (&rfds); - if ((0 == dev.write_pout.size) && (1 == stdin_open)) + if ((0 == write_pout.size) && (1 == stdin_open)) { FD_SET (STDIN_FILENO, &rfds); maxfd = MAX (maxfd, STDIN_FILENO); @@ -1623,22 +2041,24 @@ main (int argc, char *argv[]) FD_SET (STDOUT_FILENO, &wfds); maxfd = MAX (maxfd, STDOUT_FILENO); } - if (0 < dev.write_pout.size) + if (0 < write_pout.size) { FD_SET (dev.fd_raw, &wfds); maxfd = MAX (maxfd, dev.fd_raw); } - retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL); - if ((-1 == retval) && (EINTR == errno)) - continue; - if (0 > retval) { - fprintf (stderr, "select failed: %s\n", strerror (errno)); - break; + int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL); + if ((-1 == retval) && (EINTR == errno)) + continue; + if (0 > retval) + { + fprintf (stderr, "select failed: %s\n", strerror (errno)); + break; + } } if (FD_ISSET (STDOUT_FILENO, &wfds)) { - ret = + ssize_t ret = write (STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size - write_std.pos); if (0 > ret) @@ -1655,31 +2075,35 @@ main (int argc, char *argv[]) } if (FD_ISSET (dev.fd_raw, &wfds)) { - ret = write (dev.fd_raw, dev.write_pout.buf, dev.write_pout.size); + ssize_t ret = + write (dev.fd_raw, write_pout.buf + write_std.pos, + write_pout.size - write_pout.pos); if (0 > ret) { fprintf (stderr, "Failed to write to WLAN device: %s\n", strerror (errno)); break; } - dev.write_pout.pos += ret; - if ((dev.write_pout.pos != dev.write_pout.size) && (ret != 0)) + write_pout.pos += ret; + if ((write_pout.pos != write_pout.size) && (0 != ret)) { /* we should not get partial sends with packet-oriented devices... */ fprintf (stderr, "Write error, partial send: %u/%u\n", - dev.write_pout.pos, dev.write_pout.size); + (unsigned int) write_pout.pos, + (unsigned int) write_pout.size); break; } - if (dev.write_pout.pos == dev.write_pout.size) + if (write_pout.pos == write_pout.size) { - dev.write_pout.pos = 0; - dev.write_pout.size = 0; + write_pout.pos = 0; + write_pout.size = 0; } } if (FD_ISSET (STDIN_FILENO, &rfds)) { - ret = read (STDIN_FILENO, readbuf, sizeof (readbuf)); + ssize_t ret = + read (STDIN_FILENO, readbuf, sizeof (readbuf)); if (0 > ret) { fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno)); @@ -1695,32 +2119,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);