blob: 2275d98a0ff3e69aeb7899fa3752e4c9d857b1d4 [file] [log] [blame]
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <libubox/blobmsg_json.h>
#include "libubus.h"
#include <uci.h>
#include <include/log.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <fcntl.h>
#define WIFI_DEBUG
#ifdef WIFI_DEBUG
#define WIFI_DBG(format, args...) RDPRINTF("%s: " format,__FUNCTION__, ##args);
#else
#define WIFI_DBG(...) do {} while (0)
#endif
#define WIFI_ERR(format, args...) RERRMSG("%s: " format,__FUNCTION__, ##args);
#ifndef UNUSESET
#define UNUSESET(param) (void)(param)
#endif
#define WIFI_PACKAGE_NAME "wireless"
#define WIFI_SECTION_DEVICE "wifi-device"
#define WIFI_SECTION_IFACE "wifi-iface"
#define WIFI_SECTION_SETTING "wifi-settings"
#define WIFI_SECTION_CHIP "chip"
#define MAX_WIFI_DEVICE_SECTION 10
#define MAX_WIFI_IFACE_SECTION 10
#define MAX_DEV_NAME_LEN 32
#define ADD_MULTI_SSID_SEC 0
#define DELETE_MULTI_SSID_SEC 1
#define MAX_MULTI_SSID_NUM 2
#define IMSI_FILE "/tmp/imsi_file"
#define WIFI_SECTION_BS "wifi-bandSteering"
#define HOSTAPD_EV_WPS_START "WPS-START"
#define HOSTAPD_EV_WPS_FAIL "WPS-FAIL"
#define HOSTAPD_EV_WPS_SUCCESS "WPS-SUCCESS"
#define WPS_STATUS_CLEAR_TIMEOUT 2*60*1000 //ms
#define MULTI_VIRTUAL_AP_IFNAME_PREFIX "va"
extern struct ubus_context *applet_ubus_ctx;
static struct ubus_context *wifi_ubus_ctx = NULL;
static struct blob_buf wifi_buf;
static struct ubus_subscriber hostapd_event_subscriber;
static struct ubus_subscriber charger_event;
static struct ubus_subscriber hostapd_wlan1_event_subscriber;
static void wps_status_clear_cb(struct uloop_timeout *timeout);
static struct uloop_timeout wps_status_clear_timeout = {
.cb = wps_status_clear_cb,
};
#define MIN_AUTO_OFF_TIMEOUT 600
#define CHARGER_UBUS_ID "aoc"
#define CHARGER_UBUS_REQUEST "get_chg_info"
enum {
WIFI_OFF,
WIFI_START,
WIFI_READY,
NO_WIFI,
};
enum {
WIFI_AP0,
WIFI_AP1,
MAX_WIFI_CHIP_NUM
};
enum isolate_state{
AP_ISOLATE_NO_CHANGE,
AP_ISOLATE_OFF_ON,
AP_ISOLATE_ON_OFF
};
enum e_wps_status {
WPS_STATUS_INIT,
WPS_STATUS_START,
WPS_STATUS_SUCCESS,
WPS_STATUS_FAIL
};
enum e_wps_state{
WPS_STATE_INIT,
WPS_STATE_5G_PREFER,
WPS_STATE_5G_START,
WPS_STATE_5G_SUCCESS,
WPS_STATE_5G_FAIL,
WPS_STATE_24G_START,
WPS_STATE_24G_SUCCESS,
WPS_STATE_24G_FAIL
};
#define MULTI_SSID_NUM 3
struct ap_sec_info {
struct uci_section *device;
struct uci_section *iface[MULTI_SSID_NUM];
int n_ssid;
};
struct sta_sec_info {
struct uci_section *device;
struct uci_section *iface;
};
struct wifi_sec_info {
struct ap_sec_info ap_2G;
struct ap_sec_info ap_5G;
struct sta_sec_info sta;
struct uci_section *chip;
int auto_off_enable;
int auto_off_timeout;
};
struct wireless_info {
int n_dev;
struct wifi_sec_info wifi_info[MAX_WIFI_CHIP_NUM];
struct uci_section *chip;
struct uci_section *sec_bs;
int chip_type;
int wifi6;
int band_steering_support;
int band_steering_enable;
int wifi_5g_index;
int wifi_24g_index;
};
struct wps_conn_info {
enum e_wps_status wps_status;
char peer_mac[20];
};
struct wps_conn_ctx {
enum e_wps_state state;
int method; // 0: pbc, 1: pin
int ap_5g_index;
int ap_24g_index;
int ap_index;
char pin[32];
};
static const struct blobmsg_policy wps_event_pol[] = {
[0] = {
.name = "address",
.type = BLOBMSG_TYPE_STRING,
},
};
struct wps_conn_info g_wps_info[MAX_WIFI_CHIP_NUM];
struct wps_conn_ctx g_wps_conn_ctx;
/*==================================================================================
* Struct
* MCC -- Counrty
*
*=================================================================================*/
#define MAX_COUNTRY_NAME_LEN 32 /*Can be changed if necessary*/
typedef struct{
char mcc[4];
char country[MAX_COUNTRY_NAME_LEN];
char ccode[3];
}MCC_Country;
/*==================================================================================
* Static Array
* Mobile Country Code
*
*=================================================================================*/
static MCC_Country MrvlMccCountryTable[] =
{
{"001", "Test", ""},
{"289", "Abkhazia", "GE"},
{"412", "Afghanistan", "AF"},
{"276", "Albania", "AL"},
{"603", "Algeria", "DZ"},
{"544", "America", "AS"},
{"213", "Andorra", "AD"},
{"631", "Angola", "AO"},
{"365", "Anguilla", "AI"},
{"344", "Antigua", "AG"},
{"722", "Argentina", "AR"},
{"283", "Armenia", "AM"},
{"363", "Aruba", "AW"},
{"505", "Australia", "AU"},
{"232", "Austria", "AT"},
{"400", "Azerbaijan", "AZ"},
{"364", "Bahamas", "BS"},
{"426", "Bahrain", "BH"},
{"470", "Bangladesh", "BD"},
{"342", "Barbados", "BB"},
{"257", "Belarus", "BY"},
{"206", "Belgium", "BE"},
{"702", "Belize", "BZ"},
{"616", "Benin", "BJ"},
{"350", "Bermuda", "BM"},
{"402", "Bhutan", "BT"},
{"736", "Bolivia", "BO"},
{"218", "Bosnia", "BA"},
{"652", "Botswana", "BW"},
{"724", "Brazil", "BR"},
{"348", "British", "VG"},
{"528", "Brunei", "BN"},
{"284", "Bulgaria", "BG"},
{"613", "Burkina", "BF"},
{"642", "Burundi", "BI"},
{"456", "Cambodia", "KH"},
{"624", "Cameroon", "CM"},
{"302", "Canada", "CA"},
{"625", "Cape", "CV"},
{"346", "Cayman", "KY"},
{"623", "Centra African", "CF"},
{"622", "Chad", "TD"},
{"730", "Chile", "CL"},
{"460", "China", "CN"},
{"732", "Colombia", "CO"},
{"654", "Comoros", "KM"},
{"629", "Congo", "CG"},
{"548", "Cook Islands", "CK"},
{"712", "Costa Rica", "CR"},
{"612", "Ivory Coast", "CI"},
{"219", "Croatia", "HR"},
{"368", "Cuba", "CU"},
{"362", "AN", "CW"},
{"280", "Cyprus", "CY"},
{"230", "Czech Repubic", "CZ"},
{"630", "Democratic", "CD"},
{"238", "Denmark", "DK"},
{"638", "Djibouti", "DJ"},
{"366", "Dominica", "DM"},
{"370", "Dominican", "DO"},
{"514", "East Timor", "TL"},
{"740", "Ecuador", "EC"},
{"602", "Egypt", "EG"},
{"706", "EI Salvador", "SV"},
{"627", "Equatorial", "GQ"},
{"657", "Eritrea", "ER"},
{"248", "Estonia", "EE"},
{"636", "Ethiopia", "ET"},
{"288", "Faroe Islands", "FO"},
{"542", "Fiji", "FJ"},
{"244", "Finland", "FI"},
{"208", "France", "FR"},
{"547", "France", "PF"},
{"628", "Gabon", "GA"},
{"607", "Gambia", "GM"},
{"282", "Georgia", "GE"},
{"262", "Germany", "DE"},
{"620", "Ghana", "GH"},
{"266", "Gibraltar", "GI"},
{"202", "Greece", "GR"},
{"290", "Greenland", "GL"},
{"352", "Grenada", "GD"},
{"340", "Guadeloupe", "GP"},
{"704", "Guatemala", "GT"},
{"611", "Guinea", "GN"},
{"632", "Guinea-Bissau", "GW"},
{"738", "Guyana", "GY"},
{"372", "Haiti", "HT"},
{"708", "Honduras", "HN"},
{"454", "HongKong", "HK"},
{"216", "Hungary", "HU"},
{"274", "Iceland", "IS"},
{"404", "India", "IN"},
{"405", "India", "IN"},
{"510", "Indonesia", "ID"},
{"432", "Iran", "IR"},
{"418", "Iraq", "IQ"},
{"272", "Ireland", "IE"},
{"425", "Israle", "IL"},
{"222", "Italy", "IT"},
{"338", "Jamaica", "JM"},
{"440", "Japan", "JP"},
{"416", "Jordan", "JO"},
{"401", "Kazakhstan", "KZ"},
{"639", "Kenya", "KE"},
{"545", "Kiribati", "KI"},
{"467", "DPRK", "KP"},
{"450", "Korea", "KR"},
{"419", "Kuwait", "KW"},
{"437", "Kyrgyzstan", "KG"},
{"457", "Laos", "LA"},
{"247", "Latvia", "LV"},
{"415", "Lebanon", "LB"},
{"651", "Lesotho", "LS"},
{"618", "Liberia", "LR"},
{"606", "Libya", "LY"},
{"295", "Liechtenstein", "LI"},
{"246", "Lithuania", "LT"},
{"270", "Luxembourg", "LU"},
{"455", "Macau", "MO"},
{"294", "Macedonia", "MK"},
{"646", "Madagascar", "MG"},
{"650", "Malawi", "MW"},
{"502", "Malaysia", "MY"},
{"472", "Maldives", "MV"},
{"610", "Mali", "ML"},
{"278", "Malta", "MT"},
{"551", "Marshall Island", "MH"},
{"609", "Mauritania", "MR"},
{"617", "Mauritius", "MU"},
{"334", "Mexico", "MX"},
{"550", "Micronesia", "FM"},
{"259", "Moldva", "MD"},
{"212", "Monaco", "MC"},
{"428", "Mongolia", "MN"},
{"297", "Montenegro", "ME"},
{"354", "Montserrat", "MS"},
{"604", "Morocco", "MA"},
{"643", "Mozambique", "MZ"},
{"414", "Myanmar", "MM"},
{"649", "Namibia", "NA"},
{"536", "Nauru", "NR"},
{"429", "Nepal", "NP"},
{"204", "Netherlands", "NL"},
{"546", "New Caledonia", "NC"},
{"530", "New Zealand", "NZ"},
{"710", "Nicaragua", "NI"},
{"614", "Niger", "NE"},
{"621", "Nigeria", "NG"},
{"555", "Niue", "NU"},
{"242", "Norway", "NO"},
{"422", "Oman", "OM"},
{"410", "Pakistan", "PK"},
{"552", "Palau", "PW"},
{"714", "Pabana", "PA"},
{"537", "Papua", "PG"},
{"744", "Paraguay", "PY"},
{"716", "Peru", "PE"},
{"515", "Philippines", "PH"},
{"260", "Poland", "PL"},
{"268", "Portugal", "PT"},
{"330", "Puerto Rico", "PR"},
{"427", "Qatar", "QA"},
{"647", "RE", "RE"},
{"226", "Romania", "RO"},
{"250", "Russian", "RU"},
{"635", "Rwanda", "RW"},
{"356", "KN", "KN"},
{"358", "Saint Lucia", "LC"},
{"308", "PM", "PM"},
{"360", "VC", "VC"},
{"549", "Samoa", "WS"},
{"292", "San Marino", "SM"},
{"626", "ST", "ST"},
{"420", "Saudi Arabia", "SA"},
{"608", "Senegal", "SN"},
{"220", "Seribia", "RS"},
{"633", "Seychelles", "SC"},
{"619", "Sierra Leone", "SL"},
{"525", "Singapore", "SG"},
{"231", "Slovakia", "SK"},
{"293", "Slovenia", "SI"},
{"540", "Solomon", "SB"},
{"637", "Somalia", "SO"},
{"655", "South Africa", "ZA"},
{"659", "South Sudan", ""},
{"214", "Spain", "ES"},
{"413", "Sri Lanka", "LK"},
{"634", "Sudan", "SD"},
{"746", "Suriname", "SR"},
{"653", "Swaziland", "SZ"},
{"240", "Sweden", "SE"},
{"228", "Switzerland", "CH"},
{"417", "Syria", "SY"},
{"466", "Taiwan", "TW"},
{"436", "Tajikistan", "TJ"},
{"640", "Tanzania", "TZ"},
{"520", "Thailand", "TH"},
{"539", "Tonga", "TO"},
{"374", "Trinidad", "TT"},
{"605", "Tunisia", "TN"},
{"286", "Turkey", "TR"},
{"438", "Turkmenistan", "TM"},
{"376", "Turks(TC)", "TC"},
{"553", "Tuvalu", ""},
{"641", "Uganda", "UG"},
{"255", "UKraine", "UA"},
{"424", "Arab Emirates", "AE"},
{"234", "United Kingdom", "GB"},
{"310", "Guam", "US"},
{"311", "USA", "US"},
{"313", "USA", "US"},
{"316", "USA", "US"},
{"748", "Uruguay", "UY"},
{"434", "Uzbekistan", "UZ"},
{"541", "Vanuatu", "VU"},
{"225", "Vatican", "VA"},
{"734", "Venezuela", "VE"},
{"452", "Vietnam", "VN"},
{"421", "Yemen", "YE"},
{"645", "Zambia", "ZM"},
{"648", "Zimbabwe", "ZW"},
};
/* Domain and country mapping */
static char FCCDomain_Countries[][4] = {
"AE", "AM", "AN", "AR", "AU", "AZ", "BH", "BL", "BN", "BR", "CL", "CN", "CR", "CS", "DZ", "EC",
"EG", "GE", "GB", "HN", "HK", "ID", "IL", "IN", "IR", "JM", "JO", "KP", "KR", "KW", "KZ", "LB",
"LK", "MA", "MO", "MY", "NP", "OM", "PE", "PG", "PH", "PK", "PT", "QA", "SA", "SG", "SV", "SY",
"TH", "TT", "TN", "UY", "YE", "ZA", "ZW", "VN"
};
static char FCC1Domain_Countries[][4] = {
"US", "UZ", "CA", "CO", "DO", "GT", "MX", "PA", "PR", "TW", "NZ", "BO", "BZ", "VE"
};
static char MKKDomain_Countries[][4] = { "JP" };
static char ETSIDomain_Countries[][4] = {
"AL", "AD", "AT", "BY", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
"MK", "DE", "GR", "HU", "IS", "IE", "IT", "LV", "LI", "LT", "LU", "MT", "MD", "MC",
"ME", "NL", "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK", "ES", "SE", "CH", "TR",
"UA", "UK"
};
/* Domain specific sub-band information */
/* Domain name followed by set of triplets separated by comma */
/* 1st number in triplet is First channel, */
/* 2nd number in triplet is Number of channels followed from the First channel */
/* 3rd number in triplet is Max-TX-power in dbm */
static int FCCDomain_Subband[3] = {1, 13, 20};
static int FCC1Domain_Subband[3] = {1, 11, 30};
static int ETSIDomain_Subband[3] = {1, 13, 20};
static int MKKDomain_Subband[3] = {1, 14, 23};
#define HOSTAPD_SER "hostapd.uap0"
#define HOSTAPD_SER_PREFIX "hostapd"
static char hostapd_obj_name[32];
static int active_clients[MAX_WIFI_CHIP_NUM] = {0};
static int wifi_status[MAX_WIFI_CHIP_NUM] = {WIFI_OFF, WIFI_OFF};
struct wireless_info g_wireless_info;
int g_isolate_status;
int g_current_ap;
int ssid_change_notify(struct ubus_context *ctx, char *new_ssid);
void wifi_server_main(void);
extern struct uci_context *uci_applet_ctx_get(void);
extern void free_applet_uci_ctx(void);
//extern void obj_cm_add_ev(struct ubus_context *ctx, char *obj_path);
static struct uci_context *uci_wifi_ctx_get(void)
{
return uci_applet_ctx_get();
}
static void wireless_package_info_uci_sec_reset()
{
struct wireless_info *info = &g_wireless_info;
int i;
for (i = 0; i < MAX_WIFI_CHIP_NUM; i++) {
memset(&(info->wifi_info[i].ap_2G), 0, sizeof(info->wifi_info[i].ap_2G));
memset(&(info->wifi_info[i].ap_5G), 0, sizeof(info->wifi_info[i].ap_5G));
memset(&(info->wifi_info[i].sta), 0, sizeof(info->wifi_info[i].sta));
info->wifi_info[i].chip = NULL;
}
info->chip = NULL;
info->sec_bs = NULL;
}
static void free_wifi_uci_ctx(void)
{
free_applet_uci_ctx();
wireless_package_info_uci_sec_reset();
}
static int wireless_load_config_package(struct uci_context *local_ctx, const char *config_file, struct uci_package **package)
{
struct uci_element *e = NULL;
struct uci_package *p = NULL;
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, config_file) != 0)
continue;
p = uci_to_package(e);
break;
}
if (!p) {
uci_load(local_ctx, config_file, &p);
}
if (!p) {
return -1;
}
*package = p;
return 0;
}
/*===============================================================================
* API: IMSI_MATCH_COUNTRYCode
* Return : if found , Country(In English),Please do not free return pointer
* If not found, NULL.
*===============================================================================*/
static char * match_country_code_by_imsi(char *imsi)
{
unsigned int array_size = 0;
if (!imsi ||strlen(imsi) < 14 ) {
WIFI_ERR("Leave, IMSI ERROR");
return NULL;
}
WIFI_DBG("IMSI %s", imsi);
for (array_size = 0; array_size < ARRAY_SIZE(MrvlMccCountryTable); array_size++) {
if (!strncmp(imsi, MrvlMccCountryTable[array_size].mcc, 3)) {
WIFI_ERR("Leave, match Country %s", MrvlMccCountryTable[array_size].country);
return MrvlMccCountryTable[array_size].ccode;
}
}
return NULL;
}
/*get IMSI from tmp file*/
static int get_imsi_from_tmp_file(char *imsi_buf, int buf_size)
{
int fd = 0, size = 0;
fd = open(IMSI_FILE, O_RDONLY);
if (fd < 0) {
/*File not exist or no read access*/
return -1;
}
size = read(fd, imsi_buf, buf_size - 1);
if (size < 0) {
/*read fail*/
close(fd);
return -1;
}
close(fd);
return 0;
}
static const char *get_conuntry_code()
{
char imsi[32] = { '\0' };
if (get_imsi_from_tmp_file(imsi, 32) != 0) {
WIFI_ERR("get imsi from file fail");
return NULL;
}
char *ccode = match_country_code_by_imsi(imsi);
if (ccode == NULL) {
WIFI_ERR("no match country code with imsi %s", imsi);
return NULL;
}
return ccode;
}
/*WIFI channel range match from IMSI*/
static void get_wifi_channel_range(int *first, int *last)
{
int i = 0;
int limit;
int found = 0;
char imsi[32] = { '\0' };
static int sf = 0;
static int sl = 0;
if (sf != 0 && sl != 0) {
*first = sf;
*last = sl;
return;
}
if (get_imsi_from_tmp_file(imsi, 32) != 0) {
goto cfound;
}
char *ccode = match_country_code_by_imsi(imsi);
if (ccode == NULL) {
goto cfound;
}
WIFI_DBG("country code is %s", ccode);
/* Search specific domain name */
limit = sizeof(FCCDomain_Countries)/4;
for (i = 0; i < limit; i++) {
if (!strcmp(FCCDomain_Countries[i], ccode)) {
found = 1;
*first = FCCDomain_Subband[0];
*last = FCCDomain_Subband[0] + FCCDomain_Subband[1] -1;
goto cfound;
}
}
limit = sizeof(FCC1Domain_Countries)/4;
for (i = 0; i < limit; i++) {
if (!strcmp(FCC1Domain_Countries[i], ccode)) {
found = 1;
*first = FCC1Domain_Subband[0];
*last = FCC1Domain_Subband[0] + FCC1Domain_Subband[1] - 1;
goto cfound;
}
}
limit = sizeof(MKKDomain_Countries)/4;
for (i = 0; i < limit; i++) {
if (!strcmp(MKKDomain_Countries[i], ccode)) {
found = 1;
*first = MKKDomain_Subband[0];
*last = MKKDomain_Subband[0] + MKKDomain_Subband[1] - 1;
goto cfound;
}
}
limit = sizeof(ETSIDomain_Countries)/4;
for (i = 0; i < limit; i++) {
if (!strcmp(ETSIDomain_Countries[i], ccode)) {
found = 1;
*first = ETSIDomain_Subband[0];
*last = ETSIDomain_Subband[0] + ETSIDomain_Subband[1] - 1;
goto cfound;
}
}
cfound:
if (found == 0) {
*first = 1;
*last = 11;
}
sf = *first;
sl = *last;
WIFI_DBG("first channel is %d, last channel is %d", *first, *last);
return;
}
static char g_wireless_ifname[MAX_WIFI_CHIP_NUM][MAX_DEV_NAME_LEN];
static const char *get_wireless_ifname(int ap_index)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *option_value = NULL;
char ap_name[32] = { 0 };
if (ap_index >= MAX_WIFI_CHIP_NUM)
return NULL;
if (strlen(g_wireless_ifname[ap_index]))
return g_wireless_ifname[ap_index];
/*load /etc/config/wireless */
local_ctx = (struct uci_context *)uci_wifi_ctx_get();
if (!local_ctx) {
goto exit;
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0)
goto exit;
uci_foreach_element(&p->sections, e)
{
uci_sec = uci_to_section(e);
if (uci_sec)
{
if (strcmp(uci_sec->type, WIFI_SECTION_IFACE) == 0)
{
option_value = uci_lookup_option_string(local_ctx, uci_sec, "ifname");
if (option_value)
{
snprintf(ap_name, sizeof(ap_name), "AP%d", ap_index);
WIFI_DBG( "get wireless iface name %s, ap_name %s", option_value, ap_name);
if (strstr(uci_sec->e.name, ap_name))
{
strncpy(g_wireless_ifname[ap_index], option_value, MAX_DEV_NAME_LEN - 1);
return option_value;
}
}
}
}
}
exit:
WIFI_DBG( " no value found");
return NULL;
}
static char *get_hostapd_obj_name(int ap_index)
{
const char *ifname = get_wireless_ifname(ap_index);
if (ifname)
{
snprintf(hostapd_obj_name, 32, "%s.%s", HOSTAPD_SER_PREFIX, ifname);
}
else
snprintf(hostapd_obj_name, 32, "%s", HOSTAPD_SER);
return hostapd_obj_name;
}
static int wireless_lookup_hostapd_id(unsigned int *id, int ap_index)
{
char *hostapd_name = get_hostapd_obj_name(ap_index);
if (hostapd_name)
{
if (ubus_lookup_id(applet_ubus_ctx, hostapd_name, id) == 0) {
WIFI_ERR("Lookup object %s SUCCESS with id 0x%x", hostapd_name, id);
wifi_status[ap_index] = WIFI_READY;
return 0;
}
}
return -1;
}
#define ASRWIFI_VERSION_FILE "/sys/kernel/debug/ieee80211/asrphy0/asr/wifi_version"
#define ASRWIFI6_VERSION_FILE "/sys/kernel/debug/ieee80211/asrphy0/asr_80211ax/wifi_version"
#define ASRWIFI_TYPE "asr5803"
#define ASRWIFI6_TYPE "asr5861"
#define ASRWIFI6_SBAND_TYPE "asr5811"
static int read_chip_type_from_sys(void)
{
FILE *fp = NULL;
int nread = 0, type = 0;
char read_buf[64];
fp = fopen(ASRWIFI_VERSION_FILE, "r");
if (fp) {
memset(read_buf, 0, sizeof(read_buf));
nread = fread(read_buf, sizeof(char), sizeof(read_buf) - 1, fp);
WIFI_DBG("wifi_version %s", read_buf);
if (nread > 0 && strstr(read_buf, ASRWIFI_TYPE)) {
type = 1;
goto end;
}
}
else
{
fp = fopen(ASRWIFI6_VERSION_FILE, "r");
if (fp) {
memset(read_buf, 0, sizeof(read_buf));
nread = fread(read_buf, sizeof(char), sizeof(read_buf) - 1, fp);
WIFI_DBG("wifi6_version %s", read_buf);
if (nread > 0 && strstr(read_buf, ASRWIFI6_TYPE)) {
type = 2;
goto end;
}
else if (nread > 0 && strstr(read_buf, ASRWIFI6_SBAND_TYPE)) {
type = 3;
goto end;
}
}
}
end:
if (fp)
fclose(fp);
return type;
}
int chip_type_support_dual_ap()
{
if (read_chip_type_from_sys() == 2)
return true;
else
return false;
}
static int parse_wireless_package_info(struct uci_context *uci_ctx, struct uci_package *p, struct wireless_info *w_info)
{
struct uci_element *e = NULL;
struct wireless_info *info = w_info;
struct uci_section *uci_sec = NULL;
const char *option_value = NULL;
int i, n_2G_ssid = 0, n_5G_ssid = 0;
if(!uci_ctx || !p || !info) {
return -1;
}
memset(info, 0, sizeof(struct wireless_info));
if (wifi_status[WIFI_AP0] == NO_WIFI) {
WIFI_ERR("%s: NO WIFI card", __func__);
info->n_dev = 0;
return 0;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WIFI_SECTION_DEVICE) == 0) {
WIFI_DBG("find one wifi-device, section name is %s", uci_sec->e.name);
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "hwmode");
if (option_value) {
WIFI_DBG("hwmode value is %s", option_value);
if (strchr(option_value, 'a')) {
if (strstr(uci_sec->e.name, "AP0")) {
if (strstr(uci_sec->e.name, "5G")) {
info->wifi_info[WIFI_AP0].ap_5G.device = uci_sec;
info->wifi_5g_index = WIFI_AP0;
}
else {
info->wifi_info[WIFI_AP0].ap_2G.device = uci_sec;
info->wifi_24g_index= WIFI_AP0;
}
//info->n_dev = info->n_dev < 1 ? 1 : info->n_dev;
info->n_dev++;
} else if (strstr(uci_sec->e.name, "AP1")) {
if (strstr(uci_sec->e.name, "5G")) {
info->wifi_info[WIFI_AP1].ap_5G.device = uci_sec;
info->wifi_5g_index = WIFI_AP1;
}
else {
info->wifi_info[WIFI_AP1].ap_2G.device = uci_sec;
info->wifi_24g_index= WIFI_AP1;
}
//info->n_dev = info->n_dev < 2 ? 2 : info->n_dev;
info->n_dev++;
}
} else {
if (strstr(uci_sec->e.name, "AP0")) {
info->wifi_info[WIFI_AP0].ap_2G.device = uci_sec;
info->wifi_24g_index= WIFI_AP0;
//info->n_dev = info->n_dev < 1 ? 1 : info->n_dev;
info->n_dev++;
} else if(strstr(uci_sec->e.name, "AP1")) {
info->wifi_info[WIFI_AP1].ap_2G.device = uci_sec;
info->wifi_24g_index= WIFI_AP1;
//info->n_dev = info->n_dev < 2 ? 2 : info->n_dev;
info->n_dev++;
}
}
} else {
if (strstr(uci_sec->e.name, "STA0")) {
info->wifi_info[WIFI_AP0].sta.device = uci_sec;
} else if (strstr(uci_sec->e.name, "STA1")) {
info->wifi_info[WIFI_AP1].sta.device = uci_sec;
}
}
} else if (strcmp(uci_sec->type, WIFI_SECTION_IFACE) == 0) {
WIFI_DBG("find one wifi-iface, section name is %s", uci_sec->e.name);
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "device");
if (option_value) {
WIFI_DBG("device value is %s", option_value);
for ( i = 0; i < MAX_WIFI_CHIP_NUM; i++) {
if (info->wifi_info[i].ap_2G.device) {
if (strcmp(option_value, info->wifi_info[i].ap_2G.device->e.name) == 0) {
WIFI_DBG("find wifi-iface(24G)");
n_2G_ssid = info->wifi_info[i].ap_2G.n_ssid;
info->wifi_info[i].ap_2G.iface[n_2G_ssid]= uci_sec;
info->wifi_info[i].ap_2G.n_ssid++;
break;
}
}
if (info->wifi_info[i].ap_5G.device) {
if (strcmp(option_value, info->wifi_info[i].ap_5G.device->e.name) == 0) {
WIFI_DBG("find wifi-iface(5G)");
n_5G_ssid = info->wifi_info[i].ap_5G.n_ssid;
info->wifi_info[i].ap_5G.iface[n_5G_ssid] = uci_sec;
info->wifi_info[i].ap_5G.n_ssid++;
break;
}
}
}
}
}else if (strcmp(uci_sec->type, WIFI_SECTION_SETTING) == 0) {
WIFI_DBG("find wifi-settings, section name is %s", uci_sec->e.name);
if (uci_sec->e.name && !strcmp(uci_sec->e.name, "AP0")) {
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "auto_off_enable");
if (option_value) {
info->wifi_info[WIFI_AP0].auto_off_enable= atoi(option_value);
}
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "auto_off_timeout");
if (option_value) {
info->wifi_info[WIFI_AP0].auto_off_timeout = atoi(option_value);
} else {
info->wifi_info[WIFI_AP0].auto_off_timeout = MIN_AUTO_OFF_TIMEOUT;
}
} else if (uci_sec->e.name && !strcmp(uci_sec->e.name, "AP1")) {
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "auto_off_enable");
if (option_value) {
info->wifi_info[WIFI_AP1].auto_off_enable= atoi(option_value);
}
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "auto_off_timeout");
if (option_value) {
info->wifi_info[WIFI_AP1].auto_off_timeout = atoi(option_value);
} else {
info->wifi_info[WIFI_AP0].auto_off_timeout = MIN_AUTO_OFF_TIMEOUT;
}
}
} else if (strcmp(uci_sec->type, WIFI_SECTION_CHIP) == 0) {
WIFI_DBG("find one wifi-device, section name is %s", uci_sec->e.name);
info->chip = uci_sec;
} else if (strcmp(uci_sec->type, WIFI_SECTION_BS) == 0) {
info->sec_bs = uci_sec;
option_value = uci_lookup_option_string(uci_ctx, uci_sec, "bs_enable");
if (option_value) {
info->band_steering_enable = atoi(option_value);
} else {
info->band_steering_enable = 0;
}
}
}
info->chip_type = read_chip_type_from_sys();
if (info->chip_type == 2 || info->chip_type == 3)
info->wifi6 = 1;
if (info->chip_type == 2)
info->band_steering_support = 1;
return 0;
}
static int my_system(const char *cmd)
{
FILE *fp;
int res;
char buf[1024];
if (cmd == NULL) {
return -1;
}
if ((fp = popen(cmd, "r")) == NULL) {
WIFI_ERR("popen error: %s/n", strerror(errno));
return -1;
} else {
while (fgets(buf, sizeof(buf), fp)) {
WIFI_DBG("%s", buf);
}
if ((res = pclose(fp)) == -1) {
return res;
} else if (res == 0) {
return res;
} else {
WIFI_DBG("popen res is :%d\n", res);
return res;
}
}
}
enum {
RETURN_CODE,
__RETURN_MAX,
};
static const struct blobmsg_policy return_policy[__RETURN_MAX] = {
[RETURN_CODE] = { .name = "rc", .type = BLOBMSG_TYPE_INT32 },
};
static void alarm_task_cb(struct ubus_request *req,int type,
struct blob_attr *msg)
{
struct blob_attr *tb[__RETURN_MAX];
int rc;
(void)(req);
(void)(type);
blobmsg_parse(return_policy, __RETURN_MAX, tb,
blob_data(msg), blob_len(msg));
if (!tb[RETURN_CODE]) {
fprintf(stderr, "No return code received from server\n");
return;
}
rc = blobmsg_get_u32(tb[RETURN_CODE]);
*(uint32_t *)req->priv = rc;
return;
}
static int shutdown_wifi_auto_off(void)
{
unsigned int id;
int ret, rc;
ret = ubus_lookup_id(wifi_ubus_ctx, CHARGER_UBUS_ID, &id);
if (ret != UBUS_STATUS_OK)
return ret;
blob_buf_init(&wifi_buf, 0);
blobmsg_add_string(&wifi_buf,"alarm_name", "wifi_alarm");
ret = ubus_invoke(wifi_ubus_ctx, id, "alarm_cancel", wifi_buf.head,
alarm_task_cb, &rc,0);
if (ret) {
WIFI_ERR("%s failed\n", __FUNCTION__);
return ret;
}
APRINTK("wireless: turn off wifi auto_off\n");
WIFI_DBG("wireless: turn off wifi auto_off\n");
return rc;
}
static int set_wifi_auto_off_on(void)
{
struct wireless_info *info = &g_wireless_info;
unsigned int id;
int ret, rc;
ret = ubus_lookup_id(wifi_ubus_ctx, CHARGER_UBUS_ID, &id);
if (ret != UBUS_STATUS_OK)
return ret;
blob_buf_init(&wifi_buf, 0);
blobmsg_add_u32(&wifi_buf, "time",
info->wifi_info[WIFI_AP0].auto_off_timeout);
blobmsg_add_string(&wifi_buf,"alarm_name", "wifi_alarm");
ret = ubus_invoke(wifi_ubus_ctx, id, "alarm_set", wifi_buf.head,
alarm_task_cb, &rc,0);
if (ret) {
WIFI_ERR("%s failed\n", __FUNCTION__);
return ret;
}
if (rc)
WIFI_ERR("%s failed rc=%d\n", __FUNCTION__, rc);
APRINTK("wireless: enable wifi auto_off, timeout=%dsec ----->\n",
info->wifi_info[WIFI_AP0].auto_off_timeout);
WIFI_DBG("wireless: enable wifi auto_off, timeout=%dsec ----->\n",
info->wifi_info[WIFI_AP0].auto_off_timeout);
return rc;
}
static int init_wifi_settings(void)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct wireless_info *info = &g_wireless_info;
/*load /etc/config/wireless */
local_ctx = (struct uci_context *)uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0)
goto EXIT;
info->wifi_5g_index = -1;
info->wifi_24g_index = -1;
parse_wireless_package_info(local_ctx, p, info);
if (info->wifi_info[WIFI_AP0].auto_off_enable == 1 &&
active_clients[WIFI_AP0] == 0 &&
wifi_status[WIFI_AP0] == WIFI_READY)
set_wifi_auto_off_on();
EXIT:
return 0;
}
/*listen events from charger,start*/
static int charger_status = 0;
enum {
ACCH_ONLINE_ID,
USBCHG_ONLINE_ID,
ALARM_NAME,
ONKEY_TYPE,
};
static const struct blobmsg_policy charger_pol[] = {
[ACCH_ONLINE_ID] = {
.name = "acchg_online",
.type = BLOBMSG_TYPE_INT32,
},
[USBCHG_ONLINE_ID] = {
.name = "usbchg_online",
.type = BLOBMSG_TYPE_INT32,
},
[ALARM_NAME] = {
.name = "alarm_name",
.type = BLOBMSG_TYPE_STRING,
},
[ONKEY_TYPE] = {
.name = "type",
.type = BLOBMSG_TYPE_INT32,
},
};
static void get_charger_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct blob_attr *charger_data[ARRAY_SIZE(charger_pol)];
int acch_online = 0;
int usbchg_online = 0;
UNUSESET(type);
UNUSESET(req);
if (blobmsg_parse(charger_pol, ARRAY_SIZE(charger_pol), charger_data, blob_data(msg), blob_len(msg)) != 0) {
return;
}
if (!charger_data[ACCH_ONLINE_ID] || !charger_data[USBCHG_ONLINE_ID]) {
return;
}
if (charger_data[ACCH_ONLINE_ID])
acch_online = blobmsg_get_u32(charger_data[ACCH_ONLINE_ID]);
if (charger_data[USBCHG_ONLINE_ID])
usbchg_online = blobmsg_get_u32(charger_data[USBCHG_ONLINE_ID]);
if (acch_online || usbchg_online) {
charger_status = 1;
shutdown_wifi_auto_off();
}
return;
}
static void charger_complete_cb(struct ubus_request *req, int ret)
{
UNUSESET(ret);
free(req);
return;
}
static int invoke_to_get_charger_data(struct ubus_context *ctx)
{
uint32_t id;
struct ubus_request *req = NULL;
int ret;
/* Look up the target object id by the object path */
ret = ubus_lookup_id(ctx, CHARGER_UBUS_ID, &id);
if (ret)
return ret;
req = malloc(sizeof(*req));
if (!req) {
WIFI_ERR("malloc fail");
ret = -1;
return ret;
}
memset(req, 0, sizeof(*req));
ret = ubus_invoke_async(ctx, id, CHARGER_UBUS_REQUEST, NULL, req);
if (ret) {
WIFI_ERR("ubus_invoke_async error %d", ret);
return ret;
}
/*these cb initializations are after ubus_invoke_async() because ubus_invoke_async() zeros req */
req->data_cb = get_charger_data_cb;
req->complete_cb = charger_complete_cb;
ubus_complete_request_async(ctx, req);
return 0;
}
static int
charger_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *charger_data[ARRAY_SIZE(charger_pol)];
struct wireless_info *info = &g_wireless_info;
int acch_online = 0;
int usbchg_online = 0;
UNUSESET(obj);
UNUSESET(ctx);
UNUSESET(req);
UNUSESET(method);
if (blobmsg_parse(charger_pol, ARRAY_SIZE(charger_pol), charger_data,
blob_data(msg), blob_len(msg)) != 0) {
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (!strcmp(method, "alarm_triggered") && charger_data[ALARM_NAME]) {
if (!strcmp(blobmsg_get_string(charger_data[ALARM_NAME]),
"wifi_alarm")) {
my_system("echo wifi.lock 1000000000 > /sys/power/wake_lock");
my_system("/sbin/wifi down");
}
return 0;
}
if (!strcmp(method, "onkey_pressed") && charger_data[ONKEY_TYPE]) {
if (blobmsg_get_u32(charger_data[ONKEY_TYPE]) == 0 &&
wifi_status[WIFI_AP0] == WIFI_OFF) {
wifi_status[WIFI_AP0] = WIFI_START;
my_system("echo wifi.lock 20000000000 > /sys/power/wake_lock");
my_system("/sbin/wifi up");
}
return 0;
}
if (!charger_data[ACCH_ONLINE_ID] || !charger_data[USBCHG_ONLINE_ID]) {
return UBUS_STATUS_NO_DATA;
}
if (charger_data[ACCH_ONLINE_ID]) {
acch_online = blobmsg_get_u32(charger_data[ACCH_ONLINE_ID]);
}
if (charger_data[USBCHG_ONLINE_ID]) {
usbchg_online = blobmsg_get_u32(charger_data[USBCHG_ONLINE_ID]);
}
if (acch_online || usbchg_online) {
charger_status = 1;
if (info->wifi_info[WIFI_AP0].auto_off_enable == 1) {
shutdown_wifi_auto_off();
}
} else {
/*charger status from on to off */
if (charger_status == 1) {
if (info->wifi_info[WIFI_AP0].auto_off_enable == 1 &&
active_clients[WIFI_AP0] == 0 &&
wifi_status[WIFI_AP0] == WIFI_READY) {
set_wifi_auto_off_on();
}
}
charger_status = 0;
}
return 0;
}
/* statistics get_active_clients_num*/
enum {
ATTR_CLIENTS_INFO,
ATTR_ACTIVE_CLIENTS_NUM,
ATTR_USB_STATE,
ATTR_WLAN_CLIENTS,
ATTR_WLAN1_CLIENTS
};
static const struct blobmsg_policy active_clients_num_attr_policy[] = {
[ATTR_CLIENTS_INFO] = {.name = "clients_info", .type = BLOBMSG_TYPE_TABLE},
[ATTR_ACTIVE_CLIENTS_NUM] = {.name = "active_clients_num", .type = BLOBMSG_TYPE_STRING},
[ATTR_USB_STATE] = {.name = "usb_state", .type = BLOBMSG_TYPE_STRING},
[ATTR_WLAN_CLIENTS] = {.name = "wlan_clients", .type = BLOBMSG_TYPE_STRING},
[ATTR_WLAN1_CLIENTS] = {.name = "wlan1_clients", .type = BLOBMSG_TYPE_STRING},
};
static void get_client_number_cb(struct ubus_request *req, int type,
struct blob_attr *msg)
{
struct blob_attr *tb[ARRAY_SIZE(active_clients_num_attr_policy)];
struct wireless_info *info = &g_wireless_info;
int clients_num = 0, usb_state = 0;
int ret;
int wlan_clients = 0, wlan1_clients = 0;
UNUSESET(type);
UNUSESET(req);
ret = blobmsg_parse(active_clients_num_attr_policy,
ARRAY_SIZE(active_clients_num_attr_policy),
tb, blob_data(msg), blob_len(msg));
if (ret){
WIFI_ERR("parsing clients_num blobmsg failed %d\n", ret);
return;
}
if (!tb[ATTR_CLIENTS_INFO])
return;
ret = blobmsg_parse(active_clients_num_attr_policy,
ARRAY_SIZE(active_clients_num_attr_policy), tb,
blobmsg_data(tb[ATTR_CLIENTS_INFO]),
blobmsg_data_len(tb[ATTR_CLIENTS_INFO]));
if (ret){
WIFI_ERR("parsing clients_num blobmsg failed %d\n", ret);
return;
}
if (!tb[ATTR_ACTIVE_CLIENTS_NUM] || !tb[ATTR_USB_STATE] || !tb[ATTR_WLAN_CLIENTS] || !tb[ATTR_WLAN1_CLIENTS]) {
WIFI_ERR("parsing clients_num blobmsg failed %d\n", ret);
return;
}
clients_num = atoi(blobmsg_get_string(tb[ATTR_ACTIVE_CLIENTS_NUM]));
usb_state = atoi(blobmsg_get_string(tb[ATTR_USB_STATE]));
wlan_clients = atoi(blobmsg_get_string(tb[ATTR_WLAN_CLIENTS]));
wlan1_clients = atoi(blobmsg_get_string(tb[ATTR_WLAN1_CLIENTS]));
WIFI_ERR("all_clients_num %d, usb_state %d, wlan_clients %d, wlan1_clients %d\n", clients_num, usb_state);
if (clients_num > 0 && usb_state == 1)
clients_num --;
if (info->wifi_info[WIFI_AP0].auto_off_enable) {
if ((active_clients[WIFI_AP0] > 0) &&
(wlan_clients == 0)) {
set_wifi_auto_off_on();
}
else if ((active_clients[WIFI_AP0] == 0) &&
(wlan_clients > 0)) {
shutdown_wifi_auto_off();
}
}
active_clients[WIFI_AP0] = wlan_clients;
if (info->wifi_info[WIFI_AP1].auto_off_enable) {
if ((active_clients[WIFI_AP1] > 0) &&
(wlan1_clients == 0)) {
set_wifi_auto_off_on();
}
else if ((active_clients[WIFI_AP1] == 0) &&
(wlan1_clients > 0)) {
shutdown_wifi_auto_off();
}
}
active_clients[WIFI_AP1] = wlan1_clients;
return;
}
//static void get_client_number_complete_cb(struct ubus_request *req, int ret)
//{
// UNUSESET(ret);
// free(req);
// return;
//}
#if 1
static int invoke_to_get_client_number(struct ubus_context *ctx)
{
uint32_t id;
//struct ubus_request *req = NULL;
int ret;
/* Look up the target object id by the object path */
ret = ubus_lookup_id(ctx, "statistics", &id);
if (ret)
return ret;
//req = malloc(sizeof(*req));
//if (!req) {
// WIFI_ERR("malloc fail");
// ret = -1;
// return ret;
//}
//memset(req, 0, sizeof(*req));
ret = ubus_invoke(ctx, id, "get_active_clients_num", NULL,
get_client_number_cb, NULL, 0);
if (ret) {
WIFI_ERR("ubus_invoke error %d", ret);
return ret;
}
//ret = ubus_invoke_async(ctx, id, "get_active_clients_num", NULL, req);
//if (ret) {
// WIFI_ERR("ubus_invoke_async error %d", ret);
// return ret;
//}
//req->data_cb = get_client_number_cb;
//req->complete_cb = get_client_number_complete_cb;
//req->priv = ctx;
//ubus_complete_request(ctx, req, 0);
return 0;
}
/*listen events from charger*/
static int listen_to_charger_ser(struct ubus_context *ctx)
{
unsigned int id;
int ret;
if (ubus_lookup_id(ctx, CHARGER_UBUS_ID, &id)) {
return -1;
}
charger_event.cb = charger_event_cb;
ret = ubus_subscribe(ctx, &charger_event, id);
WIFI_DBG("watching object %08x: %s", id, ubus_strerror(ret));
return ret;
}
#endif
void wps_status_clear_cb(struct uloop_timeout *timeout)
{
int i;
for (i = 0; i < MAX_WIFI_CHIP_NUM; i++ )
memset(&g_wps_info[i], 0, sizeof(struct wps_conn_info));
uloop_timeout_cancel(timeout);
return;
}
static int
hostapd_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *hostapd_wps_event_attr[ARRAY_SIZE(wps_event_pol)];
char mac_str[20] = { 0 };
char cmd[32] = { 0 };
UNUSESET(obj);
UNUSESET(ctx);
UNUSESET(req);
if (blobmsg_parse(wps_event_pol, ARRAY_SIZE(wps_event_pol), hostapd_wps_event_attr, blob_data(msg), blob_len(msg)) != 0) {
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (!hostapd_wps_event_attr[0] ) {
return UBUS_STATUS_NO_DATA;
}
strncpy(mac_str, blobmsg_get_string(hostapd_wps_event_attr[0]), 18);
WIFI_DBG("WPS client mac %s, event %s", mac_str, method);
if (!strcmp(method, HOSTAPD_EV_WPS_START)) {
g_wps_info[WIFI_AP0].wps_status = WPS_STATUS_START;
if (g_wps_conn_ctx.ap_5g_index == WIFI_AP0) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_PREFER)
g_wps_conn_ctx.state = WPS_STATE_5G_START;
}
uloop_timeout_cancel(&wps_status_clear_timeout);
uloop_timeout_set(&wps_status_clear_timeout, WPS_STATUS_CLEAR_TIMEOUT);
} else if (!strcmp(method, HOSTAPD_EV_WPS_SUCCESS)) {
if (g_wps_conn_ctx.ap_5g_index == WIFI_AP0) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_START)
g_wps_conn_ctx.state = WPS_STATE_5G_SUCCESS;
}
g_wps_info[WIFI_AP0].wps_status = WPS_STATUS_SUCCESS;
} else if (!strcmp(method, HOSTAPD_EV_WPS_FAIL)) {
if (g_wps_conn_ctx.ap_5g_index== WIFI_AP0) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_START) {
g_wps_conn_ctx.state = WPS_STATE_5G_FAIL;
g_wps_info[WIFI_AP0].wps_status = WPS_STATUS_START;
WIFI_DBG("try auto connect to band 24G with method %d for AP %d", g_wps_conn_ctx.method, g_wps_conn_ctx.ap_24g_index);
if (g_wps_conn_ctx.method == 0)
snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s wps_pbc", get_wireless_ifname(g_wps_conn_ctx.ap_24g_index));
else if (g_wps_conn_ctx.method == 1)
snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s wps_pin any %s", get_wireless_ifname(g_wps_conn_ctx.ap_24g_index), g_wps_conn_ctx.pin);
if (strlen(cmd) > 0) {
if (my_system(cmd) == 0) {
g_wps_conn_ctx.state = WPS_STATE_24G_START;
}
else {
g_wps_conn_ctx.state = WPS_STATE_24G_FAIL;
g_wps_info[WIFI_AP0].wps_status = WPS_STATUS_FAIL;
g_wps_conn_ctx.ap_index = g_wps_conn_ctx.ap_24g_index;
}
}
}
}
else
g_wps_info[WIFI_AP0].wps_status = WPS_STATUS_FAIL;
}
strcpy(g_wps_info[WIFI_AP0].peer_mac, mac_str);
return 0;
}
static int
hostapd_wlan1_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *hostapd_wps_event_attr[ARRAY_SIZE(wps_event_pol)];
char mac_str[20] = { 0 };
char cmd[32];
UNUSESET(obj);
UNUSESET(ctx);
UNUSESET(req);
if (blobmsg_parse(wps_event_pol, ARRAY_SIZE(wps_event_pol), hostapd_wps_event_attr, blob_data(msg), blob_len(msg)) != 0) {
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (!hostapd_wps_event_attr[0] ) {
return UBUS_STATUS_NO_DATA;
}
strncpy(mac_str, blobmsg_get_string(hostapd_wps_event_attr[0]), 18);
WIFI_DBG("WPS client mac %s, event %s", mac_str, method);
if (!strcmp(method, HOSTAPD_EV_WPS_START)) {
g_wps_info[WIFI_AP1].wps_status = WPS_STATUS_START;
if (g_wps_conn_ctx.ap_5g_index == WIFI_AP1) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_PREFER)
g_wps_conn_ctx.state = WPS_STATE_5G_START;
}
uloop_timeout_cancel(&wps_status_clear_timeout);
uloop_timeout_set(&wps_status_clear_timeout, WPS_STATUS_CLEAR_TIMEOUT);
} else if (!strcmp(method, HOSTAPD_EV_WPS_SUCCESS)) {
if (g_wps_conn_ctx.ap_5g_index == WIFI_AP1) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_START)
g_wps_conn_ctx.state = WPS_STATE_5G_SUCCESS;
}
g_wps_info[WIFI_AP1].wps_status = WPS_STATUS_SUCCESS;
} else if (!strcmp(method, HOSTAPD_EV_WPS_FAIL)) {
if (g_wps_conn_ctx.ap_5g_index== WIFI_AP1) {
if (g_wps_conn_ctx.state == WPS_STATE_5G_START) {
g_wps_conn_ctx.state = WPS_STATE_5G_FAIL;
g_wps_info[WIFI_AP1].wps_status = WPS_STATUS_START;
WIFI_DBG("try auto connect to band 24G with method %d for AP %d", g_wps_conn_ctx.method, g_wps_conn_ctx.ap_24g_index);
if (g_wps_conn_ctx.method == 0)
snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s wps_pbc", get_wireless_ifname(g_wps_conn_ctx.ap_24g_index));
else if (g_wps_conn_ctx.method == 1)
snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s wps_pin any %s", get_wireless_ifname(g_wps_conn_ctx.ap_24g_index), g_wps_conn_ctx.pin);
if (strlen(cmd) > 0) {
if (my_system(cmd) == 0) {
g_wps_conn_ctx.state = WPS_STATE_24G_START;
}
else {
g_wps_conn_ctx.state = WPS_STATE_24G_FAIL;
g_wps_info[WIFI_AP1].wps_status = WPS_STATUS_FAIL;
g_wps_conn_ctx.ap_index = g_wps_conn_ctx.ap_24g_index;
}
}
}
}
else
g_wps_info[WIFI_AP1].wps_status = WPS_STATUS_FAIL;
}
strcpy(g_wps_info[WIFI_AP1].peer_mac, mac_str);
return 0;
}
/*listen events from hostapd*/
static int wireless_listen_to_hostapd(struct ubus_context *ctx, int ap_index)
{
unsigned int id;
int ret;
char *hostapd_name = get_hostapd_obj_name(ap_index);
if (!hostapd_name) {
return -1;
}
if (ubus_lookup_id(ctx, hostapd_name, &id)) {
return -1;
}
if (ap_index == WIFI_AP0) {
hostapd_event_subscriber.cb = hostapd_event_cb;
ret = ubus_subscribe(ctx, &hostapd_event_subscriber, id);
}
else if (ap_index == WIFI_AP1) {
hostapd_wlan1_event_subscriber.cb = hostapd_wlan1_event_cb;
ret = ubus_subscribe(ctx, &hostapd_wlan1_event_subscriber, id);
}
WIFI_DBG( "watching object 0x%lx: %s", id, ubus_strerror(ret));
return ret;
}
/*================================================
method: get_wifi_basic_info
return :
<wireless>
<wireless_num/>
<AP0>
<wifi_if_24G>
<switch/> on/off
<ssid/>
<channel/>
</wifi_if_24G>
<wifi_if_5G>
<switch/> on/off
<ssid/>
<channel/>
</wifi_if_5G>
</AP0>
</wireless>
================================================*/
static int wifi_get_basic_info_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
void *tb_24G = NULL, *tb_wireless = NULL, *tb_5G = NULL, *tb_device = NULL, *tb_ssid = NULL;
char dev_name[10] = { 0 }, iface_name[10] = { 0 }, s_channel_first[4] = { 0 }, s_channel_last[4] = { 0 };
int i, j, n_2G_ssid = 0, n_5G_ssid = 0, channel_first = 0, channel_last = 0;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
blobmsg_buf_init(&wifi_buf);
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0)
goto EXIT;
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
for ( i = 0; i < info->n_dev; i++) {
if (info->wifi_info[i].ap_2G.device ||info->wifi_info[i].ap_5G.device) {
snprintf(dev_name, sizeof(dev_name) - 1, "AP%d", i);
}
else {
continue;
}
WIFI_DBG("device name %s", dev_name);
tb_device = blobmsg_open_table(&wifi_buf, dev_name);
dev_sec_24G = info->wifi_info[i].ap_2G.device;
dev_sec_5G = info->wifi_info[i].ap_5G.device;
if (dev_sec_24G) {
tb_24G = blobmsg_open_table(&wifi_buf, "wifi_if_24G");
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "disabled");
if (option_value) {
WIFI_DBG("disabled is %s", option_value);
if (strcmp(option_value, "1") == 0) {
blobmsg_add_string(&wifi_buf, "switch", "off");
} else {
WIFI_DBG("wifi_status[%d] %d", i, wifi_status[i]);
if (wifi_status[i] == WIFI_OFF)
blobmsg_add_string(&wifi_buf, "switch", "off");
else
blobmsg_add_string(&wifi_buf, "switch", "on");
}
}
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "channel");
if (option_value) {
WIFI_DBG("channel is %s", option_value);
blobmsg_add_string(&wifi_buf, "channel", option_value);
}
get_wifi_channel_range(&channel_first, &channel_last);
memset(s_channel_first, 0, 4);
memset(s_channel_last, 0, 4);
snprintf(s_channel_first, 4, "%d", channel_first);
snprintf(s_channel_last, 4, "%d", channel_last);
blobmsg_add_string(&wifi_buf, "first_channel", s_channel_first);
blobmsg_add_string(&wifi_buf, "last_channel", s_channel_last);
n_2G_ssid = info->wifi_info[i].ap_2G.n_ssid;
for ( j = 0; j < n_2G_ssid; j++) {
iface_sec_24G = info->wifi_info[i].ap_2G.iface[j];
snprintf(iface_name, sizeof(iface_name) - 1, "ssid%d", j);
tb_ssid = blobmsg_open_table(&wifi_buf, iface_name);
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "ssid");
if (option_value) {
WIFI_DBG("SSID is %s", option_value);
blobmsg_add_string(&wifi_buf, "ssid", option_value);
}
blobmsg_close_table(&wifi_buf, tb_ssid);
}
blobmsg_close_table(&wifi_buf, tb_24G);
}
if (dev_sec_5G) {
tb_5G = blobmsg_open_table(&wifi_buf, "wifi_if_24G");
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "disabled");
if (option_value) {
WIFI_DBG("disabled is %s", option_value);
if (strcmp(option_value, "1") == 0) {
blobmsg_add_string(&wifi_buf, "switch", "off");
} else {
if (wifi_status[i] == WIFI_OFF)
blobmsg_add_string(&wifi_buf, "switch", "off");
else
blobmsg_add_string(&wifi_buf, "switch", "on");
}
}
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "channel");
if (option_value) {
WIFI_DBG("channel is %s", option_value);
blobmsg_add_string(&wifi_buf, "channel", option_value);
}
get_wifi_channel_range(&channel_first, &channel_last);
memset(s_channel_first, 0, 4);
memset(s_channel_last, 0, 4);
snprintf(s_channel_first, 4, "%d", channel_first);
snprintf(s_channel_last, 4, "%d", channel_last);
blobmsg_add_string(&wifi_buf, "first_channel", s_channel_first);
blobmsg_add_string(&wifi_buf, "last_channel", s_channel_last);
n_5G_ssid = info->wifi_info[i].ap_5G.n_ssid;
for ( j = 0; j < n_5G_ssid; j++) {
iface_sec_5G = info->wifi_info[i].ap_5G.iface[j];
snprintf(iface_name, sizeof(iface_name) - 1, "ssid%d", j);
tb_ssid = blobmsg_open_table(&wifi_buf, iface_name);
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "ssid");
if (option_value) {
WIFI_DBG("SSID is %s", option_value);
blobmsg_add_string(&wifi_buf, "ssid", option_value);
}
blobmsg_close_table(&wifi_buf, tb_ssid);
}
blobmsg_close_table(&wifi_buf, tb_5G);
}
blobmsg_close_table(&wifi_buf, tb_device);
}
EXIT:
if (tb_wireless) {
blobmsg_close_table(&wifi_buf, tb_wireless);
}
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done");
return 0;
};
static void set_current_ap_index(int index)
{
g_current_ap = index;
WIFI_DBG("%s: index %d", __func__, index);
}
static int get_current_ap_index()
{
return g_current_ap;
}
/*================================================
method: get_wifi_detail
<wireless>
<wireless_num/>
<wireless_type/>
<AP0>
<wifi_if_24G>
<switch/>
<net_mode/>
<channel/>
<first_channel/>
<last_channel/>
<bandwidth/>
<hidden/>
<isolate/>
<ssid/>
<encryption>
<key>
<key1>
<key2>
<key3>
<key4>
<wpa_group_rekey/>
</wifi_if_24G>
<wifi_if_5G>
...
</wifi_if_5G>
</AP0>
</wireless>
================================================*/
static int wifi_get_detail_info_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL, *opt_val = NULL;
void *tb_24G = NULL, *tb_wireless = NULL, *tb_5G = NULL, *tb_device = NULL, *tb_ssid = NULL;
char dev_name[10] = { 0 }, iface_name[10] = { 0 }, s_channel_first[4] = { 0 }, s_channel_last[4] = { 0 };;
int i, j, n_2G_ssid = 0, n_5G_ssid = 0, channel_first = 0, channel_last = 0;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
blobmsg_buf_init(&wifi_buf);
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
parse_wireless_package_info(local_ctx, p, info);
}else {
goto EXIT;
}
}
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
blobmsg_add_u32(&wifi_buf, "wireless_num", (unsigned int)info->n_dev);
blobmsg_add_u32(&wifi_buf, "wireless_type", (unsigned int)info->chip_type);
blobmsg_add_u32(&wifi_buf, "wifi6_support", (unsigned int)info->wifi6);
blobmsg_add_u32(&wifi_buf, "current_ap", (unsigned int)g_current_ap);
blobmsg_add_u32(&wifi_buf, "bs_support", (unsigned int)info->band_steering_support);
blobmsg_add_u32(&wifi_buf, "bs_enable", (unsigned int)info->band_steering_enable);
WIFI_DBG("wireless number %d, wireless type %d, wifi6_support %d, currrent_ap %d, bs_support %d, bs_enable %d",
info->n_dev, info->chip_type, info->wifi6, g_current_ap, info->band_steering_support, info->band_steering_enable);
/*get detail info -- 2.4G begin */
/*form response blobmsg */
for ( i = 0; i < info->n_dev; i++) {
if (info->wifi_info[i].sta.device) {
sprintf(dev_name, "STA%d", i);
/*STA switch */
WIFI_DBG("device name %s", dev_name);
tb_device = blobmsg_open_table(&wifi_buf, dev_name);
option_value = uci_lookup_option_string(local_ctx, info->wifi_info[i].sta.device, "disabled");
if (option_value) {
WIFI_DBG("%s disabled is %s", dev_name, option_value);
if (strcmp(option_value, "1") == 0) {
blobmsg_add_string(&wifi_buf, "switch", "off");
} else {
blobmsg_add_string(&wifi_buf, "switch", "on");
}
}
blobmsg_close_table(&wifi_buf, tb_device);
}
if (info->wifi_info[i].ap_2G.device ||info->wifi_info[i].ap_5G.device) {
sprintf(dev_name, "AP%d", i);
}
else {
continue;
}
WIFI_DBG("device name %s", dev_name);
tb_device = blobmsg_open_table(&wifi_buf, dev_name);
if (info->wifi_info[i].ap_2G.device && info->wifi_info[i].ap_2G.iface[0]) {
tb_24G = blobmsg_open_table(&wifi_buf, "wifi_if_24G");
dev_sec_24G = info->wifi_info[i].ap_2G.device;
/*switch */
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "disabled");
if (option_value) {
WIFI_DBG("disabled is %s", option_value);
if (strcmp(option_value, "1") == 0) {
blobmsg_add_string(&wifi_buf, "switch", "off");
} else {
WIFI_DBG("wifi_status[%d] %d", i, wifi_status[i]);
if (wifi_status[i] == WIFI_OFF)
blobmsg_add_string(&wifi_buf, "switch", "off");
else
blobmsg_add_string(&wifi_buf, "switch", "on");
}
}
/*net_mode 11g/11n/11a/11b */
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "hwmode");
if (option_value) {
WIFI_DBG("net_mode hwmode is %s", option_value);
blobmsg_add_string(&wifi_buf, "net_mode", option_value);
}
/*bandwidth */
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "htmode");
if (option_value) {
WIFI_DBG("bandwidth is %s", option_value);
blobmsg_add_string(&wifi_buf, "bandwidth", option_value);
}
/*channel */
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "channel");
if (option_value) {
WIFI_DBG("channel is %s", option_value);
blobmsg_add_string(&wifi_buf, "channel", option_value);
}
/*channel range*/
get_wifi_channel_range(&channel_first, &channel_last);
memset(s_channel_first, 0, 4);
memset(s_channel_last, 0, 4);
snprintf(s_channel_first, 4, "%d", channel_first);
snprintf(s_channel_last, 4, "%d", channel_last);
blobmsg_add_string(&wifi_buf, "first_channel", s_channel_first);
blobmsg_add_string(&wifi_buf, "last_channel", s_channel_last);
n_2G_ssid = info->wifi_info[i].ap_2G.n_ssid;
WIFI_DBG("n_2G_ssid number %d", n_2G_ssid);
blobmsg_add_u32(&wifi_buf, "n_ssid", n_2G_ssid);
/*multi SSID*/
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "unsupport_multi_ssid");
if (option_value) {
WIFI_DBG("unsupport multi ssid %s", option_value);
blobmsg_add_string(&wifi_buf, "unsupport_multi_ssid", option_value);
}
for ( j = 0; j < n_2G_ssid; j++ ) {
iface_sec_24G = info->wifi_info[i].ap_2G.iface[j];
sprintf(iface_name, "ssid%d", j);
tb_ssid = blobmsg_open_table(&wifi_buf, iface_name);
/*SSID*/
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "ssid");
if (option_value) {
WIFI_DBG("SSID is %s", option_value);
blobmsg_add_string(&wifi_buf, "ssid", option_value);
}
/*hidden */
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "hidden");
if (option_value) {
WIFI_DBG("hidden is %s", option_value);
blobmsg_add_string(&wifi_buf, "hidden", option_value);
}
/*isolate */
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "isolate");
if (option_value) {
WIFI_DBG("isolate is %s", option_value);
blobmsg_add_string(&wifi_buf, "isolate", option_value);
g_isolate_status = atoi(option_value);
}
/*auth_mode */
opt_val = uci_lookup_option_string(local_ctx, iface_sec_24G, "encryption");
if (opt_val) {
WIFI_DBG("encryption is %s", opt_val);
blobmsg_add_string(&wifi_buf, "encryption", opt_val);
if (strcmp(opt_val, "none")) {
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key", option_value);
}
/*wep */
if (strstr(opt_val, "wep")) {
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key1");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key1", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key2");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key2", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key3");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key3", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key4");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key4", option_value);
}
}
if (strstr(opt_val, "psk")) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_24G, "wpa_group_rekey");
if (option_value) {
blobmsg_add_string(&wifi_buf, "wpa_group_rekey", option_value);
}
}
}
}
blobmsg_close_table(&wifi_buf, tb_ssid);
}
blobmsg_close_table(&wifi_buf, tb_24G);
/*get detail info -- 2.4G end */
}
if (info->wifi_info[i].ap_5G.device && info->wifi_info[i].ap_5G.iface[0]) {
/*get detail info -- 5G begin */
tb_5G = blobmsg_open_table(&wifi_buf, "wifi_if_5G");
dev_sec_5G = info->wifi_info[i].ap_5G.device;
/*switch */
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "disabled");
if (option_value) {
WIFI_DBG("disabled is %s", option_value);
if (strcmp(option_value, "1") == 0) {
blobmsg_add_string(&wifi_buf, "switch", "off");
} else {
WIFI_DBG("wifi_status[%d] %d", i, wifi_status[i]);
if (wifi_status[i] == WIFI_OFF)
blobmsg_add_string(&wifi_buf, "switch", "off");
else
blobmsg_add_string(&wifi_buf, "switch", "on");
}
}
/*net_mode 11g/11n/11a/11b */
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "hwmode");
if (option_value) {
WIFI_DBG("net_mode hwmode is %s", option_value);
blobmsg_add_string(&wifi_buf, "net_mode", option_value);
}
/*bandwidth */
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "htmode");
if (option_value) {
WIFI_DBG("bandwidth is %s", option_value);
blobmsg_add_string(&wifi_buf, "bandwidth", option_value);
}
/*channel */
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "channel");
if (option_value) {
WIFI_DBG("channel is %s", option_value);
blobmsg_add_string(&wifi_buf, "channel", option_value);
}
/*channel range*/
get_wifi_channel_range(&channel_first, &channel_last);
memset(s_channel_first, 0, 4);
memset(s_channel_last, 0, 4);
snprintf(s_channel_first, 4, "%d", channel_first);
snprintf(s_channel_last, 4, "%d", channel_last);
blobmsg_add_string(&wifi_buf, "first_channel", s_channel_first);
blobmsg_add_string(&wifi_buf, "last_channel", s_channel_last);
n_5G_ssid = info->wifi_info[i].ap_5G.n_ssid;
WIFI_DBG("n_5G_ssid number %d", n_5G_ssid);
blobmsg_add_u32(&wifi_buf, "n_ssid", n_5G_ssid);
/*multi SSID*/
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "unsupport_multi_ssid");
if (option_value) {
WIFI_DBG("unsupport multi ssid %s", option_value);
blobmsg_add_string(&wifi_buf, "unsupport_multi_ssid", option_value);
}
for ( j = 0; j < n_5G_ssid; j++ ) {
iface_sec_5G = info->wifi_info[i].ap_5G.iface[j];
sprintf(iface_name, "ssid%d", j);
tb_ssid = blobmsg_open_table(&wifi_buf, iface_name);
/*SSID*/
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "ssid");
if (option_value) {
WIFI_DBG("SSID is %s", option_value);
blobmsg_add_string(&wifi_buf, "ssid", option_value);
}
/*hidden */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "hidden");
if (option_value) {
WIFI_DBG("hidden is %s", option_value);
blobmsg_add_string(&wifi_buf, "hidden", option_value);
}
/*isolate */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "isolate");
if (option_value) {
WIFI_DBG("isolate is %s", option_value);
blobmsg_add_string(&wifi_buf, "isolate", option_value);
g_isolate_status = atoi(option_value);
}
/*auth_mode */
opt_val = uci_lookup_option_string(local_ctx, iface_sec_5G, "encryption");
if (opt_val) {
WIFI_DBG("encryption is %s", opt_val);
blobmsg_add_string(&wifi_buf, "encryption", opt_val);
if (strcmp(opt_val, "none")) {
/*wep */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "key");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key", option_value);
}
if (strstr(opt_val, "wep")) {
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "key1");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key1", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "key2");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key2", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "key3");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key3", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "key4");
if (option_value) {
blobmsg_add_string(&wifi_buf, "key4", option_value);
}
}
if (strstr(opt_val, "psk")) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_5G, "wpa_group_rekey");
if (option_value) {
blobmsg_add_string(&wifi_buf, "wpa_group_rekey", option_value);
}
}
}
}
/*dtim_period */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "dtim_period");
if (option_value) {
WIFI_DBG("dtim_period is %s", option_value);
blobmsg_add_string(&wifi_buf, "dtim_period", option_value);
}
blobmsg_close_table(&wifi_buf, tb_ssid);
}
blobmsg_close_table(&wifi_buf, tb_5G);
/*get detail info -- 5G end */
}
blobmsg_close_table(&wifi_buf, tb_device);
}
EXIT:
if (tb_wireless) {
blobmsg_close_table(&wifi_buf, tb_wireless);
}
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done");
return 0;
}
/*================================================
method: set_wifi_basic_info
return :
<wireless>
<AP0>
<wifi_if_24G>
<switch/> on/off
<ssid0/> primary ssid
<ssid/>
</ssid0>
<channel/>
</wifi_if_24G>
<wifi_if_5G>
<switch/> on/off
<ssid0>
<ssid/>
</ssid0>
<channel/>
</wifi_if_5G>
</AP0>
</wireless>
================================================*/
enum {
WIFI_DEVICE,
WIFI_24G,
WIFI_5G,
WIFI_STA,
WIFI_BS,
};
enum {
SWITCH,
WIFI_SSID,
CHANNEL,
NET_MODE,
BAND_WITCH,
HIDDEN,
ISOLATE,
ENCRYPTION,
KEY,
KEY1,
KEY2,
KEY3,
KEY4,
WPA_GROUP_REKEY,
DTIM_PERIOD,
MULTI_SSID,
SSID_INDEX
};
static const struct blobmsg_policy wifi_setting_pol[] = {
[WIFI_DEVICE] = {
.name = "wifi_device",
.type = BLOBMSG_TYPE_STRING
},
[WIFI_24G] = {
.name = "wifi_if_24G",
.type = BLOBMSG_TYPE_TABLE,
},
[WIFI_5G] = {
.name = "wifi_if_5G",
.type = BLOBMSG_TYPE_TABLE,
},
[WIFI_STA] = {
.name = "wifi_sta",
.type = BLOBMSG_TYPE_TABLE,
},
[WIFI_BS] = {
.name = "bs_enable",
.type = BLOBMSG_TYPE_STRING,
},
};
static const struct blobmsg_policy wifi_basic_info_pol[] = {
[SWITCH] = {
.name = "switch",
.type = BLOBMSG_TYPE_STRING,
},
[WIFI_SSID] = {
.name = "ssid",
.type = BLOBMSG_TYPE_STRING,
},
[CHANNEL] = {
.name = "channel",
.type = BLOBMSG_TYPE_STRING,
},
};
static const struct blobmsg_policy wifi_all_info_pol[] = {
[SWITCH] = {
.name = "switch",
.type = BLOBMSG_TYPE_STRING,
},
[WIFI_SSID] = {
.name = "ssid",
.type = BLOBMSG_TYPE_STRING,
},
[CHANNEL] = {
.name = "channel",
.type = BLOBMSG_TYPE_STRING,
},
[NET_MODE] = {
.name = "net_mode",
.type = BLOBMSG_TYPE_STRING,
},
[BAND_WITCH] = {
.name = "bandwidth",
.type = BLOBMSG_TYPE_STRING,
},
[HIDDEN] = {
.name = "hidden",
.type = BLOBMSG_TYPE_STRING,
},
[ISOLATE] = {
.name = "isolate",
.type = BLOBMSG_TYPE_STRING,
},
[ENCRYPTION] = {
.name = "encryption",
.type = BLOBMSG_TYPE_STRING,
},
[KEY] = {
.name = "key",
.type = BLOBMSG_TYPE_STRING,
},
[KEY1] = {
.name = "key1",
.type = BLOBMSG_TYPE_STRING,
},
[KEY2] = {
.name = "key2",
.type = BLOBMSG_TYPE_STRING,
},
[KEY3] = {
.name = "key3",
.type = BLOBMSG_TYPE_STRING,
},
[KEY4] = {
.name = "key4",
.type = BLOBMSG_TYPE_STRING,
},
[WPA_GROUP_REKEY] = {
.name = "wpa_group_rekey",
.type = BLOBMSG_TYPE_STRING,
},
[DTIM_PERIOD] = {
.name = "dtim_period",
.type = BLOBMSG_TYPE_STRING,
},
[MULTI_SSID] = {
.name = "multi_ssid",
.type = BLOBMSG_TYPE_STRING,
},
[SSID_INDEX] = {
.name = "ssid_index",
.type = BLOBMSG_TYPE_STRING,
},
};
static int wifi_set_basic_info_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_basic_setting[ARRAY_SIZE(wifi_setting_pol)];
struct blob_attr *tb_basic_info_24G[ARRAY_SIZE(wifi_basic_info_pol)];
struct blob_attr *tb_basic_info_5G[ARRAY_SIZE(wifi_basic_info_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
void *tb_wireless = NULL;
int turn_other_off = 0, ret_val = 0, dev_index = 0;
int ssid_change = 0, ssid_len = 0;
char *new_ssid = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_setting_pol, ARRAY_SIZE(wifi_setting_pol), tb_basic_setting, blob_data(msg), blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_basic_setting[WIFI_24G] && !tb_basic_setting[WIFI_5G]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_basic_setting[WIFI_24G] && !tb_basic_setting[WIFI_5G]) {
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
ret_val = parse_wireless_package_info(local_ctx, p, info);
}else {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
}
if (tb_basic_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_basic_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
dev_sec_24G = info->wifi_info[dev_index].ap_2G.device;
dev_sec_5G = info->wifi_info[dev_index].ap_5G.device;
iface_sec_24G = info->wifi_info[dev_index].ap_2G.iface[0];
iface_sec_5G = info->wifi_info[dev_index].ap_5G.iface[0];
if (tb_basic_setting[WIFI_24G] && dev_sec_24G && iface_sec_24G) {
if (blobmsg_parse(wifi_basic_info_pol, ARRAY_SIZE(wifi_basic_info_pol), tb_basic_info_24G,
blobmsg_data(tb_basic_setting[WIFI_24G]),
blobmsg_data_len(tb_basic_setting[WIFI_24G])) == 0) {
WIFI_DBG("Parse WIFI_24G successfully\n");
if (tb_basic_info_24G[SWITCH]) {
turn_other_off = 0;
/*set SWITCH */
WIFI_DBG("setting SWITCH is %s", blobmsg_get_string(tb_basic_info_24G[SWITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "disabled";
if (strcmp(blobmsg_get_string(tb_basic_info_24G[SWITCH]), "off") == 0) {
ptr.value = "1";
} else {
ptr.value = "0";
/*need to set 5G off */
turn_other_off = 1;
}
#ifndef STANDALONE_DUAP_AP
uci_set(local_ctx, &ptr);
if ((turn_other_off == 1) && dev_sec_5G) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "disabled";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
#endif
}
if (tb_basic_info_24G[WIFI_SSID]) {
/*get current ssid */
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "ssid");
/*check whether ssid has been changed */
if (option_value && strcmp(option_value, blobmsg_get_string(tb_basic_info_24G[WIFI_SSID]))) {
ssid_len = strlen(blobmsg_get_string(tb_basic_info_24G[WIFI_SSID]));
if (new_ssid) {
free(new_ssid);
new_ssid = NULL;
}
new_ssid = malloc(ssid_len + 1);
if (new_ssid) {
memset(new_ssid, 0, ssid_len + 1);
memcpy(new_ssid, blobmsg_get_string(tb_basic_info_24G[WIFI_SSID]),
ssid_len);
}
ssid_change = 1;
}
/*set ssid */
WIFI_DBG("setting WIFI SSID is %s", blobmsg_get_string(tb_basic_info_24G[WIFI_SSID]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "ssid";
ptr.value = blobmsg_get_string(tb_basic_info_24G[WIFI_SSID]);
uci_set(local_ctx, &ptr);
}
if (tb_basic_info_24G[CHANNEL]) {
/*set channel */
WIFI_DBG("setting CHANNEL is %s", blobmsg_get_string(tb_basic_info_24G[CHANNEL]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "channel";
ptr.value = blobmsg_get_string(tb_basic_info_24G[CHANNEL]);
uci_set(local_ctx, &ptr);
}
}
}
if (tb_basic_setting[WIFI_5G] && dev_sec_5G && iface_sec_5G) {
if (blobmsg_parse(wifi_basic_info_pol, ARRAY_SIZE(wifi_basic_info_pol), tb_basic_info_5G,
blobmsg_data(tb_basic_setting[WIFI_5G]),
blobmsg_data_len(tb_basic_setting[WIFI_5G])) == 0) {
WIFI_DBG("Parse WIFI_5G successfully\n");
if (tb_basic_info_5G[SWITCH]) {
turn_other_off = 0;
/*set SWITCH */
WIFI_DBG("setting SWITCH is %s", blobmsg_get_string(tb_basic_info_5G[SWITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "disabled";
if (strcmp(blobmsg_get_string(tb_basic_info_5G[SWITCH]), "off") == 0) {
ptr.value = "1";
} else {
ptr.value = "0";
turn_other_off = 1;
}
uci_set(local_ctx, &ptr);
#ifndef STANDALONE_DUAP_AP
if ((turn_other_off == 1) && dev_sec_24G) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "disabled";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
#endif
}
if (tb_basic_info_5G[WIFI_SSID]) {
/*get current ssid, */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "ssid");
/*check whether ssid has been changed */
if (strcmp(option_value, blobmsg_get_string(tb_basic_info_5G[WIFI_SSID]))) {
ssid_len = strlen(blobmsg_get_string(tb_basic_info_5G[WIFI_SSID]));
if (new_ssid) {
free(new_ssid);
new_ssid = NULL;
}
new_ssid = malloc(ssid_len + 1);
if (new_ssid) {
memset(new_ssid, 0, ssid_len + 1);
memcpy(new_ssid, blobmsg_get_string(tb_basic_info_5G[WIFI_SSID]),
ssid_len);
}
ssid_change = 1;
}
/*set SWITCH */
WIFI_DBG("setting WIFI SSID is %s", blobmsg_get_string(tb_basic_info_5G[WIFI_SSID]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "ssid";
ptr.value = blobmsg_get_string(tb_basic_info_5G[WIFI_SSID]);
uci_set(local_ctx, &ptr);
}
if (tb_basic_info_24G[CHANNEL]) {
/*set SWITCH */
WIFI_DBG("setting CHANNEL is %s", blobmsg_get_string(tb_basic_info_5G[CHANNEL]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "channel";
ptr.value = blobmsg_get_string(tb_basic_info_5G[CHANNEL]);
uci_set(local_ctx, &ptr);
}
}
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
if (p) {
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
if ( info->wifi_info[dev_index].sta.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].sta.device->e.name);
else if ( info->wifi_info[dev_index].ap_2G.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].ap_2G.device->e.name);
else if ( info->wifi_info[dev_index].ap_5G.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].ap_5G.device->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
if (p->e.name) {
WIFI_DBG("package name is %s", p->e.name);
}
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
//my_system("/etc/init.d/mwlan reload");
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
my_system(system_buf);
WIFI_DBG("wifi restart");
}
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
/*notify that the ssid has been changed */
if ((ssid_change == 1) && new_ssid) {
ssid_change_notify(ctx, new_ssid);
}
WIFI_DBG("done");
return ret_val;
}
static int wifi_set_multi_ssid_uci_chip_section(struct uci_context *uci_ctx, struct uci_package *p, struct wireless_info *info, int add_del)
{
struct uci_section *uci_sec = info->chip;
struct uci_ptr ptr;
char ap_num[4] = { 0 };
if (!uci_ctx || !p || !uci_sec)
return 0;
switch (add_del) {
case ADD_MULTI_SSID_SEC:
snprintf(ap_num, 4, "%d", (info->n_dev * 2));
WIFI_DBG("ap_num %s", ap_num);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ap_num";
ptr.value = ap_num;
uci_set(uci_ctx, &ptr);
break;
case DELETE_MULTI_SSID_SEC:
snprintf(ap_num, 4, "%d", info->n_dev );
WIFI_DBG("ap_num %s", ap_num);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ap_num";
ptr.value = ap_num;
uci_set(uci_ctx, &ptr);
break;
}
return 1;
}
static int wifi_set_multi_ssid_uci(struct uci_context *uci_ctx, struct uci_package *p, struct ap_sec_info *ap_info, int add_del, int ap_index)
{
struct uci_section *iface_sec = NULL, *uci_sec = NULL;
struct uci_ptr ptr;
const char *value = NULL;
int ifname_index = -1, i, need_commit = 0;
char dev_name[MAX_DEV_NAME_LEN] = { 0 };
char iface_name[MAX_DEV_NAME_LEN] = { 0 };
char ifname[MAX_DEV_NAME_LEN] = { 0 };
char ssid[MAX_DEV_NAME_LEN] = { 0 };
char ssid_n[MAX_DEV_NAME_LEN] = { 0 };
char wpa_group_rekey[MAX_DEV_NAME_LEN] = { 0 };
const char *muitl_ap_ifname_prefix = get_wireless_ifname(ap_index);
char ifname_prefix[MAX_DEV_NAME_LEN] = { 0 };
switch (add_del) {
case ADD_MULTI_SSID_SEC:
snprintf(ifname_prefix, sizeof(ifname_prefix) -1, "%s-%s", muitl_ap_ifname_prefix, MULTI_VIRTUAL_AP_IFNAME_PREFIX);
iface_sec = ap_info->iface[0];
value = uci_lookup_option_string(uci_ctx, iface_sec, "ifname");
if (value) {
//sscanf(value, "uap%d", &ifname_index);
if (strstr(value, ifname_prefix))
{
sscanf(value + strlen(ifname_prefix), "%d", &ifname_index);
}
}
WIFI_DBG("ifname index %d", ifname_index);
value = uci_lookup_option_string(uci_ctx, iface_sec, "device");
if (value) {
strncpy(dev_name, value, sizeof(dev_name) - 1);
WIFI_DBG("device name is %s", dev_name);
}
value = uci_lookup_option_string(uci_ctx, iface_sec, "ssid");
if (value) {
strncpy(ssid, value, sizeof(ssid) - 1);
WIFI_DBG("ssid0 is %s", ssid);
}
value = uci_lookup_option_string(uci_ctx, iface_sec, "wpa_group_rekey");
if (value) {
strncpy(wpa_group_rekey, value, sizeof(ssid) - 1);
WIFI_DBG("wpa_group_rekey is %s", wpa_group_rekey);
}
for ( i = 1; i < MAX_MULTI_SSID_NUM; i++) {
ifname_index++;
if (iface_sec->e.name) {
WIFI_DBG("iface_sec name %s", iface_sec->e.name);
snprintf(iface_name, sizeof(iface_name) - 1, "%s_%d", iface_sec->e.name, ifname_index);
}
snprintf(ifname, sizeof(ifname) -1, "%s%d", ifname_prefix, ifname_index);
snprintf(ssid_n, sizeof(ssid_n) - 1, "%s_%d", ssid, ifname_index);
WIFI_DBG("add iface_name %s, ifname %s, ssid%d %s", iface_name, ifname, ifname_index, ssid_n);
uci_add_section(uci_ctx, p, WIFI_SECTION_IFACE, &uci_sec);
WIFI_DBG("add section 0x%x", uci_sec);
if (uci_sec) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.value = iface_name;
uci_rename(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "device";
ptr.value = dev_name;
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "network";
ptr.value = "lan";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "mode";
ptr.value = "ap";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ifname";
ptr.value = ifname;
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ssid";
ptr.value = ssid_n;
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "encryption";
ptr.value = "none";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "hidden";
ptr.value = "0";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "isolate";
ptr.value = "0";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "macfilter";
ptr.value = "disable";
uci_set(uci_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "wpa_group_rekey";
ptr.value = wpa_group_rekey;
uci_set(uci_ctx, &ptr);
ap_info->iface[i] = uci_sec;
ap_info->n_ssid++;
}
WIFI_DBG("add section 0x%x done", uci_sec);
}
//uci_commit(uci_ctx, &p, false);
need_commit = 1;
break;
case DELETE_MULTI_SSID_SEC:
while (ap_info->n_ssid > 1) {
WIFI_DBG("deleting iface %s", ap_info->iface[ap_info->n_ssid - 1]->e.name);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = ap_info->iface[ap_info->n_ssid - 1];
uci_delete(uci_ctx, &ptr);
ap_info->iface[ap_info->n_ssid - 1] = NULL;
ap_info->n_ssid--;
}
need_commit = 1;
//uci_commit(uci_ctx, &p, false);
break;
default:
break;
}
WIFI_DBG("leave, need_commit %d", need_commit);
return need_commit;
}
static void wifi_set_encrytion_uci(struct uci_context *uci_ctx, struct uci_package *p, struct uci_section *iface, struct blob_attr *tb_info[])
{
struct uci_ptr ptr;
if (tb_info[ENCRYPTION]) {
WIFI_DBG("setting encrytion is %s", blobmsg_get_string(tb_info[ENCRYPTION]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "encryption";
ptr.value = blobmsg_get_string(tb_info[ENCRYPTION]);
uci_set(uci_ctx, &ptr);
}
/*set key */
if (tb_info[KEY]) {
WIFI_DBG("setting key is %s", blobmsg_get_string(tb_info[KEY]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "key";
ptr.value = blobmsg_get_string(tb_info[KEY]);
uci_set(uci_ctx, &ptr);
}
/*set key1 */
if (tb_info[KEY1]) {
WIFI_DBG("setting key1 is %s", blobmsg_get_string(tb_info[KEY1]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "key1";
ptr.value = blobmsg_get_string(tb_info[KEY1]);
uci_set(uci_ctx, &ptr);
}
/*set key2 */
if (tb_info[KEY2]) {
WIFI_DBG("setting key2 is %s", blobmsg_get_string(tb_info[KEY2]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "key2";
ptr.value = blobmsg_get_string(tb_info[KEY2]);
uci_set(uci_ctx, &ptr);
}
/*set key3 */
if (tb_info[KEY3]) {
WIFI_DBG("setting key3 is %s", blobmsg_get_string(tb_info[KEY3]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "key3";
ptr.value = blobmsg_get_string(tb_info[KEY3]);
uci_set(uci_ctx, &ptr);
}
/*set key4 */
if (tb_info[KEY4]) {
WIFI_DBG("setting key4 is %s", blobmsg_get_string(tb_info[KEY4]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "key4";
ptr.value = blobmsg_get_string(tb_info[KEY4]);
uci_set(uci_ctx, &ptr);
}
/*set wpa_group_rekey */
if (tb_info[WPA_GROUP_REKEY]) {
WIFI_DBG("setting WPA_GROUP_REKEY is %s",
blobmsg_get_string(tb_info[WPA_GROUP_REKEY]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface;
ptr.option = "wpa_group_rekey";
ptr.value = blobmsg_get_string(tb_info[WPA_GROUP_REKEY]);
uci_set(uci_ctx, &ptr);
}
}
/*================================================
method: set_wifi_detail_2.4G/set_wifi_detail_5G
<wireless>
<wifi_device/>
<wifi_if_24G>
<switch/>
<net_mode/>
<channel/>
<bandwidth/>
<hidden/>
<isolate/>
<multi_ssid/>
<ssid_index/>
<ssid/>
<encryption>
<key>
<key1>
<key2>
<key3>
<key4>
<wpa_group_rekey/>
</wifi_if_24G>
<wifi_if_5G>
...
</wifi_if_5G>
</wireless>
================================================*/
static int wifi_set_all_setting_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_basic_setting[ARRAY_SIZE(wifi_setting_pol)];
struct blob_attr *tb_info_24G[ARRAY_SIZE(wifi_all_info_pol)];
struct blob_attr *tb_info_5G[ARRAY_SIZE(wifi_all_info_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
struct ap_sec_info *ap_info = NULL;
const char *option_value = NULL, *country_code = NULL;
void *tb_wireless = NULL;
int turn_other_off = 0;
int ret_val = 0;
int ssid_len = 0;
int ssid_change = 0;
char *new_ssid = NULL;
int dev_index, multi_ssid = 0, n_ssid = 0, ssid_index = 0, need_commit = 0;
enum isolate_state ap_isolate_state = AP_ISOLATE_NO_CHANGE;
int current_isolate_status = g_isolate_status;
int stop_start_wifi = 0;
int bs_enable = -1;
int dev_5g_index = 0;
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
char dev_name1[20] = { 0 };
unsigned int obj_id = 0, wait_seconds = 0;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_setting_pol, ARRAY_SIZE(wifi_setting_pol), tb_basic_setting, blob_data(msg), blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_basic_setting[WIFI_24G] && !tb_basic_setting[WIFI_5G]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
ret_val = parse_wireless_package_info(local_ctx, p, info);
}else {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
}
if (tb_basic_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_basic_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
dev_5g_index = dev_index;
if (tb_basic_setting[WIFI_BS]) {
bs_enable = atoi(blobmsg_get_string(tb_basic_setting[WIFI_BS]));
if (info->wifi_info[WIFI_AP0].ap_2G.device) {
dev_index = WIFI_AP0;
if (info->wifi_info[WIFI_AP1].ap_5G.device)
dev_5g_index = WIFI_AP1;
}
else if (info->wifi_info[WIFI_AP1].ap_2G.device) {
dev_index = WIFI_AP1;
if (info->wifi_info[WIFI_AP0].ap_5G.device)
dev_5g_index = WIFI_AP0;
}
}
WIFI_DBG("dev_index %d, dev_5g_index %d", dev_index, dev_5g_index);
if (tb_basic_setting[WIFI_24G]) {
if (blobmsg_parse(wifi_all_info_pol, ARRAY_SIZE(wifi_all_info_pol), tb_info_24G,
blobmsg_data(tb_basic_setting[WIFI_24G]),
blobmsg_data_len(tb_basic_setting[WIFI_24G])) == 0) {
WIFI_DBG("Parse WIFI_24G successfully\n");
dev_sec_24G = info->wifi_info[dev_index].ap_2G.device;
turn_other_off = 0;
if (tb_info_24G[SWITCH]) {
/*set SWITCH */
WIFI_DBG("setting SWITCH is %s", blobmsg_get_string(tb_info_24G[SWITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "disabled";
if (strcasecmp(blobmsg_get_string(tb_info_24G[SWITCH]), "off") == 0) {
ptr.value = "1";
if (stop_start_wifi == 0)
stop_start_wifi = 1;
} else {
turn_other_off = 1;
ptr.value = "0";
stop_start_wifi = 2;
}
uci_set(local_ctx, &ptr);
#ifndef STANDALONE_DUAP_AP
dev_sec_5G = info->wifi_info[dev_index].ap_5G.device;
if ((turn_other_off == 1) && dev_sec_5G) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "disabled";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
#endif
need_commit = 1;
}
if (tb_info_24G[MULTI_SSID]) {
multi_ssid = atoi(blobmsg_get_string(tb_info_24G[MULTI_SSID]));
}
if (tb_info_24G[SSID_INDEX]) {
ssid_index = atoi(blobmsg_get_string(tb_info_24G[SSID_INDEX]));
}
iface_sec_24G = info->wifi_info[dev_index].ap_2G.iface[ssid_index];
n_ssid = info->wifi_info[dev_index].ap_2G.n_ssid;
if (multi_ssid) {
if (n_ssid > 1) {
/*change some parameters*/
/*set encrytion */
wifi_set_encrytion_uci(local_ctx, p, iface_sec_24G, tb_info_24G);
} else {
/*need add new iface section*/
ap_info = &(info->wifi_info[dev_index].ap_2G);
need_commit |= wifi_set_multi_ssid_uci(local_ctx, p, ap_info, ADD_MULTI_SSID_SEC, dev_index);
need_commit |= wifi_set_multi_ssid_uci_chip_section(local_ctx, p, info, ADD_MULTI_SSID_SEC);
stop_start_wifi = 2;
}
} else {
if (n_ssid > 1) {
/*here should delete iface section*/
ap_info = &(info->wifi_info[dev_index].ap_2G);
need_commit |= wifi_set_multi_ssid_uci(local_ctx, p, ap_info, DELETE_MULTI_SSID_SEC, dev_index);
need_commit |= wifi_set_multi_ssid_uci_chip_section(local_ctx, p, info, DELETE_MULTI_SSID_SEC);
stop_start_wifi = 2;
} else {
/*set encrytion */
wifi_set_encrytion_uci(local_ctx, p, iface_sec_24G, tb_info_24G);
}
}
if (tb_info_24G[WIFI_SSID]) {
/*get current ssid */
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "ssid");
WIFI_DBG("setting ssid %s, uci ssid %s", blobmsg_get_string(tb_info_24G[WIFI_SSID]), option_value);
/*check whether ssid has been changed */
if (option_value && strcmp(option_value, blobmsg_get_string(tb_info_24G[WIFI_SSID]))) {
ssid_len = strlen(blobmsg_get_string(tb_info_24G[WIFI_SSID]));
if (new_ssid) {
free(new_ssid);
new_ssid = NULL;
}
new_ssid = malloc(ssid_len + 1);
if (new_ssid) {
memset(new_ssid, 0, ssid_len + 1);
strncpy(new_ssid, blobmsg_get_string(tb_info_24G[WIFI_SSID]), ssid_len);
}
ssid_change = 1;
}
/*set ssid */
if (ssid_change) {
WIFI_DBG("setting WIFI SSID is %s", blobmsg_get_string(tb_info_24G[WIFI_SSID]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "ssid";
ptr.value = blobmsg_get_string(tb_info_24G[WIFI_SSID]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
option_value = uci_lookup_option_string(local_ctx, dev_sec_24G, "country");
country_code = get_conuntry_code();
if (option_value) {
if (country_code && strcmp(option_value, country_code)) {
/*need set new country code*/
WIFI_DBG("setting country code %s", country_code);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "country";
ptr.value = country_code;
uci_set(local_ctx, &ptr);
need_commit = 1;
stop_start_wifi = 2;
}
} else {
if (country_code) {
/*need set new country code*/
WIFI_DBG("setting country code %s", country_code);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "country";
ptr.value = country_code;
uci_set(local_ctx, &ptr);
need_commit = 1;
stop_start_wifi = 2;
}
}
if (tb_info_24G[CHANNEL]) {
/*set channel */
WIFI_DBG("setting CHANNEL is %s", blobmsg_get_string(tb_info_24G[CHANNEL]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "channel";
ptr.value = blobmsg_get_string(tb_info_24G[CHANNEL]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
if (tb_info_24G[NET_MODE]) {
/*set net node */
WIFI_DBG("setting NET_MODE is %s", blobmsg_get_string(tb_info_24G[NET_MODE]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "hwmode";
ptr.value = blobmsg_get_string(tb_info_24G[NET_MODE]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
/*set bandwidth */
if (tb_info_24G[NET_MODE]) {
if (strstr(blobmsg_get_string(tb_info_24G[NET_MODE]), "ax") || strstr(blobmsg_get_string(tb_info_24G[NET_MODE]), "n")) {
/*only 11n/11ax have the htmode option*/
if (tb_info_24G[BAND_WITCH]) {
WIFI_DBG("setting bandwidth is %s", blobmsg_get_string(tb_info_24G[BAND_WITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "htmode";
ptr.value = blobmsg_get_string(tb_info_24G[BAND_WITCH]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
} else {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "htmode";
uci_delete(local_ctx, &ptr);
need_commit = 1;
}
}
/*set HIDDEN */
if (tb_info_24G[HIDDEN]) {
WIFI_DBG("setting HIDDEN is %s", blobmsg_get_string(tb_info_24G[HIDDEN]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "hidden";
ptr.value = blobmsg_get_string(tb_info_24G[HIDDEN]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
/*set ISOLATE */
if (tb_info_24G[ISOLATE]) {
WIFI_DBG("setting ISOLATE is %s", blobmsg_get_string(tb_info_24G[ISOLATE]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "isolate";
ptr.value = blobmsg_get_string(tb_info_24G[ISOLATE]);
uci_set(local_ctx, &ptr);
need_commit = 1;
current_isolate_status = atoi(blobmsg_get_string(tb_info_24G[ISOLATE]));
/*set 5G isolate*/
n_ssid = info->wifi_info[dev_index].ap_5G.n_ssid;
for (ssid_index = 0; ssid_index < n_ssid; ssid_index++) {
iface_sec_5G = info->wifi_info[dev_index].ap_5G.iface[ssid_index];
WIFI_DBG("setting 5G ISOLATE");
if (current_isolate_status) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "isolate";
ptr.value = "1";
uci_set(local_ctx, &ptr);
need_commit = 1;
} else {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "isolate";
ptr.value = "0";
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
}
/*set DTIM_PERIOD */
if (tb_info_24G[DTIM_PERIOD]) {
WIFI_DBG("setting DTIM_PERIOD is %s", blobmsg_get_string(tb_info_24G[DTIM_PERIOD]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "dtim_period";
ptr.value = blobmsg_get_string(tb_info_24G[DTIM_PERIOD]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
}
if (tb_basic_setting[WIFI_5G]) {
if (blobmsg_parse(wifi_all_info_pol, ARRAY_SIZE(wifi_all_info_pol), tb_info_5G,
blobmsg_data(tb_basic_setting[WIFI_5G]),
blobmsg_data_len(tb_basic_setting[WIFI_5G])) == 0) {
WIFI_DBG("Parse WIFI_5G successfully\n");
dev_sec_5G = info->wifi_info[dev_5g_index].ap_5G.device;
if (tb_info_5G[SWITCH]) {
turn_other_off = 0;
/*set SWITCH */
WIFI_DBG("setting SWITCH is %s", blobmsg_get_string(tb_info_5G[SWITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "disabled";
if (strcmp(blobmsg_get_string(tb_info_5G[SWITCH]), "off") == 0) {
ptr.value = "1";
if (stop_start_wifi == 0)
stop_start_wifi = 1;
} else {
ptr.value = "0";
turn_other_off = 1;
stop_start_wifi = 2;
}
uci_set(local_ctx, &ptr);
#ifndef STANDALONE_DUAP_AP
dev_sec_24G = info->wifi_info[dev_5g_index].ap_2G.device;
if ((turn_other_off == 1) && dev_sec_24G) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_24G;
ptr.option = "disabled";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
#endif
need_commit = 1;
}
if (tb_info_5G[MULTI_SSID]) {
multi_ssid = atoi(blobmsg_get_string(tb_info_5G[MULTI_SSID]));
}
if (tb_info_5G[SSID_INDEX]) {
ssid_index = atoi(blobmsg_get_string(tb_info_5G[SSID_INDEX]));
}
iface_sec_5G = info->wifi_info[dev_5g_index].ap_5G.iface[ssid_index];
n_ssid = info->wifi_info[dev_5g_index].ap_5G.n_ssid;
if (multi_ssid) {
if (n_ssid > 1) {
/*change some parameters*/
/*set encrytion */
wifi_set_encrytion_uci(local_ctx, p, iface_sec_5G, tb_info_5G);
} else {
/*need add new iface section*/
ap_info = &(info->wifi_info[dev_5g_index].ap_5G);
need_commit |= wifi_set_multi_ssid_uci(local_ctx, p, ap_info, ADD_MULTI_SSID_SEC, dev_5g_index);
need_commit |= wifi_set_multi_ssid_uci_chip_section(local_ctx, p, info, ADD_MULTI_SSID_SEC);
if (stop_start_wifi != 1)
stop_start_wifi = 2;
}
} else {
if (n_ssid > 1) {
/*here should delete iface section*/
ap_info = &(info->wifi_info[dev_5g_index].ap_5G);
need_commit |= wifi_set_multi_ssid_uci(local_ctx, p, ap_info, DELETE_MULTI_SSID_SEC, dev_5g_index);
need_commit |= wifi_set_multi_ssid_uci_chip_section(local_ctx, p, info, DELETE_MULTI_SSID_SEC);
if (stop_start_wifi != 1)
stop_start_wifi = 2;
} else {
/*set encrytion */
wifi_set_encrytion_uci(local_ctx, p, iface_sec_5G, tb_info_5G);
WIFI_DBG("wifi_set_encrytion_uci done");
}
}
if (tb_info_5G[WIFI_SSID]) {
/*get current ssid */
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "ssid");
WIFI_DBG("old ssid %s", option_value ? option_value : "NULL");
/*check whether ssid has been changed */
if (option_value && strcmp(option_value, blobmsg_get_string(tb_info_5G[WIFI_SSID]))) {
ssid_len = strlen(blobmsg_get_string(tb_info_5G[WIFI_SSID]));
if (new_ssid) {
free(new_ssid);
new_ssid = NULL;
}
new_ssid = malloc(ssid_len + 1);
if (new_ssid) {
memset(new_ssid, 0, ssid_len + 1);
memcpy(new_ssid, blobmsg_get_string(tb_info_5G[WIFI_SSID]), ssid_len);
}
ssid_change = 1;
WIFI_DBG("new_ssid %s", new_ssid);
}
if (ssid_change) {
/*set ssid */
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
WIFI_DBG("setting WIFI 5G SSID is %s", blobmsg_get_string(tb_info_5G[WIFI_SSID]));
ptr.option = "ssid";
ptr.value = blobmsg_get_string(tb_info_5G[WIFI_SSID]);
uci_set(local_ctx, &ptr);
}
need_commit = 1;
}
option_value = uci_lookup_option_string(local_ctx, dev_sec_5G, "country");
country_code = get_conuntry_code();
if (option_value) {
if (country_code && strcmp(option_value, country_code)) {
/*need set new country code*/
WIFI_DBG("setting country code %s", country_code);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "country";
ptr.value = country_code;
uci_set(local_ctx, &ptr);
need_commit = 1;
if (stop_start_wifi != 1)
stop_start_wifi = 2;
}
} else {
if (country_code) {
/*need set new country code*/
WIFI_DBG("setting country code %s", country_code);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "country";
ptr.value = country_code;
uci_set(local_ctx, &ptr);
need_commit = 1;
if (stop_start_wifi != 1)
stop_start_wifi = 2;
}
}
if (tb_info_5G[CHANNEL]) {
/*set channel */
WIFI_DBG("setting CHANNEL is %s", blobmsg_get_string(tb_info_5G[CHANNEL]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "channel";
ptr.value = blobmsg_get_string(tb_info_5G[CHANNEL]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
if (tb_info_5G[NET_MODE]) {
/*set net node */
WIFI_DBG("setting NET_MODE is %s", blobmsg_get_string(tb_info_5G[NET_MODE]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "hwmode";
ptr.value = blobmsg_get_string(tb_info_5G[NET_MODE]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
/*set bandwidth */
if (tb_info_5G[NET_MODE]) {
if (strstr(blobmsg_get_string(tb_info_5G[NET_MODE]), "n") || strstr(blobmsg_get_string(tb_info_5G[NET_MODE]), "ac") ||
strstr(blobmsg_get_string(tb_info_5G[NET_MODE]), "ax")) {
/*11n/11ac/11ax have the htmode option*/
if (tb_info_5G[BAND_WITCH]) {
WIFI_DBG("setting bandwidth is %s", blobmsg_get_string(tb_info_5G[BAND_WITCH]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "htmode";
ptr.value = blobmsg_get_string(tb_info_5G[BAND_WITCH]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
} else {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = dev_sec_5G;
ptr.option = "htmode";
uci_delete(local_ctx, &ptr);
need_commit = 1;
}
}
/*set HIDDEN */
if (tb_info_5G[HIDDEN]) {
WIFI_DBG("setting HIDDEN is %s", blobmsg_get_string(tb_info_5G[HIDDEN]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "hidden";
ptr.value = blobmsg_get_string(tb_info_5G[HIDDEN]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
/*set ISOLATE */
if (tb_info_5G[ISOLATE]) {
WIFI_DBG("setting ISOLATE is %s", blobmsg_get_string(tb_info_5G[ISOLATE]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "isolate";
ptr.value = blobmsg_get_string(tb_info_5G[ISOLATE]);
uci_set(local_ctx, &ptr);
need_commit = 1;
current_isolate_status = atoi(blobmsg_get_string(tb_info_5G[ISOLATE]));
/*set 5G isolate*/
n_ssid = info->wifi_info[dev_5g_index].ap_5G.n_ssid;
for (ssid_index = 0; ssid_index < n_ssid; ssid_index++) {
iface_sec_5G = info->wifi_info[dev_5g_index].ap_5G.iface[ssid_index];
WIFI_DBG("setting 5G ISOLATE");
if (current_isolate_status) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "isolate";
ptr.value = "1";
uci_set(local_ctx, &ptr);
need_commit = 1;
} else {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "isolate";
ptr.value = "0";
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
}
/*set DTIM_PERIOD */
if (tb_info_5G[DTIM_PERIOD]) {
WIFI_DBG("setting DTIM_PERIOD is %s", blobmsg_get_string(tb_info_5G[DTIM_PERIOD]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "dtim_period";
ptr.value = blobmsg_get_string(tb_info_5G[DTIM_PERIOD]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
}
if (bs_enable >= 0) {
if (info->sec_bs == NULL) {
uci_add_section(local_ctx, p, WIFI_SECTION_BS, &(info->sec_bs));
}
if (info->sec_bs) {
WIFI_DBG("setting bs_enable %d", bs_enable);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = info->sec_bs;
ptr.option = "bs_enable";
ptr.value = blobmsg_get_string(tb_basic_setting[WIFI_BS]);
uci_set(local_ctx, &ptr);
need_commit = 1;
}
}
set_current_ap_index(dev_index);
EXIT:
if (current_isolate_status == 0) {
if (g_isolate_status == current_isolate_status)
ap_isolate_state = AP_ISOLATE_NO_CHANGE;
else
ap_isolate_state = AP_ISOLATE_ON_OFF;
} else if (current_isolate_status == 1) {
if (g_isolate_status == current_isolate_status)
ap_isolate_state = AP_ISOLATE_NO_CHANGE;
else
ap_isolate_state = AP_ISOLATE_OFF_ON;
} else {
WIFI_ERR("Unknown isolate_status \r\n");
ap_isolate_state = AP_ISOLATE_NO_CHANGE;
}
g_isolate_status = current_isolate_status;
WIFI_DBG("ap_isolate_state %d, stop_start_wifi %d, current ap index %d, bs_enable %d", ap_isolate_state, stop_start_wifi, dev_index, bs_enable);
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
if (p) {
if (p->e.name) {
WIFI_DBG("package name is %s", p->e.name);
}
memset(dev_name, 0, sizeof(dev_name));
memset(system_buf, 0, sizeof(system_buf));
WIFI_DBG("bs_enable %d, dev_5g_index %d, 5G_dev_section %p", bs_enable, dev_5g_index, info->wifi_info[dev_5g_index].ap_5G.device);
if (bs_enable >= 0) {
if (bs_enable == 1)
snprintf(system_buf, sizeof(system_buf), "echo 1 > /sys/module/asr5861/parameters/bs_enable");
else
snprintf(system_buf, sizeof(system_buf), "echo 0 > /sys/module/asr5861/parameters/bs_enable");
my_system(system_buf);
if ( info->wifi_info[dev_index].ap_2G.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].ap_2G.device->e.name);
if ( info->wifi_info[dev_5g_index].ap_5G.device)
{
WIFI_DBG("e.name [%s]", info->wifi_info[dev_5g_index].ap_5G.device->e.name);
snprintf(dev_name1, sizeof(dev_name1), "%s", info->wifi_info[dev_5g_index].ap_5G.device->e.name);
WIFI_DBG("dev_name1 [%s]", dev_name1);
}
if (need_commit) {
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
}
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop %s", dev_name);
my_system(system_buf);
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop %s", dev_name1);
my_system(system_buf);
if (stop_start_wifi != 1)
{
sleep(3);
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan start %s", dev_name);
my_system(system_buf);
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan start %s", dev_name1);
my_system(system_buf);
while(wait_seconds++ < 20) {
if (wireless_lookup_hostapd_id(&obj_id, dev_index) != 0)
sleep(1);
else
break;
}
if (wait_seconds >= 20) {
WIFI_DBG("wifi not ready in %d seconds", wait_seconds);
}
else {
WIFI_DBG("wifi ready again in %d seconds", wait_seconds);
}
wait_seconds = 0;
while(wait_seconds++ < 20) {
if (wireless_lookup_hostapd_id(&obj_id, dev_5g_index) != 0)
sleep(1);
else
break;
}
if (wait_seconds >= 20) {
WIFI_DBG("wifi not ready in %d seconds", wait_seconds);
}
else {
WIFI_DBG("wifi ready again in %d seconds", wait_seconds);
}
}
goto end;
}
else {
if (chip_type_support_dual_ap())
{
if ( info->wifi_info[dev_index].sta.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].sta.device->e.name);
else if ( info->wifi_info[dev_index].ap_2G.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].ap_2G.device->e.name);
else if ( info->wifi_info[dev_index].ap_5G.device)
snprintf(dev_name, sizeof(dev_name), "%s", info->wifi_info[dev_index].ap_5G.device->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
}
}
if (need_commit) {
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
if (stop_start_wifi == 1) {
//my_system("/etc/init.d/mwlan stop");
if (strlen(dev_name) > 0)
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop %s", dev_name);
else
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop");
WIFI_DBG("wifi will stop\r\n");
} else if (stop_start_wifi == 0){
//my_system("/etc/init.d/mwlan reload");
if (strlen(dev_name) > 0)
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
else
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload");
WIFI_DBG("wifi will reload\r\n");
} else {
//my_system("/etc/init.d/mwlan stop");
WIFI_DBG("wifi will restart\r\n");
if (strlen(dev_name) > 0)
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop %s", dev_name);
else
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan stop");
my_system(system_buf);
sleep(3);
//my_system("/etc/init.d/mwlan start");
if (strlen(dev_name) > 0)
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan start %s", dev_name);
else
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan start");
//my_system("/etc/init.d/mwlan restart");
}
#ifdef AP_ISOLATE_SCRIPT
switch(ap_isolate_state) {
case AP_ISOLATE_OFF_ON:
sleep(10);
my_system("/etc/init.d/mwlan_isolate on");
break;
case AP_ISOLATE_ON_OFF:
sleep(10);
my_system("/etc/init.d/mwlan_isolate off");
break;
case AP_ISOLATE_NO_CHANGE:
default:
break;
}
#endif
WIFI_DBG("executing [%s] ", system_buf);
my_system(system_buf);
}
}
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
if (stop_start_wifi == 0 || stop_start_wifi == 2) {
while(wait_seconds++ < 20) {
if (wireless_lookup_hostapd_id(&obj_id, dev_index) != 0)
sleep(1);
else
break;
}
if (wait_seconds >= 20) {
WIFI_DBG("wifi not ready in %d seconds", wait_seconds);
}
else {
WIFI_DBG("wifi ready again in %d seconds", wait_seconds);
}
}
end:
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
/*notify that the ssid has been changed */
if ((ssid_change == 1) && new_ssid) {
ssid_change_notify(ctx, new_ssid);
}
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
/*================================================
method: wifi_get_MAC_filter_cb
<wirless>
<wireless_num/>
<AP0>
<wifi_if_24G>
<macfilter/>
<maclist_allow/>
</wifi_if_24G>
<wifi_if_5G>
...
</wifi_if_5G>
</AP0>
</wireless>
================================================*/
static int wifi_get_MAC_filter_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec = NULL;
struct uci_section *iface_sec = NULL;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
void *tb_wireless = NULL, *tb_device = NULL;
char tmp[10] = { 0 };
int i;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
blobmsg_buf_init(&wifi_buf);
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
parse_wireless_package_info(local_ctx, p, info);
}else {
goto EXIT;
}
}
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
blobmsg_add_u32(&wifi_buf, "wireless_num", (unsigned int)info->n_dev);
WIFI_DBG("wireless number %d", info->n_dev);
for ( i = 0; i < info->n_dev; i++) {
if (info->wifi_info[i].ap_2G.device ||info->wifi_info[i].ap_5G.device) {
snprintf(tmp, sizeof(tmp) - 1, "AP%d", i);
}
else {
continue;
}
WIFI_DBG("device name %s", tmp);
tb_device = blobmsg_open_table(&wifi_buf, tmp);
dev_sec = info->wifi_info[i].ap_2G.device;
iface_sec = info->wifi_info[i].ap_2G.iface[0];
if (!dev_sec || !iface_sec) {
dev_sec = info->wifi_info[i].ap_5G.device;
iface_sec = info->wifi_info[i].ap_5G.iface[0];
}
option_value = uci_lookup_option_string(local_ctx, iface_sec, "macfilter");
if (option_value) {
WIFI_DBG("macfilter is %s", option_value);
blobmsg_add_string(&wifi_buf, "macfilter", option_value);
option_value = uci_lookup_option_string(local_ctx, iface_sec, "maclist_allow");
if (option_value) {
WIFI_DBG("maclist_allow is %s", option_value);
blobmsg_add_string(&wifi_buf, "maclist_allow", option_value);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec, "maclist_deny");
if (option_value) {
WIFI_DBG("maclist_deny is %s", option_value);
blobmsg_add_string(&wifi_buf, "maclist_deny", option_value);
}
} else {
blobmsg_add_string(&wifi_buf, "macfilter", "disable");
}
blobmsg_close_table(&wifi_buf, tb_device);
}
EXIT:
if (tb_wireless) {
blobmsg_close_table(&wifi_buf, tb_wireless);
}
ubus_send_reply(ctx, req, wifi_buf.head);
WIFI_DBG("done");
blob_buf_free(&wifi_buf);
return 0;
}
enum {
MACFILTER = 1,
MACLIST_ALLOW,
MACLIST_DENY,
ADD_MACLIST_ALLOW,
ADD_MACLIST_DENY,
DEL_MACLIST_ALLOW,
DEL_MACLIST_DENY,
};
static const struct blobmsg_policy wifi_MAC_filter_pol[] = {
[WIFI_DEVICE] = {
.name = "wifi_device",
.type = BLOBMSG_TYPE_STRING,
},
[MACFILTER] = {
.name = "macfilter",
.type = BLOBMSG_TYPE_STRING,
},
[MACLIST_ALLOW] = {
.name = "maclist_allow",
.type = BLOBMSG_TYPE_STRING,
},
[MACLIST_DENY] = {
.name = "maclist_deny",
.type = BLOBMSG_TYPE_STRING,
},
[ADD_MACLIST_ALLOW] = {
.name = "add_maclist_allow",
.type = BLOBMSG_TYPE_STRING,
},
[ADD_MACLIST_DENY] = {
.name = "add_maclist_deny",
.type = BLOBMSG_TYPE_STRING,
},
[DEL_MACLIST_ALLOW] = {
.name = "del_maclist_allow",
.type = BLOBMSG_TYPE_STRING,
},
[DEL_MACLIST_DENY] = {
.name = "del_maclist_deny",
.type = BLOBMSG_TYPE_STRING,
},
};
static int wifi_set_MAC_filter_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_mac_setting[ARRAY_SIZE(wifi_MAC_filter_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
void *tb_wireless = NULL;
int ret_val = 0, dev_index = 0;
const char *before_macfilter = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_MAC_filter_pol, ARRAY_SIZE(wifi_MAC_filter_pol), tb_mac_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_mac_setting[MACFILTER] && !tb_mac_setting[MACLIST_ALLOW] && !tb_mac_setting[MACLIST_DENY]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
ret_val = parse_wireless_package_info(local_ctx, p, info);
}else {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
}
if (tb_mac_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_mac_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
dev_sec_24G = info->wifi_info[dev_index].ap_2G.device;
dev_sec_5G = info->wifi_info[dev_index].ap_5G.device;
iface_sec_24G = info->wifi_info[dev_index].ap_2G.iface[0];
dev_sec_5G = info->wifi_info[dev_index].ap_5G.iface[0];
/*set Mac filters to 2.4G */
if (dev_sec_24G && iface_sec_24G) {
before_macfilter = uci_lookup_option_string(local_ctx, iface_sec_24G, "macfilter");
if (tb_mac_setting[MACFILTER]) {
WIFI_DBG("setting MACFILTER 24G is %s", blobmsg_get_string(tb_mac_setting[MACFILTER]));
if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "disable")) {
if (!before_macfilter
|| strcmp(before_macfilter, blobmsg_get_string(tb_mac_setting[MACFILTER]))) {
WIFI_DBG("macfilter change");
if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "allow") == 0) {
if (!tb_mac_setting[MACLIST_ALLOW]) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_24G,
"maclist_allow");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
ptr.value = option_value;
uci_set(local_ctx, &ptr);
} else {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
uci_delete(local_ctx, &ptr);
}
}
} else if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "deny") == 0) {
if (!tb_mac_setting[MACLIST_DENY]) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_24G,
"maclist_deny");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
ptr.value = option_value;
uci_set(local_ctx, &ptr);
} else {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
uci_delete(local_ctx, &ptr);
}
}
}
}
}
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "macfilter");
if (tb_mac_setting[MACLIST_ALLOW]) {
WIFI_DBG("setting MACFILTER ALLOW 2.4G is %s",
blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_allow";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]);
uci_set(local_ctx, &ptr);
if (option_value && strcmp(option_value, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
WIFI_DBG("option_value 2.4G is %s", option_value);
ptr.option = "maclist";
WIFI_DBG("setting maclist 2.4G %s",
blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]));
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]);
uci_set(local_ctx, &ptr);
}
}
if (tb_mac_setting[MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 2.4G is %s", blobmsg_get_string(tb_mac_setting[MACLIST_DENY]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_deny";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_DENY]);
uci_set(local_ctx, &ptr);
if (option_value && strcmp(option_value, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_DENY]);
uci_set(local_ctx, &ptr);
}
}
}
/*Set MAC filters 5G */
if (dev_sec_5G && iface_sec_5G) {
before_macfilter = uci_lookup_option_string(local_ctx, iface_sec_5G, "macfilter");
if (tb_mac_setting[MACFILTER]) {
WIFI_DBG("setting MACFILTER is %s", blobmsg_get_string(tb_mac_setting[MACFILTER]));
if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "disable")) {
if (!before_macfilter
|| strcmp(before_macfilter, blobmsg_get_string(tb_mac_setting[MACFILTER]))) {
WIFI_DBG("macfilter change");
if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "allow") == 0) {
if (!tb_mac_setting[MACLIST_ALLOW]) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_24G,
"maclist_allow");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
ptr.value = option_value;
uci_set(local_ctx, &ptr);
} else {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
uci_delete(local_ctx, &ptr);
}
}
} else if (strcmp(blobmsg_get_string(tb_mac_setting[MACFILTER]), "deny") == 0) {
if (!tb_mac_setting[MACLIST_DENY]) {
option_value =
uci_lookup_option_string(local_ctx, iface_sec_24G,
"maclist_deny");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
ptr.value = option_value;
uci_set(local_ctx, &ptr);
} else {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
uci_delete(local_ctx, &ptr);
}
}
}
}
}
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
}
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "macfilter");
if (tb_mac_setting[MACLIST_ALLOW]) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
WIFI_DBG("setting MACFILTER ALLOW 5G is %s", blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]));
ptr.option = "maclist_allow";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]);
uci_set(local_ctx, &ptr);
if (option_value && strcmp(option_value, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_ALLOW]);
uci_set(local_ctx, &ptr);
}
}
if (tb_mac_setting[MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 5G is %s", blobmsg_get_string(tb_mac_setting[MACLIST_DENY]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist_deny";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_DENY]);
uci_set(local_ctx, &ptr);
if (option_value && strcmp(option_value, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
ptr.value = blobmsg_get_string(tb_mac_setting[MACLIST_DENY]);
uci_set(local_ctx, &ptr);
}
}
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
if (p) {
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
if (dev_sec_24G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_24G->e.name);
else if (dev_sec_5G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_5G->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
//my_system("/etc/init.d/mwlan reload");
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
my_system(system_buf);
WIFI_DBG("wifi restart\r\n");
}
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
static char *get_next_non_space_char(char *in_str)
{
char *ch = NULL;
int nExit = 0;
if (!in_str) {
return NULL;
}
ch = in_str;
while (nExit == 0) {
switch (*ch) {
case '\n':
case ' ':
case '\t':
case '\r':
continue;
default:
nExit = 1;
}
ch++;
}
return ch;
}
static char *add_multi_mac(const char *cur_mac, char *new_mac_str)
{
char *new_buf;
int buf_len = 0;
if (!cur_mac || !new_mac_str) {
return NULL;
}
buf_len = strlen(cur_mac) + strlen(new_mac_str) + 3;
new_buf = malloc(buf_len);
if (new_buf) {
memset(new_buf, 0, buf_len);
memcpy(new_buf, cur_mac, strlen(cur_mac));
strcat(new_buf, " ");
strcat(new_buf, new_mac_str);
}
return new_buf;
}
static char *delete_one_mac(char *cur_mac, char *new_mac)
{
char *new_buf = NULL;
int buf_len = 0;
char *begin = NULL;
char *end = NULL;
char one_mac[18];
if (!cur_mac) {
return NULL;
}
buf_len = strlen(cur_mac) + 3;
new_buf = (char *)malloc(buf_len);
if (!new_buf) {
WIFI_ERR("malloc fail");
return NULL;
}
memset(new_buf, 0, buf_len);
begin = get_next_non_space_char(cur_mac);
while (*begin) {
end = strchr(begin, ' ');
if (!end) {
if (strlen(begin) < 18) {
memset(one_mac, 0, sizeof(one_mac));
memcpy(one_mac, begin, strlen(begin));
if (strcmp(one_mac, new_mac) == 0) {
break;
}
strcat(new_buf, one_mac);
}
break;
}
if (end - begin < 18) {
memset(one_mac, 0, sizeof(one_mac));
memcpy(one_mac, begin, end - begin);
if (strcmp(one_mac, new_mac) == 0) {
continue;
}
}
strcat(new_buf, one_mac);
begin = end + 1;
}
return new_buf;
}
static char *del_multi_mac(const char *cur_mac, char *del_mac_str)
{
char *begin = NULL;
char *end = NULL;
char one_mac[18];
char *origin_mac = NULL;
char *new_buf = NULL;
if (!cur_mac) {
return NULL;
}
if (!del_mac_str) {
new_buf = malloc(strlen(cur_mac) + 1);
memset(new_buf, 0, sizeof(cur_mac) + 1);
memcpy(new_buf, cur_mac, strlen(cur_mac));
return new_buf;
}
begin = (char *)cur_mac;
origin_mac = (char *)cur_mac;
while (*begin) {
end = strchr(begin, ' ');
if (!end) {
memset(one_mac, 0, sizeof(one_mac));
if (strlen(begin) < 18) {
memcpy(one_mac, begin, strlen(begin));
if(origin_mac){
new_buf = delete_one_mac(origin_mac, one_mac);
}
if (origin_mac && origin_mac != cur_mac) {
free(origin_mac);
}
origin_mac = new_buf;
}
break;
}
memset(one_mac, 0, sizeof(one_mac));
if (end - begin < 18) {
memcpy(one_mac, begin, end - begin);
new_buf = delete_one_mac(origin_mac, one_mac);
if (origin_mac && origin_mac != cur_mac) {
free(origin_mac);
}
origin_mac = new_buf;
}
begin = end + 1;
}
return new_buf;
}
static int wifi_add_MAC_filter_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_mac_setting[ARRAY_SIZE(wifi_MAC_filter_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
const char *macfilter_mode = NULL;
void *tb_wireless = NULL;
int ret_val = 0, dev_index = 0;
char *new_mac_list = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_MAC_filter_pol, ARRAY_SIZE(wifi_MAC_filter_pol), tb_mac_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_mac_setting[ADD_MACLIST_ALLOW] && !tb_mac_setting[ADD_MACLIST_DENY]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
ret_val = parse_wireless_package_info(local_ctx, p, info);
}else {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
}
if (tb_mac_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_mac_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
dev_sec_24G = info->wifi_info[dev_index].ap_2G.device;
dev_sec_5G = info->wifi_info[dev_index].ap_5G.device;
iface_sec_24G = info->wifi_info[dev_index].ap_2G.iface[0];
iface_sec_5G = info->wifi_info[dev_index].ap_5G.iface[0];
/*set Mac filters to 2.4G */
if (dev_sec_24G && iface_sec_24G) {
if (tb_mac_setting[MACFILTER]) {
WIFI_DBG("macfilter %s", blobmsg_get_string(tb_mac_setting[MACFILTER]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
macfilter_mode = (const char *)blobmsg_get_string(tb_mac_setting[MACFILTER]);
} else
macfilter_mode = uci_lookup_option_string(local_ctx, iface_sec_24G, "macfilter");
if (tb_mac_setting[ADD_MACLIST_ALLOW]) {
WIFI_DBG("add MACFILTER ALLOW 2.4G is %s",
blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]));
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "maclist_allow");
if (option_value) {
new_mac_list =
add_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]));
}
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_allow";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]);
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
WIFI_DBG("option_value 2.4G is %s", option_value);
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]);
}
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]);
uci_set(local_ctx, &ptr);
}
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
if (tb_mac_setting[ADD_MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 2.4G is %s",
blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_deny";
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "maclist_deny");
if (option_value) {
new_mac_list =
add_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
}
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]);
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
WIFI_DBG("deny list %s ", new_mac_list);
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]);
WIFI_DBG("deny list %s ", blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
}
uci_set(local_ctx, &ptr);
}
}
}
/*Set MAC filters 5G */
if (dev_sec_5G && iface_sec_5G) {
if (tb_mac_setting[MACFILTER]) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
macfilter_mode = (const char *)blobmsg_get_string(tb_mac_setting[MACFILTER]);
} else
macfilter_mode = uci_lookup_option_string(local_ctx, iface_sec_5G, "macfilter");
if (tb_mac_setting[ADD_MACLIST_ALLOW]) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "maclist_allow");
if (option_value) {
new_mac_list =
add_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]));
}
WIFI_DBG("setting MACFILTER ALLOW 5G is %s",
blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]));
ptr.option = "maclist_allow";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]);
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]);
}
uci_set(local_ctx, &ptr);
}
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
if (tb_mac_setting[ADD_MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 5G is %s",
blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist_deny";
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "maclist_deny");
if (option_value) {
new_mac_list =
add_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
}
WIFI_DBG("setting MACFILTER DENY 5G is %s",
blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]));
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]);
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = blobmsg_get_string(tb_mac_setting[ADD_MACLIST_DENY]);
}
uci_set(local_ctx, &ptr);
}
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
if (p) {
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
if (dev_sec_24G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_24G->e.name);
else if (dev_sec_5G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_5G->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
//my_system("/etc/init.d/mwlan reload");
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
my_system(system_buf);
WIFI_DBG("wifi restart\r\n");
}
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
static int wifi_del_MAC_filter_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_mac_setting[ARRAY_SIZE(wifi_MAC_filter_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *dev_sec_24G = NULL, *dev_sec_5G = NULL;
struct uci_section *iface_sec_24G = NULL, *iface_sec_5G = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
const char *option_value = NULL;
const char *macfilter_mode = NULL;
void *tb_wireless = NULL;
int ret_val = 0, dev_index = 0;
char *new_mac_list = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_MAC_filter_pol, ARRAY_SIZE(wifi_MAC_filter_pol), tb_mac_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_mac_setting[DEL_MACLIST_ALLOW] && !tb_mac_setting[DEL_MACLIST_DENY]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
if (p) {
WIFI_DBG("load wireless config successfully");
ret_val = parse_wireless_package_info(local_ctx, p, info);
}else {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
}
if (tb_mac_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_mac_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
dev_sec_24G = info->wifi_info[dev_index].ap_2G.device;
dev_sec_5G = info->wifi_info[dev_index].ap_5G.device;
iface_sec_24G = info->wifi_info[dev_index].ap_2G.iface[0];
dev_sec_5G = info->wifi_info[dev_index].ap_5G.iface[0];
/*set Mac filters to 2.4G */
if (dev_sec_24G && iface_sec_24G) {
if (tb_mac_setting[MACFILTER]) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
macfilter_mode = (const char *)blobmsg_get_string(tb_mac_setting[MACFILTER]);
} else
macfilter_mode = uci_lookup_option_string(local_ctx, iface_sec_24G, "macfilter");
if (tb_mac_setting[DEL_MACLIST_ALLOW]) {
WIFI_DBG("del MACFILTER ALLOW 2.4G is %s",
blobmsg_get_string(tb_mac_setting[DEL_MACLIST_ALLOW]));
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "maclist_allow");
if (option_value) {
new_mac_list =
del_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[ADD_MACLIST_ALLOW]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_allow";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
}
}
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
if (tb_mac_setting[DEL_MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 2.4G is %s",
blobmsg_get_string(tb_mac_setting[DEL_MACLIST_DENY]));
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "maclist_deny");
if (option_value) {
new_mac_list =
del_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[DEL_MACLIST_DENY]));
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist_deny";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
}
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
}
}
/*Set MAC filters 5G */
if (dev_sec_5G && iface_sec_5G) {
if (tb_mac_setting[MACFILTER]) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "macfilter";
ptr.value = blobmsg_get_string(tb_mac_setting[MACFILTER]);
uci_set(local_ctx, &ptr);
macfilter_mode = (const char *)blobmsg_get_string(tb_mac_setting[MACFILTER]);
} else
macfilter_mode = uci_lookup_option_string(local_ctx, iface_sec_5G, "macfilter");
if (tb_mac_setting[DEL_MACLIST_ALLOW]) {
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "maclist_allow");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist_allow";
new_mac_list =
del_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[DEL_MACLIST_ALLOW]));
if (new_mac_list) {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "allow") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
}
}
if (tb_mac_setting[DEL_MACLIST_DENY]) {
WIFI_DBG("setting MACFILTER DENY 5G is %s",
blobmsg_get_string(tb_mac_setting[DEL_MACLIST_DENY]));
option_value = uci_lookup_option_string(local_ctx, iface_sec_5G, "maclist_deny");
if (option_value) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist_deny";
new_mac_list =
del_multi_mac(option_value, blobmsg_get_string(tb_mac_setting[DEL_MACLIST_DENY]));
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (macfilter_mode && strcmp(macfilter_mode, "deny") == 0) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
ptr.option = "maclist";
if (new_mac_list) {
ptr.value = new_mac_list;
} else {
ptr.value = " ";
}
uci_set(local_ctx, &ptr);
if (new_mac_list) {
free(new_mac_list);
new_mac_list = NULL;
}
}
}
}
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
if (p) {
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
if ( dev_sec_24G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_24G->e.name);
else if (dev_sec_5G)
snprintf(dev_name, sizeof(dev_name), "%s",dev_sec_5G->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
//my_system("/etc/init.d/mwlan reload");
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
my_system(system_buf);
WIFI_DBG("wifi restart\r\n");
}
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
#define BUFSIZE 512
static int wifi_get_WPS_disable_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct uci_package *p = NULL;
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_section *dev_sec_24G = NULL;
struct uci_section *iface_sec_24G = NULL;
const char *option_value = NULL;
int ret_val = 0;
void *tb_wireless = NULL;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0) {
ret_val = 1;
goto EXIT;
}
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
/*get basic info -- 2.4G begin */
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WIFI_SECTION_DEVICE) == 0) {
WIFI_DBG("find one wifi-device, section name is %s", uci_sec->e.name);
option_value = uci_lookup_option_string(local_ctx, uci_sec, "hwmode");
if (option_value) {
WIFI_DBG("hwmode value is %s", option_value);
if (!strchr(option_value, 'a')) {
dev_sec_24G = uci_sec;
}
}
} else if (strcmp(uci_sec->type, WIFI_SECTION_IFACE) == 0) {
option_value = uci_lookup_option_string(local_ctx, uci_sec, "device");
if (option_value) {
WIFI_DBG("device value is %s", option_value);
if (dev_sec_24G && dev_sec_24G->e.name) {
if (strcmp(option_value, dev_sec_24G->e.name) == 0) {
WIFI_DBG("find wifi-iface(24G)");
iface_sec_24G = uci_sec;
}
}
}
}
}
/*form response blobmsg */
if (dev_sec_24G && iface_sec_24G) {
option_value = uci_lookup_option_string(local_ctx, iface_sec_24G, "wps_pushbutton");
if (option_value) {
WIFI_DBG("wps_pushbutton is %s", option_value);
blobmsg_add_string(&wifi_buf, "wps_enable", option_value);
} else {
blobmsg_add_string(&wifi_buf, "wps_enable", "0");
}
}
EXIT:
if (tb_wireless) {
blobmsg_close_table(&wifi_buf, tb_wireless);
}
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
enum {
WPS_ENABLE,
WPS_PIN,
WPS_IFACE_INDEX,
WPS_5G_PREFER
};
static const struct blobmsg_policy wifi_WPS_set_disable_pol[] = {
[WPS_ENABLE] = {
.name = "wps_enable",
.type = BLOBMSG_TYPE_STRING,
},
[WPS_PIN] = {
.name = "wps_pin",
.type = BLOBMSG_TYPE_STRING,
},
[WPS_IFACE_INDEX] = {
.name = "wifi_iface_index",
.type = BLOBMSG_TYPE_STRING,
},
[WPS_5G_PREFER] = {
.name = "wifi_5g_prefer",
.type = BLOBMSG_TYPE_STRING,
},
};
static int wifi_set_WPS_disable_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct uci_package *p = NULL;
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_section *dev_sec_5G = NULL;
struct uci_section *dev_sec_24G = NULL;
struct uci_section *iface_sec_24G = NULL;
struct uci_section *iface_sec_5G = NULL;
const char *option_value = NULL;
int ret_val = 1;
void *tb_wireless = NULL;
struct uci_ptr ptr;
struct blob_attr *tb_wps_setting[ARRAY_SIZE(wifi_WPS_set_disable_pol)];
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_WPS_set_disable_pol, ARRAY_SIZE(wifi_WPS_set_disable_pol), tb_wps_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_wps_setting[WPS_ENABLE]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WIFI_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WIFI_PACKAGE_NAME, &p);
}
if (p) {
WIFI_DBG("load wireless config successfully");
} else {
ret_val = 1;
goto EXIT;
}
/*get basic info -- 2.4G begin */
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WIFI_SECTION_DEVICE) == 0) {
WIFI_DBG("find one wifi-device, section name is %s", uci_sec->e.name);
option_value = uci_lookup_option_string(local_ctx, uci_sec, "hwmode");
if (option_value) {
WIFI_DBG("hwmode value is %s", option_value);
if (strchr(option_value, 'a')) {
dev_sec_5G = uci_sec;
} else {
dev_sec_24G = uci_sec;
}
}
} else if (strcmp(uci_sec->type, WIFI_SECTION_IFACE) == 0) {
option_value = uci_lookup_option_string(local_ctx, uci_sec, "device");
if (option_value) {
WIFI_DBG("device value is %s", option_value);
if (dev_sec_24G && dev_sec_24G->e.name) {
if (strcmp(option_value, dev_sec_24G->e.name) == 0) {
WIFI_DBG("find wifi-iface(24G)");
iface_sec_24G = uci_sec;
}
}
if (dev_sec_5G && dev_sec_5G->e.name) {
if (strcmp(option_value, dev_sec_5G->e.name) == 0) {
WIFI_DBG("find wifi-iface(5G)");
iface_sec_5G = uci_sec;
}
}
}
}
}
/*set Mac filters to 2.4G */
if (dev_sec_24G && iface_sec_24G) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
if (tb_wps_setting[WPS_ENABLE]) {
ret_val = 0;
WIFI_DBG("setting wps enable is %s", blobmsg_get_string(tb_wps_setting[WPS_ENABLE]));
ptr.option = "wps_pushbutton";
ptr.value = blobmsg_get_string(tb_wps_setting[WPS_ENABLE]);
uci_set(local_ctx, &ptr);
}
}
/*Set MAC filters 5G */
if (dev_sec_5G && iface_sec_5G) {
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_5G;
memset(&ptr, 0, sizeof(ptr));
ptr.p = p;
ptr.s = iface_sec_24G;
if (tb_wps_setting[WPS_ENABLE]) {
ret_val = 0;
WIFI_DBG("setting wps enable is %s", blobmsg_get_string(tb_wps_setting[WPS_ENABLE]));
ptr.option = "wps_pushbutton";
ptr.value = blobmsg_get_string(tb_wps_setting[WPS_ENABLE]);
uci_set(local_ctx, &ptr);
}
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
char system_buf[50] = { 0 };
char dev_name[20] = { 0 };
if ( dev_sec_24G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_24G->e.name);
else if ( dev_sec_5G)
snprintf(dev_name, sizeof(dev_name), "%s", dev_sec_5G->e.name);
else
snprintf(dev_name, sizeof(dev_name), "AP0_24G");
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
int com_ret = uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
WIFI_DBG("commit ret is %d", com_ret);
//my_system("/etc/init.d/mwlan reload");
snprintf(system_buf, sizeof(system_buf), "/etc/init.d/mwlan reload %s", dev_name);
my_system(system_buf);
WIFI_DBG("wifi restart\r\n");
} else {
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
static int wifi_call_WPS_PBC_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
int ret_val = 1;
void *tb_wireless = NULL;
char in_buf[64] = { 0 };
int ap_index = 0;
int wps_5g_prefer = 0;
struct wireless_info *info = &g_wireless_info;
struct blob_attr *tb_wps_setting[ARRAY_SIZE(wifi_WPS_set_disable_pol)];
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
if (blobmsg_parse
(wifi_WPS_set_disable_pol, ARRAY_SIZE(wifi_WPS_set_disable_pol), tb_wps_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_wps_setting[WPS_IFACE_INDEX]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (tb_wps_setting[WPS_5G_PREFER]) {
wps_5g_prefer = atoi(blobmsg_get_string(tb_wps_setting[WPS_5G_PREFER]));
}
WIFI_DBG("iface index %s, wps_5g_prefer %d, wfi_5g_index %d", blobmsg_get_string(tb_wps_setting[WPS_IFACE_INDEX]), wps_5g_prefer, info->wifi_5g_index);
ap_index = atoi(blobmsg_get_string(tb_wps_setting[WPS_IFACE_INDEX]));
memset(&g_wps_info[ap_index], 0, sizeof(struct wps_conn_info));
memset(&g_wps_conn_ctx, 0, sizeof(struct wps_conn_ctx));
if (wps_5g_prefer == 1)
{
if (info->wifi_5g_index == WIFI_AP0 || info->wifi_5g_index == WIFI_AP1)
{
WIFI_DBG("current wifi status %d for AP %d", wifi_status[info->wifi_5g_index], info->wifi_5g_index);
if (wifi_status[info->wifi_5g_index] == WIFI_READY)
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pbc", get_wireless_ifname(info->wifi_5g_index));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
else
{
g_wps_conn_ctx.state = WPS_STATE_5G_PREFER;
g_wps_conn_ctx.method = 0;
g_wps_conn_ctx.ap_5g_index = info->wifi_5g_index;
g_wps_conn_ctx.ap_24g_index = info->wifi_24g_index;
g_wps_conn_ctx.ap_index = info->wifi_5g_index;
}
}
else
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pbc", get_wireless_ifname(info->wifi_24g_index));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
}
}
}
else
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pbc", get_wireless_ifname(ap_index));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "wps_call_pbc_result", "OK");
} else {
blobmsg_add_string(&wifi_buf, "wps_call_pbc_result", "FAIL");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
static int wifi_call_WPS_PIN_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
int ret_val = 0;
void *tb_wireless = NULL;
char in_buf[64] = { 0 };
int ap_index = 0;
int wps_5g_prefer = 0;
struct wireless_info *info = &g_wireless_info;
UNUSESET(obj);
UNUSESET(method);
struct blob_attr *tb_wps_setting[ARRAY_SIZE(wifi_WPS_set_disable_pol)];
if (blobmsg_parse
(wifi_WPS_set_disable_pol, ARRAY_SIZE(wifi_WPS_set_disable_pol), tb_wps_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_wps_setting[WPS_PIN]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_wps_setting[WPS_IFACE_INDEX]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (tb_wps_setting[WPS_5G_PREFER]) {
wps_5g_prefer = atoi(blobmsg_get_string(tb_wps_setting[WPS_5G_PREFER]));
}
WIFI_DBG("wps pin is %s, iface index %s, wps_5g_prefer %d, wifi_5g_index %d", blobmsg_get_string(tb_wps_setting[WPS_PIN]),
blobmsg_get_string(tb_wps_setting[WPS_IFACE_INDEX]), wps_5g_prefer, info->wifi_5g_index);
ap_index = atoi(blobmsg_get_string(tb_wps_setting[WPS_IFACE_INDEX]));
/*force to clear the wps status*/
memset(&g_wps_info[ap_index], 0, sizeof(struct wps_conn_info));
memset(&g_wps_conn_ctx, 0, sizeof(struct wps_conn_ctx));
if (wps_5g_prefer == 1)
{
if (info->wifi_5g_index == WIFI_AP0 || info->wifi_5g_index == WIFI_AP1)
{
WIFI_DBG("current wifi status %d for AP %d", wifi_status[info->wifi_5g_index], info->wifi_5g_index);
if (wifi_status[info->wifi_5g_index] == WIFI_READY)
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pin any %s", get_wireless_ifname(info->wifi_5g_index), blobmsg_get_string(tb_wps_setting[WPS_PIN]));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
else
{
g_wps_conn_ctx.state = WPS_STATE_5G_PREFER;
g_wps_conn_ctx.method = 1;
strncpy(g_wps_conn_ctx.pin, blobmsg_get_string(tb_wps_setting[WPS_PIN]), sizeof(g_wps_conn_ctx.pin) - 1);
g_wps_conn_ctx.ap_5g_index = info->wifi_5g_index;
g_wps_conn_ctx.ap_24g_index = info->wifi_24g_index;
g_wps_conn_ctx.ap_index = info->wifi_5g_index;
}
}
else
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pin any %s", get_wireless_ifname(info->wifi_24g_index), blobmsg_get_string(tb_wps_setting[WPS_PIN]));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
}
}
}
else
{
snprintf(in_buf, sizeof(in_buf), "hostapd_cli -i %s wps_pin any %s", get_wireless_ifname(ap_index), blobmsg_get_string(tb_wps_setting[WPS_PIN]));
ret_val = my_system(in_buf);
if (ret_val != 0)
ret_val = UBUS_STATUS_INVALID_COMMAND;
}
EXIT:
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "wps_call_pin_result", "OK");
} else {
blobmsg_add_string(&wifi_buf, "wps_call_pin_result", "FAIL");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
static int wifi_call_WPS_status_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
void *tb_wireless = NULL;
int ap_index = get_current_ap_index();
if (g_wps_conn_ctx.state > WPS_STATE_INIT)
{
ap_index = g_wps_conn_ctx.ap_index;
}
WIFI_DBG("wps_status %d, peer mac %s, ap_index %d", g_wps_info[ap_index].wps_status, g_wps_info[ap_index].peer_mac, ap_index);
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
blobmsg_add_u32(&wifi_buf, "wps_status", g_wps_info[ap_index].wps_status);
blobmsg_add_string(&wifi_buf, "peer_mac", g_wps_info[ap_index].peer_mac);
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
return 0;
}
static int wifi_call_WPS_cancel_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
FILE *read_fp = NULL;
char *read_buf = NULL;
int char_read = 0;
int ret_val = 1;
void *tb_wireless = NULL;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
read_fp = popen("hostapd_cli wps_cancel", "r");
if (read_fp) {
read_buf = malloc(BUFSIZE);
if (read_buf) {
memset(read_buf, 0, BUFSIZE);
char_read = fread(read_buf, sizeof(char), BUFSIZE - 1, read_fp);
if (char_read > 0) {
WIFI_DBG("size %d read_buf %s", char_read,read_buf);
if (strstr(read_buf, "OK")) {
ret_val = 0;
}
}
free(read_buf);
read_buf = NULL;
}
pclose(read_fp);
}
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
blobmsg_add_string(&wifi_buf, "wps_call_cancel_result", "OK");
} else {
blobmsg_add_string(&wifi_buf, "wps_call_cancel_result", "FAIL");
}
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
blob_buf_free(&wifi_buf);
WIFI_DBG("done with ret %d", ret_val);
return ret_val;
}
enum {
AUTO_OFF_ENABLE = 1,
AUTO_OFF_TIMEOUT,
};
static const struct blobmsg_policy wifi_auto_off_setting_pol[] = {
[WIFI_DEVICE] = {
.name = "wifi_device",
.type = BLOBMSG_TYPE_STRING
},
[AUTO_OFF_ENABLE] = {
.name = "auto_off_enable",
.type = BLOBMSG_TYPE_STRING,
},
[AUTO_OFF_TIMEOUT] = {
.name = "auto_off_timeout",
.type = BLOBMSG_TYPE_STRING,
},
};
static int wifi_get_auto_off_settings_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct wireless_info *info = &g_wireless_info;
void *tb_wireless = NULL, *tb_dev = NULL;
char buf[32];
int i;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (info->n_dev > MAX_WIFI_CHIP_NUM) {
info->n_dev = MAX_WIFI_CHIP_NUM;
}
blobmsg_add_u32(&wifi_buf, "wireless_num", (unsigned int)info->n_dev);
for (i = 0; i < info->n_dev; i++) {
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf) - 1, "AP%d", i);
tb_dev = blobmsg_open_table(&wifi_buf, buf);
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d", info->wifi_info[i].auto_off_enable);
blobmsg_add_string(&wifi_buf, "auto_off_enable", buf);
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d", info->wifi_info[i].auto_off_timeout);
blobmsg_add_string(&wifi_buf, "auto_off_timeout", buf);
blobmsg_close_table(&wifi_buf, tb_dev);
WIFI_DBG("AP%d, auto_off_enable %d, auto_off_timeout %d\n", i, info->wifi_info[i].auto_off_enable, info->wifi_info[i].auto_off_timeout);
}
if (tb_wireless) {
blobmsg_close_table(&wifi_buf, tb_wireless);
}
ubus_send_reply(ctx, req, wifi_buf.head);
WIFI_DBG("done");
blob_buf_free(&wifi_buf);
return 0;
}
static int wifi_set_auto_off_settings_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct blob_attr *tb_auto_off_setting[ARRAY_SIZE(wifi_auto_off_setting_pol)];
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
struct wireless_info *info = &g_wireless_info;
void *tb_wireless = NULL;
int ret_val = 0;
char dev_name[MAX_DEV_NAME_LEN] = { 0 };
int dev_index;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(wifi_auto_off_setting_pol, ARRAY_SIZE(wifi_auto_off_setting_pol), tb_auto_off_setting, blob_data(msg),
blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!tb_auto_off_setting[AUTO_OFF_ENABLE] && !tb_auto_off_setting[AUTO_OFF_TIMEOUT]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/wireless */
local_ctx = uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0) {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
if (tb_auto_off_setting[WIFI_DEVICE]) {
dev_index = atoi(blobmsg_get_string(tb_auto_off_setting[WIFI_DEVICE]));
} else {
dev_index = 0;
}
snprintf(dev_name, sizeof(dev_name), "AP%d", dev_index);
uci_sec = uci_lookup_section(local_ctx, p, dev_name);
if (!uci_sec) {
uci_add_section(local_ctx, p, WIFI_SECTION_SETTING, &uci_sec);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.value = dev_name;
uci_rename(local_ctx, &ptr);
}
if (uci_sec) {
if (tb_auto_off_setting[AUTO_OFF_ENABLE]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto_off_enable";
ptr.value = blobmsg_get_string(tb_auto_off_setting[AUTO_OFF_ENABLE]);
if (!strcmp(dev_name, "AP0"))
info->wifi_info[WIFI_AP0].auto_off_enable= atoi(ptr.value);
else if (!strcmp(dev_name, "AP1"))
info->wifi_info[WIFI_AP1].auto_off_enable= atoi(ptr.value);
else {
WIFI_ERR("unsupported device %s", dev_name);
}
uci_set(local_ctx, &ptr);
}
if (tb_auto_off_setting[AUTO_OFF_TIMEOUT]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto_off_timeout";
ptr.value = blobmsg_get_string(tb_auto_off_setting[AUTO_OFF_TIMEOUT]);
if (!strcmp(dev_name, "AP0"))
info->wifi_info[WIFI_AP0].auto_off_timeout= atoi(ptr.value);
else if (!strcmp(dev_name, "AP1"))
info->wifi_info[WIFI_AP1].auto_off_timeout= atoi(ptr.value);
else {
WIFI_ERR("unsupported device %s", dev_name);
}
uci_set(local_ctx, &ptr);
}
WIFI_DBG("dev_name %s, auto_off_enable %s, auto_off_timeout %s\n", dev_name,
blobmsg_get_string(tb_auto_off_setting[AUTO_OFF_ENABLE]), blobmsg_get_string(tb_auto_off_setting[AUTO_OFF_TIMEOUT]));
}
set_current_ap_index(dev_index);
EXIT:
WIFI_ERR("dev_name %s, active_clients %d, auto_off_enable %d", dev_name, active_clients[WIFI_AP0], info->wifi_info[WIFI_AP0].auto_off_enable);
if (ret_val == 0) {
if ((info->wifi_info[WIFI_AP0].auto_off_enable == 1)) {
if (!strcmp(dev_name, "AP0")) {
if (active_clients[WIFI_AP0] == 0)
set_wifi_auto_off_on();
}
else if (!strcmp(dev_name, "AP1")) {
if (active_clients[WIFI_AP1] == 0)
set_wifi_auto_off_on();
}
} else if (info->wifi_info[WIFI_AP0].auto_off_enable == 0) {
shutdown_wifi_auto_off();
}
}
blobmsg_buf_init(&wifi_buf);
tb_wireless = blobmsg_open_table(&wifi_buf, "wireless");
if (ret_val == 0) {
uci_commit(local_ctx, &p, false);
free_wifi_uci_ctx();
blobmsg_add_string(&wifi_buf, "setting_response", "OK");
} else
blobmsg_add_string(&wifi_buf, "setting_response", "ERROR");
blobmsg_close_table(&wifi_buf, tb_wireless);
ubus_send_reply(ctx, req, wifi_buf.head);
WIFI_DBG("done");
blob_buf_free(&wifi_buf);
return 0;
}
static const struct ubus_method wifi_methods[] = {
//UBUS_METHOD("WIFI_WATCH", wifi_watch, NULL),
UBUS_METHOD_NOARG("wifi_get_basic_info", wifi_get_basic_info_cb),
UBUS_METHOD_NOARG("wifi_get_detail", wifi_get_detail_info_cb),
UBUS_METHOD("wifi_set_basic_info", wifi_set_basic_info_cb, wifi_setting_pol),
UBUS_METHOD("wifi_set_2.4g", wifi_set_all_setting_cb, wifi_setting_pol),
UBUS_METHOD("wifi_set_5g", wifi_set_all_setting_cb, wifi_setting_pol),
UBUS_METHOD("wifi_set_all", wifi_set_all_setting_cb, wifi_setting_pol),
UBUS_METHOD_NOARG("wifi_get_mac_filter", wifi_get_MAC_filter_cb),
UBUS_METHOD("wifi_set_mac_filter", wifi_set_MAC_filter_cb, wifi_setting_pol),
UBUS_METHOD("wifi_add_mac_filter", wifi_add_MAC_filter_cb, wifi_setting_pol),
UBUS_METHOD("wifi_del_mac_filter", wifi_del_MAC_filter_cb, wifi_setting_pol),
UBUS_METHOD_NOARG("wifi_get_wps_disable", wifi_get_WPS_disable_cb),
UBUS_METHOD_NOARG("wifi_set_wps_disable", wifi_set_WPS_disable_cb),
UBUS_METHOD_NOARG("wifi_call_wps_pbc", wifi_call_WPS_PBC_cb),
UBUS_METHOD_NOARG("wifi_call_wps_cancle", wifi_call_WPS_cancel_cb),
UBUS_METHOD("wifi_call_wps_pin", wifi_call_WPS_PIN_cb, wifi_WPS_set_disable_pol),
UBUS_METHOD_NOARG("wifi_get_auto_off_setting", wifi_get_auto_off_settings_cb),
UBUS_METHOD("wifi_set_auto_off_setting", wifi_set_auto_off_settings_cb, wifi_auto_off_setting_pol),
UBUS_METHOD_NOARG("wifi_call_wps_status", wifi_call_WPS_status_cb),
};
static struct ubus_object_type wifi_object_type = UBUS_OBJECT_TYPE("wireless", wifi_methods);
static struct ubus_object wifi_service_object = {
.name = "wireless",
.type = &wifi_object_type,
.methods = wifi_methods,
.n_methods = ARRAY_SIZE(wifi_methods),
};
enum {
CLIENTS_NUM_INT,
WIFI_STATUS_STR,
WIFI_CLIENTS_NUM_STR,
WIFI_AP_INDEX_INT,
};
static const struct blobmsg_policy stat_notify_pol[] = {
[CLIENTS_NUM_INT] = {
.name = "clients_num",
.type = BLOBMSG_TYPE_STRING,
},
[WIFI_STATUS_STR] = {
.name = "wifi_status",
.type = BLOBMSG_TYPE_STRING,
},
[WIFI_CLIENTS_NUM_STR] = {
.name = "wifi_clients_num",
.type = BLOBMSG_TYPE_STRING,
},
[WIFI_AP_INDEX_INT] = {
.name = "ap_index",
.type = BLOBMSG_TYPE_INT32,
},
};
static int
stat_notify_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
int ret_val = 0;
struct blob_attr *stat_msg[ARRAY_SIZE(stat_notify_pol)];
struct wireless_info *info = &g_wireless_info;
int clients_num = 0;
char *status_str = 0;
int ap_index = 0;
UNUSESET(req);
UNUSESET(ctx);
UNUSESET(obj);
WIFI_DBG("method :%s ", method);
if (blobmsg_parse(stat_notify_pol, ARRAY_SIZE(stat_notify_pol), stat_msg, blob_data(msg), blob_len(msg)) != 0) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
return ret_val;
}
if ((strcmp(method, "wifi_clients_change") == 0) && stat_msg[WIFI_CLIENTS_NUM_STR]) {
clients_num = atoi(blobmsg_get_string(stat_msg[WIFI_CLIENTS_NUM_STR]));
ap_index = blobmsg_get_u32(stat_msg[WIFI_AP_INDEX_INT]);
if (ap_index >= MAX_WIFI_CHIP_NUM) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
return ret_val;
}
WIFI_DBG("wifi_clients_change,active_clients %d, wifi_clients_num %d, ap_index %d\n",
active_clients[ap_index], clients_num, ap_index);
if (info->wifi_info[ap_index].auto_off_enable) {
if ((active_clients[ap_index] > 0) &&
(clients_num == 0)) {
set_wifi_auto_off_on();
} else if ((active_clients[ap_index] == 0) &&
(clients_num > 0)) {
shutdown_wifi_auto_off();
}
}
active_clients[ap_index] = clients_num;
} else if ((strcmp(method, "wifi_status_change") == 0) && stat_msg[WIFI_STATUS_STR]) {
status_str = blobmsg_get_string(stat_msg[WIFI_STATUS_STR]);
ap_index = blobmsg_get_u32(stat_msg[WIFI_AP_INDEX_INT]);
if (ap_index >= MAX_WIFI_CHIP_NUM) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
return ret_val;
}
WIFI_DBG("wifi_status_change, active_clients %d, wifi_status_str %s, wifi_status %d, ap_index %d\n",
active_clients[ap_index], status_str, wifi_status[ap_index], ap_index);
if (strcmp(status_str, "start") == 0) {
wifi_status[ap_index] = WIFI_START;
} else if (strcmp(status_str, "ready") == 0) {
wifi_status[ap_index] = WIFI_READY;
if ((active_clients[ap_index] == 0) &&
(info->wifi_info[ap_index].auto_off_enable == 1)) {
set_wifi_auto_off_on();
}
} else if (strcmp(status_str, "off") == 0) {
/* For WIFI restart, report status is READY->START->OFF */
unsigned int obj_id = 0;
wifi_status[ap_index] = WIFI_OFF;
/* query again */
wireless_lookup_hostapd_id(&obj_id, ap_index);
if (info->wifi_info[ap_index].auto_off_enable && wifi_status[ap_index] == WIFI_OFF) {
shutdown_wifi_auto_off();
}
}
WIFI_DBG("wifi_status_change, wifi_status %d\n",
wifi_status[ap_index]);
} else if (strcmp(method, "ubus_object_add") == 0) {
ap_index = blobmsg_get_u32(stat_msg[WIFI_AP_INDEX_INT]);
WIFI_DBG("ubus_object_add, will listen to hostapd.wlan%d", ap_index);
if (ap_index >= MAX_WIFI_CHIP_NUM) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
return ret_val;
}
if (wireless_listen_to_hostapd(ctx, ap_index) == UBUS_STATUS_OK) {
WIFI_DBG("listen hostapd.wlan%d event ready");
} else {
WIFI_DBG("listen hostapd.wlan%d event not ready");
}
}
return ret_val;
}
/*listen events from hostapd.uap0*/
static struct ubus_subscriber stat_event;
static int listen_to_statistics_ser(struct ubus_context *ctx)
{
unsigned int id;
int ret;
if (ubus_lookup_id(ctx, "statistics", &id)) {
return -1;
}
stat_event.cb = stat_notify_event_cb;
ret = ubus_subscribe(ctx, &stat_event, id);
WIFI_DBG("watching object %08x: %s", id, ubus_strerror(ret));
return ret;
}
/*============================================
Notify other services that the SSID has been changed from WEBUI
format
{
"id":"0",
"new_ssid":""
}
============================================*/
enum {
SSID_CHANGE_NOTIFY_ID,
};
static void ssid_change_notify_complete_cb(struct ubus_request *req, int ret)
{
UNUSESET(req);
UNUSESET(ret);
return;
}
int ssid_change_notify(struct ubus_context *ctx, char *new_ssid)
{
struct ubus_notify_request nreq;
if (!new_ssid)
return 0;
blobmsg_buf_init(&wifi_buf);
blobmsg_add_u32(&wifi_buf, "id", SSID_CHANGE_NOTIFY_ID);
blobmsg_add_string(&wifi_buf, "new_ssid", new_ssid);
if (ubus_notify_async(ctx, &wifi_service_object, "ssid_change", wifi_buf.head, &nreq))
return 0;
blob_buf_free(&wifi_buf);
nreq.complete_cb = (void *)&ssid_change_notify_complete_cb;
ubus_complete_request(ctx, &nreq.req, 100);
return 0;
}
static void obj_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
const char *type, struct blob_attr *msg)
{
static const struct blobmsg_policy policy = {
"path", BLOBMSG_TYPE_STRING
};
struct blob_attr *attr;
const char *path;
char *hostapd_name = NULL;
int i = 0;
UNUSESET(ev);
if (strcmp(type, "ubus.object.add") != 0)
return;
blobmsg_parse(&policy, 1, &attr, blob_data(msg), blob_len(msg));
if (!attr)
return;
path = blobmsg_data(attr);
WIFI_DBG("obj:%s connect", path);
//obj_cm_add_ev(ctx, (char *)path);
if (strcmp(path, CHARGER_UBUS_ID) == 0) {
/*charger connects to ubusd*/
listen_to_charger_ser(ctx);
invoke_to_get_charger_data(ctx);
WIFI_DBG("charger ready");
}
for ( i = 0; i < MAX_WIFI_CHIP_NUM; i++) {
hostapd_name = get_hostapd_obj_name(i);
if (hostapd_name && strcmp(path, hostapd_name) == 0) {
/*hostapd connects to ubusd*/
if (wireless_listen_to_hostapd(ctx, i) == UBUS_STATUS_OK) {
WIFI_DBG("wifi%d event ready", i);
}
else {
WIFI_DBG("wifi%d event not ready",i);
}
}
}
return;
}
/*=========================================
* If MAC address exists in UCI and /NVM/wifi_addr is empty
* Read MAC and write it to /NVM/wifi_addr
*==========================================*/
#define WIFIMAC_FILE "/NVM/wifi_addr"
static int read_mac_from_uci(void)
{
FILE *fp = NULL;
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *opt_val = NULL;
fp = fopen(WIFIMAC_FILE, "r+");
if (fp) {
if (!feof(fp)) //not empty file
return 0;
}
if (!fp) {
//file is not exists,create file
fp = fopen(WIFIMAC_FILE, "a+");
}
if (fp) {
//read MAC from UCI
/*load /etc/config/wireless */
local_ctx = (struct uci_context *)uci_wifi_ctx_get();
if (!local_ctx) {
assert(0);
}
if (wireless_load_config_package(local_ctx, WIFI_PACKAGE_NAME, &p) != 0) {
return -1;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "wifi-iface") == 0) {
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "macaddr");
if (opt_val) {
fputs(opt_val, fp);
break;
}
}
}
}
if (fp)
fclose(fp);
return 0;
}
#define WIFI_DETECT_FILE "/etc/config/wireless"
#define WIFI_DETECT_FILE_PCIE "/tmp/wifi_ok"
#define WIFI_DETECT_FILE_PCIE_AP0 "/tmp/wifi_ok/AP0_2G"
#define WIFI_DETECT_FILE_PCIE_AP1 "/tmp/wifi_ok/AP1_5G"
static int is_wifi_card_detected(void)
{
int ret = 0;
if (access(WIFI_DETECT_FILE, F_OK) < 0) {
WIFI_ERR("WIFI not exist or init error");
} else if (access(WIFI_DETECT_FILE_PCIE, F_OK) < 0) {
WIFI_ERR("WIFI not exist or init error");
} else {
if (access(WIFI_DETECT_FILE_PCIE_AP0, F_OK) == 0)
ret |= 0x01;
if (access(WIFI_DETECT_FILE_PCIE_AP1, F_OK) == 0)
ret |= 0x02;
}
return ret;
}
void wifi_server_main(void)
{
struct wireless_info *info = &g_wireless_info;
int ret;
unsigned int id;
int i = 0;
#if 1
struct ubus_event_handler add_ev;
memset(&add_ev, 0, sizeof(add_ev));
add_ev.cb = obj_add_event_cb;
#endif
wifi_ubus_ctx = applet_ubus_ctx;
ret = is_wifi_card_detected();
if (ret == 0) {
wifi_status[WIFI_AP0] = NO_WIFI;
wifi_status[WIFI_AP1] = NO_WIFI;
}
else
{
if (ret & 0x01 == 0)
wifi_status[WIFI_AP0] = NO_WIFI;
if (ret & 0x02 == 0)
wifi_status[WIFI_AP1] = NO_WIFI;
}
read_mac_from_uci();
ret = ubus_add_object(applet_ubus_ctx, &wifi_service_object);
if (ret)
WIFI_ERR("Failed to add object: %s\n", ubus_strerror(ret));
#if 0
ret = ubus_register_event_handler(applet_ubus_ctx, &add_ev, "ubus.object.add");
if (ret)
WIFI_ERR("register event ubus.object.add error:%d", ret);
#endif
ret = ubus_register_subscriber(applet_ubus_ctx, &stat_event);
if (ret)
WIFI_ERR("Failed to register subscriber: %s", ubus_strerror(ret));
listen_to_statistics_ser(applet_ubus_ctx);
ret = ubus_register_subscriber(applet_ubus_ctx, &charger_event);
if (ret)
WIFI_ERR("Failed to register subscriber: %s", ubus_strerror(ret));
ret = ubus_register_subscriber(applet_ubus_ctx, &hostapd_event_subscriber);
if (ret)
WIFI_ERR("Failed to register subscriber: %s", ubus_strerror(ret));
ret = ubus_register_subscriber(applet_ubus_ctx, &hostapd_wlan1_event_subscriber);
if (ret)
WIFI_ERR("Failed to register subscriber: %s", ubus_strerror(ret));
if (ubus_lookup_id(applet_ubus_ctx, CHARGER_UBUS_ID, &id) == UBUS_STATUS_OK) {
WIFI_ERR("Lookup object aoc aoc SUCCESS");
listen_to_charger_ser(applet_ubus_ctx);
invoke_to_get_charger_data(applet_ubus_ctx);
}
for (i = 0; i < MAX_WIFI_CHIP_NUM; i++)
{
if (wireless_lookup_hostapd_id(&id, i) == 0)
wireless_listen_to_hostapd(applet_ubus_ctx, i);
info->wifi_info[i].auto_off_timeout = MIN_AUTO_OFF_TIMEOUT;
info->wifi_info[i].auto_off_enable = 0;
}
invoke_to_get_client_number(applet_ubus_ctx);
WIFI_ERR("Get clinet number SUCCESS");
init_wifi_settings();
WIFI_ERR("Init wifi setting SUCCESS");
}