]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-netdev.c
Merge pull request #1668 from ssahani/net1
[thirdparty/systemd.git] / src / network / networkd-netdev.c
index ece9ecc25112baa9a010f571d5ad97c8041424c6..bd1129a09b9d52cce55e02ee732fdb8e198ff941 100644 (file)
 
 #include <net/if.h>
 
-#include "networkd-netdev.h"
-#include "networkd-link.h"
-#include "network-internal.h"
 #include "conf-files.h"
 #include "conf-parser.h"
+#include "fd-util.h"
 #include "list.h"
+#include "netlink-util.h"
+#include "network-internal.h"
+#include "networkd-netdev.h"
+#include "networkd.h"
 #include "siphash24.h"
+#include "string-util.h"
 
 const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
+
         [NETDEV_KIND_BRIDGE] = &bridge_vtable,
         [NETDEV_KIND_BOND] = &bond_vtable,
         [NETDEV_KIND_VLAN] = &vlan_vtable,
         [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
+        [NETDEV_KIND_MACVTAP] = &macvtap_vtable,
         [NETDEV_KIND_IPVLAN] = &ipvlan_vtable,
         [NETDEV_KIND_VXLAN] = &vxlan_vtable,
         [NETDEV_KIND_IPIP] = &ipip_vtable,
@@ -56,6 +61,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_BOND] = "bond",
         [NETDEV_KIND_VLAN] = "vlan",
         [NETDEV_KIND_MACVLAN] = "macvlan",
+        [NETDEV_KIND_MACVTAP] = "macvtap",
         [NETDEV_KIND_IPVLAN] = "ipvlan",
         [NETDEV_KIND_VXLAN] = "vxlan",
         [NETDEV_KIND_IPIP] = "ipip",
@@ -92,10 +98,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) {
                         assert(netdev->manager);
                         assert(netdev->manager->rtnl);
 
-                        callback->callback(netdev->manager->rtnl, m, link);
+                        callback->callback(netdev->manager->rtnl, m, callback->link);
                 }
 
                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
+                link_unref(callback->link);
                 free(callback);
         }
 }
@@ -177,6 +184,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
 static int netdev_enter_failed(NetDev *netdev) {
         netdev->state = NETDEV_STATE_FAILED;
 
+        netdev_cancel_callbacks(netdev);
+
         return 0;
 }
 
@@ -237,6 +246,9 @@ static int netdev_enter_ready(NetDev *netdev) {
                 free(callback);
         }
 
+        if (NETDEV_VTABLE(netdev)->post_create)
+                NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL);
+
         return 0;
 }
 
@@ -266,12 +278,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
         int r;
 
         assert(netdev);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
         assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
 
         if (netdev->state == NETDEV_STATE_READY) {
                 r = netdev_enslave_ready(netdev, link, callback);
                 if (r < 0)
                         return r;
+        } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
+                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+
+                r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
+                if (r >= 0)
+                        callback(netdev->manager->rtnl, m, link);
         } else {
                 /* the netdev is not yet read, save this request for when it is */
                 netdev_join_callback *cb;