Bug Summary

File:src/sbin/route/route.c
Warning:line 489, column 12
Although the value stored to 'key' is used in the enclosing expression, the value is never actually read from 'key'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name route.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/route/obj -resource-dir /usr/local/lib/clang/13.0.0 -D BFD -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/route/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/route/route.c
1/* $OpenBSD: route.c,v 1.260 2021/11/10 20:24:22 bket Exp $ */
2/* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */
3
4/*
5 * Copyright (c) 1983, 1989, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/socket.h>
34#include <sys/sysctl.h>
35
36#include <net/if.h>
37#include <net/if_dl.h>
38#include <net/if_media.h>
39#include <net/if_types.h>
40#include <net/route.h>
41#include <netinet/in.h>
42#include <netmpls/mpls.h>
43
44#ifdef BFD1
45#include <sys/time.h>
46#include <net/bfd.h>
47#endif
48
49#include <arpa/inet.h>
50#include <netdb.h>
51
52#include <ifaddrs.h>
53#include <errno(*__errno()).h>
54#include <fcntl.h>
55#include <unistd.h>
56#include <limits.h>
57#include <stdio.h>
58#include <ctype.h>
59#include <stddef.h>
60#include <stdlib.h>
61#include <string.h>
62#include <time.h>
63#include <paths.h>
64#include <err.h>
65
66#include "keywords.h"
67#include "show.h"
68
69const struct if_status_description
70 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS{ { 0x06, 2, "no carrier" }, { 0x47, 2, "no network" }, { 0x17
, 2, "no carrier" }, { 0xf7, 2, "backup" }, { 0xf7, 4, "master"
}, { 0xf7, 5, "master" }, { 0xf7, 6, "master" }, { 0, 4, "active"
}, { 0, 5, "active" }, { 0, 6, "active" }, { 0, 0, "unknown"
}, { 0, 1, "invalid" }, { 0, 2, "down" }, { 0, 3, "keepalive down"
}, { 0, 0, ((void*)0) } }
;
71
72union sockunion so_dst, so_gate, so_mask, so_ifa, so_ifp, so_src, so_label,
73 so_source;
74
75typedef union sockunion *sup;
76pid_t pid;
77int rtm_addrs, s;
78int forcehost, forcenet, Fflag, nflag, qflag, tflag, Tflag;
79int iflag, verbose, aflen = sizeof(struct sockaddr_in);
80int locking, lockrest, debugonly;
81u_long mpls_flags = MPLS_OP_LOCAL0x0;
82u_long rtm_inits;
83uid_t uid;
84u_int tableid;
85
86struct rt_metrics rt_metrics;
87
88int flushroutes(int, char **);
89int newroute(int, char **);
90int setsource(int, char **);
91int pushsrc(int, char *, int);
92int show(int, char *[]);
93int keycmp(const void *, const void *);
94int keyword(char *);
95void monitor(int, char *[]);
96int nameserver(int, char **);
97int prefixlen(int, char *);
98void sockaddr(char *, struct sockaddr *);
99void sodump(sup, char *);
100char *priorityname(uint8_t);
101uint8_t getpriority(char *);
102void print_getmsg(struct rt_msghdr *, int);
103#ifdef BFD1
104const char *bfd_state(unsigned int);
105const char *bfd_diag(unsigned int);
106const char *bfd_calc_uptime(time_t);
107void print_bfdmsg(struct rt_msghdr *);
108void print_sabfd(struct sockaddr_bfd *, int);
109#endif
110const char *get_linkstate(int, int);
111void print_rtmsg(struct rt_msghdr *, int);
112void pmsg_common(struct rt_msghdr *);
113void pmsg_addrs(char *, int);
114void bprintf(FILE *, int, char *);
115int getaddr(int, int, char *, struct hostent **);
116void getmplslabel(char *, int);
117int rtmsg(int, int, int, uint8_t);
118__dead__attribute__((__noreturn__)) void usage(char *);
119void set_metric(char *, int);
120void inet_makenetandmask(u_int32_t, struct sockaddr_in *, int);
121void getlabel(char *);
122int gettable(const char *);
123int rdomain(int, char **);
124void print_rtdns(struct sockaddr_rtdns *);
125void print_rtstatic(struct sockaddr_rtstatic *);
126void print_rtsearch(struct sockaddr_rtsearch *);
127void print_80211info(struct if_ieee80211_msghdr *);
128
129__dead__attribute__((__noreturn__)) void
130usage(char *cp)
131{
132 extern char *__progname;
133
134 if (cp)
135 warnx("botched keyword: %s", cp);
136 fprintf(stderr(&__sF[2]),
137#ifndef SMALL
138 "usage: %s [-dnqtv] [-T rtable] command [[modifiers] args]\n",
139#else
140 "usage: %s [-dnqtv] command [[modifiers] args]\n",
141#endif
142 __progname);
143 exit(1);
144}
145
146#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
147 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
148#define ADVANCE(x, n)(x += (((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1)
| (sizeof(long) - 1))) : sizeof(long)))
(x += ROUNDUP((n)->sa_len)(((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
)
149
150int
151main(int argc, char **argv)
152{
153 unsigned int filter = 0;
154 int ch;
155 int rval = 0;
156 int kw;
157 int af = AF_UNSPEC0;
158#ifndef SMALL
159 int Terr = 0;
160 u_int rtable_any = RTABLE_ANY0xffffffff;
161#endif
162
163 if (argc < 2)
164 usage(NULL((void*)0));
165
166#ifndef SMALL
167 tableid = getrtable();
168#endif
169 while ((ch = getopt(argc, argv, "dnqtT:v")) != -1)
170 switch (ch) {
171 case 'n':
172 nflag = 1;
173 break;
174 case 'q':
175 qflag = 1;
176 break;
177 case 'v':
178 verbose = 1;
179 break;
180 case 't':
181 tflag = 1;
182 break;
183#ifndef SMALL
184 case 'T':
185 Terr = gettable(optarg);
186 Tflag = 1;
187 break;
188#endif
189 case 'd':
190 debugonly = 1;
191 break;
192 default:
193 usage(NULL((void*)0));
194 /* NOTREACHED */
195 }
196 argc -= optind;
197 argv += optind;
198
199 pid = getpid();
200 uid = geteuid();
201 if (*argv == NULL((void*)0))
202 usage(NULL((void*)0));
203
204 kw = keyword(*argv);
205#ifndef SMALL
206 if (Tflag && Terr != 0 && kw != K_ADD) {
207 errno(*__errno()) = Terr;
208 err(1, "routing table %u", tableid);
209 }
210 if (kw == K_EXEC)
211 exit(rdomain(argc - 1, argv + 1));
212#endif
213
214 if (kw == K_MONITOR) {
215 while (--argc > 0) {
216 if (**(++argv)== '-')
217 switch (keyword(*argv + 1)) {
218 case K_INET:
219 af = AF_INET2;
220 break;
221 case K_INET6:
222 af = AF_INET624;
223 break;
224 case K_IFACE:
225 case K_INTERFACE:
226 filter = ROUTE_FILTER(RTM_IFINFO)(1 << (0xe)) |
227 ROUTE_FILTER(RTM_IFANNOUNCE)(1 << (0xf)) |
228 ROUTE_FILTER(RTM_80211INFO)(1 << (0x15));
229 break;
230 default:
231 usage(*argv);
232 /* NOTREACHED */
233 }
234 else
235 usage(*argv);
236 }
237 }
238
239 if (tflag)
240 s = open(_PATH_DEVNULL"/dev/null", O_WRONLY0x0001);
241 else
242 s = socket(AF_ROUTE17, SOCK_RAW3, af);
243 if (s == -1)
244 err(1, "socket");
245
246 if (filter != 0) {
247 if (setsockopt(s, AF_ROUTE17, ROUTE_MSGFILTER1, &filter,
248 sizeof(filter)) == -1)
249 err(1, "setsockopt(ROUTE_MSGFILTER)");
250 }
251
252#ifndef SMALL
253 if (!tflag) {
254 /* force socket onto table user requested */
255 if (Tflag == 1 && Terr == 0) {
256 if (setsockopt(s, AF_ROUTE17, ROUTE_TABLEFILTER2,
257 &tableid, sizeof(tableid)) == -1)
258 err(1, "setsockopt(ROUTE_TABLEFILTER)");
259 } else {
260 if (setsockopt(s, AF_ROUTE17, ROUTE_TABLEFILTER2,
261 &rtable_any, sizeof(tableid)) == -1)
262 err(1, "setsockopt(ROUTE_TABLEFILTER)");
263 }
264 }
265#endif
266
267 if (pledge("stdio dns route", NULL((void*)0)) == -1)
268 err(1, "pledge");
269
270 switch (kw) {
271 case K_SHOW:
272 uid = 0;
273 exit(show(argc, argv));
274 break;
275 case K_FLUSH:
276 exit(flushroutes(argc, argv));
277 break;
278 case K_SOURCEADDR:
279 nflag = 1;
280 exit(setsource(argc, argv));
281 break;
282 }
283
284 if (pledge("stdio dns", NULL((void*)0)) == -1)
285 err(1, "pledge");
286
287 switch (kw) {
288 case K_GET:
289 uid = 0;
290 /* FALLTHROUGH */
291 case K_CHANGE:
292 case K_ADD:
293 case K_DEL:
294 case K_DELETE:
295 rval = newroute(argc, argv);
296 break;
297 case K_MONITOR:
298 monitor(argc, argv);
299 break;
300 case K_NAMESERVER:
301 rval = nameserver(argc, argv);
302 break;
303 default:
304 usage(*argv);
305 /* NOTREACHED */
306 }
307 exit(rval);
308}
309
310/*
311 * Purge all entries in the routing tables not
312 * associated with network interfaces.
313 */
314int
315flushroutes(int argc, char **argv)
316{
317 size_t needed;
318 int mib[7], mcnt, rlen, seqno, af = AF_UNSPEC0;
319 char *buf = NULL((void*)0), *next, *lim = NULL((void*)0);
320 struct rt_msghdr *rtm;
321 struct sockaddr *sa;
322 uint8_t prio = 0;
323 unsigned int ifindex = 0;
324
325 if (uid)
326 errx(1, "must be root to alter routing table");
327 shutdown(s, SHUT_RD0); /* Don't want to read back our messages */
328 while (--argc > 0) {
329 if (**(++argv) == '-')
330 switch (keyword(*argv + 1)) {
331 case K_INET:
332 af = AF_INET2;
333 break;
334 case K_INET6:
335 af = AF_INET624;
336 break;
337 case K_LINK:
338 af = AF_LINK18;
339 break;
340 case K_MPLS:
341 af = AF_MPLS33;
342 break;
343 case K_IFACE:
344 case K_INTERFACE:
345 if (!--argc)
346 usage(1+*argv);
347 ifindex = if_nametoindex(*++argv);
348 if (ifindex == 0)
349 errx(1, "no such interface %s", *argv);
350 break;
351 case K_PRIORITY:
352 if (!--argc)
353 usage(1+*argv);
354 prio = getpriority(*++argv);
355 break;
356 default:
357 usage(*argv);
358 /* NOTREACHED */
359 }
360 else
361 usage(*argv);
362 }
363 mib[0] = CTL_NET4;
364 mib[1] = PF_ROUTE17;
365 mib[2] = 0; /* protocol */
366 mib[3] = af;
367 mib[4] = NET_RT_DUMP1;
368 mib[5] = prio;
369 mib[6] = tableid;
370 mcnt = 7;
371
372 needed = get_sysctl(mib, mcnt, &buf);
373 lim = buf + needed;
374
375 if (pledge("stdio dns", NULL((void*)0)) == -1)
376 err(1, "pledge");
377
378 if (verbose) {
379 printf("Examining routing table from sysctl\n");
380 if (af)
381 printf("(address family %s)\n", (*argv + 1));
382 }
383 if (buf == NULL((void*)0))
384 return (1);
385
386 seqno = 0;
387 for (next = buf; next < lim; next += rtm->rtm_msglen) {
388 rtm = (struct rt_msghdr *)next;
389 if (rtm->rtm_version != RTM_VERSION5)
390 continue;
391 if (verbose)
392 print_rtmsg(rtm, rtm->rtm_msglen);
393 if ((rtm->rtm_flags & (RTF_GATEWAY0x2|RTF_STATIC0x800|RTF_LLINFO0x400)) == 0)
394 continue;
395 if ((rtm->rtm_flags & (RTF_LOCAL0x200000|RTF_BROADCAST0x400000)) != 0)
396 continue;
397 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
398 if (ifindex && rtm->rtm_index != ifindex)
399 continue;
400 if (sa->sa_family == AF_KEY30)
401 continue; /* Don't flush SPD */
402 if (debugonly)
403 continue;
404 rtm->rtm_type = RTM_DELETE0x2;
405 rtm->rtm_seq = seqno;
406 rtm->rtm_tableid = tableid;
407 rlen = write(s, next, rtm->rtm_msglen);
408 if (rlen < (int)rtm->rtm_msglen) {
409 warn("write to routing socket");
410 printf("got only %d for rlen\n", rlen);
411 break;
412 }
413 seqno++;
414 if (qflag)
415 continue;
416 if (verbose)
417 print_rtmsg(rtm, rlen);
418 else {
419 struct sockaddr *mask, *rti_info[RTAX_MAX15];
420
421 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
422
423 get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
424
425 sa = rti_info[RTAX_DST0];
426 mask = rti_info[RTAX_NETMASK2];
427
428 p_sockaddr(sa, mask, rtm->rtm_flags, 20);
429 p_sockaddr(rti_info[RTAX_GATEWAY1], NULL((void*)0), RTF_HOST0x4, 20);
430 printf("done\n");
431 }
432 }
433 free(buf);
434 return (0);
435}
436
437void
438set_metric(char *value, int key)
439{
440 long long relative_expire;
441 const char *errstr;
442 int flag = 0;
443
444 switch (key) {
445 case K_MTU:
446 rt_metrics.rmx_mtu = strtonum(value, 0, UINT_MAX(2147483647 *2U +1U), &errstr);
447 if (errstr)
448 errx(1, "set_metric mtu: %s is %s", value, errstr);
449 flag = RTV_MTU0x1;
450 break;
451 case K_EXPIRE:
452 relative_expire = strtonum(value, 0, INT_MAX2147483647, &errstr);
453 if (errstr)
454 errx(1, "set_metric expire: %s is %s", value, errstr);
455 rt_metrics.rmx_expire = relative_expire ?
456 relative_expire + time(NULL((void*)0)) : 0;
457 flag = RTV_EXPIRE0x4;
458 break;
459 case K_HOPCOUNT:
460 case K_RECVPIPE:
461 case K_SENDPIPE:
462 case K_SSTHRESH:
463 case K_RTT:
464 case K_RTTVAR:
465 /* no longer used, only for compatibility */
466 return;
467 default:
468 errx(1, "king bula sez: set_metric with invalid key");
469 }
470 rtm_inits |= flag;
471 if (lockrest || locking)
472 rt_metrics.rmx_locks |= flag;
473 if (locking)
474 locking = 0;
475}
476
477
478int
479setsource(int argc, char **argv)
480{
481 struct ifaddrs *ifap, *ifa = NULL((void*)0);
482 char *cmd;
483 int af = AF_UNSPEC0, ret = 0, key;
484 unsigned int ifindex = 0;
485
486 cmd = argv[0];
487 while (--argc > 0) {
488 if (**(++argv)== '-') {
489 switch (key = keyword(1 + *argv)) {
Although the value stored to 'key' is used in the enclosing expression, the value is never actually read from 'key'
490 case K_INET:
491 af = AF_INET2;
492 aflen = sizeof(struct sockaddr_in);
493 break;
494 case K_INET6:
495 af = AF_INET624;
496 aflen = sizeof(struct sockaddr_in6);
497 break;
498 case K_IFP:
499 if (!--argc)
500 usage(1+*argv);
501 ifindex = if_nametoindex(*++argv);
502 if (ifindex == 0)
503 errx(1, "no such interface %s", *argv);
504 break;
505 }
506 } else
507 break;
508 }
509
510 if (argc <= 0 && ifindex == 0)
511 printsource(af, tableid);
512 if (argc > 1 && ifindex == 0)
513 usage(NULL((void*)0));
514
515 if (uid)
516 errx(1, "must be root to alter source address");
517
518 if (ifindex) {
519 if (getifaddrs(&ifap) == -1)
520 err(1, "getifaddrs");
521 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
522 if (if_nametoindex(ifa->ifa_name) != ifindex)
523 continue;
524 if (ifa->ifa_addr == NULL((void*)0) ||
525 !(ifa->ifa_addr->sa_family == AF_INET2 ||
526 ifa->ifa_addr->sa_family == AF_INET624))
527 continue;
528 if ((af != AF_UNSPEC0) &&
529 (ifa->ifa_addr->sa_family != af))
530 continue;
531 if (ifa->ifa_addr->sa_family == AF_INET624) {
532 struct sockaddr_in6 *sin6 =
533 (struct sockaddr_in6 *)ifa->ifa_addr;
534 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
||
535 IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff
)
)
536 continue;
537 }
538 if (pushsrc(*cmd, routename(ifa->ifa_addr),
539 ifa->ifa_addr->sa_family))
540 break;
541 }
542 freeifaddrs(ifap);
543 } else {
544 ret = pushsrc(*cmd, *argv, af);
545 }
546
547 return (ret != 0);
548}
549
550int
551pushsrc(int cmd, char *src, int af)
552{
553 int ret = 0;
554
555 getaddr(RTA_IFA0x20, af, src, NULL((void*)0));
556
557 errno(*__errno()) = 0;
558 ret = rtmsg(cmd, 0, 0, 0);
559 if (!qflag && ret != 0)
560 printf("sourceaddr %s: %s\n", src, strerror(errno(*__errno())));
561
562 return (ret);
563}
564int
565newroute(int argc, char **argv)
566{
567 char *cmd, *dest = "", *gateway = "", *error;
568 int ishost = 0, ret = 0, attempts, oerrno, flags = RTF_STATIC0x800;
569 int fmask = 0, af = AF_UNSPEC0;
570 int key;
571 uint8_t prio = 0;
572 struct hostent *hp = NULL((void*)0);
573 int sawdest = 0;
574
575 if (uid)
576 errx(1, "must be root to alter routing table");
577 cmd = argv[0];
578 if (*cmd != 'g')
579 shutdown(s, SHUT_RD0); /* Don't want to read back our messages */
580 while (--argc > 0) {
581 if (**(++argv)== '-') {
582 switch (key = keyword(1 + *argv)) {
583 case K_LINK:
584 af = AF_LINK18;
585 aflen = sizeof(struct sockaddr_dl);
586 break;
587 case K_INET:
588 af = AF_INET2;
589 aflen = sizeof(struct sockaddr_in);
590 break;
591 case K_INET6:
592 af = AF_INET624;
593 aflen = sizeof(struct sockaddr_in6);
594 break;
595 case K_SA:
596 af = PF_ROUTE17;
597 aflen = sizeof(struct sockaddr_storage) - 1;
598 break;
599 case K_MPLS:
600 af = AF_MPLS33;
601 aflen = sizeof(struct sockaddr_mpls);
602 fmask |= RTF_MPLS0x100000;
603 break;
604 case K_MPLSLABEL:
605 if (!--argc)
606 usage(1+*argv);
607 if (af != AF_INET2 && af != AF_INET624)
608 errx(1, "-mplslabel requires "
609 "-inet or -inet6");
610 getmplslabel(*++argv, 0);
611 mpls_flags = MPLS_OP_PUSH0x2;
612 flags |= RTF_MPLS0x100000;
613 break;
614 case K_IN:
615 if (!--argc)
616 usage(1+*argv);
617 if (af != AF_MPLS33)
618 errx(1, "-in requires -mpls");
619 getmplslabel(*++argv, 1);
620 break;
621 case K_OUT:
622 if (!--argc)
623 usage(1+*argv);
624 if (af != AF_MPLS33)
625 errx(1, "-out requires -mpls");
626 if (mpls_flags == MPLS_OP_LOCAL0x0)
627 errx(1, "-out requires -push, -pop, "
628 "-swap");
629 getmplslabel(*++argv, 0);
630 flags |= RTF_MPLS0x100000;
631 break;
632 case K_POP:
633 if (af != AF_MPLS33)
634 errx(1, "-pop requires -mpls");
635 mpls_flags = MPLS_OP_POP0x1;
636 break;
637 case K_PUSH:
638 if (af != AF_MPLS33)
639 errx(1, "-push requires -mpls");
640 mpls_flags = MPLS_OP_PUSH0x2;
641 break;
642 case K_SWAP:
643 if (af != AF_MPLS33)
644 errx(1, "-swap requires -mpls");
645 mpls_flags = MPLS_OP_SWAP0x4;
646 break;
647 case K_IFACE:
648 case K_INTERFACE:
649 iflag++;
650 break;
651 case K_NOSTATIC:
652 flags &= ~RTF_STATIC0x800;
653 break;
654 case K_LLINFO:
655 flags |= RTF_LLINFO0x400;
656 break;
657 case K_LOCK:
658 locking = 1;
659 break;
660 case K_LOCKREST:
661 lockrest = 1;
662 break;
663 case K_HOST:
664 forcehost++;
665 break;
666 case K_REJECT:
667 flags |= RTF_REJECT0x8;
668 break;
669 case K_BLACKHOLE:
670 flags |= RTF_BLACKHOLE0x1000;
671 break;
672 case K_PROTO1:
673 flags |= RTF_PROTO10x8000;
674 break;
675 case K_PROTO2:
676 flags |= RTF_PROTO20x4000;
677 break;
678 case K_CLONING:
679 flags |= RTF_CLONING0x100;
680 break;
681 case K_STATIC:
682 flags |= RTF_STATIC0x800;
683 break;
684 case K_IFA:
685 if (!--argc)
686 usage(1+*argv);
687 getaddr(RTA_IFA0x20, af, *++argv, NULL((void*)0));
688 break;
689 case K_IFP:
690 if (!--argc)
691 usage(1+*argv);
692 getaddr(RTA_IFP0x10, AF_LINK18, *++argv, NULL((void*)0));
693 break;
694 case K_GATEWAY:
695 if (!--argc)
696 usage(1+*argv);
697 getaddr(RTA_GATEWAY0x2, af, *++argv, NULL((void*)0));
698 gateway = *argv;
699 break;
700 case K_DST:
701 if (!--argc)
702 usage(1+*argv);
703 ishost = getaddr(RTA_DST0x1, af, *++argv, &hp);
704 dest = *argv;
705 sawdest = 1;
706 break;
707 case K_LABEL:
708 if (!--argc)
709 usage(1+*argv);
710 getlabel(*++argv);
711 break;
712 case K_NETMASK:
713 if (!sawdest)
714 errx(1, "-netmask must follow "
715 "destination parameter");
716 if (!--argc)
717 usage(1+*argv);
718 getaddr(RTA_NETMASK0x4, af, *++argv, NULL((void*)0));
719 /* FALLTHROUGH */
720 case K_NET:
721 forcenet++;
722 break;
723 case K_PREFIXLEN:
724 if (!sawdest)
725 errx(1, "-prefixlen must follow "
726 "destination parameter");
727 if (!--argc)
728 usage(1+*argv);
729 ishost = prefixlen(af, *++argv);
730 break;
731 case K_MPATH:
732 flags |= RTF_MPATH0x40000;
733 break;
734 case K_MTU:
735 case K_HOPCOUNT:
736 case K_EXPIRE:
737 case K_RECVPIPE:
738 case K_SENDPIPE:
739 case K_SSTHRESH:
740 case K_RTT:
741 case K_RTTVAR:
742 if (!--argc)
743 usage(1+*argv);
744 set_metric(*++argv, key);
745 break;
746 case K_PRIORITY:
747 if (!--argc)
748 usage(1+*argv);
749 prio = getpriority(*++argv);
750 break;
751 case K_BFD:
752 flags |= RTF_BFD0x1000000;
753 fmask |= RTF_BFD0x1000000;
754 break;
755 case K_NOBFD:
756 flags &= ~RTF_BFD0x1000000;
757 fmask |= RTF_BFD0x1000000;
758 break;
759 default:
760 usage(1+*argv);
761 /* NOTREACHED */
762 }
763 } else {
764 if ((rtm_addrs & RTA_DST0x1) == 0) {
765 dest = *argv;
766 sawdest = 1;
767 ishost = getaddr(RTA_DST0x1, af, *argv, &hp);
768 } else if ((rtm_addrs & RTA_GATEWAY0x2) == 0) {
769 gateway = *argv;
770 getaddr(RTA_GATEWAY0x2, af, *argv, &hp);
771 } else
772 usage(NULL((void*)0));
773 }
774 }
775 if (forcehost)
776 ishost = 1;
777 if (forcenet)
778 ishost = 0;
779 if (forcenet && !(rtm_addrs & RTA_NETMASK0x4))
780 errx(1, "netmask missing");
781 flags |= RTF_UP0x1;
782 if (ishost)
783 flags |= RTF_HOST0x4;
784 if (iflag == 0)
785 flags |= RTF_GATEWAY0x2;
786 for (attempts = 1; ; attempts++) {
787 errno(*__errno()) = 0;
788 if ((ret = rtmsg(*cmd, flags, fmask, prio)) == 0)
789 break;
790 if (errno(*__errno()) != ENETUNREACH51 && errno(*__errno()) != ESRCH3)
791 break;
792 if (af == AF_INET2 && *gateway && hp && hp->h_addr_list[1]) {
793 hp->h_addr_list++;
794 memcpy(&so_gate.sin.sin_addr, hp->h_addr_list[0],
795 hp->h_length);
796 } else
797 break;
798 }
799 oerrno = errno(*__errno());
800 if (!qflag && (*cmd != 'g' || ret != 0)) {
801 printf("%s %s %s", cmd, ishost ? "host" : "net", dest);
802 if (*gateway) {
803 printf(": gateway %s", gateway);
804 if (attempts > 1 && ret == 0 && af == AF_INET2)
805 printf(" (%s)", inet_ntoa(so_gate.sin.sin_addr));
806 }
807 if (ret == 0)
808 printf("\n");
809 if (ret != 0) {
810 switch (oerrno) {
811 case ESRCH3:
812 error = "not in table";
813 break;
814 case EBUSY16:
815 error = "entry in use";
816 break;
817 case ENOBUFS55:
818 error = "routing table overflow";
819 break;
820 default:
821 error = strerror(oerrno);
822 break;
823 }
824 printf(": %s\n", error);
825 }
826 }
827 return (ret != 0);
828}
829
830int
831show(int argc, char *argv[])
832{
833 int af = AF_UNSPEC0;
834 char prio = 0;
835
836 while (--argc > 0) {
837 if (**(++argv)== '-')
838 switch (keyword(*argv + 1)) {
839 case K_INET:
840 af = AF_INET2;
841 break;
842 case K_INET6:
843 af = AF_INET624;
844 break;
845 case K_LINK:
846 af = AF_LINK18;
847 break;
848 case K_MPLS:
849 af = AF_MPLS33;
850 break;
851 case K_GATEWAY:
852 Fflag = 1;
853 break;
854 case K_LABEL:
855 if (!--argc)
856 usage(1+*argv);
857 getlabel(*++argv);
858 break;
859 case K_PRIORITY:
860 if (!--argc)
861 usage(1+*argv);
862 prio = getpriority(*++argv);
863 break;
864 default:
865 usage(*argv);
866 /* NOTREACHED */
867 }
868 else
869 usage(*argv);
870 }
871
872 p_rttables(af, tableid, prio);
873 return (0);
874}
875
876void
877inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits)
878{
879 u_int32_t mask;
880
881 rtm_addrs |= RTA_NETMASK0x4;
882 if (bits == 0 && net == 0)
883 mask = 0;
884 else {
885 if (bits == 0)
886 bits = 32;
887 mask = 0xffffffff << (32 - bits);
888 net &= mask;
889 }
890 sin->sin_addr.s_addr = htonl(net)(__uint32_t)(__builtin_constant_p(net) ? (__uint32_t)(((__uint32_t
)(net) & 0xff) << 24 | ((__uint32_t)(net) & 0xff00
) << 8 | ((__uint32_t)(net) & 0xff0000) >> 8 |
((__uint32_t)(net) & 0xff000000) >> 24) : __swap32md
(net))
;
891 sin = &so_mask.sin;
892 sin->sin_addr.s_addr = htonl(mask)(__uint32_t)(__builtin_constant_p(mask) ? (__uint32_t)(((__uint32_t
)(mask) & 0xff) << 24 | ((__uint32_t)(mask) & 0xff00
) << 8 | ((__uint32_t)(mask) & 0xff0000) >> 8
| ((__uint32_t)(mask) & 0xff000000) >> 24) : __swap32md
(mask))
;
893 sin->sin_family = AF_INET2;
894 sin->sin_len = sizeof(struct sockaddr_in);
895}
896
897/*
898 * Interpret an argument as a network address of some kind,
899 * returning 1 if a host address, 0 if a network address.
900 */
901int
902getaddr(int which, int af, char *s, struct hostent **hpp)
903{
904 sup su = NULL((void*)0);
905 struct hostent *hp;
906 int aflength, afamily, bits;
907
908 if (af == AF_UNSPEC0) {
909 if (strchr(s, ':') != NULL((void*)0)) {
910 af = AF_INET624;
911 aflen = sizeof(struct sockaddr_in6);
912 } else {
913 af = AF_INET2;
914 aflen = sizeof(struct sockaddr_in);
915 }
916 }
917 /* local copy of len and af so we can change it */
918 aflength = aflen;
919 afamily = af;
920
921 rtm_addrs |= which;
922 switch (which) {
923 case RTA_DST0x1:
924 su = &so_dst;
925 break;
926 case RTA_GATEWAY0x2:
927 su = &so_gate;
928 break;
929 case RTA_NETMASK0x4:
930 su = &so_mask;
931 break;
932 case RTA_IFP0x10:
933 su = &so_ifp;
934 aflength = sizeof(struct sockaddr_dl);
935 afamily = AF_LINK18;
936 break;
937 case RTA_IFA0x20:
938 su = &so_ifa;
939 break;
940 default:
941 errx(1, "internal error");
942 /* NOTREACHED */
943 }
944 memset(su, 0, sizeof(union sockunion));
945 su->sa.sa_len = aflength;
946 su->sa.sa_family = afamily;
947
948 if (strcmp(s, "default") == 0) {
949 switch (which) {
950 case RTA_DST0x1:
951 forcenet++;
952 getaddr(RTA_NETMASK0x4, af, s, NULL((void*)0));
953 break;
954 case RTA_NETMASK0x4:
955 su->sa.sa_len = 0;
956 }
957 return (0);
958 }
959
960 switch (afamily) {
961 case AF_INET624:
962 {
963 struct addrinfo hints, *res;
964 char buf[
965 sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")
966 ];
967 char *sep;
968 int error;
969
970 if (strlcpy(buf, s, sizeof buf) >= sizeof buf) {
971 errx(1, "%s: bad value", s);
972 }
973
974 sep = strchr(buf, '/');
975 if (sep != NULL((void*)0))
976 *sep++ = '\0';
977 memset(&hints, 0, sizeof(hints));
978 hints.ai_family = afamily; /*AF_INET6*/
979 hints.ai_flags = AI_NUMERICHOST4;
980 hints.ai_socktype = SOCK_DGRAM2; /*dummy*/
981 error = getaddrinfo(buf, "0", &hints, &res);
982 if (error) {
983 hints.ai_flags = 0;
984 error = getaddrinfo(buf, "0", &hints, &res);
985 if (error)
986 errx(1, "%s: %s", s, gai_strerror(error));
987 }
988 if (res->ai_next)
989 errx(1, "%s: resolved to multiple values", s);
990 memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
991 freeaddrinfo(res);
992#ifdef __KAME__
993 if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr)(((&su->sin6.sin6_addr)->__u6_addr.__u6_addr8[0] ==
0xfe) && (((&su->sin6.sin6_addr)->__u6_addr
.__u6_addr8[1] & 0xc0) == 0x80))
||
994 IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)(((&su->sin6.sin6_addr)->__u6_addr.__u6_addr8[0] ==
0xff) && (((&su->sin6.sin6_addr)->__u6_addr
.__u6_addr8[1] & 0x0f) == 0x02))
||
995 IN6_IS_ADDR_MC_INTFACELOCAL(&su->sin6.sin6_addr)(((&su->sin6.sin6_addr)->__u6_addr.__u6_addr8[0] ==
0xff) && (((&su->sin6.sin6_addr)->__u6_addr
.__u6_addr8[1] & 0x0f) == 0x01))
) &&
996 su->sin6.sin6_scope_id) {
997 *(u_int16_t *)&su->sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[2] =
998 htons(su->sin6.sin6_scope_id)(__uint16_t)(__builtin_constant_p(su->sin6.sin6_scope_id) ?
(__uint16_t)(((__uint16_t)(su->sin6.sin6_scope_id) & 0xffU
) << 8 | ((__uint16_t)(su->sin6.sin6_scope_id) &
0xff00U) >> 8) : __swap16md(su->sin6.sin6_scope_id)
)
;
999 su->sin6.sin6_scope_id = 0;
1000 }
1001#endif
1002 if (hints.ai_flags == AI_NUMERICHOST4) {
1003 if (which == RTA_DST0x1) {
1004 if (sep == NULL((void*)0) && su->sin6.sin6_scope_id == 0 &&
1005 IN6_IS_ADDR_UNSPECIFIED(&su->sin6.sin6_addr)((*(const u_int32_t *)(const void *)(&(&su->sin6.sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&su->sin6.sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&su->sin6.sin6_addr)->__u6_addr.__u6_addr8
[8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&su->sin6.sin6_addr)->__u6_addr.__u6_addr8[12]) ==
0))
)
1006 sep = "0";
1007 if (sep == NULL((void*)0) || prefixlen(AF_INET624, sep))
1008 return (1);
1009 }
1010 return (0);
1011 } else
1012 return (1);
1013 }
1014
1015 case AF_LINK18:
1016 su->sdl.sdl_index = if_nametoindex(s);
1017 memset(&su->sdl.sdl_data, 0, sizeof(su->sdl.sdl_data));
1018 return (1);
1019 case AF_MPLS33:
1020 errx(1, "mpls labels require -in or -out switch");
1021 case PF_ROUTE17:
1022 su->sa.sa_len = sizeof(struct sockaddr_storage) - 1;
1023 sockaddr(s, &su->sa);
1024 return (1);
1025
1026 case AF_INET2:
1027 if (hpp != NULL((void*)0))
1028 *hpp = NULL((void*)0);
1029 if (which == RTA_DST0x1 && !forcehost) {
1030 bits = inet_net_pton(AF_INET2, s, &su->sin.sin_addr,
1031 sizeof(su->sin.sin_addr));
1032 if (bits == 32)
1033 return (1);
1034 if (bits >= 0) {
1035 inet_makenetandmask(ntohl((__uint32_t)(__builtin_constant_p(su->sin.sin_addr.s_addr)
? (__uint32_t)(((__uint32_t)(su->sin.sin_addr.s_addr) &
0xff) << 24 | ((__uint32_t)(su->sin.sin_addr.s_addr
) & 0xff00) << 8 | ((__uint32_t)(su->sin.sin_addr
.s_addr) & 0xff0000) >> 8 | ((__uint32_t)(su->sin
.sin_addr.s_addr) & 0xff000000) >> 24) : __swap32md
(su->sin.sin_addr.s_addr))
1036 su->sin.sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(su->sin.sin_addr.s_addr)
? (__uint32_t)(((__uint32_t)(su->sin.sin_addr.s_addr) &
0xff) << 24 | ((__uint32_t)(su->sin.sin_addr.s_addr
) & 0xff00) << 8 | ((__uint32_t)(su->sin.sin_addr
.s_addr) & 0xff0000) >> 8 | ((__uint32_t)(su->sin
.sin_addr.s_addr) & 0xff000000) >> 24) : __swap32md
(su->sin.sin_addr.s_addr))
,
1037 &su->sin, bits);
1038 return (0);
1039 }
1040 } else if (which != RTA_DST0x1 || !forcenet)
1041 if (inet_pton(AF_INET2, s, &su->sin.sin_addr) == 1)
1042 return (1);
1043 hp = gethostbyname(s);
1044 if (hp == NULL((void*)0))
1045 errx(1, "%s: bad address", s);
1046 if (hpp != NULL((void*)0))
1047 *hpp = hp;
1048 su->sin.sin_addr = *(struct in_addr *)hp->h_addrh_addr_list[0];
1049 return (1);
1050
1051 default:
1052 errx(1, "%d: bad address family", afamily);
1053 /* NOTREACHED */
1054 }
1055}
1056
1057void
1058getmplslabel(char *s, int in)
1059{
1060 sup su = NULL((void*)0);
1061 const char *errstr;
1062 u_int32_t label;
1063
1064 label = strtonum(s, 0, MPLS_LABEL_MAX((1 << 20) - 1), &errstr);
1065 if (errstr)
1066 errx(1, "bad label: %s is %s", s, errstr);
1067 if (in) {
1068 rtm_addrs |= RTA_DST0x1;
1069 su = &so_dst;
1070 su->smpls.smpls_label = htonl(label << MPLS_LABEL_OFFSET)(__uint32_t)(__builtin_constant_p(label << 12) ? (__uint32_t
)(((__uint32_t)(label << 12) & 0xff) << 24 | (
(__uint32_t)(label << 12) & 0xff00) << 8 | ((
__uint32_t)(label << 12) & 0xff0000) >> 8 | (
(__uint32_t)(label << 12) & 0xff000000) >> 24
) : __swap32md(label << 12))
;
1071 } else {
1072 rtm_addrs |= RTA_SRC0x100;
1073 su = &so_src;
1074 su->smpls.smpls_label = htonl(label << MPLS_LABEL_OFFSET)(__uint32_t)(__builtin_constant_p(label << 12) ? (__uint32_t
)(((__uint32_t)(label << 12) & 0xff) << 24 | (
(__uint32_t)(label << 12) & 0xff00) << 8 | ((
__uint32_t)(label << 12) & 0xff0000) >> 8 | (
(__uint32_t)(label << 12) & 0xff000000) >> 24
) : __swap32md(label << 12))
;
1075 }
1076
1077 su->sa.sa_len = sizeof(struct sockaddr_mpls);
1078 su->sa.sa_family = AF_MPLS33;
1079}
1080
1081int
1082prefixlen(int af, char *s)
1083{
1084 const char *errstr;
1085 int len, q, r;
1086 int max;
1087
1088 switch (af) {
1089 case AF_INET2:
1090 max = sizeof(struct in_addr) * 8;
1091 break;
1092 case AF_INET624:
1093 max = sizeof(struct in6_addr) * 8;
1094 break;
1095 default:
1096 errx(1, "prefixlen is not supported with af %d", af);
1097 /* NOTREACHED */
1098 }
1099
1100 rtm_addrs |= RTA_NETMASK0x4;
1101 len = strtonum(s, 0, max, &errstr);
1102 if (errstr)
1103 errx(1, "prefixlen %s is %s", s, errstr);
1104
1105 q = len >> 3;
1106 r = len & 7;
1107 switch (af) {
1108 case AF_INET2:
1109 memset(&so_mask, 0, sizeof(so_mask));
1110 so_mask.sin.sin_family = AF_INET2;
1111 so_mask.sin.sin_len = sizeof(struct sockaddr_in);
1112 if (len != 0)
1113 so_mask.sin.sin_addr.s_addr = htonl(0xffffffff << (32 - len))(__uint32_t)(__builtin_constant_p(0xffffffff << (32 - len
)) ? (__uint32_t)(((__uint32_t)(0xffffffff << (32 - len
)) & 0xff) << 24 | ((__uint32_t)(0xffffffff <<
(32 - len)) & 0xff00) << 8 | ((__uint32_t)(0xffffffff
<< (32 - len)) & 0xff0000) >> 8 | ((__uint32_t
)(0xffffffff << (32 - len)) & 0xff000000) >> 24
) : __swap32md(0xffffffff << (32 - len)))
;
1114 break;
1115 case AF_INET624:
1116 so_mask.sin6.sin6_family = AF_INET624;
1117 so_mask.sin6.sin6_len = sizeof(struct sockaddr_in6);
1118 memset((void *)&so_mask.sin6.sin6_addr, 0,
1119 sizeof(so_mask.sin6.sin6_addr));
1120 if (q > 0)
1121 memset((void *)&so_mask.sin6.sin6_addr, 0xff, q);
1122 if (r > 0)
1123 *((u_char *)&so_mask.sin6.sin6_addr + q) =
1124 (0xff00 >> r) & 0xff;
1125 break;
1126 }
1127 return (len == max);
1128}
1129
1130void
1131monitor(int argc, char *argv[])
1132{
1133 int n;
1134 char msg[2048];
1135 time_t now;
1136
1137 verbose = 1;
1138 for (;;) {
1139 if ((n = read(s, msg, sizeof(msg))) == -1) {
1140 if (errno(*__errno()) == EINTR4)
1141 continue;
1142 err(1, "read");
1143 }
1144 now = time(NULL((void*)0));
1145 printf("got message of size %d on %s", n, ctime(&now));
1146 print_rtmsg((struct rt_msghdr *)msg, n);
1147 }
1148}
1149
1150
1151int
1152nameserver(int argc, char *argv[])
1153{
1154 struct rt_msghdr rtm;
1155 struct sockaddr_rtdns rtdns;
1156 struct iovec iov[3];
1157 struct addrinfo hints, *res;
1158 struct in_addr ns4[5];
1159 struct in6_addr ns6[5];
1160 size_t ns4_count = 0, ns6_count = 0;
1161 long pad = 0;
1162 unsigned int if_index;
1163 int error = 0, iovcnt = 0, padlen, i;
1164 char *if_name, buf[INET6_ADDRSTRLEN46];
1165
1166
1167 argc--;
1168 argv++;
1169 if (argc == 0)
1170 usage(NULL((void*)0));
1171
1172 if_name = *argv;
1173 argc--;
1174 argv++;
1175
1176 if ((if_index = if_nametoindex(if_name)) == 0)
1177 errx(1, "unknown interface: %s", if_name);
1178
1179 memset(&hints, 0, sizeof(hints));
1180 hints.ai_family = AF_UNSPEC0;
1181 hints.ai_socktype = SOCK_STREAM1;
1182 hints.ai_flags = AI_NUMERICHOST4 | AI_NUMERICSERV16;
1183
1184#ifndef nitems
1185#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
1186#endif
1187
1188 for (; argc > 0 && ns4_count + ns6_count < 5; argc--, argv++) {
1189 error = getaddrinfo(*argv, NULL((void*)0), &hints, &res);
1190 if (error) {
1191 errx(1, "%s", gai_strerror(error));
1192 }
1193 if (res == NULL((void*)0)) {
1194 errx(1, "%s: unknown", *argv);
1195 }
1196
1197 switch (res->ai_addr->sa_family) {
1198 case AF_INET2:
1199 memcpy(&ns4[ns4_count++],
1200 &((struct sockaddr_in *)res->ai_addr)->sin_addr,
1201 sizeof(struct in_addr));
1202 break;
1203 case AF_INET624:
1204 memcpy(&ns6[ns6_count++],
1205 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1206 sizeof(struct in6_addr));
1207 break;
1208 default:
1209 errx(1, "unknown address family");
1210 }
1211 freeaddrinfo(res);
1212 }
1213
1214 if (argc > 0)
1215 warnx("ignoring additional nameservers");
1216
1217 if (verbose) {
1218 for (i = 0; i < ns4_count; i++)
1219 warnx("v4: %s", inet_ntop(AF_INET2, &ns4[i], buf,
1220 sizeof(buf)));
1221 for (i = 0; i < ns6_count; i++)
1222 warnx("v6: %s", inet_ntop(AF_INET624, &ns6[i], buf,
1223 sizeof(buf)));
1224 }
1225
1226 memset(&rtm, 0, sizeof(rtm));
1227
1228 rtm.rtm_version = RTM_VERSION5;
1229 rtm.rtm_type = RTM_PROPOSAL0x13;
1230 rtm.rtm_msglen = sizeof(rtm);
1231 rtm.rtm_tableid = tableid;
1232 rtm.rtm_index = if_index;
1233 rtm.rtm_seq = 1;
1234 rtm.rtm_priority = RTP_PROPOSAL_STATIC57;
1235 rtm.rtm_addrs = RTA_DNS0x1000;
1236 rtm.rtm_flags = RTF_UP0x1;
1237
1238 iov[iovcnt].iov_base = &rtm;
1239 iov[iovcnt++].iov_len = sizeof(rtm);
1240
1241 iov[iovcnt].iov_base = &rtdns;
1242 iov[iovcnt++].iov_len = sizeof(rtdns);
1243 rtm.rtm_msglen += sizeof(rtdns);
1244
1245 padlen = ROUNDUP(sizeof(rtdns))((sizeof(rtdns)) > 0 ? (1 + (((sizeof(rtdns)) - 1) | (sizeof
(long) - 1))) : sizeof(long))
- sizeof(rtdns);
1246 if (padlen > 0) {
1247 iov[iovcnt].iov_base = &pad;
1248 iov[iovcnt++].iov_len = padlen;
1249 rtm.rtm_msglen += padlen;
1250 }
1251
1252 memset(&rtdns, 0, sizeof(rtdns));
1253 rtdns.sr_family = AF_INET2;
1254 rtdns.sr_len = 2 + ns4_count * sizeof(struct in_addr);
1255 memcpy(rtdns.sr_dns, ns4, rtdns.sr_len - 2);
1256
1257 if (debugonly)
1258 return (0);
1259
1260 if (writev(s, iov, iovcnt) == -1) {
1261 warn("failed to send route message");
1262 error = 1;
1263 }
1264
1265 rtm.rtm_seq++;
1266
1267 memset(&rtdns, 0, sizeof(rtdns));
1268 rtdns.sr_family = AF_INET624;
1269 rtdns.sr_len = 2 + ns6_count * sizeof(struct in6_addr);
1270 memcpy(rtdns.sr_dns, ns6, rtdns.sr_len - 2);
1271
1272 if (writev(s, iov, iovcnt) == -1) {
1273 warn("failed to send route message");
1274 error = 1;
1275 }
1276
1277 return (error);
1278}
1279
1280struct {
1281 struct rt_msghdr m_rtm;
1282 char m_space[512];
1283} m_rtmsg;
1284
1285int
1286rtmsg(int cmd, int flags, int fmask, uint8_t prio)
1287{
1288 static int seq;
1289 char *cp = m_rtmsg.m_space;
1290 int l;
1291
1292#define NEXTADDR(w, u)if (rtm_addrs & (w)) { l = ((u.sa.sa_len) > 0 ? (1 + (
((u.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof(long)); memcpy
(cp, &(u), l); cp += l; if (verbose) sodump(&(u), "u"
); }
\
1293 if (rtm_addrs & (w)) { \
1294 l = ROUNDUP(u.sa.sa_len)((u.sa.sa_len) > 0 ? (1 + (((u.sa.sa_len) - 1) | (sizeof(long
) - 1))) : sizeof(long))
; \
1295 memcpy(cp, &(u), l); \
1296 cp += l; \
1297 if (verbose) \
1298 sodump(&(u), #u); \
1299 }
1300
1301 errno(*__errno()) = 0;
1302 memset(&m_rtmsg, 0, sizeof(m_rtmsg));
1303 if (cmd == 'a')
1304 cmd = RTM_ADD0x1;
1305 else if (cmd == 'c')
1306 cmd = RTM_CHANGE0x3;
1307 else if (cmd == 'g') {
1308 cmd = RTM_GET0x4;
1309 if (so_ifp.sa.sa_family == AF_UNSPEC0) {
1310 so_ifp.sa.sa_family = AF_LINK18;
1311 so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
1312 rtm_addrs |= RTA_IFP0x10;
1313 }
1314 } else if (cmd == 's') {
1315 cmd = RTM_SOURCE0x16;
1316 } else
1317 cmd = RTM_DELETE0x2;
1318#define rtm m_rtmsg.m_rtm
1319 rtm.rtm_type = cmd;
1320 rtm.rtm_flags = flags;
1321 rtm.rtm_fmask = fmask;
1322 rtm.rtm_version = RTM_VERSION5;
1323 rtm.rtm_seq = ++seq;
1324 rtm.rtm_addrs = rtm_addrs;
1325 rtm.rtm_rmx = rt_metrics;
1326 rtm.rtm_inits = rtm_inits;
1327 rtm.rtm_tableid = tableid;
1328 rtm.rtm_priority = prio;
1329 rtm.rtm_mpls = mpls_flags;
1330 rtm.rtm_hdrlen = sizeof(rtm);
1331
1332 /* store addresses in ascending order of RTA values */
1333 NEXTADDR(RTA_DST, so_dst)if (rtm_addrs & (0x1)) { l = ((so_dst.sa.sa_len) > 0 ?
(1 + (((so_dst.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_dst), l); cp += l; if (verbose) sodump
(&(so_dst), "so_dst"); }
;
1334 NEXTADDR(RTA_GATEWAY, so_gate)if (rtm_addrs & (0x2)) { l = ((so_gate.sa.sa_len) > 0 ?
(1 + (((so_gate.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_gate), l); cp += l; if (verbose)
sodump(&(so_gate), "so_gate"); }
;
1335 NEXTADDR(RTA_NETMASK, so_mask)if (rtm_addrs & (0x4)) { l = ((so_mask.sa.sa_len) > 0 ?
(1 + (((so_mask.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_mask), l); cp += l; if (verbose)
sodump(&(so_mask), "so_mask"); }
;
1336 NEXTADDR(RTA_IFP, so_ifp)if (rtm_addrs & (0x10)) { l = ((so_ifp.sa.sa_len) > 0 ?
(1 + (((so_ifp.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_ifp), l); cp += l; if (verbose) sodump
(&(so_ifp), "so_ifp"); }
;
1337 NEXTADDR(RTA_IFA, so_ifa)if (rtm_addrs & (0x20)) { l = ((so_ifa.sa.sa_len) > 0 ?
(1 + (((so_ifa.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_ifa), l); cp += l; if (verbose) sodump
(&(so_ifa), "so_ifa"); }
;
1338 NEXTADDR(RTA_SRC, so_src)if (rtm_addrs & (0x100)) { l = ((so_src.sa.sa_len) > 0
? (1 + (((so_src.sa.sa_len) - 1) | (sizeof(long) - 1))) : sizeof
(long)); memcpy(cp, &(so_src), l); cp += l; if (verbose) sodump
(&(so_src), "so_src"); }
;
1339 NEXTADDR(RTA_LABEL, so_label)if (rtm_addrs & (0x400)) { l = ((so_label.sa.sa_len) >
0 ? (1 + (((so_label.sa.sa_len) - 1) | (sizeof(long) - 1))) :
sizeof(long)); memcpy(cp, &(so_label), l); cp += l; if (
verbose) sodump(&(so_label), "so_label"); }
;
1340 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
1341 if (verbose)
1342 print_rtmsg(&rtm, l);
1343 if (debugonly)
1344 return (0);
1345 if (write(s, &m_rtmsg, l) != l) {
1346 return (-1);
1347 }
1348 if (cmd == RTM_GET0x4) {
1349 do {
1350 l = read(s, &m_rtmsg, sizeof(m_rtmsg));
1351 } while (l > 0 && (rtm.rtm_version != RTM_VERSION5 ||
1352 rtm.rtm_seq != seq || rtm.rtm_pid != pid));
1353 if (l == -1)
1354 warn("read from routing socket");
1355 else
1356 print_getmsg(&rtm, l);
1357 }
1358#undef rtm
1359 return (0);
1360}
1361
1362char *msgtypes[] = {
1363 "",
1364 "RTM_ADD: Add Route",
1365 "RTM_DELETE: Delete Route",
1366 "RTM_CHANGE: Change Metrics or flags",
1367 "RTM_GET: Report Metrics",
1368 "RTM_LOSING: Kernel Suspects Partitioning",
1369 "RTM_REDIRECT: Told to use different route",
1370 "RTM_MISS: Lookup failed on this address",
1371 "",
1372 "",
1373 "",
1374 "RTM_RESOLVE: Route created by cloning",
1375 "RTM_NEWADDR: address being added to iface",
1376 "RTM_DELADDR: address being removed from iface",
1377 "RTM_IFINFO: iface status change",
1378 "RTM_IFANNOUNCE: iface arrival/departure",
1379 "RTM_DESYNC: route socket overflow",
1380 "RTM_INVALIDATE: invalidate cache of L2 route",
1381 "RTM_BFD: bidirectional forwarding detection",
1382 "RTM_PROPOSAL: config proposal",
1383 "RTM_CHGADDRATTR: address attributes being changed",
1384 "RTM_80211INFO: 802.11 iface status change"
1385};
1386
1387char metricnames[] =
1388"\011priority\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
1389char routeflags[] =
1390"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010XMASK_PRESENT"
1391"\011CLONING\012MULTICAST\013LLINFO\014STATIC\015BLACKHOLE\016PROTO3\017PROTO2"
1392"\020PROTO1\021CLONED\022CACHED\023MPATH\025MPLS\026LOCAL\027BROADCAST"
1393"\030CONNECTED\031BFD";
1394char ifnetflags[] =
1395"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6STATICARP\7RUNNING\010NOARP\011PPROMISC"
1396"\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST"
1397"\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII\30AUTOCONF4";
1398char addrnames[] =
1399"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\012SRCMASK\013LABEL\014BFD\015DNS\016STATIC\017SEARCH";
1400char ieee80211flags[] =
1401 "\1ASCAN\2SIBSS\011WEPON\012IBSSON\013PMGTON\014DESBSSID\016ROAMING"
1402 "\020TXPOW_FIXED\021TXPOW_AUTO\022SHSLOT\023SHPREAMBLE\024QOS"
1403 "\025USEPROT\026RSNON\027PSK\030COUNTERM\031MFPR\032HTON\033PBAR"
1404 "\034BGSCAN\035AUTO_JOIN\036VHTON";
1405char ieee80211xflags[] =
1406 "\1TX_MGMT_ONLY";
1407
1408const char *
1409get_linkstate(int mt, int link_state)
1410{
1411 const struct if_status_description *p;
1412 static char buf[8];
1413
1414 for (p = if_status_descriptions; p->ifs_string != NULL((void*)0); p++) {
1415 if (LINK_STATE_DESC_MATCH(p, mt, link_state)(((p)->ifs_type == (mt) || (p)->ifs_type == 0) &&
(p)->ifs_state == (link_state))
)
1416 return (p->ifs_string);
1417 }
1418 snprintf(buf, sizeof(buf), "[#%d]", link_state);
1419 return buf;
1420}
1421
1422void
1423print_rtmsg(struct rt_msghdr *rtm, int msglen)
1424{
1425 long long relative_expire;
1426 struct if_msghdr *ifm;
1427 struct ifa_msghdr *ifam;
1428 struct if_announcemsghdr *ifan;
1429 char ifname[IF_NAMESIZE16];
1430
1431 if (verbose == 0)
1432 return;
1433 if (rtm->rtm_version != RTM_VERSION5) {
1434 warnx("routing message version %u not understood",
1435 rtm->rtm_version);
1436 return;
1437 }
1438 if (rtm->rtm_type > 0 &&
1439 rtm->rtm_type < sizeof(msgtypes)/sizeof(msgtypes[0]))
1440 printf("%s", msgtypes[rtm->rtm_type]);
1441 else
1442 printf("[rtm_type %u out of range]", rtm->rtm_type);
1443
1444 printf(": len %u", rtm->rtm_msglen);
1445 switch (rtm->rtm_type) {
1446 case RTM_DESYNC0x10:
1447 printf("\n");
1448 break;
1449 case RTM_IFINFO0xe:
1450 ifm = (struct if_msghdr *)rtm;
1451 printf(", if# %u, ", ifm->ifm_index);
1452 if (if_indextoname(ifm->ifm_index, ifname) != NULL((void*)0))
1453 printf("name %s, ", ifname);
1454 printf("link: %s, mtu: %u, flags:",
1455 get_linkstate(ifm->ifm_data.ifi_type,
1456 ifm->ifm_data.ifi_link_state),
1457 ifm->ifm_data.ifi_mtu);
1458 bprintf(stdout(&__sF[1]), ifm->ifm_flags | (ifm->ifm_xflags << 16),
1459 ifnetflags);
1460 pmsg_addrs((char *)ifm + ifm->ifm_hdrlen, ifm->ifm_addrs);
1461 break;
1462 case RTM_80211INFO0x15:
1463 printf(", if# %u, ", rtm->rtm_index);
1464 if (if_indextoname(rtm->rtm_index, ifname) != NULL((void*)0))
1465 printf("name %s, ", ifname);
1466 print_80211info((struct if_ieee80211_msghdr *)rtm);
1467 break;
1468 case RTM_NEWADDR0xc:
1469 case RTM_DELADDR0xd:
1470 case RTM_CHGADDRATTR0x14:
1471 ifam = (struct ifa_msghdr *)rtm;
1472 printf(", if# %u, ", ifam->ifam_index);
1473 if (if_indextoname(ifam->ifam_index, ifname) != NULL((void*)0))
1474 printf("name %s, ", ifname);
1475 printf("metric %d, flags:", ifam->ifam_metric);
1476 bprintf(stdout(&__sF[1]), ifam->ifam_flags, routeflags);
1477 pmsg_addrs((char *)ifam + ifam->ifam_hdrlen, ifam->ifam_addrs);
1478 break;
1479 case RTM_IFANNOUNCE0xf:
1480 ifan = (struct if_announcemsghdr *)rtm;
1481 printf(", if# %u, name %s, what: ",
1482 ifan->ifan_index, ifan->ifan_name);
1483 switch (ifan->ifan_what) {
1484 case IFAN_ARRIVAL0:
1485 printf("arrival");
1486 break;
1487 case IFAN_DEPARTURE1:
1488 printf("departure");
1489 break;
1490 default:
1491 printf("#%u", ifan->ifan_what);
1492 break;
1493 }
1494 printf("\n");
1495 break;
1496#ifdef BFD1
1497 case RTM_BFD0x12:
1498 print_bfdmsg(rtm);
1499 break;
1500#endif
1501 case RTM_PROPOSAL0x13:
1502 printf(", source ");
1503 switch (rtm->rtm_priority) {
1504 case RTP_PROPOSAL_STATIC57:
1505 printf("static");
1506 break;
1507 case RTP_PROPOSAL_DHCLIENT58:
1508 printf("dhcp");
1509 break;
1510 case RTP_PROPOSAL_SLAAC59:
1511 printf("slaac");
1512 break;
1513 case RTP_PROPOSAL_UMB60:
1514 printf("umb");
1515 break;
1516 case RTP_PROPOSAL_PPP61:
1517 printf("ppp");
1518 break;
1519 case RTP_PROPOSAL_SOLICIT62:
1520 printf("solicit");
1521 break;
1522 default:
1523 printf("unknown");
1524 break;
1525 }
1526 printf(", table %u, if# %u, ",
1527 rtm->rtm_tableid, rtm->rtm_index);
1528 if (if_indextoname(rtm->rtm_index, ifname) != NULL((void*)0))
1529 printf("name %s, ", ifname);
1530 printf("pid: %ld, seq %d, errno %d\nflags:",
1531 (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
1532 bprintf(stdout(&__sF[1]), rtm->rtm_flags, routeflags);
1533 printf("\nfmask:");
1534 bprintf(stdout(&__sF[1]), rtm->rtm_fmask, routeflags);
1535 if (verbose) {
1536#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)RTV_f) ? 'L' : ' ')
1537 relative_expire = rtm->rtm_rmx.rmx_expire ?
1538 rtm->rtm_rmx.rmx_expire - time(NULL((void*)0)) : 0;
1539 printf("\nuse: %8llu mtu: %8u%c expire: %8lld%c",
1540 rtm->rtm_rmx.rmx_pksent,
1541 rtm->rtm_rmx.rmx_mtu, lock(MTU),
1542 relative_expire, lock(EXPIRE));
1543#undef lock
1544 }
1545 printf("\nlocks: ");
1546 bprintf(stdout(&__sF[1]), rtm->rtm_rmx.rmx_locks, metricnames);
1547 printf(" inits: ");
1548 bprintf(stdout(&__sF[1]), rtm->rtm_inits, metricnames);
1549 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen),
1550 rtm->rtm_addrs & ~(RTA_STATIC0x2000 | RTA_SEARCH0x4000 | RTA_DNS0x1000));
1551
1552 if(!(rtm->rtm_addrs & (RTA_STATIC0x2000 | RTA_SEARCH0x4000 | RTA_DNS0x1000)))
1553 break;
1554
1555 printf("proposals: ");
1556 bprintf(stdout(&__sF[1]), rtm->rtm_addrs & (RTA_STATIC0x2000 | RTA_SEARCH0x4000 |
1557 RTA_DNS0x1000), addrnames);
1558 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1559
1560 if (rtm->rtm_addrs & RTA_STATIC0x2000) {
1561 char *next = (char *)rtm + rtm->rtm_hdrlen;
1562 struct sockaddr *sa, *rti_info[RTAX_MAX15];
1563 struct sockaddr_rtstatic *rtstatic;
1564 sa = (struct sockaddr *)next;
1565 get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1566 rtstatic = (struct sockaddr_rtstatic *)
1567 rti_info[RTAX_STATIC13];
1568 if (rtstatic != NULL((void*)0))
1569 print_rtstatic(rtstatic);
1570 }
1571
1572 if (rtm->rtm_addrs & RTA_SEARCH0x4000) {
1573 char *next = (char *)rtm + rtm->rtm_hdrlen;
1574 struct sockaddr *sa, *rti_info[RTAX_MAX15];
1575 struct sockaddr_rtsearch *rtsearch;
1576 sa = (struct sockaddr *)next;
1577 get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1578 rtsearch = (struct sockaddr_rtsearch *)
1579 rti_info[RTAX_SEARCH14];
1580 if (rtsearch != NULL((void*)0))
1581 print_rtsearch(rtsearch);
1582 }
1583
1584 if (rtm->rtm_addrs & RTA_DNS0x1000) {
1585 char *next = (char *)rtm + rtm->rtm_hdrlen;
1586 struct sockaddr *sa, *rti_info[RTAX_MAX15];
1587 struct sockaddr_rtdns *rtdns;
1588 sa = (struct sockaddr *)next;
1589 get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1590 rtdns = (struct sockaddr_rtdns *)rti_info[RTAX_DNS12];
1591 if (rtdns != NULL((void*)0))
1592 print_rtdns(rtdns);
1593 }
1594 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1595 break;
1596 default:
1597 printf(", priority %u, table %u, if# %u, ",
1598 rtm->rtm_priority, rtm->rtm_tableid, rtm->rtm_index);
1599 if (if_indextoname(rtm->rtm_index, ifname) != NULL((void*)0))
1600 printf("name %s, ", ifname);
1601 printf("pid: %ld, seq %d, errno %d\nflags:",
1602 (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
1603 bprintf(stdout(&__sF[1]), rtm->rtm_flags, routeflags);
1604 printf("\nfmask:");
1605 bprintf(stdout(&__sF[1]), rtm->rtm_fmask, routeflags);
1606 if (verbose) {
1607#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)RTV_f) ? 'L' : ' ')
1608 relative_expire = rtm->rtm_rmx.rmx_expire ?
1609 rtm->rtm_rmx.rmx_expire - time(NULL((void*)0)) : 0;
1610 printf("\nuse: %8llu mtu: %8u%c expire: %8lld%c",
1611 rtm->rtm_rmx.rmx_pksent,
1612 rtm->rtm_rmx.rmx_mtu, lock(MTU),
1613 relative_expire, lock(EXPIRE));
1614#undef lock
1615 }
1616 pmsg_common(rtm);
1617 }
1618}
1619
1620char *
1621priorityname(uint8_t prio)
1622{
1623 switch (prio) {
1624 case RTP_NONE0:
1625 return ("none");
1626 case RTP_LOCAL1:
1627 return ("local");
1628 case RTP_CONNECTED4:
1629 return ("connected");
1630 case RTP_STATIC8:
1631 return ("static");
1632 case RTP_OSPF32:
1633 return ("ospf");
1634 case RTP_ISIS36:
1635 return ("is-is");
1636 case RTP_RIP40:
1637 return ("rip");
1638 case RTP_BGP48:
1639 return ("bgp");
1640 case RTP_DEFAULT56:
1641 return ("default");
1642 default:
1643 return ("");
1644 }
1645}
1646
1647uint8_t
1648getpriority(char *priostr)
1649{
1650 const char *errstr;
1651 uint8_t prio;
1652
1653 switch (keyword(priostr)) {
1654 case K_LOCAL:
1655 prio = RTP_LOCAL1;
1656 break;
1657 case K_CONNECTED:
1658 prio = RTP_CONNECTED4;
1659 break;
1660 case K_STATIC:
1661 prio = RTP_STATIC8;
1662 break;
1663 case K_OSPF:
1664 prio = RTP_OSPF32;
1665 break;
1666 case K_RIP:
1667 prio = RTP_RIP40;
1668 break;
1669 case K_BGP:
1670 prio = RTP_BGP48;
1671 break;
1672 default:
1673 prio = strtonum(priostr, -RTP_MAX63, RTP_MAX63, &errstr);
1674 if (errstr)
1675 errx(1, "priority is %s: %s", errstr, priostr);
1676 }
1677
1678 return (prio);
1679}
1680
1681void
1682print_getmsg(struct rt_msghdr *rtm, int msglen)
1683{
1684 long long relative_expire;
1685 struct sockaddr *dst = NULL((void*)0), *gate = NULL((void*)0), *mask = NULL((void*)0), *ifa = NULL((void*)0);
1686 struct sockaddr_dl *ifp = NULL((void*)0);
1687 struct sockaddr_rtlabel *sa_rl = NULL((void*)0);
1688#ifdef BFD1
1689 struct sockaddr_bfd *sa_bfd = NULL((void*)0);
1690#endif
1691 struct sockaddr *mpls = NULL((void*)0);
1692 struct sockaddr *sa;
1693 char *cp;
1694 int i;
1695
1696 printf(" route to: %s\n", routename(&so_dst.sa));
1697 if (rtm->rtm_version != RTM_VERSION5) {
1698 warnx("routing message version %u not understood",
1699 rtm->rtm_version);
1700 return;
1701 }
1702 if (rtm->rtm_msglen > msglen)
1703 warnx("message length mismatch, in packet %u, returned %d",
1704 rtm->rtm_msglen, msglen);
1705 if (rtm->rtm_errno) {
1706 warnx("RTM_GET: %s (errno %d)",
1707 strerror(rtm->rtm_errno), rtm->rtm_errno);
1708 return;
1709 }
1710 cp = ((char *)rtm + rtm->rtm_hdrlen);
1711 if (rtm->rtm_addrs)
1712 for (i = 1; i; i <<= 1)
1713 if (i & rtm->rtm_addrs) {
1714 sa = (struct sockaddr *)cp;
1715 switch (i) {
1716 case RTA_DST0x1:
1717 dst = sa;
1718 break;
1719 case RTA_GATEWAY0x2:
1720 gate = sa;
1721 break;
1722 case RTA_NETMASK0x4:
1723 mask = sa;
1724 break;
1725 case RTA_IFA0x20:
1726 ifa = sa;
1727 break;
1728 case RTA_IFP0x10:
1729 if (sa->sa_family == AF_LINK18 &&
1730 ((struct sockaddr_dl *)sa)->sdl_nlen)
1731 ifp = (struct sockaddr_dl *)sa;
1732 break;
1733 case RTA_SRC0x100:
1734 mpls = sa;
1735 break;
1736 case RTA_LABEL0x400:
1737 sa_rl = (struct sockaddr_rtlabel *)sa;
1738 break;
1739#ifdef BFD1
1740 case RTA_BFD0x800:
1741 sa_bfd = (struct sockaddr_bfd *)sa;
1742 break;
1743#endif
1744 }
1745 ADVANCE(cp, sa)(cp += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) -
1) | (sizeof(long) - 1))) : sizeof(long)))
;
1746 }
1747 if (dst && mask)
1748 mask->sa_family = dst->sa_family; /* XXX */
1749 if (dst)
1750 printf("destination: %s\n", routename(dst));
1751 if (mask) {
1752 int savenflag = nflag;
1753
1754 nflag = 1;
1755 printf(" mask: %s\n", routename(mask));
1756 nflag = savenflag;
1757 }
1758 if (gate && rtm->rtm_flags & RTF_GATEWAY0x2)
1759 printf(" gateway: %s\n", routename(gate));
1760 if (ifp)
1761 printf(" interface: %.*s\n",
1762 ifp->sdl_nlen, ifp->sdl_data);
1763 if (ifa)
1764 printf(" if address: %s\n", routename(ifa));
1765 if (mpls) {
1766 printf(" mpls label: %s %s\n", mpls_op(rtm->rtm_mpls),
1767 routename(mpls));
1768 }
1769 printf(" priority: %u (%s)\n", rtm->rtm_priority,
1770 priorityname(rtm->rtm_priority));
1771 printf(" flags: ");
1772 bprintf(stdout(&__sF[1]), rtm->rtm_flags, routeflags);
1773 printf("\n");
1774 if (sa_rl != NULL((void*)0))
1775 printf(" label: %s\n", sa_rl->sr_label);
1776#ifdef BFD1
1777 if (sa_bfd)
1778 print_sabfd(sa_bfd, rtm->rtm_fmask);
1779#endif
1780
1781#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)RTV_f) ? 'L' : ' ')
1782 relative_expire = rtm->rtm_rmx.rmx_expire ?
1783 rtm->rtm_rmx.rmx_expire - time(NULL((void*)0)) : 0;
1784 printf(" use mtu expire\n");
1785 printf("%8llu %8u%c %8lld%c\n",
1786 rtm->rtm_rmx.rmx_pksent,
1787 rtm->rtm_rmx.rmx_mtu, lock(MTU),
1788 relative_expire, lock(EXPIRE));
1789#undef lock
1790#define RTA_IGN (RTA_DST0x1|RTA_GATEWAY0x2|RTA_NETMASK0x4|RTA_IFP0x10|RTA_IFA0x20|RTA_BRD0x80)
1791 if (verbose)
1792 pmsg_common(rtm);
1793 else if (rtm->rtm_addrs &~ RTA_IGN) {
1794 printf("sockaddrs: ");
1795 bprintf(stdout(&__sF[1]), rtm->rtm_addrs, addrnames);
1796 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1797 }
1798#undef RTA_IGN
1799}
1800
1801#ifdef BFD1
1802const char *
1803bfd_state(unsigned int state)
1804{
1805 switch (state) {
1806 case BFD_STATE_ADMINDOWN0:
1807 return("admindown");
1808 break;
1809 case BFD_STATE_DOWN1:
1810 return("down");
1811 break;
1812 case BFD_STATE_INIT2:
1813 return("init");
1814 break;
1815 case BFD_STATE_UP3:
1816 return("up");
1817 break;
1818 }
1819 return "invalid";
1820}
1821
1822const char *
1823bfd_diag(unsigned int diag)
1824{
1825 switch (diag) {
1826 case BFD_DIAG_NONE0:
1827 return("none");
1828 break;
1829 case BFD_DIAG_EXPIRED1:
1830 return("expired");
1831 break;
1832 case BFD_DIAG_ECHO_FAILED2:
1833 return("echo-failed");
1834 break;
1835 case BFD_DIAG_NEIGHBOR_SIGDOWN3:
1836 return("neighbor-down");
1837 break;
1838 case BFD_DIAG_FIB_RESET4:
1839 return("fib-reset");
1840 break;
1841 case BFD_DIAG_PATH_DOWN5:
1842 return("path-down");
1843 break;
1844 case BFD_DIAG_CONCAT_PATH_DOWN6:
1845 return("concat-path-down");
1846 break;
1847 case BFD_DIAG_ADMIN_DOWN7:
1848 return("admindown");
1849 break;
1850 case BFD_DIAG_CONCAT_REVERSE_DOWN8:
1851 return("concat-reverse-down");
1852 break;
1853 }
1854 return "invalid";
1855}
1856
1857const char *
1858bfd_calc_uptime(time_t time)
1859{
1860 static char buf[256];
1861 struct tm *tp;
1862 const char *fmt;
1863
1864 if (time > 2*86400)
1865 fmt = "%dd%kh%Mm%Ss";
1866 else if (time > 2*3600)
1867 fmt = "%kh%Mm%Ss";
1868 else if (time > 2*60)
1869 fmt = "%Mm%Ss";
1870 else
1871 fmt = "%Ss";
1872
1873 tp = localtime(&time);
1874 (void)strftime(buf, sizeof(buf), fmt, tp);
1875 return (buf);
1876}
1877
1878void
1879print_bfdmsg(struct rt_msghdr *rtm)
1880{
1881 struct bfd_msghdr *bfdm = (struct bfd_msghdr *)rtm;
1882
1883 printf("\n");
1884 print_sabfd(&bfdm->bm_sa, rtm->rtm_fmask);
1885 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), rtm->rtm_addrs);
1886}
1887
1888void
1889print_sabfd(struct sockaddr_bfd *sa_bfd, int fmask)
1890{
1891 struct timeval tv;
1892
1893 gettimeofday(&tv, NULL((void*)0));
1894
1895 printf(" BFD:");
1896
1897 /* only show the state, unless verbose or -bfd */
1898 if (!verbose && ((fmask & RTF_BFD0x1000000) != RTF_BFD0x1000000)) {
1899 printf(" %s\n", bfd_state(sa_bfd->bs_state));
1900 return;
1901 }
1902
1903 switch (sa_bfd->bs_mode) {
1904 case BFD_MODE_ASYNC1:
1905 printf(" async");
1906 break;
1907 case BFD_MODE_DEMAND2:
1908 printf(" demand");
1909 break;
1910 default:
1911 printf(" unknown %u", sa_bfd->bs_mode);
1912 break;
1913 }
1914
1915 printf(" state %s", bfd_state(sa_bfd->bs_state));
1916 printf(" remote %s", bfd_state(sa_bfd->bs_remotestate));
1917 printf(" laststate %s", bfd_state(sa_bfd->bs_laststate));
1918
1919 printf(" error %u", sa_bfd->bs_error);
1920 printf("\n ");
1921 printf(" diag %s", bfd_diag(sa_bfd->bs_localdiag));
1922 printf(" remote %s", bfd_diag(sa_bfd->bs_remotediag));
1923 printf("\n ");
1924 printf(" discr %u", sa_bfd->bs_localdiscr);
1925 printf(" remote %u", sa_bfd->bs_remotediscr);
1926 printf("\n ");
1927 printf(" uptime %s", bfd_calc_uptime(tv.tv_sec - sa_bfd->bs_uptime));
1928 if (sa_bfd->bs_lastuptime)
1929 printf(" last state time %s",
1930 bfd_calc_uptime(sa_bfd->bs_lastuptime));
1931 printf("\n ");
1932 printf(" mintx %u", sa_bfd->bs_mintx);
1933 printf(" minrx %u", sa_bfd->bs_minrx);
1934 printf(" minecho %u", sa_bfd->bs_minecho);
1935 printf(" multiplier %u", sa_bfd->bs_multiplier);
1936 printf("\n");
1937}
1938#endif /* BFD */
1939
1940void
1941pmsg_common(struct rt_msghdr *rtm)
1942{
1943 printf("\nlocks: ");
1944 bprintf(stdout(&__sF[1]), rtm->rtm_rmx.rmx_locks, metricnames);
1945 printf(" inits: ");
1946 bprintf(stdout(&__sF[1]), rtm->rtm_inits, metricnames);
1947 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), rtm->rtm_addrs);
1948}
1949
1950void
1951pmsg_addrs(char *cp, int addrs)
1952{
1953 struct sockaddr *sa;
1954 int family = AF_UNSPEC0;
1955 int i;
1956 char *p;
1957
1958 if (addrs != 0) {
1959 printf("\nsockaddrs: ");
1960 bprintf(stdout(&__sF[1]), addrs, addrnames);
1961 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1962 /* first run, search for address family */
1963 p = cp;
1964 for (i = 1; i; i <<= 1)
1965 if (i & addrs) {
1966 sa = (struct sockaddr *)p;
1967 if (family == AF_UNSPEC0)
1968 switch (i) {
1969 case RTA_DST0x1:
1970 case RTA_IFA0x20:
1971 family = sa->sa_family;
1972 }
1973 ADVANCE(p, sa)(p += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) - 1
) | (sizeof(long) - 1))) : sizeof(long)))
;
1974 }
1975 /* second run, set address family for mask and print */
1976 p = cp;
1977 for (i = 1; i; i <<= 1)
1978 if (i & addrs) {
1979 sa = (struct sockaddr *)p;
1980 if (family != AF_UNSPEC0)
1981 switch (i) {
1982 case RTA_NETMASK0x4:
1983 sa->sa_family = family;
1984 }
1985 printf(" %s", routename(sa));
1986 ADVANCE(p, sa)(p += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) - 1
) | (sizeof(long) - 1))) : sizeof(long)))
;
1987 }
1988 }
1989 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1990 fflush(stdout(&__sF[1]));
1991}
1992
1993void
1994bprintf(FILE *fp, int b, char *s)
1995{
1996 int i;
1997 int gotsome = 0;
1998
1999 if (b == 0)
2000 return;
2001 while ((i = *s++)) {
2002 if ((b & (1 << (i-1)))) {
2003 if (gotsome == 0)
2004 i = '<';
2005 else
2006 i = ',';
2007 putc(i, fp)(!__isthreaded ? __sputc(i, fp) : (putc)(i, fp));
2008 gotsome = 1;
2009 for (; (i = *s) > 32; s++)
2010 putc(i, fp)(!__isthreaded ? __sputc(i, fp) : (putc)(i, fp));
2011 } else
2012 while (*s > 32)
2013 s++;
2014 }
2015 if (gotsome)
2016 putc('>', fp)(!__isthreaded ? __sputc('>', fp) : (putc)('>', fp));
2017}
2018
2019int
2020keycmp(const void *key, const void *kt)
2021{
2022 return (strcmp(key, ((struct keytab *)kt)->kt_cp));
2023}
2024
2025int
2026keyword(char *cp)
2027{
2028 struct keytab *kt;
2029
2030 kt = bsearch(cp, keywords, sizeof(keywords)/sizeof(keywords[0]),
2031 sizeof(keywords[0]), keycmp);
2032 if (!kt)
2033 return (0);
2034
2035 return (kt->kt_i);
2036}
2037
2038void
2039sodump(sup su, char *which)
2040{
2041 switch (su->sa.sa_family) {
2042 case AF_LINK18:
2043 printf("%s: link %s; ", which, link_ntoa(&su->sdl));
2044 break;
2045 case AF_INET2:
2046 printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr));
2047 break;
2048 case AF_INET624:
2049 {
2050 char ntop_buf[NI_MAXHOST256];
2051
2052 printf("%s: inet6 %s; ",
2053 which, inet_ntop(AF_INET624, &su->sin6.sin6_addr,
2054 ntop_buf, sizeof(ntop_buf)));
2055 break;
2056 }
2057 }
2058 fflush(stdout(&__sF[1]));
2059}
2060
2061/* States*/
2062#define VIRGIN0 0
2063#define GOTONE1 1
2064#define GOTTWO2 2
2065/* Inputs */
2066#define DIGIT(4*0) (4*0)
2067#define END(4*1) (4*1)
2068#define DELIM(4*2) (4*2)
2069
2070void
2071sockaddr(char *addr, struct sockaddr *sa)
2072{
2073 char *cp = (char *)sa;
2074 int size = sa->sa_len;
2075 char *cplim = cp + size;
2076 int byte = 0, state = VIRGIN0, new = 0;
2077
2078 memset(cp, 0, size);
2079 cp++;
2080 do {
2081 if ((*addr >= '0') && (*addr <= '9')) {
2082 new = *addr - '0';
2083 } else if ((*addr >= 'a') && (*addr <= 'f')) {
2084 new = *addr - 'a' + 10;
2085 } else if ((*addr >= 'A') && (*addr <= 'F')) {
2086 new = *addr - 'A' + 10;
2087 } else if (*addr == '\0')
2088 state |= END(4*1);
2089 else
2090 state |= DELIM(4*2);
2091 addr++;
2092 switch (state /* | INPUT */) {
2093 case GOTTWO2 | DIGIT(4*0):
2094 *cp++ = byte; /*FALLTHROUGH*/
2095 case VIRGIN0 | DIGIT(4*0):
2096 state = GOTONE1; byte = new; continue;
2097 case GOTONE1 | DIGIT(4*0):
2098 state = GOTTWO2; byte = new + (byte << 4); continue;
2099 default: /* | DELIM */
2100 state = VIRGIN0; *cp++ = byte; byte = 0; continue;
2101 case GOTONE1 | END(4*1):
2102 case GOTTWO2 | END(4*1):
2103 *cp++ = byte; /* FALLTHROUGH */
2104 case VIRGIN0 | END(4*1):
2105 break;
2106 }
2107 break;
2108 } while (cp < cplim);
2109 sa->sa_len = cp - (char *)sa;
2110}
2111
2112void
2113getlabel(char *name)
2114{
2115 so_label.rtlabel.sr_len = sizeof(so_label.rtlabel);
2116 so_label.rtlabel.sr_family = AF_UNSPEC0;
2117 if (strlcpy(so_label.rtlabel.sr_label, name,
2118 sizeof(so_label.rtlabel.sr_label)) >=
2119 sizeof(so_label.rtlabel.sr_label))
2120 errx(1, "label too long");
2121 rtm_addrs |= RTA_LABEL0x400;
2122}
2123
2124#ifndef SMALL
2125int
2126gettable(const char *s)
2127{
2128 const char *errstr;
2129 struct rt_tableinfo info;
2130 int mib[6];
2131 size_t len;
2132
2133 tableid = strtonum(s, 0, RT_TABLEID_MAX255, &errstr);
2134 if (errstr)
2135 errx(1, "invalid table id: %s", errstr);
2136
2137 mib[0] = CTL_NET4;
2138 mib[1] = PF_ROUTE17;
2139 mib[2] = 0;
2140 mib[3] = 0;
2141 mib[4] = NET_RT_TABLE5;
2142 mib[5] = tableid;
2143
2144 len = sizeof(info);
2145 if (sysctl(mib, 6, &info, &len, NULL((void*)0), 0) == -1)
2146 return (errno(*__errno()));
2147 else
2148 return (0);
2149}
2150
2151int
2152rdomain(int argc, char **argv)
2153{
2154 if (!argc)
2155 usage(NULL((void*)0));
2156 if (setrtable(tableid) == -1)
2157 err(1, "setrtable");
2158 execvp(*argv, argv);
2159 warn("%s", argv[0]);
2160 return (errno(*__errno()) == ENOENT2 ? 127 : 126);
2161}
2162#endif /* SMALL */
2163
2164/*
2165 * Print RTM_PROPOSAL DNS server addresses.
2166 */
2167void
2168print_rtdns(struct sockaddr_rtdns *rtdns)
2169{
2170 struct in_addr server;
2171 struct in6_addr in6;
2172 size_t srclen, offset;
2173 unsigned int servercnt;
2174 int i;
2175 char *src = rtdns->sr_dns;
2176 char ntopbuf[INET6_ADDRSTRLEN46];
2177
2178 offset = offsetof(struct sockaddr_rtdns, sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns);
2179 if (rtdns->sr_len < offset) {
2180 printf("<invalid sr_len (%u <= %zu)>\n", rtdns->sr_len,
2181 offset);
2182 return;
2183 }
2184 srclen = rtdns->sr_len - offset;
2185 if (srclen > sizeof(rtdns->sr_dns)) {
2186 printf("<invalid sr_len (%zu > %zu)>\n", srclen,
2187 sizeof(rtdns->sr_dns));
2188 return;
2189 }
2190 switch (rtdns->sr_family) {
2191 case AF_INET2:
2192 printf(" INET [");
2193 /* An array of IPv4 addresses. */
2194 servercnt = srclen / sizeof(struct in_addr);
2195 if (servercnt * sizeof(struct in_addr) != srclen) {
2196 printf("<invalid server count>\n");
2197 return;
2198 }
2199 for (i = 0; i < servercnt; i++) {
2200 memcpy(&server.s_addr, src, sizeof(server.s_addr));
2201 printf("%s%s", inet_ntoa(server), i == servercnt - 1 ?
2202 "": ", ");
2203 src += sizeof(struct in_addr);
2204 }
2205 break;
2206 case AF_INET624:
2207 printf(" INET6 [");
2208 servercnt = srclen / sizeof(struct in6_addr);
2209 if (servercnt * sizeof(struct in6_addr) != srclen) {
2210 printf("<invalid server count>\n");
2211 return;
2212 }
2213 for (i = 0; i < servercnt; i++) {
2214 memcpy(&in6, src, sizeof(in6));
2215 src += sizeof(in6);
2216 printf("%s%s", inet_ntop(AF_INET624, &in6, ntopbuf,
2217 INET6_ADDRSTRLEN46), i == servercnt - 1 ? "": ", ");
2218 }
2219 break;
2220 default:
2221 printf(" UNKNOWN [");
2222 break;
2223 }
2224 printf("]");
2225}
2226
2227/*
2228 * Print RTM_PROPOSAL static routes.
2229 */
2230void
2231print_rtstatic(struct sockaddr_rtstatic *rtstatic)
2232{
2233 struct sockaddr_in6 gateway6;
2234 struct in6_addr prefix;
2235 struct in_addr dest, gateway;
2236 size_t srclen, offset;
2237 int bits, bytes, error, first = 1;
2238 uint8_t prefixlen;
2239 unsigned char *src = rtstatic->sr_static;
2240 char ntoabuf[INET_ADDRSTRLEN16];
2241 char hbuf[NI_MAXHOST256];
2242 char ntopbuf[INET6_ADDRSTRLEN46];
2243
2244 offset = offsetof(struct sockaddr_rtstatic, sr_static)__builtin_offsetof(struct sockaddr_rtstatic, sr_static);
2245 if (rtstatic->sr_len <= offset) {
2246 printf("<invalid sr_len (%u <= %zu)>\n", rtstatic->sr_len,
2247 offset);
2248 return;
2249 }
2250 srclen = rtstatic->sr_len - offset;
2251 if (srclen > sizeof(rtstatic->sr_static)) {
2252 printf("<invalid sr_len (%zu > %zu)>\n", srclen,
2253 sizeof(rtstatic->sr_static));
2254 return;
2255 }
2256 printf(" [");
2257 switch (rtstatic->sr_family) {
2258 case AF_INET2:
2259 /* AF_INET -> RFC 3442 encoded static routes. */
2260 while (srclen) {
2261 bits = *src;
2262 src++;
2263 srclen--;
2264 bytes = (bits + 7) / 8;
2265 if (srclen < bytes || bytes > sizeof(dest.s_addr))
2266 break;
2267 memset(&dest, 0, sizeof(dest));
2268 memcpy(&dest.s_addr, src, bytes);
2269 src += bytes;
2270 srclen -= bytes;
2271 strlcpy(ntoabuf, inet_ntoa(dest), sizeof(ntoabuf));
2272 if (srclen < sizeof(gateway.s_addr))
2273 break;
2274 memcpy(&gateway.s_addr, src, sizeof(gateway.s_addr));
2275 src += sizeof(gateway.s_addr);
2276 srclen -= sizeof(gateway.s_addr);
2277 printf("%s%s/%u %s ", first ? "" : ", ", ntoabuf, bits,
2278 inet_ntoa(gateway));
2279 first = 0;
2280 }
2281 break;
2282 case AF_INET624:
2283 while (srclen >= sizeof(prefixlen) + sizeof(prefix) +
2284 sizeof(gateway6)) {
2285 memcpy(&prefixlen, src, sizeof(prefixlen));
2286 srclen -= sizeof(prefixlen);
2287 src += sizeof(prefixlen);
2288
2289 memcpy(&prefix, src, sizeof(prefix));
2290 srclen -= sizeof(prefix);
2291 src += sizeof(prefix);
2292
2293 memcpy(&gateway6, src, sizeof(gateway6));
2294 srclen -= sizeof(gateway6);
2295 src += sizeof(gateway6);
2296
2297 if ((error = getnameinfo((struct sockaddr *)&gateway6,
2298 gateway6.sin6_len, hbuf, sizeof(hbuf), NULL((void*)0), 0,
2299 NI_NUMERICHOST1 | NI_NUMERICSERV2))) {
2300 warnx("cannot get gateway address: %s",
2301 gai_strerror(error));
2302 return;
2303 }
2304 printf("%s%s/%u %s ", first ? "" : ", ",
2305 inet_ntop(AF_INET624, &prefix, ntopbuf,
2306 INET6_ADDRSTRLEN46), prefixlen, hbuf);
2307 first = 0;
2308 }
2309 break;
2310 default:
2311 printf("<unknown address family %u>", rtstatic->sr_family);
2312 break;
2313 }
2314 printf("]");
2315}
2316
2317/*
2318 * Print RTM_PROPOSAL domain search list.
2319 */
2320void
2321print_rtsearch(struct sockaddr_rtsearch *rtsearch)
2322{
2323 char *src = rtsearch->sr_search;
2324 size_t srclen, offset;
2325
2326 offset = offsetof(struct sockaddr_rtsearch, sr_search)__builtin_offsetof(struct sockaddr_rtsearch, sr_search);
2327 if (rtsearch->sr_len <= offset) {
2328 printf("<invalid sr_len (%u <= %zu)>\n", rtsearch->sr_len,
2329 offset);
2330 return;
2331 }
2332 srclen = rtsearch->sr_len - offset;
2333 if (srclen > sizeof(rtsearch->sr_search)) {
2334 printf("<invalid sr_len (%zu > %zu)>\n", srclen,
2335 sizeof(rtsearch->sr_search));
2336 return;
2337 }
2338
2339 printf(" [%.*s]", (int)srclen, src);
2340}
2341
2342/*
2343 * Print RTM_80211INFO info.
2344 */
2345void
2346print_80211info(struct if_ieee80211_msghdr *ifim)
2347{
2348 unsigned int ascii, nwidlen, i;
2349 u_int8_t *nwid, *bssid;
2350
2351 ascii = 1;
2352 nwid = ifim->ifim_ifie.ifie_nwid;
2353 nwidlen = ifim->ifim_ifie.ifie_nwid_len;
2354 for (i = 0; i < nwidlen; i++) {
2355 if (i == 0)
2356 printf("nwid ");
2357 else
2358 printf(":");
2359 printf("%02x", nwid[i]);
2360 if (!isprint((unsigned int)nwid[i]))
2361 ascii = 0;
2362 }
2363 if (i > 0) {
2364 if (ascii == 1)
2365 printf(" (%.*s)", nwidlen, nwid);
2366 printf(", ");
2367 }
2368 printf("channel %u, ", ifim->ifim_ifie.ifie_channel);
2369 bssid = ifim->ifim_ifie.ifie_addr;
2370 printf("bssid %02x:%02x:%02x:%02x:%02x:%02x\n",
2371 bssid[0], bssid[1], bssid[2],
2372 bssid[3], bssid[4], bssid[5]);
2373 printf("flags:");
2374 bprintf(stdout(&__sF[1]), ifim->ifim_ifie.ifie_flags, ieee80211flags);
2375 printf("\nxflags:");
2376 bprintf(stdout(&__sF[1]), ifim->ifim_ifie.ifie_xflags, ieee80211xflags);
2377 printf("\n");
2378}