peapod  0.1.0
EAPOL Proxy Daemon
Functions | Variables
packet.c File Reference

EAPOL packet operations. More...

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include "args.h"
#include "log.h"
#include "packet.h"
#include "process.h"
Include dependency graph for packet.c:

Functions

static void dump (struct peapod_packet packet)
 Log a hexadecimal dump of a struct peapod_packet More...
 
static void decode (struct peapod_packet packet)
 Log metadata for a struct peapod_packet in a tcpdump-like format. More...
 
void packet_init (struct iface_t *ifaces)
 Allocate the main buffer for the EAPOL packet. More...
 
uint8_t * packet_buf (struct peapod_packet packet, uint8_t orig)
 Return a pointer to a raw EAPOL packet. More...
 
uint32_t packet_tcitonl (struct tci_t tci)
 Convert a struct tci_t to a 4-byte 802.1Q tag. More...
 
char * packet_decode (uint8_t val, const struct decode_t *decode)
 Decode a byte in an EAPOL packet to a C string. More...
 
int packet_send (struct peapod_packet packet, struct iface_t *iface)
 Send an EAPOL packet on a network interface. More...
 
struct peapod_packet packet_recvmsg (struct iface_t *iface)
 Receive an EAPOL packet on a network interface. More...
 

Variables

union {
   struct cmsghdr   cmsg
 
   uint8_t   buf [CMSG_SPACE(sizeof(struct
      packet_auxdata_t))]
 
cmsg_buf
 Buffer for receiving a struct packet_auxdata_t from the kernel via recvmsg(2) More...
 
static struct msghdr msg
 A struct msghdr for recvmsg(2) More...
 
struct args_t args
 Program arguments data structure. More...
 
EAPOL packet buffer

The size of this buffer is normally 1518 bytes given a 1500-byte MTU, to accommodate the standard 1514-byte Ethernet frame size plus a 4-byte 802.1Q tag. We use an iovec with recvmsg(2) to split off the destination and source MAC addresses into their own fields of a struct peapod_packet structure at the point of capture, reading only the EAPOL MPDU (EtherType and MTU, normally 1502 bytes) into bytes 16:. Any 802.1Q tag is obtained separately via a PACKET_AUXDATA cmsg from the kernel. Bytes 0:15 may then serve as scratch space for us to reconstruct the complete EAPOL packet.

This allows us to do things like adding, modifying, or removing an 802.1Q tag for a proxied packet on a per-egress-interface basis. We simply reconstruct/modify the first 16 bytes of this buffer as needed, then call write(2) on the socket file descriptor with the proper memory offset.

static uint8_t * pkt_buf = NULL
 Main EAPOL packet buffer. More...
 
static int pkt_buf_size = 0
 Normally 1518 bytes. More...
 
uint8_t * mpdu_buf = NULL
 The EAPOL MPDU. More...
 
int mpdu_buf_size = 0
 Normally 1502 bytes. More...
 

Detailed Description

EAPOL packet operations.

Function Documentation

static void dump ( struct peapod_packet  packet)
static

Log a hexadecimal dump of a struct peapod_packet

Parameters
packetA struct peapod_packet representing an EAPOL packet
static void decode ( struct peapod_packet  packet)
static

Log metadata for a struct peapod_packet in a tcpdump-like format.

Parameters
packetA struct peapod_packet representing an EAPOL packet
void packet_init ( struct iface_t ifaces)

Allocate the main buffer for the EAPOL packet.

The size of the buffer is determined according to the highest MTU of the network interfaces used by the program.

Parameters
ifacesPointer to a list of struct iface_t structures representing network interfaces
Note
valgrind claims the memory allocated here is "possibly lost". Ignore it; we're "doing unusual things with pointers that could cause them to point into the middle of an allocated block". Quite deliberately so.
See also
http://valgrind.org/docs/manual/faq.html#faq.deflost
uint8_t* packet_buf ( struct peapod_packet  packet,
uint8_t  orig 
)

Return a pointer to a raw EAPOL packet.

Rewrites the first 16 bytes of the main packet buffer. The result shall point to the beginning of a raw EAPOL packet that is either:

  1. the original packet, including the VLAN tag, as it appeared when it was captured on the ingress interface, or
  2. the processed packet, possibly with original VLAN tag removed or tag fields changed according to interface egress options, that should be sent out on a given egress interface.

The result may then be used by the caller to (hex)dump, Base64-encode, and/or send the packet.

Parameters
packetA struct peapod_packet representing an EAPOL packet
origFlag: Reconstruct original packet as seen on ingress interface?
Returns
Pointer to the beginning of a complete EAPOL packet
uint32_t packet_tcitonl ( struct tci_t  tci)

Convert a struct tci_t to a 4-byte 802.1Q tag.

Parameters
tciA struct tci_t representing an 802.1Q TCI
Returns
An unsigned 32-bit integer in network order
char* packet_decode ( uint8_t  val,
const struct decode_t decode 
)

Decode a byte in an EAPOL packet to a C string.

The byte may be one of the following:

  1. the Type field of an EAPOL packet,
  2. the Code field of an EAP packet encapsulated in an EAPOL-EAP packet, or
  3. the Type field of an EAP-Request or EAP-Response encapsulated in an EAP packet.
Parameters
valValue of the relevant byte to decode
decodePointer to a struct decode_t matching field values with descriptions
Returns
A description, or "Unknown" if the value does not have a corresponding description in decode.
int packet_send ( struct peapod_packet  packet,
struct iface_t iface 
)

Send an EAPOL packet on a network interface.

May execute an egress script.

Parameters
packetA struct peapod_packet representing an EAPOL packet
ifacePointer to a struct iface_t representing an interface
Returns
The number of bytes successfully sent
struct peapod_packet packet_recvmsg ( struct iface_t iface)

Receive an EAPOL packet on a network interface.

Returns
A struct peapod_packet representing an EAPOL packet with its len field set to one of the following:
  1. the number of bytes successfully received (if at least 60),
  2. -1 if an error occurred while receiving,
  3. -2 if fewer than 60 bytes were received (i.e. the EAPOL packet was smaller than the minimum Ethernet frame size of 64 bytes, as the 4-byte FCS is not included), or
  4. -3 if the packet was too big to fit in the main EAPOL packet buffer (i.e. the MTU was ignored).
Note
If at least 60 bytes were successfully received, the result will have Ethernet, EAPOL, and EAP metadata in its other fields.

Variable Documentation

uint8_t* pkt_buf = NULL
static

Main EAPOL packet buffer.

int pkt_buf_size = 0
static

Normally 1518 bytes.

uint8_t* mpdu_buf = NULL

The EAPOL MPDU.

Points to byte 16 of the main EAPOL packet buffer, and thereby to the EAPOL EtherType (0x888e) followed by the MTU (normally up to 1500 bytes).

Note
Global
int mpdu_buf_size = 0

Normally 1502 bytes.

Note
Global
struct cmsghdr cmsg
uint8_t buf[CMSG_SPACE(sizeof(struct packet_auxdata_t))]
union { ... } cmsg_buf

Buffer for receiving a struct packet_auxdata_t from the kernel via recvmsg(2)

Note
Actually a struct tpacket_auxdata
See also
socket(7), "Socket options"
struct msghdr msg
static
Initial value:
= {
.msg_name = NULL,
.msg_namelen = 0,
.msg_control = &cmsg_buf,
.msg_controllen = sizeof(cmsg_buf),
.msg_flags = 0
}
static union @0 cmsg_buf
Buffer for receiving a struct packet_auxdata_t from the kernel via recvmsg(2)

A struct msghdr for recvmsg(2)

See also
recvmsg(2)
struct args_t args

Program arguments data structure.

Note
Global