#include "libudev-private.h"
#include "util.h"
#include "bus-util.h"
+#include "net-util.h"
int link_new(Manager *manager, struct udev_device *device, Link **ret) {
_cleanup_link_free_ Link *link = NULL;
Network *network;
int r;
uint64_t ifindex;
- const char *devtype;
assert(m);
assert(device);
*ret = link;
- devtype = udev_device_get_devtype(device);
- if (streq_ptr(devtype, "bridge")) {
- r = bridge_set_link(m, link);
- if (r < 0 && r != -ENOENT)
- return r;
- }
-
r = network_get(m, device, &network);
if (r < 0)
return r == -ENOENT ? 0 : r;
r = sd_rtnl_message_get_errno(m);
if (r < 0 && r != -EEXIST)
- log_warning_link(link, "could not set route: %s", strerror(-r));
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%s: could not set route: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
/* we might have received an old reply after moving back to SETTING_ADDRESSES,
* ignore it */
r = sd_rtnl_message_get_errno(m);
if (r < 0 && r != -EEXIST)
- log_struct_link(LOG_ERR, link,
+ log_struct_link(LOG_WARNING, link,
"MESSAGE=%s: could not set address: %s",
link->ifname, strerror(-r),
"ERRNO=%d", -r,
return 1;
r = sd_rtnl_message_get_errno(m);
- if (r < 0 && r != -EEXIST)
- log_warning_link(link, "could not drop address: %s", strerror(-r));
+ if (r < 0 && r != -ENOENT)
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%s: could not drop address: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
return 1;
}
return 1;
r = sd_rtnl_message_get_errno(m);
- if (r < 0 && r != -EEXIST)
- log_warning_link(link, "Could not set MTU: %s", strerror(-r));
+ if (r < 0)
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%s: could not set MTU: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
return 1;
}
struct in_addr address;
struct in_addr netmask;
struct in_addr gateway;
- int prefixlen;
+ unsigned prefixlen;
int r;
assert(link);
if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
event == DHCP_EVENT_STOP) {
+ if (link->network->dhcp_critical) {
+ log_warning_link(link, "DHCPv4 connection considered system critical, "
+ "ignoring request to reconfigure it down.");
+ return;
+ }
+
if (link->dhcp_address) {
address_drop(link->dhcp_address, link, address_drop_handler);
return;
}
- prefixlen = sd_dhcp_client_prefixlen(&netmask);
- if (prefixlen < 0) {
- log_warning_link(link, "DHCP error: no prefixlen");
- link_enter_failed(link);
- return;
- }
+ prefixlen = net_netmask_to_prefixlen(&netmask);
r = sd_dhcp_client_get_router(client, &gateway);
if (r < 0) {
addr->family = AF_INET;
addr->in_addr.in = address;
addr->prefixlen = prefixlen;
- addr->netmask = netmask;
+ addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
r = route_new_dynamic(&rt);
if (r < 0) {
r = sd_rtnl_message_get_errno(m);
if (r < 0) {
- log_warning_link(link,
- "could not bring up interface: %s", strerror(-r));
+ log_struct_link(LOG_ERR, link,
+ "MESSAGE=%s: could not bring up interface: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
link_enter_failed(link);
+ return 1;
}
link_update_flags(link, link->flags | IFF_UP);
return r;
}
- r = sd_rtnl_message_link_set_flags(req, IFF_UP);
+ r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
if (r < 0) {
log_error_link(link, "Could not set link flags: %s", strerror(-r));
return r;
return 0;
}
-static int link_bridge_joined(Link *link) {
+static int link_enslaved(Link *link) {
int r;
assert(link);
- assert(link->state == LINK_STATE_JOINING_BRIDGE);
+ assert(link->state == LINK_STATE_ENSLAVING);
assert(link->network);
r = link_up(link);
return 0;
}
-static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
+static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
Link *link = userdata;
int r;
assert(link);
- assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
+ assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
assert(link->network);
+ link->enslaving --;
+
if (link->state == LINK_STATE_FAILED)
return 1;
r = sd_rtnl_message_get_errno(m);
if (r < 0) {
log_struct_link(LOG_ERR, link,
- "MESSAGE=%s: could not join bridge '%s': %s",
- link->ifname, link->network->bridge->name, strerror(-r),
- BRIDGE(link->network->bridge),
+ "MESSAGE=%s: could not enslave: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
NULL);
link_enter_failed(link);
return 1;
}
- log_struct_link(LOG_DEBUG, link,
- "MESSAGE=%s: joined bridge '%s'",
- link->network->bridge->name,
- BRIDGE(link->network->bridge),
- NULL);
+ log_debug_link(link, "enslaved");
- link_bridge_joined(link);
+ if (link->enslaving == 0)
+ link_enslaved(link);
return 1;
}
-static int link_enter_join_bridge(Link *link) {
+static int link_enter_enslave(Link *link) {
int r;
assert(link);
assert(link->network);
assert(link->state == _LINK_STATE_INVALID);
- link->state = LINK_STATE_JOINING_BRIDGE;
+ link->state = LINK_STATE_ENSLAVING;
- if (!link->network->bridge)
- return link_bridge_joined(link);
+ if (!link->network->bridge && !link->network->bond && !link->network->vlan)
+ return link_enslaved(link);
- log_struct_link(LOG_DEBUG, link,
- "MESSAGE=%s: joining bridge '%s'",
- link->network->bridge->name,
- BRIDGE(link->network->bridge),
- NULL);
- log_debug_link(link, "joining bridge");
+ if (link->network->bridge) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%s: enslaving by '%s'",
+ link->ifname, link->network->bridge->name,
+ NETDEV(link->network->bridge),
+ NULL);
- r = bridge_join(link->network->bridge, link, &bridge_handler);
- if (r < 0) {
- log_struct_link(LOG_WARNING, link,
- "MESSAGE=%s: could not join bridge '%s': %s",
- link->network->bridge->name, strerror(-r),
- BRIDGE(link->network->bridge),
+ r = netdev_enslave(link->network->bridge, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%s: could not enslave by '%s': %s",
+ link->ifname, link->network->bridge->name, strerror(-r),
+ NETDEV(link->network->bridge),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->enslaving ++;
+ }
+
+ if (link->network->vlan) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%s: enslaving by '%s'",
+ link->ifname, link->network->vlan->name,
+ NETDEV(link->network->vlan),
NULL);
- link_enter_failed(link);
- return r;
+
+ r = netdev_enslave(link->network->vlan, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%s: could not enslave by '%s': %s",
+ link->ifname, link->network->vlan->name,
+ strerror(-r), NETDEV(link->network->vlan),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->enslaving ++;
}
return 0;
r = sd_rtnl_message_get_errno(m);
if (r < 0) {
- log_warning_link(link, "could not get state: %s", strerror(-r));
+ log_struct_link(LOG_ERR, link,
+ "MESSAGE=%s: could not get state: %s",
+ link->ifname, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
link_enter_failed(link);
+ return 1;
}
log_debug_link(link, "got link state");
return r;
}
- return link_enter_join_bridge(link);
+ return link_enter_enslave(link);
}
int link_update(Link *link, sd_rtnl_message *m) {