"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(&param->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(&param->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(&param->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(&param->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 }