File: | build-scan/../src/network/networkctl.c |
Warning: | line 1062, column 13 Potential leak of memory pointed to by 'links' |
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
| ||||
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 | } |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once |
3 | |
4 | #include <alloca.h> |
5 | #include <stddef.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | |
9 | #include "macro.h" |
10 | |
11 | #define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n))) |
12 | |
13 | #define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t))) |
14 | |
15 | #define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while (0); (t*) __builtin_alloca (sizeof(t)*(n)); }) \ |
16 | ({ \ |
17 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while (0); \ |
18 | (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \ |
19 | }) |
20 | |
21 | #define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while (0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_) ; }); }) \ |
22 | ({ \ |
23 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while (0); \ |
24 | (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_); }); \ |
25 | }) |
26 | |
27 | #define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n))) |
28 | |
29 | #define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) |
30 | |
31 | #define malloc0(n)(calloc(1, (n))) (calloc(1, (n))) |
32 | |
33 | static inline void *mfree(void *memory) { |
34 | free(memory); |
35 | return NULL((void*)0); |
36 | } |
37 | |
38 | #define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \ |
39 | ({ \ |
40 | free(a); \ |
41 | (a) = (b); \ |
42 | (b) = NULL((void*)0); \ |
43 | 0; \ |
44 | }) |
45 | |
46 | void* memdup(const void *p, size_t l) _alloc_(2); |
47 | void* memdup_suffix0(const void *p, size_t l) _alloc_(2); |
48 | |
49 | static inline void freep(void *p) { |
50 | free(*(void**) p); |
51 | } |
52 | |
53 | #define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep))) |
54 | |
55 | static inline bool_Bool size_multiply_overflow(size_t size, size_t need) { |
56 | return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL ) / need)),0)); |
57 | } |
58 | |
59 | _malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { |
60 | if (size_multiply_overflow(size, need)) |
61 | return NULL((void*)0); |
62 | |
63 | return malloc(size * need); |
64 | } |
65 | |
66 | #if !HAVE_REALLOCARRAY1 |
67 | _alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { |
68 | if (size_multiply_overflow(size, need)) |
69 | return NULL((void*)0); |
70 | |
71 | return realloc(p, size * need); |
72 | } |
73 | #endif |
74 | |
75 | _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { |
76 | if (size_multiply_overflow(size, need)) |
77 | return NULL((void*)0); |
78 | |
79 | return memdup(p, size * need); |
80 | } |
81 | |
82 | _alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { |
83 | if (size_multiply_overflow(size, need)) |
84 | return NULL((void*)0); |
85 | |
86 | return memdup_suffix0(p, size * need); |
87 | } |
88 | |
89 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); |
90 | void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); |
91 | |
92 | #define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
93 | greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
94 | |
95 | #define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
96 | greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
97 | |
98 | #define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_ ); (void *) memset(_new_, 0, _len_); }) \ |
99 | ({ \ |
100 | char *_new_; \ |
101 | size_t _len_ = n; \ |
102 | _new_ = alloca(_len_)__builtin_alloca (_len_); \ |
103 | (void *) memset(_new_, 0, _len_); \ |
104 | }) |
105 | |
106 | /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ |
107 | #define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca ((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }) \ |
108 | ({ \ |
109 | void *_ptr_; \ |
110 | size_t _mask_ = (align) - 1; \ |
111 | _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \ |
112 | (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ |
113 | }) |
114 | |
115 | #define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_ ; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_ ) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_ ); }); (void*)memset(_new_, 0, _size_); }) \ |
116 | ({ \ |
117 | void *_new_; \ |
118 | size_t _size_ = (size); \ |
119 | _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }); \ |
120 | (void*)memset(_new_, 0, _size_); \ |
121 | }) |
122 | |
123 | /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to |
124 | * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ |
125 | #define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \ |
126 | ({ \ |
127 | typeof(ptr) _ptr_ = (ptr); \ |
128 | (ptr) = NULL((void*)0); \ |
129 | _ptr_; \ |
130 | }) |