forked from servalproject/serval-dna
-
Notifications
You must be signed in to change notification settings - Fork 0
/
overlay.c
304 lines (239 loc) · 7.11 KB
/
overlay.c
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*
Serval Overlay Mesh Network.
Basically we use UDP broadcast to send link-local, and then implement a BATMAN-like protocol over the top of that.
Each overlay packet can contain one or more encapsulated packets each addressed using Serval DNA SIDs, with source,
destination and next-hop addresses.
The use of long (relative to IPv4) ECC160 addresses means that it is a really good idea to have neighbouring nodes
exchange lists of peer aliases so that addresses can be summarised, possibly using less space than IPv4 would have.
Byzantine Robustness is a goal, so we have to think about all sorts of malicious failure modes.
One approach to help byzantine robustness is to have multiple signature shells for each hop for mesh topology packets.
Thus forging a report of closeness requires forging a signature. As such frames are forwarded, the outermost signature
shell is removed.
*/
#include "mphlr.h"
int overlay_socket=-1;
typedef struct overlay_buffer {
unsigned char *bytes;
int length;
int allocSize;
int checkpointLength;
int sizeLimit;
} overlay_buffer;
int ob_unlimitsize(overlay_buffer *b);
typedef struct overlay_payload {
struct overlay_payload *prev;
struct overlay_payload *next;
/* We allows 256 bit addresses and 32bit port numbers */
char src[SIDDIDFIELD_LEN];
char dst[SIDDIDFIELD_LEN];
int srcPort;
int dstPort;
/* Hops before packet is dropped */
unsigned char ttl;
unsigned char trafficClass;
unsigned char srcAddrType;
unsigned char dstAddrType;
/* Method of encryption if any employed */
unsigned char cipher;
/* Payload flags */
unsigned char flags;
/* Pointer to the payload itself */
unsigned char *payload;
int payloadLength;
} overlay_payload;
typedef struct overlay_txqueue {
overlay_payload *first;
overlay_payload *last;
int length;
int maxLength;
/* Latency target in ms for this traffic class */
int latencyTarget;
} overlay_txqueue;
/* XXX Need to initialise these:
Real-time queue for voice
Real-time queue for video (lower priority than voice)
Ordinary service queue
Rhizome opportunistic queue
(Mesh management doesn't need a queue, as each overlay packet is tagged with some mesh management information)
*/
overlay_txqueue overlay_tx[4];
int overlay_sock=-1;
int overlay_init()
{
struct sockaddr_in bind_addr;
overlay_sock=socket(PF_INET,SOCK_DGRAM,0);
if (overlay_sock<0) {
fprintf(stderr,"Could not create overlay UDP socket.\n");
perror("socket");
exit(-3);
}
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons( PORT_DNA );
bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
if(bind(sock,(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
fprintf(stderr,"MP HLR server could not bind to UDP port %d\n", PORT_DNA);
perror("bind");
exit(-3);
}
return 0;
}
int overlay_rx_messages()
{
if (overlay_socket==-1) overlay_init();
return 0;
}
int overlay_tx_messages()
{
if (overlay_socket==-1) overlay_init();
return 0;
}
int overlay_broadcast_ensemble(char *bytes,int len)
{
struct sockaddr_in s;
memset(&s, '\0', sizeof(struct sockaddr_in));
s.sin_family = AF_INET;
s.sin_port = (in_port_t)htons( PORT_OVERLAY );
s.sin_addr.s_addr = htonl( INADDR_BROADCAST );
if(sendto(overlay_socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
/* Failed to send */
return -1;
else
/* Sent okay */
return 0;
}
int overlay_payload_verify()
{
/* Make sure that an incoming payload has a valid signature from the sender.
This is used to prevent spoofing */
return -1;
}
overlay_buffer *ob_new(int size)
{
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1);
if (!ret) return NULL;
ob_unlimitsize(ret);
return ret;
}
int ob_free(overlay_buffer *b)
{
if (!b) return -1;
if (b->bytes) free(b->bytes);
b->bytes=NULL;
b->allocSize=0;
b->sizeLimit=0;
free(b);
return 0;
}
int ob_checkpoint(overlay_buffer *b)
{
if (!b) return -1;
b->checkpointLength=b->length;
return 0;
}
int ob_rewind(overlay_buffer *b)
{
if (!b) return -1;
b->length=b->checkpointLength;
return 0;
}
int ob_limitsize(overlay_buffer *b,int bytes)
{
if (!b) return -1;
if (b->length>bytes) return -1;
if (b->checkpointLength>bytes) return -1;
if (bytes<0) return -1;
b->sizeLimit=bytes;
return 0;
}
int ob_unlimitsize(overlay_buffer *b)
{
if (!b) return -1;
b->sizeLimit=-1;
return 0;
}
int ob_makespace(overlay_buffer *b,int bytes)
{
if (b->sizeLimit!=-1) {
if (b->length+bytes>b->sizeLimit) return -1;
}
if (b->length+bytes<b->allocSize)
{
int newSize=b->length+bytes;
if (newSize<64) newSize=64;
if (newSize&63) newSize+=64-(newSize&63);
if (newSize>1024) {
if (newSize&1023) newSize+=1024-(newSize&1023);
}
if (newSize>65536) {
if (newSize&65535) newSize+=65536-(newSize&65535);
}
unsigned char *r=realloc(b->bytes,newSize);
if (!r) return -1;
b->bytes=r;
b->allocSize=newSize;
return 0;
}
else
return 0;
}
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count)
{
if (ob_makespace(b,count)) return -1;
bcopy(bytes,&b->bytes[b->length],count);
b->length+=count;
return 0;
}
int ob_append_short(overlay_buffer *b,unsigned short v)
{
unsigned short s=htons(v);
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned short));
}
int ob_append_int(overlay_buffer *b,unsigned int v)
{
unsigned int s=htonl(v);
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned int));
}
int overlay_get_nexthop(overlay_payload *p,unsigned char *hopout,int *hopaddrlen)
{
return -1;
}
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
{
/* Convert a payload structure into a series of bytes.
Also select next-hop address to help payload get to its' destination */
unsigned char nexthop[SIDDIDFIELD_LEN+1];
int nexthoplen=0;
overlay_buffer *headers=ob_new(256);
if (!headers) return -1;
if (!p) return -1;
if (!b) return -1;
/* Build header */
int fail=0;
if (overlay_get_nexthop(p,nexthop,&nexthoplen)) fail++;
if (ob_append_bytes(headers,nexthop,nexthoplen)) fail++;
/* XXX Can use shorter fields for different address types */
if (ob_append_bytes(headers,(unsigned char *)p->src,SIDDIDFIELD_LEN)) fail++;
if (ob_append_bytes(headers,(unsigned char *)p->dst,SIDDIDFIELD_LEN)) fail++;
if (fail) {
ob_free(headers);
return -1;
}
/* Write payload format plus total length of header bits */
if (ob_makespace(b,2+headers->length+p->payloadLength)) {
/* Not enough space free in output buffer */
ob_free(headers);
return -1;
}
/* Package up headers and payload */
ob_checkpoint(b);
if (ob_append_short(b,0x1000|(p->payloadLength+headers->length))) fail++;
if (ob_append_bytes(b,headers->bytes,headers->length)) fail++;
if (ob_append_bytes(b,p->payload,p->payloadLength)) fail++;
/* XXX SIGNATURE! */
ob_free(headers);
if (fail) { ob_rewind(b); return -1; } else return 0;
}
overlay_payload *overlay_payload_unpackage(overlay_buffer *b) {
/* Extract the payload at the current location in the buffer. */
return NULL;
}