You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
freshtomato-arm/release/src-rt-6.x.4708/router/eapd_arm/wps_eap.c

310 lines
6.9 KiB
C

/*
* Application-specific portion of EAPD
* (WPS)
*
* Copyright (C) 2013, Broadcom Corporation
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
* the contents of this file may not be disclosed to third parties, copied
* or duplicated in any form, in whole or in part, without the prior
* written permission of Broadcom Corporation.
*
* $Id: wps_eap.c 241182 2011-02-17 21:50:03Z $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <typedefs.h>
#include <bcmutils.h>
#include <proto/ethernet.h>
#include <proto/eapol.h>
#include <proto/eap.h>
#include <wlutils.h>
#include <eapd.h>
#include <shutils.h>
#include <UdpLib.h>
#include <security_ipc.h>
#include <bcmconfig.h>
/* Receive message from wps module */
void
wps_app_recv_handler(eapd_wksp_t *nwksp, char *wlifname, eapd_cb_t *from,
uint8 *pData, int *pLen, struct ether_addr *ap_ea)
{
eapol_header_t *eapol = (eapol_header_t*) pData;
eap_header_t *eap;
eapd_sta_t *sta;
struct ether_addr *sta_ea;
if (!nwksp || !wlifname || !from || !pData) {
EAPD_ERROR("Wrong arguments...\n");
return;
}
if (*pLen < EAPOL_HEADER_LEN) {
EAPD_ERROR("Message too short...\n");
return;
}
/* send message data out. */
sta_ea = (struct ether_addr*) eapol->eth.ether_dhost;
sta = sta_lookup(nwksp, sta_ea, NULL, wlifname, EAPD_SEARCH_ONLY);
/* monitor eapol packet */
if (eapol->type == EAPOL_START) {
/* remove exit */
if (sta)
sta_remove(nwksp, sta);
/* create new one */
sta = sta_lookup(nwksp, sta_ea, ap_ea, wlifname, EAPD_SEARCH_ENTER);
if (sta) {
sta->mode = EAPD_STA_MODE_WPS_ENR;
}
}
else {
eap = (eap_header_t *) eapol->body;
/* remove sta info when FAILURE or SUCCESS */
if ((sta) && (eapol->type == EAP_PACKET) &&
(eap->code == EAP_FAILURE || eap->code == EAP_SUCCESS)) {
sta_remove(nwksp, sta);
}
}
eapd_message_send(nwksp, from->brcmSocket, pData, *pLen);
return;
}
void
wps_app_set_eventmask(eapd_app_t *app)
{
memset(app->bitvec, 0, sizeof(app->bitvec));
setbit(app->bitvec, WLC_E_EAPOL_MSG);
setbit(app->bitvec, WLC_E_PROBREQ_MSG);
/*
*/
#ifdef __CONFIG_WFI__
setbit(app->bitvec, WLC_E_ASSOC_IND);
setbit(app->bitvec, WLC_E_REASSOC_IND);
setbit(app->bitvec, WLC_E_DISASSOC_IND);
setbit(app->bitvec, WLC_E_DEAUTH_IND);
#endif /* __CONFIG_WFI__ */
/*
*/
return;
}
int
wps_app_init(eapd_wksp_t *nwksp)
{
int reuse = 1;
eapd_wps_t *wps;
eapd_cb_t *cb;
struct sockaddr_in addr;
if (nwksp == NULL)
return -1;
wps = &nwksp->wps;
wps->appSocket = -1;
cb = wps->cb;
if (cb == NULL) {
EAPD_INFO("No any interface is running WPS !\n");
return 0;
}
while (cb) {
EAPD_INFO("init brcm interface %s \n", cb->ifname);
cb->brcmSocket = eapd_add_brcm(nwksp, cb->ifname);
if (!cb->brcmSocket)
return -1;
/* set this brcmSocket have WPS capability */
cb->brcmSocket->flag |= EAPD_CAP_WPS;
cb = cb->next;
}
/*
* appSocket for wps-monitor, wps-monitor handle all wps
* relative packets
*/
wps->appSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (wps->appSocket < 0) {
EAPD_ERROR("UDP Open failed.\n");
return -1;
}
#if defined(__ECOS)
if (setsockopt(wps->appSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&reuse,
sizeof(reuse)) < 0) {
EAPD_ERROR("UDP setsockopt failed.\n");
close(wps->appSocket);
wps->appSocket = -1;
return -1;
}
#else
if (setsockopt(wps->appSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse,
sizeof(reuse)) < 0) {
EAPD_ERROR("UDP setsockopt failed.\n");
close(wps->appSocket);
wps->appSocket = -1;
return -1;
}
#endif
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(EAPD_WKSP_WPS_UDP_RPORT);
if (bind(wps->appSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
EAPD_ERROR("UDP Bind failed, close wps appSocket %d\n", wps->appSocket);
close(wps->appSocket);
wps->appSocket = -1;
return -1;
}
EAPD_INFO("WPS appSocket %d opened\n", wps->appSocket);
return 0;
}
int
wps_app_deinit(eapd_wksp_t *nwksp)
{
eapd_wps_t *wps;
eapd_cb_t *cb, *tmp_cb;
if (nwksp == NULL) {
EAPD_ERROR("Wrong argument...\n");
return -1;
}
wps = &nwksp->wps;
cb = wps->cb;
while (cb) {
/* brcm drvSocket delete */
if (cb->brcmSocket) {
EAPD_INFO("close wps brcmSocket %d\n", cb->brcmSocket->drvSocket);
eapd_del_brcm(nwksp, cb->brcmSocket);
}
tmp_cb = cb;
cb = cb->next;
free(tmp_cb);
}
/* close appSocket for wps-monitor */
if (wps->appSocket >= 0) {
EAPD_INFO("close wps m_appSocket %d\n", wps->appSocket);
close(wps->appSocket);
wps->appSocket = -1;
}
return 0;
}
int
wps_app_monitor_sendup(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
{
eapd_wps_t *wps;
if (nwksp == NULL) {
EAPD_ERROR("Wrong argument...\n");
return -1;
}
wps = &nwksp->wps;
if (wps->appSocket >= 0) {
/* send to wps-monitor */
int sentBytes = 0;
struct sockaddr_in to;
to.sin_addr.s_addr = inet_addr(EAPD_WKSP_UDP_ADDR);
to.sin_family = AF_INET;
to.sin_port = htons(EAPD_WKSP_WPS_UDP_MPORT);
sentBytes = sendto(wps->appSocket, (char *)pData, Len, 0,
(struct sockaddr *)&to, sizeof(struct sockaddr_in));
if (sentBytes != Len) {
EAPD_ERROR("UDP send to wps-monitor on %s failed; sentBytes = %d\n",
from, sentBytes);
}
else {
/* EAPD_INFO("send %d bytes to wps-monitor on %s\n", sentBytes, from); */
}
}
else {
EAPD_ERROR("wps-monitor appSocket not created\n");
}
return 0;
}
#if EAPD_WKSP_AUTO_CONFIG
int
wps_app_enabled(char *name)
{
char value[128], os_name[IFNAMSIZ], temp[32], prefix[8];
int unit;
if (nvifname_to_osifname(name, os_name, sizeof(os_name)) < 0)
return 0;
if (wl_probe(os_name) ||
wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)))
return 0;
/* Convert eth name to wl name */
if (osifname_to_nvifname(name, prefix, sizeof(prefix)) != 0)
return 0;
strcat(prefix, "_");
eapd_safe_get_conf(value, sizeof(value), strlcat_r(prefix, "bss_enabled", temp, sizeof(temp)));
if (strcmp(value, "1"))
return 0;
eapd_safe_get_conf(value, sizeof(value), strlcat_r(prefix, "wps_mode", temp, sizeof(temp)));
if (!strcmp(value, "enabled") || !strcmp(value, "enr_enabled"))
return 1;
return 0;
}
#endif /* EAPD_WKSP_AUTO_CONFIG */
int
wps_app_handle_event(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
{
int type;
eapd_wps_t *wps;
eapd_cb_t *cb;
bcm_event_t *dpkt = (bcm_event_t *) pData;
wl_event_msg_t *event;
event = &(dpkt->event);
type = ntohl(event->event_type);
wps = &nwksp->wps;
cb = wps->cb;
while (cb) {
if (isset(wps->bitvec, type) && !strcmp(cb->ifname, from)) {
/* prepend ifname, we reserved IFNAMSIZ length already */
pData -= IFNAMSIZ;
Len += IFNAMSIZ;
memcpy(pData, event->ifname, IFNAMSIZ);
/* send to wps use cb->ifname */
wps_app_monitor_sendup(nwksp, pData, Len, cb->ifname);
break;
}
cb = cb->next;
}
return 0;
}