Beispiel #1
0
static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
        Vrf *v;
        int r;

        assert(netdev);
        assert(!link);
        assert(m);

        v = VRF(netdev);

        assert(v);

        r = sd_netlink_message_append_u32(m, IFLA_VRF_TABLE, v->table_id);
        if (r < 0)
                return log_netdev_error_errno(netdev, r, "Could not append IPLA_VRF_TABLE attribute: %m");

        return r;
}
Beispiel #2
0
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;
}