1 |
|
|
/* $OpenBSD: ripctl.c,v 1.17 2016/08/02 16:05:32 jca Exp $ |
2 |
|
|
* |
3 |
|
|
* Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> |
4 |
|
|
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> |
5 |
|
|
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> |
6 |
|
|
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org> |
7 |
|
|
* |
8 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
9 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
10 |
|
|
* copyright notice and this permission notice appear in all copies. |
11 |
|
|
* |
12 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
13 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
14 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
15 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
16 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
17 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
18 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <sys/types.h> |
22 |
|
|
#include <sys/socket.h> |
23 |
|
|
#include <sys/un.h> |
24 |
|
|
#include <netinet/in.h> |
25 |
|
|
#include <arpa/inet.h> |
26 |
|
|
#include <net/if_media.h> |
27 |
|
|
#include <net/if_types.h> |
28 |
|
|
|
29 |
|
|
#include <err.h> |
30 |
|
|
#include <errno.h> |
31 |
|
|
#include <stdio.h> |
32 |
|
|
#include <stdlib.h> |
33 |
|
|
#include <string.h> |
34 |
|
|
#include <unistd.h> |
35 |
|
|
|
36 |
|
|
#include "rip.h" |
37 |
|
|
#include "ripd.h" |
38 |
|
|
#include "ripe.h" |
39 |
|
|
#include "parser.h" |
40 |
|
|
|
41 |
|
|
__dead void usage(void); |
42 |
|
|
const char *fmt_timeframe_core(time_t); |
43 |
|
|
const char *get_linkstate(uint8_t, int); |
44 |
|
|
int show_interface_msg(struct imsg *); |
45 |
|
|
uint64_t get_ifms_type(uint8_t); |
46 |
|
|
int show_rib_msg(struct imsg *); |
47 |
|
|
int show_nbr_msg(struct imsg *); |
48 |
|
|
void show_fib_head(void); |
49 |
|
|
int show_fib_msg(struct imsg *); |
50 |
|
|
void show_interface_head(void); |
51 |
|
|
int show_fib_interface_msg(struct imsg *); |
52 |
|
|
const char *get_media_descr(uint64_t); |
53 |
|
|
void print_baudrate(uint64_t); |
54 |
|
|
|
55 |
|
|
struct imsgbuf *ibuf; |
56 |
|
|
|
57 |
|
|
__dead void |
58 |
|
|
usage(void) |
59 |
|
|
{ |
60 |
|
|
extern char *__progname; |
61 |
|
|
|
62 |
|
|
fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n", |
63 |
|
|
__progname); |
64 |
|
|
exit(1); |
65 |
|
|
} |
66 |
|
|
|
67 |
|
|
int |
68 |
|
|
main(int argc, char *argv[]) |
69 |
|
|
{ |
70 |
|
|
struct sockaddr_un sun; |
71 |
|
|
struct parse_result *res; |
72 |
|
|
struct imsg imsg; |
73 |
|
|
unsigned int ifidx = 0; |
74 |
|
|
int ctl_sock; |
75 |
|
|
int done = 0, verbose = 0; |
76 |
|
|
int n; |
77 |
|
|
int ch; |
78 |
|
|
char *sockname = RIPD_SOCKET; |
79 |
|
|
|
80 |
|
|
while ((ch = getopt(argc, argv, "s:")) != -1) { |
81 |
|
|
switch (ch) { |
82 |
|
|
case 's': |
83 |
|
|
sockname = optarg; |
84 |
|
|
break; |
85 |
|
|
default: |
86 |
|
|
usage(); |
87 |
|
|
/* NOTREACHED */ |
88 |
|
|
} |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
argc -= optind; |
92 |
|
|
argv += optind; |
93 |
|
|
|
94 |
|
|
/* parse options */ |
95 |
|
|
if ((res = parse(argc, argv)) == NULL) |
96 |
|
|
exit(1); |
97 |
|
|
|
98 |
|
|
/* connect to ripd control socket */ |
99 |
|
|
if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) |
100 |
|
|
err(1, "socket"); |
101 |
|
|
|
102 |
|
|
bzero(&sun, sizeof(sun)); |
103 |
|
|
sun.sun_family = AF_UNIX; |
104 |
|
|
strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path)); |
105 |
|
|
if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) |
106 |
|
|
err(1, "connect: %s", sockname); |
107 |
|
|
|
108 |
|
|
if (pledge("stdio flock rpath cpath wpath", NULL) == -1) |
109 |
|
|
err(1, "pledge"); |
110 |
|
|
|
111 |
|
|
if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) |
112 |
|
|
err(1, NULL); |
113 |
|
|
imsg_init(ibuf, ctl_sock); |
114 |
|
|
done = 0; |
115 |
|
|
|
116 |
|
|
/* process user request */ |
117 |
|
|
switch (res->action) { |
118 |
|
|
case NONE: |
119 |
|
|
usage(); |
120 |
|
|
/* not reached */ |
121 |
|
|
case SHOW: |
122 |
|
|
case SHOW_IFACE: |
123 |
|
|
printf("%-11s %-18s %-10s %-10s %-8s\n", |
124 |
|
|
"Interface", "Address", "State", "Linkstate", |
125 |
|
|
"Uptime"); |
126 |
|
|
if (*res->ifname) { |
127 |
|
|
ifidx = if_nametoindex(res->ifname); |
128 |
|
|
if (ifidx == 0) |
129 |
|
|
errx(1, "no such interface %s", res->ifname); |
130 |
|
|
} |
131 |
|
|
imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, |
132 |
|
|
&ifidx, sizeof(ifidx)); |
133 |
|
|
break; |
134 |
|
|
case SHOW_NBR: |
135 |
|
|
printf("%-15s %-15s %-15s %-9s %-10s\n", "ID", |
136 |
|
|
"State", "Address", "Iface", "Uptime"); |
137 |
|
|
imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); |
138 |
|
|
break; |
139 |
|
|
case SHOW_RIB: |
140 |
|
|
printf("%-20s %-17s %-7s\n", "Destination", |
141 |
|
|
"Nexthop", "Cost"); |
142 |
|
|
imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0); |
143 |
|
|
break; |
144 |
|
|
case SHOW_FIB: |
145 |
|
|
if (!res->addr.s_addr) |
146 |
|
|
imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, |
147 |
|
|
&res->flags, sizeof(res->flags)); |
148 |
|
|
else |
149 |
|
|
imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, |
150 |
|
|
&res->addr, sizeof(res->addr)); |
151 |
|
|
show_fib_head(); |
152 |
|
|
break; |
153 |
|
|
case SHOW_FIB_IFACE: |
154 |
|
|
if (*res->ifname) |
155 |
|
|
imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, |
156 |
|
|
res->ifname, sizeof(res->ifname)); |
157 |
|
|
else |
158 |
|
|
imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); |
159 |
|
|
show_interface_head(); |
160 |
|
|
break; |
161 |
|
|
case FIB: |
162 |
|
|
errx(1, "fib couple|decouple"); |
163 |
|
|
break; |
164 |
|
|
case FIB_COUPLE: |
165 |
|
|
imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0); |
166 |
|
|
printf("couple request sent.\n"); |
167 |
|
|
done = 1; |
168 |
|
|
break; |
169 |
|
|
case FIB_DECOUPLE: |
170 |
|
|
imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0); |
171 |
|
|
printf("decouple request sent.\n"); |
172 |
|
|
done = 1; |
173 |
|
|
break; |
174 |
|
|
case LOG_VERBOSE: |
175 |
|
|
verbose = 1; |
176 |
|
|
/* FALLTHROUGH */ |
177 |
|
|
case LOG_BRIEF: |
178 |
|
|
imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, |
179 |
|
|
&verbose, sizeof(verbose)); |
180 |
|
|
printf("logging request sent.\n"); |
181 |
|
|
done = 1; |
182 |
|
|
break; |
183 |
|
|
case RELOAD: |
184 |
|
|
imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); |
185 |
|
|
printf("reload request sent.\n"); |
186 |
|
|
done = 1; |
187 |
|
|
break; |
188 |
|
|
} |
189 |
|
|
|
190 |
|
|
while (ibuf->w.queued) |
191 |
|
|
if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) |
192 |
|
|
err(1, "write error"); |
193 |
|
|
|
194 |
|
|
while (!done) { |
195 |
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) |
196 |
|
|
errx(1, "imsg_read error"); |
197 |
|
|
if (n == 0) |
198 |
|
|
errx(1, "pipe closed"); |
199 |
|
|
|
200 |
|
|
while (!done) { |
201 |
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1) |
202 |
|
|
errx(1, "imsg_get error"); |
203 |
|
|
if (n == 0) |
204 |
|
|
break; |
205 |
|
|
switch (res->action) { |
206 |
|
|
case SHOW: |
207 |
|
|
case SHOW_IFACE: |
208 |
|
|
done = show_interface_msg(&imsg); |
209 |
|
|
break; |
210 |
|
|
case SHOW_NBR: |
211 |
|
|
done = show_nbr_msg(&imsg); |
212 |
|
|
break; |
213 |
|
|
case SHOW_RIB: |
214 |
|
|
done = show_rib_msg(&imsg); |
215 |
|
|
break; |
216 |
|
|
case SHOW_FIB: |
217 |
|
|
done = show_fib_msg(&imsg); |
218 |
|
|
break; |
219 |
|
|
case SHOW_FIB_IFACE: |
220 |
|
|
done = show_fib_interface_msg(&imsg); |
221 |
|
|
break; |
222 |
|
|
case NONE: |
223 |
|
|
case FIB: |
224 |
|
|
case FIB_COUPLE: |
225 |
|
|
case FIB_DECOUPLE: |
226 |
|
|
case LOG_VERBOSE: |
227 |
|
|
case LOG_BRIEF: |
228 |
|
|
case RELOAD: |
229 |
|
|
break; |
230 |
|
|
} |
231 |
|
|
imsg_free(&imsg); |
232 |
|
|
} |
233 |
|
|
} |
234 |
|
|
close(ctl_sock); |
235 |
|
|
free(ibuf); |
236 |
|
|
|
237 |
|
|
return (0); |
238 |
|
|
} |
239 |
|
|
|
240 |
|
|
uint64_t |
241 |
|
|
get_ifms_type(uint8_t if_type) |
242 |
|
|
{ |
243 |
|
|
switch (if_type) { |
244 |
|
|
case IFT_ETHER: |
245 |
|
|
return (IFM_ETHER); |
246 |
|
|
break; |
247 |
|
|
case IFT_FDDI: |
248 |
|
|
return (IFM_FDDI); |
249 |
|
|
break; |
250 |
|
|
case IFT_CARP: |
251 |
|
|
return (IFM_CARP); |
252 |
|
|
break; |
253 |
|
|
default: |
254 |
|
|
return (0); |
255 |
|
|
break; |
256 |
|
|
} |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
#define TF_BUFS 8 |
260 |
|
|
#define TF_LEN 9 |
261 |
|
|
|
262 |
|
|
const char * |
263 |
|
|
fmt_timeframe_core(time_t t) |
264 |
|
|
{ |
265 |
|
|
char *buf; |
266 |
|
|
static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ |
267 |
|
|
static int idx = 0; |
268 |
|
|
unsigned int sec, min, hrs, day; |
269 |
|
|
unsigned long long week; |
270 |
|
|
|
271 |
|
|
if (t == 0) |
272 |
|
|
return ("Stopped"); |
273 |
|
|
|
274 |
|
|
buf = tfbuf[idx++]; |
275 |
|
|
if (idx == TF_BUFS) |
276 |
|
|
idx = 0; |
277 |
|
|
|
278 |
|
|
week = t; |
279 |
|
|
|
280 |
|
|
sec = week % 60; |
281 |
|
|
week /= 60; |
282 |
|
|
min = week % 60; |
283 |
|
|
week /= 60; |
284 |
|
|
hrs = week % 24; |
285 |
|
|
week /= 24; |
286 |
|
|
day = week % 7; |
287 |
|
|
week /= 7; |
288 |
|
|
|
289 |
|
|
if (week > 0) |
290 |
|
|
snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); |
291 |
|
|
else if (day > 0) |
292 |
|
|
snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); |
293 |
|
|
else |
294 |
|
|
snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); |
295 |
|
|
|
296 |
|
|
return (buf); |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
/* prototype defined in ripd.h and shared with the kroute.c version */ |
300 |
|
|
u_int8_t |
301 |
|
|
mask2prefixlen(in_addr_t ina) |
302 |
|
|
{ |
303 |
|
|
if (ina == 0) |
304 |
|
|
return (0); |
305 |
|
|
else |
306 |
|
|
return (33 - ffs(ntohl(ina))); |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
int |
310 |
|
|
show_interface_msg(struct imsg *imsg) |
311 |
|
|
{ |
312 |
|
|
struct ctl_iface *iface; |
313 |
|
|
char *netid; |
314 |
|
|
|
315 |
|
|
switch (imsg->hdr.type) { |
316 |
|
|
case IMSG_CTL_SHOW_IFACE: |
317 |
|
|
iface = imsg->data; |
318 |
|
|
|
319 |
|
|
if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr), |
320 |
|
|
mask2prefixlen(iface->mask.s_addr)) == -1) |
321 |
|
|
err(1, NULL); |
322 |
|
|
printf("%-11s %-18s %-10s %-10s %-8s\n", |
323 |
|
|
iface->name, netid, if_state_name(iface->state), |
324 |
|
|
get_linkstate(iface->if_type, iface->linkstate), |
325 |
|
|
iface->uptime == 0 ? "00:00:00" : |
326 |
|
|
fmt_timeframe_core(iface->uptime)); |
327 |
|
|
free(netid); |
328 |
|
|
break; |
329 |
|
|
case IMSG_CTL_END: |
330 |
|
|
printf("\n"); |
331 |
|
|
return (1); |
332 |
|
|
default: |
333 |
|
|
break; |
334 |
|
|
} |
335 |
|
|
|
336 |
|
|
return (0); |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
int |
340 |
|
|
show_rib_msg(struct imsg *imsg) |
341 |
|
|
{ |
342 |
|
|
struct ctl_rt *rt; |
343 |
|
|
char *dstnet; |
344 |
|
|
|
345 |
|
|
switch (imsg->hdr.type) { |
346 |
|
|
case IMSG_CTL_SHOW_RIB: |
347 |
|
|
rt = imsg->data; |
348 |
|
|
if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), |
349 |
|
|
mask2prefixlen(rt->netmask.s_addr)) == -1) |
350 |
|
|
err(1, NULL); |
351 |
|
|
|
352 |
|
|
printf("%-20s %-17s %-7d\n", dstnet, |
353 |
|
|
inet_ntoa(rt->nexthop), |
354 |
|
|
rt->metric); |
355 |
|
|
free(dstnet); |
356 |
|
|
|
357 |
|
|
break; |
358 |
|
|
case IMSG_CTL_END: |
359 |
|
|
printf("\n"); |
360 |
|
|
return (1); |
361 |
|
|
default: |
362 |
|
|
break; |
363 |
|
|
} |
364 |
|
|
|
365 |
|
|
return (0); |
366 |
|
|
} |
367 |
|
|
|
368 |
|
|
int |
369 |
|
|
show_nbr_msg(struct imsg *imsg) |
370 |
|
|
{ |
371 |
|
|
struct ctl_nbr *nbr; |
372 |
|
|
char *state; |
373 |
|
|
|
374 |
|
|
switch (imsg->hdr.type) { |
375 |
|
|
case IMSG_CTL_SHOW_NBR: |
376 |
|
|
nbr = imsg->data; |
377 |
|
|
if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), |
378 |
|
|
if_state_name(nbr->iface_state)) == -1) |
379 |
|
|
err(1, NULL); |
380 |
|
|
printf("%-15s %-16s", inet_ntoa(nbr->id), |
381 |
|
|
state); |
382 |
|
|
printf("%-15s %-10s", inet_ntoa(nbr->addr), nbr->name); |
383 |
|
|
printf("%-15s\n", nbr->uptime == 0 ? "-" : |
384 |
|
|
fmt_timeframe_core(nbr->uptime)); |
385 |
|
|
free(state); |
386 |
|
|
break; |
387 |
|
|
case IMSG_CTL_END: |
388 |
|
|
printf("\n"); |
389 |
|
|
return (1); |
390 |
|
|
default: |
391 |
|
|
break; |
392 |
|
|
} |
393 |
|
|
|
394 |
|
|
return (0); |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
void |
398 |
|
|
show_fib_head(void) |
399 |
|
|
{ |
400 |
|
|
printf("flags: * = valid, R = RIP, C = Connected, S = Static\n"); |
401 |
|
|
printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); |
402 |
|
|
} |
403 |
|
|
|
404 |
|
|
int |
405 |
|
|
show_fib_msg(struct imsg *imsg) |
406 |
|
|
{ |
407 |
|
|
struct kroute *k; |
408 |
|
|
char *p; |
409 |
|
|
|
410 |
|
|
switch (imsg->hdr.type) { |
411 |
|
|
case IMSG_CTL_KROUTE: |
412 |
|
|
if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) |
413 |
|
|
errx(1, "wrong imsg len"); |
414 |
|
|
k = imsg->data; |
415 |
|
|
|
416 |
|
|
if (k->flags & F_DOWN) |
417 |
|
|
printf(" "); |
418 |
|
|
else |
419 |
|
|
printf("*"); |
420 |
|
|
|
421 |
|
|
if (k->flags & F_RIPD_INSERTED) |
422 |
|
|
printf("R"); |
423 |
|
|
else if (k->flags & F_CONNECTED) |
424 |
|
|
printf("C"); |
425 |
|
|
else if (k->flags & F_STATIC) |
426 |
|
|
printf("S"); |
427 |
|
|
else |
428 |
|
|
printf(" "); |
429 |
|
|
|
430 |
|
|
printf(" "); |
431 |
|
|
if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), |
432 |
|
|
mask2prefixlen(k->netmask.s_addr)) == -1) |
433 |
|
|
err(1, NULL); |
434 |
|
|
printf("%-20s ", p); |
435 |
|
|
free(p); |
436 |
|
|
|
437 |
|
|
if (k->nexthop.s_addr) |
438 |
|
|
printf("%s", inet_ntoa(k->nexthop)); |
439 |
|
|
else if (k->flags & F_CONNECTED) |
440 |
|
|
printf("link#%u", k->ifindex); |
441 |
|
|
printf("\n"); |
442 |
|
|
|
443 |
|
|
break; |
444 |
|
|
case IMSG_CTL_END: |
445 |
|
|
printf("\n"); |
446 |
|
|
return (1); |
447 |
|
|
default: |
448 |
|
|
break; |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
return (0); |
452 |
|
|
} |
453 |
|
|
|
454 |
|
|
void |
455 |
|
|
show_interface_head(void) |
456 |
|
|
{ |
457 |
|
|
printf("%-15s%-15s%s\n", "Interface", "Flags", |
458 |
|
|
"Link state"); |
459 |
|
|
} |
460 |
|
|
|
461 |
|
|
int |
462 |
|
|
show_fib_interface_msg(struct imsg *imsg) |
463 |
|
|
{ |
464 |
|
|
struct kif *k; |
465 |
|
|
uint64_t ifms_type; |
466 |
|
|
|
467 |
|
|
switch (imsg->hdr.type) { |
468 |
|
|
case IMSG_CTL_IFINFO: |
469 |
|
|
k = imsg->data; |
470 |
|
|
printf("%-15s", k->ifname); |
471 |
|
|
printf("%-15s", k->flags & IFF_UP ? "UP" : ""); |
472 |
|
|
ifms_type = get_ifms_type(k->if_type); |
473 |
|
|
if (ifms_type) |
474 |
|
|
printf("%s, ", get_media_descr(ifms_type)); |
475 |
|
|
|
476 |
|
|
printf("%s", get_linkstate(k->if_type, k->link_state)); |
477 |
|
|
|
478 |
|
|
if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { |
479 |
|
|
printf(", "); |
480 |
|
|
print_baudrate(k->baudrate); |
481 |
|
|
} |
482 |
|
|
printf("\n"); |
483 |
|
|
break; |
484 |
|
|
case IMSG_CTL_END: |
485 |
|
|
printf("\n"); |
486 |
|
|
return (1); |
487 |
|
|
default: |
488 |
|
|
break; |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
return (0); |
492 |
|
|
} |
493 |
|
|
|
494 |
|
|
const struct if_status_description |
495 |
|
|
if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; |
496 |
|
|
const struct ifmedia_description |
497 |
|
|
ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; |
498 |
|
|
|
499 |
|
|
const char * |
500 |
|
|
get_media_descr(uint64_t media_type) |
501 |
|
|
{ |
502 |
|
|
const struct ifmedia_description *p; |
503 |
|
|
|
504 |
|
|
for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) |
505 |
|
|
if (media_type == p->ifmt_word) |
506 |
|
|
return (p->ifmt_string); |
507 |
|
|
|
508 |
|
|
return ("unknown"); |
509 |
|
|
} |
510 |
|
|
|
511 |
|
|
const char * |
512 |
|
|
get_linkstate(uint8_t if_type, int link_state) |
513 |
|
|
{ |
514 |
|
|
const struct if_status_description *p; |
515 |
|
|
static char buf[8]; |
516 |
|
|
|
517 |
|
|
for (p = if_status_descriptions; p->ifs_string != NULL; p++) { |
518 |
|
|
if (LINK_STATE_DESC_MATCH(p, if_type, link_state)) |
519 |
|
|
return (p->ifs_string); |
520 |
|
|
} |
521 |
|
|
snprintf(buf, sizeof(buf), "[#%d]", link_state); |
522 |
|
|
return (buf); |
523 |
|
|
} |
524 |
|
|
|
525 |
|
|
void |
526 |
|
|
print_baudrate(uint64_t baudrate) |
527 |
|
|
{ |
528 |
|
|
if (baudrate > IF_Gbps(1)) |
529 |
|
|
printf("%llu GBit/s", baudrate / IF_Gbps(1)); |
530 |
|
|
else if (baudrate > IF_Mbps(1)) |
531 |
|
|
printf("%llu MBit/s", baudrate / IF_Mbps(1)); |
532 |
|
|
else if (baudrate > IF_Kbps(1)) |
533 |
|
|
printf("%llu KBit/s", baudrate / IF_Kbps(1)); |
534 |
|
|
else |
535 |
|
|
printf("%llu Bit/s", baudrate); |
536 |
|
|
} |