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