445 lines
13 KiB
C
445 lines
13 KiB
C
/* ipwps_private_api.c - WSC Private API implementation */
|
|
|
|
/*
|
|
* Copyright (c) 2008 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute, modify, or otherwise make use
|
|
* of this software may be licensed only pursuant to the terms
|
|
* of an applicable Wind River license agreement.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01a,13Jan09,mry Created
|
|
*/
|
|
|
|
/* DESCRIPTION:
|
|
* ===========
|
|
* Implements the IPWPS private APIs used by IPWPS related modules.
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipwps_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_errno.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_ipd.h>
|
|
|
|
#include "ipwps_debug.h"
|
|
#include "ipwps_public.h"
|
|
#include "ipwps_private_api.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_send_timeout_event
|
|
*===========================================================================
|
|
* Description: .
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err ipwps_send_timeout_event(Ipwps_msg_type_wpstimeout tmo_evtype) {
|
|
Ipwps_ipd_msg *request, *response;
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
|
|
if (!IPWPS_ISVALID_TIMEOUT_EVENT_TYPE(tmo_evtype)) {
|
|
IPCOM_LOG1(ERR, "ipwps_send_timeout_event :: Invalid tmo_evtype %d", tmo_evtype);
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
request = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
response = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
if (!request || !response ) {
|
|
rc = IPCOM_ERR_NO_MEMORY;
|
|
goto done_timeout_event;
|
|
}
|
|
|
|
IPWPS_PREPARE_IPD_MSG(request, IPWPS_IPD_EVENT_WPSTIMEOUT, IPCOM_SUCCESS, tmo_evtype);
|
|
|
|
rc = ipcom_ipd_datamsg(IPWPS_PROCESS_NAME,request,sizeof(Ipwps_ipd_msg),response,sizeof(Ipwps_ipd_msg));
|
|
if (rc != IPCOM_SUCCESS) {
|
|
IPCOM_LOG1(ERR, "ipwps_send_timeout_event :: ipcom_ipd_datamsg() failed, rc = %d", rc);
|
|
goto done_timeout_event;
|
|
}
|
|
|
|
rc = response->ipd_msg.msgerr;
|
|
if (rc < 0) {
|
|
IPCOM_LOG2(ERR, "ipwps_send_timeout_event :: failure response msgerr = %d (%s)", rc, ipcom_err_string(rc));
|
|
}
|
|
|
|
done_timeout_event:
|
|
if (response)
|
|
ipcom_free(response);
|
|
if (request)
|
|
ipcom_free(request);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_notify_eapol_start
|
|
*===========================================================================
|
|
* Description: .
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_notify_eapol_start(char* wls_if, Ip_u32 ip8021x_instance, Ip_u8* peer_eth_addr) {
|
|
Ipwps_ipd_msg *request, *response;
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
|
|
if (!wls_if || !peer_eth_addr)
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
|
|
IPCOM_LOG9(DEBUG2, "%s: wls_if : %s, ip8021x_inst: %d, peer_addr: %.2x %.2x %.2x %.2x %.2x %.2x\n", __FUNCTION__,
|
|
wls_if, ip8021x_instance,
|
|
peer_eth_addr[0], peer_eth_addr[1], peer_eth_addr[2], peer_eth_addr[3], peer_eth_addr[4], peer_eth_addr[5]);
|
|
|
|
|
|
request = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
response = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
if (!request || !response ) {
|
|
rc = IPCOM_ERR_NO_MEMORY;
|
|
goto done_eapol_event;
|
|
}
|
|
|
|
IPWPS_PREPARE_IPD_MSG(request, IPWPS_IPD_EVENT_WPSPROTO, IPCOM_SUCCESS, IPWPS_MSG_TYPE_WPSPROTO_EAPOL_NOTIFY);
|
|
|
|
request->wps_msg_data.wps_eapol_notify.eapol_event = IPWPS_EAPOL_EVENT_RCV_START;
|
|
ipcom_memcpy(request->wps_msg_data.wps_eapol_notify.if_name, wls_if, IPWPS_MAX_IFNAME);
|
|
request->wps_msg_data.wps_eapol_notify.ip8021x_inst = ip8021x_instance;
|
|
ipcom_memcpy(request->wps_msg_data.wps_eapol_notify.peeraddr, peer_eth_addr, 6);
|
|
|
|
rc = ipcom_ipd_datamsg(IPWPS_PROCESS_NAME,request,sizeof(Ipwps_ipd_msg),response,sizeof(Ipwps_ipd_msg));
|
|
if (rc != IPCOM_SUCCESS) {
|
|
IPCOM_LOG2(ERR, "ipwps_handle_wsc_event :: ipcom_ipd_datamsg() failed, rc = %d (%s)", rc, ipcom_err_string(rc));
|
|
goto done_eapol_event;
|
|
}
|
|
|
|
rc = response->ipd_msg.msgerr;
|
|
if (rc < 0) {
|
|
IPCOM_LOG2(ERR, "ipwps_handle_wsc_event :: failure response msgerr = %d (%s)", rc, ipcom_err_string(rc));
|
|
}
|
|
|
|
done_eapol_event:
|
|
if (response)
|
|
ipcom_free(response);
|
|
if (request)
|
|
ipcom_free(request);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_create_proto_msg_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipwps_wsc_proto_msg *ipwps_create_proto_msg_data(int event_or_rc, Ip_u32 datasize, Ip_u8 *data) {
|
|
Ipwps_wsc_proto_msg *msg_data;
|
|
|
|
if (datasize > IPWPS_PROTO_MSG_DATALEN_MAX) {
|
|
IPCOM_LOG2(CRIT, "ipwps_create_proto_msg_data :: requested datasize %d > max len %d",
|
|
datasize, IPWPS_PROTO_MSG_DATALEN_MAX);
|
|
return IP_NULL;
|
|
}
|
|
if (datasize && !data) {
|
|
IPCOM_LOG1(ERR, "ipwps_create_proto_msg_data :: null data for non zero datasize %d",
|
|
datasize);
|
|
return IP_NULL;
|
|
}
|
|
|
|
msg_data = ipcom_calloc(1, sizeof(Ipwps_wsc_proto_msg));
|
|
if (msg_data) {
|
|
msg_data->event_or_rc = event_or_rc;
|
|
msg_data->proto_data.len = datasize;
|
|
if (datasize)
|
|
ipcom_memcpy(msg_data->proto_data.data, data, datasize);
|
|
}
|
|
return msg_data;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_wsc_event_name
|
|
*===========================================================================
|
|
* Description: .
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL char *
|
|
ipwps_wsc_event_name(Ipwps_wsc_event wsc_event) {
|
|
char *name = "UNKNOWN";
|
|
|
|
switch (wsc_event) {
|
|
case IPWPS_WSC_EVENT_RCV_ID_RESP:
|
|
name = "IPWPS_WSC_EVENT_RCV_ID_RESP";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_WSC_START:
|
|
name = "IPWPS_WSC_EVENT_RCV_WSC_START";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_WSC_ACK:
|
|
name = "IPWPS_WSC_EVENT_RCV_WSC_ACK";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_WSC_NACK:
|
|
name = "IPWPS_WSC_EVENT_RCV_WSC_NACK";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_WSC_MSG:
|
|
name = "IPWPS_WSC_EVENT_RCV_WSC_MSG";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_WSC_DONE:
|
|
name = "IPWPS_WSC_EVENT_RCV_WSC_DONE";
|
|
break;
|
|
case IPWPS_WSC_EVENT_RCV_EAP_FAIL:
|
|
name = "IPWPS_WSC_EVENT_RCV_EAP_FAIL";
|
|
break;
|
|
default:
|
|
IP_PANIC();
|
|
break;
|
|
}
|
|
return name;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_handle_wsc_event
|
|
*===========================================================================
|
|
* Description: .
|
|
* Parameters:
|
|
* Returns:
|
|
* return code from ipd message or IPCOM_ERR_TIMEOUT in case of response timeout
|
|
* or error indication.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_err ipwps_handle_wsc_event
|
|
(
|
|
Ipwps_wsc_proto_msg *wsc_rcvd_msg,
|
|
Ipwps_wsc_rc *wsc_rc,
|
|
Ipwps_proto_data **wsc_resp_data
|
|
) {
|
|
Ipwps_ipd_msg *request, *response;
|
|
Ipwps_proto_data *resp_data = IP_NULL;
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
|
|
ip_assert(wsc_rcvd_msg);
|
|
|
|
#ifdef IPWPS_DEBUG_WSC_EVENTS
|
|
IPCOM_LOG2(DEBUG2, "ipwps_handle_wsc_event :: Received event %s with datasize %d",
|
|
ipwps_wsc_event_name((Ipwps_wsc_event)wsc_rcvd_msg->event_or_rc), wsc_rcvd_msg->proto_data.len);
|
|
ipwps_dump_data("ipwps_handle_wsc_event :: data:", wsc_rcvd_msg->proto_data.data, wsc_rcvd_msg->proto_data.len);
|
|
#endif
|
|
ip_assert(wsc_rc);
|
|
ip_assert(wsc_resp_data);
|
|
|
|
request = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
response = ipcom_calloc(1, sizeof(Ipwps_ipd_msg));
|
|
if (!request || !response ) {
|
|
rc = IPCOM_ERR_NO_MEMORY;
|
|
goto done_wsc_event;
|
|
}
|
|
|
|
IPWPS_PREPARE_IPD_MSG(request, IPWPS_IPD_EVENT_WPSPROTO, IPCOM_SUCCESS, IPWPS_MSG_TYPE_WPSPROTO_WSCNOTIFY);
|
|
|
|
ipcom_memcpy(&request->wps_msg_data.wps_proto_msg, wsc_rcvd_msg, sizeof(Ipwps_wsc_proto_msg));
|
|
rc = ipcom_ipd_datamsg(IPWPS_PROCESS_NAME,request,sizeof(Ipwps_ipd_msg),response,sizeof(Ipwps_ipd_msg));
|
|
if (rc != IPCOM_SUCCESS) {
|
|
IPCOM_LOG1(ERR, "ipwps_handle_wsc_event :: ipcom_ipd_datamsg() failed, rc = %d", rc);
|
|
goto done_wsc_event;
|
|
}
|
|
|
|
rc = response->ipd_msg.msgerr;
|
|
if (rc < 0) {
|
|
IPCOM_LOG1(ERR, "ipwps_handle_wsc_event :: failure response msgerr = %d", rc);
|
|
goto done_wsc_event;
|
|
}
|
|
|
|
if (response->wps_msg_type.wpsproto != IPWPS_MSG_TYPE_WPSPROTO_WSCRESPONSE) {
|
|
IPCOM_LOG1(ERR, "ipwps_handle_wsc_event :: unexpected response wps_msg_type = %d", (response->wps_msg_type.overlay));
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto done_wsc_event;
|
|
}
|
|
*wsc_rc = (Ipwps_wsc_rc)response->wps_msg_data.wps_proto_msg.event_or_rc;
|
|
if (response->wps_msg_data.wps_proto_msg.proto_data.len == 0)
|
|
goto done_wsc_event;
|
|
|
|
#ifdef IPWPS_DEBUG_WSC_EVENTS
|
|
IPCOM_LOG3(DEBUG2, "ipwps_handle_wsc_event :: response rc = %d (%s), wsc_rc = %d",
|
|
rc, ipcom_err_string(rc), *wsc_rc);
|
|
#endif
|
|
resp_data = ipcom_calloc(1, sizeof(Ipwps_proto_data));
|
|
if (!resp_data) {
|
|
IPCOM_LOG0(CRIT, "ipwps_handle_wsc_event :: failed to alloc resp_data");
|
|
rc = IPCOM_ERR_NO_MEMORY;
|
|
goto done_wsc_event;
|
|
}
|
|
ipcom_memcpy(resp_data, &response->wps_msg_data.wps_proto_msg.proto_data, sizeof(Ipwps_proto_data));
|
|
|
|
done_wsc_event:
|
|
if (response)
|
|
ipcom_free(response);
|
|
if (request)
|
|
ipcom_free(request);
|
|
|
|
*wsc_resp_data = resp_data;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_dump_data
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipwps_dump_data(char *prefix_str, Ip_u8* buf, int len)
|
|
{
|
|
char* str;
|
|
int i;
|
|
|
|
if (!buf) {
|
|
IPCOM_LOG1(DEBUG2, "ipwps_dump_data :: null buffer, len = %d", len);
|
|
return;
|
|
}
|
|
str = ipcom_calloc(1, len*2+1);
|
|
if (str)
|
|
{
|
|
for(i=0; i<len; i++)
|
|
{
|
|
ipcom_sprintf(&str[2*i], "%02x", (unsigned char)buf[i]);
|
|
}
|
|
str[2*len] = 0;
|
|
|
|
IPCOM_LOG3(DEBUG2, "%s (%d bytes) %s", prefix_str, len, str);
|
|
|
|
|
|
ipcom_free(str);
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "ipwps_dump_data :: failed to log %d bytes buffer", len);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipwps_dump_ascii
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipwps_dump_ascii(char *prefix_str, Ip_u8* buf, int len)
|
|
{
|
|
char* str;
|
|
int i;
|
|
|
|
if (!buf) {
|
|
IPCOM_LOG1(DEBUG2, "ipwps_dump_ascii :: null buffer, len = %d", len);
|
|
return;
|
|
}
|
|
str = ipcom_calloc(1, len+1);
|
|
if (str)
|
|
{
|
|
for(i=0; i<len; i++)
|
|
{
|
|
ipcom_sprintf(&str[i], "%c", (char)buf[i]);
|
|
}
|
|
str[len] = '\0'; /* NULL Terminate */
|
|
|
|
IPCOM_LOG3(DEBUG2, "%s (%d bytes) %s", prefix_str, len, str);
|
|
|
|
|
|
ipcom_free(str);
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "ipwps_dump_ascii :: failed to log %d bytes buffer", len);
|
|
}
|
|
}
|
|
|