sdk-hwV1.3/external/eyesee-mpp/system/public/wifi/wpa_supplicant/wpa_ctrl.c

293 lines
8.7 KiB
C
Executable File

/* *******************************************************************************
* Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
* *******************************************************************************/
/**
* @file wpa_ctrl.c
* @brief Control wpa_supplicant moudel
* @author id:
* @version v0.1
* @date 2016-08-28
*/
/******************************************************************************/
/* Include Files */
/******************************************************************************/
#include "wpa_ctrl.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
/******************************************************************************/
/* Macros & Typedefs */
/******************************************************************************/
/* None */
/******************************************************************************/
/* Structure Declarations */
/******************************************************************************/
/* None */
/******************************************************************************/
/* Global Variables */
/******************************************************************************/
/* None */
/******************************************************************************/
/* Function Declarations */
/******************************************************************************/
/* None */
/******************************************************************************/
/* Function Definitions */
/******************************************************************************/
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
int ret = 0;
int tries = 0;
int flags = 0;
size_t res = 0;
static int counter = 0;
struct wpa_ctrl *ctrl = NULL;
ctrl = malloc(sizeof(struct wpa_ctrl));
if (NULL == ctrl) {
printf("[FUN]:%s [LINE]:%d Input wifi_name or pscan_status is NULL!\n",
__func__, __LINE__);
return NULL;
}
memset(ctrl, 0 , sizeof(struct wpa_ctrl));
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
printf("[FUN]:%s [LINE]:%d Fail to create PF_UNIX socket! errno[%d] errinfo[%s]\n",
__func__, __LINE__, errno, strerror(errno));
free(ctrl);
return NULL;
}
ctrl->local.sun_family = AF_UNIX;
counter++;
do {
ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
"/tmp/wpa_ctrl_%d-%d", getpid(), counter);
if (ret < 0 || (unsigned int) ret >= sizeof(ctrl->local.sun_path)) {
close(ctrl->s);
free(ctrl);
return NULL;
}
tries++;
unlink(ctrl->local.sun_path);
ret = bind(ctrl->s, (struct sockaddr *)&ctrl->local, sizeof(ctrl->local));
if (ret < 0) {
printf("[FUN]:%s [LINE]:%d Fail to bind UNIX:%s socket! tries[%d] EADDRINUSE[%d] ret[%d] errno[%d] errinfo[%s]\n",
__func__, __LINE__, ctrl->local.sun_path, tries, EADDRINUSE, ret, errno, strerror(errno));
if (EADDRINUSE == errno && tries < 4) {
printf("[FUN]:%s [LINE]:%d Do bind next. tries:%d \n", __func__, __LINE__, tries);
/*
* getpid() returns unique identifier for this instance
* of wpa_ctrl, so the existing socket file must have
* been left by unclean termination of an earlier run.
* Remove the file and try again.
*/
unlink(ctrl->local.sun_path);
usleep(10);
continue;
}
close(ctrl->s);
free(ctrl);
return NULL;
}
printf("[FUN]:%s [LINE]:%d bind UNIX:%s socket OK! ret:%d\n", __func__, __LINE__, ctrl->local.sun_path, ret);
break;
} while (1);
ctrl->dest.sun_family = AF_UNIX;
if (strlen(ctrl_path) >= sizeof(ctrl->dest.sun_path)) {
printf("[FUN]:%s [LINE]:%d error! ctrl_path:%s sun_path:%s \n",
__func__, __LINE__, ctrl_path, ctrl->dest.sun_path);
close(ctrl->s);
free(ctrl);
return NULL;
}
memset(ctrl->dest.sun_path, 0, sizeof(ctrl->dest.sun_path));
strncpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path));
ret = connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest));
if (ret < 0) {
printf("[FUN]:%s [LINE]:%d Fail connect! ret:%d errno[%d] errinfo[%s]\n",
__func__, __LINE__, ret, errno, strerror(errno));
close(ctrl->s);
unlink(ctrl->local.sun_path);
free(ctrl);
return NULL;
}
return ctrl;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
unlink(ctrl->local.sun_path);
close(ctrl->s);
free(ctrl);
}
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
{
int res = 0;
const char *_cmd = NULL;
fd_set rfds;
size_t _cmd_len;
struct timeval tv;
_cmd = cmd;
_cmd_len = cmd_len;
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
printf("[FUN]:%s [LINE]:%d Fail connect! errno[%d] errinfo[%s]\n", __func__, __LINE__,
errno, strerror(errno));
return -1;
}
for (;;) {
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
if (res < 0) {
return res;
}
if (FD_ISSET(ctrl->s, &rfds)) {
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0) {
printf("[FUN]:%s [LINE]:%d Fail connect! errno[%d] errinfo[%s]\n",
__func__, __LINE__, errno, strerror(errno));
return res;
}
if (res > 0 && reply[0] == '<') {
/* This is an unsolicited message from
* wpa_supplicant, not the reply to the
* request. Use msg_cb to report this to the
* caller. */
if (msg_cb) {
/* Make sure the message is nul
* terminated. */
if ((size_t) res == *reply_len) {
res = (*reply_len) - 1;
}
reply[res] = '\0';
msg_cb(reply, res);
}
continue;
}
*reply_len = res;
break;
} else {
return -2;
}
}
return 0;
}
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
{
int ret = 0;
char buf[10] = {0};
size_t len = 10;
ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
buf, &len, NULL);
if (ret < 0) {
return ret;
}
if (3 == len && memcmp(buf, "OK\n", 3) == 0) {
return 0;
}
return -1;
}
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 1);
}
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 0);
}
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, int *reply_len)
{
int res;
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0) {
printf("[FUN]:%s [LINE]:%d Fail connect! res:%d errno[%d] errinfo[%s]\n",
__func__, __LINE__, res, errno, strerror(errno));
return res;
}
*reply_len = res;
return 0;
}
int wpa_ctrl_pending(struct wpa_ctrl *ctrl, int sec, int usec)
{
int ret = 0;
struct timeval tv;
fd_set rfds;
tv.tv_sec = sec;
tv.tv_usec = usec;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
if (0 == sec && 0 == usec) {
ret = select(ctrl->s + 1, &rfds, NULL, NULL, NULL);
} else {
ret = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
}
if (ret < 0) {
return -1;
} else if(0 == ret) {
return 0;
}
return FD_ISSET(ctrl->s, &rfds);
}
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
{
return ctrl->s;
}