gnunet-helper-transport-wlan.c   gnunet-helper-transport-wlan.c 
/* /*
This file is part of GNUnet. 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) 2007, 2008, Andy Green <andy@warmcat.com>
Copyright (C) 2009 Thomas d'Otreppe Copyright (C) 2009 Thomas d'Otreppe
GNUnet is free software; you can redistribute it and/or modify GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your by the Free Software Foundation; either version 3, or (at your
option) any later version. option) any later version.
GNUnet is distributed in the hope that it will be useful, but GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the along with GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330, Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. Boston, MA 02111-1307, USA.
*/ */
/** /**
* @file src/transport/gnunet-helper-transport-wlan.c * @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. * This code will work under GNU/Linux only.
* @author David Brodski * @author David Brodski
* @author Christian Grothoff
* *
* This program serves as the mediator between the wlan interface and * This program will allow receiving and sending traffic from the WLAN
* gnunet * 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 * we use our local copy of ieee80211_radiotap.h
* *
* - since we can't support extensions we don't understand * - since we can't support extensions we don't understand
* - since linux does not include it in userspace headers * - since linux does not include it in userspace headers
* *
* Portions of this code were taken from the ieee80211_radiotap.h header, * Portions of this code were taken from the ieee80211_radiotap.h header,
* which is * which is
skipping to change at line 73 skipping to change at line 109
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE. * OF SUCH DAMAGE.
*/ */
/* /*
* Modifications to fit into the linux IEEE 802.11 stack, * Modifications to fit into the linux IEEE 802.11 stack,
* Mike Kershaw (dragorn@kismetwireless.net) * Mike Kershaw (dragorn@kismetwireless.net)
*/ */
/*
/**
* parts taken from aircrack-ng, parts changend. * parts taken from aircrack-ng, parts changend.
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <netpacket/packet.h> #include <netpacket/packet.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
skipping to change at line 105 skipping to change at line 141
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>
#include <sys/param.h> #include <sys/param.h>
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include "gnunet_protocols.h" #include "gnunet_protocols.h"
#include "plugin_transport_wlan.h" #include "plugin_transport_wlan.h"
/**
* Packet format type for the messages we receive from
* the kernel. This is for plain messages (with no
* performance information included).
*/
#define ARPHRD_IEEE80211 801 #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_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 MAXLINE 4096
#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK 0x80000000 /* ********* structure of messages of type ARPHRD_IEEE80211_PRISM ********* ** */
/* Name Data type Units /**
* ---- --------- ----- * Device name length in PRISM frames.
* * (In the kernel, this is "WLAN_DEVNAMELEN_MAX")
* IEEE80211_RADIOTAP_TSFT __le64 microseconds */
* #define PRISM_DEVICE_NAME_LENGTH 16
* 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. * Monitor Frame (indicator that we have a 'struct PrismHeader').
* */
* IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap #define PRISM_MSGCODE_MONITOR 0x0041
*
* Tx/Rx frequency in MHz, followed by flags (see below). /**
* * Mac time element. In micro-seconds.
* IEEE80211_RADIOTAP_FHSS __le16 see below * Drivers appear to use a 64bit counter to hold mactime internal
* * the then fill the prism header with the lower 32 bits
* For frequency-hopping radios, the hop set (first byte) */
* and pattern (second byte). #define PRISM_DID_MACTIME 0x2041
*
* IEEE80211_RADIOTAP_RATE uint8_t 500kb/s /**
* * Channel element
* Tx/Rx data rate */
* #define PRISM_DID_CHANNEL 0x3041
* IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
* one milliwatt (dBm) /**
* * Signal element. Should be the signal strength in dbm, some people
* RF signal power at the antenna, decibel difference from * suggest that instead "100 - (strength in dbm)" is used (to make this
* one milliwatt. * a positive integer).
* */
* IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from #define PRISM_DID_SIGNAL 0x6041
* one milliwatt (dBm)
* /**
* RF noise power at the antenna, decibel difference from one * Noise element
* milliwatt. */
* #define PRISM_DID_NOISE 0x7041
* IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
* /**
* RF signal power at the antenna, decibel difference from an * Rate element, in units/multiples of 500Khz
* arbitrary, fixed reference. */
* #define PRISM_DID_RATE 0x8041
* IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
* /**
* RF noise power at the antenna, decibel difference from an * Value is set (supplied)
* arbitrary, fixed reference point. */
* #define PRISM_STATUS_OK 0
* IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
* /**
* Quality of Barker code lock. Unitless. Monotonically * Value not supplied.
* nondecreasing with "better" lock strength. Called "Signal */
* Quality" in datasheets. (Is there a standard way to measure #define PRISM_STATUS_NO_VALUE 1
* this?)
* /**
* IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless * Values in the 'struct PrismHeader'. All in host byte order (!).
* */
* Transmit power expressed as unitless distance from max struct PrismValue
* power set at factory calibration. 0 is max power. {
* Monotonically nondecreasing with lower power levels. /**
* * This has a different ID for each parameter, see
* IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB) * PRISM_DID_* constants.
* */
* Transmit power expressed as decibel distance from max power uint32_t did;
* set at factory calibration. 0 is max power. Monotonically
* nondecreasing with lower power levels. /**
* * See PRISM_STATUS_*-constants. Note that they are unusual: 0 = set; 1
* IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from = not set
* one milliwatt (dBm) */
* uint16_t status;
* Transmit power expressed as dBm (decibels from a 1 milliwatt
* reference). This is the absolute power level measured at /**
* the antenna port. * length of data (which is always a uint32_t, but presumably this can be
* used
* IEEE80211_RADIOTAP_FLAGS uint8_t bitmap * to specify that fewer bytes are used (with values in 'len' from 0-4).
* We
* Properties of transmitted and received frames. See flags * ignore this field.
* defined below. */
* uint16_t len;
* IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
* /**
* Unitless indication of the Rx/Tx antenna for this packet. * The data value
* The first antenna is antenna 0. */
* uint32_t data;
* IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
* } __attribute__ ((packed));
* Properties of received frames. See flags defined below.
* /**
* IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap * Prism header format ('struct p80211msg' in Linux). All in host byte ord
* er (!).
* Properties of transmitted frames. See flags defined below. */
* struct PrismHeader
* IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data {
* /**
* Number of rts retries a transmitted frame used. * We expect this to be a PRISM_MSGCODE_*.
* */
* IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data uint32_t msgcode;
*
* Number of unicast retries a transmitted frame used. /**
* * 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 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_TSFT = 0,
/**
* IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
*
* Properties of transmitted and received frames. See flags
* defined below.
*/
IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_FLAGS = 1,
/**
* IEEE80211_RADIOTAP_RATE uint8_t 500kb/s
*
* Tx/Rx data rate
*/
IEEE80211_RADIOTAP_RATE = 2, 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_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_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_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_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_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_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_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_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_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_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_DB_ANTNOISE = 13,
/**
* IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
*
* Properties of received frames. See flags defined below.
*/
IEEE80211_RADIOTAP_RX_FLAGS = 14, 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_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_RTS_RETRIES = 16,
/**
* IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data
*
* Number of unicast retries a transmitted frame used.
*/
IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_DATA_RETRIES = 17,
/**
* Extension bit, used to indicate that more bits are needed for
* the bitmask.
*/
IEEE80211_RADIOTAP_EXT = 31 IEEE80211_RADIOTAP_EXT = 31
}; };
/* For IEEE80211_RADIOTAP_FLAGS */ /**
#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received * Bitmask indicating an extension of the bitmask is used.
* during CFP * (Mask corresponding to IEEE80211_RADIOTAP_EXT).
*/ */
#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received #define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK (1 << IEEE80211_RADIOTAP_EXT
* with short )
* preamble
*/ /**
#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
* with WEP encryption * as part of a 'struct Ieee80211RadiotapHeader' extension
*/ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received * 'it_present'). The radiotap flags are an 8-bit field.
* with fragmentation *
*/ * Frame was sent/received during CFP (Contention Free Period)
#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FC */
S */ #define IEEE80211_RADIOTAP_F_CFP 0x01
#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding
between /**
* 802.11 header and payloa * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
d * as part of a 'struct Ieee80211RadiotapHeader' extension
* (to 32-bit boundary) * if the IEEE80211_RADIOTAP_FLAGS bit is set in
*/ * 'it_present'). The radiotap flags are an 8-bit field.
/* 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 */
/**
* 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.
* *
* I suggest the following extensible radio capture format. It is * Frame was sent/received with short preamble
* based on a bitmap indicating which fields are present. */
#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 RadiotapTransmissi
onHeader'):
* failed due to excessive retries
*/
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001
/**
* For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissi
onHeader'):
* used cts 'protection'
*/
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002
/**
* For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissi
onHeader'):
* used rts/cts handshake
*/
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004
/**
* For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissi
onHeader'):
* frame should not be ACKed
*/
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008
/**
* For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissi
onHeader'):
* 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 * I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the * should expect in the following, and for that reason I tell the
* units and origin of each measurement (where it applies), or else I * units and origin of each measurement (where it applies), or else I
* use sufficiently weaselly language ("is a monotonically nondecreasing * use sufficiently weaselly language ("is a monotonically nondecreasing
* function of...") that I cannot set false expectations for lawyerly * function of...") that I cannot set false expectations for lawyerly
* readers. * readers.
* *
* The radio capture header precedes the 802.11 header. * The radio capture header precedes the 802.11 header.
* All data in the header is little endian on all platforms. * 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 * Version 0. Only increases for drastic changes, introduction of
* compatible new fields does not count. * compatible new fields does not count.
*/ */
uint8_t it_version; uint8_t it_version;
/**
* Padding. Set to 0.
*/
uint8_t it_pad; uint8_t it_pad;
/** /**
* length of the whole header in bytes, including it_version, * length of the whole header in bytes, including it_version,
* it_pad, it_len, and data fields. * it_pad, it_len, and data fields.
*/ */
uint16_t it_len; uint16_t it_len;
/** /**
* A bitmap telling which fields are present. Set bit 31 * A bitmap telling which fields are present. Set bit 31
* (0x80000000) to extend the bitmap by another 32 bits. Additional * (0x80000000) to extend the bitmap by another 32 bits. Additional
* extensions are made by setting bit 31. * extensions are made by setting bit 31.
*/ */
uint32_t it_present; 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; 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; uint8_t pad1;
/** /**
* * Transmission flags from on the IEEE80211_RADIOTAP_F_TX_* constant fami ly.
*/ */
uint16_t txflags; uint16_t txflags;
}; };
/** /**
* IO buffer used for buffering data in transit (to wireless or to stdout). * 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 #define IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK ((1 << IEEE80211_RA
DIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_TX_FLAGS))
/**
* struct Ieee80211RadiotapHeaderIterator - tracks walk through present rad
iotap arguments
* in the radiotap header. Used when we parse radiotap packets received fr
om the kernel.
*/
struct Ieee80211RadiotapHeaderIterator
{ {
/** /**
* How many bytes of data are stored in 'buf' for transmission right now? * pointer to the radiotap header we are walking through
* Data always starts at offset 0 and extends to 'size'.
*/ */
size_t size; const struct Ieee80211RadiotapHeader *rtheader;
/** /**
* How many bytes that were stored in 'buf' did we already write to the * pointer to current radiotap arg
* destination? Always smaller than 'size'.
*/ */
size_t pos; const uint8_t *this_arg;
/** /**
* Buffered data; twice the maximum allowed message size as we add some * internal next argument pointer
* headers.
*/ */
char buf[MAXLINE * 2]; const uint8_t *arg;
};
/** /**
* Buffer for data read from stdin to be transmitted to the wirless card. * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT i
*/ s used).
static struct SendBuffer write_pout; */
const uint32_t *next_bitmap;
/** /**
* Buffer for data read from the wireless card to be transmitted to stdout. * length of radiotap header in host byte ordering
*/ */
static struct SendBuffer write_std; size_t max_length;
GNUNET_NETWORK_STRUCT_BEGIN /**
* 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;
/** /**
* generic definitions for IEEE 802.11 frames * IEEE80211_RADIOTAP_... index of current arg
*/ */
struct ieee80211_frame unsigned int this_arg_index;
{
uint8_t i_fc[2]; /**
uint8_t i_dur[2]; * internal next argument index
uint8_t i_addr1[IEEE80211_ADDR_LEN]; */
uint8_t i_addr2[IEEE80211_ADDR_LEN]; unsigned int arg_index;
uint8_t i_addr3[IEEE80211_ADDR_LEN];
uint8_t i_seq[2]; };
/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
/* see below */ /* ************** end of structure of ARPHRD_IEEE80211_FULL **************
} GNUNET_PACKED; */
GNUNET_NETWORK_STRUCT_END
/* ************************** our globals ******************************* *
/
/** /**
* struct for storing the information of the hardware * struct for storing the information of the hardware. There is only
* one of these.
*/ */
struct HardwareInfos struct HardwareInfos
{ {
/** /**
* file descriptor for the raw socket * file descriptor for the raw socket
*/ */
int fd_raw; int fd_raw;
/** /**
skipping to change at line 420 skipping to change at line 714
*/ */
char iface[IFNAMSIZ]; char iface[IFNAMSIZ];
/** /**
* MAC address of our own WLAN interface. * MAC address of our own WLAN interface.
*/ */
struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac; struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
}; };
/** /**
* struct ieee80211_radiotap_iterator - tracks walk through present radiota * IO buffer used for buffering data in transit (to wireless or to stdout).
p arguments
* in the radiotap header.
*/ */
struct ieee80211_radiotap_iterator struct SendBuffer
{ {
/** /**
* pointer to the radiotap header we are walking through * How many bytes of data are stored in 'buf' for transmission right now?
*/ * Data always starts at offset 0 and extends to 'size'.
const struct ieee80211_radiotap_header *rtheader;
/**
* length of radiotap header in cpu byte ordering
*/
size_t max_length;
/**
* IEEE80211_RADIOTAP_... index of current arg
*/
unsigned int this_arg_index;
/**
* pointer to current radiotap arg
*/ */
uint8_t *this_arg; size_t size;
/** /**
* internal next argument index * How many bytes that were stored in 'buf' did we already write to the
* destination? Always smaller than 'size'.
*/ */
unsigned int arg_index; size_t pos;
/** /**
* internal next argument pointer * Buffered data; twice the maximum allowed message size as we add some
* headers.
*/ */
uint8_t *arg; char buf[MAXLINE * 2];
};
/** /**
* internal pointer to next present uint32_t * Buffer for data read from stdin to be transmitted to the wirless card.
*/ */
uint32_t *next_bitmap; static struct SendBuffer write_pout;
/** /**
* internal shifter for curr uint32_t bitmap, b0 set == arg present * Buffer for data read from the wireless card to be transmitted to stdout.
*/ */
uint32_t bitmap_shifter; 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 everyo
ne
* for now.
*/
#define ALIGN_FACTOR 8 #define ALIGN_FACTOR 8
/** /**
* Smallest supported message. * Smallest supported message.
*/ */
#define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader) #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
/** /**
* Functions with this signature are called whenever a * Functions with this signature are called whenever a
* complete message is received by the tokenizer. * complete message is received by the tokenizer.
skipping to change at line 540 skipping to change at line 825
* @return handle to tokenizer * @return handle to tokenizer
*/ */
static struct MessageStreamTokenizer * static struct MessageStreamTokenizer *
mst_create (MessageTokenizerCallback cb, mst_create (MessageTokenizerCallback cb,
void *cb_cls) void *cb_cls)
{ {
struct MessageStreamTokenizer *ret; struct MessageStreamTokenizer *ret;
ret = malloc (sizeof (struct MessageStreamTokenizer)); ret = malloc (sizeof (struct MessageStreamTokenizer));
if (NULL == ret) if (NULL == ret)
{
fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
exit (1); exit (1);
}
ret->hdr = malloc (MIN_BUFFER_SIZE); ret->hdr = malloc (MIN_BUFFER_SIZE);
if (NULL == ret->hdr) if (NULL == ret->hdr)
exit (2); {
fprintf (stderr, "Failed to allocate buffer for alignment\n");
exit (1);
}
ret->curr_buf = MIN_BUFFER_SIZE; ret->curr_buf = MIN_BUFFER_SIZE;
ret->cb = cb; ret->cb = cb;
ret->cb_cls = cb_cls; ret->cb_cls = cb_cls;
return ret; return ret;
} }
/** /**
* Add incoming data to the receive buffer and call the * Add incoming data to the receive buffer and call the
* callback for all complete messages. * callback for all complete messages.
* *
skipping to change at line 603 skipping to change at line 894
size -= delta; size -= delta;
} }
if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
{ {
return GNUNET_OK; return GNUNET_OK;
} }
hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
want = ntohs (hdr->size); want = ntohs (hdr->size);
if (want < sizeof (struct GNUNET_MessageHeader)) if (want < sizeof (struct GNUNET_MessageHeader))
{ {
// GNUNET_break_op (0); fprintf (stderr,
return GNUNET_SYSERR; "Received invalid message from stdin\n");
exit (1);
} }
if (mst->curr_buf - mst->off < want) if (mst->curr_buf - mst->off < want)
{ {
/* need more space */ /* need more space */
mst->pos -= mst->off; mst->pos -= mst->off;
memmove (ibuf, &ibuf[mst->off], mst->pos); memmove (ibuf, &ibuf[mst->off], mst->pos);
mst->off = 0; mst->off = 0;
} }
if (want > mst->curr_buf) if (want > mst->curr_buf)
{ {
mst->hdr = realloc (mst->hdr, want); mst->hdr = realloc (mst->hdr, want);
if (NULL == mst->hdr) if (NULL == mst->hdr)
exit (3); {
fprintf (stderr, "Failed to allocate buffer for alignment\n");
exit (1);
}
ibuf = (char *) mst->hdr; ibuf = (char *) mst->hdr;
mst->curr_buf = want; mst->curr_buf = want;
} }
hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
if (mst->pos - mst->off < want) if (mst->pos - mst->off < want)
{ {
delta = GNUNET_MIN (want - (mst->pos - mst->off), size); delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
memcpy (&ibuf[mst->pos], buf, delta); memcpy (&ibuf[mst->pos], buf, delta);
mst->pos += delta; mst->pos += delta;
buf += delta; buf += delta;
skipping to change at line 656 skipping to change at line 951
break; break;
offset = (unsigned long) buf; offset = (unsigned long) buf;
need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO; need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
if (GNUNET_NO == need_align) if (GNUNET_NO == need_align)
{ {
/* can try to do zero-copy and process directly from original buffer */ /* can try to do zero-copy and process directly from original buffer */
hdr = (const struct GNUNET_MessageHeader *) buf; hdr = (const struct GNUNET_MessageHeader *) buf;
want = ntohs (hdr->size); want = ntohs (hdr->size);
if (want < sizeof (struct GNUNET_MessageHeader)) if (want < sizeof (struct GNUNET_MessageHeader))
{ {
// GNUNET_break_op (0); fprintf (stderr,
mst->off = 0; "Received invalid message from stdin\n");
return GNUNET_SYSERR; exit (1);
} }
if (size < want) if (size < want)
break; /* or not, buffer incomplete, so copy to pr ivate buffer... */ break; /* or not, buffer incomplete, so copy to pr ivate buffer... */
mst->cb (mst->cb_cls, hdr); mst->cb (mst->cb_cls, hdr);
buf += want; buf += want;
size -= want; size -= want;
} }
else else
{ {
/* need to copy to private buffer to align; /* need to copy to private buffer to align;
* yes, we go a bit more spagetti than usual here */ * yes, we go a bit more spagetti than usual here */
goto do_align; goto do_align;
} }
} }
if (size > 0) if (size > 0)
{ {
if (size + mst->pos > mst->curr_buf) if (size + mst->pos > mst->curr_buf)
{ {
mst->hdr = realloc (mst->hdr, size + mst->pos); mst->hdr = realloc (mst->hdr, size + mst->pos);
if (NULL == mst->hdr) if (NULL == mst->hdr)
exit (4); {
fprintf (stderr, "Failed to allocate buffer for alignment\n");
exit (1);
}
ibuf = (char *) mst->hdr; ibuf = (char *) mst->hdr;
mst->curr_buf = size + mst->pos; 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); memcpy (&ibuf[mst->pos], buf, size);
mst->pos += size; mst->pos += size;
} }
return ret; return ret;
} }
/** /**
* Destroys a tokenizer. * Destroys a tokenizer.
* *
* @param mst tokenizer to destroy * @param mst tokenizer to destroy
*/ */
static void static void
mst_destroy (struct MessageStreamTokenizer *mst) mst_destroy (struct MessageStreamTokenizer *mst)
{ {
free (mst->hdr); free (mst->hdr);
free (mst); free (mst);
} }
/* end of server_mst.c copy */ /* ***************** end of server_mst.c clone ***************** **/
/* ************** code for handling of ARPHRD_IEEE80211_FULL **************
*/
/** /**
* Radiotap header iteration * Radiotap header iteration
* *
* call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
* struct ieee80211_radiotap_iterator (no need to init the struct beforehan d) * struct Ieee80211RadiotapHeaderIterator (no need to init the struct befor ehand)
* then loop calling __ieee80211_radiotap_iterator_next()... it returns -1 * 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 * 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 * that is present. The iterator's this_arg member points to the start of the
* argument associated with the current argument index that is present, * argument associated with the current argument index that is present,
* which can be found in the iterator's this_arg_index member. This arg * which can be found in the iterator's this_arg_index member. This arg
* index corresponds to the IEEE80211_RADIOTAP_... defines. * index corresponds to the IEEE80211_RADIOTAP_... defines.
* *
* @param iterator iterator to initialize * @param iterator iterator to initialize
* @param radiotap_header message to parse * @param radiotap_header message to parse
* @param max_length number of valid bytes in radiotap_header * @param max_length number of valid bytes in radiotap_header
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
static int static int
ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *itera ieee80211_radiotap_iterator_init (struct Ieee80211RadiotapHeaderIterator *i
tor, terator,
const struct ieee80211_radiotap_header const struct Ieee80211RadiotapHeader *rad
*radiotap_header, iotap_header,
size_t max_length) size_t max_length)
{ {
if ( (iterator == NULL) || if ( (iterator == NULL) ||
(radiotap_header == NULL) ) (radiotap_header == NULL) )
return -1; return -1;
/* Linux only supports version 0 radiotap format */ /* Linux only supports version 0 radiotap format */
if (0 != radiotap_header->it_version) if (0 != radiotap_header->it_version)
return -1; return -1;
/* sanity check for allowed length and radiotap length field */ /* 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))) ) (max_length < (GNUNET_le16toh (radiotap_header->it_len))) )
return -1; return -1;
memset (iterator, 0, sizeof (struct Ieee80211RadiotapHeaderIterator));
iterator->rtheader = radiotap_header; iterator->rtheader = radiotap_header;
iterator->max_length = GNUNET_le16toh (radiotap_header->it_len); iterator->max_length = GNUNET_le16toh (radiotap_header->it_len);
iterator->arg_index = 0;
iterator->bitmap_shifter = GNUNET_le32toh (radiotap_header->it_present); iterator->bitmap_shifter = GNUNET_le32toh (radiotap_header->it_present);
iterator->arg = iterator->arg = ((uint8_t *) radiotap_header) + sizeof (struct Ieee80211R
((uint8_t *) radiotap_header) + sizeof (struct ieee80211_radiotap_hea adiotapHeader);
der);
iterator->this_arg = 0;
/* find payload start allowing for extended bitmap(s) */ /* 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_MA SK))
{ {
while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & IEEE80211_RADIO
IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK) TAP_PRESENT_EXTEND_MASK)
{ {
iterator->arg += sizeof (uint32_t); iterator->arg += sizeof (uint32_t);
/* /*
* check for insanity where the present bitmaps * check for insanity where the present bitmaps
* keep claiming to extend up to or even beyond the * keep claiming to extend up to or even beyond the
* stated radiotap header length * stated radiotap header length
*/ */
if (iterator->arg - ((uint8_t*) iterator->rtheader) > iterator->max_l ength) if (iterator->arg - ((uint8_t*) iterator->rtheader) > iterator->max_l ength)
return -1; return -1;
} }
iterator->arg += sizeof (uint32_t); iterator->arg += sizeof (uint32_t);
/* /*
* no need to check again for blowing past stated radiotap * no need to check again for blowing past stated radiotap
* header length, becuase ieee80211_radiotap_iterator_next * header length, becuase ieee80211_radiotap_iterator_next
* checks it before it is dereferenced * checks it before it is dereferenced
*/ */
} }
/* we are all initialized happily */ /* we are all initialized happily */
return 0; return 0;
} }
/** /**
* @brief ieee80211_radiotap_iterator_next - return next radiotap parser it erator arg * Returns the next radiotap parser iterator arg.
* *
* This function returns the next radiotap arg index (IEEE80211_RADIOTAP_.. .) * This function returns the next radiotap arg index (IEEE80211_RADIOTAP_.. .)
* and sets iterator->this_arg to point to the payload for the arg. It tak es * and sets iterator->this_arg to point to the payload for the arg. It tak es
* care of alignment handling and extended present fields. interator->this _arg * care of alignment handling and extended present fields. interator->this _arg
* can be changed by the caller. The args pointed to are in little-endian * can be changed by the caller. The args pointed to are in little-endian
* format. * format.
* *
* @param iterator: radiotap_iterator to move to next arg (if any) * @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 * @return next present arg index on success or -1 if no more or error
*/ */
static int static int
ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *itera tor) ieee80211_radiotap_iterator_next (struct Ieee80211RadiotapHeaderIterator *i terator)
{ {
/* /*
* small length lookup table for all radiotap types we heard of * small length lookup table for all radiotap types we heard of
* starting from b0 in the bitmap, so we can walk the payload * starting from b0 in the bitmap, so we can walk the payload
* area of the radiotap header * area of the radiotap header
* *
* There is a requirement to pad args, so that args * There is a requirement to pad args, so that args
* of a given length must begin at a boundary of that length * of a given length must begin at a boundary of that length
* -- but note that compound args are allowed (eg, 2 x uint16_t * -- but note that compound args are allowed (eg, 2 x uint16_t
* for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
* a reliable indicator of alignment requirement. * a reliable indicator of alignment requirement.
skipping to change at line 836 skipping to change at line 1134
/* /*
* add more here as they are defined in * add more here as they are defined in
* include/net/ieee80211_radiotap.h * include/net/ieee80211_radiotap.h
*/ */
}; };
/* /*
* for every radiotap entry we can at * for every radiotap entry we can at
* least skip (by knowing the length)... * least skip (by knowing the length)...
*/ */
while (iterator->arg_index < sizeof (rt_sizes)) while (iterator->arg_index < sizeof (rt_sizes))
{ {
int hit = 0; int hit = (0 != (iterator->bitmap_shifter & 1));
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; 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->rtheade
r)) & (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 * this is what we will return to user, but we need to
* claims to have more arg content than the length of the * move on first so next call has something fresh to test
* radiotap section. We will normally end up equalling this */
* max_length on the last arg, never exceeding it. iterator->this_arg_index = iterator->arg_index;
*/ iterator->this_arg = iterator->arg;
if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > /* internally move on the size of this arg (using lower nybble from
iterator->max_length) the table) */
return -1; 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)) > iter
ator->max_length)
return -1;
}
/* Now, move on to next bit / next entry */
iterator->arg_index++; iterator->arg_index++;
if (((iterator->arg_index & 31) == 0))
if (0 == (iterator->arg_index % 32))
{ {
/* completed current uint32_t bitmap */ /* completed current uint32_t bitmap */
if (iterator->bitmap_shifter & 1) if (0 != (iterator->bitmap_shifter & 1))
{ {
/* b31 was set, there is more */ /* bit 31 was set, there is more; move to next uint32_t bitmap */
/* move to next uint32_t bitmap */
iterator->bitmap_shifter = GNUNET_le32toh (*iterator->next_bitmap); iterator->bitmap_shifter = GNUNET_le32toh (*iterator->next_bitmap);
iterator->next_bitmap++; iterator->next_bitmap++;
} }
else else
{ {
/* no more bitmaps: end */ /* no more bitmaps: end (by setting arg_index to high, unsupported value) */
iterator->arg_index = sizeof (rt_sizes); iterator->arg_index = sizeof (rt_sizes);
} }
} }
else else
{ /* just try the next bit */ {
/* just try the next bit (while loop will move on) */
iterator->bitmap_shifter >>= 1; iterator->bitmap_shifter >>= 1;
} }
/* if we found a valid arg earlier, return it now */ /* if we found a valid arg earlier, return it now */
if (hit) if (hit)
return iterator->this_arg_index; return iterator->this_arg_index;
} }
/* we don't know how to handle any more args, we're done */ /* we don't know how to handle any more args (or there are no more),
so we're done (this is not an error) */
return -1; return -1;
} }
/** /**
* Return the channel from the frequency (in Mhz) * Calculate crc32, the start of the calculation
* @param frequency of the channel
* @return number of the channel
*/
static int
get_channel_from_frequency (int frequency)
{
if (frequency >= 2412 && frequency <= 2472)
return (frequency - 2407) / 5;
if (frequency == 2484)
return 14;
if (frequency >= 5000 && frequency <= 6100)
return (frequency - 5000) / 5;
return -1;
}
/**
* function to calculate the crc, the start of the calculation
* *
* @param buf buffer to calc the crc * @param buf buffer to calc the crc
* @param len len of the buffer * @param len len of the buffer
* @return crc sum * @return crc sum
*/ */
static unsigned long static unsigned long
calc_crc_osdep (const unsigned char *buf, size_t len) calc_crc_osdep (const unsigned char *buf, size_t len)
{ {
static const unsigned long int crc_tbl_osdep[256] = { static const unsigned long int crc_tbl_osdep[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
skipping to change at line 1031 skipping to change at line 1313
}; };
unsigned long crc = 0xFFFFFFFF; unsigned long crc = 0xFFFFFFFF;
for (; len > 0; len--, buf++) for (; len > 0; len--, buf++)
crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8); crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
return (~crc); return (~crc);
} }
/** /**
* 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, * @param buf buffer of the packet, with len + 4 bytes of data,
* the last 4 bytes being the checksum * the last 4 bytes being the checksum
* @param len length of the payload in data * @param len length of the payload in data
* @return 0 on success (checksum matches), 1 on error * @return 0 on success (checksum matches), 1 on error
*/ */
static int static int
check_crc_buf_osdep (const unsigned char *buf, size_t len) check_crc_buf_osdep (const unsigned char *buf, size_t len)
{ {
unsigned long crc; unsigned long crc;
crc = calc_crc_osdep (buf, len); crc = calc_crc_osdep (buf, len);
buf += len; buf += len;
if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3]) ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
return 0; return 0;
return 1; 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;
}
/** /**
* Get the channel used by our WLAN interface. * Get the channel used by our WLAN interface.
* *
* @param dev pointer to the dev struct of the card * @param dev pointer to the dev struct of the card
* @return channel number, -1 on error * @return channel number, -1 on error
*/ */
static int static int
linux_get_channel (const struct HardwareInfos *dev) linux_get_channel (const struct HardwareInfos *dev)
{ {
struct iwreq wrq; struct iwreq wrq;
int fd; int32_t frequency;
int frequency;
int chan;
memset (&wrq, 0, sizeof (struct iwreq)); memset (&wrq, 0, sizeof (struct iwreq));
strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ); strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
fd = dev->fd_raw; if (0 > ioctl (dev->fd_raw, SIOCGIWFREQ, &wrq))
if (0 > ioctl (fd, SIOCGIWFREQ, &wrq))
return -1; return -1;
frequency = wrq.u.freq.m; /* 'iw_freq' defines 'm' as '__s32', so we keep
frequency = wrq.u.freq.m; it signed */
if (100000000 < frequency) if (100000000 < frequency)
frequency /= 100000; frequency /= 100000;
else if (1000000 < frequency) else if (1000000 < frequency)
frequency /= 1000; frequency /= 1000;
if (1000 < frequency) if (1000 < frequency)
chan = get_channel_from_frequency (frequency); return get_channel_from_frequency (frequency);
else return frequency;
chan = frequency;
return chan;
} }
/** /**
* 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 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_TRA
NSPORT_WLAN_Ieee80211Frame',
* followed by the actual payload
* @param buf_size size of the buffer * @param buf_size size of the buffer
* @param ri radiotap_rx info * @param ri where to write radiotap_rx info
* @return size read from the buffer * @return number of bytes written to 'buf'
*/ */
static ssize_t static ssize_t
linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size, linux_read (struct HardwareInfos *dev,
struct Radiotap_rx *ri) unsigned char *buf, size_t buf_size,
struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
{ {
unsigned char tmpbuf[buf_size]; unsigned char tmpbuf[buf_size];
ssize_t caplen; ssize_t caplen;
int n, got_signal, got_noise, got_channel, fcs_removed; size_t n;
int got_signal = 0;
n = got_signal = got_noise = got_channel = fcs_removed = 0; int got_noise = 0;
int got_channel = 0;
int fcs_removed = 0;
caplen = read (dev->fd_raw, tmpbuf, buf_size); caplen = read (dev->fd_raw, tmpbuf, buf_size);
if (0 > caplen) if (0 > caplen)
{ {
if (EAGAIN == errno) if (EAGAIN == errno)
return 0; return 0;
fprintf (stderr, "Failed to read from RAW socket: %s\n", strerror (errn o)); fprintf (stderr, "Failed to read from RAW socket: %s\n", strerror (errn o));
return -1; return -1;
} }
memset (buf, 0, buf_size);
memset (ri, 0, sizeof (*ri)); memset (ri, 0, sizeof (*ri));
switch (dev->arptype_in) switch (dev->arptype_in)
{ {
case ARPHRD_IEEE80211_PRISM: case ARPHRD_IEEE80211_PRISM:
{
/* skip the prism header */
if (tmpbuf[7] == 0x40)
{ {
/* prism54 uses a different format */ const struct PrismHeader *ph;
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);
}
if ( (n < 8) || (n >= caplen) ) ph = (const struct PrismHeader*) tmpbuf;
return 0; 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 */
}
break; break;
case ARPHRD_IEEE80211_FULL: 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)
{ {
struct Ieee80211RadiotapHeaderIterator iterator;
struct Ieee80211RadiotapHeader *rthdr;
switch (iterator.this_arg_index) 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))
{ {
switch (iterator.this_arg_index)
case IEEE80211_RADIOTAP_TSFT: {
ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg)) case IEEE80211_RADIOTAP_TSFT:
; ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg)
break; );
break;
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
if (!got_signal) if (!got_signal)
{ {
if (*iterator.this_arg < 127) ri->ri_power = * ((int8_t*) iterator.this_arg);
ri->ri_power = *iterator.this_arg; got_signal = 1;
else }
ri->ri_power = *iterator.this_arg - 255; break;
case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
got_signal = 1; if (!got_signal)
} {
break; ri->ri_power = * ((int8_t*) iterator.this_arg);
got_signal = 1;
case IEEE80211_RADIOTAP_DB_ANTSIGNAL: }
if (!got_signal) break;
{ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
if (*iterator.this_arg < 127) if (!got_noise)
ri->ri_power = *iterator.this_arg; {
else ri->ri_noise = * ((int8_t*) iterator.this_arg);
ri->ri_power = *iterator.this_arg - 255; got_noise = 1;
}
got_signal = 1; break;
} case IEEE80211_RADIOTAP_DB_ANTNOISE:
break; if (!got_noise)
{
case IEEE80211_RADIOTAP_DBM_ANTNOISE: ri->ri_noise = * ((int8_t*) iterator.this_arg);
if (!got_noise) got_noise = 1;
{ }
if (*iterator.this_arg < 127) break;
ri->ri_noise = *iterator.this_arg; case IEEE80211_RADIOTAP_ANTENNA:
else ri->ri_antenna = *iterator.this_arg;
ri->ri_noise = *iterator.this_arg - 255; break;
case IEEE80211_RADIOTAP_CHANNEL:
got_noise = 1; ri->ri_channel = *iterator.this_arg;
} got_channel = 1;
break; break;
case IEEE80211_RADIOTAP_RATE:
case IEEE80211_RADIOTAP_DB_ANTNOISE: ri->ri_rate = (*iterator.this_arg) * 500000;
if (!got_noise) break;
{ case IEEE80211_RADIOTAP_FLAGS:
if (*iterator.this_arg < 127) {
ri->ri_noise = *iterator.this_arg; uint8_t flags = *iterator.this_arg;
else /* is the CRC visible at the end? if so, remove */
ri->ri_noise = *iterator.this_arg - 255; if (0 != (flags & IEEE80211_RADIOTAP_F_FCS))
{
got_noise = 1; fcs_removed = 1;
} caplen -= sizeof (uint32_t);
break; }
break;
case IEEE80211_RADIOTAP_ANTENNA: }
ri->ri_antenna = *iterator.this_arg; case IEEE80211_RADIOTAP_RX_FLAGS:
break; {
uint16_t flags = ntohs (* ((uint16_t *) iterator.this_arg));
case IEEE80211_RADIOTAP_CHANNEL: if (0 != (flags & IEEE80211_RADIOTAP_F_RX_BADFCS))
ri->ri_channel = *iterator.this_arg; return 0;
got_channel = 1; }
break; break;
} /* end of 'switch' */
case IEEE80211_RADIOTAP_RATE: } /* end of the 'while' loop */
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;
}
break; break;
case ARPHRD_IEEE80211: case ARPHRD_IEEE80211:
/* do nothing? */ n = 0; /* no header */
break; break;
default: default:
errno = ENOTSUP; errno = ENOTSUP; /* unsupported format */
return -1; return -1;
} }
caplen -= n; 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 /* 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 - if ( (0 == fcs_removed) &&
4))) (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); memcpy (buf, tmpbuf + n, caplen);
if (!got_channel)
ri->ri_channel = linux_get_channel (dev);
return caplen; 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. * Open the wireless network interface for reading/writing.
* *
* @param dev pointer to the device struct * @param dev pointer to the device struct
* @return 0 on success * @return 0 on success
*/ */
static int static int
open_device_raw (struct HardwareInfos *dev) open_device_raw (struct HardwareInfos *dev)
{ {
struct ifreq ifr; struct ifreq ifr;
skipping to change at line 1379 skipping to change at line 1692
} }
/* enable promiscuous mode */ /* enable promiscuous mode */
memset (&mr, 0, sizeof (mr)); memset (&mr, 0, sizeof (mr));
mr.mr_ifindex = sll.sll_ifindex; mr.mr_ifindex = sll.sll_ifindex;
mr.mr_type = PACKET_MR_PROMISC; mr.mr_type = PACKET_MR_PROMISC;
if (0 != if (0 !=
setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
sizeof (mr))) sizeof (mr)))
{ {
fprintf (stderr, "Failed to enable promiscuous mode on interface `%.*s' fprintf (stderr,
\n", "Failed to enable promiscuous mode on interface `%.*s'\n",
IFNAMSIZ, dev->iface); IFNAMSIZ,
dev->iface);
return 1; return 1;
} }
return 0; return 0;
} }
/** /**
* Test if the given interface name really corresponds to a wireless * Test if the given interface name really corresponds to a wireless
* device. * device.
* *
* @param iface name of the interface * @param iface name of the interface
* @return 0 on success, 1 on error * @return 0 on success, 1 on error
*/ */
static int static int
test_wlan_interface (const char *iface) test_wlan_interface (const char *iface)
{ {
char strbuf[512]; char strbuf[512];
struct stat sbuf; struct stat sbuf;
int ret; int ret;
/* mac80211 stack detection */ ret = snprintf (strbuf, sizeof (strbuf),
ret = "/sys/class/net/%s/phy80211/subsystem",
snprintf (strbuf, sizeof (strbuf), "/sys/class/net/%s/phy80211/subsys iface);
tem",
iface);
if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf))) if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
{ {
fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", ifac fprintf (stderr,
e); "Did not find 802.11 interface `%s'. Exiting.\n",
return 1; iface);
exit (1);
} }
return 0; 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 * @param dev the Hardware_Infos struct
* @return 0 if mac belongs to us, 1 if mac is for another target * @return 0 if mac belongs to us, 1 if mac is for another target
*/ */
static int static int
mac_test (const struct ieee80211_frame *uint8_taIeeeHeader, mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
const struct HardwareInfos *dev) const struct HardwareInfos *dev)
{ {
if (0 != memcmp (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
_SIZE)) return 1; /* not a GNUnet ad-hoc package */
return 1; if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &dev->pl_mac, MAC_ADDR_SIZE (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
)) return 0; /* for us, or broadcast */
return 0; return 1; /* not for us */
if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &bc_all_mac, MAC_ADDR_SIZE)
)
return 0;
return 1;
} }
/** /**
* function to set the wlan header to make attacks more difficult * Set the wlan header to sane values to make attacks more difficult
* @param uint8_taIeeeHeader pointer to the header of the packet *
* @param taIeeeHeader pointer to the header of the packet
* @param dev pointer to the Hardware_Infos struct * @param dev pointer to the Hardware_Infos struct
*/ */
static void static void
mac_set (struct ieee80211_frame *uint8_taIeeeHeader, mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
const struct HardwareInfos *dev) const struct HardwareInfos *dev)
{ {
uint8_taIeeeHeader->i_fc[0] = 0x08; taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
uint8_taIeeeHeader->i_fc[1] = 0x00; taIeeeHeader->addr2 = dev->pl_mac;
memcpy (uint8_taIeeeHeader->i_addr2, &dev->pl_mac, MAC_ADDR_SIZE); taIeeeHeader->addr3 = mac_bssid_gnunet;
memcpy (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE);
} }
/** /**
* function to process the data from the stdin * Process data from the stdin. Takes the message, prepends the
* @param cls pointer to the device struct * 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 * @param hdr pointer to the start of the packet
*/ */
static void static void
stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
{ {
struct HardwareInfos *dev = cls; struct HardwareInfos *dev = cls;
struct Radiotap_Send *header = (struct Radiotap_Send *) &hdr[1]; const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
struct ieee80211_frame *wlanheader; struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader;
size_t sendsize; size_t sendsize;
struct RadioTapheader rtheader; struct RadiotapTransmissionHeader 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);
sendsize = ntohs (hdr->size); sendsize = ntohs (hdr->size);
if (sendsize < if ( (sendsize <
sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader)) 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); exit (1);
} }
sendsize -= sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) -
sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader); sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
if (MAXLINE < sendsize) 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))
{
fprintf (stderr, "Function stdin_send_hw: wrong packet type\n");
exit (1); exit (1);
} }
header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
rtheader.header.it_version = 0;
rtheader.header.it_pad = 0;
rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader)); rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader));
rtheader.header.it_present = GNUNET_htole16 (IEEE80211_RADIOTAP_OUR_TRANS MISSION_HEADER_MASK);
rtheader.rate = header->rate; rtheader.rate = header->rate;
rtheader.pad1 = 0;
rtheader.txflags = GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80
211_RADIOTAP_F_TX_NOSEQ);
memcpy (write_pout.buf, &rtheader, sizeof (rtheader)); memcpy (write_pout.buf, &rtheader, sizeof (rtheader));
memcpy (write_pout.buf + sizeof (rtheader), &header[1], sendsize); memcpy (&write_pout.buf[sizeof (rtheader)], &header->frame, sendsize);
wlanheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.
buf[sizeof (rtheader)];
/* payload contains MAC address, but we don't trust it, so we'll /* payload contains MAC address, but we don't trust it, so we'll
* overwrite it with OUR MAC address again to prevent mischief */ * overwrite it with OUR MAC address to prevent mischief */
wlanheader = (struct ieee80211_frame *) (write_pout.buf + sizeof (rtheade
r));
mac_set (wlanheader, dev); mac_set (wlanheader, dev);
write_pout.size = sendsize + sizeof (rtheader); write_pout.size = sendsize + sizeof (rtheader);
} }
/** /**
* Main function of the helper. This code accesses a WLAN interface * Main function of the helper. This code accesses a WLAN interface
* in monitoring mode (layer 2) and then forwards traffic in both * in monitoring mode (layer 2) and then forwards traffic in both
* directions between the WLAN interface and stdin/stdout of this * directions between the WLAN interface and stdin/stdout of this
* process. Error messages are written to stdout. * process. Error messages are written to stdout.
* *
skipping to change at line 1695 skipping to change at line 2004
if (0 == ret) if (0 == ret)
{ {
/* stop reading... */ /* stop reading... */
stdin_open = 0; stdin_open = 0;
} }
mst_receive (stdin_mst, readbuf, ret); mst_receive (stdin_mst, readbuf, ret);
} }
if (FD_ISSET (dev.fd_raw, &rfds)) if (FD_ISSET (dev.fd_raw, &rfds))
{ {
struct GNUNET_MessageHeader *header; struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
struct Radiotap_rx *rxinfo;
struct ieee80211_frame *datastart;
ssize_t ret; ssize_t ret;
header = (struct GNUNET_MessageHeader *) write_std.buf; rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_s
rxinfo = (struct Radiotap_rx *) &header[1]; td.buf;
datastart = (struct ieee80211_frame *) &rxinfo[1];
ret = ret =
linux_read (&dev, (unsigned char *) datastart, linux_read (&dev, (unsigned char *) &rrm->frame,
sizeof (write_std.buf) - sizeof (struct Radiotap_rx) sizeof (write_std.buf)
- - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceive
sizeof (struct GNUNET_MessageHeader), rxinfo); Message)
+ sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)
,
rrm);
if (0 > ret) if (0 > ret)
{ {
fprintf (stderr, "Read error from raw socket: %s\n", strerror (errn o)); fprintf (stderr, "Read error from raw socket: %s\n", strerror (errn o));
break; break;
} }
if ((0 < ret) && (0 == mac_test (datastart, &dev))) if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
{ {
write_std.size = write_std.size = ret
ret + sizeof (struct GNUNET_MessageHeader) + + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
sizeof (struct Radiotap_rx); - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
header->size = htons (write_std.size); rrm->header.size = htons (write_std.size);
header->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA); rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER
);
} }
} }
} }
/* Error handling, try to clean up a bit at least */ /* Error handling, try to clean up a bit at least */
mst_destroy (stdin_mst); mst_destroy (stdin_mst);
(void) close (dev.fd_raw); (void) close (dev.fd_raw);
return 1; /* we never exit 'normally' */ return 1; /* we never exit 'normally' */
} }
/* end of gnunet-helper-transport-wlan.c */ /* end of gnunet-helper-transport-wlan.c */
 End of changes. 168 change blocks. 
584 lines changed or deleted 909 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/