"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.
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 }