]>
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); | |
18 | ||
d5099efc | 19 | r = hashmap_ensure_allocated(&m->links, NULL); |
7de12ae7 TG |
20 | if (r < 0) |
21 | return r; | |
22 | ||
d5099efc | 23 | r = hashmap_ensure_allocated(&m->links_by_name, &string_hash_ops); |
7de12ae7 TG |
24 | if (r < 0) |
25 | return r; | |
26 | ||
f023184e YW |
27 | n = strdup(ifname); |
28 | if (!n) | |
7de12ae7 TG |
29 | return -ENOMEM; |
30 | ||
f023184e YW |
31 | l = new(Link, 1); |
32 | if (!l) | |
7de12ae7 TG |
33 | return -ENOMEM; |
34 | ||
f023184e YW |
35 | *l = (Link) { |
36 | .manager = m, | |
37 | .ifname = TAKE_PTR(n), | |
38 | .ifindex = ifindex, | |
75cd4a5d | 39 | .required_operstate = LINK_OPERSTATE_RANGE_DEFAULT, |
f023184e YW |
40 | }; |
41 | ||
7de12ae7 TG |
42 | r = hashmap_put(m->links_by_name, l->ifname, l); |
43 | if (r < 0) | |
44 | return r; | |
45 | ||
7de12ae7 TG |
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; | |
7de12ae7 | 52 | |
f023184e | 53 | TAKE_PTR(l); |
7de12ae7 TG |
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 | ||
f023184e | 67 | free(l->state); |
7de12ae7 | 68 | free(l->ifname); |
6b430fdb | 69 | return mfree(l); |
7de12ae7 TG |
70 | } |
71 | ||
1c4baffc | 72 | int link_update_rtnl(Link *l, sd_netlink_message *m) { |
d2437732 | 73 | const char *ifname; |
7de12ae7 TG |
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 | ||
1c4baffc | 84 | r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); |
7de12ae7 TG |
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 | ||
f023184e YW |
95 | assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l); |
96 | free_and_replace(l->ifname, new_ifname); | |
7de12ae7 TG |
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) { | |
f023184e | 107 | _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL; |
f023184e | 108 | int r, ret = 0; |
7de12ae7 | 109 | |
f023184e YW |
110 | assert(l); |
111 | assert(l->ifname); | |
c1a38904 | 112 | |
f023184e YW |
113 | r = sd_network_link_get_required_for_online(l->ifindex); |
114 | if (r < 0) | |
07e1ffe4 YW |
115 | ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, " |
116 | "ignoring: %m"); | |
f023184e YW |
117 | else |
118 | l->required_for_online = r > 0; | |
7de12ae7 | 119 | |
f023184e YW |
120 | r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); |
121 | if (r < 0) | |
07e1ffe4 | 122 | ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m"); |
75cd4a5d DDM |
123 | else if (isempty(required_operstate)) |
124 | l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT; | |
f023184e | 125 | else { |
75cd4a5d DDM |
126 | r = parse_operational_state_range(required_operstate, &l->required_operstate); |
127 | if (r < 0) | |
07e1ffe4 YW |
128 | ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), |
129 | "Failed to parse required operational state, ignoring: %m"); | |
f023184e | 130 | } |
7de12ae7 | 131 | |
f023184e YW |
132 | r = sd_network_link_get_operational_state(l->ifindex, &operstate); |
133 | if (r < 0) | |
07e1ffe4 | 134 | ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m"); |
f023184e | 135 | else { |
75cd4a5d DDM |
136 | LinkOperationalState s; |
137 | ||
f023184e YW |
138 | s = link_operstate_from_string(operstate); |
139 | if (s < 0) | |
07e1ffe4 YW |
140 | ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), |
141 | "Failed to parse operational state, ignoring: %m"); | |
f023184e YW |
142 | else |
143 | l->operational_state = s; | |
144 | } | |
7de12ae7 | 145 | |
f023184e YW |
146 | r = sd_network_link_get_setup_state(l->ifindex, &state); |
147 | if (r < 0) | |
07e1ffe4 | 148 | ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m"); |
f023184e YW |
149 | else |
150 | free_and_replace(l->state, state); | |
7de12ae7 | 151 | |
f023184e | 152 | return ret; |
7de12ae7 | 153 | } |