File: | build-scan/../src/network/netdev/netdev.c |
Warning: | line 680, column 13 Access to field 'config_verify' 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_15 { 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 | } |