diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e76340b..e797c452 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,10 @@ target_link_libraries(wifidogx ${CURL_LIBRARIES} ) +target_link_libraries(wdctlx + event +) + # Installation install(TARGETS wifidogx wdctlx RUNTIME DESTINATION bin diff --git a/src/util.c b/src/util.c index c1b3de6f..274e42b3 100644 --- a/src/util.c +++ b/src/util.c @@ -266,50 +266,7 @@ is_valid_mac(const char *mac) return (i == 12 && (s == 5 || s == 0)); } -// when sockfd is block, set timeout for connect -int -wd_connect(int sockfd, const struct sockaddr *their_addr, socklen_t addrlen, int timeout) -{ - // Set non-blocking - long arg = fcntl(sockfd, F_GETFL, NULL); - arg |= O_NONBLOCK; - fcntl(sockfd, F_SETFL, arg); - - int res = connect(sockfd, their_addr, addrlen); - if ((res == -1) && (errno != EINPROGRESS)) { - goto ERROR; - } else if (res == 0) { - goto SUCCESS; - } else { - int so_error = 0; - unsigned len = sizeof(so_error); - - struct pollfd fds; - memset(&fds, 0, sizeof(fds)); - fds.fd = sockfd; - fds.events = POLLOUT; - res = poll(&fds, 1, timeout*1000); - switch(res) { - case 1: // data to read - getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len); - if (so_error == 0) { - goto SUCCESS; - } - break; - default: - break; - } - } - -ERROR: - return -1; -SUCCESS: - // Set to blocking mode again... - arg = fcntl(sockfd, F_GETFL, NULL); - arg &= (~O_NONBLOCK); - fcntl(sockfd, F_SETFL, arg); - return 0; -} + #define BUF_MAX 1024 diff --git a/src/util.h b/src/util.h index 1e71d6f3..5fd92d78 100644 --- a/src/util.h +++ b/src/util.h @@ -30,8 +30,6 @@ int is_valid_ip6(const char *); int is_valid_mac(const char *); -int wd_connect(int, const struct sockaddr *, socklen_t, int); - float get_cpu_usage(); #endif /* _UTIL_H_ */ diff --git a/src/wd_util.c b/src/wd_util.c index c0b108a7..14a9ecc6 100644 --- a/src/wd_util.c +++ b/src/wd_util.c @@ -2115,4 +2115,4 @@ __get_client_name(t_client *client) pclose(f_dhcp); debug(LOG_INFO, "__get_client_name [%s]", name); } -} \ No newline at end of file +} diff --git a/src/wdctl.c b/src/wdctl.c index 429b15bf..25cd97a8 100644 --- a/src/wdctl.c +++ b/src/wdctl.c @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: GPL-3.0-only /* * Copyright (c) 2023 Dengfeng Liu @@ -6,142 +5,135 @@ #define _GNU_SOURCE +#include +#include +#include #include "common.h" -#include "wdctl.h" -#include "util.h" +#include "wd_util.h" + +#define DEFAULT_SOCK "/tmp/wdctlx.sock" -#define WDCTL_TIMEOUT 1000*2 -#define WDCTL_MSG_LENG 1024*8 +#define WDCTL_TIMEOUT 2000 +#define WDCTL_MSG_LEN 8192 +static struct event_base *base = NULL; static char *sk_name = NULL; char *program_argv0 = NULL; -static void show_command(const char *type); -static void add_command(const char *type, char *values); -static void clear_command(const char *type); static void display_help(); -static void stop_command(); -static void reset_command(const char *value); -static void status_command(const char *type); -static void refresh_command(); -static void send_request(int, const char *); -static void read_response(int); -static void wdctl_command_action(const char *, const char *); -static int connect_to_server(const char *); +static void event_cb(struct bufferevent *bev, short events, void *ctx) { + int *connection_success = (int *)ctx; + if (events & BEV_EVENT_CONNECTED) { + *connection_success = 1; + event_base_loopexit(base, NULL); + } else if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + *connection_success = 0; + event_base_loopexit(base, NULL); + } +} -static int -connect_to_server(const char *sock_name) -{ +static struct bufferevent *connect_to_server(const char *sock_name) { struct sockaddr_un sa_un; - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - fprintf(stdout, "wdctl: could not get socket (Error: %s)\n", strerror(errno)); + int connection_success = 0; + + base = event_base_new(); + if (!base) { + fprintf(stdout, "Could not create event base\n"); exit(EXIT_FAILURE); } + memset(&sa_un, 0, sizeof(sa_un)); sa_un.sun_family = AF_UNIX; - if (sock_name) { - strncpy(sa_un.sun_path, sock_name, (sizeof(sa_un.sun_path) - 1)); - } else { - strncpy(sa_un.sun_path, DEFAULT_SOCK, (sizeof(sa_un.sun_path) - 1)); - + strncpy(sa_un.sun_path, sock_name ? sock_name : DEFAULT_SOCK, sizeof(sa_un.sun_path) - 1); + + struct bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); + if (!bev) { + fprintf(stdout, "Could not create bufferevent\n"); + event_base_free(base); + exit(EXIT_FAILURE); } - if (wd_connect(sock, (struct sockaddr *)&sa_un, strlen(sa_un.sun_path) + sizeof(sa_un.sun_family), 2)) { - fprintf(stdout, "wdctl: wifidog probably not started (Error: %s)\n", strerror(errno)); + bufferevent_setcb(bev, NULL, NULL, event_cb, &connection_success); + bufferevent_enable(bev, EV_READ | EV_WRITE); + + struct timeval tv = {2, 0}; + bufferevent_set_timeouts(bev, &tv, &tv); + + if (bufferevent_socket_connect(bev, (struct sockaddr *)&sa_un, sizeof(sa_un)) < 0) { + fprintf(stdout, "Could not connect\n"); + bufferevent_free(bev); + event_base_free(base); exit(EXIT_FAILURE); } - return sock; -} + event_base_dispatch(base); + + if (!connection_success) { + fprintf(stdout, "wdctlx: apfree-wifidog probably not started\n"); + bufferevent_free(bev); + event_base_free(base); + exit(EXIT_FAILURE); + } -static void -send_request(int sock, const char *request) -{ - struct pollfd fds; - fds.fd = sock; - fds.events = POLLOUT; + event_base_free(base); + return bev; +} - if (poll(&fds, 1, WDCTL_TIMEOUT) > 0 && fds.revents == POLLOUT) { - write(sock, request, strlen(request)); - } +static void send_request(struct bufferevent *bev, const char *request) { + bufferevent_write(bev, request, strlen(request)); } -/** - * @brief execute command sending from wdctl_thread after process wdctlx's command - * usually it execute 'dnsmasq restart', this feature depends openwrt system - * - */ -static void -execute_post_cmd(char *raw_cmd) -{ +static void execute_post_cmd(char *raw_cmd) { size_t nlen = strlen(raw_cmd); - if (nlen < 3) goto ERR; + if (nlen < 3) return; - char *cmd = NULL; - if (raw_cmd[0] == '[' && raw_cmd[nlen-1] == ']') { - raw_cmd[nlen-1] = '\0'; - cmd = raw_cmd + 1; + if (raw_cmd[0] == '[' && raw_cmd[nlen - 1] == ']') { + raw_cmd[nlen - 1] = '\0'; + char *cmd = raw_cmd + 1; system(cmd); - fprintf(stdout, "execut shell [%s] success", cmd); - return; + fprintf(stdout, "Executed shell command: [%s]\n", cmd); + } else { + fprintf(stdout, "[%s] is an illegal post command\n", raw_cmd); } - -ERR: - fprintf(stdout, "[%s] is illegal post command", raw_cmd); } -/** - * @brief read reponse from wdctl_thread - * - */ -static void -read_response(int sock) -{ - char buf[WDCTL_MSG_LENG+1] = {0}; - struct pollfd fds; - fds.fd = sock; - fds.events = POLLIN; - - if (poll(&fds, 1, WDCTL_TIMEOUT) > 0 && fds.revents == POLLIN) { - if (read(sock, buf, WDCTL_MSG_LENG) > 0) { - if (!strncmp(buf, "CMD", 3)) { - execute_post_cmd(buf+3); - } else - fprintf(stdout, "%s\n", buf); +static void read_response(struct bufferevent *bev) { + char buf[WDCTL_MSG_LEN + 1] = {0}; + int n = bufferevent_read(bev, buf, WDCTL_MSG_LEN); + if (n > 0) { + buf[n] = '\0'; + if (!strncmp(buf, "CMD", 3)) { + execute_post_cmd(buf + 3); + } else { + fprintf(stdout, "%s\n", buf); } - } - close(sock); + } } -static void -wdctl_command_action(const char *cmd, const char *param) -{ - char *request = NULL; - int sock = connect_to_server(sk_name); - - if(param) - asprintf(&request, "%s %s", cmd, param); - else - asprintf(&request, "%s", cmd); +static void wdctl_command_action(const char *cmd, const char *param) { + struct bufferevent *bev = connect_to_server(sk_name); + char *request = NULL; - send_request(sock, request); + if (param) + asprintf(&request, "%s %s", cmd, param); + else + asprintf(&request, "%s", cmd); + + send_request(bev, request); free(request); - read_response(sock); + read_response(bev); + bufferevent_free(bev); } -int -main(int argc, char **argv) -{ +int main(int argc, char **argv) { if (argc < 2) { display_help(); return 1; } program_argv0 = argv[0]; - char *command = argv[1]; char *type = (argc > 2) ? argv[2] : NULL; char *values = (argc > 3) ? argv[3] : NULL; @@ -151,37 +143,57 @@ main(int argc, char **argv) printf("Error: Missing type argument\n"); return 1; } - show_command(type); + if (strcmp(type, "domain") == 0) { + wdctl_command_action("show_trusted_domains", NULL); + } else if (strcmp(type, "wildcard_domain") == 0) { + wdctl_command_action("show_trusted_pdomains", NULL); + } else if (strcmp(type, "mac") == 0) { + wdctl_command_action("show_trusted_mac", NULL); + } else { + printf("Unknown type\n"); + } } else if (strcmp(command, "add") == 0) { if (!type || !values) { printf("Error: Missing type or values argument\n"); return 1; } - add_command(type, values); + if (strcmp(type, "domain") == 0) { + wdctl_command_action("add_trusted_domains", values); + } else if (strcmp(type, "wildcard_domain") == 0) { + wdctl_command_action("add_trusted_pdomains", values); + } else if (strcmp(type, "mac") == 0) { + wdctl_command_action("add_trusted_mac", values); + } else { + printf("Unknown type\n"); + } } else if (strcmp(command, "clear") == 0) { if (!type) { printf("Error: Missing type argument\n"); return 1; } - clear_command(type); + if (strcmp(type, "domain") == 0) { + wdctl_command_action("clear_trusted_domains", NULL); + } else if (strcmp(type, "wildcard_domain") == 0) { + wdctl_command_action("clear_trusted_pdomains", NULL); + } else if (strcmp(type, "mac") == 0) { + wdctl_command_action("clear_trusted_mac", NULL); + } else { + printf("Unknown type\n"); + } } else if (strcmp(command, "help") == 0 || strcmp(command, "?") == 0) { display_help(); } else if (strcmp(command, "stop") == 0) { - stop_command(); + wdctl_command_action("stop", NULL); } else if (strcmp(command, "reset") == 0) { if (!values) { printf("Error: Missing reset argument\n"); return 1; } - reset_command(values); + wdctl_command_action("reset", values); } else if (strcmp(command, "status") == 0) { - if (type) { - status_command(type); - } else { - status_command(NULL); - } + wdctl_command_action("status", type); } else if (strcmp(command, "refresh") == 0) { - refresh_command(); + wdctl_command_action("refresh", NULL); } else { printf("Unknown command. Type 'wdctlx help' or 'wdctlx ?' for help.\n"); return 1; @@ -190,93 +202,14 @@ main(int argc, char **argv) return 0; } -static void -show_command(const char *type) { - printf("Showing %s\n", type); - // Add the logic to show the domain|wildcard_domain|mac - if (strcmp(type, "domain") == 0) { - wdctl_command_action("show_trusted_domains", NULL); - } else if (strcmp(type, "wildcard_domain") == 0) { - wdctl_command_action("show_trusted_pdomains", NULL); - } else if (strcmp(type, "mac") == 0) { - wdctl_command_action("show_trusted_mac", NULL); - } else { - printf("Unknown type\n"); - } -} - -static void -add_command(const char *type, char *values) { - printf("Adding %s values is %s\n", type, values); - - // Add the logic to add the values to domain|wildcard_domain|mac - if (strcmp(type, "domain") == 0) { - wdctl_command_action("add_trusted_domains", values); - } else if (strcmp(type, "wildcard_domain") == 0) { - wdctl_command_action("add_trusted_pdomains", values); - } else if (strcmp(type, "mac") == 0) { - wdctl_command_action("add_trusted_mac", values); - } else { - printf("Unknown type\n"); - } -} - -static void -clear_command(const char *type) { - printf("Clearing %s\n", type); - // Add the logic to clear the domain|wildcard_domain|mac - if (strcmp(type, "domain") == 0) { - wdctl_command_action("clear_trusted_domains", NULL); - } else if (strcmp(type, "wildcard_domain") == 0) { - wdctl_command_action("clear_trusted_pdomains", NULL); - } else if (strcmp(type, "mac") == 0) { - wdctl_command_action("clear_trusted_mac", NULL); - } else { - printf("Unknown type\n"); - } -} - -static void -display_help() { +static void display_help() { printf("Commands:\n"); printf("wdctlx show domain|wildcard_domain|mac\n"); printf("wdctlx add domain|wildcard_domain|mac value1,value2...\n"); printf("wdctlx clear domain|wildcard_domain|mac\n"); printf("wdctlx help|?\n"); printf("wdctlx stop\n"); - printf("wdctlx reset\n"); - printf("wdctlx status\n"); - printf("wdctlx refresh [type]\n"); -} - -static void -stop_command() { - printf("Stopping wdctlx\n"); - // Add the logic to stop the process - wdctl_command_action("stop", NULL); -} - -static void -reset_command(const char *value) { - printf("Resetting wdctlx\n"); - // Add the logic to reset the process - wdctl_command_action("reset", value); -} - -static void -status_command(const char *type) { - if (type) { - wdctl_command_action("status", type); - } else { - printf("Status: Running\n"); - // Add the logic to show the status - wdctl_command_action("status", NULL); - } -} - -static void -refresh_command(const char *type) -{ - printf("Refreshing wdctlx\n"); - wdctl_command_action("refresh", NULL); + printf("wdctlx reset value\n"); + printf("wdctlx status [type]\n"); + printf("wdctlx refresh\n"); } diff --git a/src/wdctl.h b/src/wdctl.h deleted file mode 100644 index 53b9d590..00000000 --- a/src/wdctl.h +++ /dev/null @@ -1,49 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-only -/* - * Copyright (c) 2023 Dengfeng Liu - */ - -#ifndef _WDCTL_H_ -#define _WDCTL_H_ - -#define DEFAULT_SOCK "/tmp/wdctl.sock" - -#define WDCTL_UNDEF 0 -#define WDCTL_STATUS 1 -#define WDCTL_STOP 2 -#define WDCTL_KILL 3 -#define WDCTL_RESTART 4 -#define WDCTL_ADD_TRUSTED_DOMAINS 5 -#define WDCTL_REPARSE_TRUSTED_DOMAINS 6 -#define WDCTL_CLEAR_TRUSTED_DOMAINS 7 -#define WDCTL_SHOW_TRUSTED_DOMAINS 8 -#define WDCTL_ADD_DOMAIN_IP 9 -#define WDCTL_ADD_ROAM_MACLIST 10 -#define WDCTL_CLEAR_ROAM_MACLIST 11 -#define WDCTL_SHOW_ROAM_MACLIST 12 -#define WDCTL_ADD_UNTRUSTED_MACLIST 13 -#define WDCTL_CLEAR_UNTRUSTED_MACLIST 14 -#define WDCTL_SHOW_UNTRUSTED_MACLIST 15 -#define WDCTL_ADD_TRUSTED_MACLIST 16 -#define WDCTL_CLEAR_TRUSTED_MACLIST 17 -#define WDCTL_SHOW_TRUSTED_MACLIST 18 -#define WDCTL_USER_CFG_SAVE 19 -#define WDCTL_ADD_WILDCARD_DOMAIN 20 -#define WDCTL_ADD_TRUSTED_IPLIST 21 -#define WDCTL_ADD_ONLINE_CLIENT 22 -#define WDCTL_DEL_TRUSTED_DOMAINS 23 -#define WDCTL_CLEAR_TRUSTED_IPLIST 24 -#define WDCTL_DEL_TRUSTED_IPLIST 25 -#define WDCTL_DEL_TRUSTED_MACLIST 26 -#define WDCTL_DEL_UNTRUSTED_MACLIST 27 -#define WDCTL_ADD_TRUSTED_PAN_DOMAINS 28 -#define WDCTL_DEL_TRUSTED_PAN_DOMAINS 29 -#define WDCTL_CLEAR_TRUSTED_PAN_DOMAINS 30 -#define WDCTL_SHOW_TRUSTED_PAN_DOMAINS 31 -#define WDCTL_ADD_TRUSTED_LOCAL_MACLIST 32 -#define WDCTL_DEL_TRUSTED_LOCAL_MACLIST 33 -#define WDCTL_SHOW_TRUSTED_LOCAL_MACLIST 34 -#define WDCTL_CLEAR_TRUSTED_LOCAL_MACLIST 35 - -#endif