-int tap_fd = -1;
-int taptype = TAP_TYPE_ETHERTAP;
-int total_tap_in = 0;
-int total_tap_out = 0;
-int total_socket_in = 0;
-int total_socket_out = 0;
-
-config_t *upstreamcfg;
-static int seconds_till_retry;
-
-int keylifetime = 0;
-int keyexpires = 0;
-
-char *unknown = NULL;
-
-subnet_t mymac;
-
-int xsend(connection_t *cl, vpn_packet_t *inpkt)
-{
- vpn_packet_t outpkt;
- int outlen, outpad;
- EVP_CIPHER_CTX ctx;
- struct sockaddr_in to;
- socklen_t tolen = sizeof(to);
-cp
- outpkt.len = inpkt->len;
-
- /* Encrypt the packet */
-
- EVP_EncryptInit(&ctx, cl->cipher_pkttype, cl->cipher_pktkey, cl->cipher_pktkey + cl->cipher_pkttype->key_len);
- EVP_EncryptUpdate(&ctx, outpkt.data, &outlen, inpkt->data, inpkt->len);
- EVP_EncryptFinal(&ctx, outpkt.data + outlen, &outpad);
- outlen += outpad + 2;
-
-/* Bypass
- outlen = outpkt.len + 2;
- memcpy(&outpkt, inpkt, outlen);
-*/
-
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
- outlen, cl->name, cl->hostname);
-
- total_socket_out += outlen;
-
- to.sin_family = AF_INET;
- to.sin_addr.s_addr = htonl(cl->address);
- to.sin_port = htons(cl->port);
-
- if((sendto(myself->socket, (char *) &(outpkt.len), outlen, 0, (const struct sockaddr *)&to, tolen)) < 0)
- {
- syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"),
- cl->name, cl->hostname);
- return -1;
- }
-cp
- return 0;
-}
-
-int xrecv(connection_t *cl, vpn_packet_t *inpkt)
-{
- vpn_packet_t outpkt;
- int outlen, outpad;
- EVP_CIPHER_CTX ctx;
-cp
- outpkt.len = inpkt->len;
-
- /* Decrypt the packet */
-
- EVP_DecryptInit(&ctx, myself->cipher_pkttype, myself->cipher_pktkey, myself->cipher_pktkey + myself->cipher_pkttype->key_len);
- EVP_DecryptUpdate(&ctx, outpkt.data, &outlen, inpkt->data, inpkt->len + 8);
- EVP_DecryptFinal(&ctx, outpkt.data + outlen, &outpad);
- outlen += outpad;
-
-/* Bypass
- outlen = outpkt.len+2;
- memcpy(&outpkt, inpkt, outlen);
-*/
-
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_ERR, _("Writing packet of %d bytes to tap device"),
- outpkt.len, outlen);
-
- /* Fix mac address */
-
- memcpy(outpkt.data, mymac.net.mac.address.x, 6);
-
- if(taptype == TAP_TYPE_TUNTAP)
- {
- if(write(tap_fd, outpkt.data, outpkt.len) < 0)
- syslog(LOG_ERR, _("Can't write to tun/tap device: %m"));
- else
- total_tap_out += outpkt.len;
- }
- else /* ethertap */
- {
- if(write(tap_fd, outpkt.data - 2, outpkt.len + 2) < 0)
- syslog(LOG_ERR, _("Can't write to ethertap device: %m"));
- else
- total_tap_out += outpkt.len + 2;
- }
-cp
- return 0;
-}
-
-/*
- add the given packet of size s to the
- queue q, be it the send or receive queue
-*/
-void add_queue(packet_queue_t **q, void *packet, size_t s)
-{
- queue_element_t *e;
-cp
- e = xmalloc(sizeof(*e));
- e->packet = xmalloc(s);
- memcpy(e->packet, packet, s);
-
- if(!*q)
- {
- *q = xmalloc(sizeof(**q));
- (*q)->head = (*q)->tail = NULL;
- }
-
- e->next = NULL; /* We insert at the tail */
-
- if((*q)->tail) /* Do we have a tail? */
- {
- (*q)->tail->next = e;
- e->prev = (*q)->tail;
- }
- else /* No tail -> no head too */
- {
- (*q)->head = e;
- e->prev = NULL;
- }
-
- (*q)->tail = e;
-cp
-}
-
-/* Remove a queue element */
-void del_queue(packet_queue_t **q, queue_element_t *e)
-{
-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(connection_t *cl, packet_queue_t **pq,
- int (*function)(connection_t*,vpn_packet_t*))
-{
- 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 >= DEBUG_TRAFFIC)
- 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(connection_t *cl)
-{
-cp
- if(cl->sq)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_DEBUG, _("Flushing send queue for %s (%s)"),
- cl->name, cl->hostname);
- flush_queue(cl, &(cl->sq), xsend);
- }
-
- if(cl->rq)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_DEBUG, _("Flushing receive queue for %s (%s)"),
- cl->name, cl->hostname);
- 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)
-{
- connection_t *cl;
- subnet_t *subnet;
-cp
- if((subnet = lookup_subnet_ipv4(to)) == NULL)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- {
- syslog(LOG_NOTICE, _("Trying to look up %d.%d.%d.%d in connection list failed!"),
- IP_ADDR_V(to));
- }
-
- return -1;
- }
-
- cl = subnet->owner;
-
- if(cl == myself)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- {
- syslog(LOG_NOTICE, _("Packet with destination %d.%d.%d.%d is looping back to us!"),
- IP_ADDR_V(to));
- }
-
- return -1;
- }
-
- /* If we ourselves have indirectdata flag set, we should send only to our uplink! */
-
- /* FIXME - check for indirection and reprogram it The Right Way(tm) this time. */
-
- if(!cl->status.validkey)
- {
-/* FIXME: Don't queue until everything else is fixed.
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
- cl->name, cl->hostname);
- add_queue(&(cl->sq), packet, packet->len + 2);
-*/
- if(!cl->status.waitingforkey)
- send_req_key(myself, cl); /* Keys should be sent to the host running the tincd */
- return 0;
- }
-
- if(!cl->status.active)
- {
-/* FIXME: Don't queue until everything else is fixed.
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("%s (%s) is not ready, queueing packet"),
- cl->name, cl->hostname);
- add_queue(&(cl->sq), packet, packet->len + 2);
-*/
- 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;
-#ifdef HAVE_LINUX
-# ifdef HAVE_TUNTAP
- struct ifreq ifr;
-# endif
-#endif
-
-cp
- if((cfg = get_config_val(config, config_tapdevice)))
- tapfname = cfg->data.ptr;
- else
- {
-#ifdef HAVE_LINUX
-# ifdef HAVE_TUNTAP
- tapfname = "/dev/misc/net/tun";
-# else
- tapfname = "/dev/tap0";
-# endif
-#endif
-#ifdef HAVE_FREEBSD
- tapfname = "/dev/tap0";
-#endif
-#ifdef HAVE_SOLARIS
- tapfname = "/dev/tun";
-#endif
- }
-cp
- if((nfd = open(tapfname, O_RDWR | O_NONBLOCK)) < 0)
- {
- syslog(LOG_ERR, _("Could not open %s: %m"), tapfname);
- return -1;
- }
-cp
- tap_fd = nfd;
-
- taptype = TAP_TYPE_ETHERTAP;
-
- /* Set default MAC address for ethertap devices */
-
- mymac.type = SUBNET_MAC;
- mymac.net.mac.address.x[0] = 0xfe;
- mymac.net.mac.address.x[1] = 0xfd;
- mymac.net.mac.address.x[2] = 0x00;
- mymac.net.mac.address.x[3] = 0x00;
- mymac.net.mac.address.x[4] = 0x00;
- mymac.net.mac.address.x[5] = 0x00;
-
-#ifdef HAVE_LINUX
- #ifdef HAVE_TUNTAP
- /* Ok now check if this is an old ethertap or a new tun/tap thingie */
- memset(&ifr, 0, sizeof(ifr));
-cp
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (netname)
- strncpy(ifr.ifr_name, netname, IFNAMSIZ);
-cp
- if (!ioctl(tap_fd, TUNSETIFF, (void *) &ifr))
- {
- syslog(LOG_INFO, _("%s is a new style tun/tap device"), tapfname);
- taptype = TAP_TYPE_TUNTAP;
- }
- #endif
-#endif
-#ifdef HAVE_FREEBSD
- taptype = TAP_TYPE_TUNTAP;