K2.6 patches and update.
[tomato.git] / release / src-rt / wl / eapd / ses_eap.c
blob40fe2ee211be5211b0f3f8828f76de48a2bec69f
1 /*
2 * Application-specific portion of EAPD
3 * (SES)
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: ses_eap.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 <sys/types.h>
21 #include <sys/socket.h>
22 #include <net/if.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <typedefs.h>
26 #include <bcmutils.h>
27 #include <proto/ethernet.h>
28 #include <proto/eapol.h>
29 #include <proto/eap.h>
30 #include <wlutils.h>
31 #include <eapd.h>
32 #include <shutils.h>
33 #include <UdpLib.h>
34 #include <security_ipc.h>
36 #define SES_NV_INTERFACE "ses_interface"
38 void
39 ses_app_recv_handler(eapd_wksp_t *nwksp, char *wlifname, eapd_cb_t *from,
40 uint8 *pData, int *pLen)
42 eapol_header_t *eapol = (eapol_header_t*) pData;
43 eap_header_t *eap;
44 eapd_sta_t *sta;
45 struct ether_addr *sta_ea;
47 if (!nwksp || !wlifname || !from || !pData) {
48 EAPD_ERROR("Wrong arguments...\n");
49 return;
52 if (*pLen < EAPOL_HEADER_LEN)
53 return; /* message too short */
55 /* send message data out. */
56 sta_ea = (struct ether_addr*) eapol->eth.ether_dhost;
57 sta = sta_lookup(nwksp, sta_ea, NULL, wlifname, EAPD_SEARCH_ONLY);
59 /* monitor eapol packet */
60 eap = (eap_header_t *) eapol->body;
61 if ((sta) && (eapol->type == EAP_PACKET) &&
62 (eap->code == EAP_FAILURE || eap->code == EAP_SUCCESS)) {
63 sta_remove(nwksp, sta);
66 eapd_message_send(nwksp, from->brcmSocket, (uint8*) eapol, *pLen);
68 return;
71 void
72 ses_app_set_eventmask(eapd_app_t *app)
74 memset(app->bitvec, 0, sizeof(app->bitvec));
76 setbit(app->bitvec, WLC_E_EAPOL_MSG);
77 return;
80 int
81 ses_app_init(eapd_wksp_t *nwksp)
83 int reuse = 1;
84 eapd_ses_t *ses;
85 eapd_cb_t *cb;
86 struct sockaddr_in addr;
89 if (nwksp == NULL)
90 return -1;
92 ses = &nwksp->ses;
93 ses->appSocket = -1;
95 cb = ses->cb;
96 if (cb == NULL) {
97 EAPD_INFO("No any SES application need to run\n");
98 return 0;
101 while (cb) {
102 EAPD_INFO("ses: init brcm interface %s \n", cb->ifname);
103 cb->brcmSocket = eapd_add_brcm(nwksp, cb->ifname);
104 if (!cb->brcmSocket)
105 return -1;
106 /* set this brcmSocket have SES capability */
107 cb->brcmSocket->flag |= EAPD_CAP_SES;
109 cb = cb->next;
112 /* appSocket for ses */
113 ses->appSocket = socket(AF_INET, SOCK_DGRAM, 0);
114 if (ses->appSocket < 0) {
115 EAPD_ERROR("UDP Open failed.\n");
116 return -1;
118 #if defined(__ECOS)
119 if (setsockopt(ses->appSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&reuse,
120 sizeof(reuse)) < 0) {
121 EAPD_ERROR("UDP setsockopt failed.\n");
122 close(ses->appSocket);
123 ses->appSocket = -1;
124 return -1;
126 #else
127 if (setsockopt(ses->appSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse,
128 sizeof(reuse)) < 0) {
129 EAPD_ERROR("UDP setsockopt failed.\n");
130 close(ses->appSocket);
131 ses->appSocket = -1;
132 return -1;
134 #endif
136 memset(&addr, 0, sizeof(struct sockaddr_in));
137 addr.sin_family = AF_INET;
138 addr.sin_addr.s_addr = INADDR_ANY;
139 addr.sin_port = htons(EAPD_WKSP_SES_UDP_RPORT);
140 if (bind(ses->appSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
141 EAPD_ERROR("UDP Bind failed, close ses appSocket %d\n", ses->appSocket);
142 close(ses->appSocket);
143 ses->appSocket = -1;
144 return -1;
146 EAPD_INFO("SES appSocket %d opened\n", ses->appSocket);
148 return 0;
152 ses_app_deinit(eapd_wksp_t *nwksp)
154 eapd_ses_t *ses;
155 eapd_cb_t *cb, *tmp_cb;
157 if (nwksp == NULL) {
158 EAPD_ERROR("Wrong argument...\n");
159 return -1;
162 ses = &nwksp->ses;
163 cb = ses->cb;
164 while (cb) {
165 if (cb->brcmSocket) {
166 EAPD_INFO("close ses brcm drvSocket %d\n", cb->brcmSocket->drvSocket);
167 eapd_del_brcm(nwksp, cb->brcmSocket);
170 tmp_cb = cb;
171 cb = cb->next;
172 free(tmp_cb);
175 /* close appSocket */
176 if (ses->appSocket >= 0) {
177 EAPD_INFO("close ses appSocket %d\n", ses->appSocket);
178 close(ses->appSocket);
179 ses->appSocket = -1;
182 return 0;
186 ses_app_sendup(eapd_wksp_t *nwksp, uint8 *pData, int pLen, char *from)
188 eapd_ses_t *ses;
190 if (nwksp == NULL) {
191 EAPD_ERROR("Wrong argument...\n");
192 return -1;
195 ses = &nwksp->ses;
196 if (ses->appSocket >= 0) {
197 /* send to ses */
198 int sentBytes = 0;
199 struct sockaddr_in to;
201 to.sin_addr.s_addr = inet_addr(EAPD_WKSP_UDP_ADDR);
202 to.sin_family = AF_INET;
203 to.sin_port = htons(EAPD_WKSP_SES_UDP_SPORT);
205 sentBytes = sendto(ses->appSocket, (char *)pData, pLen, 0,
206 (struct sockaddr *)&to, sizeof(struct sockaddr_in));
208 if (sentBytes != pLen) {
209 EAPD_ERROR("UDP send failed; sentBytes = %d\n", sentBytes);
211 else {
212 /* EAPD_INFO("Send %d bytes to ses\n", sentBytes); */
215 else {
216 EAPD_ERROR("ses appSocket not created\n");
218 return 0;
221 #if EAPD_WKSP_AUTO_CONFIG
223 ses_app_enabled(char *name)
225 char value[128];
226 int unit;
228 /* ses service not enabled */
229 eapd_safe_get_conf(value, sizeof(value), "ses_enable");
230 if (strcmp(value, "1") != 0)
231 return 0;
233 eapd_safe_get_conf(value, sizeof(value), SES_NV_INTERFACE);
234 if (!strcmp(value, "")) {
235 if (wl_probe(name))
236 return 0;
237 snprintf(value, sizeof(value), "%s", name);
240 if ((wl_probe(value) != 0) ||
241 (wl_ioctl(value, WLC_GET_INSTANCE, &unit, sizeof(unit)) != 0)) {
242 EAPD_ERROR("ERROR: Invalid default wireless interface %s\n", value);
243 return 0;
246 return 1;
248 #endif /* EAPD_WKSP_AUTO_CONFIG */
251 ses_app_handle_event(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
253 int type;
254 eapd_ses_t *ses;
255 eapd_cb_t *cb;
256 bcm_event_t *dpkt = (bcm_event_t *) pData;
257 wl_event_msg_t *event;
259 event = &(dpkt->event);
260 type = ntohl(event->event_type);
262 ses = &nwksp->ses;
263 cb = ses->cb;
264 while (cb) {
265 if (isset(ses->bitvec, type) && !strcmp(cb->ifname, from)) {
266 /* prepend ifname, we reserved IFNAMSIZ length already */
267 pData -= IFNAMSIZ;
268 Len += IFNAMSIZ;
269 memcpy(pData, event->ifname, IFNAMSIZ);
271 /* send to ses use cb->ifname */
272 ses_app_sendup(nwksp, pData, Len, cb->ifname);
273 break;
275 cb = cb->next;
278 return 0;