-int handle_incoming_meta_data(conn_list_t *cl)
-{
- int x, l = sizeof(x), lenin;
- unsigned char tmp[1600];
- int request;
-
- if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
- {
- syslog(LOG_ERR, "This is a bug: %s:%d: %d:%m", __FILE__, __LINE__, cl->meta_socket);
- return -1;
- }
- if(x)
- {
- syslog(LOG_ERR, "Metadata socket error: %s", sys_errlist[x]);
- return -1;
- }
-
- if((lenin = recv(cl->meta_socket, &tmp, sizeof(tmp), 0)) <= 0)
- {
- syslog(LOG_ERR, "Receive failed: %m");
- return -1;
- }
-
- request = (int)(tmp[0]);
-
- if(debug_lvl > 3)
- syslog(LOG_DEBUG, "got request %d", request);
-
- if(request_handlers[request] == NULL)
- syslog(LOG_ERR, "Unknown request %d.", request);
- else
- if(request_handlers[request](cl, tmp, lenin) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- check all connections to see if anything
- happened on their sockets
-*/
-void check_network_activity(fd_set *f)
-{
- conn_list_t *p;
- int x, l = sizeof(x);
-
- for(p = conn_list; p != NULL; p = p->next)
- {
- if(p->status.remove)
- continue;
-cp
- if(p->status.active)
- if(FD_ISSET(p->socket, f))
- {
- /*
- The only thing that can happen to get us here is apparently an
- error on this outgoing(!) UDP socket that isn't immediate (i.e.
- something that will not trigger an error directly on send()).
- I've once got here when it said `No route to host'.
- */
- getsockopt(p->socket, SOL_SOCKET, SO_ERROR, &x, &l);
- syslog(LOG_ERR, "Outgoing data socket error: %s", sys_errlist[x]);
- terminate_connection(p);
- return;
- }
-cp
- if(p->status.meta)
- if(FD_ISSET(p->meta_socket, f))
- if(handle_incoming_meta_data(p) < 0)
- {
- terminate_connection(p);
- return;
- }
-cp
- }
-
-cp
- if(FD_ISSET(myself->socket, f))
- handle_incoming_vpn_data(myself);
-cp
- if(FD_ISSET(myself->meta_socket, f))
- handle_new_meta_connection(myself);
-cp
-}
-
-/*
- read, encrypt and send data that is
- available through the ethertap device
-*/
-void handle_tap_input(void)
-{
- vpn_packet_t vp;
- ip_t from, to;
- int ether_type, lenin;
-
- memset(&vp, 0, sizeof(vp));
- if((lenin = read(tap_fd, &vp, MTU)) <= 0)
- {
- syslog(LOG_ERR, "Error while reading from tapdevice: %m");
- return;
- }
-
- total_tap_in += lenin;
-
- ether_type = ntohs(*((unsigned short*)(&vp.data[12])));
- if(ether_type != 0x0800)
- {
- if(debug_lvl > 0)
- syslog(LOG_INFO, "Non-IP ethernet frame %04x from " MAC_ADDR_S,
- ether_type, MAC_ADDR_V(vp.data[6]));
- return;
- }
-
- if(lenin < 32)
- {
- if(debug_lvl > 0)
- syslog(LOG_INFO, "Dropping short packet");
- return;
- }
-
- from = ntohl(*((unsigned long*)(&vp.data[26])));
- to = ntohl(*((unsigned long*)(&vp.data[30])));
-
- if(debug_lvl > 2)
- syslog(LOG_DEBUG, "An IP packet (%04x) for " IP_ADDR_S " from " IP_ADDR_S,
- ether_type, IP_ADDR_V(to), IP_ADDR_V(from));
- if(debug_lvl > 3)
- syslog(LOG_DEBUG, MAC_ADDR_S " to " MAC_ADDR_S,
- MAC_ADDR_V(vp.data[0]), MAC_ADDR_V(vp.data[6]));
-
- vp.len = (length_t)lenin - 2;
-cp
- strip_mac_addresses(&vp);
-cp
- send_packet(to, &vp);
-cp
-}
-
-/*
- this is where it al happens...
-*/
-void main_loop(void)
-{
- fd_set fset;
- struct timeval tv;
- int r;
-
- last_ping_time = time(NULL);
-
- for(;;)
- {
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
-
-cp
- prune_conn_list();
-cp
- build_fdset(&fset);
-cp
-
- if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0)
- {
- if(errno == EINTR) /* because of alarm */
- continue;
- syslog(LOG_ERR, "Error while waiting for input: %m");
- return;
- }
-cp
-
- if(r == 0 || last_ping_time + timeout < time(NULL))
- /* Timeout... hm... something might be wrong. */
- {
- check_dead_connections();
- send_broadcast_ping();
- continue;
+int main_loop(void) {
+ timeout_t pingtimer = {{0}};
+ timeout_t periodictimer = {{0}};
+
+ timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
+ timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
+
+#ifndef HAVE_MINGW
+ signal_t sighup = {0};
+ signal_t sigterm = {0};
+ signal_t sigquit = {0};
+ signal_t sigint = {0};
+ signal_t sigalrm = {0};
+
+ signal_add(&sighup, sighup_handler, &sighup, SIGHUP);
+ signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM);
+ signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT);
+ signal_add(&sigint, sigterm_handler, &sigint, SIGINT);
+ signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM);
+#endif
+
+ if(!event_loop()) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
+ return 1;