2 * WPA Supplicant - Layer2 packet handling with Linux packet sockets
3 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 #include <sys/ioctl.h>
17 #include <netpacket/packet.h>
22 #include "l2_packet.h"
25 struct l2_packet_data
{
26 int fd
; /* packet socket for EAPOL frames */
27 char ifname
[IFNAMSIZ
+ 1];
29 u8 own_addr
[ETH_ALEN
];
30 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
31 const u8
*buf
, size_t len
);
32 void *rx_callback_ctx
;
33 int l2_hdr
; /* whether to include layer 2 (Ethernet) header data
38 int l2_packet_get_own_addr(struct l2_packet_data
*l2
, u8
*addr
)
40 os_memcpy(addr
, l2
->own_addr
, ETH_ALEN
);
45 int l2_packet_send(struct l2_packet_data
*l2
, const u8
*dst_addr
, u16 proto
,
46 const u8
*buf
, size_t len
)
52 ret
= send(l2
->fd
, buf
, len
, 0);
54 perror("l2_packet_send - send");
56 struct sockaddr_ll ll
;
57 os_memset(&ll
, 0, sizeof(ll
));
58 ll
.sll_family
= AF_PACKET
;
59 ll
.sll_ifindex
= l2
->ifindex
;
60 ll
.sll_protocol
= htons(proto
);
61 ll
.sll_halen
= ETH_ALEN
;
62 os_memcpy(ll
.sll_addr
, dst_addr
, ETH_ALEN
);
63 ret
= sendto(l2
->fd
, buf
, len
, 0, (struct sockaddr
*) &ll
,
66 perror("l2_packet_send - sendto");
72 static void l2_packet_receive(int sock
, void *eloop_ctx
, void *sock_ctx
)
74 struct l2_packet_data
*l2
= eloop_ctx
;
77 struct sockaddr_ll ll
;
80 os_memset(&ll
, 0, sizeof(ll
));
82 res
= recvfrom(sock
, buf
, sizeof(buf
), 0, (struct sockaddr
*) &ll
,
85 perror("l2_packet_receive - recvfrom");
89 l2
->rx_callback(l2
->rx_callback_ctx
, ll
.sll_addr
, buf
, res
);
93 struct l2_packet_data
* l2_packet_init(
94 const char *ifname
, const u8
*own_addr
, unsigned short protocol
,
95 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
96 const u8
*buf
, size_t len
),
97 void *rx_callback_ctx
, int l2_hdr
)
99 struct l2_packet_data
*l2
;
101 struct sockaddr_ll ll
;
103 l2
= os_zalloc(sizeof(struct l2_packet_data
));
106 os_strlcpy(l2
->ifname
, ifname
, sizeof(l2
->ifname
));
107 l2
->rx_callback
= rx_callback
;
108 l2
->rx_callback_ctx
= rx_callback_ctx
;
111 l2
->fd
= socket(PF_PACKET
, l2_hdr
? SOCK_RAW
: SOCK_DGRAM
,
114 perror("socket(PF_PACKET)");
118 os_memset(&ifr
, 0, sizeof(ifr
));
119 os_strlcpy(ifr
.ifr_name
, l2
->ifname
, sizeof(ifr
.ifr_name
));
120 if (ioctl(l2
->fd
, SIOCGIFINDEX
, &ifr
) < 0) {
121 perror("ioctl[SIOCGIFINDEX]");
126 l2
->ifindex
= ifr
.ifr_ifindex
;
128 os_memset(&ll
, 0, sizeof(ll
));
129 ll
.sll_family
= PF_PACKET
;
130 ll
.sll_ifindex
= ifr
.ifr_ifindex
;
131 ll
.sll_protocol
= htons(protocol
);
132 if (bind(l2
->fd
, (struct sockaddr
*) &ll
, sizeof(ll
)) < 0) {
133 perror("bind[PF_PACKET]");
139 if (ioctl(l2
->fd
, SIOCGIFHWADDR
, &ifr
) < 0) {
140 perror("ioctl[SIOCGIFHWADDR]");
145 os_memcpy(l2
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
147 eloop_register_read_sock(l2
->fd
, l2_packet_receive
, l2
, NULL
);
153 void l2_packet_deinit(struct l2_packet_data
*l2
)
159 eloop_unregister_read_sock(l2
->fd
);
167 int l2_packet_get_ip_addr(struct l2_packet_data
*l2
, char *buf
, size_t len
)
171 struct sockaddr_in
*saddr
;
174 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
179 os_memset(&ifr
, 0, sizeof(ifr
));
180 os_strlcpy(ifr
.ifr_name
, l2
->ifname
, sizeof(ifr
.ifr_name
));
181 if (ioctl(s
, SIOCGIFADDR
, &ifr
) < 0) {
182 if (errno
!= EADDRNOTAVAIL
)
183 perror("ioctl[SIOCGIFADDR]");
188 saddr
= aliasing_hide_typecast(&ifr
.ifr_addr
, struct sockaddr_in
);
189 if (saddr
->sin_family
!= AF_INET
)
191 res
= os_strlcpy(buf
, inet_ntoa(saddr
->sin_addr
), len
);
198 void l2_packet_notify_auth_start(struct l2_packet_data
*l2
)