First version

This commit is contained in:
nickh 2017-05-30 22:16:06 +02:00
parent cf448f548a
commit 6257306d7e
14 changed files with 838 additions and 0 deletions

4
CMakeLists.txt Executable file
View file

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(dawn)
ADD_SUBDIRECTORY(src)

4
files/dawn.config Normal file
View file

@ -0,0 +1,4 @@
config 'settings' 'dawn'
option broadcast_ip '192.186.1.255'
option broadcast_port '1025'
option background '0'

40
files/dawn.init Executable file
View file

@ -0,0 +1,40 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=50
STOP=50
PROG=/usr/sbin/dawn
NAME=dawn
start_service()
{
echo "Starting Service..."
local broadcast_ip
local broadcast_port
config_load "${NAME}"
config_get broadcast_ip dawn broadcast_ip
config_get broadcast_port dawn broadcast_port
procd_open_instance
echo "$PROG -p $broadcast_port -i $broadcast_ip"
procd_set_param command "$PROG"
procd_append_param command -p "${broadcast_port}"
procd_append_param command -i "${broadcast_ip}"
procd_set_param stdout 1
procd_set_param stderr 1
echo "${command}"
#procd_append_param command stdout 1
procd_set_param respawn
echo "Closing instance"
procd_close_instance
echo "Dawn isntance started! (TESTstsasdft)"
}

20
src/CMakeLists.txt Executable file
View file

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(dawn)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations -Wno-unknown-warning-option -Wno-format-truncation)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
SET(SOURCES
main.c datastorage.c datastorage.h networksocket.c networksocket.h ubus.c ubus.h utils.h runopts.c runopts.h)
SET(LIBS
ubox ubus json-c blobmsg_json config)
ADD_EXECUTABLE(dawn ${SOURCES})
TARGET_LINK_LIBRARIES(dawn ${LIBS})
INSTALL(TARGETS dawn
RUNTIME DESTINATION /usr/bin/
)

264
src/datastorage.c Normal file
View file

@ -0,0 +1,264 @@
#include "datastorage.h"
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
int mac_is_equal(uint8_t addr1[], uint8_t addr2[]);
int mac_is_greater(uint8_t addr1[], uint8_t addr2[]);
void print_probe_entry(probe_entry entry);
int delete_probe_req(node* head, uint8_t bssid_addr[], uint8_t client_addr[]);
int mac_is_first_in_list(node* head, uint8_t bssid_addr[], uint8_t client_addr[]);
void insert_to_list(probe_entry entry)
{
pthread_mutex_lock(&list_mutex);
// first delete probe request
delete_probe_req(probe_list_head, entry.bssid_addr, entry.client_addr);
probe_list_head = insert(probe_list_head, entry);
pthread_mutex_unlock(&list_mutex);
}
node* insert(node* head, probe_entry entry) {
node *temp, *prev, *next;
temp = (node*)malloc(sizeof(node));
temp->data = entry;
temp->ptr = NULL;
if(!head)
{
head = temp;
}
else
{
// TODO: make sorting as startup parameter
prev = NULL;
next = head;
while(next
&& (
mac_is_greater(entry.client_addr, next->data.client_addr)
|| (
mac_is_equal(entry.client_addr, next->data.client_addr)
//&& !mac_is_equal(entry.bssid_addr, next->data.bssid_addr)
&& entry.signal < next->data.signal
)
|| (
mac_is_equal(entry.client_addr, next->data.client_addr)
//&& !mac_is_equal(entry.bssid_addr, next->data.bssid_addr)
&& entry.signal == next->data.signal
&& entry.freq < next->data.freq
)
|| (
mac_is_equal(entry.client_addr, next->data.client_addr)
//&& !mac_is_equal(entry.bssid_addr, next->data.bssid_addr)
&& entry.signal == next->data.signal
&& entry.freq == next->data.freq
&& mac_is_greater(entry.bssid_addr, next->data.bssid_addr)
)
)
)
{
/*
if(mac_is_smaller(entry.client_addr, next->data.client_addr)
{
break;
}
else if(mac_is_equal(entry.client_addr, next->data.client_addr)
{
if(entry.freq >= next->data.freq)
{
if(mac_is_smaller(entry.bssid_addr, next->data.bssid_addr))
{
break;
}
else if(mac_is_equal(entry.bssid_addr, next->data.bssid_addr))
{
if()
}
}
}*/
/*
if(mac_is_greater(entry.client_addr, next->data.client_addr))
{
if(entry.freq > next->data.freq)
{
if(entry.signal >= next->data.signal)
{
if(mac_is_greater(entry.bssid_addr, next->data.bssid_addr))
{
break;
}
}
}
}
*/
prev = next;
next = next->ptr;
}
if(next && mac_is_equal(entry.client_addr,next->data.client_addr)
&& mac_is_equal(entry.bssid_addr, next->data.bssid_addr)
)//&& entry.freq == next->data.freq)
{
next->data.signal = entry.signal;
}
else if(!next){
prev->ptr = temp;
}
else
{
if(prev) {
temp->ptr = prev->ptr;
prev-> ptr = temp;
} else {
temp->ptr = head;
head = temp;
}
}
}
return head;
}
int delete_probe_req(node* head, uint8_t bssid_addr[], uint8_t client_addr[])
{
if(!head)
{
return 1;
}
if(mac_is_equal(client_addr, head->data.client_addr)
&& mac_is_equal(bssid_addr, head->data.bssid_addr))
{
node *temp = head;
head = head->ptr;
free(temp);
return 1;
}
node *prev = NULL;
node *next = head;
while(next)
{
if(mac_is_greater(next->data.client_addr, client_addr))
{
break;
}
if(mac_is_equal(client_addr, next->data.client_addr)
&& mac_is_equal(bssid_addr, next->data.bssid_addr))
{
node *temp = next;
prev->ptr = next->ptr;
free(temp);
return 1;
}
prev = next;
next = next->ptr;
}
return 0;
}
int mac_is_first_in_list(node* head, uint8_t bssid_addr[], uint8_t client_addr[])
{
if(!head)
{
return 1;
}
node *next = head;
while(next)
{
if(mac_is_greater(next->data.client_addr, client_addr))
{
break;
}
if(mac_is_equal(client_addr, next->data.client_addr))
{
print_probe_entry(next->data);
return mac_is_equal(bssid_addr, next->data.bssid_addr);
}
next = next->ptr;
}
return 0;
}
int mac_first_in_probe_list(uint8_t bssid_addr[], uint8_t client_addr[])
{
pthread_mutex_lock(&list_mutex);
int ret = mac_is_first_in_list(probe_list_head, bssid_addr, client_addr);
pthread_mutex_unlock(&list_mutex);
return ret;
}
void free_list(node *head) {
node *prev = head;
node *cur = head;
while(cur) {
prev = cur;
cur = prev->ptr;
free(prev);
}
}
int mac_is_equal(uint8_t addr1[], uint8_t addr2[])
{
return memcmp(addr1, addr2, ETH_ALEN * sizeof(uint8_t)) == 0;
}
int mac_is_greater(uint8_t addr1[], uint8_t addr2[])
{
for(int i = 0; i < ETH_ALEN; i++)
{
if(addr1[i] > addr2[i])
{
return 1;
}
if(addr1[i] < addr2[i])
{
return 0;
}
// if equal continue...
}
return 0;
}
void print_list()
{
pthread_mutex_lock(&list_mutex);
node* head = probe_list_head;
if(!head)
{
return;
}
node* next;
next = head;
while(next)
{
print_probe_entry(next->data);
next = next->ptr;
}
pthread_mutex_unlock(&list_mutex);
}
void print_probe_entry(probe_entry entry)
{
char mac_buf_ap[20];
char mac_buf_client[20];
char mac_buf_target[20];
sprintf(mac_buf_ap, "%x:%x:%x:%x:%x:%x", MAC2STR(entry.bssid_addr));
sprintf(mac_buf_client, "%x:%x:%x:%x:%x:%x", MAC2STR(entry.client_addr));
sprintf(mac_buf_target, "%x:%x:%x:%x:%x:%x", MAC2STR(entry.target_addr));
printf("bssid_addr: %s, client_addr: %s, target_addr: %s, signal: %d, freq: %d\n",
mac_buf_ap, mac_buf_client, mac_buf_target, entry.signal, entry.freq);
}

41
src/datastorage.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef __DAWN_DATASTORAGE_H
#define __DAWN_DATASTORAGE_H
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <string.h>
#include <pthread.h>
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
// Probe entrys
typedef struct {
uint8_t bssid_addr[ETH_ALEN];
uint8_t client_addr[ETH_ALEN];
uint8_t target_addr[ETH_ALEN];
uint32_t signal;
uint32_t freq;
time_t time;
}probe_entry;
// List
typedef struct node{
probe_entry data;
struct node *ptr;
} node;
node* insert(node* head, probe_entry entry);
void free_list(node *head);
void print_list();
void insert_to_list(probe_entry entry);
int mac_first_in_probe_list(uint8_t bssid_addr[], uint8_t client_addr[]);
pthread_mutex_t list_mutex;
node* probe_list_head;
#endif

43
src/main.c Normal file
View file

@ -0,0 +1,43 @@
#include <stdio.h>
#include <libubus.h>
#include "ubus.h"
#include "datastorage.h"
#include "networksocket.h"
#define BUFSIZE 17
int main(int argc, char **argv)
{
const char *ubus_socket = NULL;
int ch;
char opt_broadcast_ip[BUFSIZE];
char opt_broadcast_port[BUFSIZE];
while ((ch = getopt(argc, argv, "cs:p:i:b:")) != -1) {
switch (ch) {
case 's':
ubus_socket = optarg;
break;
case 'p':
snprintf(opt_broadcast_port,BUFSIZE,"%s",optarg);
printf("broadcast port: %s\n", opt_broadcast_port);
break;
case 'i':
snprintf(opt_broadcast_ip,BUFSIZE,"%s",optarg);
printf("broadcast ip: %s\n", opt_broadcast_ip);
break;
default:
break;
}
}
argc -= optind;
argv += optind;
init_socket_runopts(opt_broadcast_ip, opt_broadcast_port);
dawn_init_ubus(ubus_socket);
return 0;
}

172
src/networksocket.c Normal file
View file

@ -0,0 +1,172 @@
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libconfig.h>
#include <libubox/blobmsg_json.h>
#include "networksocket.h"
#include "datastorage.h"
#include "ubus.h"
/* Network Defines */
#define MAX_RECV_STRING 255
#define NET_CONFIG_PATH "/etc/wlancontroller/networkconfig.conf"
/* Network Attributes */
int sock;
struct sockaddr_in broadcast_addr;
const char *broadcast_ip;
unsigned short broadcast_port;
int broadcast_permission;
char recv_string[MAX_RECV_STRING+1];
int recv_stringLen;
void* receive_msg(void *args);
int init_socket_runopts(char* _broadcast_ip, char* _broadcast_port){
int tmp_broacast_port = atoi(_broadcast_port);
init_socket(_broadcast_ip, tmp_broacast_port);
pthread_t sniffer_thread;
if( pthread_create( &sniffer_thread , NULL , receive_msg , NULL) )
{
fprintf(stderr, "Could not create receiving thread!");
return -1;
}
fprintf(stdout, "Connected to %s:%d\n", _broadcast_ip, tmp_broacast_port);
return 0;
}
int init_socket_conffile(){
const char *_broadcast_ip;
int _broacast_port;
config_t cfg;
//config_setting_t *setting;
const char *config_file_name = NET_CONFIG_PATH;
config_init(&cfg);
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&cfg, config_file_name))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
return(EXIT_FAILURE);
}
if(config_lookup_string(&cfg, "broadcast_ip", &_broadcast_ip))
printf("Broadcast IP: %s\n", _broadcast_ip);
else
fprintf(stderr, "No 'name' setting in configuration file.\n");
if(config_lookup_int(&cfg, "broacast_port", &_broacast_port))
printf("Broadcast Port: %d\n\n", _broacast_port);
else
fprintf(stderr, "No 'name' setting in configuration file.\n");
init_socket(_broadcast_ip, _broacast_port);
config_destroy(&cfg);
pthread_t sniffer_thread;
if( pthread_create( &sniffer_thread , NULL , receive_msg , NULL) )
{
fprintf(stderr, "Could not create receiving thread!");
return -1;
}
return 0;
}
void* receive_msg(void *args)
{
while(1)
{
if ((recv_stringLen = recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0)) < 0)
{
fprintf(stderr, "Could not receive message!");
continue;
}
printf("[WC] Network-Received: %s\n", recv_string);
probe_entry prob_req;
struct blob_buf b;
blob_buf_init(&b, 0);
blobmsg_add_json_from_string(&b, recv_string);
recv_string[recv_stringLen] = '\0';
char *str;
str = blobmsg_format_json(b.head, true);
printf("Parsed: '%s'\n", str);
parse_to_probe_req(b.head, &prob_req);
// insert to list
insert_to_list(prob_req);
}
}
int init_socket(const char *_broadcast_ip, unsigned short _broadcast_port)
{
broadcast_ip = _broadcast_ip;
broadcast_port = _broadcast_port;
/* Create socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
fprintf(stderr, "Failed to create socket.\n");
return -1;
}
/* Allow broadcast */
broadcast_permission = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *) &broadcast_permission,
sizeof(broadcast_permission)) < 0)
{
fprintf(stderr, "Failed to create socket.\n");
return -1;
}
/* Construct Address */
memset(&broadcast_addr, 0, sizeof(broadcast_addr));
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_addr.s_addr = inet_addr(broadcast_ip);
broadcast_addr.sin_port = htons(broadcast_port);
if (bind(sock, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr)) < 0)
{
fprintf(stderr, "Binding socket failed!\n");
return -1;
}
return 0;
}
int send_string(char *msg)
{
int msglen = strlen(msg);
if (sendto(sock, msg, msglen, 0, (struct sockaddr *)
&broadcast_addr, sizeof(broadcast_addr)) != msglen)
{
fprintf(stderr, "Failed to send message.\n");
return -1;
}
return 0;
}
void close_socket()
{
close(sock);
}

12
src/networksocket.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef __DAWN_NETWORKSOCKET_H
#define __DAWN_NETWORKSOCKET_H
#include "ubus.h"
int init_socket_runopts(char* broadcast_ip, char* broadcast_port);
int init_socket_conffile();
int init_socket(const char *_broadcastIP, unsigned short _broadcastPort);
int send_string(char *msg);
void close_socket();
#endif

2
src/runopts.c Normal file
View file

@ -0,0 +1,2 @@
#include "runopts.h"

4
src/runopts.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef __DAWN_RUNOPTS_H_
#define __DAWN_RUNOPTS_H_
#endif

185
src/ubus.c Normal file
View file

@ -0,0 +1,185 @@
#include <libubus.h>
#include <libubox/blobmsg_json.h>
#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
#include "networksocket.h"
#include "ubus.h"
#include "utils.h"
static struct ubus_context *ctx;
static struct ubus_subscriber hostapd_event;
enum {
PROB_BSSID_ADDR,
PROB_CLIENT_ADDR,
PROB_TARGET_ADDR,
PROB_SIGNAL,
PROB_FREQ,
__PROB_MAX,
};
static const struct blobmsg_policy prob_policy[__PROB_MAX] = {
[PROB_BSSID_ADDR] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING },
[PROB_CLIENT_ADDR] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
[PROB_TARGET_ADDR] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
[PROB_SIGNAL] = { .name = "signal", .type = BLOBMSG_TYPE_INT32 },
[PROB_FREQ] = { .name = "freq", .type = BLOBMSG_TYPE_INT32 },
};
/* Function Definitions */
static void hostapd_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s, uint32_t id);
static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg);
static int add_subscriber(char* name);
//int parse_to_probe_req(struct blob_attr *msg, probe_entry* prob_req);
static int subscribe_to_hostapd_interfaces();
static int decide_function(probe_entry* prob_req)
{
int ret = mac_first_in_probe_list(prob_req->bssid_addr, prob_req->client_addr);
if(ret)
{
printf("Mac will be accepted!\n");
} else
{
printf("Mac will be declined!\n");
}
return ret;
}
static void hostapd_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s, uint32_t id)
{
fprintf(stderr, "Object %08x went away\n", id);
}
int parse_to_probe_req(struct blob_attr *msg, probe_entry* prob_req)
{
struct blob_attr *tb[__PROB_MAX];
blobmsg_parse(prob_policy, __PROB_MAX, tb, blob_data(msg), blob_len(msg));
if (hwaddr_aton(blobmsg_data(tb[PROB_BSSID_ADDR]), prob_req->bssid_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[PROB_CLIENT_ADDR]), prob_req->client_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[PROB_TARGET_ADDR]), prob_req->target_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[PROB_SIGNAL])
{
prob_req->signal = blobmsg_get_u32(tb[PROB_SIGNAL]);
}
if (tb[PROB_FREQ])
{
prob_req->freq = blobmsg_get_u32(tb[PROB_FREQ]);
}
return 0;
}
static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
// write probe to table
probe_entry prob_req;
parse_to_probe_req(msg, &prob_req);
insert_to_list(prob_req);
// send probe via network
char *str;
str = blobmsg_format_json(msg, true);
send_string(str);
printf("[WC] Hostapd-Probe: %s : %s\n", method, str);
print_list();
// deny access
if(!decide_function(&prob_req))
{
return UBUS_STATUS_UNKNOWN_ERROR;
}
// allow access
return 0;
}
static int add_subscriber(char* name)
{
uint32_t id = 0;
if (ubus_lookup_id(ctx, name, &id)) {
fprintf(stderr, "Failed to look up test object for %s\n", name);
return -1;
}
// add callbacks
hostapd_event.remove_cb = hostapd_handle_remove;
hostapd_event.cb = hostapd_notify;
int ret = ubus_subscribe(ctx, &hostapd_event, id);
fprintf(stderr, "Watching object %08x: %s\n", id, ubus_strerror(ret));
return 0;
}
static int subscribe_to_hostapd_interfaces()
{
DIR * dirp;
struct dirent * entry;
int ret = ubus_register_subscriber(ctx, &hostapd_event);
if (ret)
{
fprintf(stderr, "Failed to add watch handler: %s\n", ubus_strerror(ret));
return -1;
}
dirp = opendir("/var/run/hostapd"); // error handling?
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_SOCK) {
char subscribe_name[256];
sprintf(subscribe_name, "hostapd.%s", entry->d_name);
printf("Subscribing to %s\n", subscribe_name);
add_subscriber(subscribe_name);
}
}
return 0;
}
int dawn_init_ubus(const char *ubus_socket)
{
uloop_init();
signal(SIGPIPE, SIG_IGN);
ctx = ubus_connect(ubus_socket);
if (!ctx) {
fprintf(stderr, "Failed to connect to ubus\n");
return -1;
} else {
printf("Connected to ubus\n");
}
ubus_add_uloop(ctx);
subscribe_to_hostapd_interfaces();
uloop_run();
close_socket();
ubus_free(ctx);
uloop_done();
return 0;
}

10
src/ubus.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __DAWN_UBUS_H
#define __DAWN_UBUS_H
#include "datastorage.h"
int dawn_init_ubus(const char *ubus_socket);
int parse_to_probe_req(struct blob_attr *msg, probe_entry* prob_req);
#endif

37
src/utils.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef __DAWN_UTILS_H
#define __DAWN_UTILS_H
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
static int hex_to_bin(char ch)
{
if ((ch >= '0') && (ch <= '9'))
return ch - '0';
ch = tolower(ch);
if ((ch >= 'a') && (ch <= 'f'))
return ch - 'a' + 10;
return -1;
}
static int hwaddr_aton(const char *txt, uint8_t *addr)
{
int i;
for (i = 0; i < ETH_ALEN; i++) {
int a, b;
a = hex_to_bin(*txt++);
if (a < 0)
return -1;
b = hex_to_bin(*txt++);
if (b < 0)
return -1;
*addr++ = (a << 4) | b;
if (i < 5 && *txt++ != ':')
return -1;
}
return 0;
}
#endif