int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; if (section) { route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { *ret = route; route = NULL; return 0; } } r = route_new(&route); if (r < 0) return r; route->protocol = RTPROT_STATIC; route->network = network; LIST_PREPEND(routes, network->static_routes, route); if (section) { route->section = section; hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route); } *ret = route; route = NULL; return 0; }
static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { _cleanup_route_free_ Route *route = NULL; struct in6_addr gateway; uint16_t lifetime; unsigned preference; usec_t time_now; int r; assert(link); assert(rt); r = sd_ndisc_router_get_lifetime(rt, &lifetime); if (r < 0) { log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); return; } if (lifetime == 0) /* not a default router */ return; r = sd_ndisc_router_get_address(rt, &gateway); if (r < 0) { log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); return; } r = sd_ndisc_router_get_preference(rt, &preference); if (r < 0) { log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); return; } r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); if (r < 0) { log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); return; } r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return; } route->family = AF_INET6; route->table = RT_TABLE_MAIN; route->protocol = RTPROT_RA; route->pref = preference; route->gw.in6 = gateway; route->lifetime = time_now + lifetime * USEC_PER_SEC; r = route_configure(route, link, ndisc_netlink_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set default route: %m"); link_enter_failed(link); return; } link->ndisc_messages++; }
static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { _cleanup_route_free_ Route *route = NULL; usec_t time_now; uint32_t lifetime; unsigned prefixlen; int r; assert(link); assert(rt); r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); if (r < 0) { log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); return; } r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix length: %m"); return; } r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); return; } r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return; } route->family = AF_INET6; route->table = RT_TABLE_MAIN; route->protocol = RTPROT_RA; route->flags = RTM_F_PREFIX; route->dst_prefixlen = prefixlen; route->lifetime = time_now + lifetime * USEC_PER_SEC; r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix address: %m"); return; } r = route_configure(route, link, ndisc_netlink_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set prefix route: %m"); link_enter_failed(link); return; } link->ndisc_messages++; }
static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { _cleanup_address_free_ Address *ll_addr = NULL; _cleanup_route_free_ Route *route = NULL; struct in_addr address; int r; assert(ll); assert(link); r = sd_ipv4ll_get_address(ll, &address); if (r == -ENOENT) return 0; else if (r < 0) return r; log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", ADDRESS_FMT_VAL(address)); r = address_new(&ll_addr); if (r < 0) return r; ll_addr->family = AF_INET; ll_addr->in_addr.in = address; ll_addr->prefixlen = 16; ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen); ll_addr->scope = RT_SCOPE_LINK; r = address_configure(ll_addr, link, ipv4ll_address_handler, false); if (r < 0) return r; link->ipv4ll_address = false; r = route_new(&route); if (r < 0) return r; route->family = AF_INET; route->scope = RT_SCOPE_LINK; route->protocol = RTPROT_STATIC; route->priority = IPV4LL_ROUTE_METRIC; r = route_configure(route, link, ipv4ll_route_handler); if (r < 0) return r; link->ipv4ll_route = false; return 0; }
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) { _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL; _cleanup_route_free_ Route *route = NULL; int r; assert(network); assert(ret); assert(!!filename == (section_line > 0)); if (filename) { r = network_config_section_new(filename, section_line, &n); if (r < 0) return r; route = hashmap_get(network->routes_by_section, n); if (route) { *ret = route; route = NULL; return 0; } } if (network->n_static_routes >= routes_max()) return -E2BIG; r = route_new(&route); if (r < 0) return r; route->protocol = RTPROT_STATIC; if (filename) { route->section = n; n = NULL; r = hashmap_put(network->routes_by_section, route->section, route); if (r < 0) return r; } route->network = network; LIST_PREPEND(routes, network->static_routes, route); network->n_static_routes++; *ret = route; route = NULL; return 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; }
static int route_add_internal( Link *link, Set **routes, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; assert(link); assert(routes); assert(dst); r = route_new(&route); if (r < 0) return r; route->family = family; route->dst = *dst; route->dst_prefixlen = dst_prefixlen; route->tos = tos; route->priority = priority; route->table = table; r = set_ensure_allocated(routes, &route_hash_ops); if (r < 0) return r; r = set_put(*routes, route); if (r < 0) return r; route->link = link; if (ret) *ret = route; route = NULL; return 0; }
int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; assert(network); assert(ret); if (section) { route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { *ret = route; route = NULL; return 0; } } if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX) return -E2BIG; r = route_new(&route); if (r < 0) return r; route->protocol = RTPROT_STATIC; if (section) { route->section = section; r = hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route); if (r < 0) return r; } route->network = network; LIST_PREPEND(routes, network->static_routes, route); network->n_static_routes++; *ret = route; route = NULL; return 0; }
int main(int argc, char **argv) { #if 0 CORBA_Environment ev; CORBA_ORB orb; Map map_client = CORBA_OBJECT_NIL; #endif char *gps; setenv("LC_NUMERIC","C",1); setlocale(LC_ALL,""); setlocale(LC_NUMERIC,"C"); gtk_set_locale(); setlocale(LC_NUMERIC,"C"); debug_init(); gtk_init(&argc, &argv); gdk_rgb_init(); // i18n basic support bindtextdomain( "navit", "./locale" ); textdomain( "navit" ); map_data_default=load_maps(NULL); plugin_load(); co=gui_gtk_window(1300000,7000000,32); co->route=route_new(); route_mapdata_set(co->route, co->map_data); gps=getenv("GPSDATA"); if (gps) { co->vehicle=vehicle_new(gps); if (co->vehicle) { co->cursor=cursor_new(co,co->vehicle); sdl_gui_new(co->vehicle); } } else { g_warning(gettext("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]")); } co->speech=speech_new(); if (! co->speech) g_warning(gettext("Can't connect to speechd, no speech output available")); speech_handle=co->speech; if (co->vehicle) co->compass=compass_new(co); if (co->vehicle) co->track=track_new(co->map_data); #if 0 CORBA_exception_init(&ev); orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); g_assert(ev._major == CORBA_NO_EXCEPTION); map_srv_start_poa(orb, &ev); g_assert(ev._major == CORBA_NO_EXCEPTION); map_client = map_srv_start_object(&ev, map); retval = CORBA_ORB_object_to_string(orb, map_client, &ev); g_assert(ev._major == CORBA_NO_EXCEPTION); ior=fopen("map.ior","w"); if (ior) { fprintf(ior, "%s\n", retval); fclose(ior); } CORBA_free(retval); #endif initSDL(); gtk_main(); return 0; }
static int link_set_dhcp_routes(Link *link) { struct in_addr gateway, address; _cleanup_free_ sd_dhcp_route **static_routes = NULL; int r, n, i; assert(link); assert(link->dhcp_lease); assert(link->network); if (!link->network->dhcp_use_routes) return 0; r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r < 0 && r != -ENODATA) return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); if (r >= 0) { _cleanup_route_free_ Route *route = NULL; _cleanup_route_free_ Route *route_gw = NULL; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->protocol = RTPROT_DHCP; r = route_new(&route_gw); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); /* The dhcp netmask may mask out the gateway. Add an explicit * route for the gw host so that we can route no matter the * netmask or existing kernel route tables. */ route_gw->family = AF_INET; route_gw->dst.in = gateway; route_gw->dst_prefixlen = 32; route_gw->prefsrc.in = address; route_gw->scope = RT_SCOPE_LINK; route_gw->protocol = RTPROT_DHCP; route_gw->priority = link->network->dhcp_route_metric; route_gw->table = link->network->dhcp_route_table; r = route_configure(route_gw, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; route->family = AF_INET; route->gw.in = gateway; route->prefsrc.in = address; route->priority = link->network->dhcp_route_metric; route->table = link->network->dhcp_route_table; r = route_configure(route, link, dhcp4_route_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } link->dhcp4_messages++; } n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); if (n == -ENODATA) return 0; if (n < 0) return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m"); for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET; route->protocol = RTPROT_DHCP; assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); route->priority = link->network->dhcp_route_metric; route->table = link->network->dhcp_route_table; route->scope = route_scope_from_address(route, &address); r = route_configure(route, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; } return 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; }
static int link_set_dhcp_routes(Link *link) { _cleanup_free_ sd_dhcp_route **static_routes = NULL; bool classless_route = false, static_route = false; const struct in_addr *router; struct in_addr address; int r, n, i; uint32_t table; assert(link); if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */ return 0; if (!link->network) /* link went down while we configured the IP addresses? */ return 0; if (!link->network->dhcp_use_routes) return 0; table = link_get_dhcp_route_table(link); r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); if (n == -ENODATA) log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m"); else if (n < 0) log_link_debug_errno(link, n, "DHCP error: could not get routes: %m"); for (i = 0; i < n; i++) { switch (sd_dhcp_route_get_option(static_routes[i])) { case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: classless_route = true; break; case SD_DHCP_OPTION_STATIC_ROUTE: static_route = true; break; } } for (i = 0; i < n; i++) { _cleanup_(route_freep) Route *route = NULL; /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, the DHCP client MUST ignore the Static Routes option. */ if (classless_route && sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE) continue; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET; route->protocol = RTPROT_DHCP; assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); route->priority = link->network->dhcp_route_metric; route->table = table; route->scope = route_scope_from_address(route, &address); r = route_configure(route, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; } r = sd_dhcp_lease_get_router(link->dhcp_lease, &router); if (IN_SET(r, 0, -ENODATA)) log_link_info(link, "DHCP: No gateway received from DHCP server."); else if (r < 0) log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); else if (in4_addr_is_null(&router[0])) log_link_info(link, "DHCP: Received gateway is null."); /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and a Router option, the DHCP client MUST ignore the Router option. */ if (classless_route && static_route) log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) { _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL; r = route_new(&route_gw); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); /* The dhcp netmask may mask out the gateway. Add an explicit * route for the gw host so that we can route no matter the * netmask or existing kernel route tables. */ route_gw->family = AF_INET; route_gw->dst.in = router[0]; route_gw->dst_prefixlen = 32; route_gw->prefsrc.in = address; route_gw->scope = RT_SCOPE_LINK; route_gw->protocol = RTPROT_DHCP; route_gw->priority = link->network->dhcp_route_metric; route_gw->table = table; r = route_configure(route_gw, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET; route->gw.in = router[0]; route->prefsrc.in = address; route->protocol = RTPROT_DHCP; route->priority = link->network->dhcp_route_metric; route->table = table; r = route_configure(route, link, dhcp4_route_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } link->dhcp4_messages++; } return 0; }
void navit_init(struct navit *this_) { struct menu *mapmen,*men,*men2; struct map *map; struct mapset_handle *handle; struct mapset *ms=this_->mapsets->data; if (this_->menubar) { mapmen=menu_add(this_->menubar, "Map", menu_type_submenu, NULL, NULL, NULL); // menu_add(map, "Test", menu_type_menu, NULL, NULL); men=menu_add(mapmen, "Layout", menu_type_submenu, NULL, NULL, NULL); menu_add(men, "Test", menu_type_menu, NULL, NULL, NULL); men=menu_add(mapmen, "Projection", menu_type_submenu, NULL, NULL, NULL); menu_add(men, "M&G", menu_type_menu, navit_projection_set, this_, (void *)projection_mg); menu_add(men, "Garmin", menu_type_menu, navit_projection_set, this_, (void *)projection_garmin); handle=mapset_open(ms); while ((map=mapset_next(handle,0))) { char *s=g_strdup_printf("%s:%s", map_get_type(map), map_get_filename(map)); men2=menu_add(mapmen, s, menu_type_toggle, navit_map_toggle, this_, map); menu_set_toggle(men2, map_get_active(map)); g_free(s); } mapset_close(handle); } { struct mapset *ms=this_->mapsets->data; struct coord c; int pos,flag=0; FILE *f; char buffer[2048]; this_->route=route_new(ms); this_->navigation=navigation_new(ms); dbg(0,"navigation_register_callback(%p, ... %p)\n", this_->navigation, this_); navigation_register_callback(this_->navigation, navigation_mode_long, navit_show_roadbook, this_); #if 1 this_->track=track_new(ms); #endif men=NULL; if (this_->menubar) { men=menu_add(this_->menubar, "Route", menu_type_submenu, NULL, NULL, NULL); men=menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL); } f=fopen("destination.txt", "r"); if (f) { while (! feof(f) && fgets(buffer, 2048, f)) { if ((pos=coord_parse(buffer, projection_mg, &c))) { if (buffer[pos] && buffer[pos] != '\n' ) { struct coord *cn=g_new(struct coord, 1); *cn=c; buffer[strlen(buffer)-1]='\0'; if (men) menu_add(men, buffer+pos+1, menu_type_menu, navit_set_destination_menu, this_, cn); } flag=1; } } fclose(f); if (flag) route_set_destination(this_->route, &c); } } global_navit=this_; }
static int link_set_dhcp_routes(Link *link) { _cleanup_free_ sd_dhcp_route **static_routes = NULL; bool classless_route = false, static_route = false; struct in_addr gateway, address; int r, n, i; uint32_t table; assert(link); if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */ return 0; if (!link->network) /* link went down while we configured the IP addresses? */ return 0; if (!link->network->dhcp_use_routes) return 0; /* When the interface is part of an VRF use the VRFs routing table, unless * there is a another table specified. */ table = link->network->dhcp_route_table; if (!link->network->dhcp_route_table_set && link->network->vrf != NULL) table = VRF(link->network->vrf)->table; r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); if (n < 0) log_link_debug_errno(link, n, "DHCP error: could not get routes: %m"); for (i = 0; i < n; i++) { if (static_routes[i]->option == SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE) classless_route = true; if (static_routes[i]->option == SD_DHCP_OPTION_STATIC_ROUTE) static_route = true; } for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, the DHCP client MUST ignore the Static Routes option. */ if (classless_route && static_routes[i]->option == SD_DHCP_OPTION_STATIC_ROUTE) continue; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET; route->protocol = RTPROT_DHCP; assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); route->priority = link->network->dhcp_route_metric; route->table = table; route->scope = route_scope_from_address(route, &address); r = route_configure(route, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; } r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r == -ENODATA) log_link_info_errno(link, r, "DHCP: No routes received from DHCP server: %m"); else if (r < 0) log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and a Router option, the DHCP client MUST ignore the Router option. */ if (classless_route && static_route) log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); if (r >= 0 && !classless_route) { _cleanup_route_free_ Route *route = NULL; _cleanup_route_free_ Route *route_gw = NULL; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->protocol = RTPROT_DHCP; r = route_new(&route_gw); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); /* The dhcp netmask may mask out the gateway. Add an explicit * route for the gw host so that we can route no matter the * netmask or existing kernel route tables. */ route_gw->family = AF_INET; route_gw->dst.in = gateway; route_gw->dst_prefixlen = 32; route_gw->prefsrc.in = address; route_gw->scope = RT_SCOPE_LINK; route_gw->protocol = RTPROT_DHCP; route_gw->priority = link->network->dhcp_route_metric; route_gw->table = table; r = route_configure(route_gw, link, dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages++; route->family = AF_INET; route->gw.in = gateway; route->prefsrc.in = address; route->priority = link->network->dhcp_route_metric; route->table = table; r = route_configure(route, link, dhcp4_route_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } link->dhcp4_messages++; } return 0; }