Upstream vwifi v7.0 (Raizo62/vwifi @ 4a9842e)

Unmodified upstream source from https://github.com/Raizo62/vwifi
Commit: 4a9842e "CMakeLists.txt : VERSION = 7.0"

Simulator of WiFi (802.11) interfaces to communicate between
several Virtual Machines via mac80211_hwsim + TCP relay.

License: Apache-2.0
This commit is contained in:
Guy Resheff
2026-03-08 08:19:45 -07:00
commit 92df7a383a
75 changed files with 8628 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
# Old build artifacts
# vwifi-server
# vwifi-client
# vwifi-ctrl
# vwifi-add-interfaces
# obj/
# CMake build artifacts
build/
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
compile_commands.json
Makefile
*.a
*.so
# For cppcheck
vwifi-cppcheck.xml
# For eclipse :
.project
.cproject
.settings
# For Visual Studio Code :
.vscode
+2
View File
@@ -0,0 +1,2 @@
Raizo62 (David Ansart / https://github.com/Raizo62)
SecurityLab (Boussad Ait-Salem / https://securitylab.fr/home)
+162
View File
@@ -0,0 +1,162 @@
cmake_minimum_required(VERSION 3.10)
project(vwifi VERSION 7.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# --- Compiler Flags ---
# Add flags similar to the Makefile's MODE settings
# Using Release build type for optimizations by default
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose build type: Debug Release RelWithDebInfo MinSizeRel" FORCE)
endif()
option(ENABLE_VHOST "Enable vhost support" ON)
if(NOT ENABLE_VHOST)
add_definitions(-DDISABLE_VHOST)
endif()
# Common flags (add more as needed based on Makefile MODE)
add_compile_options(-Wall -Wextra -pedantic)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(-O3 -s)
# add_definitions(-DNDEBUG) # Uncomment if asserts should be disabled in release
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_options(-g)
add_definitions(-D_DEBUG)
endif()
# Add version definition
# Check if this is a git repository and get the commit hash
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
execute_process(
COMMAND "${GIT_EXECUTABLE}" log --pretty=format:%h -n 1
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_COMMIT_HASH)
set(FULL_VERSION "${PROJECT_VERSION}-${GIT_COMMIT_HASH}")
message(STATUS "Building Git version: ${FULL_VERSION}")
else()
set(FULL_VERSION "${PROJECT_VERSION}")
message(STATUS "Building version: ${FULL_VERSION} (Not a Git repo or git error)")
endif()
add_definitions(-DVERSION=\"${FULL_VERSION}\")
# --- Find Dependencies ---
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBNL3 REQUIRED IMPORTED_TARGET libnl-genl-3.0 libnl-3.0)
# --- Include Directories ---
include_directories(src)
include_directories(${LIBNL3_INCLUDE_DIRS})
# --- Common Static Library ---
# List all .cc files EXCEPT the main files for the executables
set(COMMON_SOURCES
src/ccoordinate.cc
src/cctrlserver.cc
src/cdynbuffer.cc
src/cinfosocket.cc
src/cinfowifi.cc
src/ckernelwifi.cc
src/cmonwirelessdevice.cc
src/cselect.cc
src/csocket.cc
src/csocketclient.cc
src/csocketclientitcp.cc
src/csocketclientvtcp.cc
src/csocketserver.cc
src/csocketserverfunctionitcp.cc
src/csocketserverfunctionvtcp.cc
src/cthread.cc
src/cwifi.cc
src/cwificlient.cc
src/cwifiserver.cc
src/cwifiserveritcp.cc
src/cwifiservervtcp.cc
src/cwirelessdevice.cc
src/cwirelessdevicelist.cc
src/tools.cc
src/addinterfaces.cc
)
add_library(vwifi_common STATIC ${COMMON_SOURCES})
# Link common library dependencies once
target_link_libraries(vwifi_common PUBLIC Threads::Threads PkgConfig::LIBNL3)
# --- Executables ---
add_executable(vwifi-server src/vwifi-server.cc)
target_link_libraries(vwifi-server PRIVATE vwifi_common)
add_executable(vwifi-client src/vwifi-client.cc)
target_link_libraries(vwifi-client PRIVATE vwifi_common)
add_executable(vwifi-ctrl src/vwifi-ctrl.cc)
target_link_libraries(vwifi-ctrl PRIVATE vwifi_common)
add_executable(vwifi-add-interfaces src/vwifi-add-interfaces.cc)
# vwifi-add-interfaces seems to only need addinterfaces.o, which is in vwifi_common
target_link_libraries(vwifi-add-interfaces PRIVATE vwifi_common)
# Optional: vwifi-inet-monitor (based on commented out Makefile line)
# add_executable(vwifi-inet-monitor src/vwifi-inet-monitor.cc)
# target_link_libraries(vwifi-inet-monitor PRIVATE vwifi_common) # Check its specific dependencies if uncommenting
# --- Installation ---
include(GNUInstallDirs)
install(TARGETS vwifi-server vwifi-client vwifi-ctrl vwifi-add-interfaces
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# Optional: Install man pages if needed (requires CMake code)
# install(FILES man/vwifi.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 RENAME vwifi.1)
# --- Optional: Add tests ---
# enable_testing()
# add_subdirectory(tests) # If tests have their own CMakeLists.txt
# --- Custom Target for Cppcheck ---
find_program(CPPCHECK_EXECUTABLE cppcheck)
if(CPPCHECK_EXECUTABLE)
file(GLOB_RECURSE ALL_CC_SOURCES "src/*.cc")
get_property(GLOBAL_DEFINITIONS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS)
set(CPPCHECK_DEFS "")
foreach(DEF ${GLOBAL_DEFINITIONS})
if(DEF MATCHES "^-D")
set(CPPCHECK_DEFS "${CPPCHECK_DEFS} ${DEF}")
else()
set(CPPCHECK_DEFS "${CPPCHECK_DEFS} -D${DEF}")
endif()
endforeach()
set(CPPCHECK_DEFS "${CPPCHECK_DEFS} -D_DEBUG")
get_property(COMMON_COMPILE_OPTIONS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS)
set(CPPCHECK_CFLAGS "")
foreach(OPT ${COMMON_COMPILE_OPTIONS})
set(CPPCHECK_CFLAGS "${CPPCHECK_CFLAGS} ${OPT}")
endforeach()
# Définition du chemin de sortie du fichier XML
# CMAKE_CURRENT_BINARY_DIR pointe vers le répertoire de construction
set(CPPCHECK_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-cppcheck.xml")
add_custom_target(
cppcheck
COMMAND ${CPPCHECK_EXECUTABLE} --verbose --enable=all --enable=style --xml
${CPPCHECK_CFLAGS} ${CPPCHECK_DEFS} ${ALL_CC_SOURCES} 2> ${CPPCHECK_OUTPUT_FILE}
# WORKING_DIRECTORY reste le répertoire source pour que cppcheck trouve les fichiers
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running Cppcheck static analysis and generating XML report in build directory."
BYPRODUCTS ${CPPCHECK_OUTPUT_FILE}
)
endif()
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser 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
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+384
View File
@@ -0,0 +1,384 @@
# What is this ?
Simulate Wi-Fi (802.11) between Linux Virtual Machines on Qemu/VirtualBox/...
* It can be used in Hypervisors (GNS3, QEmu, Virtualbox, VMware, Hyper-V, ...)
* The Wireless emulator uses the `mac80211_hwsim` linux driver
* Implements the packet loss simulation based on distance
* Emulates the node mobility in GNS3
* Tested:
* with `hostapd` and `wpa_supplicant` with these configurations:
* Open
* WEP
* WPA2
* WPA-EAP
* in the context of WPA2 attack with `Aircrack-NG` (Kali / Parrot-OS)
* with OpenWRT
* Remaining features to be implemented:
* Integrate to other OS (Windows...)
* Add obstacle models
* Etc.
![Example](./screenshots/GNS3_Attack_with_KaliLinux.png)
# Explanations
* With the parameter "-h" (or "--help"), all programs display help and their parameters
* ***vwifi-client*** should be started on the VMs, and ***vwifi-server*** on the Host.
* ***vwifi-client*** and ***vwifi-server*** can communicate either with the VHOST protocol (by default), or with the TCP protocol.
* With the option "-s" (or "--spy"), ***vwifi-client*** :
* receives always all communications, even if the loss of packets is enable ;
* works only with TCP ;
* connects to 127.0.0.1, by default ;
* ***vwifi-client*** uses the `mac80211_hwsim` kernel module to have the wifi interfaces.
* To use TCP protocol, ***vwifi-server*** and ***vwifi-client*** must be connected to a different IP network than that of the wifi.
* ***vwifi-add-interfaces*** is used to create the wlan interfaces to the module `mac80211_hwsim`. ***vwifi-client*** controls only these interfaces. ***vwifi-add-interfaces*** can be run several times.
* ***vwifi-ctrl*** is used to interact with ***vwifi-server***.
* ***vwifi-server*** can directly enable packet loss with the parameter "-l" (or "--lost-packets")
* If ***vwifi-server*** detects the same IP for several ***vwifi-client*** (due to PAT/NPAT/...), use the option "-u" ("-- use-port-in-hash") on ***vwifi-server*** to add the network port to create the ID for each client, instead of just using the IP. Attention, the display of ID by ***vwifi-server*** and ***vwifi-client*** will no longer be the same.
* You can change the defaults IP and ports with parameters (see the parameter "-h" to help)
# Install
## On Debian-based Linux distributions
### Dependencies
```bash
sudo apt-get update
sudo apt-get install cmake make g++ pkg-config
sudo apt-get install libnl-3-dev libnl-genl-3-dev
```
### Building
* Optional: To download and update the file `mac80211_hwsim.h` (if needed, requires wget) :
```bash
wget -q -N https://raw.githubusercontent.com/torvalds/linux/master/drivers/net/wireless/virtual/mac80211_hwsim.h -P src
```
* To change the default ports and IP, edit: `src/config.h`
* To configure :
```bash
mkdir build
cd build
cmake ..
```
* To Customize the build :
* For a debug build : Add `-DCMAKE_BUILD_TYPE=Debug`
* To disable VHOST protocol : Add `-DENABLE_VHOST=OFF`
* To build : `make`
* To install : `sudo make install`
## On OpenWRT
* See the wiki : [Install-vwifi-on-OpenWRT-X86_64](https://github.com/Raizo62/vwifi/wiki/Install-on-OpenWRT-X86_64)
# Configuration
## Method 1 : With VHOST
### Host
* Shell :
* Load the module VHOST :
```bash
# sudo modprobe -r vhost_vsock vmw_vsock_virtio_transport_common vsock # if necessary
sudo modprobe vhost_vsock
sudo chmod a+rw /dev/vhost-vsock
```
* Start the ***vwifi-server*** :
```bash
vwifi-server
```
* Hypervisor
* QEmu : add the option : `-device vhost-vsock-pci,id=vwifi0,guest-cid=NUM` with NUM an identifier greater than 2
* GNS3 (>= 2.2) : QEmu : add the option : `-device vhost-vsock-pci,id=vwifi0,guest-cid=%guest-cid%`
### Each Guest
* Load the necessary module mac80211_hwsim with 0 radios :
```bash
sudo modprobe mac80211_hwsim radios=0
```
* Create the wlan interfaces (on this example, 2 interfaces) :
* Without parameters, the MAC address is preset with the default value "74:F8:F6", and the 4th byte is randomized
* ***vwifi-client*** can do the same with the parameters "--number" and "--mac"
```bash
sudo vwifi-add-interfaces 2 0a:0b:0c:03:02
```
* Connect all these wlan interfaces to the ***vwifi-server*** :
```bash
sudo vwifi-client
```
* ***vwifi-client*** displays the CID of the VM in the Hypervisor. It is used by ***vwifi-server*** to identify this guest.
## Method 2 : With TCP
* ***vwifi-server*** and ***vwifi-client*** must be connected to a different IP network than that of the wifi (for example : 172.16.0.0/16)
### Host
* Start the ***vwifi-server*** :
```bash
vwifi-server
```
* We will suppose that the Host have the IP address : 172.16.0.1
### Each Guest
* Load the necessary module mac80211_hwsim with 0 radios :
```bash
sudo modprobe mac80211_hwsim radios=0
```
* Create the wlan interfaces (on this example, 2 interfaces) :
* Without parameters, the MAC address is preset with the default value "74:F8:F6", and the 4th byte is randomized
* ***vwifi-client*** can do the same with the parameters "--number" and "--mac"
```bash
sudo vwifi-add-interfaces 2 0a:0b:0c:03:02
```
* Connect all these wlan interfaces to the ***vwifi-server*** :
```bash
sudo vwifi-client 172.16.0.1
```
* ***vwifi-client*** displays an ID which is an hashsum of the IP. It is used by ***vwifi-server*** to identify this guest.
# Capture packets from Host
## Configure the Spy
```bash
sudo modprobe mac80211_hwsim radios=0
sudo vwifi-client -s -n 1
```
## Capture
* Configure wlan0 to monitor mode :
```bash
sudo ip link set wlan0 down
sudo iw wlan0 set monitor control
sudo ip link set wlan0 up
```
### With tcpdump
* Capture from wlan0 :
```bash
sudo tcpdump -n -i wlan0
```
### With wireshark
* Start Wireshark and capture from wlan0 :
```bash
sudo wireshark
```
# Control
## Host
* Show the list of connected guest (display : cid and coordinate x, y z) :
```bash
vwifi-ctrl ls
```
* Set the new coordinate (11, 12, 13) of the guest with the cid 10 :
```bash
vwifi-ctrl set 10 11 12 13
```
* Set the name "AP" of the guest with the cid 10 :
```bash
vwifi-ctrl setname 10 AP
```
* Enable the lost of packets :
```bash
vwifi-ctrl loss yes
```
* Disable the lost of packets :
```bash
vwifi-ctrl loss no
```
* Display the config of ***vwifi-server*** :
```bash
vwifi-ctrl status
```
* Display the distance in meters between the guest with the cid 10 and the guest with the cid 20 :
```bash
vwifi-ctrl distance 10 20
```
* Set the scale of the distances between the clients to 0.005
```bash
vwifi-ctrl scale 0.005
```
# Examples of commands to test Wifi
## Test 1 : WPA
### Packages needed on the guests for this test
```bash
sudo apt install hostapd wpasupplicant
```
### Guests
* Guest Wifi 1 :
```bash
sudo ip a a 10.0.0.1/8 dev wlan0
sudo hostapd tests/hostapd_wpa.conf
```
* Guest Wifi 2 :
```bash
sudo wpa_supplicant -Dnl80211 -iwlan0 -c tests/wpa_supplicant.conf
sudo ip a a 10.0.0.2/8 dev wlan0
ping 10.0.0.1
```
* Guest Wifi 3 :
```bash
sudo wpa_supplicant -Dnl80211 -iwlan0 -c tests/wpa_supplicant.conf
sudo ip a a 10.0.0.3/8 dev wlan0
ping 10.0.0.2
```
## Test 2 : Open
### Packages needed on the guests for this test
```bash
sudo apt install hostapd iw tcpdump
```
### Guests
* Guest Wifi 1 :
```bash
sudo ip a a 10.0.0.1/8 dev wlan0
sudo hostapd tests/hostapd_open.conf
```
* Guest Wifi 2 :
```bash
sudo ip link set up wlan0
sudo iw dev wlan0 connect mac80211_open
sudo ip a a 10.0.0.2/8 dev wlan0
ping 10.0.0.1
```
* Guest Wifi 3 :
```bash
sudo ip link set up wlan0
sudo tcpdump -n -e -I -i wlan0 -w /hosthome/projects/vwifi_capture_wlan0.pcap
```
### Host
```bash
tail -f -c +0b /home/user/projects/vwifi_capture_wlan0.pcap | wireshark -k -i -
```
## Test 3 : Ad-Hoc
### Packages needed on the guests for this test
```bash
sudo apt install iw
```
### Guests
* Guest Wifi 1 :
```bash
sudo ip link set up wlan0
sudo iw wlan0 set type ibss
sudo iw wlan0 ibss join MYNETWORK 2412 # frequency 2412 is channel 1
sudo ip a a 10.0.0.1/8 dev wlan0
```
* Guest Wifi 2 :
```bash
sudo ip link set up wlan0
sudo iw wlan0 set type ibss
sudo iw wlan0 ibss join MYNETWORK 2412 # frequency 2412 is channel 1
sudo ip a a 10.0.0.2/8 dev wlan0
ping 10.0.0.1
```
## Test 4 : WEP
### Packages needed on the guests for this test
```bash
sudo apt install hostapd
```
### Guests
* Guest Wifi 1 :
```bash
sudo ip a a 10.0.0.1/8 dev wlan0
sudo hostapd tests/hostapd_wep.conf
```
* Guest Wifi 2 :
```bash
cat << EOF | sudo tee -a /etc/network/interfaces > /dev/null
iface wlan0 inet static
wireless-essid AP_WEP
wireless-key s:12345
address 10.0.0.2
netmask 255.255.255.0
EOF
sudo ifup wlan0
ping 10.0.0.1
```
# Others Tools
* start-vwifi-client.sh : do all the commands necessary to start ***vwifi-client*** on a Guest
* fast-vwifi-update.sh : set with ***vwifi-ctrl*** the coordinates of each VMs which has the option `guest-cid=`, found in the open project of GNS3
* client.sh : configure the client wifi with Open or WPA
* Makefile.dependency.sh : generate automatically the file "Makefile.in", include in "Makefile", which contains dependencies for "make"
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+152
View File
@@ -0,0 +1,152 @@
/*
From : https://android.googlesource.com/device/generic/goldfish/+/refs/heads/master/wifi/mac80211_create_radios/main.cpp
Licence http://www.apache.org/licenses/LICENSE-2.0
*/
#include <memory>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <netlink/netlink.h>
#include <net/ethernet.h>
#include <climits>
#include <stdio.h>
#include <unistd.h> // getuid
#include "addinterfaces.h"
#include "config_hwsim.h"
const char* nlErrStr(const int e)
{
return (e < 0) ? nl_geterror(e) : "";
}
#define RETURN(R) return (R);
#define RETURN_ERROR(C, R) \
do { \
fprintf(stderr,"%s:%d '%s' failed\n", __func__, __LINE__, C); \
return (R); \
} while (false);
#define RETURN_NL_ERROR(C, NLR, R) \
do { \
fprintf(stderr,"%s:%d '%s' failed with '%s'\n", __func__, __LINE__, C, nlErrStr((NLR))); \
return (R); \
} while (false);
struct nl_sock_deleter
{
void operator()(struct nl_sock* x) const
{
nl_socket_free(x);
}
};
struct nl_msg_deleter
{
void operator()(struct nl_msg* x) const
{
nlmsg_free(x);
}
};
int ParseAddress(const char* str, TByte addr[ETH_ALEN])
{
return sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&addr[0], &addr[1], &addr[2],&addr[3], &addr[4], &addr[5]);
}
std::unique_ptr<struct nl_msg, nl_msg_deleter> CreateNlMessage(
const int family,
const int cmd)
{
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg(nlmsg_alloc());
if (!msg)
{
RETURN_ERROR("nlmsg_alloc", nullptr);
}
void* user = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, family, 0,
NLM_F_REQUEST, cmd, VERSION_NR);
if (!user)
{
RETURN_ERROR("genlmsg_put", nullptr);
}
RETURN(msg);
}
std::unique_ptr<struct nl_msg, nl_msg_deleter>
BuildCreateRadioMessage(const int family, const TByte mac[ETH_ALEN])
{
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg =
CreateNlMessage(family, HWSIM_CMD_NEW_RADIO);
if (!msg)
{
RETURN(nullptr);
}
int ret;
ret = nla_put(msg.get(), HWSIM_ATTR_PERM_ADDR, ETH_ALEN, mac);
if (ret)
{
RETURN_NL_ERROR("nla_put(HWSIM_ATTR_PERM_ADDR)", ret, nullptr);
}
ret = nla_put_flag(msg.get(), HWSIM_ATTR_SUPPORT_P2P_DEVICE);
if (ret)
{
RETURN_NL_ERROR("nla_put(HWSIM_ATTR_SUPPORT_P2P_DEVICE)", ret, nullptr);
}
RETURN(msg);
}
int CreateRadios(struct nl_sock* socket, const int netlinkFamily,
const int nRadios, TByte* mac)
{
for (int idx = 0; idx < nRadios; ++idx)
{
if( nRadios != 1 ) // if i set only 1 interface, the mac address is not modified : the user can choose all the mac address
mac[5] = idx;
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg =
BuildCreateRadioMessage(netlinkFamily, mac);
if (msg)
{
int ret = nl_send_auto(socket, msg.get());
if (ret < 0)
{
RETURN_NL_ERROR("nl_send_auto", ret, 1);
}
}
else
{
RETURN(1);
}
}
RETURN(0);
}
int ManageRadios(const int nRadios, TByte* macPrefix)
{
std::unique_ptr<struct nl_sock, nl_sock_deleter> socket(nl_socket_alloc());
if (!socket)
{
RETURN_ERROR("nl_socket_alloc", 1);
}
int ret;
ret = genl_connect(socket.get());
if (ret)
{
RETURN_NL_ERROR("genl_connect", ret, 1);
}
const int netlinkFamily = genl_ctrl_resolve(socket.get(), KERNEL_HWSIM_FAMILY_NAME);
if (netlinkFamily < 0)
{
fprintf(stderr,"The kernel module 'mac80211_hwsim' is not loaded\n");
return 2;
//RETURN_NL_ERROR("genl_ctrl_resolve", ret, 1);
}
ret = CreateRadios(socket.get(), netlinkFamily, nRadios, macPrefix);
if (ret)
{
RETURN(ret);
}
RETURN(0);
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef _ADDINTERFACE_H_
#define _ADDINTERFACE_H_
#include "types.h"
int ParseAddress(const char* str, TByte addr[ETH_ALEN]);
int ManageRadios(const int nRadios, TByte* macPrefix);
#endif
+80
View File
@@ -0,0 +1,80 @@
#include "ccoordinate.h"
#include <math.h> // sqrt
TScale Scale=1;
CCoordinate::CCoordinate(TValue x, TValue y, TValue z)
{
Set(x, y, z);
}
CCoordinate::CCoordinate()
{
X=0;
Y=0;
Z=0;
}
CCoordinate::CCoordinate(const CCoordinate& coo)
{
*this=coo;
}
void CCoordinate::SetX(TValue x)
{
X=x;
}
void CCoordinate::SetY(TValue y)
{
Y=y;
}
void CCoordinate::SetZ(TValue z)
{
Z=z;
}
void CCoordinate::Set(TValue x, TValue y)
{
SetX(x);
SetY(y);
}
void CCoordinate::Set(TValue x, TValue y, TValue z)
{
Set(x, y);
SetZ(z);
}
void CCoordinate::Set(CCoordinate coo)
{
Set(coo.X,coo.Y,coo.Z);
}
TDistance CCoordinate::DistanceWith(TValue x, TValue y, TValue z)
{
return Scale*sqrt( (X-x)*(X-x)+(Y-y)*(Y-y)+(Z-z)*(Z-z) );
}
TDistance CCoordinate::DistanceWith(CCoordinate coo)
{
return DistanceWith(coo.X, coo.Y, coo.Z);
}
void CCoordinate::Display(ostream& os) const
{
os << X << " " << Y << " " << Z;
}
ostream& operator<<(ostream& os, const CCoordinate& coo)
{
coo.Display(os) ;
return os;
}
CCoordinate& CCoordinate::operator=(const CCoordinate& coo)
{
Set(coo.X,coo.Y,coo.Z);
return *this;
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef _CCOORDINATE_H_
#define _CCOORDINATE_H_
#include <iostream>
#include "types.h" // TValue, TDistance
using namespace std;
extern TScale Scale;
class CCoordinate
{
TValue X;
TValue Y;
TValue Z;
public :
CCoordinate();
CCoordinate(TValue x, TValue y, TValue z);
CCoordinate(const CCoordinate& coo);
void SetX(TValue x);
void SetY(TValue y);
void SetZ(TValue z);
void Set(TValue x, TValue y);
void Set(TValue x, TValue y, TValue z);
void Set(CCoordinate coo);
TDistance DistanceWith(TValue x, TValue y, TValue z);
TDistance DistanceWith(CCoordinate coo);
void Display(ostream& os) const;
friend ostream& operator<<(ostream& os, const CCoordinate& coo);
CCoordinate& operator=(const CCoordinate& coo);
};
#endif
+455
View File
@@ -0,0 +1,455 @@
#include <cstring> // strcpy
#include "cctrlserver.h"
#include "config.h" // MAX_SIZE_NAME
CCTRLServer::CCTRLServer(CWifiServer* wifiServerVTCP, CWifiServer* wifiServerITCP, CWifiServer* wifiServerSPY, CSelect* scheduler) : CSocketServer()
{
WifiServerVTCP=wifiServerVTCP;
WifiServerITCP=wifiServerITCP;
WifiServerSPY=wifiServerSPY;
Scheduler=scheduler;
}
CCTRLServer::~CCTRLServer()
{
// Close any open connections
CloseAllClient();
}
bool CCTRLServer::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionITCP::_Listen(master, port);
}
TDescriptor CCTRLServer::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionITCP::_Accept(master, cid);
}
ssize_t CCTRLServer::Read(char* data, ssize_t sizeOfData)
{
return CSocket::Read(GetSocketClient(0),data, sizeOfData);
}
ssize_t CCTRLServer::Send(char* data, ssize_t sizeOfData)
{
return CSocket::Send(GetSocketClient(0),data, sizeOfData);
}
TOrder CCTRLServer::GetOrder()
{
TOrder order;
if( GetNumberClient() != 1 )
return TORDER_NO;
if( Read(reinterpret_cast<char*>(&order), sizeof(TOrder)) == SOCKET_ERROR )
return TORDER_NO;
return order;
}
bool CCTRLServer::SendCInfoWifi(CInfoWifi* infoWifi)
{
TCID cid=infoWifi->GetCid();
if( Send(reinterpret_cast<char*>(&cid),sizeof(cid)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : cid : "<<infoWifi->GetCid()<<endl;
return false;
}
CCoordinate coo=(*infoWifi);
if( Send(reinterpret_cast<char*>(&coo),sizeof(coo)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : CCoordinate : "<<infoWifi->GetCid()<<endl;
return false;
}
int sizeName=infoWifi->GetSizeName();
if( Send(reinterpret_cast<char*>(&sizeName),sizeof(sizeName)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : size of name : "<<infoWifi->GetCid()<<endl;
return false;
}
if( sizeName > 0 )
{
char name[MAX_SIZE_NAME+1]; // +1 : \0
strcpy(name,(infoWifi->GetName()).c_str());
if( Send(name,sizeName+1) == SOCKET_ERROR ) // +1 : \0
{
cerr<<"Error : SendCInfoWifi : name : "<<infoWifi->GetCid()<<endl;
return false;
}
}
return true;
}
void CCTRLServer::SendList()
{
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CInfoWifi* infoWifi;
// Spies :
TIndex number=WifiServerSPY->GetNumberClient();
if( Send(reinterpret_cast<char*>(&number), sizeof(number)) == SOCKET_ERROR )
return;
for(TIndex i=0; i<number;i++)
{
if( WifiServerSPY->IsEnable(i) )
{
infoWifi=WifiServerSPY->GetReferenceOnInfoWifiByIndex(i);
if( ! SendCInfoWifi(infoWifi) )
{
cerr<<"Error : SendList : Send : Spies : CInfoWifi : "<<*infoWifi<<endl;
return;
}
}
}
// Clients
number=WifiServerITCP->GetNumberClient();
if( Send(reinterpret_cast<char*>(&number), sizeof(number)) == SOCKET_ERROR )
return;
for(TIndex i=0; i<number;i++)
{
if( WifiServerITCP->IsEnable(i) )
{
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByIndex(i);
if( ! SendCInfoWifi(infoWifi) )
{
cerr<<"Error : SendList : Send : Clients : CInfoWifi : "<<*infoWifi<<endl;
return;
}
}
}
}
void CCTRLServer::ChangeCoordinate()
{
TCID cid;
if( Read(reinterpret_cast<char*>(&cid), sizeof(TCID)) == SOCKET_ERROR )
return;
CCoordinate coo;
if( Read(reinterpret_cast<char*>(&coo), sizeof(coo)) == SOCKET_ERROR )
return;
if( cid < TCID_GUEST_MIN )
return;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CInfoWifi* infoWifi;
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->Set(coo);
return;
}
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid);
if( infoWifi != NULL )
{
infoWifi->Set(coo);
return;
}
CInfoWifi infoNewWifi(cid,coo);
WifiServerITCP->AddInfoWifiDeconnected(infoNewWifi);
}
void CCTRLServer::SetName()
{
TCID cid;
if( Read(reinterpret_cast<char*>(&cid), sizeof(TCID)) == SOCKET_ERROR )
return;
int sizeName;
char strName[MAX_SIZE_NAME+1]; // +1 : \0
if( Read(reinterpret_cast<char*>(&sizeName), sizeof(sizeName)) == SOCKET_ERROR )
return;
if( Read(reinterpret_cast<char*>(strName), sizeof(strName)) == SOCKET_ERROR )
return;
if( cid < TCID_GUEST_MIN )
return;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
string name(strName);
CInfoWifi* infoWifi;
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
infoWifi=WifiServerSPY->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
}
void CCTRLServer::ChangePacketLoss()
{
int value;
if( Read(reinterpret_cast<char*>(&value), sizeof(value)) == SOCKET_ERROR )
return;
if ( value )
{
#ifdef _DEBUG
cout<<"Packet loss : Enable"<<endl;
#endif
CanLostPackets=true;
}
else
{
#ifdef _DEBUG
cout<<"Packet loss : Disable"<<endl;
#endif
CanLostPackets=false;
}
}
void CCTRLServer::SendStatus()
{
if( Send(reinterpret_cast<char*>(&CanLostPackets),sizeof(CanLostPackets)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : PacketLoss"<<endl;
return;
}
if( Send(reinterpret_cast<char*>(&Scale),sizeof(Scale)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Scale"<<endl;
return;
}
#ifdef ENABLE_VHOST
// VHOST
if( Send(reinterpret_cast<char*>(&WifiServerVTCP->Port),sizeof(WifiServerVTCP->Port)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Port VHOST"<<endl;
return;
}
#endif
// INET
if( Send(reinterpret_cast<char*>(&WifiServerITCP->Port),sizeof(WifiServerITCP->Port)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Port INET"<<endl;
return;
}
// SizeOfDisconnected
// be careful : the same List is shared by WifiServerVTCP and WifiServerITCP
if( Send(reinterpret_cast<char*>(&WifiServerITCP->MaxClientDeconnected),sizeof(WifiServerITCP->MaxClientDeconnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Size MaxClientDeconnected"<<endl;
return;
}
// SPY
bool spyIsConnected=( WifiServerSPY->GetNumberClient() > 0 );
if( Send(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : spyIsConnected"<<endl;
return;
}
}
void CCTRLServer::SendShow()
{
if( Send(reinterpret_cast<char*>(&CanLostPackets),sizeof(CanLostPackets)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : PacketLoss"<<endl;
return;
}
if( Send(reinterpret_cast<char*>(&Scale),sizeof(Scale)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : Scale"<<endl;
return;
}
bool spyIsConnected=( WifiServerSPY->GetNumberClient() > 0 );
if( Send(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : spyIsConnected"<<endl;
return;
}
}
void CCTRLServer::SendDistance()
{
TCID cid1, cid2;
if( Read(reinterpret_cast<char*>(&cid1), sizeof(TCID)) == SOCKET_ERROR )
return;
if( Read(reinterpret_cast<char*>(&cid2), sizeof(TCID)) == SOCKET_ERROR )
return;
int codeError;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CCoordinate* coo1;
coo1=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid1);
if( coo1 == NULL )
{
coo1=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid1);
if( coo1 == NULL )
{
codeError=-1;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
cerr<<"Error : SendDistance : Send : unknown cid1"<<endl;
return ;
}
}
CCoordinate* coo2;
coo2=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid2);
if( coo2 == NULL )
{
coo2=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid2);
if( coo2 == NULL )
{
codeError=-2;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
cerr<<"Error : SendDistance : Send : unknown cid2"<<endl;
return ;
}
}
codeError=0;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
{
cerr<<"Error : SendDistance : Send : no error"<<endl;
return ;
}
TDistance distance=coo1->DistanceWith(*coo2);
if( Send(reinterpret_cast<char*>(&distance),sizeof(distance)) == SOCKET_ERROR )
{
cerr<<"Error : SendDistance : Send : distance"<<endl;
return;
}
}
void CCTRLServer::SetScale()
{
TScale new_scale;
if( Read(reinterpret_cast<char*>(&new_scale), sizeof(new_scale)) == SOCKET_ERROR )
return;
Scale=new_scale;
}
void CCTRLServer::CloseAllClient()
{
// because the same List is shared by WifiServerVTCP and WifiServerITCP
// Clients :
// be careful : In the Scheduler, i must delete only the nodes of WifiServer, not the node of the CTRLServer
for (TIndex i = 0; i < WifiServerITCP->GetNumberClient(); i++)
Scheduler->DelNode((*WifiServerITCP)[i]);
WifiServerITCP->CloseAllClient();
// Spies :
for (TIndex i = 0; i < WifiServerSPY->GetNumberClient(); i++)
Scheduler->DelNode((*WifiServerSPY)[i]);
WifiServerSPY->CloseAllClient();
}
void CCTRLServer::ReceiveOrder()
{
if ( Accept() == SOCKET_ERROR )
return;
TOrder order=GetOrder();
switch( order )
{
case TORDER_NO : break ;
case TORDER_LIST :
SendList();
break;
case TORDER_CHANGE_COORDINATE :
ChangeCoordinate();
break;
case TORDER_SETNAME :
SetName();
break;
case TORDER_PACKET_LOSS :
ChangePacketLoss();
break;
case TORDER_STATUS :
SendStatus();
break;
case TORDER_SHOW :
SendShow();
break;
case TORDER_DISTANCE_BETWEEN_CID :
SendDistance();
break;
case TORDER_SET_SCALE :
SetScale();
break;
case TORDER_CLOSE_ALL_CLIENT :
CloseAllClient();
break;
}
CloseClient(0);
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef _CCTRLSERVER_H_
#define _CCTRLSERVER_H_
#include "cwifiserver.h" // CWifiServer CSocketServer
#include "csocketserverfunctionitcp.h" // CSocketServerFunctionITCP
#include "cselect.h" // CSelect
#include "types.h" // TOrder
class CCTRLServer : public CSocketServer, public CSocketServerFunctionITCP
{
CWifiServer* WifiServerVTCP;
CWifiServer* WifiServerITCP;
CWifiServer* WifiServerSPY;
CSelect* Scheduler;
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
using CSocketServer::Read;
ssize_t Read(char* data, ssize_t sizeOfData);
using CSocketServer::Send;
ssize_t Send(char* data, ssize_t sizeOfData);
TOrder GetOrder();
bool SendCInfoWifi(CInfoWifi* infoWifi);
void SendList();
void ChangeCoordinate();
void SetName();
void ChangePacketLoss();
void SendStatus();
void SendShow();
void SendDistance();
void SetScale();
void CloseAllClient();
public :
CCTRLServer(CWifiServer* wifiServerVTCP, CWifiServer* wifiServerITCP, CWifiServer* wifiServerSPY, CSelect* scheduler);
virtual ~CCTRLServer();
void ReceiveOrder();
};
#endif
+62
View File
@@ -0,0 +1,62 @@
#include <iostream>
#include <string.h> // memcpy
#include "cdynbuffer.h"
const int DEFAULT_SIZE_BUFFER=1024;
CDynBuffer::CDynBuffer()
{
Buffer = nullptr;
Size=0;
Allocate(DEFAULT_SIZE_BUFFER,false);
}
CDynBuffer::~CDynBuffer()
{
if( Buffer != nullptr )
{
delete Buffer;
Buffer=nullptr;
Size=0;
}
}
void CDynBuffer::NeededSize(int size, bool keepValues)
{
if( size <= Size )
return;
Allocate(size,keepValues);
}
char* CDynBuffer::GetBuffer() const
{
return Buffer;
}
void CDynBuffer::Allocate(int size, bool keepValues)
{
if( ! keepValues )
{
if( Buffer != nullptr )
delete[] Buffer;
Buffer = new char [size];
}
else
{
char* newBuffer = new char [size];
if( Buffer != nullptr )
{
memcpy(newBuffer,Buffer,Size);
delete[] Buffer;
}
Buffer = newBuffer;
}
Size=size;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _CDYNBUFFER_H_
#define _CDYNBUFFER_H_
class CDynBuffer
{
private :
char* Buffer;
int Size;
void Allocate(int size, bool keepValues);
public :
CDynBuffer();
~CDynBuffer();
void NeededSize(int size, bool keepValues);
char* GetBuffer() const;
};
#endif
+53
View File
@@ -0,0 +1,53 @@
#include <unistd.h> // close
#include <assert.h> // assert
#include "cinfosocket.h"
CInfoSocket::CInfoSocket()
{
SetDescriptor(-1);
DisableIt();
}
CInfoSocket::CInfoSocket(TDescriptor descriptor)
{
SetDescriptor(descriptor);
EnableIt();
}
void CInfoSocket::SetDescriptor(TDescriptor descriptor)
{
Descriptor=descriptor;
EnableIt();
}
TDescriptor CInfoSocket::GetDescriptor() const
{
return Descriptor;
}
void CInfoSocket::EnableIt()
{
assert( Descriptor >= 0 );
Enable=true;
}
void CInfoSocket::DisableIt()
{
Enable=false;
}
bool CInfoSocket::IsEnable()
{
return Enable;
}
void CInfoSocket::Close()
{
if( IsEnable() )
{
DisableIt();
close(Descriptor);
}
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef _CINFOSOCKET_H_
#define _CINFOSOCKET_H_
#include <iostream> // ostream
#include "types.h" // TDescriptor
using namespace std;
class CInfoSocket
{
TDescriptor Descriptor;
bool Enable;
void EnableIt();
public :
CInfoSocket();
explicit CInfoSocket(TDescriptor descriptor);
void SetDescriptor(TDescriptor descriptor);
TDescriptor GetDescriptor() const;
void DisableIt();
bool IsEnable();
void Close();
};
#endif
+63
View File
@@ -0,0 +1,63 @@
#include <assert.h> // assert
#include "config.h" // MAX_SIZE_NAME
#include "cinfowifi.h"
CInfoWifi::CInfoWifi(): CCoordinate()
{
SetCid(0);
}
CInfoWifi::CInfoWifi(TCID cid, CCoordinate coo) : CCoordinate(coo)
{
SetCid(cid);
}
void CInfoWifi::SetCid(TCID cid)
{
// with the empty constructor : cid=0
assert( cid==0 || cid >=TCID_GUEST_MIN );
Cid=cid;
}
TCID CInfoWifi::GetCid() const
{
return Cid;
}
void CInfoWifi::SetName(string name)
{
if( name.size() > MAX_SIZE_NAME )
name.resize(MAX_SIZE_NAME);
Name=name;
}
string CInfoWifi::GetName() const
{
return Name;
}
int CInfoWifi::GetSizeName() const
{
return Name.size();
}
bool CInfoWifi::HasName() const
{
return ! Name.empty();
}
void CInfoWifi::Display(ostream& os) const
{
os << Cid << " ";
if( HasName() )
os << "("<<Name<<") ";
CCoordinate::Display(os);
}
ostream& operator<<(ostream& os, const CInfoWifi& infowifi)
{
infowifi.Display(os) ;
return os;
}
+39
View File
@@ -0,0 +1,39 @@
#ifndef _CINFOWIFI_H_
#define _CINFOWIFI_H_
#include <iostream> // ostream
#include <string>
#include "ccoordinate.h"
#include "types.h" // TCID
const TCID TCID_GUEST_MIN=3;
using namespace std;
class CInfoWifi : public CCoordinate
{
TCID Cid;
string Name;
public :
CInfoWifi();
CInfoWifi(TCID cid, CCoordinate coo);
void SetCid(TCID cid);
TCID GetCid() const;
void SetName(string name);
string GetName() const;
int GetSizeName() const;
bool HasName() const;
void Display(ostream& os) const;
friend ostream& operator<<(ostream& os, const CInfoWifi& infowifi);
};
#endif
+1095
View File
File diff suppressed because it is too large Load Diff
+275
View File
@@ -0,0 +1,275 @@
#ifndef _CKERNELWIFI_H_
#define _CKERNELWIFI_H_
#include <string>
#include <mutex>
#include "config_hwsim.h"
#include "cwirelessdevice.h"
#include "cwirelessdevicelist.h"
#include "cmonwirelessdevice.h"
#include "cselect.h"
#include <pthread.h>
#include "cthread.h"
#include <condition_variable>
#include "cdynbuffer.h"
namespace ckernelwifi{
class CallFromStaticFunc ;
}
class CKernelWifi : public intthread::AsyncTask {
protected :
pthread_t serverloop_id ;
CSelect Scheduler;
bool _connected_to_server { false };
std::mutex _mutex_connected_to_server ;
std::condition_variable _cond_connected_to_server ;
bool _being_initialized { false } ;
bool _being_started { false } ;
std::mutex _being_started_mutex ;
WirelessDeviceList _list_winterfaces ;
/** pointer for netlink socket */
struct nl_sock * _netlink_socket { nullptr };
/** pointer for netlink callback function */
struct nl_cb * _cb { nullptr };
/** For the family ID used by hwsim */
int m_family_id { 1 };
intthread::InterruptibleThread hwsimloop_task ;
intthread::InterruptibleThread serverloop_task ;
intthread::InterruptibleThread monitorloop_task ;
intthread::InterruptibleThread winterface_update_loop_task ;
intthread::InterruptibleThread connection_to_server_loop_task ;
bool _initialized { false } ;
std::mutex _mutex_initialized ;
MonitorWirelessDevice * monwireless = nullptr ;
int init();
int init_first();
void mac_address_to_string(char *address, struct ether_addr *mac);
public :
static ckernelwifi::CallFromStaticFunc * forward ;
/**
* \brief Default Constructor
*/
CKernelWifi();
/**
* \brief Default Destructor
*/
~CKernelWifi();
/**
* \brief start the all activity
*/
int start();
/**
* \brief stop the all activity
*/
int stop();
int process_messages(struct nl_msg *msg);
/**
* \brief free dynamicly allocated memory and socket descriptors
*/
void clean_all();
bool initialized();
void connected_to_server(bool v);
bool is_connected_to_server();
bool reconnect_to_server() ;
void manage_server_crash_loop() ;
void being_started(bool v);
bool is_being_started();
protected :
void cout_mac_address(struct ether_addr *src);
/**
* \brief Callback function to process messages received from kernel
* It processes the frames received from hwsim via netlink messages.
* These frames get sent via vsock to vwifi-server.
* \param msg - pointer to netlink message
* \param arg - pointer to additional args
* \return success or failure
*/
static int process_messages_cb(struct nl_msg *msg, void *arg);
/**
* \brief Send a register message to kernel via netlink
* This informs hwsim we wish to receive frames
* Taken from wmediumd
* \return void
*/
int send_register_msg();
/**
* \brief Initialize netlink communications
* Taken from wmediumd
* \return void
*/
int init_netlink();
int init_netlink_first();
/**
* \brief start receiving hwsim netlink frame from hwsim driver
*/
void recv_msg_from_hwsim_loop_start();
/**
* \brief Send a tx_info frame to the kernel space. This frame indicates
* that the frame was transmitted/acked successfully. The ack is sent back
* to the driver with HWSIM_ATTR_ADDR_TRANSMITTER unmodified.
* This is derived form wmediumd.
* TODO: modify if we create more accurate acking.
* \param src - mac address of transmitting radio
* \param flags - falgs
* \param signal - signal strength
* \param tx_attempts - number of transmit attempts
* \param cookie - unique identifier for frame
* \return success or failure
*/
int send_tx_info_frame_nl(struct ether_addr *src,
unsigned int flags, int signal,
struct hwsim_tx_rate *tx_attempts,
u64 cookie);
/**
* \brief start receiving hwsim frame from vwifi-server loop
*/
void recv_msg_from_server_loop_start();
static void recv_msg_from_server_signal_handle(int sig_num);
/**
* @brief this is meant to be a thread which detects removal of driver
* Used to suspend normal actions until driver is loaded
* @return void
*/
void monitor_hwsim_loop();
void winet_update_loop();
/**
* \brief Send a cloned frame to the kernel space driver.
* This will send a frame to the driver using netlink.
* It is received by hwsim with hwsim_cloned_frame_received_nl()
* This is taken from wmediumd and modified. It is called after the
* message has been received from wmasterd.
* \param dst - mac address of receving radio
* \param data - frame data
* \param data_len - length of frame
* \param rate_idx - number of attempts
* \param signal - signal strength
* \param freq - frequency
* \return success or failure
*/
int send_cloned_frame_msg(struct ether_addr *dst, char *data, int data_len,int rate_idx, int signal, uint32_t freq);
/**
* \brief handle messages received from server
*/
void recv_from_server();
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle addding wireless inet
*/
void handle_new_winet_notification(WirelessDevice);
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle deleting wireless inet
*/
void handle_del_winet_notification(const WirelessDevice&);
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle initial wireless inet
*/
void handle_init_winet_notification(WirelessDevice);
/**
* \brief get permanent mac address of ifname interface
*/
bool get_pmaddr(struct ether_addr &,const char *ifname);
/**
*\biref reconnecting to a server when detecting a socket disconnection
*/
void manage_server_crash();
// virtual :
virtual bool _Connect(int* id) = 0;
virtual ssize_t _SendSignal(TPower* power, const char* buffer, int sizeOfBuffer) = 0;
virtual ssize_t _RecvSignal(TPower* power, CDynBuffer* buffer) = 0;
virtual void _Close() = 0;
};
/**
* \namespace ckernelwifi
*
* A namespace is used here, since a class CallFromStaticFunc is defined in other files
*/
namespace ckernelwifi {
/**
* \class CallFromStaticFunc
* \brief this class is an artifact used to call a member function from static function
*/
class CallFromStaticFunc {
CKernelWifi * m_obj ;
public:
explicit CallFromStaticFunc(CKernelWifi * obj){
m_obj = obj ;
};
int process_messages(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->process_messages(msg);
return 0 ;
};
};
}
#endif /* _CKERNELWIFI_H_ */
+11
View File
@@ -0,0 +1,11 @@
#ifndef _CLISTINFO_H_
#define _CLISTINFO_H_
#include <vector> // vector
template <typename TypeInfo>
class CListInfo : public std::vector<TypeInfo>
{
};
#endif
+672
View File
@@ -0,0 +1,672 @@
#include "cmonwirelessdevice.h"
#include "cwirelessdevice.h"
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <net/if_arp.h>
#include <stdexcept>
#include <thread>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/family.h>
#include <netlink/route/link.h>
#include <linux/nl80211.h>
#ifdef _DEBUG
#include <net/if.h> // IFF_UP
#endif
/* allow calling a non static function from static function */
monitorinet::CallFromStaticFunc * MonitorWirelessDevice::forward = nullptr ;
void MonitorWirelessDevice::setNewInetCallback(CallbackFunction cb){
_newinet_cb = cb ;
}
void MonitorWirelessDevice::setDelInetCallback(CallbackFunction cb){
_delinet_cb = cb ;
}
void MonitorWirelessDevice::setInitInetCallback(CallbackFunction cb){
_initinet_cb = cb ;
}
MonitorWirelessDevice::MonitorWirelessDevice(){
struct sockaddr_nl addr;
/* create a netlink route socket */
if(( _inetsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
throw std::runtime_error("couldn't create a AF_NETLINK socket");
/* joins the multicast groups for link notifications */
std::memset(&addr, 0, sizeof addr);
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
if (bind(_inetsock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
throw std::runtime_error("couldn't bind to AF_NETLINK socket");
/* allows calls from static callback to non static member function */
forward = new monitorinet::CallFromStaticFunc(this);
/* init netlink 80211 */
if (nl80211_init() < 0)
throw std::runtime_error("Error initializing netlink 802.11");
}
MonitorWirelessDevice::~MonitorWirelessDevice(){
#ifdef _DEBUG
std::cout << __func__ << std::endl ;
#endif
if (started())
stop();
while(!outside_loop());
clean();
}
void MonitorWirelessDevice::clean(){
close(_inetsock);
nl_cb_put(wifi.cb);
nl_cb_put(wifi.cb1);
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
}
int MonitorWirelessDevice::main_loop() {
fd_set rfds;
struct timeval tv;
_outsideloopmutex.lock() ;
_outsideloop = false ;
_outsideloopmutex.unlock();
while (started()) {
FD_ZERO(&rfds);
FD_CLR(_inetsock, &rfds);
FD_SET(_inetsock, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
int retval = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select in MonitorWirelessDevice main_loop function");
stop();
}
else
if (retval){
#ifdef _DEBUG
std::cout << __func__ << "process event received from AF_NETLINK socket" << std::endl ;
#endif
recv_inet_event();
}
}
_outsideloopmutex.lock() ;
_outsideloop = true ;
_outsideloopmutex.unlock();
return 0;
}
bool MonitorWirelessDevice::outside_loop(){
bool outsideorno = false ;
_outsideloopmutex.lock();
if (_outsideloop) outsideorno = true ;
_outsideloopmutex.unlock();
return outsideorno ;
}
void MonitorWirelessDevice::start() {
if(started())
return ;
if (!outside_loop())
return ;
_startedmutex.lock() ;
_started = true ;
_startedmutex.unlock();
std::thread mainloop(&MonitorWirelessDevice::main_loop,this);
mainloop.detach();
}
void MonitorWirelessDevice::stop() {
_startedmutex.lock();
_started = false ;
_startedmutex.unlock();
}
bool MonitorWirelessDevice::started() {
bool startorno = false ;
_startedmutex.lock();
if (_started) startorno = true ;
_startedmutex.unlock();
return startorno ;
}
/***********************************************************************************************/
/***************** handle netlink net device events from kernel ******************************/
/**********************************************************************************************/
void MonitorWirelessDevice::recv_inet_event()
{
int len;
char buf[IFLIST_REPLY_BUFFER];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl snl;
struct msghdr msg = { static_cast<void *>(&snl), sizeof(snl), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nlmsgheader;
/* read the waiting message */
len = recvmsg(_inetsock, &msg, 0);
if (len < 0)
perror("read_netlink");
for (nlmsgheader = reinterpret_cast<struct nlmsghdr *>(buf); NLMSG_OK(nlmsgheader, (unsigned int)len); nlmsgheader = NLMSG_NEXT(nlmsgheader, len)) {
switch (nlmsgheader->nlmsg_type) {
case NLMSG_DONE:
break;
case NLMSG_ERROR:
perror("read_netlink");
break;
// case RTM_SETLINK: /* we try to use it in order to detect chaging in wireless inet configuration, but it didn't work
//#ifdef _DEBUG
// std::cout << "Network interface configuration modified" << std::endl ;
//#endif
// break;
case RTM_NEWLINK:
#ifdef _DEBUG
std::cout << "Network interface added" << std::endl ;
#endif
new_net_interface(nlmsgheader);
break;
case RTM_DELLINK:
#ifdef _DEBUG
std::cout << "Network interface deleted" << std::endl ;
#endif
del_net_interface(nlmsgheader);
break;
default:
break;
}
}
}
void MonitorWirelessDevice::new_net_interface(struct nlmsghdr *h)
{
int len;
struct rtattr *tb[IFLA_MAX + 1];
char *name;
struct rtattr *rta;
struct ifinfomsg *ifi;
struct ether_addr macaddr ;
ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(h));
/*if (!(ifi->ifi_flags & IFLA_ADDRESS))
{
std::cout << "! IFLA_ADDRESS" << std::endl ;
return;
}*/
#ifdef _DEBUG
if (ifi->ifi_flags & IFF_UP) { // get UP flag of the network interface
std::cout << "interface UP" << std::endl;
} else {
std::cout << "Interface DOWN" << std::endl;
}
#endif
/* retrieve all attributes */
memset(tb, 0, sizeof(tb));
rta = IFLA_RTA(ifi);
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
while (RTA_OK(rta, len)) {
if (rta->rta_type <= IFLA_MAX)
tb[rta->rta_type] = rta;
rta = RTA_NEXT(rta, len);
}
/* require name field to be set */
if (tb[IFLA_IFNAME]) {
name = static_cast<char *>(RTA_DATA(tb[IFLA_IFNAME]));
} else {
std::cerr << "do not find interface name" << std::endl ;
return;
}
#ifdef _DEBUG
if (ifi->ifi_family == AF_UNSPEC)
std::cout << "family: AF_UNSPEC" << std::endl;
if (ifi->ifi_family == AF_INET6)
std::cout << "family: AF_INET6" << std::endl ;
#endif
/* require address field to be set */
if (tb[IFLA_ADDRESS]) {
std::memcpy(&macaddr, static_cast<void *>(RTA_DATA(tb[IFLA_ADDRESS])), ETH_ALEN);
}
std::string inet_name(name);
WirelessDevice inetdevice (inet_name,ifi->ifi_index,ifi->ifi_type,macaddr,0);
if(inetdevice.checkif_wireless_device()){
get_winterface_infos(ifi->ifi_index); // we can call a callback here, instead calling it in recv_winterface_infos, to reduce cpu
}
}
void MonitorWirelessDevice::del_net_interface(struct nlmsghdr *h)
{
int len;
struct rtattr *tb[IFLA_MAX + 1];
char *name;
struct rtattr *rta;
struct ifinfomsg *ifi;
struct ether_addr macaddr ;
ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(h));
/*if (!(ifi->ifi_flags & IFLA_ADDRESS))
{
std::cout << "! IFLA_ADDRESS" << std::endl ;
return;
}*/
/* retrieve all attributes */
memset(tb, 0, sizeof(tb));
rta = IFLA_RTA(ifi);
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
while (RTA_OK(rta, len)) {
if (rta->rta_type <= IFLA_MAX)
tb[rta->rta_type] = rta;
rta = RTA_NEXT(rta, len);
}
/* require name field to be set */
if (tb[IFLA_IFNAME]) {
name = static_cast<char *>(RTA_DATA(tb[IFLA_IFNAME]));
} else {
std::cerr << "do not find interface name" << std::endl ;
return;
}
#ifdef _DEBUG
if (ifi->ifi_family == AF_UNSPEC)
std::cout << "family: AF_UNSPEC" << std::endl;
if (ifi->ifi_family == AF_INET6)
std::cout << "family: AF_INET6" << std::endl ;
#endif
/* require address field to be set */
if (tb[IFLA_ADDRESS]) {
std::memcpy(&macaddr, static_cast<void *>(RTA_DATA(tb[IFLA_ADDRESS])), ETH_ALEN);
std::string inet_name(name);
WirelessDevice inetdevice (inet_name,ifi->ifi_index,ifi->ifi_type,macaddr,0);
if(inetdevice.checkif_wireless_device()){
_delinet_cb(inetdevice);
}
}
}
/***********************************************************************************************/
/***************** handle communication with nl80211 module ***********************************/
/**********************************************************************************************/
int MonitorWirelessDevice::nl80211_init(){
std::cout << __func__ << std::endl ;
/* init netlink socket with nl80211 module */
wifi.nls = nl_socket_alloc();
if (!wifi.nls) {
std::cerr << "Failed to allocate netlink socket." << std::endl ;
return -ENOMEM;
}
nl_socket_set_buffer_size(wifi.nls, 8192, 8192);
if (genl_connect(wifi.nls)) {
std::cerr << "Failed to connect to generic netlink" << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOLINK;
}
wifi.nl80211_id = genl_ctrl_resolve(wifi.nls, "nl80211");
if (wifi.nl80211_id < 0) {
std::cerr << "nl80211 not found." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOENT;
}
/*set a callback that receive messages from a module */
wifi.cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!wifi.cb) {
std::cerr << "Failed to allocate netlink callback." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOMEM;
}
/*set a callback that receive messages from a module */
wifi.cb1 = nl_cb_alloc(NL_CB_DEFAULT);
if (!wifi.cb1) {
std::cerr << "Failed to allocate netlink callback." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOMEM;
}
/* set callbacks */
nl_cb_set(wifi.cb1, NL_CB_VALID, NL_CB_CUSTOM,recv_winterface_extra_infos_cb, &(wifi.err1));
nl_cb_set(wifi.cb1, NL_CB_FINISH, NL_CB_CUSTOM, handle_iee80211_com_finish_cb, &(wifi.err1));
nl_cb_set(wifi.cb, NL_CB_VALID, NL_CB_CUSTOM,recv_winterface_infos_cb, &(wifi.err));
nl_cb_set(wifi.cb, NL_CB_FINISH, NL_CB_CUSTOM, handle_iee80211_com_finish_cb, &(wifi.err));
return wifi.nl80211_id ;
}
int MonitorWirelessDevice::get_winterface_infos(int ifindex)
{
wifi.err = 1 ;
int flags ;
/* for one interface or for all interface */
if (ifindex != 0)
flags = 0;
else
flags = NLM_F_DUMP;
/* allocate a msg to send to a module */
struct nl_msg *msg = nlmsg_alloc();
if (!msg) {
std::cerr << "Failed to allocate netlink message." << std::endl ;
return -ENOMEM;
}
/* send get inerface command to deriver */
genlmsg_put(msg, 0, 0, wifi.nl80211_id, 0, flags , NL80211_CMD_GET_INTERFACE, 0);
//genlmsg_put(msg,NL_AUTO_PORT,NL_AUTO_SEQ,wifi.nl80211_id,0,flags, NL80211_CMD_GET_INTERFACE, 0);
if (ifindex != 0)
nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex);
if (nl_send_auto(wifi.nls, msg) < 0)
{
nlmsg_free(msg);
return -1 ;
}
if (ifindex != 0)
nl_recvmsgs(wifi.nls, wifi.cb);
else
while(wifi.err > 0)
nl_recvmsgs(wifi.nls, wifi.cb);
nlmsg_free(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_infos_cb(struct nl_msg *msg, [[maybe_unused]] void *arg){
forward->recv_winterface_infos(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_infos(struct nl_msg *msg){
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = static_cast<struct genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
char *ifname;
int ifindex;
int iftype;
struct ether_addr macaddr ;
uint32_t txp = 0;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
if (tb_msg[NL80211_ATTR_IFNAME])
ifname = nla_get_string(tb_msg[NL80211_ATTR_IFNAME]) ;
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_IFINDEX])
ifindex = nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_MAC])
std::memcpy(&macaddr, static_cast<void *>(nla_data(tb_msg[NL80211_ATTR_MAC])), ETH_ALEN);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_IFTYPE])
iftype = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) {
txp = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]);
}
std::string inet_name(ifname);
WirelessDevice inetdevice (inet_name,ifindex,iftype,macaddr,txp);
if(!init_interfaces){
_initinet_cb(inetdevice);
init_interfaces = true ;
}
else
_newinet_cb(inetdevice) ;
return NL_SKIP;
}
int MonitorWirelessDevice::recv_winterface_extra_infos_cb(struct nl_msg *msg, [[maybe_unused]] void *arg){
forward->recv_winterface_extra_infos(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_extra_infos(struct nl_msg *msg){
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = static_cast<struct genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
// struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
struct nla_policy stats[NL80211_STA_INFO_MAX + 1];
stats[NL80211_STA_INFO_INACTIVE_TIME].type = NLA_U32 ;
stats[NL80211_STA_INFO_RX_BYTES].type = NLA_U32 ;
stats[NL80211_STA_INFO_TX_BYTES].type = NLA_U32 ;
stats[NL80211_STA_INFO_RX_PACKETS].type = NLA_U32 ;
stats[NL80211_STA_INFO_TX_PACKETS].type = NLA_U32 ;
stats[NL80211_STA_INFO_SIGNAL].type = NLA_U8 ;
stats[NL80211_STA_INFO_TX_BITRATE].type = NLA_NESTED;
stats[NL80211_STA_INFO_LLID].type = NLA_U16 ;
stats[NL80211_STA_INFO_PLID].type = NLA_U16 ;
stats[NL80211_STA_INFO_PLINK_STATE].type = NLA_U8 ;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
/* get signal power-tx */
if (!tb_msg[NL80211_ATTR_STA_INFO]) {
std::cerr << __func__ << "sta stats missing!" << std::endl ;
return NL_SKIP;
}
if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb_msg[NL80211_ATTR_STA_INFO], stats))
{
std::cerr << "failed to parse nested attributes" << std::endl;
return NL_SKIP;
}
if (sinfo[NL80211_STA_INFO_SIGNAL]) {
int signal = 100+(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
std::cout << __func__ << " Signal : " << signal << std::endl ;
}
return NL_SKIP;
}
int MonitorWirelessDevice::handle_iee80211_com_finish_cb( [[maybe_unused]] struct nl_msg *msg, void *arg){
forward->handle_iee80211_com_finish(arg);
return 0 ;
}
int MonitorWirelessDevice::handle_iee80211_com_finish(void *arg){
#ifdef _DEBUG
std::cout << __func__ << std::endl ;
#endif
int *ret = static_cast<int *>(arg);
*ret = 0;
return NL_SKIP;
}
+199
View File
@@ -0,0 +1,199 @@
#ifndef _CMONITORWIRELESSDEVICE_H_
#define _CMONITORWIRELESSDEVICE_H_
#include "cwirelessdevice.h"
#include <list>
#include <mutex>
#include <functional>
namespace monitorinet {
class CallFromStaticFunc;
}
/** Buffer size for netlink route interface list */
#define IFLIST_REPLY_BUFFER 4096
typedef std::function<void(WirelessDevice)> CallbackFunction ;
typedef struct {
struct nl_sock *nls;
int nl80211_id;
int err,err1 ;
struct nl_cb* cb;
struct nl_cb* cb1;
} WIFI;
class MonitorWirelessDevice {
/* set to true when wireless interfaces are initialised */
bool init_interfaces = false ;
/* for netlink communication with 80211 module */
WIFI wifi ;
bool _outsideloop { true } ;
bool _started { false } ;
int _inetsock ;
std::mutex _startedmutex ;
std::mutex _outsideloopmutex ;
int main_loop();
/**
* \brief processes netlink route events from the kernel
* Determines the event type for netlink route messages (del/new).
* \return void
*/
void recv_inet_event();
bool outside_loop();
void clean();
/**
* \brief processes RTM_NEWLINK messages
* Detects when interfaces are created and modified
* \param struct nlmsghdr * - netlink message header
* \return void
*/
void new_net_interface(struct nlmsghdr *) ;
void del_net_interface(struct nlmsghdr *h);
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by new_net_interface function in order to send a created, deleted or changed wirelessdevice
*/
CallbackFunction _newinet_cb ;
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by new_net_interface function in order to send a created, deleted or changed wirelessdevice
*/
CallbackFunction _delinet_cb ;
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by recv_winterface_infos function in order to send infos of each existing wireless interface
*/
CallbackFunction _initinet_cb ;
static int recv_winterface_infos_cb(struct nl_msg *msg, void *arg);
static int recv_winterface_extra_infos_cb(struct nl_msg *msg, void *arg);
static int handle_iee80211_com_finish_cb(struct nl_msg *msg, void *arg);
static monitorinet::CallFromStaticFunc * forward ;
public:
MonitorWirelessDevice();
~MonitorWirelessDevice();
MonitorWirelessDevice(const MonitorWirelessDevice &) = delete ;
MonitorWirelessDevice & operator=(const MonitorWirelessDevice&) = delete ;
void start();
void stop();
bool started();
/**
* \brief set new interface notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setNewInetCallback(CallbackFunction);
/**
* \brief set delete interface notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setInitInetCallback(CallbackFunction);
/**
* \brief set interface initial list notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setDelInetCallback(CallbackFunction);
/**
*\fn int get_interface_infos()
* \brief Uses nl80211 to initialize a list of wireless interfaces Processes multiple netlink messages containing interface data
*\return error codes
*/
int get_winterface_infos(int);
int recv_winterface_infos(struct nl_msg *msg);
int recv_winterface_extra_infos(struct nl_msg *msg);
int handle_iee80211_com_finish(void *arg);
int nl80211_init() ;
};
/**
* \namespace monitorinet
*
* A namespace is used here, since a class CallFromStaticFunc is defined in other files
*/
namespace monitorinet {
/**
* \class CallFromStaticFunc
* \brief this class is an artifact used to call a member function from static function
*/
class CallFromStaticFunc {
MonitorWirelessDevice * m_obj ;
public:
explicit CallFromStaticFunc(MonitorWirelessDevice * obj){
m_obj = obj ;
};
int recv_winterface_infos(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->recv_winterface_infos(msg);
return 0 ;
};
int recv_winterface_extra_infos(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->recv_winterface_extra_infos(msg);
return 0 ;
};
int handle_iee80211_com_finish(void *arg) {
// add exception to check null ptr
m_obj->handle_iee80211_com_finish(arg);
return 0 ;
};
};
}
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "types.h" // TIndex / TPort
#ifndef DISABLE_VHOST
#define ENABLE_VHOST
#endif
const TIndex WIFI_MAX_DECONNECTED_CLIENT = 15;
const bool LOST_PACKET_BY_DEFAULT=false;
const TPort DEFAULT_WIFI_CLIENT_PORT_VHOST = 8211;
const TPort DEFAULT_WIFI_CLIENT_PORT_INET = DEFAULT_WIFI_CLIENT_PORT_VHOST+1;
const TPort DEFAULT_WIFI_SPY_PORT = DEFAULT_WIFI_CLIENT_PORT_VHOST+2;
const TPort DEFAULT_CTRL_PORT = DEFAULT_WIFI_CLIENT_PORT_VHOST+3;
#define DEFAULT_ADDRESS_IP "127.0.0.1"
const int MAX_SIZE_NAME=12;
const int DEFAULT_NUMBER_WLAN_INTERFACE=0;
#define DEFAULT_MAC_PREFIX "74:F8:F6"
#ifdef _DEBUG
// #define _VERBOSE1
// #define _VERBOSE2
#endif
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef _CONFIG_HWSIM_
#define _CONFIG_HWSIM_
#include "hwsim.h"
constexpr char KERNEL_HWSIM_FAMILY_NAME[] = "MAC80211_HWSIM";
#endif
+99
View File
@@ -0,0 +1,99 @@
#include <errno.h> // errno
#include <assert.h> // assert
#include <cstddef> // NULL
#include "cselect.h"
using namespace std;
CSelect::CSelect()
{
Init();
}
void CSelect::Init()
{
//clear the socket set
FD_ZERO(&Master);
//clear the socket set
FD_ZERO(&Dup);
MaxDescriptor=-1;
}
void CSelect::UpdateMaxDescriptor(TDescriptor descriptor)
{
//highest file descriptor number, need it for the select function
if ( descriptor > MaxDescriptor )
MaxDescriptor=descriptor;
}
bool CSelect::AddNode(TDescriptor descriptor)
{
//add new socket to array of sockets
ListNodes.push_back(descriptor);
//add child sockets to set
FD_SET( descriptor , &Master);
//highest file descriptor number, need it for the select function
UpdateMaxDescriptor(descriptor);
return true;
}
void CSelect::DelNode(TDescriptor descriptor)
{
MaxDescriptor=-1;
for (auto node = ListNodes.begin() ; node != ListNodes.end(); ++node)
{
if( *node == descriptor )
{
auto node_to_delete = node;
FD_CLR(descriptor , &Master);
for (++node ; node != ListNodes.end(); ++node)
UpdateMaxDescriptor(*node);
ListNodes.erase(node_to_delete);
return;
}
UpdateMaxDescriptor(*node);
}
}
TDescriptor CSelect::Wait()
{
return Wait(NULL);
}
TDescriptor CSelect::Wait(const sigset_t *sigmask)
{
/* back up master */
Dup = Master;
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
int activity=pselect( MaxDescriptor + 1 , &Dup , NULL , NULL , NULL, sigmask);
if ((activity < 0) && (errno!=EINTR))
return SCHEDULER_ERROR;
return activity;
}
bool CSelect::DescriptorHasAction(TDescriptor descriptor)
{
return FD_ISSET( descriptor , &Dup);
}
bool CSelect::NodeHasAction(TIndex index)
{
assert( index < ListNodes.size() );
return FD_ISSET( ListNodes[index] , &Dup);
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef _CSELECT_H_
#define _CSELECT_H_
#include <sys/select.h> // fd_set
#include <sys/socket.h>
#include <vector> // vector
#include "types.h" // TDescriptor
const int SCHEDULER_ERROR=-1;
class CSelect
{
private :
//set of socket descriptors
fd_set Master;
fd_set Dup;
TDescriptor MaxDescriptor;
std::vector<TDescriptor> ListNodes;
void UpdateMaxDescriptor(TDescriptor descriptor);
void Init();
public :
CSelect();
bool AddNode(TDescriptor descriptor);
void DelNode(TDescriptor descriptor);
TDescriptor Wait();
TDescriptor Wait(const sigset_t *sigmask);
bool DescriptorHasAction(TDescriptor descriptor);
bool NodeHasAction(TIndex index);
};
#endif
+106
View File
@@ -0,0 +1,106 @@
#include <cstdio> //perror
#include <iostream> // cout
#include <sys/socket.h> //socket
#include <arpa/inet.h> // struct sockaddr_in & inet_ntoa & ntohs
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include <unistd.h> // close
#include <fcntl.h> // F_GETFL O_NONBLOCK
#include "csocket.h"
using namespace std;
CSocket::CSocket()
{
Master=0;
}
CSocket::~CSocket()
{
Close();
}
CSocket::CSocket( const CSocket & socket )
{
Master=socket.Master;
}
TDescriptor CSocket::GetDescriptor() const
{
return Master;
}
ssize_t CSocket::Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData)
{
ssize_t ret = send(descriptor, data, sizeOfData, 0);
if ( ret != sizeOfData )
return SOCKET_ERROR ;
return ret;
}
ssize_t CSocket::SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData)
{
ssize_t ret = Send(descriptor, (char*)&sizeOfData, (unsigned)sizeof(sizeOfData));
if( ret == SOCKET_ERROR )
return SOCKET_ERROR;
return Send(descriptor, data, sizeOfData);
}
ssize_t CSocket::Read(TDescriptor descriptor, char* data, ssize_t sizeOfData)
{
ssize_t ret = recv(descriptor , data, sizeOfData, 0);
if ( ret <= 0 )
return SOCKET_ERROR ;
return ret;
}
ssize_t CSocket::ReadEqualSize(TDescriptor descriptor, CDynBuffer* data, ssize_t byteAlreadyRead, ssize_t sizeToRead)
{
ssize_t sizeToRead_backup = sizeToRead;
sizeToRead-=byteAlreadyRead;
data->NeededSize(sizeToRead_backup,(byteAlreadyRead!=0));
char* buffer = data->GetBuffer();
buffer+=byteAlreadyRead;
while( sizeToRead > 0 )
{
ssize_t sizeRead=Read(descriptor, buffer, sizeToRead);
if( sizeRead == SOCKET_ERROR )
return SOCKET_ERROR;
sizeToRead-=sizeRead;
buffer+=sizeRead;
}
return sizeToRead_backup;
}
ssize_t CSocket::ReadBigData(TDescriptor descriptor, CDynBuffer* data)
{
TMinimalSize size;
int ret = Read(descriptor, (char*)&size, (unsigned)sizeof(size));
if( ret == SOCKET_ERROR )
return SOCKET_ERROR;
return ReadEqualSize(descriptor, data, 0, size);
}
CSocket::operator int()
{
return Master;
}
void CSocket::Close()
{
close(Master);
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef _CSOCKET_H_
#define _CSOCKET_H_
#include <sys/types.h> // ssize_t
#include "types.h" // TDescriptor / TSocket
#include "cdynbuffer.h" // CDynBuffer
const int SOCKET_ERROR=-1;
class CSocket
{
friend class CWifi;
protected :
TDescriptor Master;
CSocket();
CSocket( const CSocket & socket );
TDescriptor GetDescriptor() const;
virtual ssize_t Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData);
virtual ssize_t SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData);
virtual ssize_t Read(TDescriptor descriptor, char* data, ssize_t sizeOfData);
virtual ssize_t ReadBigData(TDescriptor descriptor, CDynBuffer* data);
private :
ssize_t ReadEqualSize(TDescriptor descriptor, CDynBuffer* data, ssize_t byteAlreadyRead, ssize_t sizeToRead);
public :
void Close();
~CSocket();
operator int();
};
#endif
+102
View File
@@ -0,0 +1,102 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include "csocketclient.h"
#include "tools.h"
using namespace std;
// ----------------- CSocketClient
CSocketClient::~CSocketClient()
{
CSocket::Close();
}
CSocketClient::CSocketClient() : CSocket()
{
Init();
}
void CSocketClient::Init()
{
IsConnected=false;
StopTheReconnect=false ;
}
bool CSocketClient::ConnectLoop()
{
while ( ! StopTheReconnect )
{
if( _Connect() )
return true;
}
// The system asks to stop the reconnect
return false;
}
bool CSocketClient::Connect(struct sockaddr* server, size_t size_of_server)
{
if( ! _Configure() )
{
cerr<<"Error : CSocketClient::Connect : Configure"<<endl;
return false;
}
if( ! connect(Master,server,size_of_server) )
{
IsConnected=true;
return true;
}
perror("CSocketClient::Connect : connect");
Close();
sleep(2);
return false;
}
ssize_t CSocketClient::Send(const char* data, ssize_t sizeOfData)
{
if ( IsConnected ){
return CSocket::Send(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::SendBigData(const char* data, TMinimalSize sizeOfData)
{
if ( IsConnected ){
return CSocket::SendBigData(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::Read(char* data, ssize_t sizeOfData)
{
if ( IsConnected ){
return CSocket::Read(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::ReadBigData(CDynBuffer* data)
{
if ( IsConnected ){
return CSocket::ReadBigData(Master, data);
}
return SOCKET_ERROR;
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef _CSOCKETCLIENT_H_
#define _CSOCKETCLIENT_H_
#include "csocket.h"
class CSocketClient : public CSocket
{
bool IsConnected;
bool StopTheReconnect;
void Init();
protected :
bool Connect(struct sockaddr* server, size_t size_of_server);
public :
CSocketClient();
virtual ~CSocketClient();
using CSocket::Send;
ssize_t Send(const char* data, ssize_t sizeOfData);
using CSocket::SendBigData;
ssize_t SendBigData(const char* data, TMinimalSize sizeOfData);
using CSocket::Read;
ssize_t Read(char* data, ssize_t sizeOfData);
using CSocket::ReadBigData;
ssize_t ReadBigData(CDynBuffer* data);
bool ConnectLoop();
// virtual :
virtual bool _Configure() = 0;
virtual bool _Connect() = 0;
virtual int _GetID() = 0;
};
#endif
+53
View File
@@ -0,0 +1,53 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include "csocketclientitcp.h"
#include "tools.h"
using namespace std;
CSocketClientITCP::CSocketClientITCP() : CSocketClient()
{
}
void CSocketClientITCP::Init(const char* IP, TPort port)
{
Server.sin_family = AF_INET;
Server.sin_addr.s_addr = inet_addr(IP);
Server.sin_port = htons(port);
}
bool CSocketClientITCP::_Configure()
{
Master = socket(AF_INET , SOCK_STREAM , 0);
if( Master == SOCKET_ERROR )
{
perror("CSocketClientITCP::Configure : socket");
return false;
}
return true;
}
bool CSocketClientITCP::_Connect()
{
return Connect((struct sockaddr*) &Server, sizeof(Server));
}
int CSocketClientITCP::_GetID()
{
struct sockaddr_in my_addr;
socklen_t len = sizeof(my_addr);
getsockname(Master, (struct sockaddr *) &my_addr, &len);
return hash_ipaddr(&my_addr) ;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef _CSOCKETCLIENTITCP_H_
#define _CSOCKETCLIENTITCP_H_
#include "csocketclient.h"
#include <netinet/ip.h> // struct sockaddr_in
class CSocketClientITCP : public CSocketClient
{
private :
struct sockaddr_in Server;
public :
CSocketClientITCP();
void Init(const char* IP, TPort port);
bool _Configure() override;
bool _Connect() override;
int _GetID() override;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include <cstring> // memset
#include "csocketclientvtcp.h"
#include "tools.h"
using namespace std;
CSocketClientVTCP::CSocketClientVTCP() : CSocketClient()
{
}
void CSocketClientVTCP::Init(TPort port)
{
memset(&Server, 0, sizeof(Server));
Server.svm_family = AF_VSOCK;
Server.svm_port = port;
Server.svm_cid = 2;
}
bool CSocketClientVTCP::_Configure()
{
Master = socket(AF_VSOCK , SOCK_STREAM , 0);
if( Master == SOCKET_ERROR )
{
perror("CSocketClientVTCP::Configure : socket");
return false;
}
return true;
}
bool CSocketClientVTCP::_Connect()
{
return Connect((struct sockaddr*) &Server, sizeof(Server));
}
int CSocketClientVTCP::_GetID()
{
int cid;
int ioctl_fd = open("/dev/vsock", 0);
if (ioctl_fd < 0)
{
perror("Error : CSocketClientVHOST::GetID : open /dev/vsock :");
return -1;
}
if( ioctl(ioctl_fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid) < 0 )
{
perror("Error : CSocketClientVHOST::GetID : ioctl : Cannot get local CID :");
close(ioctl_fd);
return -1;
}
close(ioctl_fd);
return cid;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef _CSOCKETCLIENTVTCP_H_
#define _CSOCKETCLIENTVTCP_H_
#include <netinet/ip.h> // struct sockaddr_in
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocketclient.h"
class CSocketClientVTCP : public CSocketClient
{
private :
struct sockaddr_vm Server;
public :
CSocketClientVTCP();
void Init(TPort port);
bool _Configure() override;
bool _Connect() override;
int _GetID() override;
};
#endif
+166
View File
@@ -0,0 +1,166 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocketserver.h"
using namespace std;
CSocketServer::CSocketServer(CListInfo<CInfoSocket>* infoSockets) : CSocket()
{
Init(0);
if( infoSockets == NULL )
{
InfoSockets = new CListInfo<CInfoSocket>;
ListInfoSelfManaged=true;
}
else
{
InfoSockets = infoSockets;
ListInfoSelfManaged=false;
}
}
CSocketServer::CSocketServer( const CSocketServer & socketServer ) : CSocket(socketServer)
{
*this=socketServer;
}
CSocketServer& CSocketServer::operator=(const CSocketServer& socketServer)
{
if( this != &socketServer )
{
// protect against invalid self-assignment
Init(socketServer.GetPort());
ListInfoSelfManaged=socketServer.ListInfoSelfManaged;
if( ListInfoSelfManaged )
{
if( InfoSockets != NULL )
delete InfoSockets;
InfoSockets = new CListInfo<CInfoSocket>(*(socketServer.InfoSockets));
}
else
{
InfoSockets = socketServer.InfoSockets;
}
}
// by convention, always return *this
return *this;
}
void CSocketServer::Init(TPort port)
{
Port=port;
}
TPort CSocketServer::GetPort() const
{
return Port;
}
CSocketServer::~CSocketServer()
{
for (auto& infoSocket : *InfoSockets)
infoSocket.Close();
delete InfoSockets;
CSocket::Close();
}
bool CSocketServer::Listen()
{
return _Listen(Master, Port);
}
TDescriptor CSocketServer::Accept(TCID& cid)
{
TDescriptor new_socket;
new_socket = _Accept(Master, cid);
if( new_socket == SOCKET_ERROR )
return SOCKET_ERROR;
//add new socket to array of sockets
InfoSockets->push_back(CInfoSocket(new_socket));
return new_socket;
}
TDescriptor CSocketServer::Accept()
{
TCID cid;
return Accept(cid);
}
TDescriptor CSocketServer::GetSocketClient(TIndex index) const
{
assert( index < InfoSockets->size() );
return (*InfoSockets)[index].GetDescriptor();
}
TDescriptor CSocketServer::operator[] (TIndex index)
{
return GetSocketClient(index);
}
TIndex CSocketServer::GetNumberClient() const
{
return InfoSockets->size();
}
bool CSocketServer::IsEnable(TIndex index)
{
assert( index < GetNumberClient() );
return (*InfoSockets)[index].IsEnable();
}
void CSocketServer::DisableClient(TIndex index)
{
assert( index < InfoSockets->size() );
(*InfoSockets)[index].DisableIt();
}
void CSocketServer::CloseClient(TIndex index)
{
assert( index < InfoSockets->size() );
(*InfoSockets)[index].Close();
InfoSockets->erase (InfoSockets->begin()+index);
}
ssize_t CSocketServer::Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData)
{
return CSocket::Send(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData)
{
return CSocket::SendBigData(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::Read(TDescriptor descriptor, char* data, ssize_t sizeOfData)
{
return CSocket::Read(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::ReadBigData(TDescriptor descriptor, CDynBuffer* data)
{
return CSocket::ReadBigData(descriptor, data);
}
+63
View File
@@ -0,0 +1,63 @@
#ifndef _CSOCKETSERVER_H_
#define _CSOCKETSERVER_H_
#include "csocket.h"
#include "cinfosocket.h"
#include "clistinfo.h"
#include "types.h" // TIndex
class CSocketServer : public CSocket
{
protected :
TPort Port;
bool ListInfoSelfManaged;
CListInfo<CInfoSocket>* InfoSockets;
TDescriptor GetSocketClient(TIndex index) const;
TDescriptor Accept(TCID& cid);
TDescriptor Accept();
explicit CSocketServer(CListInfo<CInfoSocket>* infoSockets = NULL);
CSocketServer(TSocket type, CListInfo<CInfoSocket>* infoSockets = NULL);
CSocketServer( const CSocketServer & socketServer );
~CSocketServer();
CSocketServer& operator=(const CSocketServer& socketServer);
TPort GetPort() const;
void DisableClient(TIndex index);
void CloseClient(TIndex index);
ssize_t Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData) override;
ssize_t SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData) override;
ssize_t Read(TDescriptor descriptor, char* data, ssize_t sizeOfData) override;
ssize_t ReadBigData(TDescriptor descriptor, CDynBuffer* data) override;
// virtual :
virtual bool _Listen(TDescriptor& master, TPort port) = 0;
virtual TDescriptor _Accept(TDescriptor master, TCID& cid) = 0;
public :
TIndex GetNumberClient() const;
TDescriptor operator[] (TIndex index);
bool IsEnable(TIndex index);
void Init(TPort port);
bool Listen();
};
#endif
+95
View File
@@ -0,0 +1,95 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include "csocket.h" // SOCKET_ERROR
#include "csocketserverfunctionitcp.h"
#include "tools.h"
using namespace std;
bool CSocketServerFunctionITCP::Configure(TDescriptor& master)
{
//create a master socket
master = socket(AF_INET , SOCK_STREAM , 0);
if( master == SOCKET_ERROR )
{
perror("CSocketServerFunctionITCP::Configure : socket");
return false;
}
return true;
}
bool CSocketServerFunctionITCP::_Listen(TDescriptor& master, TPort port)
{
if( ! Configure(master) )
{
cerr<<"Error : CSocketServerFunctionITCP::_Listen : Configure"<<endl;
return false;
}
//set master socket to allow multiple connections ,
//this is just a good habit, it will work without this
int opt = 1 ; // TRUE
if( setsockopt(master, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_REUSEADDR");
return false;
}
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (setsockopt (master, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_RCVTIMEO\n");
if (setsockopt (master, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_SNDTIMEO\n");
//type of socket created
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( port );
//bind the socket
if (bind(master, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("CSocketServer::_Listen : bind");
return false;
}
cout<<"Listener on port : "<<port<<endl;
//try to specify maximum of 3 pending connections for the master socket
if( listen(master, 3) < 0 )
{
perror("CSocketServerFunctionITCP::_Listen : listen");
return false;
}
return true;
}
TDescriptor CSocketServerFunctionITCP::_Accept(TDescriptor master, TCID& cid)
{
TDescriptor new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if( (new_socket = accept(master, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0 )
{
perror("CSocketServerFunctionITCP::_Accept : accept");
return SOCKET_ERROR;
}
cid=hash_ipaddr(&address);
return new_socket;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CSOCKETSERVERFUNCTIONITCP_H_
#define _CSOCKETSERVERFUNCTIONITCP_H_
#include "types.h"
class CSocketServerFunctionITCP
{
private :
bool Configure(TDescriptor& master);
protected:
bool _Listen(TDescriptor& master, TPort port);
TDescriptor _Accept(TDescriptor master, TCID& cid);
};
#endif
+91
View File
@@ -0,0 +1,91 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memset
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocket.h" // SOCKET_ERROR
#include "csocketserverfunctionvtcp.h"
using namespace std;
bool CSocketServerFunctionVTCP::Configure(TDescriptor& master)
{
//create a master socket
master = socket(AF_VSOCK , SOCK_STREAM , 0);
if( master == SOCKET_ERROR )
{
perror("CSocketServerFunctionVTCP::_Configure : socket");
return false;
}
return true;
}
bool CSocketServerFunctionVTCP::_Listen(TDescriptor& master, TPort port)
{
if( ! Configure(master) )
{
cerr<<"Error : CSocketServerFunctionVTCP::_Listen : Configure"<<endl;
return false;
}
//type of socket created
struct sockaddr_vm address;
memset(&address, 0, sizeof(address));
address.svm_family = AF_VSOCK;
address.svm_port = port;
address.svm_cid = VMADDR_CID_ANY;
//bind the socket
if (bind(master, (struct sockaddr*)&address, sizeof(address)) != 0)
{
perror("CSocketServerFunctionVTCP::_Listen : bind");
return false;
}
/* Seems useless with VSOCK : the server detects immediately that a client is disconnected
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (setsockopt (master, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionVTCP::_Listen : setsockopt : SO_RCVTIMEO\n");
if (setsockopt (master, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionVTCP::_Listen : setsockopt : SO_SNDTIMEO\n");
*/
cout<<"Listener on port : "<<port<<endl;
//try to specify maximum of 3 pending connections for the master socket
if( listen(master, 3) < 0 )
{
perror("CSocketServerFunctionVTCP::_Listen : listen");
return false;
}
return true;
}
TDescriptor CSocketServerFunctionVTCP::_Accept(TDescriptor master, TCID& cid)
{
TDescriptor new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if( (new_socket = accept(master, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0 )
{
perror("CSocketServerFunctionVTCP::_Accept : accept");
return SOCKET_ERROR;
}
cid=((struct sockaddr_vm*)&address)->svm_cid;
return new_socket;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CSOCKETSERVERFUNCTIONVTCP_H_
#define _CSOCKETSERVERFUNCTIONVTCP_H_
#include "types.h"
class CSocketServerFunctionVTCP
{
private :
bool Configure(TDescriptor& master);
protected:
bool _Listen(TDescriptor& master, TPort port);
TDescriptor _Accept(TDescriptor master, TCID& cid);
};
#endif
+142
View File
@@ -0,0 +1,142 @@
#include "cthread.h"
#include <condition_variable>
#include <signal.h>
namespace intthread {
/*********************************************************/
/* Global variables and functions */
/********************************************************/
thread_local InterruptFlag this_thread_interrupt_flag ;
void interruption_point(){
if(this_thread_interrupt_flag.is_set())
{
throw thread_interrupted();
}
}
/*********************************************************/
/* InterruptFlag class definitions */
/********************************************************/
InterruptFlag::InterruptFlag()
{
_set = false ;
}
void InterruptFlag::set(){
std::lock_guard<std::mutex> guard(_mutex);
_set = true ;
}
bool InterruptFlag::is_set() {
std::lock_guard<std::mutex> guard(_mutex);
return _set ;
}
/*********************************************************/
/* InterruptibleThread class definitions */
/********************************************************/
int InterruptibleThread::number_thread = 0 ;
std::mutex InterruptibleThread::_number_thread_mutex ;
InterruptibleThread::InterruptibleThread(){
count_thread();
}
bool InterruptibleThread::started()
{
return _started ;
}
void InterruptibleThread::interrupt(){
if (_interrupt_flag != nullptr){
_interrupt_flag->set();
}
_started = false ;
}
void InterruptibleThread::join(){
_internal_thread.join();
}
pthread_t InterruptibleThread::get_native_handle(){
return _internal_thread.native_handle();
}
std::thread::id InterruptibleThread::get_id(){
return _internal_thread.get_id();
}
void InterruptibleThread::count_thread(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
number_thread++;
}
void InterruptibleThread::uncount_thread(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
number_thread--;
}
bool InterruptibleThread::all_thread_interrupted(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
return (number_thread == 0);
}
/*********************************************************/
/* AsyncTask class definitions */
/********************************************************/
AsyncTask::AsyncTask(){
}
void AsyncTask::dead() {
std::unique_lock<std::mutex> lk(_mutex_condition);
InterruptibleThread::uncount_thread() ;
_condition.notify_all();
lk.unlock();
}
}
+127
View File
@@ -0,0 +1,127 @@
#ifndef _CTHREAD_H_
#define _CTHREAD_H_
#include <pthread.h>
#include <thread>
#include <future>
#include <iostream>
#include <mutex>
//#include <functional>
namespace intthread {
void interruption_point();
struct thread_interrupted{};
class InterruptFlag
{
private:
bool _set ;
std::mutex _mutex ;
public:
InterruptFlag();
void set();
bool is_set() ;
};
class AsyncTask
{
protected :
std::condition_variable _condition ;
std::mutex _mutex_condition ;
public:
AsyncTask();
void dead() ;
};
extern thread_local InterruptFlag this_thread_interrupt_flag ;
class InterruptibleThread
{
private:
InterruptFlag* _interrupt_flag {nullptr} ;
std::thread _internal_thread ;
static int number_thread ;
static std::mutex _number_thread_mutex ;
bool _started {false} ;
public:
InterruptibleThread();
pthread_t get_native_handle();
/* include <functional> with this version */
/*template<typename CLASS>
void start(CLASS * obj , void (CLASS::* f)() ){
std::function< void(void)> _f = std::bind(f,*obj) ;
std::promise<InterruptFlag*> p ;
_internal_thread = std::thread([_f,&p]{
p.set_value(&this_thread_interrupt_flag);
_f();
});
_interrupt_flag = p.get_future().get();
}*/
bool started() ;
template <typename OBJECT, typename FUNC>
void start(OBJECT * obj , FUNC f ){
std::promise<InterruptFlag*> p ;
_internal_thread = std::thread([obj,f,&p]{
p.set_value(&this_thread_interrupt_flag);
(obj->*f)();
});
_interrupt_flag = p.get_future().get();
_started = true ;
}
void interrupt();
void join();
std::thread::id get_id();
static bool all_thread_interrupted();
static void count_thread();
static void uncount_thread();
};
} // intthread space
#endif
+97
View File
@@ -0,0 +1,97 @@
#include <math.h> // log10
#include <stdlib.h> // rand
#include <iostream>
#include <netlink/netlink.h> // (struct nlmsghdr *)
#include "hwsim.h" // HWSIM_ATTR_FREQ
#include <netlink/genl/genl.h> // genlmsg_parse
#include "cwifi.h"
//#include "config.h"
const double ConstanteC=92.45;
const TFrequency DEFAULT_FREQUENCY=2412; // Hz
const int MTU=2352; // Maximum Transmission Unit : 2352 (from include/linux/ieee80211.h)
TFrequency CWifi::GetFrequency(struct nlmsghdr* nlh)
{
/* we get the attributes*/
struct nlattr *attrs[HWSIM_ATTR_FREQ + 1];
genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_FREQ, NULL);
/* we get frequence */
if (attrs[HWSIM_ATTR_FREQ])
return nla_get_u32(attrs[HWSIM_ATTR_FREQ]);
else
return DEFAULT_FREQUENCY;
}
// distance : meter
// frequency : Hz
int CWifi::Attenuation(TDistance distance, TFrequency frequency)
{
if( distance == 0 )
return 0;
// ConstanteC+20*log10(frequency/1000)+20*log10(distance/1000);
// ConstanteC+20*(log10(frequency)-log10(1000))+20*(log10(distance)-log10(1000))
return ConstanteC+20*(log10(frequency)-3)+20*(log10(distance)-3);
}
TPower CWifi::BoundedPower(int power)
{
if( power < TPower_MIN )
return TPower_MIN;
if( power > TPower_MAX )
return TPower_MAX;
return power;
}
bool CWifi::PacketIsLost(TPower signalLevel)
{
//don't forget : signalLevel is negative
int alea = rand() % 53 + 40; // between 40 and 92
if( alea > -signalLevel )
return false;
return true;
}
ssize_t CWifi::SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
{
// cout<<"send power : "<<power<<endl;
int val=socket->Send(descriptor, reinterpret_cast<const char*>(power), sizeof(TPower));
if( val <= 0 )
return val;
// std::cout<<"send big data of size : "<<sizeOfBuffer<<std::endl;
return socket->Send(descriptor, buffer, sizeOfBuffer);
}
ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
{
int valread;
// read the power
valread = socket->Read(descriptor, reinterpret_cast<char*>(power), sizeof(TPower));
if ( valread <= 0 )
return valread;
// read the signal
// "nlmsg_len" (type "uint32_t") is the first attribut of the "struct nlmsghdr" in "libnl3/netlink/netlink-kernel.h"
ssize_t sizeRead = socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr));
if( sizeRead == SOCKET_ERROR )
return SOCKET_ERROR;
int sizeTotal=reinterpret_cast<struct nlmsghdr *>(buffer->GetBuffer())->nlmsg_len;
if( sizeTotal > MTU ) // to avoid that a error packet overfulls the memory
return SOCKET_ERROR;
return socket->ReadEqualSize(descriptor, buffer, sizeRead, sizeTotal);
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _WIFI_H_
#define _WIFI_H_
#include "types.h" // TPower
#include "csocket.h" // CSocket
class CWifi
{
protected :
TFrequency GetFrequency(struct nlmsghdr* nlh);
// distance : meter
int Attenuation(TDistance distance, TFrequency frequency);
// return power value between [TPower_MIN,TPower_MAX]
TPower BoundedPower(int power);
bool PacketIsLost(TPower signalLevel);
ssize_t SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer);
ssize_t RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer);
};
#endif
+1
View File
@@ -0,0 +1 @@
#include "cwificlient.h"
+35
View File
@@ -0,0 +1,35 @@
#ifndef _CWIFICLIENT_H_
#define _CWIFICLIENT_H_
#include "ckernelwifi.h"
#include "csocketclient.h"
#include "cwifi.h"
template <typename TypeCSocketClient>
class CWifiClient : public CKernelWifi, public CWifi, public TypeCSocketClient
{
bool _Connect(int* id) override
{
if( ! TypeCSocketClient::_Connect() )
return false;
if( ! Scheduler.AddNode(*this) )
return false;
*id=TypeCSocketClient::_GetID();
return true;
}
ssize_t _SendSignal(TPower* power, const char* buffer, int sizeOfBuffer) override
{ return SendSignalWithSocket(this, this->GetDescriptor(), power, buffer, sizeOfBuffer); }
ssize_t _RecvSignal(TPower* power, CDynBuffer* buffer) override
{ return RecvSignalWithSocket(this, this->GetDescriptor(), power, buffer); }
void _Close() override { TypeCSocketClient::Close(); };
};
#endif /* _CWIFICLIENT_H_ */
+267
View File
@@ -0,0 +1,267 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // struct sockaddr_in
#include <sys/socket.h> // AF_VSOCK / AF_INET
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "cwifiserver.h"
#include "tools.h"
#include "config.h" // LOST_PACKET_BY_DEFAULT
bool CanLostPackets=LOST_PACKET_BY_DEFAULT;
using namespace std;
CWifiServer::CWifiServer() : CSocketServer ()
{
DefaultValues();
InfoWifis = new CListInfo<CInfoWifi>;
InfoWifisDeconnected = new CListInfo<CInfoWifi>;
}
CWifiServer::CWifiServer(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CSocketServer (infoSockets)
{
DefaultValues();
InfoWifis = infoWifis;
InfoWifisDeconnected = infoWifisDeconnected;
}
CWifiServer::CWifiServer( const CWifiServer & wifiServer ) : CSocketServer(wifiServer), CWifi(wifiServer)
{
*this=wifiServer;
}
CWifiServer::~CWifiServer()
{
if( ListInfoSelfManaged )
{
delete InfoWifis;
delete InfoWifisDeconnected;
}
}
CWifiServer& CWifiServer::operator=(const CWifiServer& wifiServer)
{
if( this != &wifiServer )
{
// protect against invalid self-assignment
MaxClientDeconnected=wifiServer.MaxClientDeconnected;
if( ListInfoSelfManaged )
{
if( InfoWifis != NULL )
{
delete InfoWifis;
delete InfoWifisDeconnected;
}
InfoWifis = new CListInfo<CInfoWifi>(*(wifiServer.InfoWifis));
InfoWifisDeconnected = new CListInfo<CInfoWifi>(*(wifiServer.InfoWifisDeconnected));
}
else
{
InfoWifis = wifiServer.InfoWifis;
InfoWifisDeconnected = wifiServer.InfoWifisDeconnected;
}
}
// by convention, always return *this
return *this;
}
void CWifiServer::DefaultValues()
{
MaxClientDeconnected=0;
}
bool CWifiServer::Listen(TIndex maxClientDeconnected)
{
MaxClientDeconnected=maxClientDeconnected;
if( ! _Listen(Master, Port) )
return false;
return true;
}
bool CWifiServer::RecoverInfosOfInfoWifiDeconnected(TCID cid, CCoordinate& coo, string& name)
{
for (auto infoWifiDeconnected = InfoWifisDeconnected->begin(); infoWifiDeconnected != InfoWifisDeconnected->end(); ++infoWifiDeconnected)
{
if ( infoWifiDeconnected->GetCid() == cid )
{
coo=*infoWifiDeconnected;
name=infoWifiDeconnected->GetName();
InfoWifisDeconnected->erase(infoWifiDeconnected);
return true;
}
}
return false;
}
bool CWifiServer::RecoverInfosOfInfoWifi(TCID cid, CCoordinate& coo, string& name)
{
int index=0;
for (auto& infoWifi : *InfoWifis)
{
if( IsEnable(index) )
if( infoWifi.GetCid() == cid )
{
coo=infoWifi;
name=infoWifi.GetName();
DisableClient(index);
return true;
}
index++;
}
return false;
}
TDescriptor CWifiServer::Accept()
{
TCID cid;
TDescriptor new_socket = CSocketServer::Accept(cid);
if( new_socket == SOCKET_ERROR )
return SOCKET_ERROR;
CInfoWifi infoWifi;
CCoordinate coo;
string name;
if( RecoverInfosOfInfoWifiDeconnected(cid,coo,name) || RecoverInfosOfInfoWifi(cid, coo,name) )
{
infoWifi.Set(coo);
infoWifi.SetName(name);
}
infoWifi.SetCid(cid);
InfoWifis->push_back(infoWifi);
return new_socket;
}
void CWifiServer::ShowInfoWifi(TIndex index)
{
assert( index < GetNumberClient() );
cout<<(*InfoWifis)[index];
}
void CWifiServer::CloseClient(TIndex index)
{
assert( index < GetNumberClient() );
CSocketServer::CloseClient(index);
// save the InfoWifi (the coordinate of the cid)
AddInfoWifiDeconnected( (*InfoWifis)[index] );
InfoWifis->erase(InfoWifis->begin()+index);
}
void CWifiServer::CloseAllClient()
{
// ( be careful : "TIndex i" is a **unsigned** int : i=0 ; i-1 != -1 but = 65534 )
TIndex nbre=GetNumberClient(); // because CloseClient changes the value of GetNumberClient()
for (TIndex i = 0; i < nbre; i++)
CloseClient(0); // we can Close the 0 because we use the shift
}
ssize_t CWifiServer::SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
{
return SendSignalWithSocket(this, descriptor, power, buffer, sizeOfBuffer);
}
ssize_t CWifiServer::RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
{
return RecvSignalWithSocket(this, descriptor, power, buffer);
}
void CWifiServer::SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData)
{
CCoordinate coo=(*InfoWifis)[index];
// cout<<"Forward "<<sizeOfData<<" bytes with "<<power<<" powers"<<endl;
for (TIndex i = 0; i < GetNumberClient(); i++)
{
if( i != index )
if( IsEnable(i) )
{
TFrequency frequency = static_cast<TFrequency>(GetFrequency( reinterpret_cast<struct nlmsghdr*>(const_cast<char*>(data)) ));
TPower signalLevel=BoundedPower(power-Attenuation(coo.DistanceWith((*InfoWifis)[i]),frequency));
if( ! CanLostPackets || ! PacketIsLost(signalLevel) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &signalLevel, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
}
}
void CWifiServer::SendAllOtherClientsWithoutLoss(TIndex index, TPower power, const char* data, ssize_t sizeOfData)
{
for (TIndex i = 0; i < GetNumberClient(); i++)
{
if( i != index )
if( IsEnable(i) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
}
void CWifiServer::SendAllClientsWithoutLoss(TPower power, const char* data, ssize_t sizeOfData)
{
for (TIndex i = 0; i < GetNumberClient(); i++)
if( IsEnable(i) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiByCID(TCID cid) const
{
for (auto& infoWifi : *InfoWifis)
{
if( infoWifi.GetCid() == cid )
return &infoWifi;
}
return NULL;
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiDeconnectedByCID(TCID cid) const
{
for (auto& infoWifiDeconnected : *InfoWifisDeconnected)
{
if( infoWifiDeconnected.GetCid() == cid )
return &infoWifiDeconnected;
}
return NULL;
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiByIndex(TIndex index) const
{
assert( index < GetNumberClient() );
return &((*InfoWifis)[index]);
}
void CWifiServer::AddInfoWifiDeconnected(CInfoWifi infoWifi)
{
if( InfoWifisDeconnected->size() >= MaxClientDeconnected )
InfoWifisDeconnected->erase(InfoWifisDeconnected->begin());
InfoWifisDeconnected->push_back(infoWifi);
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef _CWIFISERVER_H_
#define _CWIFISERVER_H_
#include "csocketserver.h"
#include "cinfowifi.h"
#include "cwifi.h"
extern bool CanLostPackets;
class CWifiServer : public CSocketServer, public CWifi
{
friend class CCTRLServer;
TIndex MaxClientDeconnected;
CListInfo<CInfoWifi>* InfoWifis;
CListInfo<CInfoWifi>* InfoWifisDeconnected;
bool RecoverInfosOfInfoWifiDeconnected(TCID cid, CCoordinate& coo, string& name);
bool RecoverInfosOfInfoWifi(TCID cid, CCoordinate& coo, string& name);
void DefaultValues();
public :
CWifiServer();
CWifiServer(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
CWifiServer( const CWifiServer & wifiServer );
~CWifiServer();
CWifiServer& operator=(const CWifiServer& wifiServer);
bool Listen(TIndex maxClientDeconnected);
TDescriptor Accept();
void ShowInfoWifi(TIndex index);
void CloseClient(TIndex index);
void CloseAllClient();
ssize_t SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer);
ssize_t RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer);
void SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData);
void SendAllOtherClientsWithoutLoss(TIndex index, TPower power, const char* data, ssize_t sizeOfData);
void SendAllClientsWithoutLoss(TPower power, const char* data, ssize_t sizeOfData);
CInfoWifi* GetReferenceOnInfoWifiByCID(TCID cid) const;
CInfoWifi* GetReferenceOnInfoWifiDeconnectedByCID(TCID cid) const;
CInfoWifi* GetReferenceOnInfoWifiByIndex(TIndex index) const;
void AddInfoWifiDeconnected(CInfoWifi infoWifi);
};
#endif
+19
View File
@@ -0,0 +1,19 @@
#include"cwifiserveritcp.h"
CWifiServerITCP::CWifiServerITCP() : CWifiServer()
{
}
CWifiServerITCP::CWifiServerITCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CWifiServer(infoSockets, infoWifis, infoWifisDeconnected)
{
}
bool CWifiServerITCP::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionITCP::_Listen(master, port);
}
TDescriptor CWifiServerITCP::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionITCP::_Accept(master, cid);
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef _CWIFISERVERITCP_H_
#define _CWIFISERVERITCP_H_
#include "csocketserverfunctionitcp.h"
#include "cwifiserver.h"
class CWifiServerITCP : public CWifiServer, public CSocketServerFunctionITCP
{
public:
CWifiServerITCP();
CWifiServerITCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
private:
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#include"cwifiservervtcp.h"
CWifiServerVTCP::CWifiServerVTCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CWifiServer(infoSockets, infoWifis, infoWifisDeconnected)
{
}
bool CWifiServerVTCP::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionVTCP::_Listen(master, port);
}
TDescriptor CWifiServerVTCP::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionVTCP::_Accept(master, cid);
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CWIFISERVERVTCP_H_
#define _CWIFISERVERVTCP_H_
#include "csocketserverfunctionvtcp.h"
#include "cwifiserver.h"
class CWifiServerVTCP : public CWifiServer, public CSocketServerFunctionVTCP
{
public:
CWifiServerVTCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
private :
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
};
#endif
+107
View File
@@ -0,0 +1,107 @@
#include "cwirelessdevice.h"
#include <sys/socket.h>
#include <net/if_arp.h>
#include <cstring>
#include <regex>
const std::regex wlan("wlan[0-9]*");
WirelessDevice::WirelessDevice(){
}
WirelessDevice::~WirelessDevice(){
}
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(macaddr) {
// _machwsim.ether_addr_octet[0] |= 0x40 ;
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
}
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,const struct ether_addr & machwsim,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(machwsim) {
}
std::string WirelessDevice::getName() const {
return _name ;
}
struct ether_addr WirelessDevice::getMacaddr() const {
return _macaddr ;
}
void WirelessDevice::setMachwsim(const struct ether_addr & machwsim) {
_machwsim = machwsim ;
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
}
struct ether_addr WirelessDevice::getMachwsim() const {
return _machwsim ;
}
bool WirelessDevice::checkif_wireless_device(){
if (std::regex_match(_name,wlan))
return true ;
else
return false;
}
int WirelessDevice::getIndex() const {
return _index ;
}
int WirelessDevice::getTxPower() const {
return _txpower ;
}
// friend functions
std::ostream & operator<< ( std::ostream & os , const WirelessDevice & wdevice ){
char macstring[18];
char machwsimstring[18];
sprintf(macstring, "%02X:%02X:%02X:%02X:%02X:%02X",
wdevice._macaddr.ether_addr_octet[0], wdevice._macaddr.ether_addr_octet[1], wdevice._macaddr.ether_addr_octet[2],
wdevice._macaddr.ether_addr_octet[3], wdevice._macaddr.ether_addr_octet[4], wdevice._macaddr.ether_addr_octet[5]);
sprintf(machwsimstring, "%02X:%02X:%02X:%02X:%02X:%02X",
wdevice._machwsim.ether_addr_octet[0], wdevice._machwsim.ether_addr_octet[1], wdevice._machwsim.ether_addr_octet[2],
wdevice._machwsim.ether_addr_octet[3], wdevice._machwsim.ether_addr_octet[4], wdevice._machwsim.ether_addr_octet[5]);
os << "name: " << wdevice._name << std::endl ;
os << "index: " << wdevice._index << std::endl ;
/* ARPHRD_ETHER normal, ARPHRD_IEEE80211_RADIOTAP as monitor */
if (wdevice._iftype == ARPHRD_ETHER)
os << "iftype: ARPHRD_ETHER" << std::endl ;
else if (wdevice._iftype == ARPHRD_IEEE80211_RADIOTAP)
os << "iftype: ARPHRD_IEEE80211_RADIOTAP" << std::endl;
else
os << "iftype: UNKNOWN" << std::endl;
os << "mac:" << macstring << std::endl ;
os << "mac hwsim:" << machwsimstring << std::endl ;
os << "Tx-Power : " << wdevice._txpower / 100 << "." << wdevice._txpower % 100 << "dBm" << std::endl ;
return os ;
}
+60
View File
@@ -0,0 +1,60 @@
#ifndef _WIRELESSDEVICE_H
#define _WIRELESSDEVICE_H
#include <net/ethernet.h>
#include <string>
#include <iostream>
class WirelessDevice {
std::string _name;
int _index;
int _iftype;
//unsigned char _macaddr[ETH_ALEN];
int _txpower ;
struct ether_addr _macaddr ;
struct ether_addr _machwsim = {0x00,0X00,0x00,0X00,0x00,0X00};
public:
WirelessDevice();
~WirelessDevice();
/**
* \fn WirelessDevice(std::string n,int i,int t,const struct ether_addr & m,const struct ether_addr & h);
* \biref Constructor
* \param n - interface name
* i - index
* t - type
* m - wireless net device mac address
* h - wireless net device mac address in hwsim driver
*/
WirelessDevice(const std::string &,int,int,const struct ether_addr &,const struct ether_addr &,int);
/**
* \fn WirelessDevice(std::string n,int i,int t,const struct ether_addr & m);
* \biref Constructor
* \param n - interface name
* i - index
* t - type
* m - wireless net device mac address
*/
WirelessDevice(const std::string &,int,int,const struct ether_addr &,int);
friend std::ostream & operator<< ( std::ostream & , const WirelessDevice &);
struct ether_addr getMacaddr() const ;
struct ether_addr getMachwsim() const ;
void setMachwsim(const struct ether_addr &);
std::string getName() const ;
bool checkif_wireless_device();
int getIndex() const ;
int getTxPower() const ;
};
#endif
+102
View File
@@ -0,0 +1,102 @@
/**
* \file cwirelessdevicelist.cc
* \brief manage std::list of WirelessDevice objects
* \author
* \version
*/
#include "cwirelessdevicelist.h"
#include <cstring>
#include <algorithm> // std::transform
WirelessDeviceList::WirelessDeviceList(){
}
WirelessDeviceList::~WirelessDeviceList(){
}
bool WirelessDeviceList::get_device_by_mac(WirelessDevice & wdev , struct ether_addr macaddr) {
_listaccess.lock();
for (auto & wd : _wdevices_list){
struct ether_addr mac = wd.second.getMacaddr() ;
if(std::memcmp(&mac,&macaddr,ETH_ALEN) == 0){
wdev = wd.second ;
_listaccess.unlock();
return true ;
}
}
_listaccess.unlock();
return false ;
}
void WirelessDeviceList::add_device(const WirelessDevice & wdevice){
_listaccess.lock();
_wdevices_list[wdevice.getIndex()] = wdevice ;
_listaccess.unlock();
}
void WirelessDeviceList::delete_device(const WirelessDevice & wdevice){
_listaccess.lock();
_wdevices_list.erase(wdevice.getIndex()) ;
_listaccess.unlock();
}
void WirelessDeviceList::delete_device(int index){
_listaccess.lock();
_wdevices_list.erase(index);
_listaccess.unlock();
}
std::vector<WirelessDevice> & WirelessDeviceList::list_devices() {
std::vector<WirelessDevice> * list_wd = new std::vector<WirelessDevice>();
list_wd->reserve(_wdevices_list.size());
_listaccess.lock();
std::transform (_wdevices_list.begin(),
_wdevices_list.end(),
back_inserter(*list_wd),
[] (std::pair<int, WirelessDevice> const & pair)
{
return pair.second;
}
);
_listaccess.unlock();
return *(list_wd) ;
}
/** friend functions */
std::ostream & operator<< ( std::ostream & os , WirelessDeviceList & wdlist ){
wdlist._listaccess.lock();
for (const auto & wd : wdlist._wdevices_list){
os << wd.second;
os << std::endl ;
}
wdlist._listaccess.unlock();
return os ;
}
+85
View File
@@ -0,0 +1,85 @@
/**
* \file cwirelessdevicelist.h
* \brief manage std::list of WirelessDevice objects
* \author
* \version
*/
#ifndef _CWIRELESSDEVICELIST_H_
#define _CWIRELESSDEVICELIST_H_
#include <map>
#include <mutex>
#include <vector>
#include "cwirelessdevice.h"
/**
* \class WirelessDeviceList
* \brief This class represents a std::list of WirelessDevice objects
*/
class WirelessDeviceList {
/**
* \brief manage threads access to wdevices_list
*/
std::mutex _listaccess ;
/**
* \brief list of existing wireless network interfaces
*/
std::map<int,WirelessDevice> _wdevices_list;
public:
WirelessDeviceList();
~WirelessDeviceList();
/**
* \fn add_device(int)
* \brief Add to _wdevices_list a wireless network device
* \param wdevice Wireless network device
* \return void
*/
void add_device(const WirelessDevice & wdevice);
/**
* \fn delete_device(int)
* \brief Remove from _wdevice_list a wireless network device by index
* \param index Ifindex of wireless network device
* \return void
*/
void delete_device(int index);
/**
* \fn delete_device(const WirelessDevice & wdevice)
* \brief Remove from _wdevice_list a wireless network device by index
* \param wdevice wireless network device to remove from _wdevices_list
* \return void
*/
void delete_device(const WirelessDevice & wdevice);
/**
* \fn list_devices()
* \brief Get a list of all wireless network devices
* \return std::vector List of all devices
*/
std::vector<WirelessDevice> & list_devices() ;
/**
* \fn get_device_by_mac(struct ether_addr macaddr)
* \brief Get a device related to mac address
* \param wdev : WirelessDevice to find
* \param macaddr : mac address to find
* \return true if found and false otherwise
*/
bool get_device_by_mac(WirelessDevice & wdev , struct ether_addr macaddr);
/**
* \brief << operator overidden
*/
friend std::ostream & operator<< ( std::ostream & , WirelessDeviceList &);
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef _HWSIM_H_
#define _HWSIM_H_
#include "types.h"
#define __packed __attribute__((packed))
#define BIT(x) (1 << (x))
#include "mac80211_hwsim.h"
#define VERSION_NR 1
#endif /* _HWSIM_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef IEEE80211_H_
#define IEEE80211_H_
// From Kernel : include/net/mac80211.h
#define IEEE80211_TX_MAX_RATES 4
#endif /* IEEE80211_H_ */
+344
View File
@@ -0,0 +1,344 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
* Copyright (C) 2020, 2022-2024 Intel Corporation
*/
#ifndef __MAC80211_HWSIM_H
#define __MAC80211_HWSIM_H
/**
* enum hwsim_tx_control_flags - flags to describe transmission info/status
*
* These flags are used to give the wmediumd extra information in order to
* modify its behavior for each frame
*
* @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
* @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack
* @HWSIM_TX_STAT_ACK: Frame was acknowledged
*
*/
enum hwsim_tx_control_flags {
HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
HWSIM_TX_CTL_NO_ACK = BIT(1),
HWSIM_TX_STAT_ACK = BIT(2),
};
/**
* DOC: Frame transmission/registration support
*
* Frame transmission and registration support exists to allow userspace
* entities such as wmediumd to receive and process all broadcasted
* frames from a mac80211_hwsim radio device.
*
* This allow user space applications to decide if the frame should be
* dropped or not and implement a wireless medium simulator at user space.
*
* Registration is done by sending a register message to the driver and
* will be automatically unregistered if the user application doesn't
* responds to sent frames.
* Once registered the user application has to take responsibility of
* broadcasting the frames to all listening mac80211_hwsim radio
* interfaces.
*
* For more technical details, see the corresponding command descriptions
* below.
*/
/**
* enum hwsim_commands - supported hwsim commands
*
* @HWSIM_CMD_UNSPEC: unspecified command to catch errors
*
* @HWSIM_CMD_REGISTER: request to register and received all broadcasted
* frames by any mac80211_hwsim radio device.
* @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
* space, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
* %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
* %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional)
* @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
* kernel, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
* %HWSIM_ATTR_TX_INFO, %WSIM_ATTR_TX_INFO_FLAGS,
* %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
* @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters,
* returns the radio ID (>= 0) or negative on errors, if successful
* then multicast the result, uses optional parameter:
* %HWSIM_ATTR_REG_STRICT_REG, %HWSIM_ATTR_SUPPORT_P2P_DEVICE,
* %HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, %HWSIM_ATTR_CHANNELS,
* %HWSIM_ATTR_NO_VIF, %HWSIM_ATTR_RADIO_NAME, %HWSIM_ATTR_USE_CHANCTX,
* %HWSIM_ATTR_REG_HINT_ALPHA2, %HWSIM_ATTR_REG_CUSTOM_REG,
* %HWSIM_ATTR_PERM_ADDR
* @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
* @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
* %HWSIM_ATTR_RADIO_ID
* @HWSIM_CMD_ADD_MAC_ADDR: add a receive MAC address (given in the
* %HWSIM_ATTR_ADDR_RECEIVER attribute) to a device identified by
* %HWSIM_ATTR_ADDR_TRANSMITTER. This lets wmediumd forward frames
* to this receiver address for a given station.
* @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes
* are the same as to @HWSIM_CMD_ADD_MAC_ADDR.
* @HWSIM_CMD_START_PMSR: request to start peer measurement with the
* %HWSIM_ATTR_PMSR_REQUEST. Result will be sent back asynchronously
* with %HWSIM_CMD_REPORT_PMSR.
* @HWSIM_CMD_ABORT_PMSR: Abort previously started peer measurement.
* @HWSIM_CMD_REPORT_PMSR: Report peer measurement data.
* @__HWSIM_CMD_MAX: enum limit
*/
enum hwsim_commands {
HWSIM_CMD_UNSPEC,
HWSIM_CMD_REGISTER,
HWSIM_CMD_FRAME,
HWSIM_CMD_TX_INFO_FRAME,
HWSIM_CMD_NEW_RADIO,
HWSIM_CMD_DEL_RADIO,
HWSIM_CMD_GET_RADIO,
HWSIM_CMD_ADD_MAC_ADDR,
HWSIM_CMD_DEL_MAC_ADDR,
HWSIM_CMD_START_PMSR,
HWSIM_CMD_ABORT_PMSR,
HWSIM_CMD_REPORT_PMSR,
__HWSIM_CMD_MAX,
};
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
#define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO
#define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO
/**
* enum hwsim_attrs - hwsim netlink attributes
*
* @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
*
* @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
* the frame is broadcasted to
* @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
* the frame was broadcasted from
* @HWSIM_ATTR_FRAME: Data array
* @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
* properly the frame at user space
* @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
* space
* @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
* space
* @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
* @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
* @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO
* command giving the number of channels supported by the new radio
* @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO
* only to destroy a radio
* @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint
* (nla string, length 2)
* @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute)
* @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute)
* @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag)
* @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO
* command to force use of channel contexts even when only a
* single channel is supported
* @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO
* command to force radio removal when process that created the radio dies
* @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666
* @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio.
* @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore
* @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received.
* @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding
* rates of %HWSIM_ATTR_TX_INFO
* @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
* @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface types bits
* @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types
* @HWSIM_ATTR_MLO_SUPPORT: claim MLO support (exact parameters TBD) for
* the new radio
* @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO
* to provide peer measurement capabilities. (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR
* to provide details about peer measurement request (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR
* to provide peer measurement result (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag).
* Adds one radio for each band. Number of supported channels will be set for
* each radio instead of for the wiphy.
* @__HWSIM_ATTR_MAX: enum limit
*/
enum hwsim_attrs {
HWSIM_ATTR_UNSPEC,
HWSIM_ATTR_ADDR_RECEIVER,
HWSIM_ATTR_ADDR_TRANSMITTER,
HWSIM_ATTR_FRAME,
HWSIM_ATTR_FLAGS,
HWSIM_ATTR_RX_RATE,
HWSIM_ATTR_SIGNAL,
HWSIM_ATTR_TX_INFO,
HWSIM_ATTR_COOKIE,
HWSIM_ATTR_CHANNELS,
HWSIM_ATTR_RADIO_ID,
HWSIM_ATTR_REG_HINT_ALPHA2,
HWSIM_ATTR_REG_CUSTOM_REG,
HWSIM_ATTR_REG_STRICT_REG,
HWSIM_ATTR_SUPPORT_P2P_DEVICE,
HWSIM_ATTR_USE_CHANCTX,
HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
HWSIM_ATTR_RADIO_NAME,
HWSIM_ATTR_NO_VIF,
HWSIM_ATTR_FREQ,
HWSIM_ATTR_PAD,
HWSIM_ATTR_TX_INFO_FLAGS,
HWSIM_ATTR_PERM_ADDR,
HWSIM_ATTR_IFTYPE_SUPPORT,
HWSIM_ATTR_CIPHER_SUPPORT,
HWSIM_ATTR_MLO_SUPPORT,
HWSIM_ATTR_PMSR_SUPPORT,
HWSIM_ATTR_PMSR_REQUEST,
HWSIM_ATTR_PMSR_RESULT,
HWSIM_ATTR_MULTI_RADIO,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
/**
* struct hwsim_tx_rate - rate selection/status
*
* @idx: rate index to attempt to send with
* @count: number of tries in this rate before going to the next rate
*
* A value of -1 for @idx indicates an invalid rate and, if used
* in an array of retry rates, that no more rates should be tried.
*
* When used for transmit status reporting, the driver should
* always report the rate and number of retries used.
*
*/
struct hwsim_tx_rate {
s8 idx;
u8 count;
} __packed;
/**
* enum hwsim_tx_rate_flags - per-rate flags set by the rate control algorithm.
* Inspired by structure mac80211_rate_control_flags. New flags may be
* appended, but old flags not deleted, to keep compatibility for
* userspace.
*
* These flags are set by the Rate control algorithm for each rate during tx,
* in the @flags member of struct ieee80211_tx_rate.
*
* @MAC80211_HWSIM_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.
* @MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.
* This is set if the current BSS requires ERP protection.
* @MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @MAC80211_HWSIM_TX_RC_MCS: HT rate.
* @MAC80211_HWSIM_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is
* split into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @MAC80211_HWSIM_TX_RC_GREEN_FIELD: Indicates whether this rate should be used
* in Greenfield mode.
* @MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be
* 40 MHz.
* @MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
* @MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
* (80+80 isn't supported yet)
* @MAC80211_HWSIM_TX_RC_DUP_DATA: The frame should be transmitted on both of
* the adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
* @MAC80211_HWSIM_TX_RC_SHORT_GI: Short Guard interval should be used for this
* rate.
*/
enum hwsim_tx_rate_flags {
MAC80211_HWSIM_TX_RC_USE_RTS_CTS = BIT(0),
MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT = BIT(1),
MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
/* rate index is an HT/VHT MCS instead of an index */
MAC80211_HWSIM_TX_RC_MCS = BIT(3),
MAC80211_HWSIM_TX_RC_GREEN_FIELD = BIT(4),
MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH = BIT(5),
MAC80211_HWSIM_TX_RC_DUP_DATA = BIT(6),
MAC80211_HWSIM_TX_RC_SHORT_GI = BIT(7),
MAC80211_HWSIM_TX_RC_VHT_MCS = BIT(8),
MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH = BIT(9),
MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH = BIT(10),
};
/**
* struct hwsim_tx_rate_flag - rate selection/status
*
* @idx: rate index to attempt to send with
* @flags: the rate flags according to &enum hwsim_tx_rate_flags
*
* A value of -1 for @idx indicates an invalid rate and, if used
* in an array of retry rates, that no more rates should be tried.
*
* When used for transmit status reporting, the driver should
* always report the rate and number of retries used.
*
*/
struct hwsim_tx_rate_flag {
s8 idx;
u16 flags;
} __packed;
/**
* DOC: Frame transmission support over virtio
*
* Frame transmission is also supported over virtio to allow communication
* with external entities.
*/
/**
* enum hwsim_vqs - queues for virtio frame transmission
*
* @HWSIM_VQ_TX: send frames to external entity
* @HWSIM_VQ_RX: receive frames and transmission info reports
* @HWSIM_NUM_VQS: enum limit
*/
enum hwsim_vqs {
HWSIM_VQ_TX,
HWSIM_VQ_RX,
HWSIM_NUM_VQS,
};
/**
* enum hwsim_rate_info_attributes - bitrate information.
*
* Information about a receiving or transmitting bitrate
* that can be mapped to struct rate_info
*
* @__HWSIM_RATE_INFO_ATTR_INVALID: reserved, netlink attribute 0 is invalid
* @HWSIM_RATE_INFO_ATTR_FLAGS: bitflag of flags from &enum rate_info_flags
* @HWSIM_RATE_INFO_ATTR_MCS: mcs index if struct describes an HT/VHT/HE rate
* @HWSIM_RATE_INFO_ATTR_LEGACY: bitrate in 100kbit/s for 802.11abg
* @HWSIM_RATE_INFO_ATTR_NSS: number of streams (VHT & HE only)
* @HWSIM_RATE_INFO_ATTR_BW: bandwidth (from &enum rate_info_bw)
* @HWSIM_RATE_INFO_ATTR_HE_GI: HE guard interval (from &enum nl80211_he_gi)
* @HWSIM_RATE_INFO_ATTR_HE_DCM: HE DCM value
* @HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC: HE RU allocation (from &enum nl80211_he_ru_alloc,
* only valid if bw is %RATE_INFO_BW_HE_RU)
* @HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH: In case of EDMG the number of bonded channels (1-4)
* @HWSIM_RATE_INFO_ATTR_EHT_GI: EHT guard interval (from &enum nl80211_eht_gi)
* @HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC: EHT RU allocation (from &enum nl80211_eht_ru_alloc,
* only valid if bw is %RATE_INFO_BW_EHT_RU)
* @NUM_HWSIM_RATE_INFO_ATTRS: internal
* @HWSIM_RATE_INFO_ATTR_MAX: highest attribute number
*/
enum hwsim_rate_info_attributes {
__HWSIM_RATE_INFO_ATTR_INVALID,
HWSIM_RATE_INFO_ATTR_FLAGS,
HWSIM_RATE_INFO_ATTR_MCS,
HWSIM_RATE_INFO_ATTR_LEGACY,
HWSIM_RATE_INFO_ATTR_NSS,
HWSIM_RATE_INFO_ATTR_BW,
HWSIM_RATE_INFO_ATTR_HE_GI,
HWSIM_RATE_INFO_ATTR_HE_DCM,
HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC,
HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH,
HWSIM_RATE_INFO_ATTR_EHT_GI,
HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC,
/* keep last */
NUM_HWSIM_RATE_INFO_ATTRS,
HWSIM_RATE_INFO_ATTR_MAX = NUM_HWSIM_RATE_INFO_ATTRS - 1
};
#endif /* __MAC80211_HWSIM_H */
+71
View File
@@ -0,0 +1,71 @@
#include <cstddef> // NULL
#include <arpa/inet.h> // struct sockaddr_in & inet_ntoa & ntohs
#include "tools.h"
#include <assert.h> // assert
bool HashUsesPort=false;
unsigned long hash_ipaddr(struct sockaddr_in* addr)
{
unsigned long res;
assert( addr != NULL );
res = (((addr->sin_addr.s_addr >> 24) & 0xff) * 256) +
(((addr->sin_addr.s_addr >> 16) & 0xff) * 256) +
(((addr->sin_addr.s_addr >> 8) & 0xff)* 256) +
(addr->sin_addr.s_addr & 0xff);
if( HashUsesPort )
res += addr->sin_port;
return res;
}
bool isInt(const char *str) {
if( *str == '-' || *str == '+' )
str++;
while (*str) {
if( *str < '0' || *str > '9' )
return false;
str++;
}
return true;
}
bool isPositiveInt(const char *str)
{
if( *str == '-' )
return false;
return isInt(str);
}
bool isIntOrFloat(const char *str) {
bool seeDot=false;
bool seeDigit=false;
if (*str == '-' || *str == '+')
str++;
while (*str) {
if( *str == '.' )
{
if( seeDot )
return false;
seeDot=true;
}
else
{
if( *str < '0' || *str > '9' )
return false;
seeDigit=true;
}
str++;
}
return seeDigit;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef _TOOLS_H_
#define _TOOLS_H_
extern bool HashUsesPort;
unsigned long hash_ipaddr(struct sockaddr_in* addr);
bool isInt(const char *str);
bool isPositiveInt(const char *str);
bool isIntOrFloat(const char *str);
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#include <stdint.h>
typedef int8_t s8;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint64_t u64;
typedef int32_t s32;
typedef uint32_t u32;
// int
typedef s32 TValue;
// unsigned int
typedef u32 TCID;
enum TOrder {
TORDER_NO, TORDER_LIST, TORDER_SHOW, TORDER_CHANGE_COORDINATE, TORDER_SETNAME, TORDER_PACKET_LOSS, TORDER_STATUS, TORDER_DISTANCE_BETWEEN_CID, TORDER_SET_SCALE, TORDER_CLOSE_ALL_CLIENT
};
// int
typedef s32 TDescriptor;
// unsigned int
typedef u32 TIndex;
// int
typedef s32 TSocket;
// AF_INET : use IP
// AF_VSOCK : use vsock
// unsigned short
typedef u16 TPort;
// char
typedef s8 TPower; // empirical observed values with int : [-123,20]
const TPower TPower_MAX=-10; // dBm is always negative. -10 is an empirical value
const TPower TPower_MIN=INT8_MIN;
// double
typedef double TDistance; // in meters
typedef double TScale;
// u32
typedef u32 TFrequency; // Hz
// unsigned short
typedef u16 TMinimalSize;
typedef u8 TByte;
#endif
+107
View File
@@ -0,0 +1,107 @@
/*
From : https://android.googlesource.com/device/generic/goldfish/+/refs/heads/master/wifi/mac80211_create_radios/main.cpp
Licence http://www.apache.org/licenses/LICENSE-2.0
*/
#include <memory>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <netlink/netlink.h>
#include <net/ethernet.h>
#include <climits>
#include <stdio.h>
#include <unistd.h> // getuid
#include "config_hwsim.h"
#include "addinterfaces.h"
#include "config.h" // DEFAULT_MAC_PREFIX
int ParseInt(const char* str, int* result)
{
return sscanf(str, "%d", result);
}
int help(FILE* dst, const int ret)
{
fprintf(dst, "%s",
"Usage:\n"
" vwifi-add-interfaces [-h] [-v] n_radios mac_prefix\n"
" vwifi-add-interfaces [--help] [--version] n_radios mac_prefix\n"
" where\n"
" n_radios - int, [1,100], e.g. 2\n"
" mac_prefix - xx:xx:xx:xx:xx (if n_radios > 1 then only the first 5 bytes are used\n"
" then all bytes are used)\n\n"
" vwifi-add-interfaces will create n_radios with MAC addresses xx:xx:xx:xx:xx:nn\n"
" where xx:xx:xx:xx:xx is the mac_prefix specified\n"
" and nn is incremented (from zero, and only if n_radios > 1)\n");
return ret;
}
int main(int argc, char* argv[])
{
int nRadios;
TByte macPrefix[ETH_ALEN]= {};
if( argc == 1 )
return help(stdout,0);
if( ! ParseAddress(DEFAULT_MAC_PREFIX,macPrefix) )
return help(stderr, 6);
if( strlen(DEFAULT_MAC_PREFIX) <= 8 )
{ // if possible, randomize the 4th byte
srand(time(NULL));
macPrefix[3]=rand()%100;
}
int arg_idx = 1;
int arg_used = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
fprintf(stdout,"Version : %s\n",VERSION);
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
return help(stdout,0);
}
if( argv[arg_idx][0] == '-' )
{
fprintf(stderr,"Error : unknown parameter : %s\n",argv[arg_idx]);
return help(stderr, 1);
}
switch ( arg_used )
{
case 1 :
if (!ParseInt(argv[arg_idx], &nRadios))
return help(stderr, 2);
if (nRadios < 1)
return help(stderr, 3);
if (nRadios > 100)
return help(stderr, 4);
arg_used++;
break;
case 2 :
if( strlen(argv[arg_idx]) > 17 )
return help(stderr, 5);
if( ! ParseAddress(argv[arg_idx],macPrefix) )
return help(stderr, 6);
arg_used++;
break;
}
arg_idx++;
}
if( getuid() )
{
fprintf(stderr,"Error : This program must be run as root!!\n");
return 2;
}
return ManageRadios(nRadios, macPrefix);
}
+223
View File
@@ -0,0 +1,223 @@
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <string.h> // strcmp
#include <memory>
#include "config.h" // DEFAULT_WIFI_CLIENT_PORT_VHOST / DEFAULT_WIFI_CLIENT_PORT_INET
#include "tools.h" // isInt
#include "cwificlient.h"
#ifdef ENABLE_VHOST
#include "csocketclientvtcp.h"
#endif
#include "csocketclientitcp.h"
#include "addinterfaces.h"
enum STATE {
STARTED=1,
STOPPED ,
SUSPENDED
};
CKernelWifi* wifiClient;
enum STATE _state = STOPPED ;
void signal_handler(int signal_num)
{
switch(signal_num)
{
case SIGINT :
case SIGTERM :
case SIGQUIT :
std::cout << signal_num << std::endl ;
wifiClient->stop() ;
_state = STOPPED ;
break ;
case SIGTSTP:
std::cout << "This signal is ignored" << std::endl ;
break ;
default :
std::cerr << "Signal not handled" << std::endl ;
}
std::cout << "OUT SWITCH" << std::endl ;
}
void help()
{
#ifdef ENABLE_VHOST
std::cout<<"Usage: vwifi-client [-h] [-v] [-s] [IP_ADDR] [-p PORT] [-u] [-n NUMBER_INTERFACE] [-m MAC_PREFIX]"<<std::endl;
std::cout<<" [--help] [--version] [--spy] [IP_ADDR] [--port PORT] [--use-port-in-hash] [--number NUMBER_INTERFACE] [--mac MAC_PREFIX]"<<std::endl;
std::cout<<" By default : client mode : TCP : IP_ADDR="<<DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_CLIENT_PORT_INET << std::endl;
std::cout<<" client mode : VHOST : PORT="<< DEFAULT_WIFI_CLIENT_PORT_VHOST << std::endl;
std::cout<<" spy mode (--spy) : IP_ADDR="<< DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_SPY_PORT << std::endl;
std::cout<<" NUMBER_INTERFACE="<< DEFAULT_NUMBER_WLAN_INTERFACE <<" MAC_PREFIX="<< DEFAULT_MAC_PREFIX << std::endl;
#else
std::cout<<"Usage: vwifi-client [-h] [-v] [-s] IP_ADDR [-p PORT] [-u] [-n NUMBER_INTERFACE] [-m MAC_PREFIX]"<<std::endl;
std::cout<<" [--help] [--version] [--spy] IP_ADDR [--port PORT] [--use-port-in-hash] [--number NUMBER_INTERFACE] [--mac MAC_PREFIX]"<<std::endl;
std::cout<<" By default : client mode : TCP : IP_ADDR="<<DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_CLIENT_PORT_INET << std::endl;
std::cout<<" spy mode (--spy) : IP_ADDR="<< DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_SPY_PORT << std::endl;
std::cout<<" NUMBER_INTERFACE="<< DEFAULT_NUMBER_WLAN_INTERFACE <<" MAC_PREFIX="<< DEFAULT_MAC_PREFIX << std::endl;
#endif
}
int main (int argc , char ** argv){
bool spy = false;
std::string ip_addr;
TPort port_number = 0;
int number_interface=DEFAULT_NUMBER_WLAN_INTERFACE;
TByte mac_prefix[ETH_ALEN]={};
ParseAddress(DEFAULT_MAC_PREFIX, mac_prefix);
if( strlen(DEFAULT_MAC_PREFIX) <= 8 )
{ // if possible, randomize the 4th byte
srand(time(NULL));
mac_prefix[3]=rand()%100;
}
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
std::cout<<"Version : "<<VERSION<<std::endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
help();
return 0;
}
if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
port_number = std::stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ! strcmp("-u", argv[arg_idx]) || ! strcmp("--use-port-in-hash", argv[arg_idx]) )
{
HashUsesPort=true;
}
else if( ! strcmp("-s", argv[arg_idx]) || ! strcmp("--spy", argv[arg_idx]) )
{
spy=true;
}
else if( ( ! strcmp("-n", argv[arg_idx]) || ! strcmp("--number", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
number_interface = std::stoi(argv[arg_idx+1]);
if (number_interface > 100)
{
std::cerr<<"Error : NUMBER > 100"<<std::endl;
return 4;
}
arg_idx++;
}
else if( ( ! strcmp("-m", argv[arg_idx]) || ! strcmp("--mac", argv[arg_idx]) ) && (arg_idx + 1) < argc)
{
std::string string = std::string(argv[arg_idx+1]);
if( string.size() > 17 )
{
std::cerr<<"Error : the MAC_PREFIX is too long"<<std::endl;
return 5;
}
if( ! ParseAddress(string.c_str(), mac_prefix) )
return 6;
arg_idx++;
}
else
{
if( ip_addr.empty() )
ip_addr = std::string(argv[arg_idx]);
else
{
std::cerr<<"Error : problem with this parameter : "<< argv[arg_idx] <<std::endl;
help();
return 1;
}
}
arg_idx++;
}
if( getuid() )
{
std::cerr<<"Error : This program must be run as root!!"<<std::endl;
return 2;
}
if( number_interface )
if( ManageRadios(number_interface,mac_prefix) )
return 7;
/* Handle signals */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, signal_handler);
//signal(SIGCONT, signal_handler);
if( spy )
{ // mode TCP
if( ip_addr.empty() )
ip_addr = std::string(DEFAULT_ADDRESS_IP);
if( ! port_number )
port_number = DEFAULT_WIFI_SPY_PORT;
std::cout<<"Type : AF_INET"<<std::endl;
wifiClient=new CWifiClient<CSocketClientITCP>;
static_cast<CWifiClient<CSocketClientITCP>*>(wifiClient)->Init(ip_addr.c_str(), port_number);
}
else
{
if( ip_addr.empty() )
{ // IP not set -> mode VHOST
#ifdef ENABLE_VHOST
if( ! port_number )
port_number = DEFAULT_WIFI_CLIENT_PORT_VHOST;
std::cout<<"Type : AF_VSOCK"<<std::endl;
wifiClient=new CWifiClient<CSocketClientVTCP>;
static_cast<CWifiClient<CSocketClientVTCP>*>(wifiClient)->Init(port_number);
#else
std::cerr<<"Error : This program is not build with VHOST!!"<<std::endl;
return 8;
#endif
}
else
{ // mode TCP
if( ! port_number )
port_number = DEFAULT_WIFI_CLIENT_PORT_INET;
std::cout<<"Type : AF_INET"<<std::endl;
wifiClient=new CWifiClient<CSocketClientITCP>;
static_cast<CWifiClient<CSocketClientITCP>*>(wifiClient)->Init(ip_addr.c_str(), port_number);
}
}
if(!wifiClient->start())
std::cout << "Starting process aborted" << std::endl ;
std::cout << "Good Bye (:-)" << std::endl ;
_exit(EXIT_SUCCESS);
}
+807
View File
@@ -0,0 +1,807 @@
#include <iostream> // cout
#include <string.h> //strlen
#include "config.h"
#include "tools.h" // isInt isPositiveInt isIntOrFloat
#include "csocketclientitcp.h"
#include "types.h"
#include "ccoordinate.h" // CCoordinate
#include "cinfowifi.h"
using namespace std;
std::string IP_Ctrl = std::string(DEFAULT_ADDRESS_IP);
TPort Port_Ctrl = DEFAULT_CTRL_PORT;
char* NameOfProg;
void Help()
{
cout<<NameOfProg<<" [order]"<<endl;
cout<<" with [order] :"<<endl;
cout<<" ls"<<endl;
cout<<" - List the Clients"<<endl;
cout<<" set CID X Y Z"<<endl;
cout<<" - Change the coordinate of the Client with CID"<<endl;
cout<<" setname CID NAME"<<endl;
cout<<" - Set the NAME of the Client with CID"<<endl;
cout<<" loss yes/no"<<endl;
cout<<" - loss yes : packets can be lost"<<endl;
cout<<" - loss no : no packets can be lost"<<endl;
cout<<" show"<<endl;
cout<<" - Display the status of loss and list of Clients"<<endl;
cout<<" status"<<endl;
cout<<" - Display the status of the configuration of vwifi-server"<<endl;
cout<<" distance CID1 CID2"<<endl;
cout<<" - Display the distance in meters between the Client with CID1 and the Client with CID2"<<endl;
cout<<" scale VALUE"<<endl;
cout<<" - Set the scale of the distances between the clients to VALUE"<<endl;
cout<<" - VALUE can be a decimal number"<<endl;
cout<<" close"<<endl;
cout<<" - Close all the connections with Wifi Clients"<<endl;
cout<<endl;
cout<<" [-p PORT] or [--port PORT] : Set the port used by the vwifi-server (by default PORT="<< Port_Ctrl <<")"<<endl;
cout<<" [-i IP] or [--ip IP] : Set the IP used by the vwifi-server (by default IP="<< IP_Ctrl <<")"<<endl;
cout<<" [-v] or [--version] : Display the version of "<<NameOfProg<<endl;
cout<<" [-h] or [--help] : this help"<<endl;
}
int GetCInfoWifi(CSocketClientITCP & socket, CInfoWifi* infoWifi)
{
int err;
TCID cid;
err=socket.Read(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : cid"<<endl;
return 1;
}
CCoordinate coo;
err=socket.Read(reinterpret_cast<char*>(&coo),sizeof(coo));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : CCoordinate (cid:"<<cid<<")"<<endl;
return 1;
}
int sizeName;
err=socket.Read(reinterpret_cast<char*>(&sizeName),sizeof(sizeName));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : size of name (cid:"<<cid<<")"<<endl;
return 1;
}
if( sizeName > MAX_SIZE_NAME )
{
cerr<<"Error : GetCInfoWifi : size of name > "<<MAX_SIZE_NAME<<" (cid:"<<cid<<")"<<endl;
return 1;
}
char strName[MAX_SIZE_NAME+1]; // +1 : \0
if( sizeName > 0 )
{
err=socket.Read(reinterpret_cast<char*>(strName),sizeName+1); // +1 : \0
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : size of name (cid:"<<cid<<")"<<endl;
return 1;
}
}
else
strName[0]='\0';
infoWifi->SetCid(cid);
infoWifi->Set(coo);
string name(strName);
infoWifi->SetName(name);
return 0;
}
int AskList()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : ls : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_LIST;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Send : order"<<endl;
return 1;
}
// Spies :
TIndex number;
err=socket.Read(reinterpret_cast<char*>(&number),sizeof(number));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : number"<<endl;
return 1;
}
CInfoWifi info;
for(TIndex i=0; i<number;i++)
{
err=GetCInfoWifi(socket,&info);
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : CInfoWifi"<<endl;
return 1;
}
cout<<"S:"<<info.GetCid();
if( info.HasName() )
cout<<" ("<<info.GetName()<<")";
cout<<endl;
}
// Clients :
err=socket.Read(reinterpret_cast<char*>(&number),sizeof(number));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : number"<<endl;
return 1;
}
for(TIndex i=0; i<number;i++)
{
err=GetCInfoWifi(socket,&info);
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : CInfoWifi"<<endl;
return 1;
}
cout<<info<<endl;
}
socket.Close();
return 0;
}
int ChangeCoordinate(int argc, char *argv[])
{
if( argc != 5 )
{
cerr<<"Error : set : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : set : the CID is not an integer"<<endl;
return 1;
}
TCID cid=atoi(argv[1]);
if( cid < TCID_GUEST_MIN )
{
cerr<<"Error : set : the CID must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
if( ! isInt(argv[2]) )
{
cerr<<"Error : set : the x coordinate is not an integer"<<endl;
return 1;
}
if( ! isInt(argv[3]) )
{
cerr<<"Error : set : the y coordinate is not an integer"<<endl;
return 1;
}
if( ! isInt(argv[4]) )
{
cerr<<"Error : set : the z coordinate is not an integer"<<endl;
return 1;
}
TValue x=atoi(argv[2]);
TValue y=atoi(argv[3]);
TValue z=atoi(argv[4]);
CCoordinate coo(x,y,z);
cout<<cid<<" "<<coo<<" "<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : set : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_CHANGE_COORDINATE;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : cid"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&coo),sizeof(coo));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : "<<coo<<endl;
return 1;
}
socket.Close();
return 0;
}
int SetName(int argc, char *argv[])
{
if( argc != 3 )
{
cerr<<"Error : setname : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : setname : the CID is not an integer"<<endl;
return 1;
}
TCID cid=atoi(argv[1]);
if( cid < TCID_GUEST_MIN )
{
cerr<<"Error : setname : the CID must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
string name(argv[2]);
int sizeName=name.size();
if( name.length() > MAX_SIZE_NAME )
{
name.resize(MAX_SIZE_NAME);
sizeName=MAX_SIZE_NAME;
}
cout<<cid<<" "<<name<<" "<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : setname : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SETNAME;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : cid"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&sizeName),sizeof(sizeName));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : size of name"<<endl;
return 1;
}
err=socket.Send(const_cast<char*>(name.c_str()),sizeName+1); // +1 : \0
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : name"<<name<<endl;
return 1;
}
socket.Close();
return 0;
}
int ChangePacketLoss(int argc, char *argv[])
{
if( argc != 2 )
{
cerr<<"Error : loss : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
int value;
if ( ! strcmp(argv[1],"yes") )
value=1;
else if ( ! strcmp(argv[1],"no") )
value=0;
else
{
cerr<<"Error : loss : the value can only be \"yes\" or \"no\""<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : loss : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_PACKET_LOSS;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : loss : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&value),sizeof(value));
if( err == SOCKET_ERROR )
{
if ( value )
cerr<<"Error : loss : socket.Send : yes"<<endl;
else
cerr<<"Error : loss : socket.Send : no"<<endl;
return 1;
}
socket.Close();
return 0;
}
int AskStatus()
{
cout<<"CTRL : IP : "<<IP_Ctrl.c_str()<<endl;
cout<<"CTRL : Port : "<<Port_Ctrl<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : status : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_STATUS;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Send : Order"<<endl;
return 1;
}
bool loss;
err=socket.Read(reinterpret_cast<char*>(&loss),sizeof(loss));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Loss"<<endl;
return 1;
}
cout<<"SRV : PacketLoss : ";
if ( loss )
cout<<"Enable"<<endl;
else
cout<<"Disable"<<endl;
TScale scale;
err=socket.Read(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : scale"<<endl;
return 1;
}
cout<<"SRV : Scale : "<<scale<<endl;
// VHOST
TPort port;
err=socket.Read(reinterpret_cast<char*>(&port),sizeof(port));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Port VHOST"<<endl;
return 1;
}
cout<<"SRV VHOST : Port : "<<port<<endl;
// INET
err=socket.Read(reinterpret_cast<char*>(&port),sizeof(port));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Port INET"<<endl;
return 1;
}
cout<<"SRV INET : Port : "<<port<<endl;
// SizeOfDisconnected
// becareful : the same List is shared by WifiServerVTCP and WifiServerITCP
TIndex size;
err=socket.Read(reinterpret_cast<char*>(&size),sizeof(size));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Size INET"<<endl;
return 1;
}
cout<<"SRV : SizeOfDisconnected : "<<size<<endl;
// SPY
bool spyIsConnected;
err=socket.Read(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : spyIsConnected"<<endl;
return 1;
}
cout<<"SPY : ";
if ( spyIsConnected )
cout<<"Connected"<<endl;
else
cout<<"Disconnected"<<endl;
socket.Close();
return 0;
}
int AskShow()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : show : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SHOW;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Send : Order"<<endl;
return 1;
}
bool loss;
err=socket.Read(reinterpret_cast<char*>(&loss),sizeof(loss));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : Loss"<<endl;
return 1;
}
cout<<"PacketLoss : ";
if ( loss )
cout<<"Enable"<<endl;
else
cout<<"Disable"<<endl;
TScale scale;
err=socket.Read(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : scale"<<endl;
return 1;
}
cout<<"Scale : "<<scale<<endl;
bool spyIsConnected;
err=socket.Read(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : spyIsConnected"<<endl;
return 1;
}
cout<<"Spy : ";
if ( spyIsConnected )
cout<<"Connected"<<endl;
else
cout<<"Disconnected"<<endl;
socket.Close();
cout<<"----------------"<<endl;
return AskList();
}
int DistanceBetweenCID(int argc, char *argv[])
{
if( argc != 3 )
{
cerr<<"Error : distance : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : distance : the CID 1 is not an integer"<<endl;
return 1;
}
TCID cid1=atoi(argv[1]);
if( cid1 < TCID_GUEST_MIN )
{
cerr<<"Error : distance : the CID 1 must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
if( ! isPositiveInt(argv[2]) )
{
cerr<<"Error : distance : the CID 2 is not an integer"<<endl;
return 1;
}
TCID cid2=atoi(argv[2]);
if( cid2 < TCID_GUEST_MIN )
{
cerr<<"Error : distance : the CID2 must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : distance : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_DISTANCE_BETWEEN_CID;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid1),sizeof(cid1));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : cid 1"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid2),sizeof(cid2));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : cid 2"<<endl;
return 1;
}
int codeError;
err=socket.Read(reinterpret_cast<char*>(&codeError),sizeof(codeError));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Read : codeError"<<endl;
return 1;
}
if ( codeError == -1 )
{
cerr<<"Error : distance : unknown cid 1 : "<<cid1<<endl;
return 1;
}
if ( codeError == -2 )
{
cerr<<"Error : distance : unknown cid 2 : "<<cid2<<endl;
return 1;
}
TDistance distance;
err=socket.Read(reinterpret_cast<char*>(&distance),sizeof(distance));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Read : distance"<<endl;
return 1;
}
cout<<distance<<endl;
socket.Close();
return 0;
}
int SetScale(int argc, char *argv[])
{
if( argc != 2)
{
cerr<<"Error : scale : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isIntOrFloat(argv[1]) )
{
cerr<<"Error : scale : the format of the value is uncorrect"<<endl;
return 1;
}
TScale scale=atof(argv[1]);
if( scale <= 0 )
{
cerr<<"Error : scale : the value must be greater than 0"<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : scale : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SET_SCALE;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : scale : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : scale : socket.Send : scale"<<endl;
return 1;
}
socket.Close();
return 0;
}
int CloseAllClient()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : close : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_CLOSE_ALL_CLIENT;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : close : socket.Send : order"<<endl;
return 1;
}
socket.Close();
return 0;
}
int main(int argc , char *argv[])
{
char** param_cmd = new char*[argc];
int nbr_param_cmd=0;
NameOfProg=argv[0];
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
std::cout<<"Version : "<<VERSION<<std::endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
Help();
return 1;
}
if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Ctrl = std::stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-i", argv[arg_idx]) || ! strcmp("--ip", argv[arg_idx]) ) && (arg_idx + 1) < argc)
{
IP_Ctrl = std::string(argv[arg_idx+1]);
arg_idx++;
}
else
{
param_cmd[nbr_param_cmd++]=argv[arg_idx];
}
arg_idx++;
}
if( nbr_param_cmd == 0 )
{
Help();
return 0;
}
if( ! strcasecmp(param_cmd[0],"ls") )
return AskList();
if( ! strcasecmp(param_cmd[0],"set") )
return ChangeCoordinate(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"setname") )
return SetName(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"loss") )
return ChangePacketLoss(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"show") )
return AskShow();
if( ! strcasecmp(param_cmd[0],"status") )
return AskStatus();
if( ! strcasecmp(param_cmd[0],"distance") )
return DistanceBetweenCID(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"scale") )
return SetScale(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"close") )
return CloseAllClient();
cerr<<NameOfProg<<" : Error : unknown order : "<<param_cmd[0]<<endl;
return 1;
}
+54
View File
@@ -0,0 +1,54 @@
#include "cwirelessdevice.h"
#include "cmonwirelessdevice.h"
#include <iostream>
#include <unistd.h>
#include <signal.h>
MonitorWirelessDevice monitor ;
void signal_handler([[maybe_unused]] int signal_num)
{
std::cout << __func__ << std::endl ;
monitor.stop();
}
int main (){
/* Handle signals */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGHUP, SIG_IGN);
/* struct ether_addr mac { 0xff, 0x00, 0x00,0x00, 0xfe, 0x00 };
struct ether_addr mac3 { 0xaa, 0xbb, 0x00,0x00, 0xfe, 0x00 };
WirelessDevice wdevice("wlan0",4,5,mac);
std::cout << wdevice << std::endl ;
WirelessDevice wdevice2 ;
wdevice2 = wdevice;
wdevice.setMacaddr(mac3);
std::cout << wdevice2 << std::endl ;
std::cout << wdevice << std::endl ;
*/
monitor.start();
pause();
std::cout << "end" << std::endl ;
return 0 ;
}
+309
View File
@@ -0,0 +1,309 @@
#include <iostream> // cout
#include <string.h> // strcmp
#include "config.h"
#include "tools.h" // isPositiveInt
#include "cwifiserveritcp.h"
#ifdef ENABLE_VHOST
#include "cwifiservervtcp.h"
#endif
#include "cctrlserver.h"
#include "cselect.h"
#include "cdynbuffer.h"
using namespace std;
CDynBuffer Buffer; // Buffer to stock received values
#ifdef ENABLE_VHOST
TPort Port_VHOST = DEFAULT_WIFI_CLIENT_PORT_VHOST;
#endif
TPort Port_TCP = DEFAULT_WIFI_CLIENT_PORT_INET;
TPort Port_Spy = DEFAULT_WIFI_SPY_PORT;
TPort Port_Ctrl = DEFAULT_CTRL_PORT;
CSelect Scheduler;
void RemoveClient(CWifiServer* srv, bool srvIsSpy, TIndex i, TDescriptor socket)
{
if( ! srvIsSpy )
{
cout<<"Client disconnected : "; srv->ShowInfoWifi(i) ; cout<<endl;
}
else
cout<<"Spy disconnected : "<< srv->GetReferenceOnInfoWifiByIndex(i)->GetCid() <<endl;
srv->CloseClient(i);
//del master socket to set
Scheduler.DelNode(socket);
}
void ForwardData(bool srcIsSpy, CWifiServer* src, CWifiServer* otherDst)
{
int valread;
TPower power;
for ( TIndex i = 0 ; i < src->GetNumberClient() ; )
{
TDescriptor socket = (*src)[i];
if( ! src->IsEnable(i) )
{
RemoveClient(src, srcIsSpy , i, socket);
continue;
}
if( Scheduler.DescriptorHasAction(socket) )
{
//Check if it was for closing , and also read the
//incoming message
valread=src->RecvSignal(socket,&power,&Buffer);
if( valread <=0 )
{
RemoveClient(src, srcIsSpy , i, socket);
continue;
}
if( ! srcIsSpy )
{
src->SendAllOtherClients(i,power,Buffer.GetBuffer(),valread);
otherDst->SendAllClientsWithoutLoss(power,Buffer.GetBuffer(),valread);
}
else
{
src->SendAllOtherClientsWithoutLoss(i,power,Buffer.GetBuffer(),valread);
otherDst->SendAllClientsWithoutLoss(power,Buffer.GetBuffer(),valread);
}
}
i++;
}
}
int vwifi_server()
{
TDescriptor socket;
CListInfo<CInfoSocket> infoSockets;
CListInfo<CInfoWifi> infoWifis;
CListInfo<CInfoWifi> infoWifisDeconnected;
#ifdef ENABLE_VHOST
CWifiServerVTCP wifiServerVTCP(&infoSockets,&infoWifis,&infoWifisDeconnected);
cout<<"CLIENT VHOST : ";
wifiServerVTCP.Init(Port_VHOST);
if( ! wifiServerVTCP.Listen(WIFI_MAX_DECONNECTED_CLIENT) )
{
cerr<<"Error : wifiServerVTCP.Listen"<<endl;
exit(EXIT_FAILURE);
}
#endif
CWifiServerITCP wifiServerITCP(&infoSockets,&infoWifis,&infoWifisDeconnected);
cout<<"CLIENT TCP : ";
wifiServerITCP.Init(Port_TCP);
if( ! wifiServerITCP.Listen(WIFI_MAX_DECONNECTED_CLIENT) )
{
cerr<<"Error : wifiServerITCP.Listen"<<endl;
exit(EXIT_FAILURE);
}
CWifiServer* wifiServer=&wifiServerITCP; // or wifiServerVTCP, if exist, it doesn't change anything
cout<<"SPY : ";
CWifiServerITCP wifiServerSPY;
wifiServerSPY.Init(Port_Spy);
if( ! wifiServerSPY.Listen(1) )
{
cerr<<"Error : wifiServerSPY.Listen"<<endl;
exit(EXIT_FAILURE);
}
cout<<"CTRL : ";
#ifdef ENABLE_VHOST
CCTRLServer ctrlServer(&wifiServerVTCP, &wifiServerITCP, &wifiServerSPY,&Scheduler);
#else
CCTRLServer ctrlServer(NULL, &wifiServerITCP, &wifiServerSPY,&Scheduler);
#endif
ctrlServer.Init(Port_Ctrl);
if( ! ctrlServer.Listen() )
{
cerr<<"Error : ctrlServer.Listen"<<endl;
exit(EXIT_FAILURE);
}
cout<<"Size of disconnected : "<<WIFI_MAX_DECONNECTED_CLIENT<<endl;
if( CanLostPackets )
cout<<"Packet loss : Enable"<<endl;
else
cout<<"Packet loss : disable"<<endl;
cout<<"Scale : "<<Scale<<endl;
//add master socket to set
#ifdef ENABLE_VHOST
Scheduler.AddNode(wifiServerVTCP);
#endif
Scheduler.AddNode(wifiServerITCP);
Scheduler.AddNode(wifiServerSPY);
Scheduler.AddNode(ctrlServer);
while( true )
{
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
if( Scheduler.Wait() == SCHEDULER_ERROR )
{
cerr<<"Error : scheduler.Wait"<<endl;
return 1;
}
else {
//If something happened on the master socket ,
//then its an incoming connection
#ifdef ENABLE_VHOST
if( Scheduler.DescriptorHasAction(wifiServerVTCP) )
{
socket = wifiServerVTCP.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiServerVTCP.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Client VHost : "; wifiServer->ShowInfoWifi(wifiServer->GetNumberClient()-1) ; cout<<endl;
}
#endif
if( Scheduler.DescriptorHasAction(wifiServerITCP) )
{
socket = wifiServerITCP.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiServerITCP.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Client TCP : "; wifiServer->ShowInfoWifi(wifiServer->GetNumberClient()-1) ; cout<<endl;
}
if( Scheduler.DescriptorHasAction(wifiServerSPY) )
{
socket = wifiServerSPY.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiSpyServer.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Spy : "<<wifiServerSPY.GetReferenceOnInfoWifiByIndex(wifiServerSPY.GetNumberClient()-1)->GetCid()<<endl;
}
if( Scheduler.DescriptorHasAction(ctrlServer) )
{
ctrlServer.ReceiveOrder();
}
//else its some IO operation on some other socket
ForwardData(false, wifiServer, &wifiServerSPY);
ForwardData(true, &wifiServerSPY, wifiServer);
}
}
return 0;
}
void help()
{
#ifdef ENABLE_VHOST
cout<<"Usage: vwifi-server [-h] [-v] [-l] [-u] [-p PORT_VHOST] [-t PORT_TCP] [-s PORT_SPY] [-c PORT_CTRL]"<<endl;
cout<<" [--help] [--version] [--lost-packets] [--use-port-in-hash] [--port-vhost PORT_VHOST] [--port-tcp PORT_TCP] [--port-spy PORT_SPY] [--port-ctrl PORT_CTRL]"<<endl;
cout<<" By default : PORT_VHOST="<< DEFAULT_WIFI_CLIENT_PORT_VHOST <<
" PORT_TCP=" << DEFAULT_WIFI_CLIENT_PORT_INET <<
" PORT_SPY=" << DEFAULT_WIFI_SPY_PORT <<
" PORT_CTRL=" << DEFAULT_CTRL_PORT <<endl;
#else
cout<<"Usage: vwifi-server [-h] [-v] [-l] [-u] [-t PORT_TCP] [-s PORT_SPY] [-c PORT_CTRL]"<<endl;
cout<<" [--help] [--version] [--lost-packets] [--use-port-in-hash] [--port-tcp PORT_TCP] [--port-spy PORT_SPY] [--port-ctrl PORT_CTRL]"<<endl;
cout<<" By default : PORT_TCP=" << DEFAULT_WIFI_CLIENT_PORT_INET <<
" PORT_SPY=" << DEFAULT_WIFI_SPY_PORT <<
" PORT_CTRL=" << DEFAULT_CTRL_PORT <<endl;
#endif
}
int main(int argc, char** argv)
{
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
cout<<"Version : "<<VERSION<<endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
help();
return 0;
}
if( ! strcmp("-l", argv[arg_idx]) || ! strcmp("--lost-packets", argv[arg_idx]) )
{
CanLostPackets=true;
}
else if( ! strcmp("-u", argv[arg_idx]) || ! strcmp("--use-port-in-hash", argv[arg_idx]) )
{
HashUsesPort=true;
}
#ifdef ENABLE_VHOST
else if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port-vhost", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_VHOST = stoi(argv[arg_idx+1]);
arg_idx++;
}
#endif
else if( ( ! strcmp("-t", argv[arg_idx]) || ! strcmp("--port-tcp", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_TCP = stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-s", argv[arg_idx]) || ! strcmp("--port-spy", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Spy = stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-c", argv[arg_idx]) || ! strcmp("--port-ctrl", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Ctrl = stoi(argv[arg_idx+1]);
arg_idx++;
}
else
{
cerr<<"Error : problem with this parameter : "<< argv[arg_idx] <<endl;
help();
return 1;
}
arg_idx++;
}
return vwifi_server();
}
+8
View File
@@ -0,0 +1,8 @@
interface=wlan0
driver=nl80211
hw_mode=g
channel=1
ssid=mac80211_open
auth_algs=1
wpa=0
+9
View File
@@ -0,0 +1,9 @@
interface=wlan0
driver=nl80211
ssid=AP_WEP
hw_mode=g
channel=1
ignore_broadcast_ssid=0
wep_default_key=0
wep_key0="12345"
+11
View File
@@ -0,0 +1,11 @@
interface=wlan0
driver=nl80211
hw_mode=g
channel=1
ssid=mac80211_wpa
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
wpa_passphrase=12345678
+10
View File
@@ -0,0 +1,10 @@
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="mac80211_wpa"
psk="12345678"
key_mgmt=WPA-PSK
proto=WPA2
pairwise=CCMP
group=CCMP
}
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
MODE="d" # dhcp , s : static
INET="wlan1"
CONN="o" # wpa : w , open : o
WPA_CONF_FILE_PATH="tests/wpa_supplicant.conf"
IP="10.0.0.2/8"
help(){
echo "Help : $0 -m s|d -c o|w interface IP_STATIC/MASQUE"
echo " -m : IP Configuration mode"
echo " d : dhcp "
echo " s : static"
echo " -c : Connection mode"
echo " o : open "
echo " w : wpa"
}
if (( $# == 0 ))
then
help
exit 1
fi
while getopts "m:c:" option ; do
case $option in
m) MODE="${OPTARG}"
;;
c) CONN="${OPTARG}"
;;
*) help
;;
esac
done
shift $(($OPTIND - 1))
INET=$1
IP="$2"
#######################
if [ $CONN == "w" ] ; then
wpa_supplicant -Dnl80211 -i ${INET} -c ${WPA_CONF_FILE_PATH} &
else
ip link set up ${INET}
iw dev ${INET} connect mac80211_open
fi
sleep 3
if [ ${MODE} == "s" ] ; then
ip a a ${IP} dev wlan0
else
dhclient -v -i ${INET}
fi
+90
View File
@@ -0,0 +1,90 @@
#!/bin/bash
# Script : fast-vwifi-update
# Ecris par : David Ansart
# Ecris pour : Live Raizo / http://live-raizo.sourceforge.net
# But : Mettre à jour vwifi-server avec les positions des VMs dans GNS3
LOGIN=user
PASSWORD=user
SERVER=localhost
CERROR='\e[0;1;31m' # Rouge
SansCouleur='\e[0;m'
OptionVWifiQEmu=vwifi0
if [ -z "$(pgrep -xf '/usr/bin/python3 /usr/bin/gns3.*')" ]
then
>&2 echo -e "${CERROR}Error: Your GNS3 project must be open !!!${SansCouleur}"
exit 2
fi
if [ -z "$(pgrep 'vwifi-server')" ]
then
>&2 echo -e "${CERROR}Error: vwifi-server is not started !!!${SansCouleur}"
exit 2
fi
# récupère l'identifiant du projet
IdProjet=$(wget -q --user="$LOGIN" --password="$PASSWORD" "http://${SERVER}:3080/v2/projects" -O - | jq -M -r --unbuffered '.[] | select (.status=="opened") | .project_id')
if [ -z "${IdProjet}" ]
then
>&2 echo -e "${CERROR}Error: No project is open !!!${SansCouleur}"
exit 2
fi
# récupère la configuration du projet
ConfigProjectGNS3="$(mktemp fast-vwifi-update.XXXXXXXXXX --tmpdir=/tmp)"
wget -q --user="$LOGIN" --password="$PASSWORD" "http://${SERVER}:3080/v2/projects/${IdProjet}/nodes" -O "${ConfigProjectGNS3}"
NbValue=0
VMWithWifi=false
IFS=$'\n'
for line in $(jq -M '.[] | select (.node_type=="qemu") | {name: .name, x: .x, y: .y, z: .z , option: .command_line} ' "${ConfigProjectGNS3}")
do
if [[ "${line}" =~ ^[[:space:]]+\"name\":.* ]]
then
((NbValue++))
# attention au decallage du print (?)
Name=$(echo "${line}" | awk -F '[:, ]' '{print $5}' | tr -d '"' )
elif [[ "${line}" =~ ^[[:space:]]+\"x\":.* ]]
then
((NbValue++))
# attention au decallage du print (?)
X=$(echo "${line}" | awk -F '[:, ]' '{print $5}')
elif [[ "${line}" =~ ^[[:space:]]+\"y\":.* ]]
then
((NbValue++))
# attention au decallage du print (?)
Y=$(echo "${line}" | awk -F '[:, ]' '{print $5}')
elif [[ "${line}" =~ ^[[:space:]]+\"z\":.* ]]
then
((NbValue++))
# attention au decallage du print (?)
Z=$(echo "${line}" | awk -F '[:, ]' '{print $5}')
elif [[ "${line}" =~ ^[[:space:]]+\"option\":.* ]]
then
((NbValue++))
CID=$(echo "${line}" | grep -E -o 'id='${OptionVWifiQEmu}',guest-cid=[[:digit:]]+' | sed 's/id='${OptionVWifiQEmu}',guest-cid=//')
if [ -n "${CID}" ]
then
VMWithWifi=true
fi
fi
if (( NbValue == 5 ))
then
NbValue=0
if ${VMWithWifi}
then
echo "${CID}" "(${Name})" "${X}" "${Y}" "${Z}"
vwifi-ctrl setname "${CID}" "${Name}" > /dev/null
vwifi-ctrl set "${CID}" "${X}" "${Y}" "${Z}" > /dev/null
VMWithWifi=false
fi
fi
done
rm -f "${ConfigProjectGNS3}"
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
FOLDER_VWIFI='/hosthome/vwifi'
DEFAULT_PREFIX_MAC_ADDRESS='74:F8:F6'
# -------------------
cd "${FOLDER_VWIFI}"
if (( $# == 0 ))
then
NbrWifi=2
else
NbrWifi="$1"
fi
if [ -e /sys/module/mac80211_hwsim ]
then
OldNbrWifi=$(cat /sys/module/mac80211_hwsim/parameters/radios)
if (( NbrWifi != OldNbrWifi ))
then
modprobe -r mac80211_hwsim
fi
fi
modprobe mac80211_hwsim radios=0
hexchars="0123456789ABCDEF"
middle=$( for i in {1..4} ; do echo -n ${hexchars:$(( $RANDOM % 16 )):1} ; done | sed -e 's/\(..\)/:\1/g' )
MAC_ADDRESS="${DEFAULT_PREFIX_MAC_ADDRESS}${middle}"
./vwifi-add-interfaces "${NbrWifi}" "${MAC_ADDRESS}"
if [ "$(tty)" = '/dev/ttyS0' ]
then
# In Console Mode -> Tmux can be usefull
if [ -v TMUX ]
then
# Already in tmux
./vwifi-client
else
tmux new-session -s vwifi "bash --rcfile <(echo '. ~/.bashrc; ./vwifi-client')" ; detach &> /dev/null
tmux attach -t vwifi
fi
else
./vwifi-client
fi