/*
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 <andy@warmcat.com>
- 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
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, 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
*
* 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 <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
+ * (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
* 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;
/**
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
/**
* @param cls closure
* @param message the actual message
*/
-typedef void (*MessageTokenizerCallback) (void *cls,
+typedef void (*MessageTokenizerCallback) (void *cls,
const struct
GNUNET_MessageHeader *
message);
};
-
/**
* 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 */
+ int hit = (0 != (iterator->bitmap_shifter & 1));
- 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 -1;
+ /* 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
/**
- * 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)
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)
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 (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;
- }
+ 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
*/
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;
}
/**
- * 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;
+ uid_t uid;
- dev.fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
- raw_eno = errno; /* remember for later */
+ /* assert privs so we can modify the firewall rules! */
uid = getuid ();
#ifdef HAVE_SETRESUID
- if (0 != setresuid (uid, uid, uid))
+ if (0 != setresuid (uid, 0, 0))
{
- fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
- if (-1 != dev.fd_raw)
- (void) close (dev.fd_raw);
- return 1;
+ fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
+ return 254;
}
#else
- if (0 != (setuid (uid) | seteuid (uid)))
+ if (0 != seteuid (0))
{
- fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
- if (-1 != dev.fd_raw)
- (void) close (dev.fd_raw);
- return 1;
+ 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)
{
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);
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)
}
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));
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);