-/*
- 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 >= 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)
-{
- conn_list_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 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.dataopen)
- if(setup_vpn_connection(cl) < 0)
- {
- syslog(LOG_ERR, _("Could not open UDP connection to %s (%s)"),
- cl->name, cl->hostname);
- return -1;
- }
-
- if(!cl->status.validkey)
- {
- 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)
- {
- 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;
- char *envvar;
- struct ifreq ifr;
-
-cp
- if((cfg = get_config_val(config, tapdevice)))
- tapfname = cfg->data.ptr;
- else
-#ifdef HAVE_TUNTAP
- tapfname = "/dev/misc/net/tun";
-#else
- tapfname = "/dev/tap0";
-#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 = 0;
-
-#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 = 1;
-
- if((cfg = get_config_val(config, tapsubnet)) == NULL)
- syslog(LOG_INFO, _("tun/tap device will be left unconfigured"));
- else
- /* Setup inetaddr/netmask etc */;
- }
-#endif
-
- /* Add name of network interface to environment (for scripts) */
-
- ioctl(tap_fd, SIOCGIFNAME, (void *) &ifr);
- asprintf(&envvar, "IFNAME=%s", ifr.ifr_name);
- putenv(envvar);
- free(envvar);
-
-cp
- return 0;
-}
-
-/*
- set up the socket that we listen on for incoming
- (tcp) connections
-*/
-int setup_listen_meta_socket(int port)
-{
- int nfd, flags;
- struct sockaddr_in a;
- const int one = 1;
- config_t const *cfg;
-cp
- if((nfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- {
- syslog(LOG_ERR, _("Creating metasocket failed: %m"));
- return -1;
- }
-
- if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
- {
- syslog(LOG_ERR, _("setsockopt: %m"));
- return -1;
- }
-
- if(setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)))
- {
- syslog(LOG_ERR, _("setsockopt: %m"));
- return -1;
- }
-
- flags = fcntl(nfd, F_GETFL);
- if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- syslog(LOG_ERR, _("fcntl: %m"));
- return -1;
- }
-
- if((cfg = get_config_val(config, interface)))
- {
- if(setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, cfg->data.ptr, strlen(cfg->data.ptr)))
- {
- syslog(LOG_ERR, _("Unable to bind listen socket to interface %s: %m"), cfg->data.ptr);
- return -1;
- }
- }
-
- memset(&a, 0, sizeof(a));
- a.sin_family = AF_INET;
- a.sin_port = htons(port);
-
- if((cfg = get_config_val(config, interfaceip)))
- a.sin_addr.s_addr = htonl(cfg->data.ip->address);
- else
- a.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
- {
- syslog(LOG_ERR, _("Can't bind to port %hd/tcp: %m"), port);
- return -1;
- }
-
- if(listen(nfd, 3))
- {
- syslog(LOG_ERR, _("listen: %m"));
- return -1;
- }
-cp
- return nfd;