K2.6 patches and update.
[tomato.git] / release / src-rt / wl / eapd / eapd_linux.c
blobee99acbb4d35959d72d3ce898b732776f7a7b9cc
1 /*
2 * Linux-specific portion of EAPD
3 * (OS dependent file)
5 * Copyright (C) 2010, Broadcom Corporation
6 * All Rights Reserved.
7 *
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 $
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <signal.h>
22 #include <net/if.h>
23 #include <arpa/inet.h>
24 #include <sys/ioctl.h>
25 #include <linux/if_packet.h>
26 #include <typedefs.h>
27 #include <bcmutils.h>
28 #include <proto/ethernet.h>
29 #include <proto/eapol.h>
30 #include <proto/eap.h>
31 #include <wlutils.h>
32 #include <bcmnvram.h>
33 #include <eapd.h>
34 #include <wlif_utils.h>
35 #include <UdpLib.h>
37 static eapd_wksp_t *eapd_nwksp = NULL;
39 static void
40 eapd_hup_hdlr(int sig)
42 if (eapd_nwksp)
43 eapd_nwksp->flags |= EAPD_WKSP_FLAG_SHUTDOWN;
45 return;
48 #ifdef EAPDDUMP
49 static void
50 eapd_dump_hdlr(int sig)
52 if (eapd_nwksp)
53 eapd_nwksp->flags |= EAPD_WKSP_FLAG_DUMP;
55 return;
57 #endif
59 static int
60 eapd_send(eapd_wksp_t *nwksp, int drvSocket, struct iovec *frags, int nfrags)
62 struct msghdr mh;
64 memset(&mh, 0, sizeof(mh));
65 mh.msg_name = (caddr_t) NULL;
66 mh.msg_namelen = 0;
67 mh.msg_iov = frags;
68 mh.msg_iovlen = nfrags;
70 if (sendmsg(drvSocket, &mh, 0) < 0) {
71 EAPD_ERROR("send error %d to drvSocket %d\n", errno, drvSocket);
72 return errno;
74 else {
75 EAPD_INFO("send successful on drvSocket %d\n", drvSocket);
78 return 0;
81 /* Send a canned EAPOL packet */
82 void
83 eapd_eapol_canned_send(eapd_wksp_t *nwksp, struct eapd_socket *Socket, eapd_sta_t *sta,
84 unsigned char code, unsigned char type)
86 eapol_header_t eapol;
87 eap_header_t eap;
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);
98 eap.code = code;
99 eap.id = sta->pae_id;
100 eap.length = eapol.length;
101 eap.type = type;
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);
111 void
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)
125 struct ifreq ifr;
126 struct sockaddr_ll ll;
128 if (nwksp == NULL || sock == NULL) {
129 EAPD_ERROR("Wrong arguments...\n");
130 return -1;
133 sock->drvSocket = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE_BRCM));
134 if (sock->drvSocket < 0) {
135 EAPD_ERROR("open socket error!!\n");
136 return -1;
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;
147 return -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;
161 return -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);
168 return 0;
172 eapd_brcm_close(int drvSocket)
174 close(drvSocket);
175 return 0;
178 #ifdef BCMWPA2
180 eapd_preauth_open(eapd_wksp_t *nwksp, eapd_preauth_socket_t *sock)
182 struct ifreq ifr;
183 struct sockaddr_ll ll;
185 if (nwksp == NULL || sock == NULL) {
186 EAPD_ERROR("Wrong arguments...\n");
187 return -1;
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");
193 return -1;
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;
204 return -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;
217 return -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);
224 return 0;
228 eapd_preauth_close(int drvSocket)
230 close(drvSocket);
231 return 0;
233 #endif /* BCMWPA2 */
236 * Configuration APIs
239 eapd_safe_get_conf(char *outval, int outval_size, char *name)
241 char *val;
243 if (name == NULL || outval == NULL) {
244 if (outval)
245 memset(outval, 0, outval_size);
246 return -1;
249 val = nvram_safe_get(name);
250 if (!strcmp(val, ""))
251 memset(outval, 0, outval_size);
252 else
253 snprintf(outval, outval_size, "%s", val);
254 return 0;
257 int main(int argc, char* argv[])
259 #ifdef BCMDBG
260 char *dbg;
261 #endif
263 #ifdef BCMDBG
264 /* display usage if nothing is specified */
265 if (argc == 2 &&
266 (!strncmp(argv[1], "-h", 2) ||
267 !strncmp(argv[1], "-H", 2))) {
268 eapd_wksp_display_usage();
269 return 0;
272 /* get eapd_msg_level from nvram */
273 if ((dbg = nvram_get("eapd_dbg"))) {
274 eapd_msg_level = (uint)strtoul(dbg, NULL, 0);
277 #endif
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");
282 return -1;
285 #if EAPD_WKSP_AUTO_CONFIG
286 /* auto config */
287 if (argc == 1) {
288 if (eapd_wksp_auto_config(eapd_nwksp)) {
289 EAPD_ERROR("Unable to auto config. Quitting...\n");
290 eapd_wksp_cleanup(eapd_nwksp);
291 return -1;
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);
297 return -1;
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);
304 return -1;
306 #endif /* EAPD_WKSP_AUTO_CONFIG */
308 /* establish a handler to handle SIGTERM. */
309 signal(SIGTERM, eapd_hup_hdlr);
311 #ifdef EAPDDUMP
312 signal(SIGUSR1, eapd_dump_hdlr);
313 #endif
315 /* run main loop to dispatch messages */
316 eapd_wksp_main_loop(eapd_nwksp);
318 EAPD_INFO("EAP Dispatcher Stopped...\n");
320 return 0;