first version

This commit is contained in:
Polynomialdivision 2020-03-23 19:18:13 +01:00
commit f03f55ff92
28 changed files with 5682 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)

33
INSTALL.md Normal file
View file

@ -0,0 +1,33 @@
## Installation
### Compiling DAWN
Add [bowlfeed](https://github.com/berlin-open-wireless-lab/bowl-feed.git) to feeds.conf
src-git bowlfeed git@github.com:berlin-open-wireless-lab/bowl-feed.git
Update Feeds
./scripts/feeds update -a
Install DAWN
./scripts/feeds install dawn
Select dawn under
make menuconfig
Compile
make package/dawn/compile
### Configure Dawn
Edit settings under
/etc/config/dawn
Restart daemon
/etc/init.d/dawn restart

340
LICENSE Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

119
README.md Normal file
View file

@ -0,0 +1,119 @@
![DAWN PICTURE](https://image.ibb.co/nbmNfJ/dawn_bla.png)
# DAWN
Decentralized WiFi Controller
## Related
|Repro |Content |
|------------------|--------------------------|
|[patches-pending](https://github.com/berlin-open-wireless-lab/patches-pending)|Pending OpenWrt Patches DAWN is depending on|
|[bowl-feed](https://github.com/berlin-open-wireless-lab/bowl-feed)|Feed for DAWN|
## Installation
See [installation](INSTALL.md).
## LuCI App
There is an luci app called [luci-app-dawn](https://github.com/berlin-open-wireless-lab/bowl-feed).
## Setting up Routers
You can find a good guide to configure your router is [here](https://gist.github.com/braian87b/bba9da3a7ac23c35b7f1eecafecdd47d).
I setup the OpenWRT Router as dumb APs.
## Configuration
|Option |Standard | Meaning |
|-------------------|---------|---------|
|ht_support | '10' |If AP and station support high throughput.|
|vht_support | '100' |If AP and station support very high throughput.|
|no_ht_support | '0' |If AP and station not supporting high throughput.|
|no_vht_support | '0' |If AP and station not supporting very high throughput.
|rssi | '10' |If RSSI is greater equal rssi_val.|
|low_rssi | '-500' |If RSSI is less than low_rssi_val.|
|freq | '100' |If connection is 5Ghz.|
|chan_util | '0' |If channel utilization is lower chan_util_val.|
|max_chan_util | '-500' |If channel utilization is greater max_chan_util_val.|
|rssi_val | '-60' |Threshold for an good RSSI.|
|low_rssi_val | '-80' |Threshold for an bad RSSI.|
|chan_util_val | '140' |Threshold for an good channel utilization.|
|max_chan_util_val | '170' |Threshold for a bad channel utilization.|
|min_probe_count | '2' |Minimum number of probe requests aftrer calculating if AP is best and sending a probe response.|
|bandwith_threshold | '6' |Threshold for the receiving bit rate indicating if a client is in an active transmission.|
|use_station_count | '1' |Use station count as metric.|
|max_station_diff | '1' |Maximal station difference that is allowed.|
|eval_probe_req | '1' |Evaluate the incoming probe requests.|
|eval_auth_req | '1' |Evaluate the incomning authentication reqeuests.|
|eval_assoc_req | '1' |Evaluate the incoming association requests.|
|deny_auth_reason | '1' |Status code for denying authentications.|
|deny_assoc_reason | '17' |Status code for denying associations.|
|use_driver_recog | '1' |Allow drivers to connect after a certain time.|
## ubus interface
To get an overview of all connected Clients sorted by the SSID.
root@OpenWrt:~# ubus call dawn get_network
{
"Free-Cookies": {
"00:27:19:XX:XX:XX": {
"78:02:F8:XX:XX:XX": {
"freq": 2452,
"ht": 1,
"vht": 0,
"collision_count": 4
}
},
"A4:2B:B0:XX:XX:XX": {
"48:27:EA:XX:XX:XX: {
"freq": 2412,
"ht": 1,
"vht": 0,
"collision_count": 4
},
}
},
"Free-Cookies_5G": {
}
}
To get the hearing map you can use:
root@OpenWrt:~# ubus call dawn get_hearing_map
{
"Free-Cookies": {
"0E:5B:DB:XX:XX:XX": {
"00:27:19:XX:XX:XX": {
"signal": -64,
"freq": 2452,
"ht_support": true,
"vht_support": false,
"channel_utilization": 12,
"num_sta": 1,
"ht": 1,
"vht": 0,
"score": 10
},
"A4:2B:B0:XX:XX:XX": {
"signal": -70,
"freq": 2412,
"ht_support": true,
"vht_support": false,
"channel_utilization": 71,
"num_sta": 3,
"ht": 1,
"vht": 0,
"score": 10
}
}
}
}
## OpenWrt in a Nutshell
![OpenWrtInANuthshell](https://raw.githubusercontent.com/PolynomialDivision/upload_stuff/master/dawn_pictures/openwrt_in_a_nutshell_dawn.png)

54
src/CMakeLists.txt Executable file
View 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
View 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;
}

View 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
View 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
View 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
View 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
View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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;
}

View 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;
}

View 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
View 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
View 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

File diff suppressed because it is too large Load diff

356
src/utils/dawn_iwinfo.c Normal file
View 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
View 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;
}

View 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

File diff suppressed because it is too large Load diff

80
src/utils/utils.c Normal file
View 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);
}