p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6");
- r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
enable_disable(!disabled), link->ifname);
if (r < 0)
return r;
- link = new0(Link, 1);
+ link = new(Link, 1);
if (!link)
return -ENOMEM;
- link->n_ref = 1;
- link->manager = manager;
- link->state = LINK_STATE_PENDING;
- link->rtnl_extended_attrs = true;
- link->ifindex = ifindex;
- link->iftype = iftype;
+ *link = (Link) {
+ .n_ref = 1,
+ .manager = manager,
+ .state = LINK_STATE_PENDING,
+ .rtnl_extended_attrs = true,
+ .ifindex = ifindex,
+ .iftype = iftype,
+ };
+
link->ifname = strdup(ifname);
if (!link->ifname)
return -ENOMEM;
return 0;
}
+static void link_detach_from_manager(Link *link) {
+ if (!link || !link->manager)
+ return;
+
+ hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
+ set_remove(link->manager->links_requesting_uuid, link);
+ link_clean(link);
+
+ link->manager = NULL;
+}
+
static Link *link_free(Link *link) {
Address *address;
Link *carrier;
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
- if (link->manager) {
- hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
- set_remove(link->manager->links_requesting_uuid, link);
- link_clean(link);
- }
+ link_detach_from_manager(link);
free(link->ifname);
LIST_FOREACH(rules, rule, link->network->rules) {
r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
- rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule);
+ rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif,
+ rule->protocol, &rule->sport, &rule->dport, &rrule);
if (r == 0) {
(void) routing_policy_rule_make_local(link->manager, rrule);
continue;
}
static int link_enter_set_routes(Link *link) {
+ enum {
+ PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
+ PHASE_GATEWAY, /* Second phase: Routes with a gateway */
+ _PHASE_MAX
+ } phase;
Route *rt;
int r;
link_set_state(link, LINK_STATE_SETTING_ROUTES);
- LIST_FOREACH(routes, rt, link->network->static_routes) {
- r = route_configure(rt, link, route_handler);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not set routes: %m");
- link_enter_failed(link);
- return r;
- }
+ /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
+ for (phase = 0; phase < _PHASE_MAX; phase++)
+ LIST_FOREACH(routes, rt, link->network->static_routes) {
- link->route_messages++;
- }
+ if (in_addr_is_null(rt->family, &rt->gw) != (phase == PHASE_NON_GATEWAY))
+ continue;
+
+ r = route_configure(rt, link, route_handler);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set routes: %m");
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->route_messages++;
+ }
if (link->route_messages == 0) {
link->static_routes_configured = true;
p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp");
- r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m");
log_link_debug(link, "Link removed");
(void) unlink(link->state_file);
+
+ link_detach_from_manager(link);
+
link_unref(link);
return;
* primarily to keep IPv4 and IPv6 packet forwarding behaviour
* somewhat in sync (see below). */
- r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
* same behaviour there and also propagate the setting from
* one to all, to keep things simple (see above). */
- r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
/* We handle router advertisements ourselves, tell the kernel to GTFO */
- r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
xsprintf(buf, "%i", link->network->ipv6_hop_limit);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
- r = write_string_file(p, buf, 0);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
assert(link);
- r = parse_env_file(NULL, link->state_file, NEWLINE,
+ r = parse_env_file(NULL, link->state_file,
"NETWORK_FILE", &network_file,
"ADDRESSES", &addresses,
"ROUTES", &routes,
"DHCP4_ADDRESS", &dhcp4_address,
- "IPV4LL_ADDRESS", &ipv4ll_address,
- NULL);
+ "IPV4LL_ADDRESS", &ipv4ll_address);
if (r < 0 && r != -ENOENT)
return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file);