K2.6 patches and update.
[tomato.git] / release / src-rt / wl / eapd / wps_eap.c
blob4beb6c184cf03b6796d396ecf71bbadfd8e7e14c
1 /*
2 * Application-specific portion of EAPD
3 * (WPS)
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: wps_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>
35 #include <bcmconfig.h>
37 /* Receive message from wps module */
38 void
39 wps_app_recv_handler(eapd_wksp_t *nwksp, char *wlifname, eapd_cb_t *from,
40 uint8 *pData, int *pLen, struct ether_addr *ap_ea)
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 EAPD_ERROR("Message too short...\n");
54 return;
57 /* send message data out. */
58 sta_ea = (struct ether_addr*) eapol->eth.ether_dhost;
59 sta = sta_lookup(nwksp, sta_ea, NULL, wlifname, EAPD_SEARCH_ONLY);
61 /* monitor eapol packet */
62 if (eapol->type == EAPOL_START) {
63 /* remove exit */
64 if (sta)
65 sta_remove(nwksp, sta);
66 /* create new one */
67 sta = sta_lookup(nwksp, sta_ea, ap_ea, wlifname, EAPD_SEARCH_ENTER);
68 if (sta) {
69 sta->mode = EAPD_STA_MODE_WPS_ENR;
72 else {
73 eap = (eap_header_t *) eapol->body;
74 /* remove sta info when FAILURE or SUCCESS */
75 if ((sta) && (eapol->type == EAP_PACKET) &&
76 (eap->code == EAP_FAILURE || eap->code == EAP_SUCCESS)) {
77 sta_remove(nwksp, sta);
81 eapd_message_send(nwksp, from->brcmSocket, pData, *pLen);
83 return;
86 void
87 wps_app_set_eventmask(eapd_app_t *app)
89 memset(app->bitvec, 0, sizeof(app->bitvec));
91 setbit(app->bitvec, WLC_E_EAPOL_MSG);
92 setbit(app->bitvec, WLC_E_PROBREQ_MSG);
95 #ifdef __CONFIG_WFI__
96 setbit(app->bitvec, WLC_E_ASSOC_IND);
97 setbit(app->bitvec, WLC_E_REASSOC_IND);
98 setbit(app->bitvec, WLC_E_DISASSOC_IND);
99 setbit(app->bitvec, WLC_E_DEAUTH_IND);
100 #endif /* __CONFIG_WFI__ */
103 return;
107 wps_app_init(eapd_wksp_t *nwksp)
109 int reuse = 1;
110 eapd_wps_t *wps;
111 eapd_cb_t *cb;
112 struct sockaddr_in addr;
114 if (nwksp == NULL)
115 return -1;
117 wps = &nwksp->wps;
118 wps->appSocket = -1;
120 cb = wps->cb;
121 if (cb == NULL) {
122 EAPD_INFO("No any interface is running WPS !\n");
123 return 0;
126 while (cb) {
127 EAPD_INFO("init brcm interface %s \n", cb->ifname);
128 cb->brcmSocket = eapd_add_brcm(nwksp, cb->ifname);
129 if (!cb->brcmSocket)
130 return -1;
131 /* set this brcmSocket have WPS capability */
132 cb->brcmSocket->flag |= EAPD_CAP_WPS;
134 cb = cb->next;
138 * appSocket for wps-monitor, wps-monitor handle all wps
139 * relative packets
141 wps->appSocket = socket(AF_INET, SOCK_DGRAM, 0);
142 if (wps->appSocket < 0) {
143 EAPD_ERROR("UDP Open failed.\n");
144 return -1;
146 #if defined(__ECOS)
147 if (setsockopt(wps->appSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&reuse,
148 sizeof(reuse)) < 0) {
149 EAPD_ERROR("UDP setsockopt failed.\n");
150 close(wps->appSocket);
151 wps->appSocket = -1;
152 return -1;
154 #else
155 if (setsockopt(wps->appSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse,
156 sizeof(reuse)) < 0) {
157 EAPD_ERROR("UDP setsockopt failed.\n");
158 close(wps->appSocket);
159 wps->appSocket = -1;
160 return -1;
162 #endif
164 memset(&addr, 0, sizeof(struct sockaddr_in));
165 addr.sin_family = AF_INET;
166 addr.sin_addr.s_addr = INADDR_ANY;
167 addr.sin_port = htons(EAPD_WKSP_WPS_UDP_RPORT);
168 if (bind(wps->appSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
169 EAPD_ERROR("UDP Bind failed, close wps appSocket %d\n", wps->appSocket);
170 close(wps->appSocket);
171 wps->appSocket = -1;
172 return -1;
174 EAPD_INFO("WPS appSocket %d opened\n", wps->appSocket);
176 return 0;
180 wps_app_deinit(eapd_wksp_t *nwksp)
182 eapd_wps_t *wps;
183 eapd_cb_t *cb, *tmp_cb;
185 if (nwksp == NULL) {
186 EAPD_ERROR("Wrong argument...\n");
187 return -1;
189 wps = &nwksp->wps;
190 cb = wps->cb;
191 while (cb) {
192 /* brcm drvSocket delete */
193 if (cb->brcmSocket) {
194 EAPD_INFO("close wps brcmSocket %d\n", cb->brcmSocket->drvSocket);
195 eapd_del_brcm(nwksp, cb->brcmSocket);
198 tmp_cb = cb;
199 cb = cb->next;
200 free(tmp_cb);
203 /* close appSocket for wps-monitor */
204 if (wps->appSocket >= 0) {
205 EAPD_INFO("close wps m_appSocket %d\n", wps->appSocket);
206 close(wps->appSocket);
207 wps->appSocket = -1;
210 return 0;
214 wps_app_monitor_sendup(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
216 eapd_wps_t *wps;
218 if (nwksp == NULL) {
219 EAPD_ERROR("Wrong argument...\n");
220 return -1;
223 wps = &nwksp->wps;
224 if (wps->appSocket >= 0) {
225 /* send to wps-monitor */
226 int sentBytes = 0;
227 struct sockaddr_in to;
229 to.sin_addr.s_addr = inet_addr(EAPD_WKSP_UDP_ADDR);
230 to.sin_family = AF_INET;
231 to.sin_port = htons(EAPD_WKSP_WPS_UDP_MPORT);
233 sentBytes = sendto(wps->appSocket, (char *)pData, Len, 0,
234 (struct sockaddr *)&to, sizeof(struct sockaddr_in));
236 if (sentBytes != Len) {
237 EAPD_ERROR("UDP send to wps-monitor on %s failed; sentBytes = %d\n",
238 from, sentBytes);
240 else {
241 /* EAPD_INFO("send %d bytes to wps-monitor on %s\n", sentBytes, from); */
244 else {
245 EAPD_ERROR("wps-monitor appSocket not created\n");
248 return 0;
251 #if EAPD_WKSP_AUTO_CONFIG
253 wps_app_enabled(char *name)
255 char value[128], os_name[IFNAMSIZ], temp[32], prefix[8];
256 int unit;
258 if (nvifname_to_osifname(name, os_name, sizeof(os_name)) < 0)
259 return 0;
260 if (wl_probe(os_name) ||
261 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)))
262 return 0;
263 /* Convert eth name to wl name */
264 if (osifname_to_nvifname(name, prefix, sizeof(prefix)) != 0)
265 return 0;
267 strcat(prefix, "_");
268 eapd_safe_get_conf(value, sizeof(value), strcat_r(prefix, "bss_enabled", temp));
269 if (strcmp(value, "1"))
270 return 0;
272 eapd_safe_get_conf(value, sizeof(value), strcat_r(prefix, "wps_mode", temp));
273 if (!strcmp(value, "enabled") || !strcmp(value, "enr_enabled"))
274 return 1;
276 return 0;
278 #endif /* EAPD_WKSP_AUTO_CONFIG */
281 wps_app_handle_event(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
283 int type;
284 eapd_wps_t *wps;
285 eapd_cb_t *cb;
286 bcm_event_t *dpkt = (bcm_event_t *) pData;
287 wl_event_msg_t *event;
289 event = &(dpkt->event);
290 type = ntohl(event->event_type);
292 wps = &nwksp->wps;
293 cb = wps->cb;
294 while (cb) {
295 if (isset(wps->bitvec, type) && !strcmp(cb->ifname, from)) {
296 /* prepend ifname, we reserved IFNAMSIZ length already */
297 pData -= IFNAMSIZ;
298 Len += IFNAMSIZ;
299 memcpy(pData, event->ifname, IFNAMSIZ);
301 /* send to wps use cb->ifname */
302 wps_app_monitor_sendup(nwksp, pData, Len, cb->ifname);
303 break;
305 cb = cb->next;
308 return 0;