| File: | build-scan/../src/network/netdev/netdev.c |
| Warning: | line 673, column 26 Access to field 'sections' results in a dereference of a null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <net/if.h> | |||
| 4 | ||||
| 5 | #include "alloc-util.h" | |||
| 6 | #include "conf-files.h" | |||
| 7 | #include "conf-parser.h" | |||
| 8 | #include "fd-util.h" | |||
| 9 | #include "list.h" | |||
| 10 | #include "netlink-util.h" | |||
| 11 | #include "network-internal.h" | |||
| 12 | #include "netdev/netdev.h" | |||
| 13 | #include "networkd-manager.h" | |||
| 14 | #include "networkd-link.h" | |||
| 15 | #include "siphash24.h" | |||
| 16 | #include "stat-util.h" | |||
| 17 | #include "string-table.h" | |||
| 18 | #include "string-util.h" | |||
| 19 | ||||
| 20 | #include "netdev/bridge.h" | |||
| 21 | #include "netdev/bond.h" | |||
| 22 | #include "netdev/geneve.h" | |||
| 23 | #include "netdev/vlan.h" | |||
| 24 | #include "netdev/macvlan.h" | |||
| 25 | #include "netdev/ipvlan.h" | |||
| 26 | #include "netdev/vxlan.h" | |||
| 27 | #include "netdev/tunnel.h" | |||
| 28 | #include "netdev/tuntap.h" | |||
| 29 | #include "netdev/veth.h" | |||
| 30 | #include "netdev/dummy.h" | |||
| 31 | #include "netdev/vrf.h" | |||
| 32 | #include "netdev/vcan.h" | |||
| 33 | #include "netdev/vxcan.h" | |||
| 34 | #include "netdev/wireguard.h" | |||
| 35 | #include "netdev/netdevsim.h" | |||
| 36 | ||||
| 37 | const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { | |||
| 38 | [NETDEV_KIND_BRIDGE] = &bridge_vtable, | |||
| 39 | [NETDEV_KIND_BOND] = &bond_vtable, | |||
| 40 | [NETDEV_KIND_VLAN] = &vlan_vtable, | |||
| 41 | [NETDEV_KIND_MACVLAN] = &macvlan_vtable, | |||
| 42 | [NETDEV_KIND_MACVTAP] = &macvtap_vtable, | |||
| 43 | [NETDEV_KIND_IPVLAN] = &ipvlan_vtable, | |||
| 44 | [NETDEV_KIND_VXLAN] = &vxlan_vtable, | |||
| 45 | [NETDEV_KIND_IPIP] = &ipip_vtable, | |||
| 46 | [NETDEV_KIND_GRE] = &gre_vtable, | |||
| 47 | [NETDEV_KIND_GRETAP] = &gretap_vtable, | |||
| 48 | [NETDEV_KIND_IP6GRE] = &ip6gre_vtable, | |||
| 49 | [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable, | |||
| 50 | [NETDEV_KIND_SIT] = &sit_vtable, | |||
| 51 | [NETDEV_KIND_VTI] = &vti_vtable, | |||
| 52 | [NETDEV_KIND_VTI6] = &vti6_vtable, | |||
| 53 | [NETDEV_KIND_VETH] = &veth_vtable, | |||
| 54 | [NETDEV_KIND_DUMMY] = &dummy_vtable, | |||
| 55 | [NETDEV_KIND_TUN] = &tun_vtable, | |||
| 56 | [NETDEV_KIND_TAP] = &tap_vtable, | |||
| 57 | [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, | |||
| 58 | [NETDEV_KIND_VRF] = &vrf_vtable, | |||
| 59 | [NETDEV_KIND_VCAN] = &vcan_vtable, | |||
| 60 | [NETDEV_KIND_GENEVE] = &geneve_vtable, | |||
| 61 | [NETDEV_KIND_VXCAN] = &vxcan_vtable, | |||
| 62 | [NETDEV_KIND_WIREGUARD] = &wireguard_vtable, | |||
| 63 | [NETDEV_KIND_NETDEVSIM] = &netdevsim_vtable, | |||
| 64 | }; | |||
| 65 | ||||
| 66 | static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { | |||
| 67 | [NETDEV_KIND_BRIDGE] = "bridge", | |||
| 68 | [NETDEV_KIND_BOND] = "bond", | |||
| 69 | [NETDEV_KIND_VLAN] = "vlan", | |||
| 70 | [NETDEV_KIND_MACVLAN] = "macvlan", | |||
| 71 | [NETDEV_KIND_MACVTAP] = "macvtap", | |||
| 72 | [NETDEV_KIND_IPVLAN] = "ipvlan", | |||
| 73 | [NETDEV_KIND_VXLAN] = "vxlan", | |||
| 74 | [NETDEV_KIND_IPIP] = "ipip", | |||
| 75 | [NETDEV_KIND_GRE] = "gre", | |||
| 76 | [NETDEV_KIND_GRETAP] = "gretap", | |||
| 77 | [NETDEV_KIND_IP6GRE] = "ip6gre", | |||
| 78 | [NETDEV_KIND_IP6GRETAP] = "ip6gretap", | |||
| 79 | [NETDEV_KIND_SIT] = "sit", | |||
| 80 | [NETDEV_KIND_VETH] = "veth", | |||
| 81 | [NETDEV_KIND_VTI] = "vti", | |||
| 82 | [NETDEV_KIND_VTI6] = "vti6", | |||
| 83 | [NETDEV_KIND_DUMMY] = "dummy", | |||
| 84 | [NETDEV_KIND_TUN] = "tun", | |||
| 85 | [NETDEV_KIND_TAP] = "tap", | |||
| 86 | [NETDEV_KIND_IP6TNL] = "ip6tnl", | |||
| 87 | [NETDEV_KIND_VRF] = "vrf", | |||
| 88 | [NETDEV_KIND_VCAN] = "vcan", | |||
| 89 | [NETDEV_KIND_GENEVE] = "geneve", | |||
| 90 | [NETDEV_KIND_VXCAN] = "vxcan", | |||
| 91 | [NETDEV_KIND_WIREGUARD] = "wireguard", | |||
| 92 | [NETDEV_KIND_NETDEVSIM] = "netdevsim", | |||
| 93 | }; | |||
| 94 | ||||
| 95 | DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind)const char *netdev_kind_to_string(NetDevKind i) { if (i < 0 || i >= (NetDevKind) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(netdev_kind_table), typeof (&*(netdev_kind_table))), sizeof(netdev_kind_table)/sizeof ((netdev_kind_table)[0]), ((void)0)))) return ((void*)0); return netdev_kind_table[i]; } NetDevKind netdev_kind_from_string(const char *s) { return (NetDevKind) string_table_lookup(netdev_kind_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(netdev_kind_table), typeof(&*(netdev_kind_table)) ), sizeof(netdev_kind_table)/sizeof((netdev_kind_table)[0]), ( (void)0))), s); }; | |||
| 96 | DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind")int config_parse_netdev_kind(const char *unit, const char *filename , unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { NetDevKind *i = data, x; do { if ((__builtin_expect (!!(!(filename)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("filename"), "../src/network/netdev/netdev.c", 96, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("lvalue"), "../src/network/netdev/netdev.c" , 96, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("rvalue"), "../src/network/netdev/netdev.c", 96, __PRETTY_FUNCTION__ ); } while (0); do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/netdev.c" , 96, __PRETTY_FUNCTION__); } while (0); x = netdev_kind_from_string (rvalue); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_SYSTEMD) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/network/netdev/netdev.c" , 96, __func__, "Failed to parse netdev kind" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; }; | |||
| 97 | ||||
| 98 | static void netdev_cancel_callbacks(NetDev *netdev) { | |||
| 99 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *m = NULL((void*)0); | |||
| 100 | netdev_join_callback *callback; | |||
| 101 | ||||
| 102 | if (!netdev || !netdev->manager) | |||
| 103 | return; | |||
| 104 | ||||
| 105 | rtnl_message_new_synthetic_error(netdev->manager->rtnl, -ENODEV19, 0, &m); | |||
| 106 | ||||
| 107 | while ((callback = netdev->callbacks)) { | |||
| 108 | if (m) { | |||
| 109 | assert(callback->link)do { if ((__builtin_expect(!!(!(callback->link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("callback->link"), "../src/network/netdev/netdev.c" , 109, __PRETTY_FUNCTION__); } while (0); | |||
| 110 | assert(callback->callback)do { if ((__builtin_expect(!!(!(callback->callback)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("callback->callback"), "../src/network/netdev/netdev.c" , 110, __PRETTY_FUNCTION__); } while (0); | |||
| 111 | assert(netdev->manager)do { if ((__builtin_expect(!!(!(netdev->manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev->manager"), "../src/network/netdev/netdev.c" , 111, __PRETTY_FUNCTION__); } while (0); | |||
| 112 | assert(netdev->manager->rtnl)do { if ((__builtin_expect(!!(!(netdev->manager->rtnl)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->manager->rtnl" ), "../src/network/netdev/netdev.c", 112, __PRETTY_FUNCTION__ ); } while (0); | |||
| 113 | ||||
| 114 | callback->callback(netdev->manager->rtnl, m, callback->link); | |||
| 115 | } | |||
| 116 | ||||
| 117 | LIST_REMOVE(callbacks, netdev->callbacks, callback)do { typeof(*(netdev->callbacks)) **_head = &(netdev-> callbacks), *_item = (callback); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/network/netdev/netdev.c", 117, __PRETTY_FUNCTION__ ); } while (0); if (_item->callbacks_next) _item->callbacks_next ->callbacks_prev = _item->callbacks_prev; if (_item-> callbacks_prev) _item->callbacks_prev->callbacks_next = _item->callbacks_next; else { do { if ((__builtin_expect( !!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("*_head == _item"), "../src/network/netdev/netdev.c", 117, __PRETTY_FUNCTION__); } while (0); *_head = _item->callbacks_next ; } _item->callbacks_next = _item->callbacks_prev = ((void *)0); } while (0); | |||
| 118 | link_unref(callback->link); | |||
| 119 | free(callback); | |||
| 120 | } | |||
| 121 | } | |||
| 122 | ||||
| 123 | static void netdev_free(NetDev *netdev) { | |||
| 124 | if (!netdev) | |||
| 125 | return; | |||
| 126 | ||||
| 127 | netdev_cancel_callbacks(netdev); | |||
| 128 | ||||
| 129 | if (netdev->ifname && netdev->manager) | |||
| 130 | hashmap_remove(netdev->manager->netdevs, netdev->ifname); | |||
| 131 | ||||
| 132 | free(netdev->filename); | |||
| 133 | ||||
| 134 | free(netdev->description); | |||
| 135 | free(netdev->ifname); | |||
| 136 | free(netdev->mac); | |||
| 137 | ||||
| 138 | condition_free_list(netdev->match_host); | |||
| 139 | condition_free_list(netdev->match_virt); | |||
| 140 | condition_free_list(netdev->match_kernel_cmdline); | |||
| 141 | condition_free_list(netdev->match_kernel_version); | |||
| 142 | condition_free_list(netdev->match_arch); | |||
| 143 | ||||
| 144 | /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that | |||
| 145 | * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure | |||
| 146 | * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full, | |||
| 147 | * comprehensive NetDev structure allocation with enough space for whatever the specific kind needs). Now, in | |||
| 148 | * the first case we shouldn't try to destruct the per-kind NetDev fields on destruction, in the second case we | |||
| 149 | * should. We use the state field to discern the two cases: it's _NETDEV_STATE_INVALID on the first "raw" | |||
| 150 | * call. */ | |||
| 151 | if (netdev->state != _NETDEV_STATE_INVALID && | |||
| 152 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0)) && | |||
| 153 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->done) | |||
| 154 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->done(netdev); | |||
| 155 | ||||
| 156 | free(netdev); | |||
| 157 | } | |||
| 158 | ||||
| 159 | NetDev *netdev_unref(NetDev *netdev) { | |||
| 160 | if (netdev && (-- netdev->n_ref <= 0)) | |||
| 161 | netdev_free(netdev); | |||
| 162 | ||||
| 163 | return NULL((void*)0); | |||
| 164 | } | |||
| 165 | ||||
| 166 | NetDev *netdev_ref(NetDev *netdev) { | |||
| 167 | if (netdev) | |||
| 168 | assert_se(++ netdev->n_ref >= 2)do { if ((__builtin_expect(!!(!(++ netdev->n_ref >= 2)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("++ netdev->n_ref >= 2" ), "../src/network/netdev/netdev.c", 168, __PRETTY_FUNCTION__ ); } while (0); | |||
| 169 | ||||
| 170 | return netdev; | |||
| 171 | } | |||
| 172 | ||||
| 173 | void netdev_drop(NetDev *netdev) { | |||
| 174 | if (!netdev || netdev->state == NETDEV_STATE_LINGER) | |||
| 175 | return; | |||
| 176 | ||||
| 177 | netdev->state = NETDEV_STATE_LINGER; | |||
| 178 | ||||
| 179 | log_netdev_debug(netdev, "netdev removed")({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 179, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "netdev removed") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c" , 179, __func__, "netdev removed"); }); | |||
| 180 | ||||
| 181 | netdev_cancel_callbacks(netdev); | |||
| 182 | ||||
| 183 | netdev_unref(netdev); | |||
| 184 | ||||
| 185 | return; | |||
| 186 | } | |||
| 187 | ||||
| 188 | int netdev_get(Manager *manager, const char *name, NetDev **ret) { | |||
| 189 | NetDev *netdev; | |||
| 190 | ||||
| 191 | assert(manager)do { if ((__builtin_expect(!!(!(manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("manager"), "../src/network/netdev/netdev.c" , 191, __PRETTY_FUNCTION__); } while (0); | |||
| 192 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/network/netdev/netdev.c" , 192, __PRETTY_FUNCTION__); } while (0); | |||
| 193 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/netdev/netdev.c" , 193, __PRETTY_FUNCTION__); } while (0); | |||
| 194 | ||||
| 195 | netdev = hashmap_get(manager->netdevs, name); | |||
| 196 | if (!netdev) { | |||
| 197 | *ret = NULL((void*)0); | |||
| 198 | return -ENOENT2; | |||
| 199 | } | |||
| 200 | ||||
| 201 | *ret = netdev; | |||
| 202 | ||||
| 203 | return 0; | |||
| 204 | } | |||
| 205 | ||||
| 206 | static int netdev_enter_failed(NetDev *netdev) { | |||
| 207 | netdev->state = NETDEV_STATE_FAILED; | |||
| 208 | ||||
| 209 | netdev_cancel_callbacks(netdev); | |||
| 210 | ||||
| 211 | return 0; | |||
| 212 | } | |||
| 213 | ||||
| 214 | static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_handler_t callback) { | |||
| 215 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *req = NULL((void*)0); | |||
| 216 | int r; | |||
| 217 | ||||
| 218 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 218, __PRETTY_FUNCTION__); } while (0); | |||
| 219 | assert(netdev->state == NETDEV_STATE_READY)do { if ((__builtin_expect(!!(!(netdev->state == NETDEV_STATE_READY )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->state == NETDEV_STATE_READY" ), "../src/network/netdev/netdev.c", 219, __PRETTY_FUNCTION__ ); } while (0); | |||
| 220 | assert(netdev->manager)do { if ((__builtin_expect(!!(!(netdev->manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev->manager"), "../src/network/netdev/netdev.c" , 220, __PRETTY_FUNCTION__); } while (0); | |||
| 221 | assert(netdev->manager->rtnl)do { if ((__builtin_expect(!!(!(netdev->manager->rtnl)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->manager->rtnl" ), "../src/network/netdev/netdev.c", 221, __PRETTY_FUNCTION__ ); } while (0); | |||
| 222 | assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF })/sizeof(int)]; switch(netdev->kind) { case NETDEV_KIND_BRIDGE : case NETDEV_KIND_BOND: case NETDEV_KIND_VRF: _found = 1; break ; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)" ), "../src/network/netdev/netdev.c", 222, __PRETTY_FUNCTION__ ); } while (0); | |||
| 223 | assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("link"), "../src/network/netdev/netdev.c" , 223, __PRETTY_FUNCTION__); } while (0); | |||
| 224 | assert(callback)do { if ((__builtin_expect(!!(!(callback)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("callback"), "../src/network/netdev/netdev.c" , 224, __PRETTY_FUNCTION__); } while (0); | |||
| 225 | ||||
| 226 | if (link->flags & IFF_UPIFF_UP && netdev->kind == NETDEV_KIND_BOND) { | |||
| 227 | log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname)({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 227, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Link '%s' was up when attempting to enslave it. Bringing link down." , link->ifname) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c", 227, __func__ , "Link '%s' was up when attempting to enslave it. Bringing link down." , link->ifname); }); | |||
| 228 | r = link_down(link); | |||
| 229 | if (r < 0) | |||
| 230 | return log_netdev_error_errno(netdev, r, "Could not bring link down: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 230, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not bring link down: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 230, __func__, "Could not bring link down: %m" ); }); | |||
| 231 | } | |||
| 232 | ||||
| 233 | r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINKRTM_SETLINK, link->ifindex); | |||
| 234 | if (r < 0) | |||
| 235 | return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 235, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not allocate RTM_SETLINK message: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 235, __func__, "Could not allocate RTM_SETLINK message: %m" ); }); | |||
| 236 | ||||
| 237 | r = sd_netlink_message_append_u32(req, IFLA_MASTERIFLA_MASTER, netdev->ifindex); | |||
| 238 | if (r < 0) | |||
| 239 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 239, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_MASTER attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 239, __func__, "Could not append IFLA_MASTER attribute: %m" ); }); | |||
| 240 | ||||
| 241 | r = sd_netlink_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL((void*)0)); | |||
| 242 | if (r < 0) | |||
| 243 | return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 243, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not send rtnetlink message: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 243, __func__, "Could not send rtnetlink message: %m" ); }); | |||
| 244 | ||||
| 245 | link_ref(link); | |||
| 246 | ||||
| 247 | log_netdev_debug(netdev, "Enslaving link '%s'", link->ifname)({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 247, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Enslaving link '%s'" , link->ifname) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c", 247, __func__ , "Enslaving link '%s'", link->ifname); }); | |||
| 248 | ||||
| 249 | return 0; | |||
| 250 | } | |||
| 251 | ||||
| 252 | static int netdev_enter_ready(NetDev *netdev) { | |||
| 253 | netdev_join_callback *callback, *callback_next; | |||
| 254 | int r; | |||
| 255 | ||||
| 256 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 256, __PRETTY_FUNCTION__); } while (0); | |||
| 257 | assert(netdev->ifname)do { if ((__builtin_expect(!!(!(netdev->ifname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev->ifname"), "../src/network/netdev/netdev.c" , 257, __PRETTY_FUNCTION__); } while (0); | |||
| 258 | ||||
| 259 | if (netdev->state != NETDEV_STATE_CREATING) | |||
| 260 | return 0; | |||
| 261 | ||||
| 262 | netdev->state = NETDEV_STATE_READY; | |||
| 263 | ||||
| 264 | log_netdev_info(netdev, "netdev ready")({ const NetDev *_n = (netdev); _n ? log_object_internal(6, 0 , "../src/network/netdev/netdev.c", 264, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "netdev ready") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((6))), 0, "../src/network/netdev/netdev.c" , 264, __func__, "netdev ready"); }); | |||
| 265 | ||||
| 266 | LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks)for ((callback) = (netdev->callbacks); (callback) && (((callback_next) = (callback)->callbacks_next), 1); (callback ) = (callback_next)) { | |||
| 267 | /* enslave the links that were attempted to be enslaved before the | |||
| 268 | * link was ready */ | |||
| 269 | r = netdev_enslave_ready(netdev, callback->link, callback->callback); | |||
| 270 | if (r < 0) | |||
| 271 | return r; | |||
| 272 | ||||
| 273 | LIST_REMOVE(callbacks, netdev->callbacks, callback)do { typeof(*(netdev->callbacks)) **_head = &(netdev-> callbacks), *_item = (callback); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/network/netdev/netdev.c", 273, __PRETTY_FUNCTION__ ); } while (0); if (_item->callbacks_next) _item->callbacks_next ->callbacks_prev = _item->callbacks_prev; if (_item-> callbacks_prev) _item->callbacks_prev->callbacks_next = _item->callbacks_next; else { do { if ((__builtin_expect( !!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("*_head == _item"), "../src/network/netdev/netdev.c", 273, __PRETTY_FUNCTION__); } while (0); *_head = _item->callbacks_next ; } _item->callbacks_next = _item->callbacks_prev = ((void *)0); } while (0); | |||
| 274 | link_unref(callback->link); | |||
| 275 | free(callback); | |||
| 276 | } | |||
| 277 | ||||
| 278 | if (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->post_create) | |||
| 279 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->post_create(netdev, NULL((void*)0), NULL((void*)0)); | |||
| 280 | ||||
| 281 | return 0; | |||
| 282 | } | |||
| 283 | ||||
| 284 | /* callback for netdev's created without a backing Link */ | |||
| 285 | static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { | |||
| 286 | _cleanup_(netdev_unrefp)__attribute__((cleanup(netdev_unrefp))) NetDev *netdev = userdata; | |||
| 287 | int r; | |||
| 288 | ||||
| 289 | assert(netdev->state != _NETDEV_STATE_INVALID)do { if ((__builtin_expect(!!(!(netdev->state != _NETDEV_STATE_INVALID )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->state != _NETDEV_STATE_INVALID" ), "../src/network/netdev/netdev.c", 289, __PRETTY_FUNCTION__ ); } while (0); | |||
| 290 | ||||
| 291 | r = sd_netlink_message_get_errno(m); | |||
| 292 | if (r == -EEXIST17) | |||
| 293 | log_netdev_info(netdev, "netdev exists, using existing without changing its parameters")({ const NetDev *_n = (netdev); _n ? log_object_internal(6, 0 , "../src/network/netdev/netdev.c", 293, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "netdev exists, using existing without changing its parameters" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((6 ))), 0, "../src/network/netdev/netdev.c", 293, __func__, "netdev exists, using existing without changing its parameters" ); }); | |||
| 294 | else if (r < 0) { | |||
| 295 | log_netdev_warning_errno(netdev, r, "netdev could not be created: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(4, r , "../src/network/netdev/netdev.c", 295, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "netdev could not be created: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/network/netdev/netdev.c", 295, __func__, "netdev could not be created: %m" ); }); | |||
| 296 | netdev_drop(netdev); | |||
| 297 | ||||
| 298 | return 1; | |||
| 299 | } | |||
| 300 | ||||
| 301 | log_netdev_debug(netdev, "Created")({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 301, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Created") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c" , 301, __func__, "Created"); }); | |||
| 302 | ||||
| 303 | return 1; | |||
| 304 | } | |||
| 305 | ||||
| 306 | int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { | |||
| 307 | int r; | |||
| 308 | ||||
| 309 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 309, __PRETTY_FUNCTION__); } while (0); | |||
| 310 | assert(netdev->manager)do { if ((__builtin_expect(!!(!(netdev->manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev->manager"), "../src/network/netdev/netdev.c" , 310, __PRETTY_FUNCTION__); } while (0); | |||
| 311 | assert(netdev->manager->rtnl)do { if ((__builtin_expect(!!(!(netdev->manager->rtnl)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->manager->rtnl" ), "../src/network/netdev/netdev.c", 311, __PRETTY_FUNCTION__ ); } while (0); | |||
| 312 | assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF })/sizeof(int)]; switch(netdev->kind) { case NETDEV_KIND_BRIDGE : case NETDEV_KIND_BOND: case NETDEV_KIND_VRF: _found = 1; break ; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)" ), "../src/network/netdev/netdev.c", 312, __PRETTY_FUNCTION__ ); } while (0); | |||
| 313 | ||||
| 314 | if (netdev->state == NETDEV_STATE_READY) { | |||
| 315 | r = netdev_enslave_ready(netdev, link, callback); | |||
| 316 | if (r < 0) | |||
| 317 | return r; | |||
| 318 | } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){NETDEV_STATE_LINGER, NETDEV_STATE_FAILED })/sizeof(int)]; switch(netdev->state) { case NETDEV_STATE_LINGER : case NETDEV_STATE_FAILED: _found = 1; break; default: break ; } _found; })) { | |||
| 319 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *m = NULL((void*)0); | |||
| 320 | ||||
| 321 | r = rtnl_message_new_synthetic_error(netdev->manager->rtnl, -ENODEV19, 0, &m); | |||
| 322 | if (r >= 0) | |||
| 323 | callback(netdev->manager->rtnl, m, link); | |||
| 324 | } else { | |||
| 325 | /* the netdev is not yet read, save this request for when it is */ | |||
| 326 | netdev_join_callback *cb; | |||
| 327 | ||||
| 328 | cb = new0(netdev_join_callback, 1)((netdev_join_callback*) calloc((1), sizeof(netdev_join_callback ))); | |||
| 329 | if (!cb) | |||
| 330 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/netdev.c" , 330, __func__); | |||
| 331 | ||||
| 332 | cb->callback = callback; | |||
| 333 | cb->link = link; | |||
| 334 | link_ref(link); | |||
| 335 | ||||
| 336 | LIST_PREPEND(callbacks, netdev->callbacks, cb)do { typeof(*(netdev->callbacks)) **_head = &(netdev-> callbacks), *_item = (cb); do { if ((__builtin_expect(!!(!(_item )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/network/netdev/netdev.c", 336, __PRETTY_FUNCTION__); } while (0); if ((_item->callbacks_next = *_head)) _item-> callbacks_next->callbacks_prev = _item; _item->callbacks_prev = ((void*)0); *_head = _item; } while (0); | |||
| 337 | ||||
| 338 | log_netdev_debug(netdev, "Will enslave '%s', when ready", link->ifname)({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 338, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Will enslave '%s', when ready" , link->ifname) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c", 338, __func__ , "Will enslave '%s', when ready", link->ifname); }); | |||
| 339 | } | |||
| 340 | ||||
| 341 | return 0; | |||
| 342 | } | |||
| 343 | ||||
| 344 | int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { | |||
| 345 | uint16_t type; | |||
| 346 | const char *kind; | |||
| 347 | const char *received_kind; | |||
| 348 | const char *received_name; | |||
| 349 | int r, ifindex; | |||
| 350 | ||||
| 351 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 351, __PRETTY_FUNCTION__); } while (0); | |||
| 352 | assert(message)do { if ((__builtin_expect(!!(!(message)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("message"), "../src/network/netdev/netdev.c" , 352, __PRETTY_FUNCTION__); } while (0); | |||
| 353 | ||||
| 354 | r = sd_netlink_message_get_type(message, &type); | |||
| 355 | if (r < 0) | |||
| 356 | return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 356, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get rtnl message type: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 356, __func__, "Could not get rtnl message type: %m" ); }); | |||
| 357 | ||||
| 358 | if (type != RTM_NEWLINKRTM_NEWLINK) { | |||
| 359 | log_netdev_error(netdev, "Cannot set ifindex from unexpected rtnl message type.")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 359, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Cannot set ifindex from unexpected rtnl message type." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/network/netdev/netdev.c", 359, __func__, "Cannot set ifindex from unexpected rtnl message type." ); }); | |||
| 360 | return -EINVAL22; | |||
| 361 | } | |||
| 362 | ||||
| 363 | r = sd_rtnl_message_link_get_ifindex(message, &ifindex); | |||
| 364 | if (r < 0) { | |||
| 365 | log_netdev_error_errno(netdev, r, "Could not get ifindex: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 365, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get ifindex: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 365, __func__, "Could not get ifindex: %m" ); }); | |||
| 366 | netdev_enter_failed(netdev); | |||
| 367 | return r; | |||
| 368 | } else if (ifindex <= 0) { | |||
| 369 | log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex)({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 369, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Got invalid ifindex: %d" , ifindex) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 369, __func__ , "Got invalid ifindex: %d", ifindex); }); | |||
| 370 | netdev_enter_failed(netdev); | |||
| 371 | return -EINVAL22; | |||
| 372 | } | |||
| 373 | ||||
| 374 | if (netdev->ifindex > 0) { | |||
| 375 | if (netdev->ifindex != ifindex) { | |||
| 376 | log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d",({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 377, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not set ifindex to %d, already set to %d" , ifindex, netdev->ifindex) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 377 , __func__, "Could not set ifindex to %d, already set to %d", ifindex, netdev->ifindex); }) | |||
| 377 | ifindex, netdev->ifindex)({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 377, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not set ifindex to %d, already set to %d" , ifindex, netdev->ifindex) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 377 , __func__, "Could not set ifindex to %d, already set to %d", ifindex, netdev->ifindex); }); | |||
| 378 | netdev_enter_failed(netdev); | |||
| 379 | return -EEXIST17; | |||
| 380 | } else | |||
| 381 | /* ifindex already set to the same for this netdev */ | |||
| 382 | return 0; | |||
| 383 | } | |||
| 384 | ||||
| 385 | r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); | |||
| 386 | if (r < 0) | |||
| 387 | return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 387, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get IFNAME: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 387, __func__, "Could not get IFNAME: %m" ); }); | |||
| 388 | ||||
| 389 | if (!streq(netdev->ifname, received_name)(strcmp((netdev->ifname),(received_name)) == 0)) { | |||
| 390 | log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name)({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 390, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Received newlink with wrong IFNAME %s" , received_name) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 390, __func__ , "Received newlink with wrong IFNAME %s", received_name); }); | |||
| 391 | netdev_enter_failed(netdev); | |||
| 392 | return r; | |||
| 393 | } | |||
| 394 | ||||
| 395 | r = sd_netlink_message_enter_container(message, IFLA_LINKINFOIFLA_LINKINFO); | |||
| 396 | if (r < 0) | |||
| 397 | return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 397, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get LINKINFO: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 397, __func__, "Could not get LINKINFO: %m" ); }); | |||
| 398 | ||||
| 399 | r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind); | |||
| 400 | if (r < 0) | |||
| 401 | return log_netdev_error_errno(netdev, r, "Could not get KIND: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 401, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get KIND: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 401, __func__, "Could not get KIND: %m" ); }); | |||
| 402 | ||||
| 403 | r = sd_netlink_message_exit_container(message); | |||
| 404 | if (r < 0) | |||
| 405 | return log_netdev_error_errno(netdev, r, "Could not exit container: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 405, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not exit container: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 405, __func__, "Could not exit container: %m" ); }); | |||
| 406 | ||||
| 407 | if (netdev->kind == NETDEV_KIND_TAP) | |||
| 408 | /* the kernel does not distinguish between tun and tap */ | |||
| 409 | kind = "tun"; | |||
| 410 | else { | |||
| 411 | kind = netdev_kind_to_string(netdev->kind); | |||
| 412 | if (!kind) { | |||
| 413 | log_netdev_error(netdev, "Could not get kind")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 413, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not get kind" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/network/netdev/netdev.c", 413, __func__, "Could not get kind" ); }); | |||
| 414 | netdev_enter_failed(netdev); | |||
| 415 | return -EINVAL22; | |||
| 416 | } | |||
| 417 | } | |||
| 418 | ||||
| 419 | if (!streq(kind, received_kind)(strcmp((kind),(received_kind)) == 0)) { | |||
| 420 | log_netdev_error(netdev,({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 422, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Received newlink with wrong KIND %s, " "expected %s", received_kind, kind) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 422 , __func__, "Received newlink with wrong KIND %s, " "expected %s" , received_kind, kind); }) | |||
| 421 | "Received newlink with wrong KIND %s, "({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 422, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Received newlink with wrong KIND %s, " "expected %s", received_kind, kind) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 422 , __func__, "Received newlink with wrong KIND %s, " "expected %s" , received_kind, kind); }) | |||
| 422 | "expected %s", received_kind, kind)({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0 , "../src/network/netdev/netdev.c", 422, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Received newlink with wrong KIND %s, " "expected %s", received_kind, kind) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/network/netdev/netdev.c", 422 , __func__, "Received newlink with wrong KIND %s, " "expected %s" , received_kind, kind); }); | |||
| 423 | netdev_enter_failed(netdev); | |||
| 424 | return r; | |||
| 425 | } | |||
| 426 | ||||
| 427 | netdev->ifindex = ifindex; | |||
| 428 | ||||
| 429 | log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex)({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 429, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "netdev has index %d" , netdev->ifindex) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/network/netdev/netdev.c", 429 , __func__, "netdev has index %d", netdev->ifindex); }); | |||
| 430 | ||||
| 431 | netdev_enter_ready(netdev); | |||
| 432 | ||||
| 433 | return 0; | |||
| 434 | } | |||
| 435 | ||||
| 436 | #define HASH_KEY((const sd_id128_t) { .bytes = { 0x52, 0xe1, 0x45, 0xbd, 0x00 , 0x6f, 0x29, 0x96, 0x21, 0xc6, 0x30, 0x6d, 0x83, 0x71, 0x04, 0x48 }}) SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)((const sd_id128_t) { .bytes = { 0x52, 0xe1, 0x45, 0xbd, 0x00 , 0x6f, 0x29, 0x96, 0x21, 0xc6, 0x30, 0x6d, 0x83, 0x71, 0x04, 0x48 }}) | |||
| 437 | ||||
| 438 | int netdev_get_mac(const char *ifname, struct ether_addr **ret) { | |||
| 439 | _cleanup_free___attribute__((cleanup(freep))) struct ether_addr *mac = NULL((void*)0); | |||
| 440 | uint64_t result; | |||
| 441 | size_t l, sz; | |||
| 442 | uint8_t *v; | |||
| 443 | int r; | |||
| 444 | ||||
| 445 | assert(ifname)do { if ((__builtin_expect(!!(!(ifname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ifname"), "../src/network/netdev/netdev.c" , 445, __PRETTY_FUNCTION__); } while (0); | |||
| 446 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/netdev/netdev.c" , 446, __PRETTY_FUNCTION__); } while (0); | |||
| 447 | ||||
| 448 | mac = new0(struct ether_addr, 1)((struct ether_addr*) calloc((1), sizeof(struct ether_addr))); | |||
| 449 | if (!mac) | |||
| 450 | return -ENOMEM12; | |||
| 451 | ||||
| 452 | l = strlen(ifname); | |||
| 453 | sz = sizeof(sd_id128_t) + l; | |||
| 454 | v = alloca(sz)__builtin_alloca (sz); | |||
| 455 | ||||
| 456 | /* fetch some persistent data unique to the machine */ | |||
| 457 | r = sd_id128_get_machine((sd_id128_t*) v); | |||
| 458 | if (r < 0) | |||
| 459 | return r; | |||
| 460 | ||||
| 461 | /* combine with some data unique (on this machine) to this | |||
| 462 | * netdev */ | |||
| 463 | memcpy(v + sizeof(sd_id128_t), ifname, l); | |||
| 464 | ||||
| 465 | /* Let's hash the host machine ID plus the container name. We | |||
| 466 | * use a fixed, but originally randomly created hash key here. */ | |||
| 467 | result = siphash24(v, sz, HASH_KEY((const sd_id128_t) { .bytes = { 0x52, 0xe1, 0x45, 0xbd, 0x00 , 0x6f, 0x29, 0x96, 0x21, 0xc6, 0x30, 0x6d, 0x83, 0x71, 0x04, 0x48 }}).bytes); | |||
| 468 | ||||
| 469 | assert_cc(ETH_ALEN <= sizeof(result))GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_14 { char x[(6 <= sizeof(result)) ? 0 : -1]; }; GCC diagnostic pop ; | |||
| 470 | memcpy(mac->ether_addr_octet, &result, ETH_ALEN6); | |||
| 471 | ||||
| 472 | /* see eth_random_addr in the kernel */ | |||
| 473 | mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ | |||
| 474 | mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ | |||
| 475 | ||||
| 476 | *ret = TAKE_PTR(mac)({ typeof(mac) _ptr_ = (mac); (mac) = ((void*)0); _ptr_; }); | |||
| 477 | ||||
| 478 | return 0; | |||
| 479 | } | |||
| 480 | ||||
| 481 | static int netdev_create(NetDev *netdev, Link *link, | |||
| 482 | sd_netlink_message_handler_t callback) { | |||
| 483 | int r; | |||
| 484 | ||||
| 485 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 485, __PRETTY_FUNCTION__); } while (0); | |||
| 486 | assert(!link || callback)do { if ((__builtin_expect(!!(!(!link || callback)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!link || callback"), "../src/network/netdev/netdev.c" , 486, __PRETTY_FUNCTION__); } while (0); | |||
| 487 | ||||
| 488 | /* create netdev */ | |||
| 489 | if (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->create) { | |||
| 490 | assert(!link)do { if ((__builtin_expect(!!(!(!link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!link"), "../src/network/netdev/netdev.c" , 490, __PRETTY_FUNCTION__); } while (0); | |||
| 491 | ||||
| 492 | r = NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->create(netdev); | |||
| 493 | if (r < 0) | |||
| 494 | return r; | |||
| 495 | ||||
| 496 | log_netdev_debug(netdev, "Created")({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 496, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Created") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c" , 496, __func__, "Created"); }); | |||
| 497 | } else { | |||
| 498 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *m = NULL((void*)0); | |||
| 499 | ||||
| 500 | r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINKRTM_NEWLINK, 0); | |||
| 501 | if (r < 0) | |||
| 502 | return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 502, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not allocate RTM_NEWLINK message: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 502, __func__, "Could not allocate RTM_NEWLINK message: %m" ); }); | |||
| 503 | ||||
| 504 | r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname); | |||
| 505 | if (r < 0) | |||
| 506 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 506, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_IFNAME, attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 506, __func__, "Could not append IFLA_IFNAME, attribute: %m" ); }); | |||
| 507 | ||||
| 508 | if (netdev->mac) { | |||
| 509 | r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); | |||
| 510 | if (r < 0) | |||
| 511 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 511, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_ADDRESS attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 511, __func__, "Could not append IFLA_ADDRESS attribute: %m" ); }); | |||
| 512 | } | |||
| 513 | ||||
| 514 | if (netdev->mtu) { | |||
| 515 | r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu); | |||
| 516 | if (r < 0) | |||
| 517 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 517, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_MTU attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 517, __func__, "Could not append IFLA_MTU attribute: %m" ); }); | |||
| 518 | } | |||
| 519 | ||||
| 520 | if (link) { | |||
| 521 | r = sd_netlink_message_append_u32(m, IFLA_LINK, link->ifindex); | |||
| 522 | if (r < 0) | |||
| 523 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINK attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 523, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_LINK attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 523, __func__, "Could not append IFLA_LINK attribute: %m" ); }); | |||
| 524 | } | |||
| 525 | ||||
| 526 | r = sd_netlink_message_open_container(m, IFLA_LINKINFOIFLA_LINKINFO); | |||
| 527 | if (r < 0) | |||
| 528 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 528, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_LINKINFO attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 528, __func__, "Could not append IFLA_LINKINFO attribute: %m" ); }); | |||
| 529 | ||||
| 530 | r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); | |||
| 531 | if (r < 0) | |||
| 532 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 532, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_INFO_DATA attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 532, __func__, "Could not append IFLA_INFO_DATA attribute: %m" ); }); | |||
| 533 | ||||
| 534 | if (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->fill_message_create) { | |||
| 535 | r = NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->fill_message_create(netdev, link, m); | |||
| 536 | if (r < 0) | |||
| 537 | return r; | |||
| 538 | } | |||
| 539 | ||||
| 540 | r = sd_netlink_message_close_container(m); | |||
| 541 | if (r < 0) | |||
| 542 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 542, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_INFO_DATA attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 542, __func__, "Could not append IFLA_INFO_DATA attribute: %m" ); }); | |||
| 543 | ||||
| 544 | r = sd_netlink_message_close_container(m); | |||
| 545 | if (r < 0) | |||
| 546 | return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 546, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not append IFLA_LINKINFO attribute: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 546, __func__, "Could not append IFLA_LINKINFO attribute: %m" ); }); | |||
| 547 | ||||
| 548 | if (link) { | |||
| 549 | r = sd_netlink_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL((void*)0)); | |||
| 550 | if (r < 0) | |||
| 551 | return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 551, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not send rtnetlink message: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 551, __func__, "Could not send rtnetlink message: %m" ); }); | |||
| 552 | ||||
| 553 | link_ref(link); | |||
| 554 | } else { | |||
| 555 | r = sd_netlink_call_async(netdev->manager->rtnl, m, netdev_create_handler, netdev, 0, NULL((void*)0)); | |||
| 556 | if (r < 0) | |||
| 557 | return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r , "../src/network/netdev/netdev.c", 557, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Could not send rtnetlink message: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/network/netdev/netdev.c", 557, __func__, "Could not send rtnetlink message: %m" ); }); | |||
| 558 | ||||
| 559 | netdev_ref(netdev); | |||
| 560 | } | |||
| 561 | ||||
| 562 | netdev->state = NETDEV_STATE_CREATING; | |||
| 563 | ||||
| 564 | log_netdev_debug(netdev, "Creating")({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 564, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "Creating") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c" , 564, __func__, "Creating"); }); | |||
| 565 | } | |||
| 566 | ||||
| 567 | return 0; | |||
| 568 | } | |||
| 569 | ||||
| 570 | /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */ | |||
| 571 | int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { | |||
| 572 | int r; | |||
| 573 | ||||
| 574 | assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/netdev.c" , 574, __PRETTY_FUNCTION__); } while (0); | |||
| 575 | assert(netdev->manager)do { if ((__builtin_expect(!!(!(netdev->manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("netdev->manager"), "../src/network/netdev/netdev.c" , 575, __PRETTY_FUNCTION__); } while (0); | |||
| 576 | assert(netdev->manager->rtnl)do { if ((__builtin_expect(!!(!(netdev->manager->rtnl)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("netdev->manager->rtnl" ), "../src/network/netdev/netdev.c", 576, __PRETTY_FUNCTION__ ); } while (0); | |||
| 577 | assert(NETDEV_VTABLE(netdev))do { if ((__builtin_expect(!!(!(((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev)->kind] : ((void*)0)))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("NETDEV_VTABLE(netdev)"), "../src/network/netdev/netdev.c" , 577, __PRETTY_FUNCTION__); } while (0); | |||
| 578 | ||||
| 579 | switch (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->create_type) { | |||
| 580 | case NETDEV_CREATE_MASTER: | |||
| 581 | r = netdev_enslave(netdev, link, callback); | |||
| 582 | if (r < 0) | |||
| 583 | return r; | |||
| 584 | ||||
| 585 | break; | |||
| 586 | case NETDEV_CREATE_STACKED: | |||
| 587 | r = netdev_create(netdev, link, callback); | |||
| 588 | if (r < 0) | |||
| 589 | return r; | |||
| 590 | ||||
| 591 | break; | |||
| 592 | default: | |||
| 593 | assert_not_reached("Can not join independent netdev")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Can not join independent netdev"), "../src/network/netdev/netdev.c" , 593, __PRETTY_FUNCTION__); } while (0); | |||
| 594 | } | |||
| 595 | ||||
| 596 | return 0; | |||
| 597 | } | |||
| 598 | ||||
| 599 | static int netdev_load_one(Manager *manager, const char *filename) { | |||
| 600 | _cleanup_(netdev_unrefp)__attribute__((cleanup(netdev_unrefp))) NetDev *netdev_raw = NULL((void*)0), *netdev = NULL((void*)0); | |||
| 601 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *file = NULL((void*)0); | |||
| 602 | const char *dropin_dirname; | |||
| 603 | bool_Bool independent = false0; | |||
| 604 | int r; | |||
| 605 | ||||
| 606 | assert(manager)do { if ((__builtin_expect(!!(!(manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("manager"), "../src/network/netdev/netdev.c" , 606, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 607 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/network/netdev/netdev.c" , 607, __PRETTY_FUNCTION__); } while (0); | |||
| 608 | ||||
| 609 | file = fopen(filename, "re"); | |||
| 610 | if (!file) { | |||
| 611 | if (errno(*__errno_location ()) == ENOENT2) | |||
| 612 | return 0; | |||
| 613 | ||||
| 614 | return -errno(*__errno_location ()); | |||
| 615 | } | |||
| 616 | ||||
| 617 | if (null_or_empty_fd(fileno(file))) { | |||
| 618 | log_debug("Skipping empty file: %s", filename)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/netdev/netdev.c", 618, __func__, "Skipping empty file: %s" , filename) : -abs(_e); }); | |||
| 619 | return 0; | |||
| 620 | } | |||
| 621 | ||||
| 622 | netdev_raw = new0(NetDev, 1)((NetDev*) calloc((1), sizeof(NetDev))); | |||
| 623 | if (!netdev_raw) | |||
| 624 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/netdev.c" , 624, __func__); | |||
| 625 | ||||
| 626 | netdev_raw->n_ref = 1; | |||
| 627 | netdev_raw->kind = _NETDEV_KIND_INVALID; | |||
| 628 | netdev_raw->state = _NETDEV_STATE_INVALID; /* an invalid state means done() of the implementation won't be called on destruction */ | |||
| 629 | ||||
| 630 | dropin_dirname = strjoina(basename(filename), ".d")({ const char *_appendees_[] = { basename(filename), ".d" }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 631 | r = config_parse_many(filename, network_dirs, dropin_dirname, | |||
| 632 | "Match\0NetDev\0", | |||
| 633 | config_item_perf_lookup, network_netdev_gperf_lookup, | |||
| 634 | CONFIG_PARSE_WARN|CONFIG_PARSE_RELAXED, netdev_raw); | |||
| 635 | if (r < 0) | |||
| 636 | return r; | |||
| 637 | ||||
| 638 | /* skip out early if configuration does not match the environment */ | |||
| 639 | if (net_match_config(NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
| 640 | netdev_raw->match_host, netdev_raw->match_virt, | |||
| 641 | netdev_raw->match_kernel_cmdline, netdev_raw->match_kernel_version, | |||
| 642 | netdev_raw->match_arch, | |||
| 643 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)) <= 0) | |||
| 644 | return 0; | |||
| 645 | ||||
| 646 | if (netdev_raw->kind == _NETDEV_KIND_INVALID) { | |||
| 647 | log_warning("NetDev has no Kind configured in %s. Ignoring", filename)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/netdev/netdev.c", 647, __func__, "NetDev has no Kind configured in %s. Ignoring" , filename) : -abs(_e); }); | |||
| 648 | return 0; | |||
| 649 | } | |||
| 650 | ||||
| 651 | if (!netdev_raw->ifname) { | |||
| 652 | log_warning("NetDev without Name configured in %s. Ignoring", filename)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/netdev/netdev.c", 652, __func__, "NetDev without Name configured in %s. Ignoring" , filename) : -abs(_e); }); | |||
| 653 | return 0; | |||
| 654 | } | |||
| 655 | ||||
| 656 | r = fseek(file, 0, SEEK_SET0); | |||
| 657 | if (r < 0) | |||
| 658 | return -errno(*__errno_location ()); | |||
| 659 | ||||
| 660 | netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size)(calloc(1, (((netdev_raw)->kind != _NETDEV_KIND_INVALID ? netdev_vtable [(netdev_raw)->kind] : ((void*)0))->object_size))); | |||
| 661 | if (!netdev) | |||
| 662 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/netdev.c" , 662, __func__); | |||
| 663 | ||||
| 664 | netdev->n_ref = 1; | |||
| 665 | netdev->manager = manager; | |||
| 666 | netdev->kind = netdev_raw->kind; | |||
| 667 | netdev->state = NETDEV_STATE_LOADING; /* we initialize the state here for the first time, so that done() will be called on destruction */ | |||
| 668 | ||||
| 669 | if (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->init) | |||
| 670 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->init(netdev); | |||
| 671 | ||||
| 672 | r = config_parse(NULL((void*)0), filename, file, | |||
| 673 | NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->sections, | |||
| ||||
| 674 | config_item_perf_lookup, network_netdev_gperf_lookup, | |||
| 675 | CONFIG_PARSE_WARN, netdev); | |||
| 676 | if (r < 0) | |||
| 677 | return r; | |||
| 678 | ||||
| 679 | /* verify configuration */ | |||
| 680 | if (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->config_verify) { | |||
| 681 | r = NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->config_verify(netdev, filename); | |||
| 682 | if (r < 0) | |||
| 683 | return 0; | |||
| 684 | } | |||
| 685 | ||||
| 686 | netdev->filename = strdup(filename); | |||
| 687 | if (!netdev->filename) | |||
| 688 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/netdev.c" , 688, __func__); | |||
| 689 | ||||
| 690 | if (!netdev->mac && netdev->kind != NETDEV_KIND_VLAN) { | |||
| 691 | r = netdev_get_mac(netdev->ifname, &netdev->mac); | |||
| 692 | if (r < 0) | |||
| 693 | return log_error_errno(r, "Failed to generate predictable MAC address for %s: %m", netdev->ifname)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/netdev/netdev.c", 693, __func__, "Failed to generate predictable MAC address for %s: %m" , netdev->ifname) : -abs(_e); }); | |||
| 694 | } | |||
| 695 | ||||
| 696 | r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev); | |||
| 697 | if (r < 0) | |||
| 698 | return r; | |||
| 699 | ||||
| 700 | LIST_HEAD_INIT(netdev->callbacks)do { (netdev->callbacks) = ((void*)0); } while (0); | |||
| 701 | ||||
| 702 | log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind))({ const NetDev *_n = (netdev); _n ? log_object_internal(7, 0 , "../src/network/netdev/netdev.c", 702, __func__, "INTERFACE=" , _n->ifname, ((void*)0), ((void*)0), "loaded %s", netdev_kind_to_string (netdev->kind)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/netdev/netdev.c", 702, __func__ , "loaded %s", netdev_kind_to_string(netdev->kind)); }); | |||
| 703 | ||||
| 704 | switch (NETDEV_VTABLE(netdev)((netdev)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(netdev )->kind] : ((void*)0))->create_type) { | |||
| 705 | case NETDEV_CREATE_MASTER: | |||
| 706 | case NETDEV_CREATE_INDEPENDENT: | |||
| 707 | r = netdev_create(netdev, NULL((void*)0), NULL((void*)0)); | |||
| 708 | if (r < 0) | |||
| 709 | return r; | |||
| 710 | ||||
| 711 | break; | |||
| 712 | default: | |||
| 713 | break; | |||
| 714 | } | |||
| 715 | ||||
| 716 | switch (netdev->kind) { | |||
| 717 | case NETDEV_KIND_IPIP: | |||
| 718 | independent = IPIP(netdev)->independent; | |||
| 719 | break; | |||
| 720 | case NETDEV_KIND_GRE: | |||
| 721 | independent = GRE(netdev)->independent; | |||
| 722 | break; | |||
| 723 | case NETDEV_KIND_GRETAP: | |||
| 724 | independent = GRETAP(netdev)->independent; | |||
| 725 | break; | |||
| 726 | case NETDEV_KIND_IP6GRE: | |||
| 727 | independent = IP6GRE(netdev)->independent; | |||
| 728 | break; | |||
| 729 | case NETDEV_KIND_IP6GRETAP: | |||
| 730 | independent = IP6GRETAP(netdev)->independent; | |||
| 731 | break; | |||
| 732 | case NETDEV_KIND_SIT: | |||
| 733 | independent = SIT(netdev)->independent; | |||
| 734 | break; | |||
| 735 | case NETDEV_KIND_VTI: | |||
| 736 | independent = VTI(netdev)->independent; | |||
| 737 | break; | |||
| 738 | case NETDEV_KIND_VTI6: | |||
| 739 | independent = VTI6(netdev)->independent; | |||
| 740 | break; | |||
| 741 | case NETDEV_KIND_IP6TNL: | |||
| 742 | independent = IP6TNL(netdev)->independent; | |||
| 743 | break; | |||
| 744 | default: | |||
| 745 | break; | |||
| 746 | } | |||
| 747 | ||||
| 748 | if (independent) { | |||
| 749 | r = netdev_create(netdev, NULL((void*)0), NULL((void*)0)); | |||
| 750 | if (r < 0) | |||
| 751 | return r; | |||
| 752 | } | |||
| 753 | ||||
| 754 | netdev = NULL((void*)0); | |||
| 755 | ||||
| 756 | return 0; | |||
| 757 | } | |||
| 758 | ||||
| 759 | int netdev_load(Manager *manager) { | |||
| 760 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **files = NULL((void*)0); | |||
| 761 | NetDev *netdev; | |||
| 762 | char **f; | |||
| 763 | int r; | |||
| 764 | ||||
| 765 | assert(manager)do { if ((__builtin_expect(!!(!(manager)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("manager"), "../src/network/netdev/netdev.c" , 765, __PRETTY_FUNCTION__); } while (0); | |||
| 766 | ||||
| 767 | while ((netdev = hashmap_first(manager->netdevs))) | |||
| 768 | netdev_unref(netdev); | |||
| 769 | ||||
| 770 | r = conf_files_list_strv(&files, ".netdev", NULL((void*)0), 0, network_dirs); | |||
| 771 | if (r < 0) | |||
| 772 | return log_error_errno(r, "Failed to enumerate netdev files: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/netdev/netdev.c", 772, __func__, "Failed to enumerate netdev files: %m" ) : -abs(_e); }); | |||
| 773 | ||||
| 774 | STRV_FOREACH_BACKWARDS(f, files)for (f = ({ char **_l = files; _l ? _l + strv_length(_l) - 1U : ((void*)0); }); (files) && ((f) >= (files)); (f )--) { | |||
| 775 | r = netdev_load_one(manager, *f); | |||
| 776 | if (r < 0) | |||
| 777 | return r; | |||
| 778 | } | |||
| 779 | ||||
| 780 | return 0; | |||
| 781 | } |