/*
This file is part of GNUnet.
- (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+ (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
Copyright (c) 2007, 2008, Andy Green <andy@warmcat.com>
Copyright (C) 2009 Thomas d'Otreppe
*/
/**
* @file src/transport/gnunet-helper-transport-wlan.c
- * @brief wlan layer two server; must run as root (SUID will do)
+ * @brief mediator between the wlan interface and gnunet; must run as root (SUID will do)
* This code will work under GNU/Linux only.
* @author David Brodski
+ * @author Christian Grothoff
*
- * This program serves as the mediator between the wlan interface and
- * gnunet
+ * This program will allow receiving and sending traffic from the WLAN
+ * interface. It will force traffic to be in 'ad-hoc' mode, use the
+ * proper MAC address of the WLAN interface and use a GNUnet-specific
+ * SSID (and a GNUnet-specific SNAP header). It only takes a single
+ * argument, which is the name of the WLAN interface to use. The
+ * program detects if the interface is not a WLAN interface and exits
+ * with an error in that case.
+ *
+ * Once initialized, the program will first send a 'struct
+ * GNUNET_TRANSPORT_WLAN_HelperControlMessage' to 'stdout'. That
+ * message contains the MAC address of the WLAN interface. It will
+ * then read messages from the WLAN interface and send them together
+ * with performance information as 'struct
+ * GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage' messages to 'stdout'.
+ * Furthermore, it will read a stream of messages from 'stdin' that
+ * have the format from 'struct
+ * GNUNET_TRANSPORT_WLAN_RadiotapSendMessage'. Those messages will
+ * then be sent via the WLAN interface; however, the sender MAC
+ * address will be forced to be the correct address from our WLAN
+ * card. If 'stdin' closes, receiving from the WLAN interface will
+ * continue. If 'stdout' causes a SIGPIPE, the process dies from the
+ * signal. Errors cause an error message to be reported to 'stderr',
+ * in most cases the process also exits (with status code '1'). The
+ * program never terminates normally; it is safe to kill the
+ * process with SIGTERM or SIGKILL at any time.
+ *
+ * Since it uses RAW sockets, the binary must be installed SUID or run
+ * as 'root'. In order to keep the security risk of the resulting
+ * SUID binary minimal, the program ONLY opens the RAW socket with
+ * root privileges, then drops them and only then starts to process
+ * command line arguments. The code also does not link against any
+ * shared libraries (except libc) and is strictly minimal (except for
+ * checking for errors). The following list of people have reviewed
+ * this code and considered it safe since the last modification (if
+ * you reviewed it, please have your name added to the list):
+ *
+ * - Christian Grothoff (Apr 3rd 2012)
*/
/*-
* Modifications to fit into the linux IEEE 802.11 stack,
* Mike Kershaw (dragorn@kismetwireless.net)
*/
-
-/**
+/*
* parts taken from aircrack-ng, parts changend.
*/
-#define _GNU_SOURCE
+#include "gnunet_config.h"
+#define SOCKTYPE int
+#define FDTYPE int
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#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.
+ * Maximum size of a message allowed in either direction
+ * (used for our receive and sent buffers).
*/
#define MAXLINE 4096
-#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK 0x80000000
+/* ********* structure of messages of type ARPHRD_IEEE80211_PRISM *********** */
-/* Name Data type Units
- * ---- --------- -----
- *
- * IEEE80211_RADIOTAP_TSFT __le64 microseconds
- *
- * Value in microseconds of the MAC's 64-bit 802.11 Time
- * Synchronization Function timer when the first bit of the
- * MPDU arrived at the MAC. For received frames, only.
- *
- * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
- *
- * Tx/Rx frequency in MHz, followed by flags (see below).
- *
- * IEEE80211_RADIOTAP_FHSS __le16 see below
- *
- * For frequency-hopping radios, the hop set (first byte)
- * and pattern (second byte).
- *
- * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s
- *
- * Tx/Rx data rate
- *
- * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
- * one milliwatt (dBm)
- *
- * RF signal power at the antenna, decibel difference from
- * one milliwatt.
- *
- * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
- * one milliwatt (dBm)
- *
- * RF noise power at the antenna, decibel difference from one
- * milliwatt.
- *
- * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
- *
- * RF signal power at the antenna, decibel difference from an
- * arbitrary, fixed reference.
- *
- * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
- *
- * RF noise power at the antenna, decibel difference from an
- * arbitrary, fixed reference point.
- *
- * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
- *
- * Quality of Barker code lock. Unitless. Monotonically
- * nondecreasing with "better" lock strength. Called "Signal
- * Quality" in datasheets. (Is there a standard way to measure
- * this?)
- *
- * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
- *
- * Transmit power expressed as unitless distance from max
- * power set at factory calibration. 0 is max power.
- * Monotonically nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
- *
- * Transmit power expressed as decibel distance from max power
- * set at factory calibration. 0 is max power. Monotonically
- * nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
- * one milliwatt (dBm)
- *
- * Transmit power expressed as dBm (decibels from a 1 milliwatt
- * reference). This is the absolute power level measured at
- * the antenna port.
- *
- * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
- *
- * Properties of transmitted and received frames. See flags
- * defined below.
- *
- * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
- *
- * Unitless indication of the Rx/Tx antenna for this packet.
- * The first antenna is antenna 0.
- *
- * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
- *
- * Properties of received frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
- *
- * Properties of transmitted frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data
- *
- * Number of rts retries a transmitted frame used.
- *
- * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data
- *
- * Number of unicast retries a transmitted frame used.
- *
+/**
+ * Device name length in PRISM frames.
+ * (In the kernel, this is "WLAN_DEVNAMELEN_MAX")
+ */
+#define PRISM_DEVICE_NAME_LENGTH 16
+
+/**
+ * Monitor Frame (indicator that we have a 'struct PrismHeader').
+ */
+#define PRISM_MSGCODE_MONITOR 0x0041
+
+/**
+ * Mac time element. In micro-seconds.
+ * Drivers appear to use a 64bit counter to hold mactime internal
+ * the then fill the prism header with the lower 32 bits
+ */
+#define PRISM_DID_MACTIME 0x2041
+
+/**
+ * Channel element
+ */
+#define PRISM_DID_CHANNEL 0x3041
+
+/**
+ * Signal element. Should be the signal strength in dbm, some people
+ * suggest that instead "100 - (strength in dbm)" is used (to make this
+ * a positive integer).
+ */
+#define PRISM_DID_SIGNAL 0x6041
+
+/**
+ * Noise element
+ */
+#define PRISM_DID_NOISE 0x7041
+
+/**
+ * Rate element, in units/multiples of 500Khz
+ */
+#define PRISM_DID_RATE 0x8041
+
+
+/**
+ * Value is set (supplied)
+ */
+#define PRISM_STATUS_OK 0
+
+/**
+ * Value not supplied.
+ */
+#define PRISM_STATUS_NO_VALUE 1
+
+
+/**
+ * Values in the 'struct PrismHeader'. All in host byte order (!).
+ */
+struct PrismValue
+{
+ /**
+ * This has a different ID for each parameter, see
+ * PRISM_DID_* constants.
+ */
+ uint32_t did;
+
+ /**
+ * See PRISM_STATUS_*-constants. Note that they are unusual: 0 = set; 1 = not set
+ */
+ uint16_t status;
+
+ /**
+ * length of data (which is always a uint32_t, but presumably this can be used
+ * to specify that fewer bytes are used (with values in 'len' from 0-4). We
+ * ignore this field.
+ */
+ uint16_t len;
+
+ /**
+ * The data value
+ */
+ uint32_t data;
+
+} __attribute__ ((packed));
+
+
+/**
+ * Prism header format ('struct p80211msg' in Linux). All in host byte order (!).
+ */
+struct PrismHeader
+{
+ /**
+ * We expect this to be a PRISM_MSGCODE_*.
+ */
+ uint32_t msgcode;
+
+ /**
+ * The length of the entire header.
+ */
+ uint32_t msglen;
+
+ /**
+ * Name of the device that captured the packet.
+ */
+ char devname[PRISM_DEVICE_NAME_LENGTH];
+
+ /* followed by 'struct PrismValue's. Documentation suggests that these
+ are typically the hosttime, mactime, channel, rssi, sq, signal, noise,
+ rate, istx and frmlen values, but documentation is sparse. So we
+ will use the 'did' fields to find out what we actually got. */
+
+} __attribute__ ((packed));
+
+
+/* ****** end of structure of messages of type ARPHRD_IEEE80211_PRISM ******* */
+
+/* ********** structure of messages of type ARPHRD_IEEE80211_FULL *********** */
+
+/**
+ * Bits in the 'it_present' bitmask from the 'struct
+ * Ieee80211RadiotapHeader'. For each value, we give the name, data
+ * type, unit and then a description below. Note that the actual size
+ * of the extension can be bigger as arguments must be padded so that
+ * args of a given length must begin at a boundary of that length.
+ * However, note that compound args are allowed (eg, 2 x uint16_t for
+ * IEEE80211_RADIOTAP_CHANNEL) so total argument length is not a
+ * reliable indicator of alignment requirement. See also
+ * 'man 9 ieee80211_radiotap'.
*/
enum RadiotapType
{
+
+ /**
+ * IEEE80211_RADIOTAP_TSFT __le64 microseconds
+ *
+ * Value in microseconds of the MAC's 64-bit 802.11 Time
+ * Synchronization Function timer when the first bit of the
+ * MPDU arrived at the MAC. For received frames, only.
+ */
IEEE80211_RADIOTAP_TSFT = 0,
+
+ /**
+ * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
+ *
+ * Properties of transmitted and received frames. See flags
+ * defined below.
+ */
IEEE80211_RADIOTAP_FLAGS = 1,
+
+ /**
+ * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s
+ *
+ * Tx/Rx data rate
+ */
IEEE80211_RADIOTAP_RATE = 2,
+
+ /**
+ * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
+ *
+ * Tx/Rx frequency in MHz, followed by flags (see below).
+ */
IEEE80211_RADIOTAP_CHANNEL = 3,
+ /**
+ * IEEE80211_RADIOTAP_FHSS __le16 see below
+ *
+ * For frequency-hopping radios, the hop set (first byte)
+ * and pattern (second byte).
+ */
IEEE80211_RADIOTAP_FHSS = 4,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF signal power at the antenna, decibel difference from
+ * one milliwatt.
+ */
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF noise power at the antenna, decibel difference from one
+ * milliwatt.
+ */
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+
+ /**
+ * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
+ *
+ * Quality of Barker code lock. Unitless. Monotonically
+ * nondecreasing with "better" lock strength. Called "Signal
+ * Quality" in datasheets. (Is there a standard way to measure
+ * this?)
+ */
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+
+ /**
+ * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
+ *
+ * Transmit power expressed as unitless distance from max
+ * power set at factory calibration. 0 is max power.
+ * Monotonically nondecreasing with lower power levels.
+ */
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
+ *
+ * Transmit power expressed as decibel distance from max power
+ * set at factory calibration. 0 is max power. Monotonically
+ * nondecreasing with lower power levels.
+ */
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * Transmit power expressed as dBm (decibels from a 1 milliwatt
+ * reference). This is the absolute power level measured at
+ * the antenna port.
+ */
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+
+ /**
+ * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
+ *
+ * Unitless indication of the Rx/Tx antenna for this packet.
+ * The first antenna is antenna 0.
+ */
IEEE80211_RADIOTAP_ANTENNA = 11,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
+ *
+ * RF signal power at the antenna, decibel difference from an
+ * arbitrary, fixed reference.
+ */
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
+ *
+ * RF noise power at the antenna, decibel difference from an
+ * arbitrary, fixed reference point.
+ */
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+
+ /**
+ * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
+ *
+ * Properties of received frames. See flags defined below.
+ */
IEEE80211_RADIOTAP_RX_FLAGS = 14,
+
+ /**
+ * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
+ *
+ * Properties of transmitted frames. See flags defined below.
+ */
IEEE80211_RADIOTAP_TX_FLAGS = 15,
+
+ /**
+ * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data
+ *
+ * Number of rts retries a transmitted frame used.
+ */
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+
+ /**
+ * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data
+ *
+ * Number of unicast retries a transmitted frame used.
+ */
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
+ /**
+ * Extension bit, used to indicate that more bits are needed for
+ * the bitmask.
+ */
IEEE80211_RADIOTAP_EXT = 31
};
-/* For IEEE80211_RADIOTAP_FLAGS */
-#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
- * during CFP
- */
-#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
- * with short
- * preamble
- */
-#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
- * with WEP encryption
- */
-#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
- * with fragmentation
- */
-#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
-#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
- * 802.11 header and payload
- * (to 32-bit boundary)
- */
-/* For IEEE80211_RADIOTAP_RX_FLAGS */
-#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
-
-/* For IEEE80211_RADIOTAP_TX_FLAGS */
-#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
- * retries */
-#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
-#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
-#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* frame should not be ACKed */
-#define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010 /* sequence number handled
- * by userspace */
+/**
+ * Bitmask indicating an extension of the bitmask is used.
+ * (Mask corresponding to IEEE80211_RADIOTAP_EXT).
+ */
+#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK (1 << IEEE80211_RADIOTAP_EXT)
+
+
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame was sent/received during CFP (Contention Free Period)
+ */
+#define IEEE80211_RADIOTAP_F_CFP 0x01
/**
- * A generic radio capture format is desirable. There is one for
- * Linux, but it is neither rigidly defined (there were not even
- * units given for some fields) nor easily extensible.
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
*
- * I suggest the following extensible radio capture format. It is
- * based on a bitmap indicating which fields are present.
+ * Frame was sent/received with 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
* 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
uint8_t it_version;
/**
- *
+ * Padding. Set to 0.
*/
uint8_t it_pad;
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];
-};
-
-/**
- * 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;
-
-
+ const uint8_t *arg;
-
-/**
- * struct for storing the information of the hardware
- */
-struct HardwareInfos
-{
+ /**
+ * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used).
+ */
+ const uint32_t *next_bitmap;
/**
- * file descriptor for the raw socket
+ * length of radiotap header in host byte ordering
*/
- int fd_raw;
+ size_t max_length;
/**
- * Which format has the header that we're getting when receiving packets?
- * Some ARPHRD_IEEE80211_XXX-value.
+ * internal shifter for current uint32_t bitmap, (it_present in host byte order),
+ * If bit 0 is set, the 'arg_index' argument is present.
*/
- int arptype_in;
+ uint32_t bitmap_shifter;
/**
- * Name of the interface, not necessarily 0-terminated (!).
+ * IEEE80211_RADIOTAP_... index of current arg
*/
- char iface[IFNAMSIZ];
+ unsigned int this_arg_index;
/**
- * MAC address of our own WLAN interface.
+ * internal next argument index
*/
- struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
+ unsigned int arg_index;
+
};
+/* ************** end of structure of ARPHRD_IEEE80211_FULL ************** */
+
+/* ************************** our globals ******************************* */
+
/**
- * struct ieee80211_radiotap_iterator - tracks walk through present radiotap arguments
- * in the radiotap header.
+ * 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
- */
- size_t max_length;
/**
- * IEEE80211_RADIOTAP_... index of current arg
+ * file descriptor for the raw socket
*/
- unsigned int this_arg_index;
+ int fd_raw;
/**
- * pointer to current radiotap arg
+ * Which format has the header that we're getting when receiving packets?
+ * Some ARPHRD_IEEE80211_XXX-value.
*/
- uint8_t *this_arg;
+ int arptype_in;
/**
- * internal next argument index
+ * Name of the interface, not necessarily 0-terminated (!).
*/
- unsigned int arg_index;
+ char iface[IFNAMSIZ];
/**
- * internal next argument pointer
+ * MAC address of our own WLAN interface.
*/
- uint8_t *arg;
+ struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
+};
+
+/**
+ * IO buffer used for buffering data in transit (to wireless or to stdout).
+ */
+struct SendBuffer
+{
/**
- * internal pointer to next present uint32_t
+ * How many bytes of data are stored in 'buf' for transmission right now?
+ * Data always starts at offset 0 and extends to 'size'.
*/
- uint32_t *next_bitmap;
+ size_t size;
/**
- * internal shifter for curr uint32_t bitmap, b0 set == arg present
+ * How many bytes that were stored in 'buf' did we already write to the
+ * destination? Always smaller than 'size'.
*/
- uint32_t bitmap_shifter;
+ size_t pos;
+
+ /**
+ * Buffered data; twice the maximum allowed message size as we add some
+ * headers.
+ */
+ 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
/**
};
-
/**
* Create a message stream tokenizer.
*
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;
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)
{
{
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;
}
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... */
{
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;
}
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
* @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) ||
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
/**
- * @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
* 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
* for every radiotap entry we can at
* least skip (by knowing the length)...
*/
-
while (iterator->arg_index < sizeof (rt_sizes))
{
- int hit = 0;
-
- if (!(iterator->bitmap_shifter & 1))
- goto next_entry; /* arg not present */
-
- /*
- * arg is present, account for alignment padding
- * 8-bit args can be at any alignment
- * 16-bit args must start on 16-bit boundary
- * 32-bit args must start on 32-bit boundary
- * 64-bit args must start on 64-bit boundary
- *
- * note that total arg size can differ from alignment of
- * elements inside arg, so we use upper nybble of length
- * table to base alignment on
- *
- * also note: these alignments are ** relative to the
- * start of the radiotap header **. There is no guarantee
- * that the radiotap header itself is aligned on any
- * kind of boundary.
- */
-
- if ((((void *) iterator->arg) -
- ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4)
- - 1))
- iterator->arg_index +=
- (rt_sizes[iterator->arg_index] >> 4) -
- ((((void *) iterator->arg) -
- ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >>
- 4) - 1));
-
- /*
- * this is what we will return to user, but we need to
- * move on first so next call has something fresh to test
- */
-
- iterator->this_arg_index = iterator->arg_index;
- iterator->this_arg = iterator->arg;
- hit = 1;
-
- /* internally move on the size of this arg */
-
- iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
+ int hit = (0 != (iterator->bitmap_shifter & 1));
- /*
- * 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
/**
- * 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
}
+/* ************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.
*
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)
return -1;
}
- memset (buf, 0, buf_size);
- memset (ri, 0, sizeof (*ri));
-
+ memset (ri, 0, sizeof (*ri));
switch (dev->arptype_in)
{
case ARPHRD_IEEE80211_PRISM:
- {
- /* skip the prism header */
- if (tmpbuf[7] == 0x40)
- {
- /* prism54 uses a different format */
- ri->ri_power = tmpbuf[0x33];
- ri->ri_noise = *(unsigned int *) (tmpbuf + 0x33 + 12);
- ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x33 + 24)) * 500000;
- got_signal = 1;
- got_noise = 1;
- n = 0x40;
- }
- else
{
- ri->ri_mactime = *(uint64_t *) (tmpbuf + 0x5C - 48);
- ri->ri_channel = *(unsigned int *) (tmpbuf + 0x5C - 36);
- ri->ri_power = *(unsigned int *) (tmpbuf + 0x5C);
- ri->ri_noise = *(unsigned int *) (tmpbuf + 0x5C + 12);
- ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x5C + 24)) * 500000;
- got_channel = 1;
- got_signal = 1;
- got_noise = 1;
- n = *(int *) (tmpbuf + 4);
+ const struct PrismHeader *ph;
+
+ ph = (const struct PrismHeader*) tmpbuf;
+ n = ph->msglen;
+ if ( (n < 8) || (n >= caplen) )
+ return 0; /* invalid format */
+ if ( (PRISM_MSGCODE_MONITOR == ph->msgcode) &&
+ (n >= sizeof (struct PrismHeader)) )
+ {
+ const char *pos;
+ size_t left;
+ struct PrismValue pv;
+
+ left = n - sizeof (struct PrismHeader);
+ pos = (const char *) &ph[1];
+ while (left > sizeof (struct PrismValue))
+ {
+ left -= sizeof (struct PrismValue);
+ memcpy (&pv, pos, sizeof (struct PrismValue));
+ pos += sizeof (struct PrismValue);
+
+ switch (pv.did)
+ {
+ case PRISM_DID_NOISE:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_noise = pv.data;
+ /* got_noise = 1; */
+ }
+ break;
+ case PRISM_DID_RATE:
+ if (PRISM_STATUS_OK == pv.status)
+ ri->ri_rate = pv.data * 500000;
+ break;
+ case PRISM_DID_CHANNEL:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_channel = pv.data;
+ got_channel = 1;
+ }
+ break;
+ case PRISM_DID_MACTIME:
+ if (PRISM_STATUS_OK == pv.status)
+ ri->ri_mactime = pv.data;
+ break;
+ case PRISM_DID_SIGNAL:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_power = pv.data;
+ /* got_signal = 1; */
+ }
+ break;
+ }
+ }
+ }
+ if ( (n < 8) || (n >= caplen) )
+ return 0; /* invalid format */
}
-
- if ( (n < 8) || (n >= caplen) )
- return 0;
- }
break;
-
case ARPHRD_IEEE80211_FULL:
- {
- struct ieee80211_radiotap_iterator iterator;
- struct ieee80211_radiotap_header *rthdr;
-
- rthdr = (struct ieee80211_radiotap_header *) tmpbuf;
-
- if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen))
- return 0;
-
- /* go through the radiotap arguments we have been given
- * by the driver
- */
-
- while (ieee80211_radiotap_iterator_next (&iterator) >= 0)
{
-
- switch (iterator.this_arg_index)
+ struct Ieee80211RadiotapHeaderIterator iterator;
+ struct Ieee80211RadiotapHeader *rthdr;
+
+ memset (&iterator, 0, sizeof (iterator));
+ rthdr = (struct Ieee80211RadiotapHeader *) tmpbuf;
+ n = GNUNET_le16toh (rthdr->it_len);
+ if ( (n < sizeof (struct Ieee80211RadiotapHeader)) || (n >= caplen))
+ return 0; /* invalid 'it_len' */
+ if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen))
+ return 0;
+ /* go through the radiotap arguments we have been given by the driver */
+ while (0 <= ieee80211_radiotap_iterator_next (&iterator))
{
-
- case IEEE80211_RADIOTAP_TSFT:
- ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg));
- break;
-
- case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
- if (!got_signal)
- {
- if (*iterator.this_arg < 127)
- ri->ri_power = *iterator.this_arg;
- else
- ri->ri_power = *iterator.this_arg - 255;
-
- got_signal = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
- if (!got_signal)
- {
- if (*iterator.this_arg < 127)
- ri->ri_power = *iterator.this_arg;
- else
- ri->ri_power = *iterator.this_arg - 255;
-
- got_signal = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DBM_ANTNOISE:
- if (!got_noise)
- {
- if (*iterator.this_arg < 127)
- ri->ri_noise = *iterator.this_arg;
- else
- ri->ri_noise = *iterator.this_arg - 255;
-
- got_noise = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DB_ANTNOISE:
- if (!got_noise)
- {
- if (*iterator.this_arg < 127)
- ri->ri_noise = *iterator.this_arg;
- else
- ri->ri_noise = *iterator.this_arg - 255;
-
- got_noise = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_ANTENNA:
- ri->ri_antenna = *iterator.this_arg;
- break;
-
- case IEEE80211_RADIOTAP_CHANNEL:
- ri->ri_channel = *iterator.this_arg;
- got_channel = 1;
- break;
-
- case IEEE80211_RADIOTAP_RATE:
- ri->ri_rate = (*iterator.this_arg) * 500000;
- break;
-
- case IEEE80211_RADIOTAP_FLAGS:
- /* is the CRC visible at the end?
- * remove
- */
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS)
- {
- fcs_removed = 1;
- caplen -= 4;
- }
-
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_RX_BADFCS)
- return (0);
-
- break;
- }
- }
- n = GNUNET_le16toh (rthdr->it_len);
- if (n <= 0 || n >= caplen)
- return 0;
- }
+ switch (iterator.this_arg_index)
+ {
+ case IEEE80211_RADIOTAP_TSFT:
+ ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg));
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+ if (!got_signal)
+ {
+ ri->ri_power = * ((int8_t*) iterator.this_arg);
+ got_signal = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ if (!got_signal)
+ {
+ ri->ri_power = * ((int8_t*) iterator.this_arg);
+ got_signal = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+ if (!got_noise)
+ {
+ ri->ri_noise = * ((int8_t*) iterator.this_arg);
+ got_noise = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ if (!got_noise)
+ {
+ ri->ri_noise = * ((int8_t*) iterator.this_arg);
+ got_noise = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_ANTENNA:
+ ri->ri_antenna = *iterator.this_arg;
+ break;
+ case IEEE80211_RADIOTAP_CHANNEL:
+ ri->ri_channel = *iterator.this_arg;
+ got_channel = 1;
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ ri->ri_rate = (*iterator.this_arg) * 500000;
+ break;
+ case IEEE80211_RADIOTAP_FLAGS:
+ {
+ uint8_t flags = *iterator.this_arg;
+ /* is the CRC visible at the end? if so, remove */
+ if (0 != (flags & IEEE80211_RADIOTAP_F_FCS))
+ {
+ fcs_removed = 1;
+ caplen -= sizeof (uint32_t);
+ }
+ break;
+ }
+ case IEEE80211_RADIOTAP_RX_FLAGS:
+ {
+ uint16_t flags = ntohs (* ((uint16_t *) iterator.this_arg));
+ if (0 != (flags & IEEE80211_RADIOTAP_F_RX_BADFCS))
+ return 0;
+ }
+ break;
+ } /* end of 'switch' */
+ } /* end of the 'while' loop */
+ }
break;
case ARPHRD_IEEE80211:
- /* do nothing? */
+ n = 0; /* no header */
break;
+ 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) && (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.
*
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));
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;
}
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))
{
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;
}
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
mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
const struct HardwareInfos *dev)
{
+ 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;
- 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
*/
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
const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader;
size_t sendsize;
- struct RadioTapheader rtheader;
+ struct RadiotapTransmissionHeader rtheader;
+ struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame etheader;
sendsize = ntohs (hdr->size);
if ( (sendsize <
sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
- (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type)) )
+ (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
{
fprintf (stderr, "Received malformed message\n");
exit (1);
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);
}
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_len = GNUNET_htole16 (sizeof (rtheader));
- rtheader.rate = header->rate;
- memcpy (write_pout.buf, &rtheader, sizeof (rtheader));
- wlanheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf[sizeof (rtheader)];
- memcpy (wlanheader, &header->frame, sendsize);
- /* payload contains MAC address, but we don't trust it, so we'll
- * overwrite it with OUR MAC address again to prevent mischief */
- mac_set (wlanheader, dev);
- write_pout.size = sendsize + sizeof (rtheader);
+ switch (dev->arptype_in)
+ {
+ 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;
+ }
}
int stdin_open;
struct MessageStreamTokenizer *stdin_mst;
int raw_eno;
+ uid_t uid;
- memset (&dev, 0, sizeof (dev));
- dev.fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
- raw_eno = errno; /* remember for later */
-
- /* drop privs */
- {
- uid_t uid = getuid ();
+ /* assert privs so we can modify the firewall rules! */
+ 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;
- }
+ 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)
{
return 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;
if (FD_ISSET (dev.fd_raw, &rfds))
{
- struct GNUNET_MessageHeader *header;
- struct Radiotap_rx *rxinfo;
- struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *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 GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &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);