-cp
- free(e->packet);
-
- if(e->next) /* There is a successor, so we are not tail */
- {
- if(e->prev) /* There is a predecessor, so we are not head */
- {
- e->next->prev = e->prev;
- e->prev->next = e->next;
- }
- else /* We are head */
- {
- e->next->prev = NULL;
- (*q)->head = e->next;
- }
- }
- else /* We are tail (or all alone!) */
- {
- if(e->prev) /* We are not alone :) */
- {
- e->prev->next = NULL;
- (*q)->tail = e->prev;
- }
- else /* Adieu */
- {
- free(*q);
- *q = NULL;
- }
- }
-
- free(e);
-cp
-}
-
-/*
- flush a queue by calling function for
- each packet, and removing it when that
- returned a zero exit code
-*/
-void flush_queue(conn_list_t *cl, packet_queue_t **pq,
- int (*function)(conn_list_t*,void*))
-{
- queue_element_t *p, *next = NULL;
-cp
- for(p = (*pq)->head; p != NULL; )
- {
- next = p->next;
-
- if(!function(cl, p->packet))
- del_queue(pq, p);
-
- p = next;
- }
-
- if(debug_lvl > 3)
- syslog(LOG_DEBUG, _("queue flushed"));
-cp
-}
-
-/*
- flush the send&recv queues
- void because nothing goes wrong here, packets
- remain in the queue if something goes wrong
-*/
-void flush_queues(conn_list_t *cl)
-{
-cp
- if(cl->sq)
- {
- if(debug_lvl > 1)
- syslog(LOG_DEBUG, _("Flushing send queue for " IP_ADDR_S),
- IP_ADDR_V(cl->vpn_ip));
- flush_queue(cl, &(cl->sq), xsend);
- }
-
- if(cl->rq)
- {
- if(debug_lvl > 1)
- syslog(LOG_DEBUG, _("Flushing receive queue for " IP_ADDR_S),
- IP_ADDR_V(cl->vpn_ip));
- flush_queue(cl, &(cl->rq), xrecv);
- }
-cp
-}
-
-/*
- send a packet to the given vpn ip.
-*/
-int send_packet(ip_t to, vpn_packet_t *packet)
-{
- conn_list_t *cl;
-cp
- if((cl = lookup_conn(to)) == NULL)
- {
- if(debug_lvl > 2)
- {
- syslog(LOG_NOTICE, _("trying to look up " IP_ADDR_S " in connection list failed."),
- IP_ADDR_V(to));
- }
- for(cl = conn_list; cl != NULL && !cl->status.outgoing; cl = cl->next);
- if(!cl)
- { /* No open outgoing connection has been found. */
- if(debug_lvl > 2)
- syslog(LOG_NOTICE, _("There is no remote host I can send this packet to."));
- return -1;
- }
- }
-
- if(my_key_expiry <= time(NULL))
- regenerate_keys();
-
- if(!cl->status.dataopen)
- if(setup_vpn_connection(cl) < 0)
- return -1;
-
- if(!cl->status.validkey)
- {
- add_queue(&(cl->sq), packet, packet->len + 2);
- if(!cl->status.waitingforkey)
- send_key_request(cl->vpn_ip); /* Keys should be sent to the host running the tincd */
- return 0;
- }
-
- if(!cl->status.active)
- {
- add_queue(&(cl->sq), packet, packet->len + 2);
- if(debug_lvl > 1)
- syslog(LOG_INFO, _(IP_ADDR_S " is not ready, queueing packet."), IP_ADDR_V(cl->vpn_ip));
- return 0; /* We don't want to mess up, do we? */
- }
-
- /* can we send it? can we? can we? huh? */
-cp
- return xsend(cl, packet);
-}
-
-/*
- open the local ethertap device
-*/
-int setup_tap_fd(void)
-{
- int nfd;
- const char *tapfname;
- config_t const *cfg;
-cp
- if((cfg = get_config_val(tapdevice)) == NULL)
- tapfname = "/dev/tap0";
- else
- tapfname = cfg->data.ptr;
-
- if((nfd = open(tapfname, O_RDWR | O_NONBLOCK)) < 0)
- {
- syslog(LOG_ERR, _("Could not open %s: %m"), tapfname);
- return -1;
- }
-
- tap_fd = nfd;
-cp
- return 0;
+ avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext;
+ node_t *n;
+ edge_t *e;
+ subnet_t *s;
+
+ cp();
+
+ ifdebug(PROTOCOL) logger(LOG_DEBUG, _("Purging unreachable nodes"));
+
+ for(nnode = node_tree->head; nnode; nnode = nnext) {
+ nnext = nnode->next;
+ n = (node_t *) nnode->data;
+
+ if(!n->status.reachable) {
+ ifdebug(SCARY_THINGS) logger(LOG_DEBUG, _("Purging node %s (%s)"), n->name,
+ n->hostname);
+
+ for(snode = n->subnet_tree->head; snode; snode = snext) {
+ snext = snode->next;
+ s = (subnet_t *) snode->data;
+ send_del_subnet(broadcast, s);
+ subnet_del(n, s);
+ }
+
+ for(enode = n->edge_tree->head; enode; enode = enext) {
+ enext = enode->next;
+ e = (edge_t *) enode->data;
+ send_del_edge(broadcast, e);
+ edge_del(e);
+ }
+
+ node_del(n);
+ }
+ }