2 * Linux-specific portion of EAPD
5 * Copyright (C) 2010, Broadcom Corporation
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: eapd_linux.c 241391 2011-02-18 03:35:48Z stakita $
23 #include <arpa/inet.h>
24 #include <sys/ioctl.h>
25 #include <linux/if_packet.h>
28 #include <proto/ethernet.h>
29 #include <proto/eapol.h>
30 #include <proto/eap.h>
34 #include <wlif_utils.h>
37 static eapd_wksp_t
*eapd_nwksp
= NULL
;
40 eapd_hup_hdlr(int sig
)
43 eapd_nwksp
->flags
|= EAPD_WKSP_FLAG_SHUTDOWN
;
50 eapd_dump_hdlr(int sig
)
53 eapd_nwksp
->flags
|= EAPD_WKSP_FLAG_DUMP
;
60 eapd_send(eapd_wksp_t
*nwksp
, int drvSocket
, struct iovec
*frags
, int nfrags
)
64 memset(&mh
, 0, sizeof(mh
));
65 mh
.msg_name
= (caddr_t
) NULL
;
68 mh
.msg_iovlen
= nfrags
;
70 if (sendmsg(drvSocket
, &mh
, 0) < 0) {
71 EAPD_ERROR("send error %d to drvSocket %d\n", errno
, drvSocket
);
75 EAPD_INFO("send successful on drvSocket %d\n", drvSocket
);
81 /* Send a canned EAPOL packet */
83 eapd_eapol_canned_send(eapd_wksp_t
*nwksp
, struct eapd_socket
*Socket
, eapd_sta_t
*sta
,
84 unsigned char code
, unsigned char type
)
88 struct iovec frags
[2];
90 memcpy(&eapol
.eth
.ether_dhost
, &sta
->ea
, ETHER_ADDR_LEN
);
91 memcpy(&eapol
.eth
.ether_shost
, &sta
->bssid
, ETHER_ADDR_LEN
);
93 eapol
.eth
.ether_type
= htons(ETHER_TYPE_802_1X
);
94 eapol
.version
= sta
->eapol_version
;
95 eapol
.type
= EAP_PACKET
;
96 eapol
.length
= htons(type
? (EAP_HEADER_LEN
+ 1) : EAP_HEADER_LEN
);
100 eap
.length
= eapol
.length
;
103 frags
[0].iov_base
= (caddr_t
) &eapol
;
104 frags
[0].iov_len
= EAPOL_HEADER_LEN
;
105 frags
[1].iov_base
= (caddr_t
) &eap
;
106 frags
[1].iov_len
= ntohs(eapol
.length
);
108 eapd_send(nwksp
, Socket
->drvSocket
, frags
, 2);
112 eapd_message_send(eapd_wksp_t
*nwksp
, struct eapd_socket
*Socket
, uint8
*pData
, int pLen
)
114 struct iovec frags
[1];
116 frags
[0].iov_base
= (caddr_t
) pData
;
117 frags
[0].iov_len
= pLen
;
119 eapd_send(nwksp
, Socket
->drvSocket
, frags
, 1);
123 eapd_brcm_open(eapd_wksp_t
*nwksp
, eapd_brcm_socket_t
*sock
)
126 struct sockaddr_ll ll
;
128 if (nwksp
== NULL
|| sock
== NULL
) {
129 EAPD_ERROR("Wrong arguments...\n");
133 sock
->drvSocket
= socket(PF_PACKET
, SOCK_RAW
, htons(ETHER_TYPE_BRCM
));
134 if (sock
->drvSocket
< 0) {
135 EAPD_ERROR("open socket error!!\n");
139 memset(&ifr
, 0, sizeof(ifr
));
141 strcpy(ifr
.ifr_name
, sock
->ifname
);
142 if (ioctl(sock
->drvSocket
, SIOCGIFINDEX
, &ifr
) != 0) {
143 EAPD_ERROR("%s, ioctl(SIOCGIFINDEX), close drvSocket %d\n",
144 sock
->ifname
, sock
->drvSocket
);
145 close(sock
->drvSocket
);
146 sock
->drvSocket
= -1;
150 sock
->ifindex
= ifr
.ifr_ifindex
;
151 memset(&ll
, 0, sizeof(ll
));
152 ll
.sll_family
= AF_PACKET
;
153 ll
.sll_protocol
= htons(ETHER_TYPE_BRCM
);
154 ll
.sll_ifindex
= sock
->ifindex
;
156 if (bind(sock
->drvSocket
, (struct sockaddr
*) &ll
, sizeof(ll
)) < 0) {
157 EAPD_ERROR("%s, bind fail, close drvSocket %d!!\n",
158 sock
->ifname
, sock
->drvSocket
);
159 close(sock
->drvSocket
);
160 sock
->drvSocket
= -1;
163 /* at least one use it */
164 sock
->inuseCount
= 1;
166 EAPD_INFO("%s: BRCM socket %d opened\n", ifr
.ifr_name
, sock
->drvSocket
);
172 eapd_brcm_close(int drvSocket
)
180 eapd_preauth_open(eapd_wksp_t
*nwksp
, eapd_preauth_socket_t
*sock
)
183 struct sockaddr_ll ll
;
185 if (nwksp
== NULL
|| sock
== NULL
) {
186 EAPD_ERROR("Wrong arguments...\n");
190 sock
->drvSocket
= socket(PF_PACKET
, SOCK_RAW
, htons(ETHER_TYPE_802_1X_PREAUTH
));
191 if (sock
->drvSocket
< 0) {
192 EAPD_ERROR("open socket error!!\n");
196 memset(&ifr
, 0, sizeof(ifr
));
198 strcpy(ifr
.ifr_name
, sock
->ifname
);
199 if (ioctl(sock
->drvSocket
, SIOCGIFINDEX
, &ifr
) != 0) {
200 EAPD_ERROR("%s, ioctl(SIOCGIFINDEX), close drvSocket %d\n",
201 sock
->ifname
, sock
->drvSocket
);
202 close(sock
->drvSocket
);
203 sock
->drvSocket
= -1;
207 sock
->ifindex
= ifr
.ifr_ifindex
;
208 memset(&ll
, 0, sizeof(ll
));
209 ll
.sll_family
= AF_PACKET
;
210 ll
.sll_protocol
= htons(ETHER_TYPE_802_1X_PREAUTH
);
211 ll
.sll_ifindex
= sock
->ifindex
;
213 if (bind(sock
->drvSocket
, (struct sockaddr
*) &ll
, sizeof(ll
)) < 0) {
214 EAPD_ERROR("%s, bind fail, close drvSocket %d!!\n", sock
->ifname
, sock
->drvSocket
);
215 close(sock
->drvSocket
);
216 sock
->drvSocket
= -1;
219 /* at least one use it */
220 sock
->inuseCount
= 1;
222 EAPD_INFO("%s: preauth socket %d opened\n", ifr
.ifr_name
, sock
->drvSocket
);
228 eapd_preauth_close(int drvSocket
)
239 eapd_safe_get_conf(char *outval
, int outval_size
, char *name
)
243 if (name
== NULL
|| outval
== NULL
) {
245 memset(outval
, 0, outval_size
);
249 val
= nvram_safe_get(name
);
250 if (!strcmp(val
, ""))
251 memset(outval
, 0, outval_size
);
253 snprintf(outval
, outval_size
, "%s", val
);
257 int main(int argc
, char* argv
[])
264 /* display usage if nothing is specified */
266 (!strncmp(argv
[1], "-h", 2) ||
267 !strncmp(argv
[1], "-H", 2))) {
268 eapd_wksp_display_usage();
272 /* get eapd_msg_level from nvram */
273 if ((dbg
= nvram_get("eapd_dbg"))) {
274 eapd_msg_level
= (uint
)strtoul(dbg
, NULL
, 0);
278 EAPD_INFO("EAP Dispatch Start...\n");
279 /* alloc eapd work space */
280 if (!(eapd_nwksp
= eapd_wksp_alloc_workspace())) {
281 EAPD_ERROR("Unable to allocate wksp memory. Quitting...\n");
285 #if EAPD_WKSP_AUTO_CONFIG
288 if (eapd_wksp_auto_config(eapd_nwksp
)) {
289 EAPD_ERROR("Unable to auto config. Quitting...\n");
290 eapd_wksp_cleanup(eapd_nwksp
);
294 else if (eapd_wksp_parse_cmd(argc
, argv
, eapd_nwksp
)) {
295 EAPD_ERROR("Command line parsing error. Quitting...\n");
296 eapd_wksp_cleanup(eapd_nwksp
);
299 #else /* EAPD_WKSP_AUTO_CONFIG */
300 /* parse arguments in parse mode */
301 if (eapd_wksp_parse_cmd(argc
, argv
, eapd_nwksp
)) {
302 EAPD_ERROR("Command line parsing error. Quitting...\n");
303 eapd_wksp_cleanup(eapd_nwksp
);
306 #endif /* EAPD_WKSP_AUTO_CONFIG */
308 /* establish a handler to handle SIGTERM. */
309 signal(SIGTERM
, eapd_hup_hdlr
);
312 signal(SIGUSR1
, eapd_dump_hdlr
);
315 /* run main loop to dispatch messages */
316 eapd_wksp_main_loop(eapd_nwksp
);
318 EAPD_INFO("EAP Dispatcher Stopped...\n");