Exemplo n.º 1
0
/*---------------------------------------------------------------------------*/
void
route_decay(struct route_entry *e)
{
  /* If routes are not refreshed, they decay over time. This function
     is called to decay a route. The route can only be decayed once
     per second. */
  PRINTF("route_decay: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n",
	 e->time, e->time_last_decay, e->decay,
	 e->dest.u8[0], e->dest.u8[1],
	 e->nexthop.u8[0], e->nexthop.u8[1],
	 e->cost);
  
  if(e->time != e->time_last_decay) {
    /* Do not decay a route too often - not more than once per second. */
    e->time_last_decay = e->time;
    e->decay++;

    if(e->decay >= DECAY_THRESHOLD) {
      PRINTF("route_decay: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
	     e->dest.u8[0], e->dest.u8[1],
	     e->nexthop.u8[0], e->nexthop.u8[1],
	     e->cost);
      route_remove(e);
    }
  }
}
Exemplo n.º 2
0
/* Add route into kernel */
int route_add(ARPTAB_ENTRY* cur_entry)
{
    char routecmd_str[ROUTE_CMD_LEN];
    int success = 1;

    if (snprintf(routecmd_str, ROUTE_CMD_LEN-1, 
	    "ip route add %s/32 metric 50 dev %s scope link",
	    inet_ntoa(cur_entry->ipaddr_ia), cur_entry->ifname) > ROUTE_CMD_LEN-1) 
    {
	syslog(LOG_INFO, "ip route command too large to fit in buffer!");
    } else {
	if (system(routecmd_str) != 0)
	{ 
	    syslog(LOG_INFO, "'%s' unsuccessful, will try to remove!", routecmd_str); 
	    if (debug) printf("%s failed\n", routecmd_str);
	    route_remove(cur_entry);
	    success = 0;
	}
	else
	{
	    if (debug) printf("%s success\n", routecmd_str);
	    success = 1;
	}
    }
    if (success)
	cur_entry->route_added = 1;

    return success;
}
Exemplo n.º 3
0
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
        Route *route = userdata;
        int r;

        assert(route);

        r = route_remove(route, route->link, route_expire_callback);
        if (r < 0)
                log_warning_errno(r, "Could not remove route: %m");
        else
                route_free(route);

        return 1;
}
Exemplo n.º 4
0
void processarp(int in_cleanup) 
{
    ARPTAB_ENTRY *cur_entry=*arptab, *prev_entry=NULL;

    /* First loop to remove unwanted routes */
    while (cur_entry != NULL) {
	if (debug && verbose) printf("Working on route %s(%s) tstamp %u want_route %d\n", inet_ntoa(cur_entry->ipaddr_ia), cur_entry->ifname, (int) cur_entry->tstamp, cur_entry->want_route);

	if ( !cur_entry->want_route
	    || time(NULL) - cur_entry->tstamp > ARP_TABLE_ENTRY_TIMEOUT 
	    || in_cleanup)  {
	    
	    if (cur_entry->route_added)
		route_remove(cur_entry);

	    /* remove from arp list */
	    if (debug) printf("Delete arp %s(%s)\n", inet_ntoa(cur_entry->ipaddr_ia), cur_entry->ifname);
		
	    if (prev_entry != NULL) {
	        prev_entry->next = cur_entry->next;
	        free(cur_entry);
	        cur_entry=prev_entry->next;
	    } else {
	        *arptab = cur_entry->next;
	        free(cur_entry);
        	cur_entry=*arptab;
            }
	} else {
    	    prev_entry = cur_entry;
	    cur_entry = cur_entry->next;
	}	
    } /* while loop */

    /* Now loop to add new routes */
    cur_entry=*arptab;
    while (cur_entry != NULL) {
	if (time(NULL) - cur_entry->tstamp <= ARP_TABLE_ENTRY_TIMEOUT 
		&& cur_entry->want_route
		&& !cur_entry->route_added 
		&& !in_cleanup) 
	{
	    /* add route to the kernel */
	    route_add(cur_entry);
	}
	cur_entry = cur_entry->next;
    } /* while loop */

}	
Exemplo n.º 5
0
static int ipv4ll_address_lost(Link *link) {
        _cleanup_address_free_ Address *address = NULL;
        _cleanup_route_free_ Route *route = NULL;
        struct in_addr addr;
        int r;

        assert(link);

        link->ipv4ll_route = false;
        link->ipv4ll_address = false;

        r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
        if (r < 0)
                return 0;

        log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));

        r = address_new(&address);
        if (r < 0) {
                log_link_error_errno(link, r, "Could not allocate address: %m");
                return r;
        }

        address->family = AF_INET;
        address->in_addr.in = addr;
        address->prefixlen = 16;
        address->scope = RT_SCOPE_LINK;

        address_remove(address, link, &link_address_remove_handler);

        r = route_new(&route);
        if (r < 0) {
                log_link_error_errno(link, r, "Could not allocate route: %m");
                return r;
        }

        route->family = AF_INET;
        route->scope = RT_SCOPE_LINK;
        route->priority = IPV4LL_ROUTE_METRIC;

        route_remove(route, link, &link_route_remove_handler);

        link_check_ready(link);

        return 0;
}
Exemplo n.º 6
0
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
        Route *route = userdata;
        int r;

        assert(route);

        r = route_remove(route, route->link, route_expire_callback);
        if (r < 0)
                log_warning_errno(r, "Could not remove route: %m");
        else {
                /* route may not be exist in kernel. If we fail still remove it */
                route->link->link_messages++;
                route_free(route);
        }

        return 1;
}
Exemplo n.º 7
0
static int dhcp_lease_lost(Link *link) {
        _cleanup_address_free_ Address *address = NULL;
        struct in_addr addr;
        struct in_addr netmask;
        struct in_addr gateway;
        unsigned prefixlen = 0;
        int r;

        assert(link);
        assert(link->dhcp_lease);

        log_link_warning(link, "DHCP lease lost");

        if (link->network->dhcp_use_routes) {
                _cleanup_free_ sd_dhcp_route **routes = NULL;
                int n, i;

                n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
                if (n >= 0) {
                        for (i = 0; i < n; i++) {
                                _cleanup_route_free_ Route *route = NULL;

                                r = route_new(&route);
                                if (r >= 0) {
                                        route->family = AF_INET;
                                        assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
                                        assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
                                        assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);

                                        route_remove(route, link,
                                                     link_route_remove_handler);
                                }
                        }
                }
        }

        r = address_new(&address);
        if (r >= 0) {
                r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
                if (r >= 0) {
                        _cleanup_route_free_ Route *route_gw = NULL;
                        _cleanup_route_free_ Route *route = NULL;

                        r = route_new(&route_gw);
                        if (r >= 0) {
                                route_gw->family = AF_INET;
                                route_gw->dst.in = gateway;
                                route_gw->dst_prefixlen = 32;
                                route_gw->scope = RT_SCOPE_LINK;

                                route_remove(route_gw, link,
                                             link_route_remove_handler);
                        }

                        r = route_new(&route);
                        if (r >= 0) {
                                route->family = AF_INET;
                                route->gw.in = gateway;

                                route_remove(route, link,
                                             link_route_remove_handler);
                        }
                }

                r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
                if (r >= 0) {
                        r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
                        if (r >= 0)
                                prefixlen = in_addr_netmask_to_prefixlen(&netmask);

                        address->family = AF_INET;
                        address->in_addr.in = addr;
                        address->prefixlen = prefixlen;

                        address_remove(address, link, link_address_remove_handler);
                }
        }

        if (link->network->dhcp_use_mtu) {
                uint16_t mtu;

                r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
                if (r >= 0 && link->original_mtu != mtu) {
                        r = link_set_mtu(link, link->original_mtu);
                        if (r < 0) {
                                log_link_warning(link,
                                                 "DHCP error: could not reset MTU");
                                link_enter_failed(link);
                                return r;
                        }
                }
        }

        if (link->network->dhcp_use_hostname) {
                const char *hostname = NULL;

                if (link->network->dhcp_hostname)
                        hostname = link->network->dhcp_hostname;
                else
                        (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);

                if (hostname) {
                        /* If a hostname was set due to the lease, then unset it now. */
                        r = manager_set_hostname(link->manager, NULL);
                        if (r < 0)
                                log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
                }
        }

        link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
        link_dirty(link);
        link->dhcp4_configured = false;

        return 0;
}