Created
February 20, 2023 17:49
-
-
Save legale/526aecb6cbbc096ca64ec22708e3481a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
/* event_struct.h must be included first cause of LIST_HEAD macro used by libevent2 */ | |
#include <event2/event.h> | |
#include <syslog.h> | |
#include <event2/event_struct.h> | |
#include <json-c/json.h> | |
#include <iwinfo.h> /* iwinfo library (package/libiwinfo */ | |
#include "sysinfo.h" | |
#include "config.h" | |
#include "list.h" //double linked list header lib from linux kernel | |
static void parse_line(json_object *root_cur, char *line); | |
static void parse_cfg_json_object(json_object *jso, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete); | |
static void parse_cfg_json_array(json_object *a, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete); | |
static void parse_cfg_json_string(json_object *s, char *buf, size_t buf_len, char **p, bool is_delete); | |
static void parse_cfg_json_boolean(json_object *b, char *buf, size_t buf_len, char **p, bool is_delete); | |
static void parse_cfg_json_int(json_object *i, char *buf, size_t buf_len, char **p, bool is_delete); | |
static void parse_cfg_json_double(json_object *d, char *buf, size_t buf_len, char **p, bool is_delete); | |
static void parse_cfg_json(json_object *val, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete); | |
/** | |
* @brief check if file exists | |
* | |
* @param fname | |
* @return true | |
* @return false | |
*/ | |
bool is_file_exists(const char *fname){ | |
FILE *file; | |
if ((file = fopen(fname, "r"))) | |
{ | |
fclose(file); | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Remove trailing white space characters from string | |
*/ | |
size_t trim_str(char * str){ | |
int index, i; | |
/* Set default index */ | |
index = -1; | |
/* Find last index of non-white space character */ | |
i = 0; | |
while(str[i] != '\0') | |
{ | |
/* somehow char 127 'del' may appear */ | |
if(str[i] != ' ' && str[i] != '\t' && str[i] != '\n') | |
{ | |
index = i; | |
} | |
i++; | |
} | |
/* Mark next character to last non-white space character as NULL */ | |
str[index + 1] = '\0'; | |
return index; | |
} | |
static void parse_cfg_json_object(json_object *jso, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete) { | |
lh_table *table = json_object_get_object(jso); | |
for (struct lh_entry *entry = table->head; entry; entry = entry->next) { | |
char subbuf[4096]; | |
char *subp = subbuf; | |
size_t subbuf_len = buf_len; | |
memcpy(subbuf, buf, buf_len); | |
subp += buf_len; | |
char *key = (char *) entry->k; | |
if (memcmp(key, "section_type", 12)) { | |
const char *pattern = depth == 0 ? "%s" : ".%s"; | |
subbuf_len += snprintf(subp, 4096, pattern, key); | |
} | |
parse_cfg_json((json_object *) entry->v, subbuf, subbuf_len, p, depth + 1, is_delete); | |
} | |
} | |
/** | |
* @brief parse json entry type array | |
* | |
* @param a | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param depth | |
* @param is_delete | |
*/ | |
static void parse_cfg_json_array(json_object *a, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete) { | |
array_list *list = json_object_get_array(a); | |
size_t len = list->length; | |
for (size_t i = 0; i < len; i++) { | |
char subbuf[4096]; | |
char *subp = subbuf; | |
size_t subbuf_len = buf_len; | |
memcpy(subbuf, buf, buf_len); | |
subp += buf_len; | |
subbuf_len += snprintf(subp, 512, "[%zu]", i); | |
json_object *o = (json_object *) list->array[i]; | |
parse_cfg_json(o, subbuf, subbuf_len, p, depth + 1, is_delete); | |
} | |
} | |
/** | |
* @brief parse json entry type string | |
* | |
* @param s | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param is_delete | |
*/ | |
static void parse_cfg_json_string(json_object *s, char *buf, size_t buf_len, char **p, bool is_delete) { | |
memcpy(*p, buf, buf_len); | |
*p += buf_len; | |
if (!is_delete) { | |
const char *string = json_object_get_string(s); | |
*p += snprintf(*p, 512, "=\"%s\"\n", string); | |
} else { | |
**p = '\n'; | |
*p += 1; | |
} | |
} | |
/** | |
* @brief parse json entry type boolean | |
* | |
* @param b | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param is_delete | |
* @return void* | |
*/ | |
static void parse_cfg_json_boolean(json_object *b, char *buf, size_t buf_len, char **p, bool is_delete) { | |
memcpy(*p, buf, buf_len); | |
*p += buf_len; | |
if (!is_delete) { | |
int i = json_object_get_boolean(b); | |
*p += snprintf(*p, 512, "=%d\n", i); | |
} else { | |
**p = '\n'; | |
*p += 1; | |
} | |
} | |
/** | |
* @brief parse json entry type integer | |
* | |
* @param i | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param is_delete | |
* @return char* | |
*/ | |
static void parse_cfg_json_int(json_object *i, char *buf, size_t buf_len, char **p, bool is_delete) { | |
memcpy(*p, buf, buf_len); | |
*p += buf_len; | |
if (!is_delete) { | |
int ii = json_object_get_int(i); | |
*p += snprintf(*p, 512, "=%d\n", ii); | |
} else { | |
**p = '\n'; | |
*p += 1; | |
} | |
} | |
/** | |
* @brief parse json entry type double | |
* | |
* @param d | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param is_delete | |
* @return void* | |
*/ | |
static void parse_cfg_json_double(json_object *d, char *buf, size_t buf_len, char **p, bool is_delete) { | |
memcpy(*p, buf, buf_len); | |
*p += buf_len; | |
if (!is_delete) { | |
double dd = json_object_get_double(d); | |
*p += snprintf(*p, 512, "=%f\n", dd); | |
} else { | |
**p = '\n'; | |
*p += 1; | |
} | |
} | |
/** | |
* @brief dispatcher fucntion to parse json object | |
* | |
* @param val | |
* @param buf | |
* @param buf_len | |
* @param p | |
* @param depth | |
* @param is_delete | |
*/ | |
static void parse_cfg_json(json_object *val, char *buf, size_t buf_len, char **p, size_t depth, bool is_delete) { | |
json_type type = json_object_get_type(val); | |
switch (type) { | |
case json_type_object: | |
parse_cfg_json_object(val, buf, buf_len, p, depth, is_delete); | |
break; | |
case json_type_array: | |
parse_cfg_json_array(val, buf, buf_len, p, depth, is_delete); | |
break; | |
case json_type_string: | |
parse_cfg_json_string(val, buf, buf_len, p, is_delete); | |
break; | |
case json_type_boolean: | |
parse_cfg_json_boolean(val, buf, buf_len, p, is_delete); | |
break; | |
case json_type_int: | |
parse_cfg_json_int(val, buf, buf_len, p, is_delete); | |
break; | |
case json_type_double: | |
parse_cfg_json_double(val, buf, buf_len, p, is_delete); | |
break; | |
case json_type_null: | |
default: | |
break; | |
} | |
} | |
/* | |
lh_table *table = json_object_get_object(root); | |
for (struct lh_entry *entry = table->head; entry; entry = entry->next){ | |
char *key = (char *)entry->k; | |
char *val = json_object_get_string((json_object *)entry->v); | |
syslogwda(LOG_DEBUG,"key: %s val: %s\n", key, val); | |
} | |
*/ | |
bool config_set_or_delete(json_object *root, bool is_delete) { | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
char *uci_command = is_delete ? "uci delete" : "uci set"; | |
/* parse json */ | |
char buf[16384]; /* commands buffer */ | |
char *bp = buf; | |
char **p = &bp; | |
if (json_object_get_type(root) != json_type_object) { | |
syslogwda(LOG_ALERT,"error: data is not an object\n"); | |
return false; | |
} | |
parse_cfg_json(root, NULL, 0, p, 0, is_delete); | |
syslogwda(LOG_DEBUG,"commands:\n%s\n", buf); | |
/* exec */ | |
FILE *fp; | |
char command[256]; | |
char outbuf[256]; | |
char *line = strtok(buf, "\n"); | |
do { | |
snprintf(command, 256, "%s %s", uci_command, line); | |
syslogwda(LOG_WARNING,"cmd exec: %s\n", command); | |
fp = popen(command, "r"); | |
if (fp == NULL) { | |
syslogwda(LOG_ALERT,"error: Unable to open process %s\n", command); | |
return false; | |
} | |
/* print cmd outbuf */ | |
while (fgets(outbuf, 256, fp) != NULL) { | |
syslogwda(LOG_DEBUG,"%s\n", outbuf); | |
} | |
/* status code */ | |
int ret = WEXITSTATUS(pclose(fp)); | |
if (ret != 0) syslogwda(LOG_WARNING,"status code: %d %s\n", ret, strerror(ret)); | |
} while ((line = strtok(NULL, "\n"))); | |
/* commit and reload */ | |
snprintf(buf, 512, "uci commit\nreload_config\n"); | |
line = strtok(buf, "\n"); | |
do { | |
snprintf(command, 256, "%s", line); | |
syslogwda(LOG_WARNING,"cmd exec: %s\n", command); | |
fp = popen(command, "r"); | |
if (fp == NULL) { | |
syslogwda(LOG_ALERT,"error: %s Unable to open process %s\n", strerror(errno), command); | |
return false; | |
} | |
/* print cmd outbuf */ | |
while (fgets(outbuf, 256, fp) != NULL) { | |
syslogwda(LOG_DEBUG,"%s\n", outbuf); | |
} | |
/* status code */ | |
int ret = WEXITSTATUS(pclose(fp)); | |
if(ret != 0) syslogwda(LOG_DEBUG,"status code: %d %s\n", ret, strerror(ret)); | |
} while ((line = strtok(NULL, "\n"))); | |
return true; | |
} | |
size_t read_file(const char *filepath, char *buf, size_t buf_len){ | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
FILE *fp = fopen(filepath,"r"); | |
if(fp == NULL){ | |
syslogwda(LOG_ALERT,"error: Unable to open file %s\n", filepath); | |
return 0; | |
} | |
size_t read = fread(buf, 1, buf_len, fp); | |
buf[read] = '\0'; //set terminator | |
fclose(fp); | |
return read; | |
} | |
/** | |
* @brief exec given command with shell | |
* | |
* @param command | |
* @param buf | |
* @param buf_len | |
* @return int | |
*/ | |
int exec(const char *command, char *buf, size_t buf_len){ | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
FILE *fp; | |
syslogwda(LOG_NOTICE,"exec: %s\n", command); | |
fp = popen(command, "r"); | |
if (fp == NULL) { | |
syslogwda(LOG_ERR,"error: %s Unable to open process %s\n", strerror(errno), command); | |
return errno; | |
} | |
if(buf == NULL || buf_len == 0) { | |
buf_len = 8192; | |
char tmp_buf[buf_len]; | |
buf = (char *)&tmp_buf; | |
} | |
size_t p = fread(buf, 1, buf_len, fp); //fread will return number of 1 byte entries readed | |
/* check bounds */ | |
if(p > buf_len){ | |
syslogwda(LOG_ERR, "INFO: exec stdout > buf_len %zu\n", buf_len); | |
buf[buf_len - 1] = '\0'; | |
} else { | |
buf[p] = '\0'; //set terminator | |
} | |
/* status code */ | |
int ret = WEXITSTATUS(pclose(fp)); | |
if(ret != 0) syslogwda(LOG_NOTICE, "status code: %d %s\n", ret, strerror(ret)); | |
return ret; | |
} | |
/** | |
* @brief exec given command with format like printf, fprintf etc | |
* | |
* @param buf | |
* @param buflen | |
* @param fmt | |
* @param ... | |
* @return int | |
*/ | |
int execf(char *buf, size_t buflen, const char *fmt, ...){ | |
size_t cmdlen = 2048; | |
char cmd[cmdlen]; | |
va_list arg; | |
va_start (arg, fmt); | |
cmdlen -= vsnprintf(cmd, cmdlen, fmt, arg); | |
va_end (arg); | |
return exec(cmd, buf, buflen); | |
} | |
int exec2(char *outbuf, size_t *outbufsize, char *errbuf, size_t *errbufsize, char *argv[]) { | |
int fdout[2]; /* pipe fd array for the stdout */ | |
int fderr[2]; /* pipe fd array for the stderr */ | |
pid_t pid; /* process id */ | |
int status; /* place to store child process status */ | |
if (pipe(fdout)==-1) /* first pipe for the stdout */ | |
perror("pipe out"); /* exit with error if something wrong */ | |
if (pipe(fderr)==-1) /* second pipe for the stderr */ | |
perror("pipe err"); | |
/* | |
* On success, the PID of the child process is returned in the | |
* parent, and 0 is returned in the child. On failure, -1 is | |
* returned in the parent, no child process is created, and errno is | |
* set to indicate the error. | |
*/ | |
if ((pid = fork()) == -1) /* fork current process and store pid */ | |
perror("fork error"); | |
if(pid == 0) { /* if pid == 0 than this is a child process */ | |
dup2 (fdout[1], STDOUT_FILENO); /* send stdout to the pipe fdout */ | |
dup2 (fderr[1], STDERR_FILENO); /* send stderr to the pipe fderr */ | |
/* close both sides of the pipe in the child */ | |
close(fdout[0]); | |
close(fdout[1]); | |
/* close both sides of the pipe in the child */ | |
close(fderr[0]); | |
close(fderr[1]); | |
/* execvp is called in the child ps | |
* argv[0] is a ptr to the first arg | |
* &argv[0] is a ptr to a ptr to the first arg | |
*/ | |
execvp(argv[0], &argv[0]); | |
/* this part is never reached if execvp success */ | |
return errno; | |
} else { /* parent */ | |
while(wait(&status) > 0){} /* wait for the child processes to finish */ | |
/* close write ends of the pipes */ | |
close(fdout[1]); | |
close(fderr[1]); | |
/* if child process finished with errorprint error | |
* and return error code from parent process | |
*/ | |
if (WIFEXITED(status) && WEXITSTATUS(status)){ | |
printf("%s\n", strerror(WEXITSTATUS(status))); | |
return WEXITSTATUS(status); | |
} | |
*outbufsize = read(fdout[0], outbuf, *outbufsize); | |
outbuf[*outbufsize] = '\0'; | |
//printf("OUT: \"%.*s\"\n", (int)*outbufsize, outbuf); | |
*errbufsize = read(fderr[0], errbuf, *errbufsize); | |
errbuf[*errbufsize] = '\0'; | |
//printf("ERR: \"%.*s\"\n", (int)*errbufsize, errbuf); | |
/* close read ends of the pipes */ | |
close(fdout[0]); | |
close(fderr[0]); | |
} | |
return 0; | |
} | |
json_object *config_get_raw() { | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
size_t bufsize = 32768; | |
char *buf = malloc(bufsize); | |
exec("uci show", buf, bufsize); | |
json_object *json_array = json_object_new_array(); | |
char *tok = strtok(buf, "\n"); | |
size_t idx = 0; | |
do { | |
syslogwda(LOG_INFO,"uci cmd: %s\n", tok); | |
json_object *json_string = json_object_new_string(tok); | |
json_object_array_put_idx(json_array, idx, json_string); | |
idx++; | |
} while ((tok = strtok(NULL, "\n"))); | |
free(buf); | |
return json_array; | |
} | |
void config_wireless_iface(bool remove){ | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
char buf[16384]; | |
exec("uci show wireless | grep '=wifi-iface'", buf, 16384); | |
char *tok = strtok(buf, "\n"); | |
if(tok == NULL) return; | |
size_t idx = 0; | |
do { | |
char *last = strchr(tok,'='); | |
if(last == NULL){ | |
syslogwda(LOG_INFO,"%zu found: '%s' wifi-iface not found! skip.\n", idx, tok); | |
continue; | |
} | |
size_t len = last - tok; | |
char wifi_iface[len + 1]; /* + 1 for terminator byte '\0' */ | |
memcpy(wifi_iface, tok, len); | |
wifi_iface[len] = '\0'; /* terminate string */ | |
syslogwda(LOG_INFO,"%zu found '%s' len: %zu wifi-iface: '%s'\n", idx, tok, len, wifi_iface); | |
if(remove) { | |
char command[256]; | |
snprintf(command, 256, "uci delete %s", wifi_iface); | |
exec(command, NULL, 0); | |
} | |
idx++; | |
} while ((tok = strtok(NULL, "\n"))); | |
return; | |
} | |
void config_network_clear(){ | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
char buf[16384]; | |
exec("uci show network | grep -E '=[device|interface]' | grep -Ev 'dev\\d{1,2}=|loopback'", buf, 16384); | |
char *tok = strtok(buf, "\n"); | |
if(tok == NULL) return; | |
size_t idx = 0; | |
do { | |
char *last = strchr(tok,'='); | |
if(last == NULL){ | |
syslogwda(LOG_DEBUG,"%zu found: '%s' network interface not found! skip.\n", idx, tok); | |
continue; | |
} | |
size_t len = last - tok; | |
char net_iface[len + 1]; /* + 1 for terminator byte '\0' */ | |
memcpy(net_iface, tok, len); | |
net_iface[len] = '\0'; /* terminate string */ | |
syslogwda(LOG_DEBUG,"%zu found '%s' len: %zu network iface: '%s'\n", idx, tok, len, net_iface); | |
char command[256]; | |
snprintf(command, 256, "uci delete %s", net_iface); | |
exec(command, NULL, 0); | |
idx++; | |
} while ((tok = strtok(NULL, "\n"))); | |
return; | |
} | |
json_object *config_get() { | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
FILE *fp; | |
char string[1024]; /* stdout string len */ | |
fp = popen("uci show", "r"); | |
if (fp == NULL) return false; | |
/* json init */ | |
json_object *root = json_object_new_object(); | |
while (fgets(string, 1024, fp) != NULL) { | |
parse_line(root, string); | |
} | |
pclose(fp); | |
return root; | |
} | |
static void parse_line(json_object *root_cur, char *line) { | |
char *start = NULL, *end = NULL, *pos = NULL, *val = NULL, *tok = NULL, *tok_prev = NULL, *tok_last = NULL; | |
json_object *root_parent = NULL, *child = NULL; | |
bool is_section_type; //this flag for special parse uci section_type e.g.: wireless.2g=wifi-iface | |
is_section_type = false; | |
/* value delimiter */ | |
char delim = '='; | |
pos = strchr(line, delim); | |
if (pos == NULL) { | |
syslogwda(LOG_DEBUG,"warning: delimiter '%c' not found in the line: %s\n", delim, line); | |
return; | |
} | |
*pos = '\0'; /* set terminator inplace delimiter */ | |
val = pos + 1; | |
/* remove trailing \n */ | |
size_t len = strlen(val); | |
end = val + len - 1; // last char pos | |
if (*end == '\n') *end = '\0'; | |
end--; // replace \n with line terminator | |
/* remove quotes if exists */ | |
if (*val == '"' || *val == '\'') { | |
val++; //shift forward to remove opening quote | |
if (*end == '"' || *end == '\'') *end = '\0'; | |
end--; // shift backward to remove closing quote | |
} else{ | |
is_section_type = true; | |
} | |
/*last token detection */ | |
tok_last = strrchr(line, '.'); | |
if (tok_last) { | |
tok_last += 1; | |
} else { | |
tok_last = line; | |
}; | |
/* split line by dots */ | |
tok = strtok(line, "."); | |
do { | |
size_t idx = 0; | |
bool is_array = false; | |
json_object *container; | |
//syslogwda(LOG_DEBUG,"\ttok: %s \n", tok); | |
/* if array is present in token */ | |
if ((start = strchr(tok, '['))) { | |
*start = '\0'; /* set terminator char */ | |
//syslogwda(LOG_DEBUG,"\ttok clean: %s\n", tok); | |
if ((end = strchr(start + 1, ']'))) { | |
is_array = true; | |
*end = '\0'; /* set terminator char */ | |
idx = atoi(start + 1); /* array index */ | |
//syslogwda(LOG_DEBUG,"\t\tarray idx: %d\n", idx); | |
} | |
} | |
/* if last token */ | |
if (tok == tok_last) { | |
child = json_object_new_string(val); | |
/* 2 scenarios */ | |
if (!is_array) { | |
if (json_object_get_type(root_cur) != json_type_object){ | |
json_object_object_del(root_parent, tok_prev); | |
root_cur = json_object_new_object(); | |
json_object_object_add(root_parent, tok_prev, root_cur); | |
} | |
//special parse section_type | |
if(is_section_type){ | |
json_object *jso = json_object_new_object(); | |
json_object_object_add(root_cur, tok, jso); | |
root_cur = jso; | |
json_object_object_add(root_cur, "section_type", child); | |
}else { | |
json_object_object_add(root_cur, tok, child); | |
} | |
} else if (is_array) { | |
//special parse section_type | |
if(is_section_type){ | |
json_object *jso = json_object_new_object(); | |
json_object_object_add(jso, "section_type", child); | |
child = jso; | |
} | |
json_object_object_get_ex(root_cur, tok, &container); | |
//remove if not an array | |
if(json_object_get_type(container) != json_type_array){ | |
json_object_object_del(root_cur, tok); //delete container | |
container = json_object_new_array(); | |
json_object_object_add(root_cur, tok, container); | |
} | |
json_object_array_put_idx(container, idx, child); | |
} | |
continue; | |
} | |
/* get tok container */ | |
json_object_object_get_ex(root_cur, tok, &container); | |
//save for next cycles root_cur and tok | |
root_parent = root_cur; | |
tok_prev = tok; | |
/* 4 scenarios */ | |
if (!is_array && container) { | |
root_cur = container; | |
} else if (!is_array && !container) { | |
child = json_object_new_object(); | |
json_object_object_add(root_cur, tok, child); | |
root_cur = child; | |
} else if (is_array && container) { | |
if(json_object_get_type(container) != json_type_array){ | |
json_object_object_del(root_cur, tok); //delete container | |
container = json_object_new_array(); | |
json_object_object_add(root_cur, tok, container); | |
child = NULL; | |
} else { | |
child = json_object_array_get_idx(container, idx); | |
} | |
if (!child) { | |
child = json_object_new_object(); | |
json_object_array_put_idx(container, idx, child); | |
} | |
root_cur = child; | |
} else if (is_array && !container) { | |
child = json_object_new_object(); | |
container = json_object_new_array(); | |
json_object_array_put_idx(container, idx, child); | |
json_object_object_add(root_cur, tok, container); | |
root_cur = child; | |
} | |
} while ((tok = strtok(NULL, "."))); | |
} | |
int wireless_del_station(const char *dev, const char *mac) { | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
syslogwda(LOG_WARNING,"delete sta dev: %s mac: %s\n", dev, mac); | |
//if dev and mac passed | |
if(dev && mac){ | |
return ubus_hostpad_del_station(dev, mac); | |
} | |
//if dev passed and mac is not | |
size_t entry_size = sizeof(struct iwinfo_assoclist_entry); | |
const struct iwinfo_ops *iw; | |
int len = 0; | |
char buf[IWINFO_BUFSIZE]; | |
if(dev && !mac) { | |
iw = iwinfo_backend(dev); | |
iw->assoclist(dev, buf, &len); | |
for (int i = 0; i < len; i += entry_size) { | |
struct iwinfo_assoclist_entry *e; | |
e = (struct iwinfo_assoclist_entry *) &buf[i]; | |
int ret = ubus_hostpad_del_station(dev, format_mac((uint8_t *)e->mac)); | |
if(ret != 0) return ret; | |
} | |
return 0; | |
} | |
//if dev is not passed | |
/* get wlan devs */ | |
size_t devs_size = 50; | |
net_dev netdev[devs_size]; | |
net_devs devs = {.cnt = -1, .dev = (net_dev *)&netdev}; | |
get_wifi_dev(&devs, devs_size); | |
for (int i = 0; i < devs.cnt; i++) { | |
char *ifname = devs.dev[i].name; | |
/* get assoc. users list */ | |
iw = iwinfo_backend(ifname); | |
iw->assoclist(ifname, buf, &len); | |
for (int i = 0; i < len; i += entry_size) { | |
struct iwinfo_assoclist_entry *e; | |
e = (struct iwinfo_assoclist_entry *) &buf[i]; | |
int ret = ubus_hostpad_del_station(ifname, format_mac((uint8_t *)e->mac)); | |
if(ret != 0) return ret; | |
} | |
} | |
return 0; | |
} | |
int ubus_hostpad_del_station(const char *dev, const char *mac) { | |
syslogwda(LOG_INFO,"%s() %s:%d\n", __func__, __FILE__, __LINE__); | |
syslogwda(LOG_WARNING,"delete sta dev: %s mac: %s\n", dev, mac); | |
if(!dev || !mac) return -1; | |
char command[256]; | |
snprintf(command, 256, "ubus call hostapd.%s " | |
"del_client " | |
"\"{'addr':'%s', 'reason':5, 'deauth':true, 'ban_time':0}\"", | |
dev, mac); | |
FILE *fp = popen(command, "r"); | |
/* status code */ | |
int ret = WEXITSTATUS(pclose(fp)); | |
if(ret != 0) syslogwda(LOG_WARNING,"status code: %d %s\n", ret, strerror(ret)); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment