iPXE
eapol.c File Reference

Extensible Authentication Protocol over LAN (EAPoL) More...

#include <string.h>
#include <assert.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/if_ether.h>
#include <ipxe/if_arp.h>
#include <ipxe/netdevice.h>
#include <ipxe/vlan.h>
#include <ipxe/retry.h>
#include <ipxe/eap.h>
#include <ipxe/eapol.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int eapol_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source, unsigned int flags __unused)
 Process EAPoL packet.
static int eapol_eap_rx (struct eapol_supplicant *supplicant, struct io_buffer *iobuf, const void *ll_source __unused)
 Process EAPoL-encapsulated EAP packet.
static int eapol_tx (struct eapol_supplicant *supplicant, unsigned int type, const void *data, size_t len)
 Transmit EAPoL packet.
static int eapol_eap_tx (struct eap_supplicant *eap, const void *data, size_t len)
 Transmit EAPoL-encapsulated EAP packet.
static void eapol_expired (struct retry_timer *timer, int fail __unused)
 (Re)transmit EAPoL-Start packet
static int eapol_probe (struct net_device *netdev, void *priv)
 Create EAPoL supplicant.
static void eapol_notify (struct net_device *netdev, void *priv)
 Handle EAPoL supplicant state change.

Variables

struct net_driver eapol_driver __net_driver
 EAPoL driver.
static const uint8_t eapol_mac [ETH_ALEN]
 EAPoL destination MAC address.
struct net_protocol eapol_protocol __net_protocol
 EAPoL protocol.
struct eapol_handler eapol_eap __eapol_handler
 EAPoL handler for EAP packets.

Detailed Description

Extensible Authentication Protocol over LAN (EAPoL)

Definition in file eapol.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ eapol_rx()

int eapol_rx ( struct io_buffer * iobuf,
struct net_device * netdev,
const void *ll_dest __unused,
const void * ll_source,
unsigned int flags __unused )
static

Process EAPoL packet.

Parameters
iobufI/O buffer
netdevNetwork device
ll_destLink-layer destination address
ll_sourceLink-layer source address
flagsPacket flags
Return values
rcReturn status code

Definition at line 63 of file eapol.c.

65 {
66 struct eapol_supplicant *supplicant;
67 struct eapol_header *eapol;
68 struct eapol_handler *handler;
69 size_t remaining;
70 size_t len;
71 int rc;
72
73 /* Find matching supplicant */
74 supplicant = netdev_priv ( netdev, &eapol_driver );
75
76 /* Ignore non-EAPoL devices */
77 if ( ! supplicant->eap.netdev ) {
78 DBGC ( netdev, "EAPOL %s is not an EAPoL device\n",
79 netdev->name );
80 DBGC_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
81 rc = -ENOTTY;
82 goto drop;
83 }
84
85 /* Sanity checks */
86 if ( iob_len ( iobuf ) < sizeof ( *eapol ) ) {
87 DBGC ( netdev, "EAPOL %s underlength header:\n",
88 netdev->name );
89 DBGC_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
90 rc = -EINVAL;
91 goto drop;
92 }
93 eapol = iobuf->data;
94 remaining = ( iob_len ( iobuf ) - sizeof ( *eapol ) );
95 len = ntohs ( eapol->len );
96 if ( len > remaining ) {
97 DBGC ( netdev, "EAPOL %s v%d type %d len %zd underlength "
98 "payload:\n", netdev->name, eapol->version,
99 eapol->type, len );
100 DBGC_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
101 rc = -EINVAL;
102 goto drop;
103 }
104
105 /* Strip any trailing padding */
106 iob_unput ( iobuf, ( len - remaining ) );
107
108 /* Handle according to type */
110 if ( handler->type == eapol->type ) {
111 return handler->rx ( supplicant, iob_disown ( iobuf ),
112 ll_source );
113 }
114 }
115 rc = -ENOTSUP;
116 DBGC ( netdev, "EAPOL %s v%d type %d unsupported\n",
117 netdev->name, eapol->version, eapol->type );
118 DBGC_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
119
120 drop:
121 free_iob ( iobuf );
122 return rc;
123}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ring len
Length.
Definition dwmac.h:226
#define EAPOL_HANDLERS
EAPoL handler table.
Definition eapol.h:75
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define ntohs(value)
Definition byteswap.h:137
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_unput(iobuf, len)
Definition iobuf.h:140
void * netdev_priv(struct net_device *netdev, struct net_driver *driver)
Get network device driver private data.
Definition netdevice.c:153
struct net_device * netdev
Network device.
Definition eap.h:141
An EAPoL handler.
Definition eapol.h:57
int(* rx)(struct eapol_supplicant *supplicant, struct io_buffer *iobuf, const void *ll_source)
Process received packet.
Definition eapol.h:70
uint8_t type
Type.
Definition eapol.h:59
EAPoL header.
Definition eapol.h:19
uint8_t version
Version.
Definition eapol.h:21
uint8_t type
Type.
Definition eapol.h:23
uint16_t len
Payload length.
Definition eapol.h:25
An EAPoL supplicant.
Definition eapol.h:41
struct eap_supplicant eap
EAP supplicant.
Definition eapol.h:43
void * data
Start of data.
Definition iobuf.h:53
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References __unused, io_buffer::data, DBGC, DBGC_HDA, eapol_supplicant::eap, EAPOL_HANDLERS, EINVAL, ENOTSUP, ENOTTY, flags, for_each_table_entry, free_iob(), iob_disown, iob_len(), iob_unput, eapol_header::len, len, eap_supplicant::netdev, netdev, netdev_priv(), ntohs, rc, eapol_handler::rx, eapol_handler::type, eapol_header::type, and eapol_header::version.

◆ eapol_eap_rx()

int eapol_eap_rx ( struct eapol_supplicant * supplicant,
struct io_buffer * iobuf,
const void *ll_source __unused )
static

Process EAPoL-encapsulated EAP packet.

Parameters
supplicantEAPoL supplicant
ll_sourceLink-layer source address
Return values
rcReturn status code

Definition at line 139 of file eapol.c.

141 {
142 struct net_device *netdev = supplicant->eap.netdev;
143 struct eapol_header *eapol;
144 int rc;
145
146 /* Sanity check */
147 assert ( iob_len ( iobuf ) >= sizeof ( *eapol ) );
148
149 /* Strip EAPoL header */
150 eapol = iob_pull ( iobuf, sizeof ( *eapol ) );
151
152 /* Process EAP packet */
153 if ( ( rc = eap_rx ( &supplicant->eap, iobuf->data,
154 iob_len ( iobuf ) ) ) != 0 ) {
155 DBGC ( netdev, "EAPOL %s v%d EAP failed: %s\n",
156 netdev->name, eapol->version, strerror ( rc ) );
157 goto drop;
158 }
159
160 /* Update EAPoL-Start transmission timer */
161 if ( supplicant->eap.flags & EAP_FL_PASSIVE ) {
162 /* Stop sending EAPoL-Start */
163 if ( timer_running ( &supplicant->timer ) ) {
164 DBGC ( netdev, "EAPOL %s becoming passive\n",
165 netdev->name );
166 }
167 stop_timer ( &supplicant->timer );
168 } else if ( supplicant->eap.flags & EAP_FL_ONGOING ) {
169 /* Delay EAPoL-Start until after next expected packet */
170 DBGC ( netdev, "EAPOL %s deferring Start\n", netdev->name );
171 start_timer_fixed ( &supplicant->timer, EAP_WAIT_TIMEOUT );
172 supplicant->count = 0;
173 }
174
175 drop:
176 free_iob ( iobuf );
177 return rc;
178}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
int eap_rx(struct eap_supplicant *supplicant, const void *data, size_t len)
Handle EAP packet.
Definition eap.c:264
#define EAP_WAIT_TIMEOUT
EAP protocol wait timeout.
Definition eap.h:136
#define EAP_FL_ONGOING
EAP authentication is in progress.
Definition eap.h:165
#define EAP_FL_PASSIVE
EAP supplicant is passive.
Definition eap.h:175
#define iob_pull(iobuf, len)
Definition iobuf.h:107
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
uint16_t flags
Flags.
Definition eap.h:143
unsigned int count
EAPoL-Start transmission count.
Definition eapol.h:47
struct retry_timer timer
EAPoL-Start retransmission timer.
Definition eapol.h:45
A network device.
Definition netdevice.h:353

References __unused, assert, eapol_supplicant::count, io_buffer::data, DBGC, eapol_supplicant::eap, EAP_FL_ONGOING, EAP_FL_PASSIVE, eap_rx(), EAP_WAIT_TIMEOUT, eap_supplicant::flags, free_iob(), iob_len(), iob_pull, eap_supplicant::netdev, netdev, rc, start_timer_fixed(), stop_timer(), strerror(), eapol_supplicant::timer, and eapol_header::version.

◆ eapol_tx()

int eapol_tx ( struct eapol_supplicant * supplicant,
unsigned int type,
const void * data,
size_t len )
static

Transmit EAPoL packet.

Parameters
supplicantEAPoL supplicant
typePacket type
dataPacket body
lenLength of packet body
Return values
rcReturn status code

Definition at line 195 of file eapol.c.

196 {
197 struct net_device *netdev = supplicant->eap.netdev;
198 struct io_buffer *iobuf;
199 struct eapol_header *eapol;
200 int rc;
201
202 /* Allocate I/O buffer */
203 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *eapol ) + len );
204 if ( ! iobuf )
205 return -ENOMEM;
207
208 /* Construct EAPoL header */
209 eapol = iob_put ( iobuf, sizeof ( *eapol ) );
211 eapol->type = type;
212 eapol->len = htons ( len );
213
214 /* Append packet body */
215 memcpy ( iob_put ( iobuf, len ), data, len );
216
217 /* Transmit packet */
218 if ( ( rc = net_tx ( iob_disown ( iobuf ), netdev, &eapol_protocol,
219 &eapol_mac, netdev->ll_addr ) ) != 0 ) {
220 DBGC ( netdev, "EAPOL %s could not transmit type %d: %s\n",
221 netdev->name, type, strerror ( rc ) );
222 DBGC_HDA ( netdev, 0, data, len );
223 return rc;
224 }
225
226 return 0;
227}
static const uint8_t eapol_mac[ETH_ALEN]
EAPoL destination MAC address.
Definition eapol.c:49
#define EAPOL_VERSION_2001
802.1X-2001
Definition eapol.h:29
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define ENOMEM
Not enough space.
Definition errno.h:535
#define htons(value)
Definition byteswap.h:136
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition netdevice.c:1074
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition netdevice.h:46
A persistent I/O buffer.
Definition iobuf.h:38

References alloc_iob(), data, DBGC, DBGC_HDA, eapol_supplicant::eap, eapol_mac, EAPOL_VERSION_2001, ENOMEM, htons, iob_disown, iob_put, iob_reserve, eapol_header::len, len, MAX_LL_HEADER_LEN, memcpy(), net_tx(), eap_supplicant::netdev, netdev, rc, strerror(), eapol_header::type, type, and eapol_header::version.

Referenced by eapol_eap_tx(), and eapol_expired().

◆ eapol_eap_tx()

int eapol_eap_tx ( struct eap_supplicant * eap,
const void * data,
size_t len )
static

Transmit EAPoL-encapsulated EAP packet.

Parameters
supplicantEAPoL supplicant
ll_sourceLink-layer source address
Return values
rcReturn status code

Definition at line 236 of file eapol.c.

237 {
238 struct eapol_supplicant *supplicant =
240
241 /* Transmit encapsulated packet */
242 return eapol_tx ( supplicant, EAPOL_TYPE_EAP, data, len );
243}
static int eapol_tx(struct eapol_supplicant *supplicant, unsigned int type, const void *data, size_t len)
Transmit EAPoL packet.
Definition eapol.c:195
#define EAPOL_TYPE_EAP
EAPoL-encapsulated EAP packets.
Definition eapol.h:32
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36

References container_of, data, eapol_supplicant::eap, eapol_tx(), EAPOL_TYPE_EAP, and len.

Referenced by eapol_probe().

◆ eapol_expired()

void eapol_expired ( struct retry_timer * timer,
int fail __unused )
static

(Re)transmit EAPoL-Start packet

Parameters
timerEAPoL-Start timer
expiredFailure indicator

Definition at line 251 of file eapol.c.

251 {
252 struct eapol_supplicant *supplicant =
254 struct net_device *netdev = supplicant->eap.netdev;
255
256 /* Stop transmitting after maximum number of attempts */
257 if ( supplicant->count++ >= EAPOL_START_COUNT ) {
258 DBGC ( netdev, "EAPOL %s giving up\n", netdev->name );
259 return;
260 }
261
262 /* Schedule next transmission */
264
265 /* Transmit EAPoL-Start, ignoring errors */
266 DBGC2 ( netdev, "EAPOL %s transmitting Start\n", netdev->name );
267 eapol_tx ( supplicant, EAPOL_TYPE_START, NULL, 0 );
268}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define EAPOL_START_INTERVAL
Delay between EAPoL-Start packets.
Definition eapol.h:51
#define EAPOL_TYPE_START
EAPoL start.
Definition eapol.h:35
#define EAPOL_START_COUNT
Maximum number of EAPoL-Start packets to transmit.
Definition eapol.h:54
#define DBGC2(...)
Definition compiler.h:522
A timer.
Definition timer.h:29

References __unused, container_of, eapol_supplicant::count, DBGC, DBGC2, eapol_supplicant::eap, EAPOL_START_COUNT, EAPOL_START_INTERVAL, eapol_tx(), EAPOL_TYPE_START, eap_supplicant::netdev, netdev, NULL, and start_timer_fixed().

Referenced by eapol_probe().

◆ eapol_probe()

int eapol_probe ( struct net_device * netdev,
void * priv )
static

Create EAPoL supplicant.

Parameters
netdevNetwork device
privPrivate data
Return values
rcReturn status code

Definition at line 277 of file eapol.c.

277 {
278 struct eapol_supplicant *supplicant = priv;
279 struct ll_protocol *ll_protocol = netdev->ll_protocol;
280
281 /* Ignore non-EAPoL devices */
283 return 0;
284 if ( vlan_tag ( netdev ) )
285 return 0;
286
287 /* Initialise structure */
288 supplicant->eap.netdev = netdev;
289 supplicant->eap.tx = eapol_eap_tx;
290 timer_init ( &supplicant->timer, eapol_expired, &netdev->refcnt );
291
292 return 0;
293}
static void eapol_expired(struct retry_timer *timer, int fail __unused)
(Re)transmit EAPoL-Start packet
Definition eapol.c:251
static int eapol_eap_tx(struct eap_supplicant *eap, const void *data, size_t len)
Transmit EAPoL-encapsulated EAP packet.
Definition eapol.c:236
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition if_arp.h:17
int(* tx)(struct eap_supplicant *supplicant, const void *data, size_t len)
Transmit EAP response.
Definition eap.h:156
A link-layer protocol.
Definition netdevice.h:115
uint16_t ll_proto
Link-layer protocol.
Definition netdevice.h:195
static struct tlan_private * priv
Definition tlan.c:225
static unsigned int vlan_tag(struct net_device *netdev)
Get the VLAN tag.
Definition vlan.h:74

References ARPHRD_ETHER, eapol_supplicant::eap, eapol_eap_tx(), eapol_expired(), htons, ll_protocol::ll_proto, eap_supplicant::netdev, netdev, priv, eapol_supplicant::timer, eap_supplicant::tx, and vlan_tag().

◆ eapol_notify()

void eapol_notify ( struct net_device * netdev,
void * priv )
static

Handle EAPoL supplicant state change.

Parameters
netdevNetwork device
privPrivate data

Definition at line 301 of file eapol.c.

301 {
302 struct eapol_supplicant *supplicant = priv;
303
304 /* Ignore non-EAPoL devices */
305 if ( ! supplicant->eap.netdev )
306 return;
307
308 /* Terminate and reset EAP when link goes down */
309 if ( ! ( netdev_is_open ( netdev ) && netdev_link_ok ( netdev ) ) ) {
310 if ( timer_running ( &supplicant->timer ) ) {
311 DBGC ( netdev, "EAPOL %s shutting down\n",
312 netdev->name );
313 }
314 supplicant->eap.flags = 0;
315 stop_timer ( &supplicant->timer );
316 return;
317 }
318
319 /* Do nothing if EAP is already in progress */
320 if ( timer_running ( &supplicant->timer ) )
321 return;
322
323 /* Do nothing if EAP has already finished transmitting */
324 if ( supplicant->eap.flags & EAP_FL_PASSIVE )
325 return;
326
327 /* Otherwise, start sending EAPoL-Start */
328 start_timer_nodelay ( &supplicant->timer );
329 supplicant->count = 0;
330 DBGC ( netdev, "EAPOL %s starting up\n", netdev->name );
331}
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition netdevice.h:640
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100

References eapol_supplicant::count, DBGC, eapol_supplicant::eap, EAP_FL_PASSIVE, eap_supplicant::flags, eap_supplicant::netdev, netdev, netdev_is_open(), netdev_link_ok(), priv, start_timer_nodelay(), stop_timer(), and eapol_supplicant::timer.

Variable Documentation

◆ __net_driver

struct net_driver eapol_driver __net_driver
Initial value:
= {
.name = "EAPoL",
.priv_len = sizeof ( struct eapol_supplicant ),
.probe = eapol_probe,
.notify = eapol_notify,
}
static int eapol_probe(struct net_device *netdev, void *priv)
Create EAPoL supplicant.
Definition eapol.c:277
static void eapol_notify(struct net_device *netdev, void *priv)
Handle EAPoL supplicant state change.
Definition eapol.c:301

EAPoL driver.

Definition at line 46 of file eapol.c.

◆ eapol_mac

const uint8_t eapol_mac[ETH_ALEN]
static
Initial value:
= {
0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
}

EAPoL destination MAC address.

Definition at line 49 of file eapol.c.

49 {
50 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
51};

Referenced by eapol_tx().

◆ __net_protocol

struct net_protocol eapol_protocol __net_protocol
Initial value:
= {
.name = "EAPOL",
.net_proto = htons ( ETH_P_EAPOL ),
.rx = eapol_rx,
}
static int eapol_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source, unsigned int flags __unused)
Process EAPoL packet.
Definition eapol.c:63
#define ETH_P_EAPOL
Definition if_ether.h:25

EAPoL protocol.

AoE protocol.

Definition at line 126 of file eapol.c.

126 {
127 .name = "EAPOL",
128 .net_proto = htons ( ETH_P_EAPOL ),
129 .rx = eapol_rx,
130};

◆ __eapol_handler

struct eapol_handler eapol_eap __eapol_handler
Initial value:
= {
.type = EAPOL_TYPE_EAP,
.rx = eapol_eap_rx,
}
static int eapol_eap_rx(struct eapol_supplicant *supplicant, struct io_buffer *iobuf, const void *ll_source __unused)
Process EAPoL-encapsulated EAP packet.
Definition eapol.c:139

EAPoL handler for EAP packets.

Definition at line 181 of file eapol.c.

181 {
182 .type = EAPOL_TYPE_EAP,
183 .rx = eapol_eap_rx,
184};