-RETSIGTYPE
-sigalrm_handler(int a)
-{
- config_t const *cfg;
-cp
- cfg = get_config_val(upstreamip);
-
- if(!setup_outgoing_connection(cfg->data.ip->ip))
- {
- signal(SIGALRM, SIG_IGN);
- }
- else
- {
- signal(SIGALRM, sigalrm_handler);
- seconds_till_retry += 5;
- if(seconds_till_retry>300) /* Don't wait more than 5 minutes. */
- seconds_till_retry = 300;
- alarm(seconds_till_retry);
- syslog(LOG_ERR, _("Still failed to connect to other. Will retry in %d seconds."),
- seconds_till_retry);
- }
-cp
-}
-
-/*
- setup all initial network connections
-*/
-int setup_network_connections(void)
-{
- config_t const *cfg;
-cp
- if((cfg = get_config_val(pingtimeout)) == NULL)
- timeout = 5;
- else
- timeout = cfg->data.val;
-
- if(setup_tap_fd() < 0)
- return -1;
-
- if(setup_myself() < 0)
- return -1;
-
- if((cfg = get_config_val(upstreamip)) == NULL)
- /* No upstream IP given, we're listen only. */
- return 0;
-
- if(setup_outgoing_connection(cfg->data.ip->ip))
- {
- signal(SIGALRM, sigalrm_handler);
- seconds_till_retry = 300;
- alarm(seconds_till_retry);
- syslog(LOG_NOTICE, _("Try to re-establish outgoing connection in 5 minutes."));
- }
-cp
- return 0;
-}
-
-/*
- close all open network connections
-*/
-void close_network_connections(void)
-{
- conn_list_t *p;
-cp
- for(p = conn_list; p != NULL; p = p->next)
- {
- if(p->status.dataopen)
- {
- shutdown(p->socket, 0); /* No more receptions */
- close(p->socket);
- }
- if(p->status.meta)
- {
- send_termreq(p);
- shutdown(p->meta_socket, 0); /* No more receptions */
- close(p->meta_socket);
- }
- }
-
- if(myself)
- if(myself->status.active)
- {
- close(myself->meta_socket);
- close(myself->socket);
- }
-
- close(tap_fd);
- destroy_conn_list();
-
- syslog(LOG_NOTICE, _("Terminating."));
-cp
- return;
-}
-
-/*
- create a data (udp) socket
-*/
-int setup_vpn_connection(conn_list_t *cl)
-{
- int nfd, flags;
- struct sockaddr_in a;
-cp
- if(debug_lvl > 1)
- syslog(LOG_DEBUG, _("Opening UDP socket to " IP_ADDR_S), IP_ADDR_V(cl->real_ip));
-
- nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if(nfd == -1)
- {
- syslog(LOG_ERR, _("Creating data 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(nfd, (struct sockaddr *)&a, sizeof(a)) == -1)
- {
- syslog(LOG_ERR, _("Connecting to " IP_ADDR_S ":%d failed: %m"),
- IP_ADDR_V(cl->real_ip), cl->port);
- return -1;
- }
-
- flags = fcntl(nfd, F_GETFL);
- if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m"), __FILE__, __LINE__, nfd);
- return -1;
- }
-
- cl->socket = nfd;
- cl->status.dataopen = 1;
-cp
- return 0;
-}
-
-/*
- handle an incoming tcp connect call and open
- a connection to it.
-*/
-conn_list_t *create_new_connection(int sfd)
-{
- conn_list_t *p;
- struct sockaddr_in ci;
- int len = sizeof(ci);
-cp
- p = new_conn_list();
-
- if(getpeername(sfd, &ci, &len) < 0)
- {
- syslog(LOG_ERR, _("Error: getpeername: %m"));
- return NULL;
- }
-
- p->hostname = hostlookup(ci.sin_addr.s_addr);
- p->real_ip = ntohl(ci.sin_addr.s_addr);
- p->meta_socket = sfd;
- p->status.meta = 1;
- p->buflen = 0;
- p->last_ping_time = time(NULL);
- p->want_ping = 0;
-
- syslog(LOG_NOTICE, _("Connection from %s:%d"), p->hostname, htons(ci.sin_port));
-
- if(send_basic_info(p) < 0)
- {
- free(p);
- return NULL;
- }
-cp
- return p;
-}
-
-/*
- put all file descriptors in an fd_set array
-*/
-void build_fdset(fd_set *fs)
-{
- conn_list_t *p;
-cp
- FD_ZERO(fs);
-
- for(p = conn_list; p != NULL; p = p->next)
- {
- if(p->status.meta)
- FD_SET(p->meta_socket, fs);
- if(p->status.dataopen)
- FD_SET(p->socket, fs);
- }
-
- FD_SET(myself->meta_socket, fs);
- FD_SET(myself->socket, fs);
- FD_SET(tap_fd, fs);
-cp
-}
-
-/*
- receive incoming data from the listening
- udp socket and write it to the ethertap
- device after being decrypted
-*/
-int handle_incoming_vpn_data(conn_list_t *cl)
-{
- real_packet_t rp;
- int lenin;
- int x, l = sizeof(x);
- conn_list_t *f;
-cp
- if(getsockopt(cl->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
- {
- syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m"), __FILE__, __LINE__, cl->socket);
- return -1;
- }
- if(x)
- {
- syslog(LOG_ERR, _("Incoming data socket error: %s"), sys_errlist[x]);
- return -1;
- }
-
- rp.len = -1;
- lenin = recvfrom(cl->socket, &rp, MTU, 0, NULL, NULL);
- if(lenin <= 0)
- {
- syslog(LOG_ERR, _("Receiving data failed: %m"));
- return -1;
- }
- total_socket_in += lenin;
-
- rp.data.len = ntohs(rp.data.len);
- rp.len = ntohs(rp.len);
- rp.from = ntohl(rp.from);
-
- if(rp.len >= 0)
- {
- f = lookup_conn(rp.from);
- if(debug_lvl > 3)
- syslog(LOG_DEBUG, _("packet from " IP_ADDR_S " (len %d)"),
- IP_ADDR_V(rp.from), rp.len);
- if(!f)
- {
- syslog(LOG_ERR, _("Got packet from unknown source " IP_ADDR_S),
- IP_ADDR_V(rp.from));
- return -1;
- }
-
- if(f->status.validkey)
- xrecv(f, &rp);
- else
- {
- add_queue(&(f->rq), &rp, rp.len);
- if(!cl->status.waitingforkey)
- send_key_request(rp.from);