- queue_element_t *p, *prev = NULL, *next = NULL;
-
- for(p = pq->head; p != NULL; )
- {
- next = p->next;
-
-cp
- if(!function(cl, p->packet))
- {
- if(prev)
- prev->next = next;
- else
- pq->head = next;
-
-cp
- free(p->packet);
-cp
- free(p);
-cp
- }
- else
- prev = p;
-cp
-
- p = next;
- }
-
- if(debug_lvl > 3)
- syslog(LOG_DEBUG, "queue flushed");
-}
-
-/*
- 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);
- }
-cp
-
- 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;
-
- 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)
- {
- syslog(LOG_ERR, "zxnrbl");
- return -1;
- }
- }
-
-cp
- if(my_key_expiry <= time(NULL))
- regenerate_keys();
-
-cp
- if(!cl->status.dataopen)
- if(setup_vpn_connection(cl) < 0)
- return -1;
-cp
-
- if(!cl->status.validkey)
- {
- add_queue(&(cl->sq), packet, packet->len + 2);
- if(!cl->status.waitingforkey)
- send_key_request(to);
- return 0;
- }
-
-cp
- 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);
-}
-
-int send_broadcast(conn_list_t *cl, vpn_packet_t *packet)
-{
- conn_list_t *p;
-
- for(p = cl; p != NULL; p = p->next)
- if(send_packet(p->real_ip, packet) < 0)
- {
- syslog(LOG_ERR, "Could not send a broadcast packet to %08lx (%08lx): %m",
- p->vpn_ip, p->real_ip);
- break; /* FIXME: should retry later, and send a ping over the metaconnection. */
- }
-
- return 0;
-}
-
-/*
- open the local ethertap device
-*/
-int setup_tap_fd(void)
-{
- int nfd;
- const char *tapfname;
- config_t const *cfg;
-
- 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;
- 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;
-
- 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;
- }
-
- flags = fcntl(nfd, F_GETFL);
- if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- syslog(LOG_ERR, "fcntl: %m");
- return -1;
- }
-
- memset(&a, 0, sizeof(a));
- a.sin_family = AF_INET;
- a.sin_port = htons(port);
- 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;
- }
-
- return nfd;
-}
-
-/*
- setup the socket for incoming encrypted
- data (the udp part)
-*/
-int setup_vpn_in_socket(int port)
-{
- int nfd, flags;
- struct sockaddr_in a;
- const int one = 1;
-
- if((nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
- {
- syslog(LOG_ERR, "Creating socket failed: %m");
- return -1;
- }
-
- if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &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;
- }
-
- memset(&a, 0, sizeof(a));
- a.sin_family = AF_INET;
- a.sin_port = htons(port);
- 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/udp: %m", port);
- return -1;
- }
-
- return nfd;
-}
-
-/*
- setup an outgoing meta (tcp) socket
-*/
-int setup_outgoing_meta_socket(conn_list_t *cl)
-{
- int flags;
- struct sockaddr_in a;
- config_t const *cfg;
-
- if((cfg = get_config_val(upstreamport)) == NULL)
- cl->port = 655;
- else
- cl->port = cfg->data.val;
-
- cl->meta_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(cl->meta_socket == -1)
- {
- syslog(LOG_ERR, "Creating socket failed: %m");
- return -1;
- }
-
- a.sin_family = AF_INET;
- a.sin_port = htons(cl->port);
- a.sin_addr.s_addr = htonl(cl->real_ip);
-
- if(connect(cl->meta_socket, (struct sockaddr *)&a, sizeof(a)) == -1)
- {
- syslog(LOG_ERR, IP_ADDR_S ":%d: %m", IP_ADDR_V(cl->real_ip), cl->port);
- return -1;
- }
-
- flags = fcntl(cl->meta_socket, F_GETFL);
- if(fcntl(cl->meta_socket, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- syslog(LOG_ERR, "fcntl: %m");
- return -1;
- }
-
- cl->hostname = hostlookup(htonl(cl->real_ip));
-
- syslog(LOG_INFO, "Connected to %s:%hd" , cl->hostname, cl->port);
-
- return 0;
-}
-
-/*
- setup an outgoing connection. It's not
- necessary to also open an udp socket as
- well, because the other host will initiate
- an authentication sequence during which
- we will do just that.
-*/
-int setup_outgoing_connection(ip_t ip)
-{
- conn_list_t *ncn;
-
- ncn = new_conn_list();
- ncn->real_ip = ip;
-
- if(setup_outgoing_meta_socket(ncn) < 0)
- {
- syslog(LOG_ERR, "Could not set up a meta connection.");
- free_conn_element(ncn);
- return -1;
- }
-
- ncn->status.meta = 1;
- ncn->status.outgoing = 1;
- ncn->next = conn_list;
- conn_list = ncn;
-
- return 0;
-}
-
-/*
- set up the local sockets (listen only)
-*/
-int setup_myself(void)
-{
- config_t const *cfg;
-
- myself = new_conn_list();
-
- if(!(cfg = get_config_val(myvpnip)))
- {
- syslog(LOG_ERR, "No value for my VPN IP given");
- return -1;
- }
-
- myself->vpn_ip = cfg->data.ip->ip;
- myself->vpn_mask = cfg->data.ip->mask;
-
- if(!(cfg = get_config_val(listenport)))
- myself->port = 655;
- else
- myself->port = cfg->data.val;