]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/wait-online/link.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / network / wait-online / link.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "sd-network.h"
4
5 #include "alloc-util.h"
6 #include "hashmap.h"
7 #include "link.h"
8 #include "manager.h"
9 #include "string-util.h"
10
11 int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) {
12 _cleanup_(link_freep) Link *l = NULL;
13 _cleanup_free_ char *n = NULL;
14 int r;
15
16 assert(m);
17 assert(ifindex > 0);
18
19 r = hashmap_ensure_allocated(&m->links, NULL);
20 if (r < 0)
21 return r;
22
23 r = hashmap_ensure_allocated(&m->links_by_name, &string_hash_ops);
24 if (r < 0)
25 return r;
26
27 n = strdup(ifname);
28 if (!n)
29 return -ENOMEM;
30
31 l = new(Link, 1);
32 if (!l)
33 return -ENOMEM;
34
35 *l = (Link) {
36 .manager = m,
37 .ifname = TAKE_PTR(n),
38 .ifindex = ifindex,
39 .required_operstate = LINK_OPERSTATE_RANGE_DEFAULT,
40 };
41
42 r = hashmap_put(m->links_by_name, l->ifname, l);
43 if (r < 0)
44 return r;
45
46 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
47 if (r < 0)
48 return r;
49
50 if (ret)
51 *ret = l;
52
53 TAKE_PTR(l);
54 return 0;
55 }
56
57 Link *link_free(Link *l) {
58
59 if (!l)
60 return NULL;
61
62 if (l->manager) {
63 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
64 hashmap_remove(l->manager->links_by_name, l->ifname);
65 }
66
67 free(l->state);
68 free(l->ifname);
69 return mfree(l);
70 }
71
72 int link_update_rtnl(Link *l, sd_netlink_message *m) {
73 const char *ifname;
74 int r;
75
76 assert(l);
77 assert(l->manager);
78 assert(m);
79
80 r = sd_rtnl_message_link_get_flags(m, &l->flags);
81 if (r < 0)
82 return r;
83
84 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
85 if (r < 0)
86 return r;
87
88 if (!streq(l->ifname, ifname)) {
89 char *new_ifname;
90
91 new_ifname = strdup(ifname);
92 if (!new_ifname)
93 return -ENOMEM;
94
95 assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l);
96 free_and_replace(l->ifname, new_ifname);
97
98 r = hashmap_put(l->manager->links_by_name, l->ifname, l);
99 if (r < 0)
100 return r;
101 }
102
103 return 0;
104 }
105
106 int link_update_monitor(Link *l) {
107 _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL;
108 int r, ret = 0;
109
110 assert(l);
111 assert(l->ifname);
112
113 r = sd_network_link_get_required_for_online(l->ifindex);
114 if (r < 0)
115 ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, "
116 "ignoring: %m");
117 else
118 l->required_for_online = r > 0;
119
120 r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate);
121 if (r < 0)
122 ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m");
123 else if (isempty(required_operstate))
124 l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT;
125 else {
126 r = parse_operational_state_range(required_operstate, &l->required_operstate);
127 if (r < 0)
128 ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
129 "Failed to parse required operational state, ignoring: %m");
130 }
131
132 r = sd_network_link_get_operational_state(l->ifindex, &operstate);
133 if (r < 0)
134 ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m");
135 else {
136 LinkOperationalState s;
137
138 s = link_operstate_from_string(operstate);
139 if (s < 0)
140 ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
141 "Failed to parse operational state, ignoring: %m");
142 else
143 l->operational_state = s;
144 }
145
146 r = sd_network_link_get_setup_state(l->ifindex, &state);
147 if (r < 0)
148 ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m");
149 else
150 free_and_replace(l->state, state);
151
152 return ret;
153 }