]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
7de12ae7 | 2 | |
7de12ae7 | 3 | #include "sd-network.h" |
7de12ae7 | 4 | |
b5efdb8a | 5 | #include "alloc-util.h" |
c5fcf6e4 TG |
6 | #include "hashmap.h" |
7 | #include "link.h" | |
8 | #include "manager.h" | |
07630cea | 9 | #include "string-util.h" |
7de12ae7 TG |
10 | |
11 | int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { | |
12 | _cleanup_(link_freep) Link *l = NULL; | |
f023184e | 13 | _cleanup_free_ char *n = NULL; |
7de12ae7 TG |
14 | int r; |
15 | ||
16 | assert(m); | |
17 | assert(ifindex > 0); | |
ee9ead76 | 18 | assert(ifname); |
7de12ae7 | 19 | |
f023184e YW |
20 | n = strdup(ifname); |
21 | if (!n) | |
7de12ae7 TG |
22 | return -ENOMEM; |
23 | ||
f023184e YW |
24 | l = new(Link, 1); |
25 | if (!l) | |
7de12ae7 TG |
26 | return -ENOMEM; |
27 | ||
f023184e YW |
28 | *l = (Link) { |
29 | .manager = m, | |
30 | .ifname = TAKE_PTR(n), | |
31 | .ifindex = ifindex, | |
75cd4a5d | 32 | .required_operstate = LINK_OPERSTATE_RANGE_DEFAULT, |
f023184e YW |
33 | }; |
34 | ||
3f70f938 | 35 | r = hashmap_ensure_put(&m->links, NULL, INT_TO_PTR(ifindex), l); |
7de12ae7 TG |
36 | if (r < 0) |
37 | return r; | |
38 | ||
3f70f938 | 39 | r = hashmap_ensure_put(&m->links_by_name, &string_hash_ops, l->ifname, l); |
7de12ae7 TG |
40 | if (r < 0) |
41 | return r; | |
42 | ||
43 | if (ret) | |
44 | *ret = l; | |
7de12ae7 | 45 | |
f023184e | 46 | TAKE_PTR(l); |
7de12ae7 TG |
47 | return 0; |
48 | } | |
49 | ||
50 | Link *link_free(Link *l) { | |
51 | ||
52 | if (!l) | |
53 | return NULL; | |
54 | ||
55 | if (l->manager) { | |
56 | hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); | |
57 | hashmap_remove(l->manager->links_by_name, l->ifname); | |
58 | } | |
59 | ||
f023184e | 60 | free(l->state); |
7de12ae7 | 61 | free(l->ifname); |
6b430fdb | 62 | return mfree(l); |
7de12ae7 TG |
63 | } |
64 | ||
1c4baffc | 65 | int link_update_rtnl(Link *l, sd_netlink_message *m) { |
d2437732 | 66 | const char *ifname; |
7de12ae7 TG |
67 | int r; |
68 | ||
69 | assert(l); | |
70 | assert(l->manager); | |
71 | assert(m); | |
72 | ||
73 | r = sd_rtnl_message_link_get_flags(m, &l->flags); | |
74 | if (r < 0) | |
75 | return r; | |
76 | ||
1c4baffc | 77 | r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); |
7de12ae7 TG |
78 | if (r < 0) |
79 | return r; | |
80 | ||
81 | if (!streq(l->ifname, ifname)) { | |
82 | char *new_ifname; | |
83 | ||
84 | new_ifname = strdup(ifname); | |
85 | if (!new_ifname) | |
86 | return -ENOMEM; | |
87 | ||
f023184e YW |
88 | assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l); |
89 | free_and_replace(l->ifname, new_ifname); | |
7de12ae7 TG |
90 | |
91 | r = hashmap_put(l->manager->links_by_name, l->ifname, l); | |
92 | if (r < 0) | |
93 | return r; | |
94 | } | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
99 | int link_update_monitor(Link *l) { | |
6dc4531d L |
100 | _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *required_family = NULL, |
101 | *ipv4_address_state = NULL, *ipv6_address_state = NULL, *state = NULL; | |
f023184e | 102 | int r, ret = 0; |
7de12ae7 | 103 | |
f023184e YW |
104 | assert(l); |
105 | assert(l->ifname); | |
c1a38904 | 106 | |
f023184e YW |
107 | r = sd_network_link_get_required_for_online(l->ifindex); |
108 | if (r < 0) | |
07e1ffe4 YW |
109 | ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, " |
110 | "ignoring: %m"); | |
f023184e YW |
111 | else |
112 | l->required_for_online = r > 0; | |
7de12ae7 | 113 | |
f023184e YW |
114 | r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); |
115 | if (r < 0) | |
07e1ffe4 | 116 | ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m"); |
75cd4a5d DDM |
117 | else if (isempty(required_operstate)) |
118 | l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT; | |
f023184e | 119 | else { |
75cd4a5d DDM |
120 | r = parse_operational_state_range(required_operstate, &l->required_operstate); |
121 | if (r < 0) | |
07e1ffe4 YW |
122 | ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), |
123 | "Failed to parse required operational state, ignoring: %m"); | |
f023184e | 124 | } |
7de12ae7 | 125 | |
f023184e YW |
126 | r = sd_network_link_get_operational_state(l->ifindex, &operstate); |
127 | if (r < 0) | |
07e1ffe4 | 128 | ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m"); |
f023184e | 129 | else { |
75cd4a5d DDM |
130 | LinkOperationalState s; |
131 | ||
f023184e YW |
132 | s = link_operstate_from_string(operstate); |
133 | if (s < 0) | |
7211c853 | 134 | ret = log_link_debug_errno(l, s, "Failed to parse operational state, ignoring: %m"); |
f023184e YW |
135 | else |
136 | l->operational_state = s; | |
137 | } | |
7de12ae7 | 138 | |
6dc4531d L |
139 | r = sd_network_link_get_required_family_for_online(l->ifindex, &required_family); |
140 | if (r < 0) | |
141 | ret = log_link_debug_errno(l, r, "Failed to get required address family, ignoring: %m"); | |
142 | else if (isempty(required_family)) | |
143 | l->required_family = ADDRESS_FAMILY_NO; | |
144 | else { | |
145 | AddressFamily f; | |
146 | ||
147 | f = link_required_address_family_from_string(required_family); | |
148 | if (f < 0) | |
149 | ret = log_link_debug_errno(l, f, "Failed to parse required address family, ignoring: %m"); | |
150 | else | |
151 | l->required_family = f; | |
152 | } | |
153 | ||
154 | r = sd_network_link_get_ipv4_address_state(l->ifindex, &ipv4_address_state); | |
155 | if (r < 0) | |
156 | ret = log_link_debug_errno(l, r, "Failed to get IPv4 address state, ignoring: %m"); | |
157 | else { | |
158 | LinkAddressState s; | |
159 | ||
160 | s = link_address_state_from_string(ipv4_address_state); | |
161 | if (s < 0) | |
162 | ret = log_link_debug_errno(l, s, "Failed to parse IPv4 address state, ignoring: %m"); | |
163 | else | |
164 | l->ipv4_address_state = s; | |
165 | } | |
166 | ||
167 | r = sd_network_link_get_ipv6_address_state(l->ifindex, &ipv6_address_state); | |
168 | if (r < 0) | |
169 | ret = log_link_debug_errno(l, r, "Failed to get IPv6 address state, ignoring: %m"); | |
170 | else { | |
171 | LinkAddressState s; | |
172 | ||
173 | s = link_address_state_from_string(ipv6_address_state); | |
174 | if (s < 0) | |
175 | ret = log_link_debug_errno(l, s, "Failed to parse IPv6 address state, ignoring: %m"); | |
176 | else | |
177 | l->ipv6_address_state = s; | |
178 | } | |
179 | ||
f023184e YW |
180 | r = sd_network_link_get_setup_state(l->ifindex, &state); |
181 | if (r < 0) | |
07e1ffe4 | 182 | ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m"); |
f023184e YW |
183 | else |
184 | free_and_replace(l->state, state); | |
7de12ae7 | 185 | |
f023184e | 186 | return ret; |
7de12ae7 | 187 | } |