]>
Commit | Line | Data |
---|---|---|
f579559b TG |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | /*** | |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2013 Tom Gundersen <teg@jklm.no> | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU Lesser General Public License as published by | |
10 | the Free Software Foundation; either version 2.1 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | Lesser General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU Lesser General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
22 | #pragma once | |
23 | ||
24 | #include <arpa/inet.h> | |
f579559b TG |
25 | |
26 | #include "sd-event.h" | |
27 | #include "sd-rtnl.h" | |
1346b1f0 | 28 | #include "sd-bus.h" |
f5be5601 | 29 | #include "sd-dhcp-client.h" |
5c1d3fc9 | 30 | #include "sd-ipv4ll.h" |
f579559b TG |
31 | #include "udev.h" |
32 | ||
33 | #include "rtnl-util.h" | |
34 | #include "hashmap.h" | |
35 | #include "list.h" | |
06f021a8 | 36 | #include "set.h" |
2cc412b5 | 37 | #include "condition-util.h" |
f579559b | 38 | |
aba496a5 UTL |
39 | #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU |
40 | ||
1a436809 | 41 | typedef struct NetDev NetDev; |
f579559b TG |
42 | typedef struct Network Network; |
43 | typedef struct Link Link; | |
44 | typedef struct Address Address; | |
45 | typedef struct Route Route; | |
46 | typedef struct Manager Manager; | |
47 | ||
52433f6b | 48 | typedef struct netdev_enslave_callback netdev_enslave_callback; |
02b59d57 | 49 | |
52433f6b | 50 | struct netdev_enslave_callback { |
02b59d57 TG |
51 | sd_rtnl_message_handler_t callback; |
52 | Link *link; | |
53 | ||
52433f6b | 54 | LIST_FIELDS(netdev_enslave_callback, callbacks); |
02b59d57 TG |
55 | }; |
56 | ||
fe6b2d55 TG |
57 | typedef enum MacVlanMode { |
58 | NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE, | |
59 | NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA, | |
60 | NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE, | |
61 | NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU, | |
62 | _NETDEV_MACVLAN_MODE_MAX, | |
63 | _NETDEV_MACVLAN_MODE_INVALID = -1 | |
64 | } MacVlanMode; | |
65 | ||
1a436809 | 66 | typedef enum NetDevKind { |
52433f6b TG |
67 | NETDEV_KIND_BRIDGE, |
68 | NETDEV_KIND_BOND, | |
54abf461 | 69 | NETDEV_KIND_VLAN, |
fe6b2d55 | 70 | NETDEV_KIND_MACVLAN, |
52433f6b TG |
71 | _NETDEV_KIND_MAX, |
72 | _NETDEV_KIND_INVALID = -1 | |
1a436809 | 73 | } NetDevKind; |
52433f6b | 74 | |
1a436809 | 75 | typedef enum NetDevState { |
52433f6b TG |
76 | NETDEV_STATE_FAILED, |
77 | NETDEV_STATE_CREATING, | |
78 | NETDEV_STATE_READY, | |
2cc7e981 | 79 | NETDEV_STATE_LINGER, |
52433f6b TG |
80 | _NETDEV_STATE_MAX, |
81 | _NETDEV_STATE_INVALID = -1, | |
1a436809 | 82 | } NetDevState; |
52433f6b | 83 | |
1a436809 | 84 | struct NetDev { |
02b59d57 TG |
85 | Manager *manager; |
86 | ||
14b746f7 TG |
87 | int n_ref; |
88 | ||
02b59d57 TG |
89 | char *filename; |
90 | ||
edbb03e9 TG |
91 | Condition *match_host; |
92 | Condition *match_virt; | |
93 | Condition *match_kernel; | |
94 | Condition *match_arch; | |
c0dda186 | 95 | |
02b59d57 TG |
96 | char *description; |
97 | char *name; | |
1a436809 | 98 | NetDevKind kind; |
02b59d57 | 99 | |
672682a6 | 100 | uint64_t vlanid; |
fe6b2d55 | 101 | int32_t macvlan_mode; |
54abf461 | 102 | |
50add290 | 103 | int ifindex; |
1a436809 | 104 | NetDevState state; |
02b59d57 | 105 | |
52433f6b | 106 | LIST_HEAD(netdev_enslave_callback, callbacks); |
02b59d57 TG |
107 | }; |
108 | ||
f579559b TG |
109 | struct Network { |
110 | Manager *manager; | |
111 | ||
112 | char *filename; | |
113 | ||
114 | struct ether_addr *match_mac; | |
115 | char *match_path; | |
116 | char *match_driver; | |
117 | char *match_type; | |
118 | char *match_name; | |
2cc412b5 TG |
119 | Condition *match_host; |
120 | Condition *match_virt; | |
121 | Condition *match_kernel; | |
edbb03e9 | 122 | Condition *match_arch; |
f579559b TG |
123 | |
124 | char *description; | |
1a436809 TG |
125 | NetDev *bridge; |
126 | NetDev *bond; | |
672682a6 | 127 | Hashmap *vlans; |
fe6b2d55 | 128 | Hashmap *macvlans; |
f5be5601 | 129 | bool dhcp; |
5be4d38e | 130 | bool dhcp_dns; |
4f882b2a | 131 | bool dhcp_mtu; |
1346b1f0 | 132 | bool dhcp_hostname; |
039ebe6a | 133 | bool dhcp_domainname; |
eb27aeca | 134 | bool dhcp_critical; |
5c1d3fc9 | 135 | bool ipv4ll; |
f579559b | 136 | |
f048a16b TG |
137 | LIST_HEAD(Address, static_addresses); |
138 | LIST_HEAD(Route, static_routes); | |
f579559b | 139 | |
6ae115c1 TG |
140 | Hashmap *addresses_by_section; |
141 | Hashmap *routes_by_section; | |
142 | ||
06f021a8 TG |
143 | Set *dns; |
144 | ||
f579559b TG |
145 | LIST_FIELDS(Network, networks); |
146 | }; | |
147 | ||
148 | struct Address { | |
149 | Network *network; | |
6ae115c1 | 150 | uint64_t section; |
f579559b TG |
151 | |
152 | unsigned char family; | |
153 | unsigned char prefixlen; | |
5c1d3fc9 | 154 | unsigned char scope; |
f579559b TG |
155 | char *label; |
156 | ||
eb0ea358 | 157 | struct in_addr broadcast; |
aba496a5 | 158 | struct ifa_cacheinfo cinfo; |
8cd11a0f | 159 | |
f579559b TG |
160 | union { |
161 | struct in_addr in; | |
162 | struct in6_addr in6; | |
163 | } in_addr; | |
164 | ||
f048a16b | 165 | LIST_FIELDS(Address, static_addresses); |
f579559b TG |
166 | }; |
167 | ||
168 | struct Route { | |
169 | Network *network; | |
6ae115c1 | 170 | uint64_t section; |
f579559b TG |
171 | |
172 | unsigned char family; | |
6ae115c1 | 173 | unsigned char dst_prefixlen; |
5c1d3fc9 UTL |
174 | unsigned char scope; |
175 | uint32_t metrics; | |
f579559b TG |
176 | |
177 | union { | |
178 | struct in_addr in; | |
179 | struct in6_addr in6; | |
180 | } in_addr; | |
181 | ||
6ae115c1 TG |
182 | union { |
183 | struct in_addr in; | |
184 | struct in6_addr in6; | |
185 | } dst_addr; | |
186 | ||
f048a16b | 187 | LIST_FIELDS(Route, static_routes); |
f579559b TG |
188 | }; |
189 | ||
f882c247 | 190 | typedef enum LinkState { |
505f8da7 | 191 | LINK_STATE_INITIALIZING, |
52433f6b | 192 | LINK_STATE_ENSLAVING, |
ef1ba606 TG |
193 | LINK_STATE_SETTING_ADDRESSES, |
194 | LINK_STATE_SETTING_ROUTES, | |
f882c247 | 195 | LINK_STATE_CONFIGURED, |
57bd6899 | 196 | LINK_STATE_UNMANAGED, |
f882c247 | 197 | LINK_STATE_FAILED, |
370e9930 | 198 | LINK_STATE_LINGER, |
f882c247 TG |
199 | _LINK_STATE_MAX, |
200 | _LINK_STATE_INVALID = -1 | |
201 | } LinkState; | |
202 | ||
f579559b TG |
203 | struct Link { |
204 | Manager *manager; | |
205 | ||
14b746f7 TG |
206 | int n_ref; |
207 | ||
0617ffab | 208 | uint64_t ifindex; |
c166a070 | 209 | char *ifname; |
fe8db0c5 | 210 | char *state_file; |
8cd11a0f | 211 | struct ether_addr mac; |
b5db00e5 | 212 | struct udev_device *udev_device; |
f579559b TG |
213 | |
214 | unsigned flags; | |
1e9be60b | 215 | uint8_t operstate; |
f579559b TG |
216 | |
217 | Network *network; | |
f882c247 TG |
218 | |
219 | LinkState state; | |
220 | ||
f5be5601 TG |
221 | unsigned addr_messages; |
222 | unsigned route_messages; | |
52433f6b | 223 | unsigned enslaving; |
f5be5601 | 224 | |
a6cc569e TG |
225 | sd_dhcp_client *dhcp_client; |
226 | sd_dhcp_lease *dhcp_lease; | |
68a8723c | 227 | char *lease_file; |
a6cc569e | 228 | uint16_t original_mtu; |
5c1d3fc9 | 229 | sd_ipv4ll *ipv4ll; |
f579559b TG |
230 | }; |
231 | ||
232 | struct Manager { | |
233 | sd_rtnl *rtnl; | |
234 | sd_event *event; | |
1346b1f0 | 235 | sd_bus *bus; |
f579559b TG |
236 | struct udev *udev; |
237 | struct udev_monitor *udev_monitor; | |
238 | sd_event_source *udev_event_source; | |
0c2f9b84 TG |
239 | sd_event_source *sigterm_event_source; |
240 | sd_event_source *sigint_event_source; | |
f579559b | 241 | |
bbf7c048 TG |
242 | char *state_file; |
243 | ||
f579559b | 244 | Hashmap *links; |
52433f6b | 245 | Hashmap *netdevs; |
f579559b TG |
246 | LIST_HEAD(Network, networks); |
247 | ||
f579559b TG |
248 | usec_t network_dirs_ts_usec; |
249 | }; | |
250 | ||
2ad8416d ZJS |
251 | extern const char* const network_dirs[]; |
252 | ||
f579559b TG |
253 | /* Manager */ |
254 | ||
255 | int manager_new(Manager **ret); | |
256 | void manager_free(Manager *m); | |
257 | ||
02b59d57 TG |
258 | int manager_load_config(Manager *m); |
259 | bool manager_should_reload(Manager *m); | |
260 | ||
505f8da7 | 261 | int manager_rtnl_enumerate_links(Manager *m); |
f579559b | 262 | |
f882c247 | 263 | int manager_rtnl_listen(Manager *m); |
505f8da7 | 264 | int manager_udev_listen(Manager *m); |
1346b1f0 | 265 | int manager_bus_listen(Manager *m); |
f882c247 | 266 | |
3bef724f | 267 | int manager_update_resolv_conf(Manager *m); |
bbf7c048 | 268 | int manager_save(Manager *m); |
3bef724f | 269 | |
f579559b TG |
270 | DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); |
271 | #define _cleanup_manager_free_ _cleanup_(manager_freep) | |
272 | ||
1a436809 | 273 | /* NetDev */ |
52433f6b TG |
274 | |
275 | int netdev_load(Manager *manager); | |
2cc7e981 | 276 | void netdev_drop(NetDev *netdev); |
02b59d57 | 277 | |
14b746f7 TG |
278 | NetDev *netdev_unref(NetDev *netdev); |
279 | NetDev *netdev_ref(NetDev *netdev); | |
02b59d57 | 280 | |
14b746f7 TG |
281 | DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); |
282 | #define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp) | |
02b59d57 | 283 | |
1a436809 | 284 | int netdev_get(Manager *manager, const char *name, NetDev **ret); |
d39edfc7 | 285 | int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink); |
1a436809 | 286 | int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb); |
02b59d57 | 287 | |
1a436809 TG |
288 | const char *netdev_kind_to_string(NetDevKind d) _const_; |
289 | NetDevKind netdev_kind_from_string(const char *d) _pure_; | |
52433f6b | 290 | |
fe6b2d55 TG |
291 | const char *macvlan_mode_to_string(MacVlanMode d) _const_; |
292 | MacVlanMode macvlan_mode_from_string(const char *d) _pure_; | |
293 | ||
52433f6b | 294 | 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); |
02b59d57 | 295 | |
fe6b2d55 TG |
296 | int config_parse_macvlan_mode(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); |
297 | ||
c0dda186 TG |
298 | /* gperf */ |
299 | const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length); | |
300 | ||
f579559b TG |
301 | /* Network */ |
302 | ||
303 | int network_load(Manager *manager); | |
f579559b TG |
304 | |
305 | void network_free(Network *network); | |
306 | ||
307 | DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); | |
308 | #define _cleanup_network_free_ _cleanup_(network_freep) | |
309 | ||
505f8da7 TG |
310 | int network_get(Manager *manager, struct udev_device *device, |
311 | const char *ifname, const struct ether_addr *mac, | |
312 | Network **ret); | |
f579559b TG |
313 | int network_apply(Manager *manager, Network *network, Link *link); |
314 | ||
69a93e7d | 315 | int config_parse_netdev(const char *unit, const char *filename, unsigned line, |
02b59d57 TG |
316 | const char *section, unsigned section_line, const char *lvalue, |
317 | int ltype, const char *rvalue, void *data, void *userdata); | |
318 | ||
319 | /* gperf */ | |
c0dda186 | 320 | const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length); |
f579559b TG |
321 | |
322 | /* Route */ | |
f048a16b TG |
323 | int route_new_static(Network *network, unsigned section, Route **ret); |
324 | int route_new_dynamic(Route **ret); | |
f579559b | 325 | void route_free(Route *route); |
f882c247 | 326 | int route_configure(Route *route, Link *link, sd_rtnl_message_handler_t callback); |
5c1d3fc9 UTL |
327 | int route_drop(Route *route, Link *link, sd_rtnl_message_handler_t callback); |
328 | ||
f579559b TG |
329 | |
330 | DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); | |
331 | #define _cleanup_route_free_ _cleanup_(route_freep) | |
332 | ||
333 | int config_parse_gateway(const char *unit, const char *filename, unsigned line, | |
71a61510 TG |
334 | const char *section, unsigned section_line, const char *lvalue, |
335 | int ltype, const char *rvalue, void *data, void *userdata); | |
f579559b | 336 | |
6ae115c1 TG |
337 | int config_parse_destination(const char *unit, const char *filename, unsigned line, |
338 | const char *section, unsigned section_line, const char *lvalue, | |
339 | int ltype, const char *rvalue, void *data, void *userdata); | |
340 | ||
f579559b | 341 | /* Address */ |
f048a16b TG |
342 | int address_new_static(Network *network, unsigned section, Address **ret); |
343 | int address_new_dynamic(Address **ret); | |
f579559b | 344 | void address_free(Address *address); |
f882c247 | 345 | int address_configure(Address *address, Link *link, sd_rtnl_message_handler_t callback); |
aba496a5 | 346 | int address_update(Address *address, Link *link, sd_rtnl_message_handler_t callback); |
407fe036 | 347 | int address_drop(Address *address, Link *link, sd_rtnl_message_handler_t callback); |
f579559b TG |
348 | |
349 | DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); | |
350 | #define _cleanup_address_free_ _cleanup_(address_freep) | |
351 | ||
3bef724f TG |
352 | int config_parse_dns(const char *unit, const char *filename, unsigned line, |
353 | const char *section, unsigned section_line, const char *lvalue, | |
354 | int ltype, const char *rvalue, void *data, void *userdata); | |
355 | ||
f579559b | 356 | int config_parse_address(const char *unit, const char *filename, unsigned line, |
71a61510 TG |
357 | const char *section, unsigned section_line, const char *lvalue, |
358 | int ltype, const char *rvalue, void *data, void *userdata); | |
f579559b | 359 | |
eb0ea358 TG |
360 | int config_parse_broadcast(const char *unit, const char *filename, unsigned line, |
361 | const char *section, unsigned section_line, const char *lvalue, | |
362 | int ltype, const char *rvalue, void *data, void *userdata); | |
363 | ||
6ae115c1 TG |
364 | int config_parse_label(const char *unit, const char *filename, unsigned line, |
365 | const char *section, unsigned section_line, const char *lvalue, | |
366 | int ltype, const char *rvalue, void *data, void *userdata); | |
367 | ||
f579559b TG |
368 | /* Link */ |
369 | ||
14b746f7 TG |
370 | Link *link_unref(Link *link); |
371 | Link *link_ref(Link *link); | |
11a7f229 | 372 | int link_get(Manager *m, int ifindex, Link **ret); |
505f8da7 | 373 | int link_add(Manager *manager, sd_rtnl_message *message, Link **ret); |
370e9930 | 374 | void link_drop(Link *link); |
f579559b | 375 | |
22936833 | 376 | int link_update(Link *link, sd_rtnl_message *message); |
dd3efc09 | 377 | |
505f8da7 TG |
378 | int link_initialized(Link *link, struct udev_device *device); |
379 | ||
fe8db0c5 TG |
380 | int link_save(Link *link); |
381 | ||
bbf7c048 TG |
382 | bool link_has_carrier(unsigned flags, uint8_t operstate); |
383 | ||
fe8db0c5 TG |
384 | const char* link_state_to_string(LinkState s) _const_; |
385 | LinkState link_state_from_string(const char *s) _pure_; | |
386 | ||
14b746f7 TG |
387 | DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); |
388 | #define _cleanup_link_unref_ _cleanup_(link_unrefp) | |
3333d748 ZJS |
389 | |
390 | /* Macros which append INTERFACE= to the message */ | |
391 | ||
39032b87 ZJS |
392 | #define log_full_link(level, link, fmt, ...) log_meta_object(level, __FILE__, __LINE__, __func__, "INTERFACE=", link->ifname, "%s: " fmt, link->ifname, ##__VA_ARGS__) |
393 | #define log_debug_link(link, ...) log_full_link(LOG_DEBUG, link, ##__VA_ARGS__) | |
394 | #define log_info_link(link, ...) log_full_link(LOG_INFO, link, ##__VA_ARGS__) | |
395 | #define log_notice_link(link, ...) log_full_link(LOG_NOTICE, link, ##__VA_ARGS__) | |
396 | #define log_warning_link(link, ...) log_full_link(LOG_WARNING, link, ##__VA_ARGS__) | |
397 | #define log_error_link(link, ...) log_full_link(LOG_ERR, link, ##__VA_ARGS__) | |
3333d748 ZJS |
398 | |
399 | #define log_struct_link(level, link, ...) log_struct(level, "INTERFACE=%s", link->ifname, __VA_ARGS__) | |
400 | ||
401 | /* More macros which append INTERFACE= to the message */ | |
402 | ||
52433f6b TG |
403 | #define log_full_netdev(level, netdev, fmt, ...) log_meta_object(level, __FILE__, __LINE__, __func__, "INTERFACE=", netdev->name, "%s: " fmt, netdev->name, ##__VA_ARGS__) |
404 | #define log_debug_netdev(netdev, ...) log_full_netdev(LOG_DEBUG, netdev, ##__VA_ARGS__) | |
405 | #define log_info_netdev(netdev, ...) log_full_netdev(LOG_INFO, netdev, ##__VA_ARGS__) | |
406 | #define log_notice_netdev(netdev, ...) log_full_netdev(LOG_NOTICE, netdev, ##__VA_ARGS__) | |
407 | #define log_warning_netdev(netdev, ...) log_full_netdev(LOG_WARNING, netdev,## __VA_ARGS__) | |
408 | #define log_error_netdev(netdev, ...) log_full_netdev(LOG_ERR, netdev, ##__VA_ARGS__) | |
3333d748 | 409 | |
52433f6b | 410 | #define log_struct_netdev(level, netdev, ...) log_struct(level, "INTERFACE=%s", netdev->name, __VA_ARGS__) |
3333d748 | 411 | |
52433f6b | 412 | #define NETDEV(netdev) "INTERFACE=%s", netdev->name |
62870613 ZJS |
413 | #define ADDRESS_FMT_VAL(address) \ |
414 | (address).s_addr & 0xFF, \ | |
415 | ((address).s_addr >> 8) & 0xFF, \ | |
416 | ((address).s_addr >> 16) & 0xFF, \ | |
417 | (address).s_addr >> 24 |