-/*
- 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;
-cp
- 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 > 3)
- 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 > 4)
- 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;
-
- strip_mac_addresses(&vp);
-
- send_packet(to, &vp);
-cp
+static void sighup_handler(void *data) {
+ logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
+ reopenlogger();
+
+ if(reload_configuration()) {
+ exit(1);
+ }
+}
+
+static void sigalrm_handler(void *data) {
+ logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
+ retry();
+}
+#endif
+
+int reload_configuration(void) {
+ char fname[PATH_MAX];
+
+ /* Reread our own configuration file */
+
+ splay_empty_tree(&config_tree);
+
+ if(!read_server_config(&config_tree)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file.");
+ return EINVAL;
+ }
+
+ read_config_options(&config_tree, NULL);
+
+ snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
+ read_config_file(&config_tree, fname, true);
+
+ /* Parse some options that are allowed to be changed while tinc is running */
+
+ setup_myself_reloadable();
+
+ /* If StrictSubnet is set, expire deleted Subnets and read new ones in */
+
+ if(strictsubnets) {
+ for splay_each(subnet_t, subnet, &subnet_tree)
+ if(subnet->owner) {
+ subnet->expires = 1;
+ }
+ }
+
+ for splay_each(node_t, n, &node_tree) {
+ n->status.has_address = false;
+ }
+
+ load_all_nodes();
+
+ if(strictsubnets) {
+ for splay_each(subnet_t, subnet, &subnet_tree) {
+ if(!subnet->owner) {
+ continue;
+ }
+
+ if(subnet->expires == 1) {
+ send_del_subnet(everyone, subnet);
+
+ if(subnet->owner->status.reachable) {
+ subnet_update(subnet->owner, subnet, false);
+ }
+
+ subnet_del(subnet->owner, subnet);
+ } else if(subnet->expires == -1) {
+ subnet->expires = 0;
+ } else {
+ send_add_subnet(everyone, subnet);
+
+ if(subnet->owner->status.reachable) {
+ subnet_update(subnet->owner, subnet, true);
+ }
+ }
+ }
+ } else { /* Only read our own subnets back in */
+ for splay_each(subnet_t, subnet, &myself->subnet_tree)
+ if(!subnet->expires) {
+ subnet->expires = 1;
+ }
+
+ config_t *cfg = lookup_config(&config_tree, "Subnet");
+
+ while(cfg) {
+ subnet_t *subnet, *s2;
+
+ if(get_config_subnet(cfg, &subnet)) {
+ if((s2 = lookup_subnet(myself, subnet))) {
+ if(s2->expires == 1) {
+ s2->expires = 0;
+ }
+
+ free_subnet(subnet);
+ } else {
+ subnet_add(myself, subnet);
+ send_add_subnet(everyone, subnet);
+ subnet_update(myself, subnet, true);
+ }
+ }
+
+ cfg = lookup_config_next(&config_tree, cfg);
+ }
+
+ for splay_each(subnet_t, subnet, &myself->subnet_tree) {
+ if(subnet->expires == 1) {
+ send_del_subnet(everyone, subnet);
+ subnet_update(myself, subnet, false);
+ subnet_del(myself, subnet);
+ }
+ }
+ }
+
+ /* Try to make outgoing connections */
+
+ try_outgoing_connections();
+
+ /* Close connections to hosts that have a changed or deleted host config file */
+
+ for list_each(connection_t, c, &connection_list) {
+ if(c->status.control) {
+ continue;
+ }
+
+ snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
+ struct stat s;
+
+ if(stat(fname, &s) || s.st_mtime > last_config_check) {
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
+ terminate_connection(c, c->edge);
+ }
+ }
+
+ last_config_check = now.tv_sec;
+
+ return 0;
+}
+
+void retry(void) {
+ /* Reset the reconnection timers for all outgoing connections */
+ for list_each(outgoing_t, outgoing, &outgoing_list) {
+ outgoing->timeout = 0;
+
+ if(outgoing->ev.cb)
+ timeout_set(&outgoing->ev, &(struct timeval) {
+ 0, 0
+ });
+ }
+
+ /* Check for outgoing connections that are in progress, and reset their ping timers */
+ for list_each(connection_t, c, &connection_list) {
+ if(c->outgoing && !c->node) {
+ c->last_ping_time = 0;
+ }
+ }
+
+ /* Kick the ping timeout handler */
+ timeout_set(&pingtimer, &(struct timeval) {
+ 0, 0
+ });