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
link_new(Manager * m,Link ** ret,int ifindex,const char * ifname)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 assert(ifname);
19
20 n = strdup(ifname);
21 if (!n)
22 return -ENOMEM;
23
24 l = new(Link, 1);
25 if (!l)
26 return -ENOMEM;
27
28 *l = (Link) {
29 .manager = m,
30 .ifname = TAKE_PTR(n),
31 .ifindex = ifindex,
32 .required_operstate = LINK_OPERSTATE_RANGE_DEFAULT,
33 };
34
35 r = hashmap_ensure_put(&m->links_by_index, NULL, INT_TO_PTR(ifindex), l);
36 if (r < 0)
37 return r;
38
39 r = hashmap_ensure_put(&m->links_by_name, &string_hash_ops, l->ifname, l);
40 if (r < 0)
41 return r;
42
43 if (ret)
44 *ret = l;
45
46 TAKE_PTR(l);
47 return 0;
48 }
49
link_free(Link * l)50 Link *link_free(Link *l) {
51
52 if (!l)
53 return NULL;
54
55 if (l->manager) {
56 hashmap_remove(l->manager->links_by_index, INT_TO_PTR(l->ifindex));
57 hashmap_remove(l->manager->links_by_name, l->ifname);
58 }
59
60 free(l->state);
61 free(l->ifname);
62 return mfree(l);
63 }
64
link_update_rtnl(Link * l,sd_netlink_message * m)65 int link_update_rtnl(Link *l, sd_netlink_message *m) {
66 const char *ifname;
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
77 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
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
88 assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l);
89 free_and_replace(l->ifname, new_ifname);
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
link_update_monitor(Link * l)99 int link_update_monitor(Link *l) {
100 _cleanup_free_ char *required_operstate = NULL, *required_family = NULL,
101 *ipv4_address_state = NULL, *ipv6_address_state = NULL, *state = NULL;
102 int r, ret = 0;
103
104 assert(l);
105 assert(l->ifname);
106
107 r = sd_network_link_get_required_for_online(l->ifindex);
108 if (r < 0)
109 ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, "
110 "ignoring: %m");
111 else
112 l->required_for_online = r > 0;
113
114 r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate);
115 if (r < 0)
116 ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m");
117 else if (isempty(required_operstate))
118 l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT;
119 else {
120 r = parse_operational_state_range(required_operstate, &l->required_operstate);
121 if (r < 0)
122 ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
123 "Failed to parse required operational state, ignoring: %m");
124 }
125
126 r = network_link_get_operational_state(l->ifindex, &l->operational_state);
127 if (r < 0)
128 ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m");
129
130 r = sd_network_link_get_required_family_for_online(l->ifindex, &required_family);
131 if (r < 0)
132 ret = log_link_debug_errno(l, r, "Failed to get required address family, ignoring: %m");
133 else if (isempty(required_family))
134 l->required_family = ADDRESS_FAMILY_NO;
135 else {
136 AddressFamily f;
137
138 f = link_required_address_family_from_string(required_family);
139 if (f < 0)
140 ret = log_link_debug_errno(l, f, "Failed to parse required address family, ignoring: %m");
141 else
142 l->required_family = f;
143 }
144
145 r = sd_network_link_get_ipv4_address_state(l->ifindex, &ipv4_address_state);
146 if (r < 0)
147 ret = log_link_debug_errno(l, r, "Failed to get IPv4 address state, ignoring: %m");
148 else {
149 LinkAddressState s;
150
151 s = link_address_state_from_string(ipv4_address_state);
152 if (s < 0)
153 ret = log_link_debug_errno(l, s, "Failed to parse IPv4 address state, ignoring: %m");
154 else
155 l->ipv4_address_state = s;
156 }
157
158 r = sd_network_link_get_ipv6_address_state(l->ifindex, &ipv6_address_state);
159 if (r < 0)
160 ret = log_link_debug_errno(l, r, "Failed to get IPv6 address state, ignoring: %m");
161 else {
162 LinkAddressState s;
163
164 s = link_address_state_from_string(ipv6_address_state);
165 if (s < 0)
166 ret = log_link_debug_errno(l, s, "Failed to parse IPv6 address state, ignoring: %m");
167 else
168 l->ipv6_address_state = s;
169 }
170
171 r = sd_network_link_get_setup_state(l->ifindex, &state);
172 if (r < 0)
173 ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m");
174 else
175 free_and_replace(l->state, state);
176
177 return ret;
178 }
179