mirror of
https://github.com/berlin-open-wireless-lab/DAWN.git
synced 2025-03-09 15:40:12 +00:00
first version
This commit is contained in:
commit
f03f55ff92
28 changed files with 5682 additions and 0 deletions
54
src/CMakeLists.txt
Executable file
54
src/CMakeLists.txt
Executable file
|
@ -0,0 +1,54 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
PROJECT(dawn)
|
||||
|
||||
INCLUDE_DIRECTORIES(include)
|
||||
|
||||
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
|
||||
|
||||
storage/datastorage.c
|
||||
include/datastorage.h
|
||||
|
||||
network/networksocket.c
|
||||
include/networksocket.h
|
||||
|
||||
network/broadcastsocket.c
|
||||
include/broadcastsocket.h
|
||||
|
||||
network/multicastsocket.c
|
||||
include/multicastsocket.h
|
||||
|
||||
utils/ubus.c
|
||||
include/ubus.h
|
||||
|
||||
utils/dawn_uci.c
|
||||
include/dawn_uci.h
|
||||
|
||||
crypto/crypto.c
|
||||
include/crypto.h
|
||||
|
||||
include/utils.h
|
||||
utils/utils.c
|
||||
|
||||
include/tcpsocket.h
|
||||
network/tcpsocket.c
|
||||
|
||||
include/dawn_iwinfo.h
|
||||
utils/dawn_iwinfo.c
|
||||
|
||||
utils/ieee80211_utils.c
|
||||
include/ieee80211_utils.h)
|
||||
|
||||
SET(LIBS
|
||||
ubox ubus json-c blobmsg_json uci gcrypt iwinfo)
|
||||
|
||||
ADD_EXECUTABLE(dawn ${SOURCES})
|
||||
|
||||
TARGET_LINK_LIBRARIES(dawn ${LIBS})
|
||||
|
||||
INSTALL(TARGETS dawn
|
||||
RUNTIME DESTINATION /usr/sbin/)
|
100
src/crypto/crypto.c
Normal file
100
src/crypto/crypto.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
// based on:
|
||||
// https://github.com/vedantk/gcrypt-example/blob/master/gcry.cc
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gcrypt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define GCRY_CIPHER GCRY_CIPHER_AES128 // Pick the cipher here
|
||||
#define GCRY_C_MODE GCRY_CIPHER_MODE_ECB // Pick the cipher mode here
|
||||
|
||||
gcry_error_t gcry_error_handle;
|
||||
gcry_cipher_hd_t gcry_cipher_hd;
|
||||
|
||||
void gcrypt_init() {
|
||||
if (!gcry_check_version(GCRYPT_VERSION)) {
|
||||
fprintf(stderr, "gcrypt: library version mismatch");
|
||||
}
|
||||
gcry_error_t err = 0;
|
||||
err = gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
err |= gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0);
|
||||
err |= gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
|
||||
err |= gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "gcrypt: failed initialization");
|
||||
}
|
||||
}
|
||||
|
||||
void gcrypt_set_key_and_iv(const char *key, const char *iv) {
|
||||
size_t keylen = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
|
||||
size_t blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
|
||||
|
||||
gcry_error_handle = gcry_cipher_open(
|
||||
&gcry_cipher_hd, // gcry_cipher_hd_t *
|
||||
GCRY_CIPHER, // int
|
||||
GCRY_C_MODE, // int
|
||||
0);
|
||||
if (gcry_error_handle) {
|
||||
fprintf(stderr, "gcry_cipher_open failed: %s/%s\n",
|
||||
gcry_strsource(gcry_error_handle),
|
||||
gcry_strerror(gcry_error_handle));
|
||||
return;
|
||||
}
|
||||
|
||||
gcry_error_handle = gcry_cipher_setkey(gcry_cipher_hd, key, keylen);
|
||||
if (gcry_error_handle) {
|
||||
fprintf(stderr, "gcry_cipher_setkey failed: %s/%s\n",
|
||||
gcry_strsource(gcry_error_handle),
|
||||
gcry_strerror(gcry_error_handle));
|
||||
return;
|
||||
}
|
||||
|
||||
gcry_error_handle = gcry_cipher_setiv(gcry_cipher_hd, iv, blklen);
|
||||
if (gcry_error_handle) {
|
||||
fprintf(stderr, "gcry_cipher_setiv failed: %s/%s\n",
|
||||
gcry_strsource(gcry_error_handle),
|
||||
gcry_strerror(gcry_error_handle));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// free out buffer after using!
|
||||
char *gcrypt_encrypt_msg(char *msg, size_t msg_length, int *out_length) {
|
||||
if (0U != (msg_length & 0xfU))
|
||||
msg_length += 0x10U - (msg_length & 0xfU);
|
||||
|
||||
char *out = malloc(msg_length);
|
||||
gcry_error_handle = gcry_cipher_encrypt(gcry_cipher_hd, out, msg_length, msg, msg_length);
|
||||
if (gcry_error_handle) {
|
||||
fprintf(stderr, "gcry_cipher_encrypt failed: %s/%s\n",
|
||||
gcry_strsource(gcry_error_handle),
|
||||
gcry_strerror(gcry_error_handle));
|
||||
return NULL;
|
||||
}
|
||||
*out_length = msg_length;
|
||||
return out;
|
||||
}
|
||||
|
||||
// free out buffer after using!
|
||||
char *gcrypt_decrypt_msg(char *msg, size_t msg_length) {
|
||||
if (0U != (msg_length & 0xfU))
|
||||
msg_length += 0x10U - (msg_length & 0xfU);
|
||||
|
||||
char *out_buffer = malloc(msg_length);
|
||||
gcry_error_handle = gcry_cipher_decrypt(gcry_cipher_hd, out_buffer, msg_length, msg, msg_length);
|
||||
if (gcry_error_handle) {
|
||||
fprintf(stderr, "gcry_cipher_encrypt failed: %s/%s\n",
|
||||
gcry_strsource(gcry_error_handle),
|
||||
gcry_strerror(gcry_error_handle));
|
||||
free(out_buffer);
|
||||
return NULL;
|
||||
}
|
||||
char *out = malloc(strlen(out_buffer) + 1);
|
||||
strcpy(out, out_buffer);
|
||||
free(out_buffer);
|
||||
return out;
|
||||
}
|
||||
|
14
src/include/broadcastsocket.h
Normal file
14
src/include/broadcastsocket.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef __DAWN_BROADCASTSOCKET_H
|
||||
#define __DAWN_BROADCASTSOCKET_H
|
||||
|
||||
|
||||
/**
|
||||
* Function that setups a broadcast socket.
|
||||
* @param _broadcast_ip - The broadcast ip to use.
|
||||
* @param _broadcast_port - The broadcast port to use.
|
||||
* @param addr The sockaddr_in struct.
|
||||
* @return the socket that was created.
|
||||
*/
|
||||
int setup_broadcast_socket(const char *_broadcast_ip, unsigned short _broadcast_port, struct sockaddr_in *addr);
|
||||
|
||||
#endif
|
38
src/include/crypto.h
Normal file
38
src/include/crypto.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef DAWN_CRYPTO_H
|
||||
#define DAWN_CRYPTO_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Initialize gcrypt.
|
||||
* Has to be called before using the other functions!
|
||||
*/
|
||||
void gcrypt_init();
|
||||
|
||||
/**
|
||||
* Set the Key and the iv.
|
||||
* @param key
|
||||
* @param iv
|
||||
*/
|
||||
void gcrypt_set_key_and_iv(const char *key, const char *iv);
|
||||
|
||||
/**
|
||||
* Function that encrypts the message.
|
||||
* Free the string after using it!
|
||||
* @param msg
|
||||
* @param msg_length
|
||||
* @param out_length
|
||||
* @return the encrypted string.
|
||||
*/
|
||||
char *gcrypt_encrypt_msg(char *msg, size_t msg_length, int *out_length);
|
||||
|
||||
/**
|
||||
* FUnction that decrypts a message.
|
||||
* Free the string after using it!
|
||||
* @param msg
|
||||
* @param msg_length
|
||||
* @return the decrypted string.
|
||||
*/
|
||||
char *gcrypt_decrypt_msg(char *msg, size_t msg_length);
|
||||
|
||||
#endif //DAWN_CRYPTO_H
|
267
src/include/datastorage.h
Normal file
267
src/include/datastorage.h
Normal file
|
@ -0,0 +1,267 @@
|
|||
#ifndef __DAWN_DATASTORAGE_H
|
||||
#define __DAWN_DATASTORAGE_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <libubox/blobmsg_json.h>
|
||||
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
#endif
|
||||
|
||||
/* Mac */
|
||||
|
||||
// ---------------- Defines -------------------
|
||||
#define MAC_LIST_LENGTH 100
|
||||
|
||||
// ---------------- Structs ----------------
|
||||
uint8_t mac_list[MAC_LIST_LENGTH][ETH_ALEN];
|
||||
|
||||
// ---------------- Functions ----------
|
||||
void insert_macs_from_file();
|
||||
|
||||
int insert_to_maclist(uint8_t mac[]);
|
||||
|
||||
int mac_in_maclist(uint8_t mac[]);
|
||||
|
||||
|
||||
/* Metric */
|
||||
|
||||
struct probe_metric_s dawn_metric;
|
||||
|
||||
// ---------------- Structs ----------------
|
||||
struct probe_metric_s {
|
||||
int ap_weight;
|
||||
int ht_support;
|
||||
int vht_support;
|
||||
int no_ht_support;
|
||||
int no_vht_support;
|
||||
int rssi;
|
||||
int low_rssi;
|
||||
int freq;
|
||||
int chan_util;
|
||||
int max_chan_util;
|
||||
int rssi_val;
|
||||
int low_rssi_val;
|
||||
int chan_util_val;
|
||||
int max_chan_util_val;
|
||||
int min_probe_count;
|
||||
int bandwith_threshold;
|
||||
int use_station_count;
|
||||
int max_station_diff;
|
||||
int eval_probe_req;
|
||||
int eval_auth_req;
|
||||
int eval_assoc_req;
|
||||
int deny_auth_reason;
|
||||
int deny_assoc_reason;
|
||||
int use_driver_recog;
|
||||
int min_kick_count;
|
||||
int chan_util_avg_period;
|
||||
int kicking;
|
||||
};
|
||||
|
||||
struct time_config_s {
|
||||
time_t update_client;
|
||||
time_t remove_client;
|
||||
time_t remove_probe;
|
||||
time_t remove_ap;
|
||||
time_t update_hostapd;
|
||||
time_t update_tcp_con;
|
||||
time_t denied_req_threshold;
|
||||
time_t update_chan_util;
|
||||
};
|
||||
|
||||
struct network_config_s {
|
||||
const char *broadcast_ip;
|
||||
int broadcast_port;
|
||||
int tcp_port;
|
||||
int network_option;
|
||||
const char *multicast;
|
||||
const char *shared_key;
|
||||
const char *iv;
|
||||
int bool_multicast;
|
||||
int use_symm_enc;
|
||||
int collision_domain;
|
||||
int bandwidth;
|
||||
};
|
||||
|
||||
struct network_config_s network_config;
|
||||
struct time_config_s timeout_config;
|
||||
|
||||
// ---------------- Global variables ----------------
|
||||
struct probe_metric_s dawn_metric;
|
||||
|
||||
|
||||
/* Probe, Auth, Assoc */
|
||||
|
||||
// ---------------- Structs ----------------
|
||||
typedef struct probe_entry_s {
|
||||
uint8_t bssid_addr[ETH_ALEN];
|
||||
uint8_t client_addr[ETH_ALEN];
|
||||
uint8_t target_addr[ETH_ALEN];
|
||||
uint32_t signal;
|
||||
uint32_t freq;
|
||||
uint8_t ht_capabilities;
|
||||
uint8_t vht_capabilities;
|
||||
time_t time;
|
||||
int counter;
|
||||
int deny_counter;
|
||||
uint8_t max_supp_datarate;
|
||||
uint8_t min_supp_datarate;
|
||||
} probe_entry;
|
||||
|
||||
typedef struct auth_entry_s {
|
||||
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;
|
||||
int counter;
|
||||
} auth_entry;
|
||||
|
||||
typedef struct hostapd_notify_entry_s {
|
||||
uint8_t bssid_addr[ETH_ALEN];
|
||||
uint8_t client_addr[ETH_ALEN];
|
||||
} hostapd_notify_entry;
|
||||
|
||||
typedef struct auth_entry_s assoc_entry;
|
||||
|
||||
#define DENY_REQ_ARRAY_LEN 100
|
||||
struct auth_entry_s denied_req_array[DENY_REQ_ARRAY_LEN];
|
||||
pthread_mutex_t denied_array_mutex;
|
||||
|
||||
auth_entry insert_to_denied_req_array(auth_entry entry, int inc_counter);
|
||||
|
||||
// ---------------- Defines ----------------
|
||||
#define PROBE_ARRAY_LEN 1000
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
|
||||
// ---------------- Global variables ----------------
|
||||
struct probe_entry_s probe_array[PROBE_ARRAY_LEN];
|
||||
pthread_mutex_t probe_array_mutex;
|
||||
|
||||
// ---------------- Functions ----------------
|
||||
probe_entry insert_to_array(probe_entry entry, int inc_counter);
|
||||
|
||||
void probe_array_insert(probe_entry entry);
|
||||
|
||||
probe_entry probe_array_delete(probe_entry entry);
|
||||
|
||||
probe_entry probe_array_get_entry(uint8_t bssid_addr[], uint8_t client_addr[]);
|
||||
|
||||
void print_probe_array();
|
||||
|
||||
void print_probe_entry(probe_entry entry);
|
||||
|
||||
void print_auth_entry(auth_entry entry);
|
||||
|
||||
void uloop_add_data_cbs();
|
||||
|
||||
/* AP, Client */
|
||||
|
||||
// blobmsg_alloc_string_buffer(&b, "signature", 1024);
|
||||
#define SIGNATURE_LEN 1024
|
||||
|
||||
// ---------------- Structs ----------------
|
||||
typedef struct client_s {
|
||||
uint8_t bssid_addr[ETH_ALEN];
|
||||
uint8_t client_addr[ETH_ALEN];
|
||||
char signature[SIGNATURE_LEN];
|
||||
uint8_t ht_supported;
|
||||
uint8_t vht_supported;
|
||||
uint32_t freq;
|
||||
uint8_t auth;
|
||||
uint8_t assoc;
|
||||
uint8_t authorized;
|
||||
uint8_t preauth;
|
||||
uint8_t wds;
|
||||
uint8_t wmm;
|
||||
uint8_t ht;
|
||||
uint8_t vht;
|
||||
uint8_t wps;
|
||||
uint8_t mfp;
|
||||
time_t time;
|
||||
uint32_t aid;
|
||||
uint32_t kick_count;
|
||||
} client;
|
||||
|
||||
typedef struct ap_s {
|
||||
uint8_t bssid_addr[ETH_ALEN];
|
||||
uint32_t freq;
|
||||
uint8_t ht_support;
|
||||
uint8_t vht_support;
|
||||
uint32_t channel_utilization;
|
||||
time_t time;
|
||||
uint32_t station_count;
|
||||
uint8_t ssid[SSID_MAX_LEN];
|
||||
uint32_t collision_domain;
|
||||
uint32_t bandwidth;
|
||||
uint32_t ap_weight;
|
||||
} ap;
|
||||
|
||||
// ---------------- Defines ----------------
|
||||
#define ARRAY_AP_LEN 50
|
||||
#define TIME_THRESHOLD_AP 30
|
||||
#define ARRAY_CLIENT_LEN 1000
|
||||
#define TIME_THRESHOLD_CLIENT 30
|
||||
#define TIME_THRESHOLD_CLIENT_UPDATE 10
|
||||
#define TIME_THRESHOLD_CLIENT_KICK 60
|
||||
|
||||
// ---------------- Global variables ----------------
|
||||
struct client_s client_array[ARRAY_CLIENT_LEN];
|
||||
pthread_mutex_t client_array_mutex;
|
||||
struct ap_s ap_array[ARRAY_AP_LEN];
|
||||
pthread_mutex_t ap_array_mutex;
|
||||
|
||||
int mac_is_equal(uint8_t addr1[], uint8_t addr2[]);
|
||||
|
||||
int mac_is_greater(uint8_t addr1[], uint8_t addr2[]);
|
||||
|
||||
// ---------------- Functions ----------------
|
||||
|
||||
void insert_client_to_array(client entry);
|
||||
|
||||
void kick_clients(uint8_t bssid[], uint32_t id);
|
||||
|
||||
void client_array_insert(client entry);
|
||||
|
||||
client client_array_delete(client entry);
|
||||
|
||||
void print_client_array();
|
||||
|
||||
void print_client_entry(client entry);
|
||||
|
||||
ap insert_to_ap_array(ap entry);
|
||||
|
||||
void print_ap_array();
|
||||
|
||||
ap ap_array_get_ap(uint8_t bssid_addr[]);
|
||||
|
||||
int build_hearing_map_sort_client(struct blob_buf *b);
|
||||
|
||||
int build_network_overview(struct blob_buf *b);
|
||||
|
||||
int probe_array_set_all_probe_count(uint8_t client_addr[], uint32_t probe_count);
|
||||
|
||||
int ap_get_collision_count(int col_domain);
|
||||
|
||||
/* Utils */
|
||||
|
||||
// ---------------- Defines -------------------
|
||||
#define SORT_NUM 5
|
||||
|
||||
// ---------------- Global variables ----------------
|
||||
char *sort_string;
|
||||
|
||||
// ---------------- Functions -------------------
|
||||
int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], int automatic_kick);
|
||||
|
||||
|
||||
#endif
|
68
src/include/dawn_iwinfo.h
Normal file
68
src/include/dawn_iwinfo.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef DAWN_RSSI_H
|
||||
#define DAWN_RSSI_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Get RSSI using the mac adress of the client.
|
||||
* Function uses libiwinfo and searches through all interfaces that are existing.
|
||||
* @param client_addr - mac adress of the client
|
||||
* @return The RSSI of the client if successful. INT_MIN if client was not found.
|
||||
*/
|
||||
int get_rssi_iwinfo(__uint8_t *client_addr);
|
||||
|
||||
/**
|
||||
* Get expected throughut using the mac adress of the client.
|
||||
* Function uses libiwinfo and searches through all interfaces that are existing.
|
||||
* @param client_addr - mac adress of the client
|
||||
* @return
|
||||
* + The expected throughput of the client if successful.
|
||||
* + INT_MIN if client was not found.
|
||||
* + 0 if the client is not supporting this feature.
|
||||
*/
|
||||
int get_expected_throughput_iwinfo(uint8_t *client_addr);
|
||||
|
||||
/**
|
||||
* Get rx and tx bandwidth using the mac of the client.
|
||||
* Function uses libiwinfo and searches through all interfaces that are existing.
|
||||
* @param client_addr - mac adress of the client
|
||||
* @param rx_rate - float pointer for returning the rx rate
|
||||
* @param tx_rate - float pointer for returning the tx rate
|
||||
* @return 0 if successful 1 otherwise.
|
||||
*/
|
||||
int get_bandwidth_iwinfo(__uint8_t *client_addr, float *rx_rate, float *tx_rate);
|
||||
|
||||
/**
|
||||
* Function checks if two bssid adresses have the same essid.
|
||||
* Function uses libiwinfo and searches through all interfaces that are existing.
|
||||
* @param bssid_addr
|
||||
* @param bssid_addr_to_compares
|
||||
* @return 1 if the bssid adresses have the same essid.
|
||||
*/
|
||||
int compare_essid_iwinfo(__uint8_t *bssid_addr, __uint8_t *bssid_addr_to_compare);
|
||||
|
||||
/**
|
||||
* Function returns the expected throughput using the interface and the client address.
|
||||
* @param ifname
|
||||
* @param client_addr
|
||||
* @return
|
||||
* + The expected throughput of the client if successful.
|
||||
* + INT_MIN if client was not found.
|
||||
* + 0 if the client is not supporting this feature.
|
||||
*/
|
||||
int get_expected_throughput(const char *ifname, uint8_t *client_addr);
|
||||
|
||||
int get_bssid(const char *ifname, uint8_t *bssid_addr);
|
||||
|
||||
int get_ssid(const char *ifname, char *ssid);
|
||||
|
||||
int get_channel_utilization(const char *ifname, uint64_t *last_channel_time, uint64_t *last_channel_time_busy);
|
||||
|
||||
int support_ht(const char *ifname);
|
||||
|
||||
int support_vht(const char *ifname);
|
||||
|
||||
#endif //DAWN_RSSI_H
|
50
src/include/dawn_uci.h
Normal file
50
src/include/dawn_uci.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef DAWN_UCI_H
|
||||
#define DAWN_UCI_H
|
||||
|
||||
/**
|
||||
* Init uci. Call this function before using the other functions!
|
||||
* @return if call was successful.
|
||||
*/
|
||||
int uci_init();
|
||||
|
||||
/**
|
||||
* Clear uci. Call this function after using uci!
|
||||
* @return if call was successful.
|
||||
*/
|
||||
int uci_clear();
|
||||
|
||||
/**
|
||||
* Function that returns the metric for the load balancing sheme using uci.
|
||||
* @return the load balancing metric.
|
||||
*/
|
||||
struct probe_metric_s uci_get_dawn_metric();
|
||||
|
||||
/**
|
||||
* Function that returns a struct with all the time config values.
|
||||
* @return the time config values.
|
||||
*/
|
||||
struct time_config_s uci_get_time_config();
|
||||
|
||||
/**
|
||||
* Function that returns all the network informations.
|
||||
* @return the network config values.
|
||||
*/
|
||||
struct network_config_s uci_get_dawn_network();
|
||||
|
||||
/**
|
||||
* Function that returns the hostapd directory reading from the config file.
|
||||
* @return the hostapd directory.
|
||||
*/
|
||||
const char *uci_get_dawn_hostapd_dir();
|
||||
|
||||
/**
|
||||
* Function that returns the sort order.
|
||||
* @return the sort order.
|
||||
*/
|
||||
const char *uci_get_dawn_sort_order();
|
||||
|
||||
int uci_set_network(char* uci_cmd);
|
||||
|
||||
int uci_reset();
|
||||
|
||||
#endif //DAWN_UCI_H_H
|
20
src/include/ieee80211_utils.h
Normal file
20
src/include/ieee80211_utils.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef DAWN_IEEE80211_UTILS_H
|
||||
#define DAWN_IEEE80211_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Calculate bitrate using the supported rates values.
|
||||
* @param supp_rate_val
|
||||
* @return the bitrate.
|
||||
*/
|
||||
double iee80211_calculate_bitrate(uint8_t supp_rate_val);
|
||||
|
||||
/**
|
||||
* Calculate expected throughput in Mbit/sec.
|
||||
* @param exp_thr
|
||||
* @return
|
||||
*/
|
||||
double iee80211_calculate_expected_throughput_mbit(int exp_thr);
|
||||
|
||||
#endif //DAWN_IEEE80211_UTILS_H
|
21
src/include/multicastsocket.h
Normal file
21
src/include/multicastsocket.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef __DAWN_MULTICASTSTSOCKET_H
|
||||
#define __DAWN_MULTICASTSSOCKET_H
|
||||
|
||||
/**
|
||||
* Setup a multicast socket.
|
||||
* Setup permissions. Join the multicast group, etc. ...
|
||||
* @param _multicast_ip - multicast ip to use.
|
||||
* @param _multicast_port - multicast port to use.
|
||||
* @param addr
|
||||
* @return the multicast socket.
|
||||
*/
|
||||
int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_port, struct sockaddr_in *addr);
|
||||
|
||||
/**
|
||||
* Removes the multicast socket.
|
||||
* @param socket
|
||||
* @return
|
||||
*/
|
||||
int remove_multicast_socket(int socket);
|
||||
|
||||
#endif
|
39
src/include/networksocket.h
Normal file
39
src/include/networksocket.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef __DAWN_NETWORKSOCKET_H
|
||||
#define __DAWN_NETWORKSOCKET_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_mutex_t send_mutex;
|
||||
|
||||
/**
|
||||
* Init a socket using the runopts.
|
||||
* @param _ip - ip to use.
|
||||
* @param _port - port to use.
|
||||
* @param _multicast_socket - if socket should be multicast or broadcast.
|
||||
* @return the socket.
|
||||
*/
|
||||
int init_socket_runopts(const char *_ip, int _port, int _multicast_socket);
|
||||
|
||||
/**
|
||||
* Send message via network.
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
int send_string(char *msg);
|
||||
|
||||
/**
|
||||
* Send encrypted message via network.
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
int send_string_enc(char *msg);
|
||||
|
||||
/**
|
||||
* Close socket.
|
||||
*/
|
||||
void close_socket();
|
||||
|
||||
// save connections
|
||||
// struct sockaddr_in addr[100];
|
||||
|
||||
#endif
|
46
src/include/tcpsocket.h
Normal file
46
src/include/tcpsocket.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef DAWN_TCPSOCKET_H
|
||||
#define DAWN_TCPSOCKET_H
|
||||
|
||||
#include <libubox/ustream.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define ARRAY_NETWORK_LEN 50
|
||||
|
||||
struct network_con_s {
|
||||
struct list_head list;
|
||||
|
||||
struct uloop_fd fd;
|
||||
struct ustream_fd stream;
|
||||
struct sockaddr_in sock_addr;
|
||||
int connected;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add tcp connection.
|
||||
* @param ipv4
|
||||
* @param port
|
||||
* @return
|
||||
*/
|
||||
int add_tcp_conncection(char *ipv4, int port);
|
||||
|
||||
/**
|
||||
* Opens a tcp server and adds it to the uloop.
|
||||
* @param port
|
||||
* @return
|
||||
*/
|
||||
int run_server(int port);
|
||||
|
||||
/**
|
||||
* Send message via tcp to all other hosts.
|
||||
* @param msg
|
||||
*/
|
||||
void send_tcp(char *msg);
|
||||
|
||||
/**
|
||||
* Debug message.
|
||||
*/
|
||||
void print_tcp_array();
|
||||
|
||||
|
||||
#endif //DAWN_TCPSOCKET_H
|
165
src/include/ubus.h
Normal file
165
src/include/ubus.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
#ifndef __DAWN_UBUS_H
|
||||
#define __DAWN_UBUS_H
|
||||
|
||||
#include <libubox/blobmsg_json.h>
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
#include "datastorage.h"
|
||||
|
||||
// 802.11 Status codes
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
||||
#define WLAN_STATUS_DENIED_NOT_HT_SUPPORT 27
|
||||
#define WLAN_STATUS_DENIED_NOT_VHT_SUPPORT 104
|
||||
|
||||
// Disassociation Reason
|
||||
#define UNSPECIFIED_REASON 0
|
||||
#define NO_MORE_STAS 5
|
||||
|
||||
const char *hostapd_dir_glob;
|
||||
|
||||
/**
|
||||
* Init ubus.
|
||||
* Setup tcp socket.
|
||||
* Start ubus timer.
|
||||
* @param ubus_socket
|
||||
* @param hostapd_dir
|
||||
* @return
|
||||
*/
|
||||
int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir);
|
||||
|
||||
/**
|
||||
* Start the umdns timer for updating the zeroconfiguration properties.
|
||||
*/
|
||||
void start_umdns_update();
|
||||
|
||||
/**
|
||||
* Call umdns update to update the TCP connections.
|
||||
* @return
|
||||
*/
|
||||
int ubus_call_umdns();
|
||||
|
||||
/**
|
||||
* Parse to probe request.
|
||||
* @param msg
|
||||
* @param prob_req
|
||||
* @return
|
||||
*/
|
||||
int parse_to_probe_req(struct blob_attr *msg, probe_entry *prob_req);
|
||||
|
||||
/**
|
||||
* Parse to authentication request.
|
||||
* @param msg
|
||||
* @param auth_req
|
||||
* @return
|
||||
*/
|
||||
int parse_to_auth_req(struct blob_attr *msg, auth_entry *auth_req);
|
||||
|
||||
/**
|
||||
* Parse to association request.
|
||||
* @param msg
|
||||
* @param assoc_req
|
||||
* @return
|
||||
*/
|
||||
int parse_to_assoc_req(struct blob_attr *msg, assoc_entry *assoc_req);
|
||||
|
||||
/**
|
||||
* Dump a client array into the database.
|
||||
* @param msg - message to parse.
|
||||
* @param do_kick - use the automatic kick function when updating the clients.
|
||||
* @param id - ubus id.
|
||||
* @return
|
||||
*/
|
||||
int parse_to_clients(struct blob_attr *msg, int do_kick, uint32_t id);
|
||||
|
||||
/**
|
||||
* Parse to hostapd notify.
|
||||
* Notify are such notifications like:
|
||||
* + Disassociation
|
||||
* + Deauthentication
|
||||
* + ...
|
||||
* @param msg
|
||||
* @param notify_req
|
||||
* @return
|
||||
*/
|
||||
int parse_to_hostapd_notify(struct blob_attr *msg, hostapd_notify_entry *notify_req);
|
||||
|
||||
/**
|
||||
* Kick client from hostapd interface.
|
||||
* @param id - the ubus id.
|
||||
* @param client_addr - the client adress of the client to kick.
|
||||
* @param reason - the reason to kick the client.
|
||||
* @param deauth - if the client should be deauthenticated.
|
||||
* @param ban_time - the ban time the client is not allowed to connect again.
|
||||
*/
|
||||
void del_client_interface(uint32_t id, const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time);
|
||||
|
||||
/**
|
||||
* Kick client from all hostapd interfaces.
|
||||
* @param client_addr - the client adress of the client to kick.
|
||||
* @param reason - the reason to kick the client.
|
||||
* @param deauth - if the client should be deauthenticated.
|
||||
* @param ban_time - the ban time the client is not allowed to connect again.
|
||||
*/
|
||||
void del_client_all_interfaces(const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time);
|
||||
|
||||
/**
|
||||
* Send probe message via the network.
|
||||
* @param probe_entry
|
||||
* @return
|
||||
*/
|
||||
int ubus_send_probe_via_network(struct probe_entry_s probe_entry);
|
||||
|
||||
/**
|
||||
* Update the hostapd sockets.
|
||||
* @param t
|
||||
*/
|
||||
void update_hostapd_sockets(struct uloop_timeout *t);
|
||||
|
||||
/**
|
||||
* Set client timer for updating the clients.
|
||||
* @param time
|
||||
*/
|
||||
void add_client_update_timer(time_t time);
|
||||
|
||||
/**
|
||||
* Handle network messages.
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
int handle_network_msg(char *msg);
|
||||
|
||||
/**
|
||||
* Send message via network.
|
||||
* @param msg
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
int send_blob_attr_via_network(struct blob_attr *msg, char *method);
|
||||
|
||||
/**
|
||||
* Add mac to a list that contains addresses of clients that can not be controlled.
|
||||
* @param buf
|
||||
* @param name
|
||||
* @param addr
|
||||
*/
|
||||
void blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const uint8_t *addr);
|
||||
|
||||
/**
|
||||
* Function to set the probe counter to the min probe request.
|
||||
* This allows that the client is able to connect directly without sending multiple probe requests to the Access Point.
|
||||
* @param client_addr
|
||||
* @return
|
||||
*/
|
||||
int send_set_probe(uint8_t client_addr[]);
|
||||
|
||||
/**
|
||||
* Send control message to all hosts to add the mac to a don't control list.
|
||||
* @param client_addr
|
||||
* @return
|
||||
*/
|
||||
int send_add_mac(uint8_t *client_addr);
|
||||
|
||||
int uci_send_via_network();
|
||||
|
||||
#endif
|
50
src/include/utils.h
Normal file
50
src/include/utils.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef __DAWN_UTILS_H
|
||||
#define __DAWN_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
#define STR2MAC(a) &(a)[0], &(a)[1], &(a)[2], &(a)[3], &(a)[4], &(a)[5]
|
||||
|
||||
#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
|
||||
/**
|
||||
* Convert char to binary.
|
||||
* @param ch
|
||||
* @return
|
||||
*/
|
||||
int hex_to_bin(char ch);
|
||||
|
||||
/**
|
||||
* Convert mac adress string to mac adress.
|
||||
* @param txt
|
||||
* @param addr
|
||||
* @return
|
||||
*/
|
||||
int hwaddr_aton(const char *txt, uint8_t *addr);
|
||||
|
||||
/**
|
||||
* Convert mac to use big characters.
|
||||
* @param in
|
||||
* @param out
|
||||
* @return
|
||||
*/
|
||||
int convert_mac(char *in, char *out);
|
||||
|
||||
/**
|
||||
* Write mac to a file.
|
||||
* @param path
|
||||
* @param addr
|
||||
*/
|
||||
void write_mac_to_file(char *path, uint8_t addr[]);
|
||||
|
||||
/**
|
||||
* Check if a string is greater than another one.
|
||||
* @param str
|
||||
* @param str_2
|
||||
* @return
|
||||
*/
|
||||
int string_is_greater(uint8_t *str, uint8_t *str_2);
|
||||
|
||||
#endif
|
122
src/main.c
Normal file
122
src/main.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include <libubus.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "datastorage.h"
|
||||
#include "networksocket.h"
|
||||
#include "ubus.h"
|
||||
#include "dawn_uci.h"
|
||||
#include "tcpsocket.h"
|
||||
#include "crypto.h"
|
||||
|
||||
void daemon_shutdown();
|
||||
|
||||
void signal_handler(int sig);
|
||||
|
||||
int init_mutex();
|
||||
|
||||
struct sigaction signal_action;
|
||||
|
||||
void daemon_shutdown() {
|
||||
// kill threads
|
||||
close_socket();
|
||||
uci_clear();
|
||||
uloop_cancelled = true;
|
||||
|
||||
// free ressources
|
||||
fprintf(stdout, "Freeing mutex ressources\n");
|
||||
pthread_mutex_destroy(&probe_array_mutex);
|
||||
pthread_mutex_destroy(&client_array_mutex);
|
||||
pthread_mutex_destroy(&ap_array_mutex);
|
||||
}
|
||||
|
||||
void signal_handler(int sig) {
|
||||
switch (sig) {
|
||||
case SIGHUP:
|
||||
daemon_shutdown();
|
||||
break;
|
||||
case SIGINT:
|
||||
daemon_shutdown();
|
||||
break;
|
||||
case SIGTERM:
|
||||
daemon_shutdown();
|
||||
exit(EXIT_SUCCESS);
|
||||
default:
|
||||
daemon_shutdown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int init_mutex() {
|
||||
|
||||
if (pthread_mutex_init(&probe_array_mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Mutex init failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&client_array_mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Mutex init failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&ap_array_mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Mutex init failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&denied_array_mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Mutex init failed!\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
const char *ubus_socket = NULL;
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
// connect signals
|
||||
signal_action.sa_handler = signal_handler;
|
||||
sigemptyset(&signal_action.sa_mask);
|
||||
signal_action.sa_flags = 0;
|
||||
sigaction(SIGHUP, &signal_action, NULL);
|
||||
sigaction(SIGTERM, &signal_action, NULL);
|
||||
sigaction(SIGINT, &signal_action, NULL);
|
||||
|
||||
uci_init();
|
||||
struct network_config_s net_config = uci_get_dawn_network();
|
||||
network_config = net_config;
|
||||
|
||||
// init crypto
|
||||
gcrypt_init();
|
||||
gcrypt_set_key_and_iv(net_config.shared_key, net_config.iv);
|
||||
|
||||
struct time_config_s time_config = uci_get_time_config();
|
||||
timeout_config = time_config; // TODO: Refactor...
|
||||
|
||||
hostapd_dir_glob = uci_get_dawn_hostapd_dir();
|
||||
sort_string = (char *) uci_get_dawn_sort_order();
|
||||
|
||||
init_mutex();
|
||||
|
||||
switch (net_config.network_option) {
|
||||
case 0:
|
||||
init_socket_runopts(net_config.broadcast_ip, net_config.broadcast_port, 0);
|
||||
break;
|
||||
case 1:
|
||||
init_socket_runopts(net_config.broadcast_ip, net_config.broadcast_port, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
insert_macs_from_file();
|
||||
dawn_init_ubus(ubus_socket, hostapd_dir_glob);
|
||||
|
||||
return 0;
|
||||
}
|
41
src/network/broadcastsocket.c
Normal file
41
src/network/broadcastsocket.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "networksocket.h"
|
||||
#include "broadcastsocket.h"
|
||||
|
||||
int setup_broadcast_socket(const char *_broadcast_ip, unsigned short _broadcast_port, struct sockaddr_in *addr) {
|
||||
int sock;
|
||||
int broadcast_permission;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Constract addess
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr.s_addr = inet_addr(_broadcast_ip);
|
||||
addr->sin_port = htons(_broadcast_port);
|
||||
|
||||
// Bind socket
|
||||
while (bind(sock, (struct sockaddr *) addr, sizeof(*addr)) < 0) {
|
||||
fprintf(stderr, "Binding socket failed!\n");
|
||||
sleep(1);
|
||||
}
|
||||
return sock;
|
||||
}
|
83
src/network/multicastsocket.c
Normal file
83
src/network/multicastsocket.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "multicastsocket.h"
|
||||
|
||||
// based on: http://openbook.rheinwerk-verlag.de/linux_unix_programmierung/Kap11-018.htm
|
||||
|
||||
static struct ip_mreq command;
|
||||
|
||||
int setup_multicast_socket(const char *_multicast_ip, unsigned short _multicast_port, struct sockaddr_in *addr) {
|
||||
int loop = 1;
|
||||
int sock;
|
||||
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr.s_addr = inet_addr(_multicast_ip);
|
||||
addr->sin_port = htons (_multicast_port);
|
||||
|
||||
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
perror("socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// allow multiple processes to use the same port
|
||||
loop = 1;
|
||||
if (setsockopt(sock,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
&loop, sizeof(loop)) < 0) {
|
||||
perror("setsockopt:SO_REUSEADDR");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (bind(sock,
|
||||
(struct sockaddr *) addr,
|
||||
sizeof(*addr)) < 0) {
|
||||
perror("bind");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// allow broadcast
|
||||
loop = 1;
|
||||
if (setsockopt(sock,
|
||||
IPPROTO_IP,
|
||||
IP_MULTICAST_LOOP,
|
||||
&loop, sizeof(loop)) < 0) {
|
||||
perror("setsockopt:IP_MULTICAST_LOOP");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// join broadcast group
|
||||
command.imr_multiaddr.s_addr = inet_addr(_multicast_ip);
|
||||
command.imr_interface.s_addr = htonl (INADDR_ANY);
|
||||
if (command.imr_multiaddr.s_addr == -1) {
|
||||
perror("Wrong multicast address!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (setsockopt(sock,
|
||||
IPPROTO_IP,
|
||||
IP_ADD_MEMBERSHIP,
|
||||
&command, sizeof(command)) < 0) {
|
||||
perror("setsockopt:IP_ADD_MEMBERSHIP");
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
int remove_multicast_socket(int socket) {
|
||||
if (setsockopt(socket,
|
||||
IPPROTO_IP,
|
||||
IP_DROP_MEMBERSHIP,
|
||||
&command, sizeof(command)) < 0) {
|
||||
perror("setsockopt:IP_DROP_MEMBERSHIP");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
162
src/network/networksocket.c
Normal file
162
src/network/networksocket.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libubox/blobmsg_json.h>
|
||||
|
||||
#include "networksocket.h"
|
||||
#include "datastorage.h"
|
||||
#include "multicastsocket.h"
|
||||
#include "broadcastsocket.h"
|
||||
#include "ubus.h"
|
||||
#include "crypto.h"
|
||||
|
||||
/* Network Defines */
|
||||
#define MAX_RECV_STRING 2048
|
||||
|
||||
/* Network Attributes */
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
const char *ip;
|
||||
unsigned short port;
|
||||
char recv_string[MAX_RECV_STRING + 1];
|
||||
int recv_string_len;
|
||||
int multicast_socket;
|
||||
|
||||
void *receive_msg(void *args);
|
||||
|
||||
void *receive_msg_enc(void *args);
|
||||
|
||||
int init_socket_runopts(const char *_ip, int _port, int _multicast_socket) {
|
||||
|
||||
port = _port;
|
||||
ip = _ip;
|
||||
multicast_socket = _multicast_socket;
|
||||
|
||||
if (multicast_socket) {
|
||||
printf("Settingup multicastsocket!\n");
|
||||
sock = setup_multicast_socket(ip, port, &addr);
|
||||
} else {
|
||||
sock = setup_broadcast_socket(ip, port, &addr);
|
||||
}
|
||||
|
||||
pthread_t sniffer_thread;
|
||||
if (network_config.use_symm_enc) {
|
||||
if (pthread_create(&sniffer_thread, NULL, receive_msg_enc, NULL)) {
|
||||
fprintf(stderr, "Could not create receiving thread!\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (pthread_create(&sniffer_thread, NULL, receive_msg, NULL)) {
|
||||
fprintf(stderr, "Could not create receiving thread!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "Connected to %s:%d\n", ip, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *receive_msg(void *args) {
|
||||
while (1) {
|
||||
if ((recv_string_len =
|
||||
recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0)) < 0) {
|
||||
fprintf(stderr, "Could not receive message!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recv_string == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(recv_string) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
recv_string[recv_string_len] = '\0';
|
||||
|
||||
printf("Received network message: %s\n", recv_string);
|
||||
handle_network_msg(recv_string);
|
||||
}
|
||||
}
|
||||
|
||||
void *receive_msg_enc(void *args) {
|
||||
while (1) {
|
||||
if ((recv_string_len =
|
||||
recvfrom(sock, recv_string, MAX_RECV_STRING, 0, NULL, 0)) < 0) {
|
||||
fprintf(stderr, "Could not receive message!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recv_string == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(recv_string) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
recv_string[recv_string_len] = '\0';
|
||||
|
||||
char *base64_dec_str = malloc(B64_DECODE_LEN(strlen(recv_string)));
|
||||
int base64_dec_length = b64_decode(recv_string, base64_dec_str, B64_DECODE_LEN(strlen(recv_string)));
|
||||
char *dec = gcrypt_decrypt_msg(base64_dec_str, base64_dec_length);
|
||||
|
||||
printf("Received network message: %s\n", dec);
|
||||
free(base64_dec_str);
|
||||
handle_network_msg(dec);
|
||||
free(dec);
|
||||
}
|
||||
}
|
||||
|
||||
int send_string(char *msg) {
|
||||
pthread_mutex_lock(&send_mutex);
|
||||
size_t msglen = strlen(msg);
|
||||
|
||||
if (sendto(sock,
|
||||
msg,
|
||||
msglen,
|
||||
0,
|
||||
(struct sockaddr *) &addr,
|
||||
sizeof(addr)) < 0) {
|
||||
perror("sendto()");
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_string_enc(char *msg) {
|
||||
pthread_mutex_lock(&send_mutex);
|
||||
|
||||
int length_enc;
|
||||
size_t msglen = strlen(msg);
|
||||
char *enc = gcrypt_encrypt_msg(msg, msglen + 1, &length_enc);
|
||||
|
||||
char *base64_enc_str = malloc(B64_ENCODE_LEN(length_enc));
|
||||
size_t base64_enc_length = b64_encode(enc, length_enc, base64_enc_str, B64_ENCODE_LEN(length_enc));
|
||||
|
||||
if (sendto(sock,
|
||||
base64_enc_str,
|
||||
base64_enc_length, // very important to use actual length of string because of '\0' in encrypted msg
|
||||
0,
|
||||
(struct sockaddr *) &addr,
|
||||
sizeof(addr)) < 0) {
|
||||
perror("sendto()");
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
free(base64_enc_str);
|
||||
free(enc);
|
||||
pthread_mutex_unlock(&send_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_socket() {
|
||||
if (multicast_socket) {
|
||||
remove_multicast_socket(sock);
|
||||
}
|
||||
close(sock);
|
||||
}
|
288
src/network/tcpsocket.c
Normal file
288
src/network/tcpsocket.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
#include <libubox/usock.h>
|
||||
#include <libubox/ustream.h>
|
||||
#include <libubox/uloop.h>
|
||||
#include <libubox/utils.h> // base64 encoding
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "tcpsocket.h"
|
||||
#include <arpa/inet.h>
|
||||
#include "ubus.h"
|
||||
#include "crypto.h"
|
||||
|
||||
LIST_HEAD(tcp_sock_list);
|
||||
|
||||
struct network_con_s *tcp_list_contains_address(struct sockaddr_in entry);
|
||||
|
||||
static struct uloop_fd server;
|
||||
struct client *next_client = NULL;
|
||||
|
||||
struct client {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
struct ustream_fd s;
|
||||
int ctr;
|
||||
int counter;
|
||||
};
|
||||
|
||||
static void client_close(struct ustream *s) {
|
||||
struct client *cl = container_of(s,
|
||||
struct client, s.stream);
|
||||
|
||||
fprintf(stderr, "Connection closed\n");
|
||||
ustream_free(s);
|
||||
close(cl->s.fd.fd);
|
||||
free(cl);
|
||||
}
|
||||
|
||||
static void client_notify_write(struct ustream *s, int bytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
static void client_notify_state(struct ustream *s) {
|
||||
struct client *cl = container_of(s,
|
||||
struct client, s.stream);
|
||||
|
||||
if (!s->eof)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "eof!, pending: %d, total: %d\n", s->w.data_bytes, cl->ctr);
|
||||
|
||||
if (!s->w.data_bytes)
|
||||
return client_close(s);
|
||||
|
||||
}
|
||||
|
||||
static void client_to_server_close(struct ustream *s) {
|
||||
struct network_con_s *con = container_of(s,
|
||||
struct network_con_s, stream.stream);
|
||||
|
||||
fprintf(stderr, "Connection to server closed\n");
|
||||
ustream_free(s);
|
||||
close(con->fd.fd);
|
||||
list_del(&con->list);
|
||||
free(con);
|
||||
}
|
||||
|
||||
static void client_to_server_state(struct ustream *s) {
|
||||
struct client *cl = container_of(s,
|
||||
struct client, s.stream);
|
||||
|
||||
if (!s->eof)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "eof!, pending: %d, total: %d\n", s->w.data_bytes, cl->ctr);
|
||||
|
||||
if (!s->w.data_bytes)
|
||||
return client_to_server_close(s);
|
||||
|
||||
}
|
||||
|
||||
static void client_read_cb(struct ustream *s, int bytes) {
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
do {
|
||||
str = ustream_get_read_buf(s, &len);
|
||||
if (!str)
|
||||
break;
|
||||
|
||||
if (network_config.use_symm_enc) {
|
||||
char *base64_dec_str = malloc(B64_DECODE_LEN(strlen(str)));
|
||||
int base64_dec_length = b64_decode(str, base64_dec_str, B64_DECODE_LEN(strlen(str)));
|
||||
char *dec = gcrypt_decrypt_msg(base64_dec_str, base64_dec_length);
|
||||
|
||||
free(base64_dec_str);
|
||||
handle_network_msg(dec);
|
||||
free(dec);
|
||||
} else {
|
||||
handle_network_msg(str);
|
||||
}
|
||||
|
||||
ustream_consume(s, len);
|
||||
|
||||
} while (1);
|
||||
|
||||
if (s->w.data_bytes > 256 && !ustream_read_blocked(s)) {
|
||||
fprintf(stderr, "Block read, bytes: %d\n", s->w.data_bytes);
|
||||
ustream_set_read_blocked(s, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_cb(struct uloop_fd *fd, unsigned int events) {
|
||||
struct client *cl;
|
||||
unsigned int sl = sizeof(struct sockaddr_in);
|
||||
int sfd;
|
||||
|
||||
if (!next_client)
|
||||
next_client = calloc(1, sizeof(*next_client));
|
||||
|
||||
cl = next_client;
|
||||
sfd = accept(server.fd, (struct sockaddr *) &cl->sin, &sl);
|
||||
if (sfd < 0) {
|
||||
fprintf(stderr, "Accept failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cl->s.stream.string_data = 1;
|
||||
cl->s.stream.notify_read = client_read_cb;
|
||||
cl->s.stream.notify_state = client_notify_state;
|
||||
cl->s.stream.notify_write = client_notify_write;
|
||||
ustream_fd_init(&cl->s, sfd);
|
||||
next_client = NULL;
|
||||
fprintf(stderr, "New connection\n");
|
||||
}
|
||||
|
||||
int run_server(int port) {
|
||||
char port_str[12];
|
||||
sprintf(port_str, "%d", port);
|
||||
|
||||
server.cb = server_cb;
|
||||
server.fd = usock(USOCK_TCP | USOCK_SERVER | USOCK_IPV4ONLY | USOCK_NUMERIC, INADDR_ANY, port_str);
|
||||
if (server.fd < 0) {
|
||||
perror("usock");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uloop_fd_add(&server, ULOOP_READ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void client_not_be_used_read_cb(struct ustream *s, int bytes) {
|
||||
int len;
|
||||
char buf[2048];
|
||||
|
||||
len = ustream_read(s, buf, sizeof(buf));
|
||||
buf[len] = '\0';
|
||||
printf("Read %d bytes from SSL connection: %s\n", len, buf);
|
||||
}
|
||||
|
||||
static void connect_cb(struct uloop_fd *f, unsigned int events) {
|
||||
|
||||
struct network_con_s *entry = container_of(f,
|
||||
struct network_con_s, fd);
|
||||
|
||||
if (f->eof || f->error) {
|
||||
fprintf(stderr, "Connection failed\n");
|
||||
close(entry->fd.fd);
|
||||
list_del(&entry->list);
|
||||
free(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Connection established\n");
|
||||
uloop_fd_delete(&entry->fd);
|
||||
|
||||
entry->stream.stream.notify_read = client_not_be_used_read_cb;
|
||||
entry->stream.stream.notify_state = client_to_server_state;
|
||||
|
||||
ustream_fd_init(&entry->stream, entry->fd.fd);
|
||||
entry->connected = 1;
|
||||
}
|
||||
|
||||
int add_tcp_conncection(char *ipv4, int port) {
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
char port_str[12];
|
||||
sprintf(port_str, "%d", port);
|
||||
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = inet_addr(ipv4);
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
struct network_con_s *tmp = tcp_list_contains_address(serv_addr);
|
||||
if (tmp != NULL) {
|
||||
if(tmp->connected == true)
|
||||
{
|
||||
return 0;
|
||||
} else{
|
||||
// Delete already existing entry
|
||||
close(tmp->fd.fd);
|
||||
list_del(&tmp->list);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
struct network_con_s *tcp_entry = calloc(1, sizeof(struct network_con_s));
|
||||
tcp_entry->fd.fd = usock(USOCK_TCP | USOCK_NONBLOCK, ipv4, port_str);
|
||||
tcp_entry->sock_addr = serv_addr;
|
||||
|
||||
if (tcp_entry->fd.fd < 0) {
|
||||
free(tcp_entry);
|
||||
return -1;
|
||||
}
|
||||
tcp_entry->fd.cb = connect_cb;
|
||||
uloop_fd_add(&tcp_entry->fd, ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
|
||||
|
||||
printf("New TCP connection to %s:%d\n", ipv4, port);
|
||||
list_add(&tcp_entry->list, &tcp_sock_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void send_tcp(char *msg) {
|
||||
print_tcp_array();
|
||||
if (network_config.use_symm_enc) {
|
||||
int length_enc;
|
||||
size_t msglen = strlen(msg);
|
||||
char *enc = gcrypt_encrypt_msg(msg, msglen + 1, &length_enc);
|
||||
|
||||
char *base64_enc_str = malloc(B64_ENCODE_LEN(length_enc));
|
||||
size_t base64_enc_length = b64_encode(enc, length_enc, base64_enc_str, B64_ENCODE_LEN(length_enc));
|
||||
struct network_con_s *con;
|
||||
list_for_each_entry(con, &tcp_sock_list, list)
|
||||
{
|
||||
if (con->connected) {
|
||||
int len_ustream = ustream_write(&con->stream.stream, base64_enc_str, base64_enc_length, 0);
|
||||
printf("Ustream send: %d\n", len_ustream);
|
||||
if (len_ustream <= 0) {
|
||||
fprintf(stderr,"Ustream error!\n");
|
||||
//TODO: ERROR HANDLING!
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(base64_enc_str);
|
||||
free(enc);
|
||||
} else {
|
||||
struct network_con_s *con;
|
||||
|
||||
list_for_each_entry(con, &tcp_sock_list, list)
|
||||
{
|
||||
if (con->connected) {
|
||||
if (ustream_printf(&con->stream.stream, "%s", msg) == 0) {
|
||||
//TODO: ERROR HANDLING!
|
||||
fprintf(stderr,"Ustream error!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct network_con_s* tcp_list_contains_address(struct sockaddr_in entry) {
|
||||
struct network_con_s *con;
|
||||
|
||||
list_for_each_entry(con, &tcp_sock_list, list)
|
||||
{
|
||||
if(entry.sin_addr.s_addr == con->sock_addr.sin_addr.s_addr)
|
||||
{
|
||||
return con;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print_tcp_array() {
|
||||
struct network_con_s *con;
|
||||
|
||||
printf("--------Connections------\n");
|
||||
list_for_each_entry(con, &tcp_sock_list, list)
|
||||
{
|
||||
printf("Conenctin to Port: %d, Connected: %s\n", con->sock_addr.sin_port, con->connected ? "True" : "False");
|
||||
}
|
||||
printf("------------------\n");
|
||||
}
|
1290
src/storage/datastorage.c
Normal file
1290
src/storage/datastorage.c
Normal file
File diff suppressed because it is too large
Load diff
356
src/utils/dawn_iwinfo.c
Normal file
356
src/utils/dawn_iwinfo.c
Normal file
|
@ -0,0 +1,356 @@
|
|||
#include "dawn_iwinfo.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <iwinfo.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "ubus.h"
|
||||
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
|
||||
int call_iwinfo(char *client_addr);
|
||||
|
||||
int parse_rssi(char *iwinfo_string);
|
||||
|
||||
int get_rssi(const char *ifname, uint8_t *client_addr);
|
||||
|
||||
int get_bandwidth(const char *ifname, uint8_t *client_addr, float *rx_rate, float *tx_rate);
|
||||
|
||||
#define IWINFO_BUFSIZE 24 * 1024
|
||||
|
||||
#define IWINFO_ESSID_MAX_SIZE 32
|
||||
|
||||
int compare_essid_iwinfo(__uint8_t *bssid_addr, __uint8_t *bssid_addr_to_compare) {
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
char mac_buf[20];
|
||||
char mac_buf_to_compare[20];
|
||||
sprintf(mac_buf, MACSTR, MAC2STR(bssid_addr));
|
||||
sprintf(mac_buf_to_compare, MACSTR, MAC2STR(bssid_addr_to_compare));
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *entry;
|
||||
dirp = opendir(hostapd_dir_glob); // error handling?
|
||||
if (!dirp) {
|
||||
fprintf(stderr, "[COMPARE ESSID] Failed to open %s\n", hostapd_dir_glob);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *essid = NULL;
|
||||
char *essid_to_compare = NULL;
|
||||
|
||||
char buf_essid[IWINFO_ESSID_MAX_SIZE + 1] = {0};
|
||||
char buf_essid_to_compare[IWINFO_ESSID_MAX_SIZE + 1] = {0};
|
||||
|
||||
while ((entry = readdir(dirp)) != NULL && (essid == NULL || essid_to_compare == NULL)) {
|
||||
if (entry->d_type == DT_SOCK) {
|
||||
|
||||
iw = iwinfo_backend(entry->d_name);
|
||||
|
||||
static char buf_bssid[18] = {0};
|
||||
if (iw->bssid(entry->d_name, buf_bssid))
|
||||
snprintf(buf_bssid, sizeof(buf_bssid), "00:00:00:00:00:00");
|
||||
|
||||
if (strcmp(mac_buf, buf_bssid) == 0) {
|
||||
|
||||
if (iw->ssid(entry->d_name, buf_essid))
|
||||
memset(buf_essid, 0, sizeof(buf_essid));
|
||||
essid = buf_essid;
|
||||
}
|
||||
|
||||
if (strcmp(mac_buf_to_compare, buf_bssid) == 0) {
|
||||
if (iw->ssid(entry->d_name, buf_essid_to_compare))
|
||||
memset(buf_essid_to_compare, 0, sizeof(buf_essid_to_compare));
|
||||
essid_to_compare = buf_essid_to_compare;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
printf("Comparing: %s with %s\n", essid, essid_to_compare);
|
||||
|
||||
if (essid == NULL || essid_to_compare == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(essid, essid_to_compare) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_bandwidth_iwinfo(__uint8_t *client_addr, float *rx_rate, float *tx_rate) {
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *entry;
|
||||
dirp = opendir(hostapd_dir_glob); // error handling?
|
||||
if (!dirp) {
|
||||
fprintf(stderr, "[BANDWITH INFO] Failed to open %s\n", hostapd_dir_glob);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sucess = 0;
|
||||
|
||||
while ((entry = readdir(dirp)) != NULL) {
|
||||
if (entry->d_type == DT_SOCK) {
|
||||
if (get_bandwidth(entry->d_name, client_addr, rx_rate, tx_rate)) {
|
||||
sucess = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
return sucess;
|
||||
}
|
||||
|
||||
int get_bandwidth(const char *ifname, uint8_t *client_addr, float *rx_rate, float *tx_rate) {
|
||||
|
||||
int i, len;
|
||||
char buf[IWINFO_BUFSIZE];
|
||||
struct iwinfo_assoclist_entry *e;
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
|
||||
if (iw->assoclist(ifname, buf, &len)) {
|
||||
fprintf(stderr, "No information available\n");
|
||||
iwinfo_finish();
|
||||
return 0;
|
||||
} else if (len <= 0) {
|
||||
fprintf(stderr, "No station connected\n");
|
||||
iwinfo_finish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
|
||||
e = (struct iwinfo_assoclist_entry *) &buf[i];
|
||||
|
||||
if (mac_is_equal(client_addr, e->mac)) {
|
||||
*rx_rate = e->rx_rate.rate / 1000;
|
||||
*tx_rate = e->tx_rate.rate / 1000;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_rssi_iwinfo(__uint8_t *client_addr) {
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *entry;
|
||||
dirp = opendir(hostapd_dir_glob); // error handling?
|
||||
if (!dirp) {
|
||||
fprintf(stderr, "[RSSI INFO] No hostapd sockets!\n");
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
int rssi = INT_MIN;
|
||||
|
||||
while ((entry = readdir(dirp)) != NULL) {
|
||||
if (entry->d_type == DT_SOCK) {
|
||||
rssi = get_rssi(entry->d_name, client_addr);
|
||||
if (rssi != INT_MIN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
int get_rssi(const char *ifname, uint8_t *client_addr) {
|
||||
|
||||
int i, len;
|
||||
char buf[IWINFO_BUFSIZE];
|
||||
struct iwinfo_assoclist_entry *e;
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
|
||||
if (iw->assoclist(ifname, buf, &len)) {
|
||||
fprintf(stderr, "No information available\n");
|
||||
iwinfo_finish();
|
||||
return INT_MIN;
|
||||
} else if (len <= 0) {
|
||||
fprintf(stderr, "No station connected\n");
|
||||
iwinfo_finish();
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
|
||||
e = (struct iwinfo_assoclist_entry *) &buf[i];
|
||||
|
||||
if (mac_is_equal(client_addr, e->mac))
|
||||
return e->signal;
|
||||
}
|
||||
|
||||
iwinfo_finish();
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
int get_expected_throughput_iwinfo(__uint8_t *client_addr) {
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *entry;
|
||||
dirp = opendir(hostapd_dir_glob); // error handling?
|
||||
if (!dirp) {
|
||||
fprintf(stderr, "[RSSI INFO] Failed to open dir:%s\n", hostapd_dir_glob);
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
int exp_thr = INT_MIN;
|
||||
|
||||
while ((entry = readdir(dirp)) != NULL) {
|
||||
if (entry->d_type == DT_SOCK) {
|
||||
exp_thr = get_expected_throughput(entry->d_name, client_addr);
|
||||
if (exp_thr != INT_MIN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
return exp_thr;
|
||||
}
|
||||
|
||||
int get_expected_throughput(const char *ifname, uint8_t *client_addr) {
|
||||
|
||||
int i, len;
|
||||
char buf[IWINFO_BUFSIZE];
|
||||
struct iwinfo_assoclist_entry *e;
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
|
||||
if (iw->assoclist(ifname, buf, &len)) {
|
||||
fprintf(stderr, "No information available\n");
|
||||
return INT_MIN;
|
||||
} else if (len <= 0) {
|
||||
fprintf(stderr, "No station connected\n");
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
|
||||
e = (struct iwinfo_assoclist_entry *) &buf[i];
|
||||
|
||||
if (mac_is_equal(client_addr, e->mac))
|
||||
return e->thr;
|
||||
}
|
||||
iwinfo_finish();
|
||||
|
||||
return INT_MIN;
|
||||
}
|
||||
|
||||
int get_bssid(const char *ifname, uint8_t *bssid_addr) {
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
|
||||
static char buf[18] = { 0 };
|
||||
|
||||
if (iw->bssid(ifname, buf))
|
||||
snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
|
||||
|
||||
hwaddr_aton(buf,bssid_addr);
|
||||
iwinfo_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_ssid(const char *ifname, char* ssid) {
|
||||
const struct iwinfo_ops *iw;
|
||||
char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
if (iw->ssid(ifname, buf))
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
memcpy(ssid, buf, (SSID_MAX_LEN) * sizeof(char));
|
||||
strcpy(ssid, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_channel_utilization(const char *ifname, uint64_t *last_channel_time, uint64_t *last_channel_time_busy) {
|
||||
|
||||
int len;
|
||||
const struct iwinfo_ops *iw;
|
||||
char buf[IWINFO_BUFSIZE];
|
||||
struct iwinfo_survey_entry *e;
|
||||
int ret = 0;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
|
||||
int freq;
|
||||
if (iw->frequency(ifname, &freq))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iw->survey(ifname, buf, &len))
|
||||
{
|
||||
fprintf(stderr, "Survey not possible!\n\n");
|
||||
return 0;
|
||||
}
|
||||
else if (len <= 0)
|
||||
{
|
||||
fprintf(stderr, "No survey results\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0, x = 1; i < len; i += sizeof(struct iwinfo_survey_entry), x++)
|
||||
{
|
||||
e = (struct iwinfo_survey_entry *) &buf[i];
|
||||
|
||||
if(e->mhz == freq)
|
||||
{
|
||||
uint64_t dividend = e->busy_time - *last_channel_time_busy;
|
||||
uint64_t divisor = e->active_time - *last_channel_time;
|
||||
*last_channel_time = e->active_time;
|
||||
*last_channel_time_busy = e->busy_time;
|
||||
|
||||
if(divisor)
|
||||
ret = (int)(dividend * 255 / divisor);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iwinfo_finish();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int support_ht(const char *ifname) {
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
int htmodes = 0;
|
||||
|
||||
if (iw->htmodelist(ifname, &htmodes))
|
||||
{
|
||||
printf("No HT mode information available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ht_support_bitmask = (1 << 0) | (1 << 2);
|
||||
int ret = htmodes & ht_support_bitmask ? 1 : 0;
|
||||
iwinfo_finish();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int support_vht(const char *ifname) {
|
||||
const struct iwinfo_ops *iw;
|
||||
|
||||
iw = iwinfo_backend(ifname);
|
||||
int htmodes = 0;
|
||||
|
||||
if (iw->htmodelist(ifname, &htmodes))
|
||||
{
|
||||
fprintf(stderr, "No VHT mode information available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t vht_support_bitmask = (1 << 2) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
|
||||
int ret = htmodes & vht_support_bitmask ? 1 : 0;
|
||||
iwinfo_finish();
|
||||
return ret;
|
||||
}
|
202
src/utils/dawn_uci.c
Normal file
202
src/utils/dawn_uci.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
#include <uci.h>
|
||||
#include <stdlib.h>
|
||||
#include <datastorage.h>
|
||||
|
||||
#include "dawn_uci.h"
|
||||
|
||||
|
||||
static struct uci_context *uci_ctx;
|
||||
static struct uci_package *uci_pkg;
|
||||
|
||||
// why is this not included in uci lib...?!
|
||||
// found here: https://github.com/br101/pingcheck/blob/master/uci.c
|
||||
static int uci_lookup_option_int(struct uci_context *uci, struct uci_section *s,
|
||||
const char *name) {
|
||||
const char *str = uci_lookup_option_string(uci, s, name);
|
||||
return str == NULL ? -1 : atoi(str);
|
||||
}
|
||||
|
||||
struct time_config_s uci_get_time_config() {
|
||||
struct time_config_s ret;
|
||||
|
||||
struct uci_element *e;
|
||||
uci_foreach_element(&uci_pkg->sections, e)
|
||||
{
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "times") == 0) {
|
||||
ret.update_client = uci_lookup_option_int(uci_ctx, s, "update_client");
|
||||
ret.remove_client = uci_lookup_option_int(uci_ctx, s, "remove_client");
|
||||
ret.remove_probe = uci_lookup_option_int(uci_ctx, s, "remove_probe");
|
||||
ret.update_hostapd = uci_lookup_option_int(uci_ctx, s, "update_hostapd");
|
||||
ret.remove_ap = uci_lookup_option_int(uci_ctx, s, "remove_ap");
|
||||
ret.update_tcp_con = uci_lookup_option_int(uci_ctx, s, "update_tcp_con");
|
||||
ret.denied_req_threshold = uci_lookup_option_int(uci_ctx, s, "denied_req_threshold");
|
||||
ret.update_chan_util = uci_lookup_option_int(uci_ctx, s, "update_chan_util");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct probe_metric_s uci_get_dawn_metric() {
|
||||
struct probe_metric_s ret;
|
||||
|
||||
struct uci_element *e;
|
||||
uci_foreach_element(&uci_pkg->sections, e)
|
||||
{
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "metric") == 0) {
|
||||
ret.ap_weight = uci_lookup_option_int(uci_ctx, s, "ap_weight");
|
||||
ret.kicking = uci_lookup_option_int(uci_ctx, s, "kicking");
|
||||
ret.ht_support = uci_lookup_option_int(uci_ctx, s, "ht_support");
|
||||
ret.vht_support = uci_lookup_option_int(uci_ctx, s, "vht_support");
|
||||
ret.no_ht_support = uci_lookup_option_int(uci_ctx, s, "no_ht_support");
|
||||
ret.no_vht_support = uci_lookup_option_int(uci_ctx, s, "no_vht_support");
|
||||
ret.rssi = uci_lookup_option_int(uci_ctx, s, "rssi");
|
||||
ret.freq = uci_lookup_option_int(uci_ctx, s, "freq");
|
||||
ret.rssi_val = uci_lookup_option_int(uci_ctx, s, "rssi_val");
|
||||
ret.chan_util = uci_lookup_option_int(uci_ctx, s, "chan_util");
|
||||
ret.max_chan_util = uci_lookup_option_int(uci_ctx, s, "max_chan_util");
|
||||
ret.chan_util_val = uci_lookup_option_int(uci_ctx, s, "chan_util_val");
|
||||
ret.max_chan_util_val = uci_lookup_option_int(uci_ctx, s, "max_chan_util_val");
|
||||
ret.min_probe_count = uci_lookup_option_int(uci_ctx, s, "min_probe_count");
|
||||
ret.low_rssi = uci_lookup_option_int(uci_ctx, s, "low_rssi");
|
||||
ret.low_rssi_val = uci_lookup_option_int(uci_ctx, s, "low_rssi_val");
|
||||
ret.bandwith_threshold = uci_lookup_option_int(uci_ctx, s, "bandwith_threshold");
|
||||
ret.use_station_count = uci_lookup_option_int(uci_ctx, s, "use_station_count");
|
||||
ret.eval_probe_req = uci_lookup_option_int(uci_ctx, s, "eval_probe_req");
|
||||
ret.eval_auth_req = uci_lookup_option_int(uci_ctx, s, "eval_auth_req");
|
||||
ret.eval_assoc_req = uci_lookup_option_int(uci_ctx, s, "eval_assoc_req");
|
||||
ret.deny_auth_reason = uci_lookup_option_int(uci_ctx, s, "deny_auth_reason");
|
||||
ret.deny_assoc_reason = uci_lookup_option_int(uci_ctx, s, "deny_assoc_reason");
|
||||
ret.max_station_diff = uci_lookup_option_int(uci_ctx, s, "max_station_diff");
|
||||
ret.use_driver_recog = uci_lookup_option_int(uci_ctx, s, "use_driver_recog");
|
||||
ret.min_kick_count = uci_lookup_option_int(uci_ctx, s, "min_number_to_kick");
|
||||
ret.chan_util_avg_period = uci_lookup_option_int(uci_ctx, s, "chan_util_avg_period");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct network_config_s uci_get_dawn_network() {
|
||||
struct network_config_s ret;
|
||||
|
||||
struct uci_element *e;
|
||||
uci_foreach_element(&uci_pkg->sections, e)
|
||||
{
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "network") == 0) {
|
||||
ret.broadcast_ip = uci_lookup_option_string(uci_ctx, s, "broadcast_ip");
|
||||
ret.broadcast_port = uci_lookup_option_int(uci_ctx, s, "broadcast_port");
|
||||
ret.bool_multicast = uci_lookup_option_int(uci_ctx, s, "multicast");
|
||||
ret.shared_key = uci_lookup_option_string(uci_ctx, s, "shared_key");
|
||||
ret.iv = uci_lookup_option_string(uci_ctx, s, "iv");
|
||||
ret.network_option = uci_lookup_option_int(uci_ctx, s, "network_option");
|
||||
ret.tcp_port = uci_lookup_option_int(uci_ctx, s, "tcp_port");
|
||||
ret.use_symm_enc = uci_lookup_option_int(uci_ctx, s, "use_symm_enc");
|
||||
ret.collision_domain = uci_lookup_option_int(uci_ctx, s, "collision_domain");
|
||||
ret.bandwidth = uci_lookup_option_int(uci_ctx, s, "bandwidth");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *uci_get_dawn_hostapd_dir() {
|
||||
struct uci_element *e;
|
||||
uci_foreach_element(&uci_pkg->sections, e)
|
||||
{
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "hostapd") == 0) {
|
||||
return uci_lookup_option_string(uci_ctx, s, "hostapd_dir");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *uci_get_dawn_sort_order() {
|
||||
struct uci_element *e;
|
||||
uci_foreach_element(&uci_pkg->sections, e)
|
||||
{
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
|
||||
if (strcmp(s->type, "ordering") == 0) {
|
||||
return uci_lookup_option_string(uci_ctx, s, "sort_order");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uci_reset()
|
||||
{
|
||||
uci_unload(uci_ctx, uci_pkg);
|
||||
uci_load(uci_ctx, "dawn", &uci_pkg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uci_init() {
|
||||
struct uci_context *ctx = uci_ctx;
|
||||
|
||||
if (!ctx) {
|
||||
ctx = uci_alloc_context();
|
||||
uci_ctx = ctx;
|
||||
|
||||
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||
} else {
|
||||
// shouldn't happen?
|
||||
uci_pkg = uci_lookup_package(ctx, "dawn");
|
||||
if (uci_pkg)
|
||||
uci_unload(ctx, uci_pkg);
|
||||
}
|
||||
|
||||
if (uci_load(ctx, "dawn", &uci_pkg))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uci_clear() {
|
||||
if (uci_pkg != NULL) {
|
||||
uci_unload(uci_ctx, uci_pkg);
|
||||
}
|
||||
if (uci_ctx != NULL) {
|
||||
uci_free_context(uci_ctx);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uci_set_network(char* uci_cmd)
|
||||
{
|
||||
struct uci_ptr ptr;
|
||||
int ret = UCI_OK;
|
||||
struct uci_context *ctx;
|
||||
|
||||
ctx = uci_alloc_context();
|
||||
ctx->flags |= UCI_FLAG_STRICT;
|
||||
|
||||
if (uci_lookup_ptr(ctx, &ptr, uci_cmd, 1) != UCI_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = uci_set(ctx, &ptr);
|
||||
|
||||
|
||||
if (uci_lookup_ptr(ctx, &ptr, "dawn", 1) != UCI_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (uci_commit(ctx, &ptr.p, 0) != UCI_OK) {
|
||||
fprintf(stderr, "Failed to commit UCI cmd: %s\n", uci_cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
11
src/utils/ieee80211_utils.c
Normal file
11
src/utils/ieee80211_utils.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "ieee80211_utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
double iee80211_calculate_bitrate(uint8_t supp_rate_val) {
|
||||
return ((double) supp_rate_val) / 2;
|
||||
}
|
||||
|
||||
double iee80211_calculate_expected_throughput_mbit(int exp_thr) {
|
||||
return (((double) exp_thr) / 1000);
|
||||
}
|
1619
src/utils/ubus.c
Normal file
1619
src/utils/ubus.c
Normal file
File diff suppressed because it is too large
Load diff
80
src/utils/utils.c
Normal file
80
src/utils/utils.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "utils.h"
|
||||
#include "ubus.h"
|
||||
|
||||
int string_is_greater(uint8_t *str, uint8_t *str_2) {
|
||||
|
||||
int length_1 = strlen((char *) str);
|
||||
int length_2 = strlen((char *) str_2);
|
||||
|
||||
int length = length_1 < length_2 ? length_1 : length_2;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (str[i] > str_2[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (str[i] < str_2[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return length_1 > length_2;
|
||||
}
|
||||
|
||||
// source: https://elixir.bootlin.com/linux/v4.9/source/lib/hexdump.c#L28
|
||||
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;
|
||||
}
|
||||
|
||||
// based on: hostapd src/utils/common.c
|
||||
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;
|
||||
}
|
||||
|
||||
int convert_mac(char *in, char *out) {
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (in[j + 1] != ':' && in[j + 1] != '\0') {
|
||||
out[3 * i] = toupper(in[j]);
|
||||
out[(3 * i) + 1] = toupper(in[j + 1]);
|
||||
out[(3 * i) + 2] = in[j + 2];
|
||||
j += 3;
|
||||
} else {
|
||||
out[3 * i] = '0';
|
||||
out[(3 * i) + 1] = toupper(in[j]);
|
||||
out[(3 * i) + 2] = toupper(in[j + 1]);
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write_mac_to_file(char *path, uint8_t addr[]) {
|
||||
FILE *f = fopen(path, "a");
|
||||
if (f == NULL) {
|
||||
fprintf(stderr,"Error opening mac file!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char mac_buf[20];
|
||||
sprintf(mac_buf, MACSTR, MAC2STR(addr));
|
||||
|
||||
fprintf(f, "%s\n", mac_buf);
|
||||
|
||||
fclose(f);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue