File: | build-scan/../src/network/networkctl.c |
Warning: | line 266, column 28 Potential leak of memory pointed to by 't' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <getopt.h> | |||
4 | #include <linux1/if_addrlabel.h> | |||
5 | #include <net/if.h> | |||
6 | #include <stdbool.h> | |||
7 | ||||
8 | #include "sd-device.h" | |||
9 | #include "sd-hwdb.h" | |||
10 | #include "sd-lldp.h" | |||
11 | #include "sd-netlink.h" | |||
12 | #include "sd-network.h" | |||
13 | ||||
14 | #include "alloc-util.h" | |||
15 | #include "arphrd-list.h" | |||
16 | #include "device-util.h" | |||
17 | #include "ether-addr-util.h" | |||
18 | #include "fd-util.h" | |||
19 | #include "hwdb-util.h" | |||
20 | #include "local-addresses.h" | |||
21 | #include "locale-util.h" | |||
22 | #include "macro.h" | |||
23 | #include "netlink-util.h" | |||
24 | #include "pager.h" | |||
25 | #include "parse-util.h" | |||
26 | #include "socket-util.h" | |||
27 | #include "sparse-endian.h" | |||
28 | #include "stdio-util.h" | |||
29 | #include "string-table.h" | |||
30 | #include "string-util.h" | |||
31 | #include "strv.h" | |||
32 | #include "strxcpyx.h" | |||
33 | #include "terminal-util.h" | |||
34 | #include "util.h" | |||
35 | #include "verbs.h" | |||
36 | ||||
37 | static bool_Bool arg_no_pager = false0; | |||
38 | static bool_Bool arg_legend = true1; | |||
39 | static bool_Bool arg_all = false0; | |||
40 | ||||
41 | static char *link_get_type_string(unsigned short iftype, sd_device *d) { | |||
42 | const char *t; | |||
43 | char *p; | |||
44 | ||||
45 | if (d) { | |||
46 | const char *devtype = NULL((void*)0); | |||
47 | ||||
48 | (void) sd_device_get_devtype(d, &devtype); | |||
49 | if (!isempty(devtype)) | |||
50 | return strdup(devtype); | |||
51 | } | |||
52 | ||||
53 | t = arphrd_to_name(iftype); | |||
54 | if (!t) | |||
55 | return NULL((void*)0); | |||
56 | ||||
57 | p = strdup(t); | |||
58 | if (!p) | |||
59 | return NULL((void*)0); | |||
60 | ||||
61 | ascii_strlower(p); | |||
62 | return p; | |||
63 | } | |||
64 | ||||
65 | static void operational_state_to_color(const char *state, const char **on, const char **off) { | |||
66 | assert(on)do { if ((__builtin_expect(!!(!(on)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("on"), "../src/network/networkctl.c", 66 , __PRETTY_FUNCTION__); } while (0); | |||
67 | assert(off)do { if ((__builtin_expect(!!(!(off)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("off"), "../src/network/networkctl.c", 67 , __PRETTY_FUNCTION__); } while (0); | |||
68 | ||||
69 | if (streq_ptr(state, "routable")) { | |||
70 | *on = ansi_highlight_green(); | |||
71 | *off = ansi_normal(); | |||
72 | } else if (streq_ptr(state, "degraded")) { | |||
73 | *on = ansi_highlight_yellow(); | |||
74 | *off = ansi_normal(); | |||
75 | } else | |||
76 | *on = *off = ""; | |||
77 | } | |||
78 | ||||
79 | static void setup_state_to_color(const char *state, const char **on, const char **off) { | |||
80 | assert(on)do { if ((__builtin_expect(!!(!(on)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("on"), "../src/network/networkctl.c", 80 , __PRETTY_FUNCTION__); } while (0); | |||
81 | assert(off)do { if ((__builtin_expect(!!(!(off)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("off"), "../src/network/networkctl.c", 81 , __PRETTY_FUNCTION__); } while (0); | |||
82 | ||||
83 | if (streq_ptr(state, "configured")) { | |||
84 | *on = ansi_highlight_green(); | |||
85 | *off = ansi_normal(); | |||
86 | } else if (streq_ptr(state, "configuring")) { | |||
87 | *on = ansi_highlight_yellow(); | |||
88 | *off = ansi_normal(); | |||
89 | } else if (STRPTR_IN_SET(state, "failed", "linger")({ const char* _x = (state); _x && (!!strv_find((((char **) ((const char*[]) { "failed", "linger", ((void*)0) }))), ( _x))); })) { | |||
90 | *on = ansi_highlight_red(); | |||
91 | *off = ansi_normal(); | |||
92 | } else | |||
93 | *on = *off = ""; | |||
94 | } | |||
95 | ||||
96 | typedef struct LinkInfo { | |||
97 | char name[IFNAMSIZ16+1]; | |||
98 | int ifindex; | |||
99 | unsigned short iftype; | |||
100 | struct ether_addr mac_address; | |||
101 | uint32_t mtu; | |||
102 | ||||
103 | bool_Bool has_mac_address:1; | |||
104 | bool_Bool has_mtu:1; | |||
105 | } LinkInfo; | |||
106 | ||||
107 | static int link_info_compare(const void *a, const void *b) { | |||
108 | const LinkInfo *x = a, *y = b; | |||
109 | ||||
110 | return x->ifindex - y->ifindex; | |||
111 | } | |||
112 | ||||
113 | static int decode_link(sd_netlink_message *m, LinkInfo *info) { | |||
114 | const char *name; | |||
115 | uint16_t type; | |||
116 | int r; | |||
117 | ||||
118 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/network/networkctl.c", 118 , __PRETTY_FUNCTION__); } while (0); | |||
119 | assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("info"), "../src/network/networkctl.c", 119 , __PRETTY_FUNCTION__); } while (0); | |||
120 | ||||
121 | r = sd_netlink_message_get_type(m, &type); | |||
122 | if (r < 0) | |||
123 | return r; | |||
124 | ||||
125 | if (type != RTM_NEWLINKRTM_NEWLINK) | |||
126 | return 0; | |||
127 | ||||
128 | r = sd_rtnl_message_link_get_ifindex(m, &info->ifindex); | |||
129 | if (r < 0) | |||
130 | return r; | |||
131 | ||||
132 | r = sd_netlink_message_read_string(m, IFLA_IFNAME, &name); | |||
133 | if (r < 0) | |||
134 | return r; | |||
135 | ||||
136 | r = sd_rtnl_message_link_get_type(m, &info->iftype); | |||
137 | if (r < 0) | |||
138 | return r; | |||
139 | ||||
140 | strscpy(info->name, sizeof info->name, name); | |||
141 | ||||
142 | info->has_mac_address = | |||
143 | sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 && | |||
144 | memcmp(&info->mac_address, ÐER_ADDR_NULL((const struct ether_addr){}), sizeof(struct ether_addr)) != 0; | |||
145 | ||||
146 | info->has_mtu = | |||
147 | sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) && | |||
148 | info->mtu > 0; | |||
149 | ||||
150 | return 1; | |||
151 | } | |||
152 | ||||
153 | static int acquire_link_info_strv(sd_netlink *rtnl, char **l, LinkInfo **ret) { | |||
154 | _cleanup_free___attribute__((cleanup(freep))) LinkInfo *links = NULL((void*)0); | |||
155 | char **i; | |||
156 | size_t c = 0; | |||
157 | int r; | |||
158 | ||||
159 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 159 , __PRETTY_FUNCTION__); } while (0); | |||
160 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/networkctl.c", 160 , __PRETTY_FUNCTION__); } while (0); | |||
161 | ||||
162 | links = new(LinkInfo, strv_length(l))((LinkInfo*) malloc_multiply(sizeof(LinkInfo), (strv_length(l )))); | |||
163 | if (!links) | |||
164 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkctl.c" , 164, __func__); | |||
165 | ||||
166 | STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) { | |||
167 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *req = NULL((void*)0), *reply = NULL((void*)0); | |||
168 | int ifindex; | |||
169 | ||||
170 | if (parse_ifindex(*i, &ifindex) >= 0) | |||
171 | r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINKRTM_GETLINK, ifindex); | |||
172 | else { | |||
173 | r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINKRTM_GETLINK, 0); | |||
174 | if (r < 0) | |||
175 | return rtnl_log_create_error(r); | |||
176 | ||||
177 | r = sd_netlink_message_append_string(req, IFLA_IFNAME, *i); | |||
178 | } | |||
179 | if (r < 0) | |||
180 | return rtnl_log_create_error(r); | |||
181 | ||||
182 | r = sd_netlink_call(rtnl, req, 0, &reply); | |||
183 | if (r < 0) | |||
184 | return log_error_errno(r, "Failed to request link: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 184, __func__, "Failed to request link: %m" ) : -abs(_e); }); | |||
185 | ||||
186 | r = decode_link(reply, links + c); | |||
187 | if (r < 0) | |||
188 | return r; | |||
189 | if (r > 0) | |||
190 | c++; | |||
191 | } | |||
192 | ||||
193 | qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); | |||
194 | ||||
195 | *ret = TAKE_PTR(links)({ typeof(links) _ptr_ = (links); (links) = ((void*)0); _ptr_ ; }); | |||
196 | ||||
197 | return (int) c; | |||
198 | } | |||
199 | ||||
200 | static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) { | |||
201 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *req = NULL((void*)0), *reply = NULL((void*)0); | |||
202 | _cleanup_free___attribute__((cleanup(freep))) LinkInfo *links = NULL((void*)0); | |||
203 | size_t allocated = 0, c = 0; | |||
204 | sd_netlink_message *i; | |||
205 | int r; | |||
206 | ||||
207 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 207 , __PRETTY_FUNCTION__); } while (0); | |||
208 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/networkctl.c", 208 , __PRETTY_FUNCTION__); } while (0); | |||
209 | ||||
210 | r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINKRTM_GETLINK, 0); | |||
211 | if (r < 0) | |||
212 | return rtnl_log_create_error(r); | |||
213 | ||||
214 | r = sd_netlink_message_request_dump(req, true1); | |||
215 | if (r < 0) | |||
216 | return rtnl_log_create_error(r); | |||
217 | ||||
218 | r = sd_netlink_call(rtnl, req, 0, &reply); | |||
219 | if (r < 0) | |||
220 | return log_error_errno(r, "Failed to enumerate links: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 220, __func__, "Failed to enumerate links: %m" ) : -abs(_e); }); | |||
221 | ||||
222 | for (i = reply; i; i = sd_netlink_message_next(i)) { | |||
223 | if (!GREEDY_REALLOC(links, allocated, c+1)greedy_realloc((void**) &(links), &(allocated), (c+1) , sizeof((links)[0]))) | |||
224 | return -ENOMEM12; | |||
225 | ||||
226 | r = decode_link(i, links + c); | |||
227 | if (r < 0) | |||
228 | return r; | |||
229 | if (r > 0) | |||
230 | c++; | |||
231 | } | |||
232 | ||||
233 | qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); | |||
234 | ||||
235 | *ret = TAKE_PTR(links)({ typeof(links) _ptr_ = (links); (links) = ((void*)0); _ptr_ ; }); | |||
236 | ||||
237 | return (int) c; | |||
238 | } | |||
239 | ||||
240 | static int list_links(int argc, char *argv[], void *userdata) { | |||
241 | _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0); | |||
242 | _cleanup_free___attribute__((cleanup(freep))) LinkInfo *links = NULL((void*)0); | |||
243 | int c, i, r; | |||
244 | ||||
245 | r = sd_netlink_open(&rtnl); | |||
246 | if (r < 0) | |||
| ||||
247 | return log_error_errno(r, "Failed to connect to netlink: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 247, __func__, "Failed to connect to netlink: %m" ) : -abs(_e); }); | |||
248 | ||||
249 | if (argc > 1) | |||
250 | c = acquire_link_info_strv(rtnl, argv + 1, &links); | |||
251 | else | |||
252 | c = acquire_link_info_all(rtnl, &links); | |||
253 | if (c < 0) | |||
254 | return c; | |||
255 | ||||
256 | (void) pager_open(arg_no_pager, false0); | |||
257 | ||||
258 | if (arg_legend) | |||
259 | printf("%3s %-16s %-18s %-11s %-10s\n", | |||
260 | "IDX", | |||
261 | "LINK", | |||
262 | "TYPE", | |||
263 | "OPERATIONAL", | |||
264 | "SETUP"); | |||
265 | ||||
266 | for (i = 0; i < c; i++) { | |||
| ||||
267 | _cleanup_free___attribute__((cleanup(freep))) char *setup_state = NULL((void*)0), *operational_state = NULL((void*)0); | |||
268 | _cleanup_(sd_device_unrefp)__attribute__((cleanup(sd_device_unrefp))) sd_device *d = NULL((void*)0); | |||
269 | const char *on_color_operational, *off_color_operational, | |||
270 | *on_color_setup, *off_color_setup; | |||
271 | char devid[2 + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))]; | |||
272 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | |||
273 | ||||
274 | (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state); | |||
275 | operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); | |||
276 | ||||
277 | r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state); | |||
278 | if (r == -ENODATA61) /* If there's no info available about this iface, it's unmanaged by networkd */ | |||
279 | setup_state = strdup("unmanaged"); | |||
280 | setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); | |||
281 | ||||
282 | xsprintf(devid, "n%i", links[i].ifindex)do { if ((__builtin_expect(!!(!(((size_t) snprintf(devid, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (devid), typeof(&*(devid))), sizeof(devid)/sizeof((devid) [0]), ((void)0))), "n%i", links[i].ifindex) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (devid), typeof(&*(devid))), sizeof(devid)/sizeof((devid) [0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "devid" "[] must be big enough"), "../src/network/networkctl.c" , 282, __PRETTY_FUNCTION__); } while (0); | |||
283 | (void) sd_device_new_from_device_id(&d, devid); | |||
284 | ||||
285 | t = link_get_type_string(links[i].iftype, d); | |||
286 | ||||
287 | printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n", | |||
288 | links[i].ifindex, links[i].name, strna(t), | |||
289 | on_color_operational, strna(operational_state), off_color_operational, | |||
290 | on_color_setup, strna(setup_state), off_color_setup); | |||
291 | } | |||
292 | ||||
293 | if (arg_legend) | |||
294 | printf("\n%i links listed.\n", c); | |||
295 | ||||
296 | return 0; | |||
297 | } | |||
298 | ||||
299 | /* IEEE Organizationally Unique Identifier vendor string */ | |||
300 | static int ieee_oui(sd_hwdb *hwdb, const struct ether_addr *mac, char **ret) { | |||
301 | const char *description; | |||
302 | char modalias[STRLEN("OUI:XXYYXXYYXXYY")(sizeof("""OUI:XXYYXXYYXXYY""") - 1) + 1], *desc; | |||
303 | int r; | |||
304 | ||||
305 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/networkctl.c", 305 , __PRETTY_FUNCTION__); } while (0); | |||
306 | ||||
307 | if (!hwdb) | |||
308 | return -EINVAL22; | |||
309 | ||||
310 | if (!mac) | |||
311 | return -EINVAL22; | |||
312 | ||||
313 | /* skip commonly misused 00:00:00 (Xerox) prefix */ | |||
314 | if (memcmp(mac, "\0\0\0", 3) == 0) | |||
315 | return -EINVAL22; | |||
316 | ||||
317 | xsprintf(modalias, "OUI:" ETHER_ADDR_FORMAT_STR,do { if ((__builtin_expect(!!(!(((size_t) snprintf(modalias, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (modalias), typeof(&*(modalias))), sizeof(modalias)/sizeof ((modalias)[0]), ((void)0))), "OUI:" "%02X%02X%02X%02X%02X%02X" , (*mac).ether_addr_octet[0], (*mac).ether_addr_octet[1], (*mac ).ether_addr_octet[2], (*mac).ether_addr_octet[3], (*mac).ether_addr_octet [4], (*mac).ether_addr_octet[5]) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(modalias), typeof(& *(modalias))), sizeof(modalias)/sizeof((modalias)[0]), ((void )0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "modalias" "[] must be big enough"), "../src/network/networkctl.c" , 318, __PRETTY_FUNCTION__); } while (0) | |||
318 | ETHER_ADDR_FORMAT_VAL(*mac))do { if ((__builtin_expect(!!(!(((size_t) snprintf(modalias, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (modalias), typeof(&*(modalias))), sizeof(modalias)/sizeof ((modalias)[0]), ((void)0))), "OUI:" "%02X%02X%02X%02X%02X%02X" , (*mac).ether_addr_octet[0], (*mac).ether_addr_octet[1], (*mac ).ether_addr_octet[2], (*mac).ether_addr_octet[3], (*mac).ether_addr_octet [4], (*mac).ether_addr_octet[5]) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(modalias), typeof(& *(modalias))), sizeof(modalias)/sizeof((modalias)[0]), ((void )0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "modalias" "[] must be big enough"), "../src/network/networkctl.c" , 318, __PRETTY_FUNCTION__); } while (0); | |||
319 | ||||
320 | r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description); | |||
321 | if (r < 0) | |||
322 | return r; | |||
323 | ||||
324 | desc = strdup(description); | |||
325 | if (!desc) | |||
326 | return -ENOMEM12; | |||
327 | ||||
328 | *ret = desc; | |||
329 | ||||
330 | return 0; | |||
331 | } | |||
332 | ||||
333 | static int get_gateway_description( | |||
334 | sd_netlink *rtnl, | |||
335 | sd_hwdb *hwdb, | |||
336 | int ifindex, | |||
337 | int family, | |||
338 | union in_addr_union *gateway, | |||
339 | char **gateway_description) { | |||
340 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *req = NULL((void*)0), *reply = NULL((void*)0); | |||
341 | sd_netlink_message *m; | |||
342 | int r; | |||
343 | ||||
344 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 344 , __PRETTY_FUNCTION__); } while (0); | |||
345 | assert(ifindex >= 0)do { if ((__builtin_expect(!!(!(ifindex >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ifindex >= 0"), "../src/network/networkctl.c" , 345, __PRETTY_FUNCTION__); } while (0); | |||
346 | assert(IN_SET(family, AF_INET, AF_INET6))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){2, 10})/sizeof(int)]; switch(family) { case 2: case 10: _found = 1; break; default: break; } _found; })) ),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("IN_SET(family, AF_INET, AF_INET6)" ), "../src/network/networkctl.c", 346, __PRETTY_FUNCTION__); } while (0); | |||
347 | assert(gateway)do { if ((__builtin_expect(!!(!(gateway)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("gateway"), "../src/network/networkctl.c" , 347, __PRETTY_FUNCTION__); } while (0); | |||
348 | assert(gateway_description)do { if ((__builtin_expect(!!(!(gateway_description)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("gateway_description"), "../src/network/networkctl.c" , 348, __PRETTY_FUNCTION__); } while (0); | |||
349 | ||||
350 | r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGHRTM_GETNEIGH, ifindex, family); | |||
351 | if (r < 0) | |||
352 | return r; | |||
353 | ||||
354 | r = sd_netlink_message_request_dump(req, true1); | |||
355 | if (r < 0) | |||
356 | return r; | |||
357 | ||||
358 | r = sd_netlink_call(rtnl, req, 0, &reply); | |||
359 | if (r < 0) | |||
360 | return r; | |||
361 | ||||
362 | for (m = reply; m; m = sd_netlink_message_next(m)) { | |||
363 | union in_addr_union gw = {}; | |||
364 | struct ether_addr mac = {}; | |||
365 | uint16_t type; | |||
366 | int ifi, fam; | |||
367 | ||||
368 | r = sd_netlink_message_get_errno(m); | |||
369 | if (r < 0) { | |||
370 | log_error_errno(r, "got error: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 370, __func__, "got error: %m" ) : -abs(_e); }); | |||
371 | continue; | |||
372 | } | |||
373 | ||||
374 | r = sd_netlink_message_get_type(m, &type); | |||
375 | if (r < 0) { | |||
376 | log_error_errno(r, "could not get type: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 376, __func__, "could not get type: %m" ) : -abs(_e); }); | |||
377 | continue; | |||
378 | } | |||
379 | ||||
380 | if (type != RTM_NEWNEIGHRTM_NEWNEIGH) { | |||
381 | log_error("type is not RTM_NEWNEIGH")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 381, __func__, "type is not RTM_NEWNEIGH" ) : -abs(_e); }); | |||
382 | continue; | |||
383 | } | |||
384 | ||||
385 | r = sd_rtnl_message_neigh_get_family(m, &fam); | |||
386 | if (r < 0) { | |||
387 | log_error_errno(r, "could not get family: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 387, __func__, "could not get family: %m" ) : -abs(_e); }); | |||
388 | continue; | |||
389 | } | |||
390 | ||||
391 | if (fam != family) { | |||
392 | log_error("family is not correct")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 392, __func__, "family is not correct" ) : -abs(_e); }); | |||
393 | continue; | |||
394 | } | |||
395 | ||||
396 | r = sd_rtnl_message_neigh_get_ifindex(m, &ifi); | |||
397 | if (r < 0) { | |||
398 | log_error_errno(r, "could not get ifindex: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 398, __func__, "could not get ifindex: %m" ) : -abs(_e); }); | |||
399 | continue; | |||
400 | } | |||
401 | ||||
402 | if (ifindex > 0 && ifi != ifindex) | |||
403 | continue; | |||
404 | ||||
405 | switch (fam) { | |||
406 | case AF_INET2: | |||
407 | r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in); | |||
408 | if (r < 0) | |||
409 | continue; | |||
410 | ||||
411 | break; | |||
412 | case AF_INET610: | |||
413 | r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6); | |||
414 | if (r < 0) | |||
415 | continue; | |||
416 | ||||
417 | break; | |||
418 | default: | |||
419 | continue; | |||
420 | } | |||
421 | ||||
422 | if (!in_addr_equal(fam, &gw, gateway)) | |||
423 | continue; | |||
424 | ||||
425 | r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac); | |||
426 | if (r < 0) | |||
427 | continue; | |||
428 | ||||
429 | r = ieee_oui(hwdb, &mac, gateway_description); | |||
430 | if (r < 0) | |||
431 | continue; | |||
432 | ||||
433 | return 0; | |||
434 | } | |||
435 | ||||
436 | return -ENODATA61; | |||
437 | } | |||
438 | ||||
439 | static int dump_gateways( | |||
440 | sd_netlink *rtnl, | |||
441 | sd_hwdb *hwdb, | |||
442 | const char *prefix, | |||
443 | int ifindex) { | |||
444 | _cleanup_free___attribute__((cleanup(freep))) struct local_address *local = NULL((void*)0); | |||
445 | int r, n, i; | |||
446 | ||||
447 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 447 , __PRETTY_FUNCTION__); } while (0); | |||
448 | assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("prefix"), "../src/network/networkctl.c" , 448, __PRETTY_FUNCTION__); } while (0); | |||
449 | ||||
450 | n = local_gateways(rtnl, ifindex, AF_UNSPEC0, &local); | |||
451 | if (n < 0) | |||
452 | return n; | |||
453 | ||||
454 | for (i = 0; i < n; i++) { | |||
455 | _cleanup_free___attribute__((cleanup(freep))) char *gateway = NULL((void*)0), *description = NULL((void*)0); | |||
456 | ||||
457 | r = in_addr_to_string(local[i].family, &local[i].address, &gateway); | |||
458 | if (r < 0) | |||
459 | return r; | |||
460 | ||||
461 | r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description); | |||
462 | if (r < 0) | |||
463 | log_debug_errno(r, "Could not get description of gateway: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 463, __func__, "Could not get description of gateway: %m" ) : -abs(_e); }); | |||
464 | ||||
465 | printf("%*s%s", | |||
466 | (int) strlen(prefix), | |||
467 | i == 0 ? prefix : "", | |||
468 | gateway); | |||
469 | ||||
470 | if (description) | |||
471 | printf(" (%s)", description); | |||
472 | ||||
473 | /* Show interface name for the entry if we show | |||
474 | * entries for all interfaces */ | |||
475 | if (ifindex <= 0) { | |||
476 | char name[IF_NAMESIZE16+1]; | |||
477 | ||||
478 | if (if_indextoname(local[i].ifindex, name)) { | |||
479 | fputs(" on ", stdoutstdout); | |||
480 | fputs(name, stdoutstdout); | |||
481 | } else | |||
482 | printf(" on %%%i", local[i].ifindex); | |||
483 | } | |||
484 | ||||
485 | fputc('\n', stdoutstdout); | |||
486 | } | |||
487 | ||||
488 | return 0; | |||
489 | } | |||
490 | ||||
491 | static int dump_addresses( | |||
492 | sd_netlink *rtnl, | |||
493 | const char *prefix, | |||
494 | int ifindex) { | |||
495 | ||||
496 | _cleanup_free___attribute__((cleanup(freep))) struct local_address *local = NULL((void*)0); | |||
497 | int r, n, i; | |||
498 | ||||
499 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 499 , __PRETTY_FUNCTION__); } while (0); | |||
500 | assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("prefix"), "../src/network/networkctl.c" , 500, __PRETTY_FUNCTION__); } while (0); | |||
501 | ||||
502 | n = local_addresses(rtnl, ifindex, AF_UNSPEC0, &local); | |||
503 | if (n < 0) | |||
504 | return n; | |||
505 | ||||
506 | for (i = 0; i < n; i++) { | |||
507 | _cleanup_free___attribute__((cleanup(freep))) char *pretty = NULL((void*)0); | |||
508 | ||||
509 | r = in_addr_to_string(local[i].family, &local[i].address, &pretty); | |||
510 | if (r < 0) | |||
511 | return r; | |||
512 | ||||
513 | printf("%*s%s", | |||
514 | (int) strlen(prefix), | |||
515 | i == 0 ? prefix : "", | |||
516 | pretty); | |||
517 | ||||
518 | if (ifindex <= 0) { | |||
519 | char name[IF_NAMESIZE16+1]; | |||
520 | ||||
521 | if (if_indextoname(local[i].ifindex, name)) { | |||
522 | fputs(" on ", stdoutstdout); | |||
523 | fputs(name, stdoutstdout); | |||
524 | } else | |||
525 | printf(" on %%%i", local[i].ifindex); | |||
526 | } | |||
527 | ||||
528 | fputc('\n', stdoutstdout); | |||
529 | } | |||
530 | ||||
531 | return 0; | |||
532 | } | |||
533 | ||||
534 | static int dump_address_labels(sd_netlink *rtnl) { | |||
535 | _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *req = NULL((void*)0), *reply = NULL((void*)0); | |||
536 | sd_netlink_message *m; | |||
537 | int r; | |||
538 | ||||
539 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 539 , __PRETTY_FUNCTION__); } while (0); | |||
540 | ||||
541 | r = sd_rtnl_message_new_addrlabel(rtnl, &req, RTM_GETADDRLABELRTM_GETADDRLABEL, 0, AF_INET610); | |||
542 | if (r < 0) | |||
543 | return log_error_errno(r, "Could not allocate RTM_GETADDRLABEL message: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 543, __func__, "Could not allocate RTM_GETADDRLABEL message: %m" ) : -abs(_e); }); | |||
544 | ||||
545 | r = sd_netlink_message_request_dump(req, true1); | |||
546 | if (r < 0) | |||
547 | return r; | |||
548 | ||||
549 | r = sd_netlink_call(rtnl, req, 0, &reply); | |||
550 | if (r < 0) | |||
551 | return r; | |||
552 | ||||
553 | printf("%10s/%s %30s\n", "Prefix", "Prefixlen", "Label"); | |||
554 | ||||
555 | for (m = reply; m; m = sd_netlink_message_next(m)) { | |||
556 | _cleanup_free___attribute__((cleanup(freep))) char *pretty = NULL((void*)0); | |||
557 | union in_addr_union prefix = {}; | |||
558 | uint8_t prefixlen; | |||
559 | uint32_t label; | |||
560 | ||||
561 | r = sd_netlink_message_get_errno(m); | |||
562 | if (r < 0) { | |||
563 | log_error_errno(r, "got error: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 563, __func__, "got error: %m" ) : -abs(_e); }); | |||
564 | continue; | |||
565 | } | |||
566 | ||||
567 | r = sd_netlink_message_read_u32(m, IFAL_LABEL, &label); | |||
568 | if (r < 0 && r != -ENODATA61) { | |||
569 | log_error_errno(r, "Could not read IFAL_LABEL, ignoring: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 569, __func__, "Could not read IFAL_LABEL, ignoring: %m" ) : -abs(_e); }); | |||
570 | continue; | |||
571 | } | |||
572 | ||||
573 | r = sd_netlink_message_read_in6_addr(m, IFAL_ADDRESS, &prefix.in6); | |||
574 | if (r < 0) | |||
575 | continue; | |||
576 | ||||
577 | r = in_addr_to_string(AF_INET610, &prefix, &pretty); | |||
578 | if (r < 0) | |||
579 | continue; | |||
580 | ||||
581 | r = sd_rtnl_message_addrlabel_get_prefixlen(m, &prefixlen); | |||
582 | if (r < 0) | |||
583 | continue; | |||
584 | ||||
585 | printf("%10s/%-5u %30u\n", pretty, prefixlen, label); | |||
586 | } | |||
587 | ||||
588 | return 0; | |||
589 | } | |||
590 | ||||
591 | static int list_address_labels(int argc, char *argv[], void *userdata) { | |||
592 | _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0); | |||
593 | int r; | |||
594 | ||||
595 | r = sd_netlink_open(&rtnl); | |||
596 | if (r < 0) | |||
597 | return log_error_errno(r, "Failed to connect to netlink: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 597, __func__, "Failed to connect to netlink: %m" ) : -abs(_e); }); | |||
598 | ||||
599 | dump_address_labels(rtnl); | |||
600 | ||||
601 | return 0; | |||
602 | } | |||
603 | ||||
604 | static int open_lldp_neighbors(int ifindex, FILE **ret) { | |||
605 | _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0); | |||
606 | FILE *f; | |||
607 | ||||
608 | if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0) | |||
609 | return -ENOMEM12; | |||
610 | ||||
611 | f = fopen(p, "re"); | |||
612 | if (!f) | |||
613 | return -errno(*__errno_location ()); | |||
614 | ||||
615 | *ret = f; | |||
616 | return 0; | |||
617 | } | |||
618 | ||||
619 | static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) { | |||
620 | _cleanup_free___attribute__((cleanup(freep))) void *raw = NULL((void*)0); | |||
621 | size_t l; | |||
622 | le64_t u; | |||
623 | int r; | |||
624 | ||||
625 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/network/networkctl.c", 625 , __PRETTY_FUNCTION__); } while (0); | |||
626 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/networkctl.c", 626 , __PRETTY_FUNCTION__); } while (0); | |||
627 | ||||
628 | l = fread(&u, 1, sizeof(u), f); | |||
629 | if (l == 0 && feof(f)) | |||
630 | return 0; | |||
631 | if (l != sizeof(u)) | |||
632 | return -EBADMSG74; | |||
633 | ||||
634 | /* each LLDP packet is at most MTU size, but let's allow up to 4KiB just in case */ | |||
635 | if (le64toh(u) >= 4096) | |||
636 | return -EBADMSG74; | |||
637 | ||||
638 | raw = new(uint8_t, le64toh(u))((uint8_t*) malloc_multiply(sizeof(uint8_t), (le64toh(u)))); | |||
639 | if (!raw) | |||
640 | return -ENOMEM12; | |||
641 | ||||
642 | if (fread(raw, 1, le64toh(u), f) != le64toh(u)) | |||
643 | return -EBADMSG74; | |||
644 | ||||
645 | r = sd_lldp_neighbor_from_raw(ret, raw, le64toh(u)); | |||
646 | if (r < 0) | |||
647 | return r; | |||
648 | ||||
649 | return 1; | |||
650 | } | |||
651 | ||||
652 | static int dump_lldp_neighbors(const char *prefix, int ifindex) { | |||
653 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
654 | int r, c = 0; | |||
655 | ||||
656 | assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("prefix"), "../src/network/networkctl.c" , 656, __PRETTY_FUNCTION__); } while (0); | |||
657 | assert(ifindex > 0)do { if ((__builtin_expect(!!(!(ifindex > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ifindex > 0"), "../src/network/networkctl.c" , 657, __PRETTY_FUNCTION__); } while (0); | |||
658 | ||||
659 | r = open_lldp_neighbors(ifindex, &f); | |||
660 | if (r < 0) | |||
661 | return r; | |||
662 | ||||
663 | for (;;) { | |||
664 | const char *system_name = NULL((void*)0), *port_id = NULL((void*)0), *port_description = NULL((void*)0); | |||
665 | _cleanup_(sd_lldp_neighbor_unrefp)__attribute__((cleanup(sd_lldp_neighbor_unrefp))) sd_lldp_neighbor *n = NULL((void*)0); | |||
666 | ||||
667 | r = next_lldp_neighbor(f, &n); | |||
668 | if (r < 0) | |||
669 | return r; | |||
670 | if (r == 0) | |||
671 | break; | |||
672 | ||||
673 | printf("%*s", | |||
674 | (int) strlen(prefix), | |||
675 | c == 0 ? prefix : ""); | |||
676 | ||||
677 | (void) sd_lldp_neighbor_get_system_name(n, &system_name); | |||
678 | (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); | |||
679 | (void) sd_lldp_neighbor_get_port_description(n, &port_description); | |||
680 | ||||
681 | printf("%s on port %s", strna(system_name), strna(port_id)); | |||
682 | ||||
683 | if (!isempty(port_description)) | |||
684 | printf(" (%s)", port_description); | |||
685 | ||||
686 | putchar('\n'); | |||
687 | ||||
688 | c++; | |||
689 | } | |||
690 | ||||
691 | return c; | |||
692 | } | |||
693 | ||||
694 | static void dump_ifindexes(const char *prefix, const int *ifindexes) { | |||
695 | unsigned c; | |||
696 | ||||
697 | assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("prefix"), "../src/network/networkctl.c" , 697, __PRETTY_FUNCTION__); } while (0); | |||
698 | ||||
699 | if (!ifindexes || ifindexes[0] <= 0) | |||
700 | return; | |||
701 | ||||
702 | for (c = 0; ifindexes[c] > 0; c++) { | |||
703 | char name[IF_NAMESIZE16+1]; | |||
704 | ||||
705 | printf("%*s", | |||
706 | (int) strlen(prefix), | |||
707 | c == 0 ? prefix : ""); | |||
708 | ||||
709 | if (if_indextoname(ifindexes[c], name)) | |||
710 | fputs(name, stdoutstdout); | |||
711 | else | |||
712 | printf("%i", ifindexes[c]); | |||
713 | ||||
714 | fputc('\n', stdoutstdout); | |||
715 | } | |||
716 | } | |||
717 | ||||
718 | static void dump_list(const char *prefix, char **l) { | |||
719 | char **i; | |||
720 | ||||
721 | if (strv_isempty(l)) | |||
722 | return; | |||
723 | ||||
724 | STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) { | |||
725 | printf("%*s%s\n", | |||
726 | (int) strlen(prefix), | |||
727 | i == l ? prefix : "", | |||
728 | *i); | |||
729 | } | |||
730 | } | |||
731 | ||||
732 | static int link_status_one( | |||
733 | sd_netlink *rtnl, | |||
734 | sd_hwdb *hwdb, | |||
735 | const LinkInfo *info) { | |||
736 | ||||
737 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **dns = NULL((void*)0), **ntp = NULL((void*)0), **search_domains = NULL((void*)0), **route_domains = NULL((void*)0); | |||
738 | _cleanup_free___attribute__((cleanup(freep))) char *setup_state = NULL((void*)0), *operational_state = NULL((void*)0), *tz = NULL((void*)0); | |||
739 | _cleanup_(sd_device_unrefp)__attribute__((cleanup(sd_device_unrefp))) sd_device *d = NULL((void*)0); | |||
740 | char devid[2 + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))]; | |||
741 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0), *network = NULL((void*)0); | |||
742 | const char *driver = NULL((void*)0), *path = NULL((void*)0), *vendor = NULL((void*)0), *model = NULL((void*)0), *link = NULL((void*)0); | |||
743 | const char *on_color_operational, *off_color_operational, | |||
744 | *on_color_setup, *off_color_setup; | |||
745 | _cleanup_free___attribute__((cleanup(freep))) int *carrier_bound_to = NULL((void*)0), *carrier_bound_by = NULL((void*)0); | |||
746 | int r; | |||
747 | ||||
748 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 748 , __PRETTY_FUNCTION__); } while (0); | |||
749 | assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("info"), "../src/network/networkctl.c", 749 , __PRETTY_FUNCTION__); } while (0); | |||
750 | ||||
751 | (void) sd_network_link_get_operational_state(info->ifindex, &operational_state); | |||
752 | operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); | |||
753 | ||||
754 | r = sd_network_link_get_setup_state(info->ifindex, &setup_state); | |||
755 | if (r == -ENODATA61) /* If there's no info available about this iface, it's unmanaged by networkd */ | |||
756 | setup_state = strdup("unmanaged"); | |||
757 | setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); | |||
758 | ||||
759 | (void) sd_network_link_get_dns(info->ifindex, &dns); | |||
760 | (void) sd_network_link_get_search_domains(info->ifindex, &search_domains); | |||
761 | (void) sd_network_link_get_route_domains(info->ifindex, &route_domains); | |||
762 | (void) sd_network_link_get_ntp(info->ifindex, &ntp); | |||
763 | ||||
764 | xsprintf(devid, "n%i", info->ifindex)do { if ((__builtin_expect(!!(!(((size_t) snprintf(devid, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (devid), typeof(&*(devid))), sizeof(devid)/sizeof((devid) [0]), ((void)0))), "n%i", info->ifindex) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (devid), typeof(&*(devid))), sizeof(devid)/sizeof((devid) [0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "devid" "[] must be big enough"), "../src/network/networkctl.c" , 764, __PRETTY_FUNCTION__); } while (0); | |||
765 | ||||
766 | (void) sd_device_new_from_device_id(&d, devid); | |||
767 | ||||
768 | if (d) { | |||
769 | (void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); | |||
770 | (void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); | |||
771 | (void) sd_device_get_property_value(d, "ID_PATH", &path); | |||
772 | ||||
773 | r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor); | |||
774 | if (r < 0) | |||
775 | (void) sd_device_get_property_value(d, "ID_VENDOR", &vendor); | |||
776 | ||||
777 | r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model); | |||
778 | if (r < 0) | |||
779 | (void) sd_device_get_property_value(d, "ID_MODEL", &model); | |||
780 | } | |||
781 | ||||
782 | t = link_get_type_string(info->iftype, d); | |||
783 | ||||
784 | (void) sd_network_link_get_network_file(info->ifindex, &network); | |||
785 | ||||
786 | (void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to); | |||
787 | (void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by); | |||
788 | ||||
789 | printf("%s%s%s %i: %s\n", on_color_operational, special_glyph(BLACK_CIRCLE), off_color_operational, info->ifindex, info->name); | |||
790 | ||||
791 | printf(" Link File: %s\n" | |||
792 | " Network File: %s\n" | |||
793 | " Type: %s\n" | |||
794 | " State: %s%s%s (%s%s%s)\n", | |||
795 | strna(link), | |||
796 | strna(network), | |||
797 | strna(t), | |||
798 | on_color_operational, strna(operational_state), off_color_operational, | |||
799 | on_color_setup, strna(setup_state), off_color_setup); | |||
800 | ||||
801 | if (path) | |||
802 | printf(" Path: %s\n", path); | |||
803 | if (driver) | |||
804 | printf(" Driver: %s\n", driver); | |||
805 | if (vendor) | |||
806 | printf(" Vendor: %s\n", vendor); | |||
807 | if (model) | |||
808 | printf(" Model: %s\n", model); | |||
809 | ||||
810 | if (info->has_mac_address) { | |||
811 | _cleanup_free___attribute__((cleanup(freep))) char *description = NULL((void*)0); | |||
812 | char ea[ETHER_ADDR_TO_STRING_MAX(3*6)]; | |||
813 | ||||
814 | (void) ieee_oui(hwdb, &info->mac_address, &description); | |||
815 | ||||
816 | if (description) | |||
817 | printf(" HW Address: %s (%s)\n", ether_addr_to_string(&info->mac_address, ea), description); | |||
818 | else | |||
819 | printf(" HW Address: %s\n", ether_addr_to_string(&info->mac_address, ea)); | |||
820 | } | |||
821 | ||||
822 | if (info->has_mtu) | |||
823 | printf(" MTU: %" PRIu32"u" "\n", info->mtu); | |||
824 | ||||
825 | (void) dump_addresses(rtnl, " Address: ", info->ifindex); | |||
826 | (void) dump_gateways(rtnl, hwdb, " Gateway: ", info->ifindex); | |||
827 | ||||
828 | dump_list(" DNS: ", dns); | |||
829 | dump_list(" Search Domains: ", search_domains); | |||
830 | dump_list(" Route Domains: ", route_domains); | |||
831 | ||||
832 | dump_list(" NTP: ", ntp); | |||
833 | ||||
834 | dump_ifindexes("Carrier Bound To: ", carrier_bound_to); | |||
835 | dump_ifindexes("Carrier Bound By: ", carrier_bound_by); | |||
836 | ||||
837 | (void) sd_network_link_get_timezone(info->ifindex, &tz); | |||
838 | if (tz) | |||
839 | printf(" Time Zone: %s\n", tz); | |||
840 | ||||
841 | (void) dump_lldp_neighbors(" Connected To: ", info->ifindex); | |||
842 | ||||
843 | return 0; | |||
844 | } | |||
845 | ||||
846 | static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) { | |||
847 | _cleanup_free___attribute__((cleanup(freep))) char *operational_state = NULL((void*)0); | |||
848 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **dns = NULL((void*)0), **ntp = NULL((void*)0), **search_domains = NULL((void*)0), **route_domains = NULL((void*)0); | |||
849 | const char *on_color_operational, *off_color_operational; | |||
850 | ||||
851 | assert(rtnl)do { if ((__builtin_expect(!!(!(rtnl)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rtnl"), "../src/network/networkctl.c", 851 , __PRETTY_FUNCTION__); } while (0); | |||
852 | ||||
853 | (void) sd_network_get_operational_state(&operational_state); | |||
854 | operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); | |||
855 | ||||
856 | printf("%s%s%s State: %s%s%s\n", | |||
857 | on_color_operational, special_glyph(BLACK_CIRCLE), off_color_operational, | |||
858 | on_color_operational, strna(operational_state), off_color_operational); | |||
859 | ||||
860 | (void) dump_addresses(rtnl, " Address: ", 0); | |||
861 | (void) dump_gateways(rtnl, hwdb, " Gateway: ", 0); | |||
862 | ||||
863 | (void) sd_network_get_dns(&dns); | |||
864 | dump_list(" DNS: ", dns); | |||
865 | ||||
866 | (void) sd_network_get_search_domains(&search_domains); | |||
867 | dump_list("Search Domains: ", search_domains); | |||
868 | ||||
869 | (void) sd_network_get_route_domains(&route_domains); | |||
870 | dump_list(" Route Domains: ", route_domains); | |||
871 | ||||
872 | (void) sd_network_get_ntp(&ntp); | |||
873 | dump_list(" NTP: ", ntp); | |||
874 | ||||
875 | return 0; | |||
876 | } | |||
877 | ||||
878 | static int link_status(int argc, char *argv[], void *userdata) { | |||
879 | _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0); | |||
880 | _cleanup_(sd_hwdb_unrefp)__attribute__((cleanup(sd_hwdb_unrefp))) sd_hwdb *hwdb = NULL((void*)0); | |||
881 | _cleanup_free___attribute__((cleanup(freep))) LinkInfo *links = NULL((void*)0); | |||
882 | int r, c, i; | |||
883 | ||||
884 | (void) pager_open(arg_no_pager, false0); | |||
885 | ||||
886 | r = sd_netlink_open(&rtnl); | |||
887 | if (r < 0) | |||
888 | return log_error_errno(r, "Failed to connect to netlink: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 888, __func__, "Failed to connect to netlink: %m" ) : -abs(_e); }); | |||
889 | ||||
890 | r = sd_hwdb_new(&hwdb); | |||
891 | if (r < 0) | |||
892 | log_debug_errno(r, "Failed to open hardware database: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 892, __func__, "Failed to open hardware database: %m" ) : -abs(_e); }); | |||
893 | ||||
894 | if (arg_all) | |||
895 | c = acquire_link_info_all(rtnl, &links); | |||
896 | else if (argc <= 1) | |||
897 | return system_status(rtnl, hwdb); | |||
898 | else | |||
899 | c = acquire_link_info_strv(rtnl, argv + 1, &links); | |||
900 | if (c < 0) | |||
901 | return c; | |||
902 | ||||
903 | for (i = 0; i < c; i++) { | |||
904 | if (i > 0) | |||
905 | fputc('\n', stdoutstdout); | |||
906 | ||||
907 | link_status_one(rtnl, hwdb, links + i); | |||
908 | } | |||
909 | ||||
910 | return 0; | |||
911 | } | |||
912 | ||||
913 | static char *lldp_capabilities_to_string(uint16_t x) { | |||
914 | static const char characters[] = { | |||
915 | 'o', 'p', 'b', 'w', 'r', 't', 'd', 'a', 'c', 's', 'm', | |||
916 | }; | |||
917 | char *ret; | |||
918 | unsigned i; | |||
919 | ||||
920 | ret = new(char, ELEMENTSOF(characters) + 1)((char*) malloc_multiply(sizeof(char), (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(characters), typeof(& *(characters))), sizeof(characters)/sizeof((characters)[0]), ( (void)0))) + 1))); | |||
921 | if (!ret) | |||
922 | return NULL((void*)0); | |||
923 | ||||
924 | for (i = 0; i < ELEMENTSOF(characters)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(characters), typeof(&*(characters))), sizeof(characters )/sizeof((characters)[0]), ((void)0))); i++) | |||
925 | ret[i] = (x & (1U << i)) ? characters[i] : '.'; | |||
926 | ||||
927 | ret[i] = 0; | |||
928 | return ret; | |||
929 | } | |||
930 | ||||
931 | static void lldp_capabilities_legend(uint16_t x) { | |||
932 | unsigned w, i, cols = columns(); | |||
933 | static const char* const table[] = { | |||
934 | "o - Other", | |||
935 | "p - Repeater", | |||
936 | "b - Bridge", | |||
937 | "w - WLAN Access Point", | |||
938 | "r - Router", | |||
939 | "t - Telephone", | |||
940 | "d - DOCSIS cable device", | |||
941 | "a - Station", | |||
942 | "c - Customer VLAN", | |||
943 | "s - Service VLAN", | |||
944 | "m - Two-port MAC Relay (TPMR)", | |||
945 | }; | |||
946 | ||||
947 | if (x == 0) | |||
948 | return; | |||
949 | ||||
950 | printf("\nCapability Flags:\n"); | |||
951 | for (w = 0, i = 0; i < ELEMENTSOF(table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(table), typeof(&*(table))), sizeof(table)/sizeof( (table)[0]), ((void)0))); i++) | |||
952 | if (x & (1U << i) || arg_all) { | |||
953 | bool_Bool newline; | |||
954 | ||||
955 | newline = w + strlen(table[i]) + (w == 0 ? 0 : 2) > cols; | |||
956 | if (newline) | |||
957 | w = 0; | |||
958 | w += printf("%s%s%s", newline ? "\n" : "", w == 0 ? "" : "; ", table[i]); | |||
959 | } | |||
960 | puts(""); | |||
961 | } | |||
962 | ||||
963 | static int link_lldp_status(int argc, char *argv[], void *userdata) { | |||
964 | _cleanup_(sd_netlink_unrefp)__attribute__((cleanup(sd_netlink_unrefp))) sd_netlink *rtnl = NULL((void*)0); | |||
965 | _cleanup_free___attribute__((cleanup(freep))) LinkInfo *links = NULL((void*)0); | |||
966 | int i, r, c, m = 0; | |||
967 | uint16_t all = 0; | |||
968 | ||||
969 | r = sd_netlink_open(&rtnl); | |||
970 | if (r < 0) | |||
971 | return log_error_errno(r, "Failed to connect to netlink: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 971, __func__, "Failed to connect to netlink: %m" ) : -abs(_e); }); | |||
972 | ||||
973 | if (argc > 1) | |||
974 | c = acquire_link_info_strv(rtnl, argv + 1, &links); | |||
975 | else | |||
976 | c = acquire_link_info_all(rtnl, &links); | |||
977 | if (c < 0) | |||
978 | return c; | |||
979 | ||||
980 | (void) pager_open(arg_no_pager, false0); | |||
981 | ||||
982 | if (arg_legend) | |||
983 | printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", | |||
984 | "LINK", | |||
985 | "CHASSIS ID", | |||
986 | "SYSTEM NAME", | |||
987 | "CAPS", | |||
988 | "PORT ID", | |||
989 | "PORT DESCRIPTION"); | |||
990 | ||||
991 | for (i = 0; i < c; i++) { | |||
992 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
993 | ||||
994 | r = open_lldp_neighbors(links[i].ifindex, &f); | |||
995 | if (r == -ENOENT2) | |||
996 | continue; | |||
997 | if (r < 0) { | |||
998 | log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 998, __func__, "Failed to open LLDP data for %i, ignoring: %m" , links[i].ifindex) : -abs(_e); }); | |||
999 | continue; | |||
1000 | } | |||
1001 | ||||
1002 | for (;;) { | |||
1003 | _cleanup_free___attribute__((cleanup(freep))) char *cid = NULL((void*)0), *pid = NULL((void*)0), *sname = NULL((void*)0), *pdesc = NULL((void*)0); | |||
1004 | const char *chassis_id = NULL((void*)0), *port_id = NULL((void*)0), *system_name = NULL((void*)0), *port_description = NULL((void*)0), *capabilities = NULL((void*)0); | |||
1005 | _cleanup_(sd_lldp_neighbor_unrefp)__attribute__((cleanup(sd_lldp_neighbor_unrefp))) sd_lldp_neighbor *n = NULL((void*)0); | |||
1006 | uint16_t cc; | |||
1007 | ||||
1008 | r = next_lldp_neighbor(f, &n); | |||
1009 | if (r < 0) { | |||
1010 | log_warning_errno(r, "Failed to read neighbor data: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/network/networkctl.c", 1010, __func__, "Failed to read neighbor data: %m" ) : -abs(_e); }); | |||
1011 | break; | |||
1012 | } | |||
1013 | if (r == 0) | |||
1014 | break; | |||
1015 | ||||
1016 | (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id); | |||
1017 | (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); | |||
1018 | (void) sd_lldp_neighbor_get_system_name(n, &system_name); | |||
1019 | (void) sd_lldp_neighbor_get_port_description(n, &port_description); | |||
1020 | ||||
1021 | if (chassis_id) { | |||
1022 | cid = ellipsize(chassis_id, 17, 100); | |||
1023 | if (cid) | |||
1024 | chassis_id = cid; | |||
1025 | } | |||
1026 | ||||
1027 | if (port_id) { | |||
1028 | pid = ellipsize(port_id, 17, 100); | |||
1029 | if (pid) | |||
1030 | port_id = pid; | |||
1031 | } | |||
1032 | ||||
1033 | if (system_name) { | |||
1034 | sname = ellipsize(system_name, 16, 100); | |||
1035 | if (sname) | |||
1036 | system_name = sname; | |||
1037 | } | |||
1038 | ||||
1039 | if (port_description) { | |||
1040 | pdesc = ellipsize(port_description, 16, 100); | |||
1041 | if (pdesc) | |||
1042 | port_description = pdesc; | |||
1043 | } | |||
1044 | ||||
1045 | if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) { | |||
1046 | capabilities = lldp_capabilities_to_string(cc); | |||
1047 | all |= cc; | |||
1048 | } | |||
1049 | ||||
1050 | printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", | |||
1051 | links[i].name, | |||
1052 | strna(chassis_id), | |||
1053 | strna(system_name), | |||
1054 | strna(capabilities), | |||
1055 | strna(port_id), | |||
1056 | strna(port_description)); | |||
1057 | ||||
1058 | m++; | |||
1059 | } | |||
1060 | } | |||
1061 | ||||
1062 | if (arg_legend) { | |||
1063 | lldp_capabilities_legend(all); | |||
1064 | printf("\n%i neighbors listed.\n", m); | |||
1065 | } | |||
1066 | ||||
1067 | return 0; | |||
1068 | } | |||
1069 | ||||
1070 | static void help(void) { | |||
1071 | printf("%s [OPTIONS...]\n\n" | |||
1072 | "Query and control the networking subsystem.\n\n" | |||
1073 | " -h --help Show this help\n" | |||
1074 | " --version Show package version\n" | |||
1075 | " --no-pager Do not pipe output into a pager\n" | |||
1076 | " --no-legend Do not show the headers and footers\n" | |||
1077 | " -a --all Show status for all links\n\n" | |||
1078 | "Commands:\n" | |||
1079 | " list [LINK...] List links\n" | |||
1080 | " status [LINK...] Show link status\n" | |||
1081 | " lldp [LINK...] Show LLDP neighbors\n" | |||
1082 | " label Show current address label entries in the kernel\n" | |||
1083 | , program_invocation_short_name); | |||
1084 | } | |||
1085 | ||||
1086 | static int parse_argv(int argc, char *argv[]) { | |||
1087 | ||||
1088 | enum { | |||
1089 | ARG_VERSION = 0x100, | |||
1090 | ARG_NO_PAGER, | |||
1091 | ARG_NO_LEGEND, | |||
1092 | }; | |||
1093 | ||||
1094 | static const struct option options[] = { | |||
1095 | { "help", no_argument0, NULL((void*)0), 'h' }, | |||
1096 | { "version", no_argument0, NULL((void*)0), ARG_VERSION }, | |||
1097 | { "no-pager", no_argument0, NULL((void*)0), ARG_NO_PAGER }, | |||
1098 | { "no-legend", no_argument0, NULL((void*)0), ARG_NO_LEGEND }, | |||
1099 | { "all", no_argument0, NULL((void*)0), 'a' }, | |||
1100 | {} | |||
1101 | }; | |||
1102 | ||||
1103 | int c; | |||
1104 | ||||
1105 | assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/network/networkctl.c" , 1105, __PRETTY_FUNCTION__); } while (0); | |||
1106 | assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argv"), "../src/network/networkctl.c", 1106 , __PRETTY_FUNCTION__); } while (0); | |||
1107 | ||||
1108 | while ((c = getopt_long(argc, argv, "ha", options, NULL((void*)0))) >= 0) { | |||
1109 | ||||
1110 | switch (c) { | |||
1111 | ||||
1112 | case 'h': | |||
1113 | help(); | |||
1114 | return 0; | |||
1115 | ||||
1116 | case ARG_VERSION: | |||
1117 | return version(); | |||
1118 | ||||
1119 | case ARG_NO_PAGER: | |||
1120 | arg_no_pager = true1; | |||
1121 | break; | |||
1122 | ||||
1123 | case ARG_NO_LEGEND: | |||
1124 | arg_legend = false0; | |||
1125 | break; | |||
1126 | ||||
1127 | case 'a': | |||
1128 | arg_all = true1; | |||
1129 | break; | |||
1130 | ||||
1131 | case '?': | |||
1132 | return -EINVAL22; | |||
1133 | ||||
1134 | default: | |||
1135 | assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unhandled option"), "../src/network/networkctl.c", 1135, __PRETTY_FUNCTION__ ); } while (0); | |||
1136 | } | |||
1137 | } | |||
1138 | ||||
1139 | return 1; | |||
1140 | } | |||
1141 | ||||
1142 | static int networkctl_main(int argc, char *argv[]) { | |||
1143 | static const Verb verbs[] = { | |||
1144 | { "list", VERB_ANY((unsigned) -1), VERB_ANY((unsigned) -1), VERB_DEFAULT, list_links }, | |||
1145 | { "status", VERB_ANY((unsigned) -1), VERB_ANY((unsigned) -1), 0, link_status }, | |||
1146 | { "lldp", VERB_ANY((unsigned) -1), VERB_ANY((unsigned) -1), 0, link_lldp_status }, | |||
1147 | { "label", VERB_ANY((unsigned) -1), VERB_ANY((unsigned) -1), 0, list_address_labels }, | |||
1148 | {} | |||
1149 | }; | |||
1150 | ||||
1151 | return dispatch_verb(argc, argv, verbs, NULL((void*)0)); | |||
1152 | } | |||
1153 | ||||
1154 | static void warn_networkd_missing(void) { | |||
1155 | ||||
1156 | if (access("/run/systemd/netif/state", F_OK0) >= 0) | |||
1157 | return; | |||
1158 | ||||
1159 | fprintf(stderrstderr, "WARNING: systemd-networkd is not running, output will be incomplete.\n\n"); | |||
1160 | } | |||
1161 | ||||
1162 | int main(int argc, char* argv[]) { | |||
1163 | int r; | |||
1164 | ||||
1165 | log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD); | |||
1166 | log_open(); | |||
1167 | ||||
1168 | r = parse_argv(argc, argv); | |||
1169 | if (r <= 0) | |||
1170 | goto finish; | |||
1171 | ||||
1172 | warn_networkd_missing(); | |||
1173 | ||||
1174 | r = networkctl_main(argc, argv); | |||
1175 | ||||
1176 | finish: | |||
1177 | pager_close(); | |||
1178 | ||||
1179 | return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0; | |||
1180 | } |