first complete network stack version

This commit is contained in:
Martin/Geno 2018-08-05 19:35:16 +02:00
parent a4961cc6f2
commit 2349afd777
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
10 changed files with 234 additions and 71 deletions

View File

@ -16,5 +16,6 @@ bool config_client_probe_steering = true;
bool config_client_probe_learning = false;
#ifndef MINI
bool config_client_socket_learning = true;
bool config_socket_always_answer = false;
#endif

View File

@ -28,7 +28,8 @@ extern bool config_client_probe_steering;
extern bool config_client_probe_learning;
#ifndef MINI
extern bool config_client_socket_learning;
extern bool config_socket_always_answer;
#endif
#endif

View File

@ -27,11 +27,16 @@ struct option longopts[] = {
{"clean-every", required_argument, 0, 3},
{"clean-older-then", required_argument, 0, 4},
{"clean-authed", optional_argument, 0, 5},
#ifndef MINI
// network options
{"addr", required_argument, 0, 6},
{"maddr", required_argument, 0, 7},
{"port", required_argument, 0, 8},
{"ifname", required_argument, 0, 9},
// other extended option
{"socket-learning", optional_argument, 0, 10},
{"socket-always-answer", optional_argument, 0, 11},
#endif
};
void usage(int c) {
@ -54,11 +59,16 @@ void usage(int c) {
printf(" --clean-every run cleaning every (current: %ds)\n", config_client_clean_every);
printf(" --clean-older-then clean unseen for secound (current: %ds)\n", config_client_clean_older_then);
printf(" --clean-authed clean already authed also (not only learned by probes) (current: %s)\n", BOOL2STR(config_client_clean_authed));
#ifndef MINI
printf("\nnetwork options:\n");
printf(" --addr listen on ip address (current: %s)\n", addr);
printf(" --maddr listen and request on multcast address (current: %s)\n", maddr);
printf(" --port listen on port (current: %s)\n", port);
printf(" --ifname listen on interface for multicast (current: %s)\n", ifname);
printf("\nother extended options:\n");
printf(" --socket-learning learn clients during listen on socket (current: %s)\n", BOOL2STR(config_client_socket_learning));
printf(" --socket-always-answer answer on socket only with useful information (current: %s)\n", BOOL2STR(config_socket_always_answer));
#endif
printf("\nSome config could be changed by ubus, see `ubus -v list wifictld`\n");
if(c)
printf("Invalid parameter %c ignored.\n", c);
@ -143,6 +153,7 @@ int main(int argc, char *argv[])
else
config_client_clean_authed = !config_client_clean_authed;
break;
#ifndef MINI
// network options
case 6:
addr = optarg;
@ -156,6 +167,20 @@ int main(int argc, char *argv[])
case 9:
ifname = optarg;
break;
// other extended option
case 10:
if(optarg)
config_client_socket_learning = atoi(optarg);
else
config_client_socket_learning = !config_client_socket_learning;
break;
case 11:
if(optarg)
config_socket_always_answer = atoi(optarg);
else
config_socket_always_answer = !config_socket_always_answer;
break;
#endif
default:
usage(c);
return 1;

View File

@ -1,10 +1,12 @@
#include "include.h"
#include "log.h"
#include "data.h"
#include "socket.h"
#include "socket_msg.h"
#include "socket_handler.h"
static struct uloop_fd server;
struct in6_addr ownaddr;
struct sockaddr_in6 ownaddr;
struct sockaddr_in6 client_addr;
int socket_info(struct socket_msg *info) {
@ -13,14 +15,16 @@ int socket_info(struct socket_msg *info) {
ret = socket_msg_marshal(info, msg);
if (ret) {
log_error("socket_request: could not marshel message: %d\n", ret);
log_error("socket_info: could not marshel message: %d\n", ret);
return ret;
}
ret = sendto(server.fd, msg, REQUEST_MAXLEN, 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
if (ret < 0) {
log_error("socket_request: could not send message: %d\n", ret);
log_error("socket_info: could not send message: %d\n", ret);
}
if(info->type & SOCKET_MSG_TYPE_CLIENT)
log_verbose("net-send(type=client mac="MACSTR" freq=%d ssi_l=%d ssi_h=%d tprobe=%d tauth=%d authed=%s time=%d)\n", MAC2STR(info->client->addr), info->client->freq_highest, info->client->signal_lowfreq, info->client->signal_highfreq, info->client->try_probe, info->client->try_auth, BOOL2STR(info->client->authed), info->client->time);
return ret;
}
@ -42,6 +46,11 @@ int socket_request_timeout(struct socket_msg *request, struct socket_msg *answer
return -1;
}
if(bind(sock, (struct sockaddr*)&ownaddr, sizeof(ownaddr))) {
log_error("socket_request: could not bind to addr\n");
return -1;
}
int loop = 0;
if(setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
@ -55,7 +64,10 @@ int socket_request_timeout(struct socket_msg *request, struct socket_msg *answer
log_error("socket_request: could not send message: %d\n", ret);
return ret;
}
if(request->type & SOCKET_MSG_TYPE_CLIENT)
log_verbose("net-send(type=request,client mac="MACSTR" freq=%d ssi_l=%d ssi_h=%d tprobe=%d tauth=%d authed=%s time=%d)\n", MAC2STR(request->client->addr), request->client->freq_highest, request->client->signal_lowfreq, request->client->signal_highfreq, request->client->try_probe, request->client->try_auth, BOOL2STR(request->client->authed), request->client->time);
// repeat to recieve best answer till timeout
ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,sizeof(timeout));
if(ret < 0) {
close(sock);
@ -78,22 +90,30 @@ int socket_request_timeout(struct socket_msg *request, struct socket_msg *answer
return ret;
}
log_verbose("socket_request: end %d\n", ret);
if (answer->type & SOCKET_MSG_TYPE_RESPONSE) {
if(answer->type & SOCKET_MSG_TYPE_CLIENT)
log_verbose("net-recv(type=response,client mac="MACSTR" freq=%d ssi_l=%d ssi_h=%d tprobe=%d tauth=%d authed=%s time=%d)\n", MAC2STR(answer->client->addr), answer->client->freq_highest, answer->client->signal_lowfreq, answer->client->signal_highfreq, answer->client->try_probe, answer->client->try_auth, BOOL2STR(answer->client->authed), answer->client->time);
return 0;
}
log_verbose("socket_request: end %d\n", ret);
return -1;
}
static void server_cb(struct uloop_fd *fd, unsigned int events) {
int ret;
struct sockaddr_in6 addr;
char buf[REQUEST_MAXLEN];
char control[256];
char buf[REQUEST_MAXLEN];
struct socket_msg msg = {
.type = 0,
.client = malloc(sizeof(struct wifi_client)),
};
struct iovec iv = {
.iov_base = buf,
.iov_len = sizeof(buf) - 1
.iov_len = sizeof(buf)
};
struct msghdr mh = {
@ -110,15 +130,38 @@ static void server_cb(struct uloop_fd *fd, unsigned int events) {
return;
}
char addr_str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(addr.sin6_addr), addr_str, INET6_ADDRSTRLEN);
log_info("socket:recv [%s]:%d - %s\n", addr_str, ntohs(addr.sin6_port), buf);
ret = socket_msg_unmarshal(&msg, buf);
if (ret) {
log_error("socket: could not unmarshel message: %d\n", ret);
return;
}
log_verbose("net-recv(type=");
if(msg.type & SOCKET_MSG_TYPE_REQUEST)
log_verbose("request,");
if(msg.type & SOCKET_MSG_TYPE_RESPONSE)
log_verbose("response,");
if(msg.type & SOCKET_MSG_TYPE_CLIENT)
log_verbose("client mac="MACSTR" freq=%d ssi_l=%d ssi_h=%d tprobe=%d tauth=%d authed=%s time=%d)\n", MAC2STR(msg.client->addr), msg.client->freq_highest, msg.client->signal_lowfreq, msg.client->signal_highfreq, msg.client->try_probe, msg.client->try_auth, BOOL2STR(msg.client->authed), msg.client->time);
// response only if message are recieve
ret = socket_handler(&msg);
if (ret != SOCKET_HANDLER_RESPONSE) {
if(ret == SOCKET_HANDLER_ERROR)
log_error("socket_handler: returned with %d\n", ret);
return;
}
if (sendto(server.fd, addr_str, sizeof(addr_str) - 1, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
ret = socket_msg_marshal(&msg, buf);
if (ret) {
log_error("socket: could not unmarshel message: %d\n", ret);
return;
}
if (sendto(server.fd, buf, sizeof(buf), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
log_error("socket: could not send answer\n");
}
log_info("socket: send answer\n");
if(msg.type & SOCKET_MSG_TYPE_CLIENT)
log_verbose("net-send(type=response,client mac="MACSTR" freq=%d ssi_l=%d ssi_h=%d tprobe=%d tauth=%d authed=%s time=%d)\n", MAC2STR(msg.client->addr), msg.client->freq_highest, msg.client->signal_lowfreq, msg.client->signal_highfreq, msg.client->try_probe, msg.client->try_auth, BOOL2STR(msg.client->authed), msg.client->time);
}
int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socket_port) {
@ -132,6 +175,14 @@ int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socke
client_addr.sin6_port = htons(atoi(socket_port));
client_addr.sin6_scope_id = if_nametoindex(ifname);
ownaddr.sin6_family = AF_INET6;
ownaddr.sin6_scope_id = client_addr.sin6_scope_id;
if(!inet_pton(AF_INET6, socket_bind, &ownaddr.sin6_addr)) {
log_error("socket: could not parse address for socket_request\n");
return -1;
}
// listen multicast
if (!inet_pton(AF_INET6, socket_maddr, &client_addr.sin6_addr)) {
log_error("socket: invalid multicast group\n");

View File

@ -0,0 +1,59 @@
#include "config.h"
#include "include.h"
#include "data.h"
#include "socket_msg.h"
#include "socket_handler.h"
static int handle_client(struct socket_msg *msg, int response) {
struct wifi_client *own_client;
own_client = avl_find_element(&clients_by_addr, msg->client->addr, own_client, avl);
if (own_client) {
// know client with higher freq
if (own_client->freq_highest < msg->client->freq_highest) {
return SOCKET_HANDLER_RESPONSE;
}
// learn freq
if (own_client->freq_highest < msg->client->freq_highest) {
own_client->freq_highest = msg->client->freq_highest;
}
if (!own_client->authed) {
own_client->authed = msg->client->authed;
}
if (own_client->time < msg->client->time) {
own_client->time = msg->client->time;
}
return response;
}
if(!config_client_socket_learning)
return SOCKET_HANDLER_SILENCE;
// learn client
msg->client->try_probe = 0;
msg->client->try_auth = 0;
msg->client->connected = false;
msg->client->avl.key = msg->client->addr;
avl_insert(&clients_by_addr, &msg->client->avl);
return SOCKET_HANDLER_SILENCE;
}
int socket_handler(struct socket_msg *msg) {
if(msg->type & SOCKET_MSG_TYPE_RESPONSE) {
return SOCKET_HANDLER_ERROR;
}
int ret = SOCKET_HANDLER_RESPONSE;
if(msg->type & SOCKET_MSG_TYPE_REQUEST) {
msg->type = (msg->type ^ SOCKET_MSG_TYPE_REQUEST) | SOCKET_MSG_TYPE_RESPONSE;
// single handlers
if(msg->type & SOCKET_MSG_TYPE_CLIENT) ret = handle_client(msg, SOCKET_HANDLER_RESPONSE);
return ret;
}
// single handlers
if(msg->type & SOCKET_MSG_TYPE_CLIENT) ret = handle_client(msg, SOCKET_HANDLER_SILENCE);
return ret;
}

View File

@ -0,0 +1,12 @@
#ifndef __WIFICTLD_SOCKET_HANDLER_H
#define __WIFICTLD_SOCKET_HANDLER_H
#include "socket_msg.h"
#define SOCKET_HANDLER_ERROR 2
#define SOCKET_HANDLER_SILENCE 1
#define SOCKET_HANDLER_RESPONSE 0
int socket_handler(struct socket_msg *info);
#endif

View File

@ -21,7 +21,7 @@ int wifictld_ubus_init()
// connect to ubus
ctx = ubus_connect(UBUS_SOCKET);
if (!ctx) {
log_error("Failed to connect to ubus");
log_error("failed to connect to ubus\n");
return 1;
}
@ -31,14 +31,14 @@ int wifictld_ubus_init()
// add bbs
ret = wifictld_ubus_add_bss(ctx);
if (ret) {
log_error("Failed to add ubus service");
log_error("failed to add ubus service\n");
return 1;
}
// bind events
ret = wifictld_ubus_bind_events(ctx);
if (ret) {
log_error("Failed to bind for ubus events");
log_error("failed to bind for ubus events\n");
return 2;
}

View File

@ -32,7 +32,7 @@ int wifictld_ubus_bind_events(struct ubus_context *ctx)
// register subscriber on ubus
int ret = ubus_register_subscriber(ctx, &sub);
if (ret) {
log_error("Error while registering subscriber: %s", ubus_strerror(ret));
log_error("error while registering subscriber: %s\n", ubus_strerror(ret));
ubus_free(ctx);
return 2;
}
@ -138,38 +138,33 @@ static int receive_notify(struct ubus_context *ctx, struct ubus_object *obj, str
// handle
log_verbose("%s["MACSTR"] freq: %d signal %d", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
if (!strcmp(method, "auth")) {
hclient.auth = true;
if (wifi_clients_try(&hclient)) {
log_verbose(" -> reject\n");
log_verbose("%s["MACSTR"] freq: %d signal %d -> reject\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
}
log_verbose(" -> accept\n");
log_verbose("%s["MACSTR"] freq: %d signal %d -> accept\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
return WLAN_STATUS_SUCCESS;
}
if (!strcmp(method, "probe")) {
if(config_client_probe_steering) {
if (wifi_clients_try(&hclient)) {
log_verbose(" -> reject\n");
log_verbose("%s["MACSTR"] freq: %d signal %d -> reject\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
log_verbose(" -> accept\n");
log_verbose("%s["MACSTR"] freq: %d signal %d -> accept\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
return WLAN_STATUS_SUCCESS;
}
if(config_client_probe_learning) {
log_verbose(" learn");
log_verbose("%s["MACSTR"] freq: %d signal %d -> learn\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
wifi_clients_learn(&hclient);
}
}
if (!strcmp(method, "deauth")) {
} else {
wifi_clients_disconnect(&hclient);
log_verbose(" -> disconnect\n");
return WLAN_STATUS_SUCCESS;
log_verbose("%s["MACSTR"] freq: %d signal %d -> disconnect\n", method, MAC2STR(addr), hclient.freq, hclient.ssi_signal);
}
log_verbose("\n");
return WLAN_STATUS_SUCCESS;
}

View File

@ -88,6 +88,8 @@ static int ubus_get_config(struct ubus_context *ctx, struct ubus_object *obj,
blobmsg_add_bool(&b, "client_probe_steering", config_client_probe_steering);
blobmsg_add_bool(&b, "client_probe_learning", config_client_probe_learning);
#ifndef MINI
blobmsg_add_bool(&b, "client_socket_learning", config_client_socket_learning);
blobmsg_add_bool(&b, "socket_always_answer", config_socket_always_answer);
#endif
blobmsg_close_table(&b, list);
@ -110,6 +112,8 @@ enum {
SET_CONFIG_CLIENT_PROBE_STEERING,
SET_CONFIG_CLIENT_PROBE_LEARNING,
#ifndef MINI
SET_CONFIG_CLIENT_SOCKET_LEARNING,
SET_CONFIG_SOCKET_ALWAYS_ANSWER,
#endif
__SET_CONFIG_MAX
};
@ -126,6 +130,8 @@ static const struct blobmsg_policy ubus_set_config_policy[__SET_CONFIG_MAX] = {
[SET_CONFIG_CLIENT_PROBE_STEERING] = { "client_probe_steering", BLOBMSG_TYPE_BOOL },
[SET_CONFIG_CLIENT_PROBE_LEARNING] = { "client_probe_learning", BLOBMSG_TYPE_BOOL },
#ifndef MINI
[SET_CONFIG_CLIENT_SOCKET_LEARNING] = { "client_socket_learning", BLOBMSG_TYPE_BOOL },
[SET_CONFIG_SOCKET_ALWAYS_ANSWER] = { "socket_always_answer", BLOBMSG_TYPE_BOOL },
#endif
};
@ -147,7 +153,9 @@ static int ubus_set_config(struct ubus_context *ctx, struct ubus_object *obj,
!tb[SET_CONFIG_CLIENT_PROBE_STEERING] &&
!tb[SET_CONFIG_CLIENT_PROBE_LEARNING]
#ifndef MINI
// &&
&&
!tb[SET_CONFIG_CLIENT_SOCKET_LEARNING] &&
!tb[SET_CONFIG_SOCKET_ALWAYS_ANSWER]
#endif
)
return UBUS_STATUS_INVALID_ARGUMENT;
@ -172,6 +180,10 @@ static int ubus_set_config(struct ubus_context *ctx, struct ubus_object *obj,
if (tb[SET_CONFIG_CLIENT_PROBE_LEARNING])
config_client_probe_learning = blobmsg_get_bool(tb[SET_CONFIG_CLIENT_PROBE_LEARNING]);
#ifndef MINI
if (tb[SET_CONFIG_CLIENT_SOCKET_LEARNING])
config_client_socket_learning = blobmsg_get_bool(tb[SET_CONFIG_CLIENT_SOCKET_LEARNING]);
if (tb[SET_CONFIG_SOCKET_ALWAYS_ANSWER])
config_socket_always_answer = blobmsg_get_bool(tb[SET_CONFIG_SOCKET_ALWAYS_ANSWER]);
#endif
return 0;

View File

@ -32,17 +32,20 @@ void clean_cbhandler(struct uloop_timeout *t)
}
uloop_timeout_set(t, config_client_clean_every * 1000);
if (count > 0) {
log_info("remove %d of %d clients", count, all);
if(!config_client_clean_authed)
log_info(" (skipped %d authed clients)", auth);
log_info(" from memory\n");
}else{
if (count == 0) {
log_verbose("remove %d of %d clients", count, all);
if(!config_client_clean_authed)
log_verbose(" (skipped %d authed clients)", auth);
log_verbose(" from memory\n");
return;
}
log_info("remove %d of %d clients", count, all);
if(!config_client_clean_authed)
log_info(" (skipped %d authed clients)", auth);
log_info(" from memory\n");
return;
}
struct uloop_timeout clean = {
@ -65,7 +68,8 @@ void wifi_clients_close() {
}
void __client_setvalues(struct wifi_client *client, struct hostapd_client *hclient) {
bool __client_setvalues(struct wifi_client *client, struct hostapd_client *hclient) {
bool updated = false;
log_debug("wifi_clients.__client_setvalues(., %d):", hclient->freq);
if (client->freq_highest < hclient->freq) {
client->freq_highest = hclient->freq;
@ -74,15 +78,18 @@ void __client_setvalues(struct wifi_client *client, struct hostapd_client *hclie
if (hclient->freq > WIFI_CLIENT_FREQ_THREASHOLD) {
client->signal_highfreq = hclient->ssi_signal;
client->signal_lowfreq = 0;
//here to skip socket_request
updated = true;
}else{
client->signal_highfreq = 0;
client->signal_lowfreq = hclient->ssi_signal;
}
log_debug("\n");
time(&client->time);
if(!client->authed) {
client->authed = hclient->auth;
}
log_debug("\n");
return updated;
}
struct wifi_client *__get_client(struct hostapd_client *hclient){
@ -90,7 +97,17 @@ struct wifi_client *__get_client(struct hostapd_client *hclient){
client = avl_find_element(&clients_by_addr, hclient->address, client, avl);
if (client) {
#ifdef MINI
__client_setvalues(client, hclient);
#else
if (__client_setvalues(client, hclient)) {
struct socket_msg msg = {
.type = SOCKET_MSG_TYPE_CLIENT,
.client = client,
};
socket_info(&msg);
}
#endif
log_debug("wifi_clients.__get_client("MACSTR"): found existing client\n", MAC2STR(hclient->address));
return client;
}
@ -104,16 +121,18 @@ struct wifi_client *__get_client(struct hostapd_client *hclient){
client->freq_highest = 0;
__client_setvalues(client, hclient);
#ifndef MINI
#ifdef MINI
__client_setvalues(client, hclient);
#else
if(__client_setvalues(client, hclient)) {
struct socket_msg req = {
.type = SOCKET_MSG_TYPE_CLIENT,
.client = client,
}, resp = {
.client = malloc(sizeof(*client)),
.client = malloc(sizeof(struct wifi_client)),
};
if(socket_request(&req, &resp) == 0){
log_debug("wifi_clients.__get_client("MACSTR"): get client from neigbour\n", MAC2STR(hclient->address));
if (client->freq_highest < resp.client->freq_highest) {
client->freq_highest = resp.client->freq_highest;
}
@ -121,6 +140,7 @@ struct wifi_client *__get_client(struct hostapd_client *hclient){
client->authed = resp.client->authed;
}
}
}
#endif
client->avl.key = client->addr;
@ -133,23 +153,10 @@ void wifi_clients_learn(struct hostapd_client *hclient) {
__get_client(hclient);
}
#ifdef MINI
#define returnINFO_CLIENT return
#else
#define returnINFO_CLIENT if(config_client_force_probe && !hclient->auth) socket_info(&msg); return
#endif
int wifi_clients_try(struct hostapd_client *hclient) {
struct wifi_client *client;
client = __get_client(hclient);
#ifndef MINI
struct socket_msg msg = {
.type = SOCKET_MSG_TYPE_CLIENT,
.client = client,
};
#endif
if (hclient->auth) {
log_info("auth(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_auth, MAC2STR(hclient->address), hclient->freq, hclient->ssi_signal);
@ -167,12 +174,12 @@ int wifi_clients_try(struct hostapd_client *hclient) {
if(!hclient->auth){
client->try_probe = 0;
log_verbose("accept\n");
returnINFO_CLIENT 0;
return 0;
}
log_info("accept\n");
client->try_auth = 0;
client->connected = 1;
returnINFO_CLIENT 0;
return 0;
}
if (client->freq_highest > WIFI_CLIENT_FREQ_THREASHOLD) {
if (config_client_force || config_client_force_probe && !hclient->auth) {