forked from svpcom/wfb-ng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wifibroadcast.hpp
147 lines (112 loc) · 4.82 KB
/
wifibroadcast.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (C) 2017 Vasily Evseenko <[email protected]>
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __WIFIBROADCAST_HPP__
#define __WIFIBROADCAST_HPP__
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
#include <utime.h>
#include <unistd.h>
#include <getopt.h>
#include <pcap.h>
#include <endian.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#include <sodium.h>
#include <endian.h>
#define MAX_PACKET_SIZE 1510
#define MAX_RX_INTERFACES 8
using namespace std;
template<typename ... Args>
string string_format( const char *format, Args ... args )
{
size_t size = snprintf(nullptr, 0, format, args ...) + 1; // Extra space for '\0'
unique_ptr<char[]> buf(new char[ size ]);
snprintf(buf.get(), size, format, args ...);
return string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
/* this is the template radiotap header we send packets out with */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define MCS_KNOWN (IEEE80211_RADIOTAP_MCS_HAVE_MCS | IEEE80211_RADIOTAP_MCS_HAVE_BW | IEEE80211_RADIOTAP_MCS_HAVE_GI) // | IEEE80211_RADIOTAP_MCS_HAVE_FMT)
#define MCS_FLAGS (IEEE80211_RADIOTAP_MCS_BW_40 | IEEE80211_RADIOTAP_MCS_SGI) // | IEEE80211_RADIOTAP_MCS_FMT_GF)
static const uint8_t radiotap_header[] = {
0x00, 0x00, // <-- radiotap version
0x0d, 0x00, // <- radiotap header length
0x00, 0x80, 0x08, 0x00, // <-- radiotap present flags: RADIOTAP_TX_FLAGS + RADIOTAP_MCS
0x08, 0x00, // RADIOTAP_F_TX_NOACK
MCS_KNOWN , MCS_FLAGS, 0x01 // MCS default is #1 -- QPSK 1/2 40MHz SGI -- 30 Mbit/s
};
//the last byte of the mac address is recycled as a port number
#define SRC_MAC_LASTBYTE 15
#define DST_MAC_LASTBYTE 21
#define FRAME_SEQ_LB 22
#define FRAME_SEQ_HB 23
static uint8_t ieee80211_header[] = {
0x08, 0x01, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x00, 0x00, // seq num << 4 + fragment num
};
/*
Wifibroadcast protocol:
radiotap_header
ieee_80211_header
wblock_hdr_t { packet_type, nonce = (block_idx << 8 + fragment_idx) }
wpacket_hdr_t { packet_size } #
data #
+-- encrypted
*/
// nonce: 56bit block_idx + 8bit fragment_idx
#define BLOCK_IDX_MASK ((1LLU << 56) - 1)
#define MAX_BLOCK_IDX ((1LLU << 55) - 1)
#define WFB_PACKET_DATA 0x1
#define WFB_PACKET_KEY 0x2
#define SESSION_KEY_ANNOUNCE_MSEC 1000
// Network packet headers. All numbers are in network (big endian) format
// Encrypted packets can be either session key or data packet.
// Session key packet
typedef struct {
uint8_t packet_type;
uint8_t session_key_nonce[crypto_box_NONCEBYTES]; // random data
uint8_t session_key_data[crypto_aead_chacha20poly1305_KEYBYTES + crypto_box_MACBYTES]; // encrypted session key
} __attribute__ ((packed)) wsession_key_t;
// Data packet. Embed FEC-encoded data
typedef struct {
uint8_t packet_type;
uint64_t nonce; // big endian, nonce = block_idx << 8 + fragment_idx
} __attribute__ ((packed)) wblock_hdr_t;
// Plain data packet after FEC decode
typedef struct {
uint16_t packet_size; // big endian
} __attribute__ ((packed)) wpacket_hdr_t;
#define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - sizeof(radiotap_header) - sizeof(ieee80211_header) - sizeof(wblock_hdr_t) - crypto_aead_chacha20poly1305_ABYTES - sizeof(wpacket_hdr_t))
#define MAX_FEC_PAYLOAD (MAX_PACKET_SIZE - sizeof(radiotap_header) - sizeof(ieee80211_header) - sizeof(wblock_hdr_t) - crypto_aead_chacha20poly1305_ABYTES)
#define MAX_FORWARDER_PACKET_SIZE (MAX_PACKET_SIZE - sizeof(radiotap_header) - sizeof(ieee80211_header))
int open_udp_socket_for_rx(int port);
#endif