"Fossies" - the Fresh Open Source Software Archive 
Member "n2n-3.1.1/src/n2n.c" (31 Mar 2022, 28068 Bytes) of package /linux/misc/n2n-3.1.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "n2n.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
3.0_vs_3.1.1.
1 /**
2 * (C) 2007-22 - ntop.org and contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not see see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #include "n2n.h"
20
21 #include "sn_selection.h"
22
23 #include "minilzo.h"
24
25 #include <assert.h>
26
27
28
29 /* ************************************** */
30
31 SOCKET open_socket (int local_port, in_addr_t address, int type /* 0 = UDP, TCP otherwise */) {
32
33 SOCKET sock_fd;
34 struct sockaddr_in local_address;
35 int sockopt;
36
37 if((int)(sock_fd = socket(PF_INET, ((type == 0) ? SOCK_DGRAM : SOCK_STREAM) , 0)) < 0) {
38 traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n",
39 strerror(errno), sock_fd);
40 return(-1);
41 }
42
43 #ifndef WIN32
44 /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */
45 #endif
46
47 sockopt = 1;
48 setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
49
50 memset(&local_address, 0, sizeof(local_address));
51 local_address.sin_family = AF_INET;
52 local_address.sin_port = htons(local_port);
53 local_address.sin_addr.s_addr = htonl(address);
54
55 if(bind(sock_fd,(struct sockaddr*) &local_address, sizeof(local_address)) == -1) {
56 traceEvent(TRACE_ERROR, "Bind error on local port %u [%s]\n", local_port, strerror(errno));
57 return(-1);
58 }
59
60 return(sock_fd);
61 }
62
63
64 static int traceLevel = 2 /* NORMAL */;
65 static int useSyslog = 0, syslog_opened = 0;
66 static FILE *traceFile = NULL;
67
68 int getTraceLevel () {
69
70 return(traceLevel);
71 }
72
73 void setTraceLevel (int level) {
74
75 traceLevel = level;
76 }
77
78 void setUseSyslog (int use_syslog) {
79
80 useSyslog = use_syslog;
81 }
82
83 void setTraceFile (FILE *f) {
84
85 traceFile = f;
86 }
87
88 void closeTraceFile () {
89
90 if((traceFile != NULL) && (traceFile != stdout)) {
91 fclose(traceFile);
92 }
93 #ifndef WIN32
94 if(useSyslog && syslog_opened) {
95 closelog();
96 syslog_opened = 0;
97 }
98 #endif
99 }
100
101 #define N2N_TRACE_DATESIZE 32
102 void traceEvent (int eventTraceLevel, char* file, int line, char * format, ...) {
103
104 va_list va_ap;
105
106 if(traceFile == NULL) {
107 traceFile = stdout;
108 }
109
110 if(eventTraceLevel <= traceLevel) {
111 char buf[1024];
112 char out_buf[1280];
113 char theDate[N2N_TRACE_DATESIZE];
114 char *extra_msg = "";
115 time_t theTime = time(NULL);
116 int i;
117
118 /* We have two paths - one if we're logging, one if we aren't
119 * Note that the no-log case is those systems which don't support it(WIN32),
120 * those without the headers !defined(USE_SYSLOG)
121 * those where it's parametrically off...
122 */
123
124 memset(buf, 0, sizeof(buf));
125 strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime));
126
127 va_start(va_ap, format);
128 vsnprintf(buf, sizeof(buf) - 1, format, va_ap);
129 va_end(va_ap);
130
131 if(eventTraceLevel == 0 /* TRACE_ERROR */) {
132 extra_msg = "ERROR: ";
133 } else if(eventTraceLevel == 1 /* TRACE_WARNING */) {
134 extra_msg = "WARNING: ";
135 }
136
137 while(buf[strlen(buf) - 1] == '\n') {
138 buf[strlen(buf) - 1] = '\0';
139 }
140
141 #ifndef WIN32
142 if(useSyslog) {
143 if(!syslog_opened) {
144 openlog("n2n", LOG_PID, LOG_DAEMON);
145 syslog_opened = 1;
146 }
147
148 snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf);
149 syslog(LOG_INFO, "%s", out_buf);
150 } else {
151 #endif
152 for(i = strlen(file) - 1; i > 0; i--) {
153 if((file[i] == '/') || (file[i] == '\\')) {
154 i++;
155 break;
156 }
157 }
158 snprintf(out_buf, sizeof(out_buf), "%s [%s:%d] %s%s", theDate, &file[i], line, extra_msg, buf);
159 fprintf(traceFile, "%s\n", out_buf);
160 fflush(traceFile);
161 #ifndef WIN32
162 }
163 #endif
164 }
165
166 }
167
168 /* *********************************************** */
169
170 /* addr should be in network order. Things are so much simpler that way. */
171 char* intoa (uint32_t /* host order */ addr, char* buf, uint16_t buf_len) {
172
173 char *cp, *retStr;
174 uint8_t byteval;
175 int n;
176
177 cp = &buf[buf_len];
178 *--cp = '\0';
179
180 n = 4;
181 do {
182 byteval = addr & 0xff;
183 *--cp = byteval % 10 + '0';
184 byteval /= 10;
185 if(byteval > 0) {
186 *--cp = byteval % 10 + '0';
187 byteval /= 10;
188 if(byteval > 0) {
189 *--cp = byteval + '0';
190 }
191 }
192 *--cp = '.';
193 addr >>= 8;
194 } while(--n > 0);
195
196 /* Convert the string to lowercase */
197 retStr = (char*)(cp + 1);
198
199 return(retStr);
200 }
201
202
203 /** Convert subnet prefix bit length to host order subnet mask. */
204 uint32_t bitlen2mask (uint8_t bitlen) {
205
206 uint8_t i;
207 uint32_t mask = 0;
208
209 for (i = 1; i <= bitlen; ++i) {
210 mask |= 1 << (32 - i);
211 }
212
213 return mask;
214 }
215
216
217 /** Convert host order subnet mask to subnet prefix bit length. */
218 uint8_t mask2bitlen (uint32_t mask) {
219
220 uint8_t i, bitlen = 0;
221
222 for (i = 0; i < 32; ++i) {
223 if((mask << i) & 0x80000000) {
224 ++bitlen;
225 } else {
226 break;
227 }
228 }
229
230 return bitlen;
231 }
232
233
234 /* *********************************************** */
235
236 char * macaddr_str (macstr_t buf,
237 const n2n_mac_t mac) {
238
239 snprintf(buf, N2N_MACSTR_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X",
240 mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
241 mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF);
242
243 return(buf);
244 }
245
246 /* *********************************************** */
247
248 /** Resolve the supernode IP address.
249 *
250 */
251 int supernode2sock (n2n_sock_t *sn, const n2n_sn_name_t addrIn) {
252
253 n2n_sn_name_t addr;
254 char *supernode_host;
255 char *supernode_port;
256 int rv = 0;
257 int nameerr;
258 const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL};
259 struct addrinfo * ainfo = NULL;
260 struct sockaddr_in * saddr;
261
262 sn->family = AF_INVALID;
263
264 memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE);
265 supernode_host = strtok(addr, ":");
266
267 if(supernode_host) {
268 supernode_port = strtok(NULL, ":");
269 if(supernode_port) {
270 sn->port = atoi(supernode_port);
271 nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo);
272 if(0 == nameerr) {
273 /* ainfo s the head of a linked list if non-NULL. */
274 if(ainfo && (PF_INET == ainfo->ai_family)) {
275 /* It is definitely and IPv4 address -> sockaddr_in */
276 saddr = (struct sockaddr_in *)ainfo->ai_addr;
277 memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE);
278 sn->family = AF_INET;
279 traceEvent(TRACE_INFO, "supernode2sock successfully resolves supernode IPv4 address for %s", supernode_host);
280 rv = 0;
281 } else {
282 /* Should only return IPv4 addresses due to aihints. */
283 traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode IPv4 address for %s", supernode_host);
284 rv = -1;
285 }
286 freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */
287 } else {
288 traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode host %s, %d: %s", supernode_host, nameerr, gai_strerror(nameerr));
289 rv = -2;
290 }
291 } else {
292 traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l <host:port>) %s", addrIn);
293 rv = -3;
294 }
295 } else {
296 traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l <host:port>) %s",
297 addrIn);
298 rv = -4;
299 }
300
301 ainfo = NULL;
302
303 return rv;
304 }
305
306
307 #ifdef HAVE_PTHREAD
308 N2N_THREAD_RETURN_DATATYPE resolve_thread(N2N_THREAD_PARAMETER_DATATYPE p) {
309
310 n2n_resolve_parameter_t *param = (n2n_resolve_parameter_t*)p;
311 n2n_resolve_ip_sock_t *entry, *tmp_entry;
312 time_t rep_time = N2N_RESOLVE_INTERVAL / 10;
313 time_t now;
314
315 while(1) {
316 sleep(N2N_RESOLVE_INTERVAL / 60); /* wake up in-between to check for signaled requests */
317
318 // what's the time?
319 now = time(NULL);
320
321 // lock access
322 pthread_mutex_lock(¶m->access);
323
324 // is it time to resolve yet?
325 if(((param->request)) || ((now - param->last_resolved) > rep_time)) {
326 HASH_ITER(hh, param->list, entry, tmp_entry) {
327 // resolve
328 entry->error_code = supernode2sock(&entry->sock, entry->org_ip);
329 // if socket changed and no error
330 if(!sock_equal(&entry->sock, entry->org_sock)
331 && (!entry->error_code)) {
332 // flag the change
333 param->changed = 1;
334 }
335 }
336 param->last_resolved = now;
337
338 // any request fulfilled
339 param->request = 0;
340
341 // determine next resolver repetition (shorter time if resolver errors occured)
342 rep_time = N2N_RESOLVE_INTERVAL;
343 HASH_ITER(hh, param->list, entry, tmp_entry) {
344 if(entry->error_code) {
345 rep_time = N2N_RESOLVE_INTERVAL / 10;
346 break;
347 }
348 }
349 }
350
351 // unlock access
352 pthread_mutex_unlock(¶m->access);
353 }
354 }
355 #endif
356
357
358 int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list) {
359
360 #ifdef HAVE_PTHREAD
361 struct peer_info *sn, *tmp_sn;
362 n2n_resolve_ip_sock_t *entry;
363 int ret;
364
365 // create parameter structure
366 *param = (n2n_resolve_parameter_t*)calloc(1, sizeof(n2n_resolve_parameter_t));
367 if(*param) {
368 HASH_ITER(hh, sn_list, sn, tmp_sn) {
369 // create entries for those peers that come with ip_addr string (from command-line)
370 if(sn->ip_addr) {
371 entry = (n2n_resolve_ip_sock_t*)calloc(1, sizeof(n2n_resolve_ip_sock_t));
372 if(entry) {
373 entry->org_ip = sn->ip_addr;
374 entry->org_sock = &(sn->sock);
375 memcpy(&(entry->sock), &(sn->sock), sizeof(n2n_sock_t));
376 HASH_ADD(hh, (*param)->list, org_ip, sizeof(char*), entry);
377 } else
378 traceEvent(TRACE_WARNING, "resolve_create_thread was unable to add list entry for supernode '%s'", sn->ip_addr);
379 }
380 }
381 (*param)->check_interval = N2N_RESOLVE_CHECK_INTERVAL;
382 } else {
383 traceEvent(TRACE_WARNING, "resolve_create_thread was unable to create list of supernodes");
384 return -1;
385 }
386
387 // create thread
388 ret = pthread_create(&((*param)->id), NULL, resolve_thread, (void *)*param);
389 if(ret) {
390 traceEvent(TRACE_WARNING, "resolve_create_thread failed to create resolver thread with error number %d", ret);
391 return -1;
392 }
393
394 pthread_mutex_init(&((*param)->access), NULL);
395
396 return 0;
397 #else
398 return -1;
399 #endif
400 }
401
402
403 void resolve_cancel_thread (n2n_resolve_parameter_t *param) {
404
405 #ifdef HAVE_PTHREAD
406 pthread_cancel(param->id);
407 free(param);
408 #endif
409 }
410
411
412 uint8_t resolve_check (n2n_resolve_parameter_t *param, uint8_t requires_resolution, time_t now) {
413
414 uint8_t ret = requires_resolution; /* if trylock fails, it still requires resolution */
415
416 #ifdef HAVE_PTHREAD
417 n2n_resolve_ip_sock_t *entry, *tmp_entry;
418 n2n_sock_str_t sock_buf;
419
420 if(NULL == param)
421 return ret;
422
423 // check_interval and last_check do not need to be guarded by the mutex because
424 // their values get changed and evaluated only here
425
426 if((now - param->last_checked > param->check_interval) || (requires_resolution)) {
427 // try to lock access
428 if(pthread_mutex_trylock(¶m->access) == 0) {
429 // any changes?
430 if(param->changed) {
431 // reset flag
432 param->changed = 0;
433 // unselectively copy all socks (even those with error code, that would be the old one because
434 // sockets do not get overwritten in case of error in resolve_thread) from list to supernode list
435 HASH_ITER(hh, param->list, entry, tmp_entry) {
436 memcpy(entry->org_sock, &entry->sock, sizeof(n2n_sock_t));
437 traceEvent(TRACE_INFO, "resolve_check renews ip address of supernode '%s' to %s",
438 entry->org_ip, sock_to_cstr(sock_buf, &(entry->sock)));
439 }
440 }
441
442 // let the resolver thread know eventual difficulties in reaching the supernode
443 if(requires_resolution) {
444 param->request = 1;
445 ret = 0;
446 }
447
448 param->last_checked = now;
449
450 // next appointment
451 if(param->request)
452 // earlier if resolver still working on fulfilling a request
453 param->check_interval = N2N_RESOLVE_CHECK_INTERVAL / 10;
454 else
455 param->check_interval = N2N_RESOLVE_CHECK_INTERVAL;
456
457 // unlock access
458 pthread_mutex_unlock(¶m->access);
459 }
460 }
461 #endif
462
463 return ret;
464 }
465
466
467 /* ************************************** */
468
469
470 struct peer_info* add_sn_to_list_by_mac_or_sock (struct peer_info **sn_list, n2n_sock_t *sock, const n2n_mac_t mac, int *skip_add) {
471
472 struct peer_info *scan, *tmp, *peer = NULL;
473
474 if(!is_null_mac(mac)) { /* not zero MAC */
475 HASH_FIND_PEER(*sn_list, mac, peer);
476 }
477
478 if(peer == NULL) { /* zero MAC, search by socket */
479 HASH_ITER(hh, *sn_list, scan, tmp) {
480 if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) {
481 // update mac if appropriate, needs to be deleted first because it is key to the hash list
482 if(!is_null_mac(mac)) {
483 HASH_DEL(*sn_list, scan);
484 memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t));
485 HASH_ADD_PEER(*sn_list, scan);
486 }
487 peer = scan;
488 break;
489 }
490 }
491
492 if((peer == NULL) && (*skip_add == SN_ADD)) {
493 peer = (struct peer_info*)calloc(1, sizeof(struct peer_info));
494 if(peer) {
495 sn_selection_criterion_default(&(peer->selection_criterion));
496 peer->last_valid_time_stamp = initial_time_stamp();
497 memcpy(&(peer->sock), sock, sizeof(n2n_sock_t));
498 memcpy(peer->mac_addr, mac, sizeof(n2n_mac_t));
499 HASH_ADD_PEER(*sn_list, peer);
500 *skip_add = SN_ADD_ADDED;
501 }
502 }
503 }
504
505 return peer;
506 }
507
508 /* ************************************************ */
509
510
511 /* http://www.faqs.org/rfcs/rfc908.html */
512 uint8_t is_multi_broadcast (const n2n_mac_t dest_mac) {
513
514 int is_broadcast = (memcmp(broadcast_mac, dest_mac, N2N_MAC_SIZE) == 0);
515 int is_multicast = (memcmp(multicast_mac, dest_mac, 3) == 0) && !(dest_mac[3] >> 7);
516 int is_ipv6_multicast = (memcmp(ipv6_multicast_mac, dest_mac, 2) == 0);
517
518 return is_broadcast || is_multicast || is_ipv6_multicast;
519 }
520
521
522 uint8_t is_broadcast (const n2n_mac_t dest_mac) {
523
524 int is_broadcast = (memcmp(broadcast_mac, dest_mac, N2N_MAC_SIZE) == 0);
525
526 return is_broadcast;
527 }
528
529
530 uint8_t is_null_mac (const n2n_mac_t dest_mac) {
531
532 int is_null_mac = (memcmp(null_mac, dest_mac, N2N_MAC_SIZE) == 0);
533
534 return is_null_mac;
535 }
536
537
538 /* *********************************************** */
539
540 char* msg_type2str (uint16_t msg_type) {
541
542 switch(msg_type) {
543 case MSG_TYPE_REGISTER: return("MSG_TYPE_REGISTER");
544 case MSG_TYPE_DEREGISTER: return("MSG_TYPE_DEREGISTER");
545 case MSG_TYPE_PACKET: return("MSG_TYPE_PACKET");
546 case MSG_TYPE_REGISTER_ACK: return("MSG_TYPE_REGISTER_ACK");
547 case MSG_TYPE_REGISTER_SUPER: return("MSG_TYPE_REGISTER_SUPER");
548 case MSG_TYPE_REGISTER_SUPER_ACK: return("MSG_TYPE_REGISTER_SUPER_ACK");
549 case MSG_TYPE_REGISTER_SUPER_NAK: return("MSG_TYPE_REGISTER_SUPER_NAK");
550 case MSG_TYPE_FEDERATION: return("MSG_TYPE_FEDERATION");
551 default: return("???");
552 }
553
554 return("???");
555 }
556
557 /* *********************************************** */
558
559 void hexdump (const uint8_t *buf, size_t len) {
560
561 size_t i;
562
563 if(0 == len) {
564 return;
565 }
566
567 printf("-----------------------------------------------\n");
568 for(i = 0; i < len; i++) {
569 if((i > 0) && ((i % 16) == 0)) {
570 printf("\n");
571 }
572 printf("%02X ", buf[i] & 0xFF);
573 }
574 printf("\n");
575 printf("-----------------------------------------------\n");
576 }
577
578
579 /* *********************************************** */
580
581 void print_n2n_version () {
582
583 printf("Welcome to n2n v.%s for %s\n"
584 "Built on %s\n"
585 "Copyright 2007-2022 - ntop.org and contributors\n\n",
586 PACKAGE_VERSION, PACKAGE_OSNAME, PACKAGE_BUILDDATE);
587 }
588
589 /* *********************************************** */
590
591 size_t purge_expired_nodes (struct peer_info **peer_list,
592 SOCKET socket_not_to_close,
593 n2n_tcp_connection_t **tcp_connections,
594 time_t *p_last_purge,
595 int frequency, int timeout) {
596
597 time_t now = time(NULL);
598 size_t num_reg = 0;
599
600 if((now - (*p_last_purge)) < frequency) {
601 return 0;
602 }
603
604 traceEvent(TRACE_DEBUG, "Purging old registrations");
605
606 num_reg = purge_peer_list(peer_list, socket_not_to_close, tcp_connections, now - timeout);
607
608 (*p_last_purge) = now;
609 traceEvent(TRACE_DEBUG, "Remove %ld registrations", num_reg);
610
611 return num_reg;
612 }
613
614 /** Purge old items from the peer_list, eventually close the related socket, and
615 * return the number of items that were removed. */
616 size_t purge_peer_list (struct peer_info **peer_list,
617 SOCKET socket_not_to_close,
618 n2n_tcp_connection_t **tcp_connections,
619 time_t purge_before) {
620
621 struct peer_info *scan, *tmp;
622 n2n_tcp_connection_t *conn;
623 size_t retval = 0;
624
625 HASH_ITER(hh, *peer_list, scan, tmp) {
626 if((scan->purgeable == SN_PURGEABLE) && (scan->last_seen < purge_before)) {
627 if((scan->socket_fd >=0) && (scan->socket_fd != socket_not_to_close)) {
628 if(tcp_connections) {
629 HASH_FIND_INT(*tcp_connections, &scan->socket_fd, conn);
630 if(conn) {
631 HASH_DEL(*tcp_connections, conn);
632 free(conn);
633 }
634 shutdown(scan->socket_fd, SHUT_RDWR);
635 closesocket(scan->socket_fd);
636 }
637 }
638 HASH_DEL(*peer_list, scan);
639 mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_PURGE,scan);
640 /* FIXME: generates events for more than just p2p */
641 retval++;
642 free(scan);
643 }
644 }
645
646 return retval;
647 }
648
649 /** Purge all items from the peer_list and return the number of items that were removed. */
650 size_t clear_peer_list (struct peer_info ** peer_list) {
651
652 struct peer_info *scan, *tmp;
653 size_t retval = 0;
654
655 HASH_ITER(hh, *peer_list, scan, tmp) {
656 HASH_DEL(*peer_list, scan);
657 mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_CLEAR,scan);
658 /* FIXME: generates events for more than just p2p */
659 retval++;
660 free(scan);
661 }
662
663 return retval;
664 }
665
666 static uint8_t hex2byte (const char * s) {
667
668 char tmp[3];
669 tmp[0] = s[0];
670 tmp[1] = s[1];
671 tmp[2] = 0; /* NULL term */
672
673 return((uint8_t)strtol(tmp, NULL, 16));
674 }
675
676 extern int str2mac (uint8_t * outmac /* 6 bytes */, const char * s) {
677
678 size_t i;
679
680 /* break it down as one case for the first "HH", the 5 x through loop for
681 * each ":HH" where HH is a two hex nibbles in ASCII. */
682
683 *outmac = hex2byte(s);
684 ++outmac;
685 s += 2; /* don't skip colon yet - helps generalise loop. */
686
687 for(i = 1; i < 6; ++i) {
688 s += 1;
689 *outmac = hex2byte(s);
690 ++outmac;
691 s += 2;
692 }
693
694 return 0; /* ok */
695 }
696
697 extern char * sock_to_cstr (n2n_sock_str_t out,
698 const n2n_sock_t * sock) {
699
700 if(NULL == out) {
701 return NULL;
702 }
703 memset(out, 0, N2N_SOCKBUF_SIZE);
704
705 if(AF_INET6 == sock->family) {
706 /* INET6 not written yet */
707 snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port);
708 return out;
709 } else {
710 const uint8_t * a = sock->addr.v4;
711
712 snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu",
713 (unsigned short)(a[0] & 0xff),
714 (unsigned short)(a[1] & 0xff),
715 (unsigned short)(a[2] & 0xff),
716 (unsigned short)(a[3] & 0xff),
717 (unsigned short)sock->port);
718 return out;
719 }
720 }
721
722 char *ip_subnet_to_str (dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr) {
723
724 snprintf(buf, sizeof(dec_ip_bit_str_t), "%hhu.%hhu.%hhu.%hhu/%hhu",
725 (uint8_t) ((ipaddr->net_addr >> 24) & 0xFF),
726 (uint8_t) ((ipaddr->net_addr >> 16) & 0xFF),
727 (uint8_t) ((ipaddr->net_addr >> 8) & 0xFF),
728 (uint8_t) (ipaddr->net_addr & 0xFF),
729 ipaddr->net_bitlen);
730
731 return buf;
732 }
733
734
735 /* @return 1 if the two sockets are equivalent. */
736 int sock_equal (const n2n_sock_t * a,
737 const n2n_sock_t * b) {
738
739 if(a->port != b->port) {
740 return(0);
741 }
742
743 if(a->family != b->family) {
744 return(0);
745 }
746
747 switch(a->family) {
748 case AF_INET:
749 if(memcmp(a->addr.v4, b->addr.v4, IPV4_SIZE)) {
750 return(0);
751 }
752 break;
753
754 default:
755 if(memcmp(a->addr.v6, b->addr.v6, IPV6_SIZE)) {
756 return(0);
757 }
758 break;
759 }
760
761 /* equal */
762 return(1);
763 }
764
765
766 /* *********************************************** */
767
768 // fills a specified memory area with random numbers
769 int memrnd (uint8_t *address, size_t len) {
770
771 for(; len >= 4; len -= 4) {
772 *(uint32_t*)address = n2n_rand();
773 address += 4;
774 }
775
776 for(; len > 0; len--) {
777 *address = n2n_rand();
778 address++;
779 }
780
781 return 0;
782 }
783
784
785 // exclusive-ors a specified memory area with another
786 int memxor (uint8_t *destination, const uint8_t *source, size_t len) {
787
788 for(; len >= 4; len -= 4) {
789 *(uint32_t*)destination ^= *(uint32_t*)source;
790 source += 4;
791 destination += 4;
792 }
793
794 for(; len > 0; len--) {
795 *destination ^= *source;
796 source++;
797 destination++;
798 }
799
800 return 0;
801 }
802
803 /* *********************************************** */
804
805 #if defined(WIN32)
806 int gettimeofday (struct timeval *tp, void *tzp) {
807
808 time_t clock;
809 struct tm tm;
810 SYSTEMTIME wtm;
811
812 GetLocalTime(&wtm);
813 tm.tm_year = wtm.wYear - 1900;
814 tm.tm_mon = wtm.wMonth - 1;
815 tm.tm_mday = wtm.wDay;
816 tm.tm_hour = wtm.wHour;
817 tm.tm_min = wtm.wMinute;
818 tm.tm_sec = wtm.wSecond;
819 tm.tm_isdst = -1;
820 clock = mktime(&tm);
821 tp->tv_sec = clock;
822 tp->tv_usec = wtm.wMilliseconds * 1000;
823
824 return 0;
825 }
826 #endif
827
828
829 // stores the previously issued time stamp
830 static uint64_t previously_issued_time_stamp = 0;
831
832
833 // returns a time stamp for use with replay protection (branchless code)
834 //
835 // depending on the self-detected accuracy, it has the following format
836 //
837 // MMMMMMMMCCCCCCCF or
838 //
839 // MMMMMMMMSSSSSCCF
840 //
841 // with M being the 32-bit second time stamp
842 // S the 20-bit sub-second (microsecond) time stamp part, if applicable
843 // C a counter (8 bit or 24 bit) reset to 0 with every MMMMMMMM(SSSSS) turn-over
844 // F a 4-bit flag field with
845 // ...c being the accuracy indicator (if set, only counter and no sub-second accuracy)
846 //
847 uint64_t time_stamp (void) {
848
849 struct timeval tod;
850 uint64_t micro_seconds;
851 uint64_t co, mask_lo, mask_hi, hi_unchanged, counter, new_co;
852
853 gettimeofday(&tod, NULL);
854
855 // (roughly) calculate the microseconds since 1970, leftbound
856 micro_seconds = ((uint64_t)(tod.tv_sec) << 32) + ((uint64_t)tod.tv_usec << 12);
857 // more exact but more costly due to the multiplication:
858 // micro_seconds = ((uint64_t)(tod.tv_sec) * 1000000ULL + tod.tv_usec) << 12;
859
860 // extract "counter only" flag (lowest bit)
861 co = (previously_issued_time_stamp << 63) >> 63;
862 // set mask accordingly
863 mask_lo = -co;
864 mask_lo >>= 32;
865 // either 0x00000000FFFFFFFF (if co flag set) or 0x0000000000000000 (if co flag not set)
866
867 mask_lo |= (~mask_lo) >> 52;
868 // either 0x00000000FFFFFFFF (unchanged) or 0x0000000000000FFF (lowest 12 bit set)
869
870 mask_hi = ~mask_lo;
871
872 hi_unchanged = ((previously_issued_time_stamp & mask_hi) == (micro_seconds & mask_hi));
873 // 0 if upper bits unchanged (compared to previous stamp), 1 otherwise
874
875 // read counter and shift right for flags
876 counter = (previously_issued_time_stamp & mask_lo) >> 4;
877
878 counter += hi_unchanged;
879 counter &= -hi_unchanged;
880 // either counter++ if upper part of timestamp unchanged, 0 otherwise
881
882 // back to time stamp format
883 counter <<= 4;
884
885 // set new co flag if counter overflows while upper bits unchanged or if it was set before
886 new_co = (((counter & mask_lo) == 0) & hi_unchanged) | co;
887
888 // in case co flag changed, masks need to be recalculated
889 mask_lo = -new_co;
890 mask_lo >>= 32;
891 mask_lo |= (~mask_lo) >> 52;
892 mask_hi = ~mask_lo;
893
894 // assemble new timestamp
895 micro_seconds &= mask_hi;
896 micro_seconds |= counter;
897 micro_seconds |= new_co;
898
899 previously_issued_time_stamp = micro_seconds;
900
901 return micro_seconds;
902 }
903
904
905 // returns an initial time stamp for use with replay protection
906 uint64_t initial_time_stamp (void) {
907
908 return time_stamp() - TIME_STAMP_FRAME;
909 }
910
911
912 // checks if a provided time stamp is consistent with current time and previously valid time stamps
913 // and, in case of validity, updates the "last valid time stamp"
914 int time_stamp_verify_and_update (uint64_t stamp, uint64_t *previous_stamp, int allow_jitter) {
915
916 int64_t diff; /* do not change to unsigned */
917 uint64_t co; /* counter only mode (for sub-seconds) */
918
919 co = (stamp << 63) >> 63;
920
921 // is it around current time (+/- allowed deviation TIME_STAMP_FRAME)?
922 diff = stamp - time_stamp();
923 // abs()
924 diff = (diff < 0 ? -diff : diff);
925 if(diff >= TIME_STAMP_FRAME) {
926 traceEvent(TRACE_DEBUG, "time_stamp_verify_and_update found a timestamp out of allowed frame.");
927 return 0; // failure
928 }
929
930 // if applicable: is it higher than previous time stamp (including allowed deviation of TIME_STAMP_JITTER)?
931 if(NULL != previous_stamp) {
932 diff = stamp - *previous_stamp;
933 if(allow_jitter) {
934 // 8 times higher jitter allowed for counter-only flagged timestamps ( ~ 1.25 sec with 160 ms default jitter)
935 diff += TIME_STAMP_JITTER << (co << 3);
936 }
937
938 if(diff <= 0) {
939 traceEvent(TRACE_DEBUG, "time_stamp_verify_and_update found a timestamp too old compared to previous.");
940 return 0; // failure
941 }
942 // for not allowing to exploit the allowed TIME_STAMP_JITTER to "turn the clock backwards",
943 // set the higher of the values
944 *previous_stamp = (stamp > *previous_stamp ? stamp : *previous_stamp);
945 }
946
947 return 1; // success
948 }