1ccf935ddSJun-ichiro itojun Hagino /* $FreeBSD$ */ 23174c1d4SHajimu UMEMOTO /* $KAME: ndp.c,v 1.104 2003/06/27 07:48:39 itojun Exp $ */ 3ccf935ddSJun-ichiro itojun Hagino 48a16b7a1SPedro F. Giffuni /*- 58a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 68a16b7a1SPedro F. Giffuni * 79a4365d0SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 89a4365d0SYoshinobu Inoue * All rights reserved. 99a4365d0SYoshinobu Inoue * 109a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 119a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 129a4365d0SYoshinobu Inoue * are met: 139a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 149a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 159a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 169a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 179a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 189a4365d0SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 199a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 209a4365d0SYoshinobu Inoue * without specific prior written permission. 219a4365d0SYoshinobu Inoue * 229a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 239a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 249a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 259a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 269a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 279a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 289a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 299a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 309a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 319a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 329a4365d0SYoshinobu Inoue * SUCH DAMAGE. 339a4365d0SYoshinobu Inoue */ 349a4365d0SYoshinobu Inoue /* 359a4365d0SYoshinobu Inoue * Copyright (c) 1984, 1993 369a4365d0SYoshinobu Inoue * The Regents of the University of California. All rights reserved. 379a4365d0SYoshinobu Inoue * 389a4365d0SYoshinobu Inoue * This code is derived from software contributed to Berkeley by 399a4365d0SYoshinobu Inoue * Sun Microsystems, Inc. 409a4365d0SYoshinobu Inoue * 419a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 429a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 439a4365d0SYoshinobu Inoue * are met: 449a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 459a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 469a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 479a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 489a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 49fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 509a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 519a4365d0SYoshinobu Inoue * without specific prior written permission. 529a4365d0SYoshinobu Inoue * 539a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 549a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 559a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 569a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 579a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 589a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 599a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 609a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 619a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 629a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 639a4365d0SYoshinobu Inoue * SUCH DAMAGE. 649a4365d0SYoshinobu Inoue */ 659a4365d0SYoshinobu Inoue 669a4365d0SYoshinobu Inoue /* 679a4365d0SYoshinobu Inoue * Based on: 689a4365d0SYoshinobu Inoue * "@(#) Copyright (c) 1984, 1993\n\ 699a4365d0SYoshinobu Inoue * The Regents of the University of California. All rights reserved.\n"; 709a4365d0SYoshinobu Inoue * 719a4365d0SYoshinobu Inoue * "@(#)arp.c 8.2 (Berkeley) 1/2/94"; 729a4365d0SYoshinobu Inoue */ 739a4365d0SYoshinobu Inoue 749a4365d0SYoshinobu Inoue /* 759a4365d0SYoshinobu Inoue * ndp - display, set, delete and flush neighbor cache 769a4365d0SYoshinobu Inoue */ 779a4365d0SYoshinobu Inoue 789a4365d0SYoshinobu Inoue 799a4365d0SYoshinobu Inoue #include <sys/param.h> 809a4365d0SYoshinobu Inoue #include <sys/file.h> 819a4365d0SYoshinobu Inoue #include <sys/ioctl.h> 829a4365d0SYoshinobu Inoue #include <sys/socket.h> 839a4365d0SYoshinobu Inoue #include <sys/sysctl.h> 84ffa0165aSHiroki Sato #include <sys/time.h> 8533841545SHajimu UMEMOTO #include <sys/queue.h> 869a4365d0SYoshinobu Inoue 879a4365d0SYoshinobu Inoue #include <net/if.h> 889a4365d0SYoshinobu Inoue #include <net/if_dl.h> 899a4365d0SYoshinobu Inoue #include <net/if_types.h> 909a4365d0SYoshinobu Inoue #include <net/route.h> 919a4365d0SYoshinobu Inoue 929a4365d0SYoshinobu Inoue #include <netinet/in.h> 939a4365d0SYoshinobu Inoue #include <netinet/if_ether.h> 949a4365d0SYoshinobu Inoue 959a4365d0SYoshinobu Inoue #include <netinet/icmp6.h> 969a4365d0SYoshinobu Inoue #include <netinet6/in6_var.h> 979a4365d0SYoshinobu Inoue #include <netinet6/nd6.h> 989a4365d0SYoshinobu Inoue 999a4365d0SYoshinobu Inoue #include <arpa/inet.h> 1009a4365d0SYoshinobu Inoue 101aa06c87eSAlexander V. Chernikov #include <ctype.h> 1029a4365d0SYoshinobu Inoue #include <netdb.h> 1039a4365d0SYoshinobu Inoue #include <errno.h> 1049a4365d0SYoshinobu Inoue #include <nlist.h> 1059a4365d0SYoshinobu Inoue #include <stdio.h> 1069a4365d0SYoshinobu Inoue #include <string.h> 1079a4365d0SYoshinobu Inoue #include <paths.h> 1089a4365d0SYoshinobu Inoue #include <err.h> 1099a4365d0SYoshinobu Inoue #include <stdlib.h> 1109a4365d0SYoshinobu Inoue #include <fcntl.h> 1119a4365d0SYoshinobu Inoue #include <unistd.h> 112*e1c7783eSAlexander V. Chernikov #include <libxo/xo.h> 1139a4365d0SYoshinobu Inoue #include "gmt2local.h" 1149a4365d0SYoshinobu Inoue 1156e6b3f7cSQing Li #define NEXTADDR(w, s) \ 1166e6b3f7cSQing Li if (rtm->rtm_addrs & (w)) { \ 117937f8ddfSRenato Botelho bcopy((char *)&s, cp, sizeof(s)); \ 118937f8ddfSRenato Botelho cp += SA_SIZE(&s); \ 119937f8ddfSRenato Botelho } 1206e6b3f7cSQing Li 12142f3352bSJuli Mallett static pid_t pid; 1229a4365d0SYoshinobu Inoue static int nflag; 1239a4365d0SYoshinobu Inoue static int tflag; 1249a4365d0SYoshinobu Inoue static int32_t thiszone; /* time difference with gmt */ 1259a4365d0SYoshinobu Inoue static int s = -1; 1269a4365d0SYoshinobu Inoue static int repeat = 0; 1279a4365d0SYoshinobu Inoue 128f2203c27SHiroki Sato static char host_buf[NI_MAXHOST]; /* getnameinfo() */ 129f2203c27SHiroki Sato static char ifix_buf[IFNAMSIZ]; /* if_indextoname() */ 1309a4365d0SYoshinobu Inoue 131aa06c87eSAlexander V. Chernikov static int file(char *); 132f2203c27SHiroki Sato static void getsocket(void); 133f2203c27SHiroki Sato static int set(int, char **); 134f2203c27SHiroki Sato static void get(char *); 135f2203c27SHiroki Sato static int delete(char *); 136f2203c27SHiroki Sato static void dump(struct sockaddr_in6 *, int); 137784bddbcSKevin Lo static struct in6_nbrinfo *getnbrinfo(struct in6_addr *, int, int); 138784bddbcSKevin Lo static char *ether_str(struct sockaddr_dl *); 139f2203c27SHiroki Sato static int ndp_ether_aton(char *, u_char *); 140f2203c27SHiroki Sato static void usage(void); 141f2203c27SHiroki Sato static int rtmsg(int); 142f2203c27SHiroki Sato static void ifinfo(char *, int, char **); 143f2203c27SHiroki Sato static void rtrlist(void); 144f2203c27SHiroki Sato static void plist(void); 145f2203c27SHiroki Sato static void pfx_flush(void); 146f2203c27SHiroki Sato static void rtr_flush(void); 147f2203c27SHiroki Sato static void harmonize_rtr(void); 148ccf935ddSJun-ichiro itojun Hagino #ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ 149784bddbcSKevin Lo static void getdefif(void); 150784bddbcSKevin Lo static void setdefif(char *); 151ccf935ddSJun-ichiro itojun Hagino #endif 152784bddbcSKevin Lo static char *sec2str(time_t); 153ffa0165aSHiroki Sato static void ts_print(const struct timeval *); 1549a4365d0SYoshinobu Inoue 1557ae43b31SRenato Botelho static const char *rtpref_str[] = { 15633841545SHajimu UMEMOTO "medium", /* 00 */ 15733841545SHajimu UMEMOTO "high", /* 01 */ 15833841545SHajimu UMEMOTO "rsv", /* 10 */ 15933841545SHajimu UMEMOTO "low" /* 11 */ 16033841545SHajimu UMEMOTO }; 1613174c1d4SHajimu UMEMOTO 162*e1c7783eSAlexander V. Chernikov #define NDP_XO_VERSION "1" 163*e1c7783eSAlexander V. Chernikov 1649a4365d0SYoshinobu Inoue int 165bfc75db0SAndrey V. Elsukov main(int argc, char **argv) 1669a4365d0SYoshinobu Inoue { 167f2203c27SHiroki Sato int ch, mode = 0; 168f2203c27SHiroki Sato char *arg = NULL; 1699a4365d0SYoshinobu Inoue 1709a4365d0SYoshinobu Inoue pid = getpid(); 1719a4365d0SYoshinobu Inoue thiszone = gmt2local(0); 172*e1c7783eSAlexander V. Chernikov 173*e1c7783eSAlexander V. Chernikov argc = xo_parse_args(argc, argv); 174*e1c7783eSAlexander V. Chernikov if (argc < 0) 175*e1c7783eSAlexander V. Chernikov exit(1); 176*e1c7783eSAlexander V. Chernikov xo_set_version(NDP_XO_VERSION); 177*e1c7783eSAlexander V. Chernikov xo_open_container("ndp"); 178*e1c7783eSAlexander V. Chernikov 1793174c1d4SHajimu UMEMOTO while ((ch = getopt(argc, argv, "acd:f:Ii:nprstA:HPR")) != -1) 180a96bd784SHajimu UMEMOTO switch (ch) { 1819a4365d0SYoshinobu Inoue case 'a': 1829a4365d0SYoshinobu Inoue case 'c': 1833174c1d4SHajimu UMEMOTO case 'p': 1843174c1d4SHajimu UMEMOTO case 'r': 1853174c1d4SHajimu UMEMOTO case 'H': 1863174c1d4SHajimu UMEMOTO case 'P': 1873174c1d4SHajimu UMEMOTO case 'R': 1883174c1d4SHajimu UMEMOTO case 's': 1893174c1d4SHajimu UMEMOTO case 'I': 1903174c1d4SHajimu UMEMOTO if (mode) { 1913174c1d4SHajimu UMEMOTO usage(); 1923174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 1933174c1d4SHajimu UMEMOTO } 1943174c1d4SHajimu UMEMOTO mode = ch; 1953174c1d4SHajimu UMEMOTO arg = NULL; 1969a4365d0SYoshinobu Inoue break; 1973174c1d4SHajimu UMEMOTO case 'f': 198aa06c87eSAlexander V. Chernikov exit(file(optarg) ? 1 : 0); 19901d5742fSPeter Wemm case 'd': 2009a4365d0SYoshinobu Inoue case 'i': 2013174c1d4SHajimu UMEMOTO if (mode) { 2029a4365d0SYoshinobu Inoue usage(); 2033174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2043174c1d4SHajimu UMEMOTO } 2053174c1d4SHajimu UMEMOTO mode = ch; 2063174c1d4SHajimu UMEMOTO arg = optarg; 2073174c1d4SHajimu UMEMOTO break; 2089a4365d0SYoshinobu Inoue case 'n': 2099a4365d0SYoshinobu Inoue nflag = 1; 2109a4365d0SYoshinobu Inoue break; 2119a4365d0SYoshinobu Inoue case 't': 2129a4365d0SYoshinobu Inoue tflag = 1; 2139a4365d0SYoshinobu Inoue break; 2149a4365d0SYoshinobu Inoue case 'A': 2153174c1d4SHajimu UMEMOTO if (mode) { 2169a4365d0SYoshinobu Inoue usage(); 2173174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2183174c1d4SHajimu UMEMOTO } 2193174c1d4SHajimu UMEMOTO mode = 'a'; 2203174c1d4SHajimu UMEMOTO repeat = atoi(optarg); 2213174c1d4SHajimu UMEMOTO if (repeat < 0) { 2223174c1d4SHajimu UMEMOTO usage(); 2233174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2243174c1d4SHajimu UMEMOTO } 2259a4365d0SYoshinobu Inoue break; 2269a4365d0SYoshinobu Inoue default: 2279a4365d0SYoshinobu Inoue usage(); 2289a4365d0SYoshinobu Inoue } 2299a4365d0SYoshinobu Inoue 2309a4365d0SYoshinobu Inoue argc -= optind; 2319a4365d0SYoshinobu Inoue argv += optind; 2329a4365d0SYoshinobu Inoue 2333174c1d4SHajimu UMEMOTO switch (mode) { 2343174c1d4SHajimu UMEMOTO case 'a': 2353174c1d4SHajimu UMEMOTO case 'c': 2363174c1d4SHajimu UMEMOTO if (argc != 0) { 2379a4365d0SYoshinobu Inoue usage(); 2383174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2399a4365d0SYoshinobu Inoue } 2403174c1d4SHajimu UMEMOTO dump(0, mode == 'c'); 2413174c1d4SHajimu UMEMOTO break; 2423174c1d4SHajimu UMEMOTO case 'd': 2433174c1d4SHajimu UMEMOTO if (argc != 0) { 2443174c1d4SHajimu UMEMOTO usage(); 2453174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2463174c1d4SHajimu UMEMOTO } 247*e1c7783eSAlexander V. Chernikov xo_open_list("neighbor-cache"); 2483174c1d4SHajimu UMEMOTO delete(arg); 249*e1c7783eSAlexander V. Chernikov xo_close_list("neighbor-cache"); 2503174c1d4SHajimu UMEMOTO break; 2513174c1d4SHajimu UMEMOTO case 'I': 2523174c1d4SHajimu UMEMOTO #ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ 2533174c1d4SHajimu UMEMOTO if (argc > 1) { 2543174c1d4SHajimu UMEMOTO usage(); 2553174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2563174c1d4SHajimu UMEMOTO } else if (argc == 1) { 2573174c1d4SHajimu UMEMOTO if (strcmp(*argv, "delete") == 0 || 2583174c1d4SHajimu UMEMOTO if_nametoindex(*argv)) 2593174c1d4SHajimu UMEMOTO setdefif(*argv); 2603174c1d4SHajimu UMEMOTO else 261*e1c7783eSAlexander V. Chernikov xo_errx(1, "invalid interface %s", *argv); 2623174c1d4SHajimu UMEMOTO } 2633174c1d4SHajimu UMEMOTO getdefif(); /* always call it to print the result */ 2643174c1d4SHajimu UMEMOTO break; 2653174c1d4SHajimu UMEMOTO #else 266*e1c7783eSAlexander V. Chernikov xo_errx(1, "not supported yet"); 2673174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2683174c1d4SHajimu UMEMOTO #endif 2693174c1d4SHajimu UMEMOTO case 'p': 2703174c1d4SHajimu UMEMOTO if (argc != 0) { 2713174c1d4SHajimu UMEMOTO usage(); 2723174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2733174c1d4SHajimu UMEMOTO } 2749a4365d0SYoshinobu Inoue plist(); 2753174c1d4SHajimu UMEMOTO break; 2763174c1d4SHajimu UMEMOTO case 'i': 2773174c1d4SHajimu UMEMOTO ifinfo(arg, argc, argv); 2783174c1d4SHajimu UMEMOTO break; 2793174c1d4SHajimu UMEMOTO case 'r': 2803174c1d4SHajimu UMEMOTO if (argc != 0) { 2813174c1d4SHajimu UMEMOTO usage(); 2823174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2839a4365d0SYoshinobu Inoue } 2849a4365d0SYoshinobu Inoue rtrlist(); 2853174c1d4SHajimu UMEMOTO break; 2863174c1d4SHajimu UMEMOTO case 's': 2879a4365d0SYoshinobu Inoue if (argc < 2 || argc > 4) 2889a4365d0SYoshinobu Inoue usage(); 2899a4365d0SYoshinobu Inoue exit(set(argc, argv) ? 1 : 0); 2903174c1d4SHajimu UMEMOTO case 'H': 2913174c1d4SHajimu UMEMOTO if (argc != 0) { 2929a4365d0SYoshinobu Inoue usage(); 2933174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 2943174c1d4SHajimu UMEMOTO } 2953174c1d4SHajimu UMEMOTO harmonize_rtr(); 2963174c1d4SHajimu UMEMOTO break; 2973174c1d4SHajimu UMEMOTO case 'P': 2983174c1d4SHajimu UMEMOTO if (argc != 0) { 2993174c1d4SHajimu UMEMOTO usage(); 3003174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 3013174c1d4SHajimu UMEMOTO } 3023174c1d4SHajimu UMEMOTO pfx_flush(); 3033174c1d4SHajimu UMEMOTO break; 3043174c1d4SHajimu UMEMOTO case 'R': 3053174c1d4SHajimu UMEMOTO if (argc != 0) { 3063174c1d4SHajimu UMEMOTO usage(); 3073174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 3083174c1d4SHajimu UMEMOTO } 3093174c1d4SHajimu UMEMOTO rtr_flush(); 3103174c1d4SHajimu UMEMOTO break; 3113174c1d4SHajimu UMEMOTO case 0: 3123174c1d4SHajimu UMEMOTO if (argc != 1) { 3133174c1d4SHajimu UMEMOTO usage(); 3143174c1d4SHajimu UMEMOTO /*NOTREACHED*/ 3153174c1d4SHajimu UMEMOTO } 3169a4365d0SYoshinobu Inoue get(argv[0]); 3173174c1d4SHajimu UMEMOTO break; 3183174c1d4SHajimu UMEMOTO } 319*e1c7783eSAlexander V. Chernikov xo_close_container("ndp"); 320*e1c7783eSAlexander V. Chernikov xo_finish(); 3219a4365d0SYoshinobu Inoue exit(0); 3229a4365d0SYoshinobu Inoue } 3239a4365d0SYoshinobu Inoue 3249a4365d0SYoshinobu Inoue /* 3259a4365d0SYoshinobu Inoue * Process a file to set standard ndp entries 3269a4365d0SYoshinobu Inoue */ 327aa06c87eSAlexander V. Chernikov static int 328bfc75db0SAndrey V. Elsukov file(char *name) 3299a4365d0SYoshinobu Inoue { 3309a4365d0SYoshinobu Inoue FILE *fp; 3319a4365d0SYoshinobu Inoue int i, retval; 332aa06c87eSAlexander V. Chernikov char line[100], arg[5][50], *args[5], *p; 3339a4365d0SYoshinobu Inoue 334aa06c87eSAlexander V. Chernikov if ((fp = fopen(name, "r")) == NULL) 335*e1c7783eSAlexander V. Chernikov xo_err(1, "cannot open %s", name); 3369a4365d0SYoshinobu Inoue args[0] = &arg[0][0]; 3379a4365d0SYoshinobu Inoue args[1] = &arg[1][0]; 3389a4365d0SYoshinobu Inoue args[2] = &arg[2][0]; 3399a4365d0SYoshinobu Inoue args[3] = &arg[3][0]; 3409a4365d0SYoshinobu Inoue args[4] = &arg[4][0]; 3419a4365d0SYoshinobu Inoue retval = 0; 342d0691403SKevin Lo while (fgets(line, sizeof(line), fp) != NULL) { 343aa06c87eSAlexander V. Chernikov if ((p = strchr(line, '#')) != NULL) 344aa06c87eSAlexander V. Chernikov *p = '\0'; 345aa06c87eSAlexander V. Chernikov for (p = line; isblank(*p); p++); 346aa06c87eSAlexander V. Chernikov if (*p == '\n' || *p == '\0') 347aa06c87eSAlexander V. Chernikov continue; 3483174c1d4SHajimu UMEMOTO i = sscanf(line, "%49s %49s %49s %49s %49s", 3493174c1d4SHajimu UMEMOTO arg[0], arg[1], arg[2], arg[3], arg[4]); 3509a4365d0SYoshinobu Inoue if (i < 2) { 351*e1c7783eSAlexander V. Chernikov xo_warnx("bad line: %s", line); 3529a4365d0SYoshinobu Inoue retval = 1; 3539a4365d0SYoshinobu Inoue continue; 3549a4365d0SYoshinobu Inoue } 3559a4365d0SYoshinobu Inoue if (set(i, args)) 3569a4365d0SYoshinobu Inoue retval = 1; 3579a4365d0SYoshinobu Inoue } 3589a4365d0SYoshinobu Inoue fclose(fp); 3599a4365d0SYoshinobu Inoue return (retval); 3609a4365d0SYoshinobu Inoue } 3619a4365d0SYoshinobu Inoue 362f2203c27SHiroki Sato static void 3639a4365d0SYoshinobu Inoue getsocket() 3649a4365d0SYoshinobu Inoue { 3659a4365d0SYoshinobu Inoue if (s < 0) { 3669a4365d0SYoshinobu Inoue s = socket(PF_ROUTE, SOCK_RAW, 0); 3679a4365d0SYoshinobu Inoue if (s < 0) { 368*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 369a96bd784SHajimu UMEMOTO /* NOTREACHED */ 3709a4365d0SYoshinobu Inoue } 3719a4365d0SYoshinobu Inoue } 3729a4365d0SYoshinobu Inoue } 3739a4365d0SYoshinobu Inoue 374f2203c27SHiroki Sato static struct sockaddr_in6 so_mask = { 375f2203c27SHiroki Sato .sin6_len = sizeof(so_mask), 376f2203c27SHiroki Sato .sin6_family = AF_INET6 377f2203c27SHiroki Sato }; 378f2203c27SHiroki Sato static struct sockaddr_in6 blank_sin = { 379f2203c27SHiroki Sato .sin6_len = sizeof(blank_sin), 380f2203c27SHiroki Sato .sin6_family = AF_INET6 381f2203c27SHiroki Sato }; 382f2203c27SHiroki Sato static struct sockaddr_in6 sin_m; 383f2203c27SHiroki Sato static struct sockaddr_dl blank_sdl = { 384f2203c27SHiroki Sato .sdl_len = sizeof(blank_sdl), 385f2203c27SHiroki Sato .sdl_family = AF_LINK 386f2203c27SHiroki Sato }; 387f2203c27SHiroki Sato static struct sockaddr_dl sdl_m; 388f2203c27SHiroki Sato static time_t expire_time; 389f2203c27SHiroki Sato static int flags, found_entry; 390f2203c27SHiroki Sato static struct { 3919a4365d0SYoshinobu Inoue struct rt_msghdr m_rtm; 3929a4365d0SYoshinobu Inoue char m_space[512]; 3939a4365d0SYoshinobu Inoue } m_rtmsg; 3949a4365d0SYoshinobu Inoue 3959a4365d0SYoshinobu Inoue /* 3969a4365d0SYoshinobu Inoue * Set an individual neighbor cache entry 3979a4365d0SYoshinobu Inoue */ 398f2203c27SHiroki Sato static int 399bfc75db0SAndrey V. Elsukov set(int argc, char **argv) 4009a4365d0SYoshinobu Inoue { 4019a4365d0SYoshinobu Inoue register struct sockaddr_in6 *sin = &sin_m; 4029a4365d0SYoshinobu Inoue register struct sockaddr_dl *sdl; 4039a4365d0SYoshinobu Inoue register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); 4049a4365d0SYoshinobu Inoue struct addrinfo hints, *res; 4059a4365d0SYoshinobu Inoue int gai_error; 4069a4365d0SYoshinobu Inoue u_char *ea; 4079a4365d0SYoshinobu Inoue char *host = argv[0], *eaddr = argv[1]; 4089a4365d0SYoshinobu Inoue 4099a4365d0SYoshinobu Inoue getsocket(); 4109a4365d0SYoshinobu Inoue argc -= 2; 4119a4365d0SYoshinobu Inoue argv += 2; 4129a4365d0SYoshinobu Inoue sdl_m = blank_sdl; 4139a4365d0SYoshinobu Inoue sin_m = blank_sin; 4149a4365d0SYoshinobu Inoue 4159a4365d0SYoshinobu Inoue bzero(&hints, sizeof(hints)); 4169a4365d0SYoshinobu Inoue hints.ai_family = AF_INET6; 4179a4365d0SYoshinobu Inoue gai_error = getaddrinfo(host, NULL, &hints, &res); 4189a4365d0SYoshinobu Inoue if (gai_error) { 419*e1c7783eSAlexander V. Chernikov xo_warnx("%s: %s", host, gai_strerror(gai_error)); 4209a4365d0SYoshinobu Inoue return 1; 4219a4365d0SYoshinobu Inoue } 4229a4365d0SYoshinobu Inoue sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; 4230bebb544SHiroki Sato sin->sin6_scope_id = 4240bebb544SHiroki Sato ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 4259a4365d0SYoshinobu Inoue ea = (u_char *)LLADDR(&sdl_m); 4269a4365d0SYoshinobu Inoue if (ndp_ether_aton(eaddr, ea) == 0) 4279a4365d0SYoshinobu Inoue sdl_m.sdl_alen = 6; 4289a4365d0SYoshinobu Inoue flags = expire_time = 0; 4299a4365d0SYoshinobu Inoue while (argc-- > 0) { 4309a4365d0SYoshinobu Inoue if (strncmp(argv[0], "temp", 4) == 0) { 431ffa0165aSHiroki Sato struct timeval now; 432a96bd784SHajimu UMEMOTO 433ffa0165aSHiroki Sato gettimeofday(&now, 0); 4347d26db17SHiroki Sato expire_time = now.tv_sec + 20 * 60; 435ccf935ddSJun-ichiro itojun Hagino } else if (strncmp(argv[0], "proxy", 5) == 0) 436ccf935ddSJun-ichiro itojun Hagino flags |= RTF_ANNOUNCE; 4379a4365d0SYoshinobu Inoue argv++; 4389a4365d0SYoshinobu Inoue } 4399a4365d0SYoshinobu Inoue if (rtmsg(RTM_GET) < 0) { 440*e1c7783eSAlexander V. Chernikov xo_errx(1, "RTM_GET(%s) failed", host); 441a96bd784SHajimu UMEMOTO /* NOTREACHED */ 4429a4365d0SYoshinobu Inoue } 4439a4365d0SYoshinobu Inoue sin = (struct sockaddr_in6 *)(rtm + 1); 4442a81c6f1SAndrey V. Elsukov sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin); 4459a4365d0SYoshinobu Inoue if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) { 4469a4365d0SYoshinobu Inoue if (sdl->sdl_family == AF_LINK && 4473174c1d4SHajimu UMEMOTO !(rtm->rtm_flags & RTF_GATEWAY)) { 4483174c1d4SHajimu UMEMOTO switch (sdl->sdl_type) { 4499a4365d0SYoshinobu Inoue case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: 4509a4365d0SYoshinobu Inoue case IFT_ISO88024: case IFT_ISO88025: 451d99d8e2eSJohn Baldwin case IFT_L2VLAN: case IFT_BRIDGE: 4529a4365d0SYoshinobu Inoue goto overwrite; 4539a4365d0SYoshinobu Inoue } 4543174c1d4SHajimu UMEMOTO } 455*e1c7783eSAlexander V. Chernikov xo_warnx("cannot configure a new entry"); 456ccf935ddSJun-ichiro itojun Hagino return 1; 4579a4365d0SYoshinobu Inoue } 458ccf935ddSJun-ichiro itojun Hagino 4599a4365d0SYoshinobu Inoue overwrite: 4609a4365d0SYoshinobu Inoue if (sdl->sdl_family != AF_LINK) { 461*e1c7783eSAlexander V. Chernikov xo_warnx("cannot intuit interface index and type for %s", host); 4629a4365d0SYoshinobu Inoue return (1); 4639a4365d0SYoshinobu Inoue } 4649a4365d0SYoshinobu Inoue sdl_m.sdl_type = sdl->sdl_type; 4659a4365d0SYoshinobu Inoue sdl_m.sdl_index = sdl->sdl_index; 4669a4365d0SYoshinobu Inoue return (rtmsg(RTM_ADD)); 4679a4365d0SYoshinobu Inoue } 4689a4365d0SYoshinobu Inoue 4699a4365d0SYoshinobu Inoue /* 4709a4365d0SYoshinobu Inoue * Display an individual neighbor cache entry 4719a4365d0SYoshinobu Inoue */ 472f2203c27SHiroki Sato static void 473bfc75db0SAndrey V. Elsukov get(char *host) 4749a4365d0SYoshinobu Inoue { 4759a4365d0SYoshinobu Inoue struct sockaddr_in6 *sin = &sin_m; 4769a4365d0SYoshinobu Inoue struct addrinfo hints, *res; 4779a4365d0SYoshinobu Inoue int gai_error; 4789a4365d0SYoshinobu Inoue 4799a4365d0SYoshinobu Inoue sin_m = blank_sin; 4809a4365d0SYoshinobu Inoue bzero(&hints, sizeof(hints)); 4819a4365d0SYoshinobu Inoue hints.ai_family = AF_INET6; 4829a4365d0SYoshinobu Inoue gai_error = getaddrinfo(host, NULL, &hints, &res); 4839a4365d0SYoshinobu Inoue if (gai_error) { 484*e1c7783eSAlexander V. Chernikov xo_warnx("%s: %s", host, gai_strerror(gai_error)); 4859a4365d0SYoshinobu Inoue return; 4869a4365d0SYoshinobu Inoue } 4879a4365d0SYoshinobu Inoue sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; 488b1d9695cSAndrey V. Elsukov sin->sin6_scope_id = 489b1d9695cSAndrey V. Elsukov ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 490b1d9695cSAndrey V. Elsukov dump(sin, 0); 4919a4365d0SYoshinobu Inoue if (found_entry == 0) { 4929a4365d0SYoshinobu Inoue getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf, 4939a4365d0SYoshinobu Inoue sizeof(host_buf), NULL ,0, 494a96bd784SHajimu UMEMOTO (nflag ? NI_NUMERICHOST : 0)); 495*e1c7783eSAlexander V. Chernikov xo_errx(1, "%s (%s) -- no entry", host, host_buf); 4969a4365d0SYoshinobu Inoue } 4979a4365d0SYoshinobu Inoue } 4989a4365d0SYoshinobu Inoue 4999a4365d0SYoshinobu Inoue /* 5009a4365d0SYoshinobu Inoue * Delete a neighbor cache entry 5019a4365d0SYoshinobu Inoue */ 502f2203c27SHiroki Sato static int 503bfc75db0SAndrey V. Elsukov delete(char *host) 5049a4365d0SYoshinobu Inoue { 5059a4365d0SYoshinobu Inoue struct sockaddr_in6 *sin = &sin_m; 5069a4365d0SYoshinobu Inoue register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; 5076e6b3f7cSQing Li register char *cp = m_rtmsg.m_space; 5089a4365d0SYoshinobu Inoue struct sockaddr_dl *sdl; 5099a4365d0SYoshinobu Inoue struct addrinfo hints, *res; 5109a4365d0SYoshinobu Inoue int gai_error; 5119a4365d0SYoshinobu Inoue 5129a4365d0SYoshinobu Inoue getsocket(); 5139a4365d0SYoshinobu Inoue sin_m = blank_sin; 5149a4365d0SYoshinobu Inoue 5159a4365d0SYoshinobu Inoue bzero(&hints, sizeof(hints)); 5169a4365d0SYoshinobu Inoue hints.ai_family = AF_INET6; 5179a4365d0SYoshinobu Inoue gai_error = getaddrinfo(host, NULL, &hints, &res); 5189a4365d0SYoshinobu Inoue if (gai_error) { 519*e1c7783eSAlexander V. Chernikov xo_warnx("%s: %s", host, gai_strerror(gai_error)); 5209a4365d0SYoshinobu Inoue return 1; 5219a4365d0SYoshinobu Inoue } 5229a4365d0SYoshinobu Inoue sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; 5230bebb544SHiroki Sato sin->sin6_scope_id = 5240bebb544SHiroki Sato ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 5259a4365d0SYoshinobu Inoue if (rtmsg(RTM_GET) < 0) { 526*e1c7783eSAlexander V. Chernikov xo_errx(1, "RTM_GET(%s) failed", host); 527a96bd784SHajimu UMEMOTO /* NOTREACHED */ 5289a4365d0SYoshinobu Inoue } 5299a4365d0SYoshinobu Inoue sin = (struct sockaddr_in6 *)(rtm + 1); 5302a81c6f1SAndrey V. Elsukov sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin); 5319a4365d0SYoshinobu Inoue if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) { 5329a4365d0SYoshinobu Inoue if (sdl->sdl_family == AF_LINK && 533ccf935ddSJun-ichiro itojun Hagino !(rtm->rtm_flags & RTF_GATEWAY)) { 5349a4365d0SYoshinobu Inoue goto delete; 5359a4365d0SYoshinobu Inoue } 536*e1c7783eSAlexander V. Chernikov xo_warnx("delete: cannot delete non-NDP entry"); 537ccf935ddSJun-ichiro itojun Hagino return 1; 538ccf935ddSJun-ichiro itojun Hagino } 539ccf935ddSJun-ichiro itojun Hagino 5409a4365d0SYoshinobu Inoue delete: 5419a4365d0SYoshinobu Inoue if (sdl->sdl_family != AF_LINK) { 542*e1c7783eSAlexander V. Chernikov xo_warnx("cannot locate %s", host); 5439a4365d0SYoshinobu Inoue return (1); 5449a4365d0SYoshinobu Inoue } 5456e6b3f7cSQing Li /* 5466e6b3f7cSQing Li * need to reinit the field because it has rt_key 5476e6b3f7cSQing Li * but we want the actual address 5486e6b3f7cSQing Li */ 5496e6b3f7cSQing Li NEXTADDR(RTA_DST, sin_m); 5508eca593cSQing Li rtm->rtm_flags |= RTF_LLDATA; 5519a4365d0SYoshinobu Inoue if (rtmsg(RTM_DELETE) == 0) { 5520bebb544SHiroki Sato getnameinfo((struct sockaddr *)sin, 5530bebb544SHiroki Sato sin->sin6_len, host_buf, 5549a4365d0SYoshinobu Inoue sizeof(host_buf), NULL, 0, 555a96bd784SHajimu UMEMOTO (nflag ? NI_NUMERICHOST : 0)); 556*e1c7783eSAlexander V. Chernikov xo_open_instance("neighbor-cache"); 557*e1c7783eSAlexander V. Chernikov 558*e1c7783eSAlexander V. Chernikov char *ifname = if_indextoname(sdl->sdl_index, ifix_buf); 559*e1c7783eSAlexander V. Chernikov if (ifname == NULL) { 560*e1c7783eSAlexander V. Chernikov strlcpy(ifix_buf, "?", sizeof(ifix_buf)); 561*e1c7783eSAlexander V. Chernikov ifname = ifix_buf; 562*e1c7783eSAlexander V. Chernikov } 563*e1c7783eSAlexander V. Chernikov char abuf[INET6_ADDRSTRLEN]; 564*e1c7783eSAlexander V. Chernikov inet_ntop(AF_INET6, &sin->sin6_addr, abuf, sizeof(abuf)); 565*e1c7783eSAlexander V. Chernikov 566*e1c7783eSAlexander V. Chernikov xo_emit("{:hostname/%s}{d:/ (%s) deleted\n}", host, host_buf); 567*e1c7783eSAlexander V. Chernikov xo_emit("{e:address/%s}{e:interface/%s}", abuf, ifname); 568*e1c7783eSAlexander V. Chernikov xo_close_instance("neighbor-cache"); 5699a4365d0SYoshinobu Inoue } 5709a4365d0SYoshinobu Inoue 5719a4365d0SYoshinobu Inoue return 0; 5729a4365d0SYoshinobu Inoue } 5739a4365d0SYoshinobu Inoue 5743174c1d4SHajimu UMEMOTO #define W_ADDR 36 57533841545SHajimu UMEMOTO #define W_LL 17 57633841545SHajimu UMEMOTO #define W_IF 6 57733841545SHajimu UMEMOTO 5789a4365d0SYoshinobu Inoue /* 5799a4365d0SYoshinobu Inoue * Dump the entire neighbor cache 5809a4365d0SYoshinobu Inoue */ 581f2203c27SHiroki Sato static void 582b1d9695cSAndrey V. Elsukov dump(struct sockaddr_in6 *addr, int cflag) 5839a4365d0SYoshinobu Inoue { 5849a4365d0SYoshinobu Inoue int mib[6]; 5859a4365d0SYoshinobu Inoue size_t needed; 586ccf935ddSJun-ichiro itojun Hagino char *lim, *buf, *next; 5879a4365d0SYoshinobu Inoue struct rt_msghdr *rtm; 5889a4365d0SYoshinobu Inoue struct sockaddr_in6 *sin; 5899a4365d0SYoshinobu Inoue struct sockaddr_dl *sdl; 590ffa0165aSHiroki Sato struct timeval now; 5917ae43b31SRenato Botelho time_t expire; 5929a4365d0SYoshinobu Inoue int addrwidth; 59333841545SHajimu UMEMOTO int llwidth; 59433841545SHajimu UMEMOTO int ifwidth; 595ccf935ddSJun-ichiro itojun Hagino char flgbuf[8]; 59633841545SHajimu UMEMOTO char *ifname; 5979a4365d0SYoshinobu Inoue 5989a4365d0SYoshinobu Inoue /* Print header */ 599*e1c7783eSAlexander V. Chernikov if (!tflag && !cflag) { 600*e1c7783eSAlexander V. Chernikov char xobuf[200]; 601*e1c7783eSAlexander V. Chernikov snprintf(xobuf, sizeof(xobuf), 602*e1c7783eSAlexander V. Chernikov "{T:/%%-%d.%ds} {T:/%%-%d.%ds} {T:/%%%d.%ds} {T:/%%-9.9s} {T:%%1s} {T:%%5s}\n", 603*e1c7783eSAlexander V. Chernikov W_ADDR, W_ADDR, W_LL, W_LL, W_IF, W_IF); 604*e1c7783eSAlexander V. Chernikov xo_emit(xobuf, "Neighbor", "Linklayer Address", "Netif", "Expire", "S", "Flags"); 605*e1c7783eSAlexander V. Chernikov } 606*e1c7783eSAlexander V. Chernikov xo_open_list("neighbor-cache"); 6079a4365d0SYoshinobu Inoue again:; 6089a4365d0SYoshinobu Inoue mib[0] = CTL_NET; 6099a4365d0SYoshinobu Inoue mib[1] = PF_ROUTE; 6109a4365d0SYoshinobu Inoue mib[2] = 0; 6119a4365d0SYoshinobu Inoue mib[3] = AF_INET6; 6129a4365d0SYoshinobu Inoue mib[4] = NET_RT_FLAGS; 6136e6b3f7cSQing Li #ifdef RTF_LLINFO 6149a4365d0SYoshinobu Inoue mib[5] = RTF_LLINFO; 6156e6b3f7cSQing Li #else 6166e6b3f7cSQing Li mib[5] = 0; 6176e6b3f7cSQing Li #endif 6189a4365d0SYoshinobu Inoue if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 619*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(PF_ROUTE estimate)"); 6209a4365d0SYoshinobu Inoue if (needed > 0) { 6219a4365d0SYoshinobu Inoue if ((buf = malloc(needed)) == NULL) 622*e1c7783eSAlexander V. Chernikov xo_err(1, "malloc"); 6239a4365d0SYoshinobu Inoue if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 624*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(PF_ROUTE, NET_RT_FLAGS)"); 6259a4365d0SYoshinobu Inoue lim = buf + needed; 6269a4365d0SYoshinobu Inoue } else 6279a4365d0SYoshinobu Inoue buf = lim = NULL; 6289a4365d0SYoshinobu Inoue 6299a4365d0SYoshinobu Inoue for (next = buf; next && next < lim; next += rtm->rtm_msglen) { 6309a4365d0SYoshinobu Inoue int isrouter = 0, prbs = 0; 6319a4365d0SYoshinobu Inoue 6329a4365d0SYoshinobu Inoue rtm = (struct rt_msghdr *)next; 6339a4365d0SYoshinobu Inoue sin = (struct sockaddr_in6 *)(rtm + 1); 634937f8ddfSRenato Botelho sdl = (struct sockaddr_dl *)((char *)sin + 635937f8ddfSRenato Botelho ALIGN(sin->sin6_len)); 63633841545SHajimu UMEMOTO 63733841545SHajimu UMEMOTO /* 63833841545SHajimu UMEMOTO * Some OSes can produce a route that has the LINK flag but 63933841545SHajimu UMEMOTO * has a non-AF_LINK gateway (e.g. fe80::xx%lo0 on FreeBSD 64033841545SHajimu UMEMOTO * and BSD/OS, where xx is not the interface identifier on 64133841545SHajimu UMEMOTO * lo0). Such routes entry would annoy getnbrinfo() below, 64233841545SHajimu UMEMOTO * so we skip them. 64333841545SHajimu UMEMOTO * XXX: such routes should have the GATEWAY flag, not the 644a96bd784SHajimu UMEMOTO * LINK flag. However, there is rotten routing software 64533841545SHajimu UMEMOTO * that advertises all routes that have the GATEWAY flag. 64633841545SHajimu UMEMOTO * Thus, KAME kernel intentionally does not set the LINK flag. 64733841545SHajimu UMEMOTO * What is to be fixed is not ndp, but such routing software 64833841545SHajimu UMEMOTO * (and the kernel workaround)... 64933841545SHajimu UMEMOTO */ 65033841545SHajimu UMEMOTO if (sdl->sdl_family != AF_LINK) 65133841545SHajimu UMEMOTO continue; 65233841545SHajimu UMEMOTO 6533174c1d4SHajimu UMEMOTO if (!(rtm->rtm_flags & RTF_HOST)) 6543174c1d4SHajimu UMEMOTO continue; 6553174c1d4SHajimu UMEMOTO 6569a4365d0SYoshinobu Inoue if (addr) { 657b1d9695cSAndrey V. Elsukov if (IN6_ARE_ADDR_EQUAL(&addr->sin6_addr, 658b1d9695cSAndrey V. Elsukov &sin->sin6_addr) == 0 || 659b1d9695cSAndrey V. Elsukov addr->sin6_scope_id != sin->sin6_scope_id) 6609a4365d0SYoshinobu Inoue continue; 6619a4365d0SYoshinobu Inoue found_entry = 1; 6629a4365d0SYoshinobu Inoue } else if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr)) 6639a4365d0SYoshinobu Inoue continue; 6649a4365d0SYoshinobu Inoue if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) || 6659a4365d0SYoshinobu Inoue IN6_IS_ADDR_MC_LINKLOCAL(&sin->sin6_addr)) { 6669a4365d0SYoshinobu Inoue /* XXX: should scope id be filled in the kernel? */ 6679a4365d0SYoshinobu Inoue if (sin->sin6_scope_id == 0) 6689a4365d0SYoshinobu Inoue sin->sin6_scope_id = sdl->sdl_index; 6699a4365d0SYoshinobu Inoue } 6709a4365d0SYoshinobu Inoue getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf, 671a96bd784SHajimu UMEMOTO sizeof(host_buf), NULL, 0, (nflag ? NI_NUMERICHOST : 0)); 6723174c1d4SHajimu UMEMOTO if (cflag) { 673220f01cdSMunechika SUMIKAWA #ifdef RTF_WASCLONED 674220f01cdSMunechika SUMIKAWA if (rtm->rtm_flags & RTF_WASCLONED) 67502647224SMunechika SUMIKAWA delete(host_buf); 6763174c1d4SHajimu UMEMOTO #elif defined(RTF_CLONED) 6773174c1d4SHajimu UMEMOTO if (rtm->rtm_flags & RTF_CLONED) 6783174c1d4SHajimu UMEMOTO delete(host_buf); 679220f01cdSMunechika SUMIKAWA #else 6804a336ef4SAlexander V. Chernikov if (rtm->rtm_flags & RTF_PINNED) 6814a336ef4SAlexander V. Chernikov continue; 682220f01cdSMunechika SUMIKAWA delete(host_buf); 683220f01cdSMunechika SUMIKAWA #endif 68402647224SMunechika SUMIKAWA continue; 68502647224SMunechika SUMIKAWA } 686ffa0165aSHiroki Sato gettimeofday(&now, 0); 6879a4365d0SYoshinobu Inoue if (tflag) 6887d26db17SHiroki Sato ts_print(&now); 6899a4365d0SYoshinobu Inoue 6909a4365d0SYoshinobu Inoue addrwidth = strlen(host_buf); 69133841545SHajimu UMEMOTO if (addrwidth < W_ADDR) 69233841545SHajimu UMEMOTO addrwidth = W_ADDR; 69333841545SHajimu UMEMOTO llwidth = strlen(ether_str(sdl)); 69433841545SHajimu UMEMOTO if (W_ADDR + W_LL - addrwidth > llwidth) 69533841545SHajimu UMEMOTO llwidth = W_ADDR + W_LL - addrwidth; 69633841545SHajimu UMEMOTO ifname = if_indextoname(sdl->sdl_index, ifix_buf); 6977ae43b31SRenato Botelho if (ifname == NULL) { 6987ae43b31SRenato Botelho strlcpy(ifix_buf, "?", sizeof(ifix_buf)); 6997ae43b31SRenato Botelho ifname = ifix_buf; 7007ae43b31SRenato Botelho } 70133841545SHajimu UMEMOTO ifwidth = strlen(ifname); 70233841545SHajimu UMEMOTO if (W_ADDR + W_LL + W_IF - addrwidth - llwidth > ifwidth) 70333841545SHajimu UMEMOTO ifwidth = W_ADDR + W_LL + W_IF - addrwidth - llwidth; 7049a4365d0SYoshinobu Inoue 705*e1c7783eSAlexander V. Chernikov xo_open_instance("neighbor-cache"); 706*e1c7783eSAlexander V. Chernikov /* Compose format string for libxo, as it doesn't support *.* */ 707*e1c7783eSAlexander V. Chernikov char xobuf[200]; 708*e1c7783eSAlexander V. Chernikov snprintf(xobuf, sizeof(xobuf), 709*e1c7783eSAlexander V. Chernikov "{:address/%%-%d.%ds/%%s} {:mac-address/%%-%d.%ds/%%s} {:interface/%%%d.%ds/%%s}", 710*e1c7783eSAlexander V. Chernikov addrwidth, addrwidth, llwidth, llwidth, ifwidth, ifwidth); 711*e1c7783eSAlexander V. Chernikov xo_emit(xobuf, host_buf, ether_str(sdl), ifname); 7129a4365d0SYoshinobu Inoue 713463a577bSEitan Adler /* Print neighbor discovery specific information */ 714427c2f4eSAlexander V. Chernikov expire = rtm->rtm_rmx.rmx_expire; 715*e1c7783eSAlexander V. Chernikov int expire_in = expire - now.tv_sec; 716427c2f4eSAlexander V. Chernikov if (expire > now.tv_sec) 717*e1c7783eSAlexander V. Chernikov xo_emit("{d:/ %-9.9s}{e:expires_sec/%d}", sec2str(expire_in), expire_in); 718427c2f4eSAlexander V. Chernikov else if (expire == 0) 719*e1c7783eSAlexander V. Chernikov xo_emit("{d:/ %-9.9s}{en:permanent/true}", "permanent"); 7209a4365d0SYoshinobu Inoue else 721*e1c7783eSAlexander V. Chernikov xo_emit("{d:/ %-9.9s}{e:expires_sec/%d}", "expired", expire_in); 7229a4365d0SYoshinobu Inoue 723*e1c7783eSAlexander V. Chernikov char *lle_state = ""; 724427c2f4eSAlexander V. Chernikov switch (rtm->rtm_rmx.rmx_state) { 7259a4365d0SYoshinobu Inoue case ND6_LLINFO_NOSTATE: 726*e1c7783eSAlexander V. Chernikov lle_state = "N"; 7279a4365d0SYoshinobu Inoue break; 72833841545SHajimu UMEMOTO #ifdef ND6_LLINFO_WAITDELETE 7299a4365d0SYoshinobu Inoue case ND6_LLINFO_WAITDELETE: 730*e1c7783eSAlexander V. Chernikov lle_state = "W"; 7319a4365d0SYoshinobu Inoue break; 73233841545SHajimu UMEMOTO #endif 7339a4365d0SYoshinobu Inoue case ND6_LLINFO_INCOMPLETE: 734*e1c7783eSAlexander V. Chernikov lle_state = "I"; 7359a4365d0SYoshinobu Inoue break; 7369a4365d0SYoshinobu Inoue case ND6_LLINFO_REACHABLE: 737*e1c7783eSAlexander V. Chernikov lle_state = "R"; 7389a4365d0SYoshinobu Inoue break; 7399a4365d0SYoshinobu Inoue case ND6_LLINFO_STALE: 740*e1c7783eSAlexander V. Chernikov lle_state = "S"; 7419a4365d0SYoshinobu Inoue break; 7429a4365d0SYoshinobu Inoue case ND6_LLINFO_DELAY: 743*e1c7783eSAlexander V. Chernikov lle_state = "D"; 7449a4365d0SYoshinobu Inoue break; 7459a4365d0SYoshinobu Inoue case ND6_LLINFO_PROBE: 746*e1c7783eSAlexander V. Chernikov lle_state = "P"; 7479a4365d0SYoshinobu Inoue break; 7489a4365d0SYoshinobu Inoue default: 749*e1c7783eSAlexander V. Chernikov lle_state = "?"; 7509a4365d0SYoshinobu Inoue break; 7519a4365d0SYoshinobu Inoue } 752*e1c7783eSAlexander V. Chernikov xo_emit(" {:neighbor-state/%s}", lle_state); 7539a4365d0SYoshinobu Inoue 754427c2f4eSAlexander V. Chernikov isrouter = rtm->rtm_flags & RTF_GATEWAY; 755427c2f4eSAlexander V. Chernikov prbs = rtm->rtm_rmx.rmx_pksent; 7569a4365d0SYoshinobu Inoue 757ccf935ddSJun-ichiro itojun Hagino /* 758ccf935ddSJun-ichiro itojun Hagino * other flags. R: router, P: proxy, W: ?? 759ccf935ddSJun-ichiro itojun Hagino */ 760ccf935ddSJun-ichiro itojun Hagino if ((rtm->rtm_addrs & RTA_NETMASK) == 0) { 761ccf935ddSJun-ichiro itojun Hagino snprintf(flgbuf, sizeof(flgbuf), "%s%s", 762ccf935ddSJun-ichiro itojun Hagino isrouter ? "R" : "", 763ccf935ddSJun-ichiro itojun Hagino (rtm->rtm_flags & RTF_ANNOUNCE) ? "p" : ""); 764ccf935ddSJun-ichiro itojun Hagino } else { 76599e46388SXin LI #if 0 /* W and P are mystery even for us */ 7669a4365d0SYoshinobu Inoue sin = (struct sockaddr_in6 *) 7679a4365d0SYoshinobu Inoue (sdl->sdl_len + (char *)sdl); 768ccf935ddSJun-ichiro itojun Hagino snprintf(flgbuf, sizeof(flgbuf), "%s%s%s%s", 769ccf935ddSJun-ichiro itojun Hagino isrouter ? "R" : "", 770a96bd784SHajimu UMEMOTO !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr) ? "P" : "", 771a96bd784SHajimu UMEMOTO (sin->sin6_len != sizeof(struct sockaddr_in6)) ? "W" : "", 772ccf935ddSJun-ichiro itojun Hagino (rtm->rtm_flags & RTF_ANNOUNCE) ? "p" : ""); 7733174c1d4SHajimu UMEMOTO #else 7743174c1d4SHajimu UMEMOTO snprintf(flgbuf, sizeof(flgbuf), "%s%s", 7753174c1d4SHajimu UMEMOTO isrouter ? "R" : "", 7763174c1d4SHajimu UMEMOTO (rtm->rtm_flags & RTF_ANNOUNCE) ? "p" : ""); 7773174c1d4SHajimu UMEMOTO #endif 7789a4365d0SYoshinobu Inoue } 779*e1c7783eSAlexander V. Chernikov xo_emit(" {:nd-flags/%s}", flgbuf); 7809a4365d0SYoshinobu Inoue 7819a4365d0SYoshinobu Inoue if (prbs) 782*e1c7783eSAlexander V. Chernikov xo_emit("{d:/ %d}", prbs); 7839a4365d0SYoshinobu Inoue 784*e1c7783eSAlexander V. Chernikov xo_emit("\n"); 785*e1c7783eSAlexander V. Chernikov xo_close_instance("neighbor-cache"); 7869a4365d0SYoshinobu Inoue } 78733841545SHajimu UMEMOTO if (buf != NULL) 78833841545SHajimu UMEMOTO free(buf); 7899a4365d0SYoshinobu Inoue 7909a4365d0SYoshinobu Inoue if (repeat) { 791*e1c7783eSAlexander V. Chernikov xo_emit("\n"); 792*e1c7783eSAlexander V. Chernikov xo_flush(); 7939a4365d0SYoshinobu Inoue sleep(repeat); 7949a4365d0SYoshinobu Inoue goto again; 7959a4365d0SYoshinobu Inoue } 796*e1c7783eSAlexander V. Chernikov 797*e1c7783eSAlexander V. Chernikov xo_close_list("neighbor-cache"); 7989a4365d0SYoshinobu Inoue } 7999a4365d0SYoshinobu Inoue 8009a4365d0SYoshinobu Inoue static struct in6_nbrinfo * 801bfc75db0SAndrey V. Elsukov getnbrinfo(struct in6_addr *addr, int ifindex, int warning) 8029a4365d0SYoshinobu Inoue { 8039a4365d0SYoshinobu Inoue static struct in6_nbrinfo nbi; 8047ae43b31SRenato Botelho int sock; 8059a4365d0SYoshinobu Inoue 8067ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 807*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 8089a4365d0SYoshinobu Inoue 8099a4365d0SYoshinobu Inoue bzero(&nbi, sizeof(nbi)); 8109a4365d0SYoshinobu Inoue if_indextoname(ifindex, nbi.ifname); 8119a4365d0SYoshinobu Inoue nbi.addr = *addr; 8127ae43b31SRenato Botelho if (ioctl(sock, SIOCGNBRINFO_IN6, (caddr_t)&nbi) < 0) { 813ccf935ddSJun-ichiro itojun Hagino if (warning) 814*e1c7783eSAlexander V. Chernikov xo_warn("ioctl(SIOCGNBRINFO_IN6)"); 8157ae43b31SRenato Botelho close(sock); 8169a4365d0SYoshinobu Inoue return(NULL); 8179a4365d0SYoshinobu Inoue } 8189a4365d0SYoshinobu Inoue 8197ae43b31SRenato Botelho close(sock); 8209a4365d0SYoshinobu Inoue return(&nbi); 8219a4365d0SYoshinobu Inoue } 8229a4365d0SYoshinobu Inoue 8239a4365d0SYoshinobu Inoue static char * 82497f8d655SXin LI ether_str(struct sockaddr_dl *sdl) 8259a4365d0SYoshinobu Inoue { 826a96bd784SHajimu UMEMOTO static char hbuf[NI_MAXHOST]; 8279a4365d0SYoshinobu Inoue 828e4cd31ddSJeff Roberson if (sdl->sdl_alen == ETHER_ADDR_LEN) { 82997f8d655SXin LI strlcpy(hbuf, ether_ntoa((struct ether_addr *)LLADDR(sdl)), 83097f8d655SXin LI sizeof(hbuf)); 831e4cd31ddSJeff Roberson } else if (sdl->sdl_alen) { 832e4cd31ddSJeff Roberson int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; 833e4cd31ddSJeff Roberson snprintf(hbuf, sizeof(hbuf), "%s", link_ntoa(sdl) + n); 834e4cd31ddSJeff Roberson } else 835a96bd784SHajimu UMEMOTO snprintf(hbuf, sizeof(hbuf), "(incomplete)"); 8369a4365d0SYoshinobu Inoue 837a96bd784SHajimu UMEMOTO return(hbuf); 8389a4365d0SYoshinobu Inoue } 8399a4365d0SYoshinobu Inoue 840f2203c27SHiroki Sato static int 841bfc75db0SAndrey V. Elsukov ndp_ether_aton(char *a, u_char *n) 8429a4365d0SYoshinobu Inoue { 8439a4365d0SYoshinobu Inoue int i, o[6]; 8449a4365d0SYoshinobu Inoue 8459a4365d0SYoshinobu Inoue i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 8469a4365d0SYoshinobu Inoue &o[3], &o[4], &o[5]); 8479a4365d0SYoshinobu Inoue if (i != 6) { 848*e1c7783eSAlexander V. Chernikov xo_warnx("invalid Ethernet address '%s'", a); 8499a4365d0SYoshinobu Inoue return (1); 8509a4365d0SYoshinobu Inoue } 8519a4365d0SYoshinobu Inoue for (i = 0; i < 6; i++) 8529a4365d0SYoshinobu Inoue n[i] = o[i]; 8539a4365d0SYoshinobu Inoue return (0); 8549a4365d0SYoshinobu Inoue } 8559a4365d0SYoshinobu Inoue 856f2203c27SHiroki Sato static void 8579a4365d0SYoshinobu Inoue usage() 8589a4365d0SYoshinobu Inoue { 8593174c1d4SHajimu UMEMOTO printf("usage: ndp [-nt] hostname\n"); 8603174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -a | -c | -p | -r | -H | -P | -R\n"); 86133841545SHajimu UMEMOTO printf(" ndp [-nt] -A wait\n"); 8623174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -d hostname\n"); 8633174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -f filename\n"); 8643174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -i interface [flags...]\n"); 865ccf935ddSJun-ichiro itojun Hagino #ifdef SIOCSDEFIFACE_IN6 8663174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -I [interface|delete]\n"); 867ccf935ddSJun-ichiro itojun Hagino #endif 8683174c1d4SHajimu UMEMOTO printf(" ndp [-nt] -s nodename etheraddr [temp] [proxy]\n"); 8699a4365d0SYoshinobu Inoue exit(1); 8709a4365d0SYoshinobu Inoue } 8719a4365d0SYoshinobu Inoue 872f2203c27SHiroki Sato static int 873bfc75db0SAndrey V. Elsukov rtmsg(int cmd) 8749a4365d0SYoshinobu Inoue { 8759a4365d0SYoshinobu Inoue static int seq; 8769a4365d0SYoshinobu Inoue int rlen; 8779a4365d0SYoshinobu Inoue register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; 8789a4365d0SYoshinobu Inoue register char *cp = m_rtmsg.m_space; 8799a4365d0SYoshinobu Inoue register int l; 8809a4365d0SYoshinobu Inoue 8819a4365d0SYoshinobu Inoue errno = 0; 8829a4365d0SYoshinobu Inoue if (cmd == RTM_DELETE) 8839a4365d0SYoshinobu Inoue goto doit; 8849a4365d0SYoshinobu Inoue bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); 8859a4365d0SYoshinobu Inoue rtm->rtm_flags = flags; 8869a4365d0SYoshinobu Inoue rtm->rtm_version = RTM_VERSION; 8879a4365d0SYoshinobu Inoue 8889a4365d0SYoshinobu Inoue switch (cmd) { 8899a4365d0SYoshinobu Inoue default: 890*e1c7783eSAlexander V. Chernikov xo_errx(1, "internal wrong cmd"); 8919a4365d0SYoshinobu Inoue case RTM_ADD: 8929a4365d0SYoshinobu Inoue rtm->rtm_addrs |= RTA_GATEWAY; 8933174c1d4SHajimu UMEMOTO if (expire_time) { 8949a4365d0SYoshinobu Inoue rtm->rtm_rmx.rmx_expire = expire_time; 8959a4365d0SYoshinobu Inoue rtm->rtm_inits = RTV_EXPIRE; 8963174c1d4SHajimu UMEMOTO } 8978eca593cSQing Li rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); 8989a4365d0SYoshinobu Inoue /* FALLTHROUGH */ 8999a4365d0SYoshinobu Inoue case RTM_GET: 9009a4365d0SYoshinobu Inoue rtm->rtm_addrs |= RTA_DST; 9019a4365d0SYoshinobu Inoue } 9029a4365d0SYoshinobu Inoue 9039a4365d0SYoshinobu Inoue NEXTADDR(RTA_DST, sin_m); 9049a4365d0SYoshinobu Inoue NEXTADDR(RTA_GATEWAY, sdl_m); 9059a4365d0SYoshinobu Inoue 9069a4365d0SYoshinobu Inoue rtm->rtm_msglen = cp - (char *)&m_rtmsg; 9079a4365d0SYoshinobu Inoue doit: 9089a4365d0SYoshinobu Inoue l = rtm->rtm_msglen; 9099a4365d0SYoshinobu Inoue rtm->rtm_seq = ++seq; 9109a4365d0SYoshinobu Inoue rtm->rtm_type = cmd; 9119a4365d0SYoshinobu Inoue if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { 9129a4365d0SYoshinobu Inoue if (errno != ESRCH || cmd != RTM_DELETE) { 913*e1c7783eSAlexander V. Chernikov xo_err(1, "writing to routing socket"); 914a96bd784SHajimu UMEMOTO /* NOTREACHED */ 9159a4365d0SYoshinobu Inoue } 9169a4365d0SYoshinobu Inoue } 9179a4365d0SYoshinobu Inoue do { 9189a4365d0SYoshinobu Inoue l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); 9192f8c6c0aSPatrick Kelsey } while (l > 0 && (rtm->rtm_type != cmd || rtm->rtm_seq != seq || 9202f8c6c0aSPatrick Kelsey rtm->rtm_pid != pid)); 9219a4365d0SYoshinobu Inoue if (l < 0) 922*e1c7783eSAlexander V. Chernikov xo_warn("read from routing socket"); 9239a4365d0SYoshinobu Inoue return (0); 9249a4365d0SYoshinobu Inoue } 9259a4365d0SYoshinobu Inoue 926f2203c27SHiroki Sato static void 927bfc75db0SAndrey V. Elsukov ifinfo(char *ifname, int argc, char **argv) 9289a4365d0SYoshinobu Inoue { 9299a4365d0SYoshinobu Inoue struct in6_ndireq nd; 9307ae43b31SRenato Botelho int i, sock; 931ccf935ddSJun-ichiro itojun Hagino u_int32_t newflags; 93233841545SHajimu UMEMOTO #ifdef IPV6CTL_USETEMPADDR 93333841545SHajimu UMEMOTO u_int8_t nullbuf[8]; 93433841545SHajimu UMEMOTO #endif 9359a4365d0SYoshinobu Inoue 9367ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 937*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 938a96bd784SHajimu UMEMOTO /* NOTREACHED */ 9399a4365d0SYoshinobu Inoue } 9409a4365d0SYoshinobu Inoue bzero(&nd, sizeof(nd)); 941a96bd784SHajimu UMEMOTO strlcpy(nd.ifname, ifname, sizeof(nd.ifname)); 9427ae43b31SRenato Botelho if (ioctl(sock, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 943*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCGIFINFO_IN6)"); 944a96bd784SHajimu UMEMOTO /* NOTREACHED */ 9459a4365d0SYoshinobu Inoue } 9469a4365d0SYoshinobu Inoue #define ND nd.ndi 947ccf935ddSJun-ichiro itojun Hagino newflags = ND.flags; 9483174c1d4SHajimu UMEMOTO for (i = 0; i < argc; i++) { 949ccf935ddSJun-ichiro itojun Hagino int clear = 0; 950ccf935ddSJun-ichiro itojun Hagino char *cp = argv[i]; 951ccf935ddSJun-ichiro itojun Hagino 952ccf935ddSJun-ichiro itojun Hagino if (*cp == '-') { 953ccf935ddSJun-ichiro itojun Hagino clear = 1; 954ccf935ddSJun-ichiro itojun Hagino cp++; 955ccf935ddSJun-ichiro itojun Hagino } 956ccf935ddSJun-ichiro itojun Hagino 957937f8ddfSRenato Botelho #define SETFLAG(s, f) do { \ 958ccf935ddSJun-ichiro itojun Hagino if (strcmp(cp, (s)) == 0) { \ 959ccf935ddSJun-ichiro itojun Hagino if (clear) \ 960ccf935ddSJun-ichiro itojun Hagino newflags &= ~(f); \ 961ccf935ddSJun-ichiro itojun Hagino else \ 962ccf935ddSJun-ichiro itojun Hagino newflags |= (f); \ 963ccf935ddSJun-ichiro itojun Hagino } \ 964ccf935ddSJun-ichiro itojun Hagino } while (0) 965b9204379SSUZUKI Shinsuke /* 966b9204379SSUZUKI Shinsuke * XXX: this macro is not 100% correct, in that it matches "nud" against 967b9204379SSUZUKI Shinsuke * "nudbogus". But we just let it go since this is minor. 968b9204379SSUZUKI Shinsuke */ 969937f8ddfSRenato Botelho #define SETVALUE(f, v) do { \ 970b9204379SSUZUKI Shinsuke char *valptr; \ 971b9204379SSUZUKI Shinsuke unsigned long newval; \ 972b9204379SSUZUKI Shinsuke v = 0; /* unspecified */ \ 973b9204379SSUZUKI Shinsuke if (strncmp(cp, f, strlen(f)) == 0) { \ 974b9204379SSUZUKI Shinsuke valptr = strchr(cp, '='); \ 975b9204379SSUZUKI Shinsuke if (valptr == NULL) \ 976*e1c7783eSAlexander V. Chernikov xo_err(1, "syntax error in %s field", (f)); \ 977b9204379SSUZUKI Shinsuke errno = 0; \ 978b9204379SSUZUKI Shinsuke newval = strtoul(++valptr, NULL, 0); \ 979b9204379SSUZUKI Shinsuke if (errno) \ 980*e1c7783eSAlexander V. Chernikov xo_err(1, "syntax error in %s's value", (f)); \ 981b9204379SSUZUKI Shinsuke v = newval; \ 982b9204379SSUZUKI Shinsuke } \ 983b9204379SSUZUKI Shinsuke } while (0) 984b9204379SSUZUKI Shinsuke 9855b27b045SSUZUKI Shinsuke SETFLAG("disabled", ND6_IFF_IFDISABLED); 986ccf935ddSJun-ichiro itojun Hagino SETFLAG("nud", ND6_IFF_PERFORMNUD); 98707cf047dSHajimu UMEMOTO #ifdef ND6_IFF_ACCEPT_RTADV 98807cf047dSHajimu UMEMOTO SETFLAG("accept_rtadv", ND6_IFF_ACCEPT_RTADV); 98907cf047dSHajimu UMEMOTO #endif 990a283298cSHiroki Sato #ifdef ND6_IFF_AUTO_LINKLOCAL 991a283298cSHiroki Sato SETFLAG("auto_linklocal", ND6_IFF_AUTO_LINKLOCAL); 992a283298cSHiroki Sato #endif 993164051ceSHajimu UMEMOTO #ifdef ND6_IFF_NO_PREFER_IFACE 994164051ceSHajimu UMEMOTO SETFLAG("no_prefer_iface", ND6_IFF_NO_PREFER_IFACE); 995164051ceSHajimu UMEMOTO #endif 996b9204379SSUZUKI Shinsuke SETVALUE("basereachable", ND.basereachable); 997b9204379SSUZUKI Shinsuke SETVALUE("retrans", ND.retrans); 998b9204379SSUZUKI Shinsuke SETVALUE("curhlim", ND.chlim); 999ccf935ddSJun-ichiro itojun Hagino 1000ccf935ddSJun-ichiro itojun Hagino ND.flags = newflags; 10017ae43b31SRenato Botelho if (ioctl(sock, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) { 1002*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCSIFINFO_IN6)"); 1003a96bd784SHajimu UMEMOTO /* NOTREACHED */ 1004ccf935ddSJun-ichiro itojun Hagino } 1005ccf935ddSJun-ichiro itojun Hagino #undef SETFLAG 1006b9204379SSUZUKI Shinsuke #undef SETVALUE 1007ccf935ddSJun-ichiro itojun Hagino } 1008ccf935ddSJun-ichiro itojun Hagino 100931423309SHajimu UMEMOTO if (!ND.initialized) { 1010*e1c7783eSAlexander V. Chernikov xo_errx(1, "%s: not initialized yet", ifname); 101131423309SHajimu UMEMOTO /* NOTREACHED */ 101231423309SHajimu UMEMOTO } 101331423309SHajimu UMEMOTO 10147ae43b31SRenato Botelho if (ioctl(sock, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 1015*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCGIFINFO_IN6)"); 1016b9204379SSUZUKI Shinsuke /* NOTREACHED */ 1017b9204379SSUZUKI Shinsuke } 1018*e1c7783eSAlexander V. Chernikov xo_open_container("ifinfo"); 1019*e1c7783eSAlexander V. Chernikov 1020*e1c7783eSAlexander V. Chernikov xo_emit("{e:interface/%s}", ifname); 1021*e1c7783eSAlexander V. Chernikov xo_emit("linkmtu={:linkmtu/%d}", ND.linkmtu); 1022*e1c7783eSAlexander V. Chernikov xo_emit(", maxmtu={:maxmtu/%d}", ND.maxmtu); 1023*e1c7783eSAlexander V. Chernikov xo_emit(", curhlim={:curhlim/%d}", ND.chlim); 1024*e1c7783eSAlexander V. Chernikov xo_emit("{d:/, basereachable=%ds%dms}{e:basereachable_ms/%u}", 1025*e1c7783eSAlexander V. Chernikov ND.basereachable / 1000, ND.basereachable % 1000, ND.basereachable); 1026*e1c7783eSAlexander V. Chernikov xo_emit("{d:/, reachable=%ds}{e:reachable_ms/%u}", ND.reachable, ND.reachable * 1000); 1027*e1c7783eSAlexander V. Chernikov xo_emit("{d:/, retrans=%ds%dms}{e:retrans_ms/%u}", ND.retrans / 1000, ND.retrans % 1000, 1028*e1c7783eSAlexander V. Chernikov ND.retrans); 102933841545SHajimu UMEMOTO #ifdef IPV6CTL_USETEMPADDR 103033841545SHajimu UMEMOTO memset(nullbuf, 0, sizeof(nullbuf)); 103133841545SHajimu UMEMOTO if (memcmp(nullbuf, ND.randomid, sizeof(nullbuf)) != 0) { 103233841545SHajimu UMEMOTO int j; 103333841545SHajimu UMEMOTO u_int8_t *rbuf; 103433841545SHajimu UMEMOTO 103533841545SHajimu UMEMOTO for (i = 0; i < 3; i++) { 1036*e1c7783eSAlexander V. Chernikov const char *txt, *field; 103733841545SHajimu UMEMOTO switch (i) { 103833841545SHajimu UMEMOTO case 0: 1039*e1c7783eSAlexander V. Chernikov txt = "\nRandom seed(0): "; 1040*e1c7783eSAlexander V. Chernikov field = "seed_0"; 104133841545SHajimu UMEMOTO rbuf = ND.randomseed0; 104233841545SHajimu UMEMOTO break; 104333841545SHajimu UMEMOTO case 1: 1044*e1c7783eSAlexander V. Chernikov txt = "\nRandom seed(1): "; 1045*e1c7783eSAlexander V. Chernikov field = "seed_1"; 104633841545SHajimu UMEMOTO rbuf = ND.randomseed1; 104733841545SHajimu UMEMOTO break; 104833841545SHajimu UMEMOTO case 2: 1049*e1c7783eSAlexander V. Chernikov txt = "\nRandom ID: "; 1050*e1c7783eSAlexander V. Chernikov field = "random_id"; 105133841545SHajimu UMEMOTO rbuf = ND.randomid; 105233841545SHajimu UMEMOTO break; 1053ec0176bbSSUZUKI Shinsuke default: 1054*e1c7783eSAlexander V. Chernikov xo_errx(1, "impossible case for tempaddr display"); 105533841545SHajimu UMEMOTO } 1056*e1c7783eSAlexander V. Chernikov char abuf[20], xobuf[200]; 105733841545SHajimu UMEMOTO for (j = 0; j < 8; j++) 1058*e1c7783eSAlexander V. Chernikov snprintf(&abuf[j * 2], sizeof(abuf), "%02X", rbuf[j]); 1059*e1c7783eSAlexander V. Chernikov snprintf(xobuf, sizeof(xobuf), "%s{:%s/%%s}", txt, field); 1060*e1c7783eSAlexander V. Chernikov xo_emit(xobuf, abuf); 106133841545SHajimu UMEMOTO } 106233841545SHajimu UMEMOTO } 1063937f8ddfSRenato Botelho #endif /* IPV6CTL_USETEMPADDR */ 1064ccf935ddSJun-ichiro itojun Hagino if (ND.flags) { 1065*e1c7783eSAlexander V. Chernikov xo_emit("\nFlags: {e:flags/%u}", ND.flags); 1066*e1c7783eSAlexander V. Chernikov xo_open_list("flags_pretty"); 10675b27b045SSUZUKI Shinsuke #ifdef ND6_IFF_IFDISABLED 10685b27b045SSUZUKI Shinsuke if ((ND.flags & ND6_IFF_IFDISABLED)) 1069*e1c7783eSAlexander V. Chernikov xo_emit("{l:%s} ", "disabled"); 10705b27b045SSUZUKI Shinsuke #endif 107107cf047dSHajimu UMEMOTO if ((ND.flags & ND6_IFF_PERFORMNUD)) 1072*e1c7783eSAlexander V. Chernikov xo_emit("{l:%s} ", "nud"); 107307cf047dSHajimu UMEMOTO #ifdef ND6_IFF_ACCEPT_RTADV 107407cf047dSHajimu UMEMOTO if ((ND.flags & ND6_IFF_ACCEPT_RTADV)) 1075*e1c7783eSAlexander V. Chernikov xo_emit("{l:%s} ", "accept_rtadv"); 107607cf047dSHajimu UMEMOTO #endif 1077a283298cSHiroki Sato #ifdef ND6_IFF_AUTO_LINKLOCAL 1078a283298cSHiroki Sato if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL)) 1079*e1c7783eSAlexander V. Chernikov xo_emit("{l:%s} ", "auto_linklocal"); 1080a283298cSHiroki Sato #endif 1081164051ceSHajimu UMEMOTO #ifdef ND6_IFF_NO_PREFER_IFACE 1082164051ceSHajimu UMEMOTO if ((ND.flags & ND6_IFF_NO_PREFER_IFACE)) 1083*e1c7783eSAlexander V. Chernikov xo_emit("{l:%s} ", "no_prefer_iface"); 1084164051ceSHajimu UMEMOTO #endif 1085*e1c7783eSAlexander V. Chernikov xo_close_list("flags"); 1086ccf935ddSJun-ichiro itojun Hagino } 1087*e1c7783eSAlexander V. Chernikov xo_emit("\n"); 10889a4365d0SYoshinobu Inoue #undef ND 1089*e1c7783eSAlexander V. Chernikov xo_close_container("ifinfo"); 1090ccf935ddSJun-ichiro itojun Hagino 10917ae43b31SRenato Botelho close(sock); 10929a4365d0SYoshinobu Inoue } 10939a4365d0SYoshinobu Inoue 109433841545SHajimu UMEMOTO #ifndef ND_RA_FLAG_RTPREF_MASK /* XXX: just for compilation on *BSD release */ 109533841545SHajimu UMEMOTO #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ 109633841545SHajimu UMEMOTO #endif 109733841545SHajimu UMEMOTO 1098f2203c27SHiroki Sato static void 10999a4365d0SYoshinobu Inoue rtrlist() 11009a4365d0SYoshinobu Inoue { 110133841545SHajimu UMEMOTO int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST }; 110233841545SHajimu UMEMOTO char *buf; 110333841545SHajimu UMEMOTO struct in6_defrouter *p, *ep; 110433841545SHajimu UMEMOTO size_t l; 1105ffa0165aSHiroki Sato struct timeval now; 110633841545SHajimu UMEMOTO 110733841545SHajimu UMEMOTO if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) { 1108*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); 110933841545SHajimu UMEMOTO /*NOTREACHED*/ 111033841545SHajimu UMEMOTO } 1111ec0176bbSSUZUKI Shinsuke if (l == 0) 1112ec0176bbSSUZUKI Shinsuke return; 111333841545SHajimu UMEMOTO buf = malloc(l); 111433841545SHajimu UMEMOTO if (!buf) { 1115*e1c7783eSAlexander V. Chernikov xo_err(1, "malloc"); 111633841545SHajimu UMEMOTO /*NOTREACHED*/ 111733841545SHajimu UMEMOTO } 111833841545SHajimu UMEMOTO if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { 1119*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); 112033841545SHajimu UMEMOTO /*NOTREACHED*/ 112133841545SHajimu UMEMOTO } 112233841545SHajimu UMEMOTO 1123*e1c7783eSAlexander V. Chernikov xo_open_list("router-list"); 1124*e1c7783eSAlexander V. Chernikov 112533841545SHajimu UMEMOTO ep = (struct in6_defrouter *)(buf + l); 112633841545SHajimu UMEMOTO for (p = (struct in6_defrouter *)buf; p < ep; p++) { 112733841545SHajimu UMEMOTO int rtpref; 1128*e1c7783eSAlexander V. Chernikov char abuf[INET6_ADDRSTRLEN], *paddr; 112933841545SHajimu UMEMOTO 113033841545SHajimu UMEMOTO if (getnameinfo((struct sockaddr *)&p->rtaddr, 113133841545SHajimu UMEMOTO p->rtaddr.sin6_len, host_buf, sizeof(host_buf), NULL, 0, 1132a96bd784SHajimu UMEMOTO (nflag ? NI_NUMERICHOST : 0)) != 0) 113333841545SHajimu UMEMOTO strlcpy(host_buf, "?", sizeof(host_buf)); 1134*e1c7783eSAlexander V. Chernikov if (nflag) 1135*e1c7783eSAlexander V. Chernikov paddr = host_buf; 1136*e1c7783eSAlexander V. Chernikov else { 1137*e1c7783eSAlexander V. Chernikov inet_ntop(AF_INET6, &p->rtaddr.sin6_addr, abuf, sizeof(abuf)); 1138*e1c7783eSAlexander V. Chernikov paddr = abuf; 1139*e1c7783eSAlexander V. Chernikov } 114033841545SHajimu UMEMOTO 1141*e1c7783eSAlexander V. Chernikov xo_open_instance("router-list"); 1142*e1c7783eSAlexander V. Chernikov xo_emit("{:hostname/%s}{e:address/%s} if={:interface/%s}", 1143*e1c7783eSAlexander V. Chernikov host_buf, paddr, 114433841545SHajimu UMEMOTO if_indextoname(p->if_index, ifix_buf)); 1145*e1c7783eSAlexander V. Chernikov xo_open_list("flags_pretty"); 1146*e1c7783eSAlexander V. Chernikov char rflags[6] = {}, *pflags = rflags; 1147*e1c7783eSAlexander V. Chernikov if (p->flags & ND_RA_FLAG_MANAGED) { 1148*e1c7783eSAlexander V. Chernikov *pflags++ = 'M'; 1149*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "managed"); 1150*e1c7783eSAlexander V. Chernikov } 1151*e1c7783eSAlexander V. Chernikov if (p->flags & ND_RA_FLAG_OTHER) { 1152*e1c7783eSAlexander V. Chernikov *pflags++ = 'O'; 1153*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "other"); 1154*e1c7783eSAlexander V. Chernikov } 1155201100c5SBjoern A. Zeeb #ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG 1156*e1c7783eSAlexander V. Chernikov if (p->flags & ND_RA_FLAG_IPV6_ONLY) { 1157*e1c7783eSAlexander V. Chernikov *pflags++ = 'S'; 1158*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "ipv6only"); 1159*e1c7783eSAlexander V. Chernikov } 1160201100c5SBjoern A. Zeeb #endif 1161*e1c7783eSAlexander V. Chernikov xo_close_list("flags_pretty"); 1162*e1c7783eSAlexander V. Chernikov xo_emit(", flags={:flags/%s}", rflags); 1163*e1c7783eSAlexander V. Chernikov 116433841545SHajimu UMEMOTO rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff; 1165*e1c7783eSAlexander V. Chernikov xo_emit(", pref={:preference/%s}", rtpref_str[rtpref]); 116633841545SHajimu UMEMOTO 1167ffa0165aSHiroki Sato gettimeofday(&now, 0); 116833841545SHajimu UMEMOTO if (p->expire == 0) 1169*e1c7783eSAlexander V. Chernikov xo_emit(", expire=Never\n{en:permanent/true}"); 117033841545SHajimu UMEMOTO else 1171*e1c7783eSAlexander V. Chernikov xo_emit("{d:/, expire=%s\n}{e:expires_sec/%ld}", 1172*e1c7783eSAlexander V. Chernikov sec2str(p->expire - now.tv_sec), 1173*e1c7783eSAlexander V. Chernikov (long)p->expire - now.tv_sec); 1174*e1c7783eSAlexander V. Chernikov xo_close_instance("router-list"); 117533841545SHajimu UMEMOTO } 117633841545SHajimu UMEMOTO free(buf); 1177*e1c7783eSAlexander V. Chernikov xo_close_list("router-list"); 11789a4365d0SYoshinobu Inoue } 11799a4365d0SYoshinobu Inoue 1180f2203c27SHiroki Sato static void 11819a4365d0SYoshinobu Inoue plist() 11829a4365d0SYoshinobu Inoue { 118333841545SHajimu UMEMOTO int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_PRLIST }; 118433841545SHajimu UMEMOTO char *buf; 118533841545SHajimu UMEMOTO struct in6_prefix *p, *ep, *n; 118633841545SHajimu UMEMOTO struct sockaddr_in6 *advrtr; 118733841545SHajimu UMEMOTO size_t l; 1188ffa0165aSHiroki Sato struct timeval now; 118933841545SHajimu UMEMOTO const int niflags = NI_NUMERICHOST; 119033841545SHajimu UMEMOTO int ninflags = nflag ? NI_NUMERICHOST : 0; 119133841545SHajimu UMEMOTO char namebuf[NI_MAXHOST]; 119233841545SHajimu UMEMOTO 119333841545SHajimu UMEMOTO if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) { 1194*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)"); 119533841545SHajimu UMEMOTO /*NOTREACHED*/ 119633841545SHajimu UMEMOTO } 119733841545SHajimu UMEMOTO buf = malloc(l); 119833841545SHajimu UMEMOTO if (!buf) { 1199*e1c7783eSAlexander V. Chernikov xo_err(1, "malloc"); 120033841545SHajimu UMEMOTO /*NOTREACHED*/ 120133841545SHajimu UMEMOTO } 120233841545SHajimu UMEMOTO if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { 1203*e1c7783eSAlexander V. Chernikov xo_err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)"); 120433841545SHajimu UMEMOTO /*NOTREACHED*/ 120533841545SHajimu UMEMOTO } 120633841545SHajimu UMEMOTO 1207*e1c7783eSAlexander V. Chernikov xo_open_list("prefix-list"); 1208*e1c7783eSAlexander V. Chernikov 120933841545SHajimu UMEMOTO ep = (struct in6_prefix *)(buf + l); 121033841545SHajimu UMEMOTO for (p = (struct in6_prefix *)buf; p < ep; p = n) { 121133841545SHajimu UMEMOTO advrtr = (struct sockaddr_in6 *)(p + 1); 121233841545SHajimu UMEMOTO n = (struct in6_prefix *)&advrtr[p->advrtrs]; 121333841545SHajimu UMEMOTO 1214*e1c7783eSAlexander V. Chernikov xo_open_instance("prefix-list"); 121533841545SHajimu UMEMOTO if (getnameinfo((struct sockaddr *)&p->prefix, 121633841545SHajimu UMEMOTO p->prefix.sin6_len, namebuf, sizeof(namebuf), 121733841545SHajimu UMEMOTO NULL, 0, niflags) != 0) 121833841545SHajimu UMEMOTO strlcpy(namebuf, "?", sizeof(namebuf)); 1219*e1c7783eSAlexander V. Chernikov xo_emit("{:prefix/%s%s%d} if={:interface/%s}\n", namebuf, "/", 1220*e1c7783eSAlexander V. Chernikov p->prefixlen, if_indextoname(p->if_index, ifix_buf)); 122133841545SHajimu UMEMOTO 1222ffa0165aSHiroki Sato gettimeofday(&now, 0); 122333841545SHajimu UMEMOTO /* 122433841545SHajimu UMEMOTO * meaning of fields, especially flags, is very different 122533841545SHajimu UMEMOTO * by origin. notify the difference to the users. 122633841545SHajimu UMEMOTO */ 1227*e1c7783eSAlexander V. Chernikov char flags[10] = {}, *pflags = flags; 1228*e1c7783eSAlexander V. Chernikov xo_open_list("flags_pretty"); 1229*e1c7783eSAlexander V. Chernikov if (p->raflags.onlink) { 1230*e1c7783eSAlexander V. Chernikov *pflags++ = 'L'; 1231*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "ra_onlink"); 1232*e1c7783eSAlexander V. Chernikov } 1233*e1c7783eSAlexander V. Chernikov if (p->raflags.autonomous) { 1234*e1c7783eSAlexander V. Chernikov *pflags++ = 'A'; 1235*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "ra_autonomous"); 1236*e1c7783eSAlexander V. Chernikov } 1237*e1c7783eSAlexander V. Chernikov if (p->flags & NDPRF_ONLINK) { 1238*e1c7783eSAlexander V. Chernikov *pflags++ = 'O'; 1239*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "is_onlink"); 1240*e1c7783eSAlexander V. Chernikov } 1241*e1c7783eSAlexander V. Chernikov if (p->flags & NDPRF_DETACHED) { 1242*e1c7783eSAlexander V. Chernikov *pflags++ = 'D'; 1243*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "is_detached"); 1244*e1c7783eSAlexander V. Chernikov } 124533841545SHajimu UMEMOTO #ifdef NDPRF_HOME 1246*e1c7783eSAlexander V. Chernikov if (p->flags & NDPRF_HOME) { 1247*e1c7783eSAlexander V. Chernikov *pflags++ = 'H'; 1248*e1c7783eSAlexander V. Chernikov xo_emit("{el:%s}", "is_home"); 1249*e1c7783eSAlexander V. Chernikov } 125033841545SHajimu UMEMOTO #endif 1251*e1c7783eSAlexander V. Chernikov xo_close_list("flags_pretty"); 1252*e1c7783eSAlexander V. Chernikov xo_emit("flags={:flags/%s}", flags); 1253*e1c7783eSAlexander V. Chernikov int expire_in = p->expire - now.tv_sec; 1254*e1c7783eSAlexander V. Chernikov 125533841545SHajimu UMEMOTO if (p->vltime == ND6_INFINITE_LIFETIME) 1256*e1c7783eSAlexander V. Chernikov xo_emit(" vltime=infinity{e:valid-lifetime/%lu}", 1257*e1c7783eSAlexander V. Chernikov (unsigned long)p->vltime); 125833841545SHajimu UMEMOTO else 1259*e1c7783eSAlexander V. Chernikov xo_emit(" vltime={:valid-lifetime/%lu}", 1260*e1c7783eSAlexander V. Chernikov (unsigned long)p->vltime); 126133841545SHajimu UMEMOTO if (p->pltime == ND6_INFINITE_LIFETIME) 1262*e1c7783eSAlexander V. Chernikov xo_emit(", pltime=infinity{e:preferred-lifetime/%lu}", 1263*e1c7783eSAlexander V. Chernikov (unsigned long)p->pltime); 126433841545SHajimu UMEMOTO else 1265*e1c7783eSAlexander V. Chernikov xo_emit(", pltime={:preferred-lifetime/%lu}", 1266*e1c7783eSAlexander V. Chernikov (unsigned long)p->pltime); 126733841545SHajimu UMEMOTO if (p->expire == 0) 1268*e1c7783eSAlexander V. Chernikov xo_emit(", expire=Never{en:permanent/true}"); 12697d26db17SHiroki Sato else if (p->expire >= now.tv_sec) 1270*e1c7783eSAlexander V. Chernikov xo_emit(", expire=%s{e:expires_sec/%d}", 1271*e1c7783eSAlexander V. Chernikov sec2str(expire_in), expire_in); 127233841545SHajimu UMEMOTO else 1273*e1c7783eSAlexander V. Chernikov xo_emit(", expired{e:expires_sec/%d}", expire_in); 1274*e1c7783eSAlexander V. Chernikov xo_emit(", ref={:refcount/%d}", p->refcnt); 1275*e1c7783eSAlexander V. Chernikov xo_emit("\n"); 127633841545SHajimu UMEMOTO /* 127733841545SHajimu UMEMOTO * "advertising router" list is meaningful only if the prefix 127833841545SHajimu UMEMOTO * information is from RA. 127933841545SHajimu UMEMOTO */ 128033841545SHajimu UMEMOTO if (p->advrtrs) { 128133841545SHajimu UMEMOTO int j; 128233841545SHajimu UMEMOTO struct sockaddr_in6 *sin6; 128333841545SHajimu UMEMOTO 12843174c1d4SHajimu UMEMOTO sin6 = advrtr; 1285*e1c7783eSAlexander V. Chernikov xo_emit(" advertised by\n"); 1286*e1c7783eSAlexander V. Chernikov xo_open_list("advertising-routers"); 128733841545SHajimu UMEMOTO for (j = 0; j < p->advrtrs; j++) { 128833841545SHajimu UMEMOTO struct in6_nbrinfo *nbi; 128933841545SHajimu UMEMOTO 1290*e1c7783eSAlexander V. Chernikov xo_open_instance("advertising-routers"); 129133841545SHajimu UMEMOTO if (getnameinfo((struct sockaddr *)sin6, 129233841545SHajimu UMEMOTO sin6->sin6_len, namebuf, sizeof(namebuf), 129333841545SHajimu UMEMOTO NULL, 0, ninflags) != 0) 129433841545SHajimu UMEMOTO strlcpy(namebuf, "?", sizeof(namebuf)); 1295*e1c7783eSAlexander V. Chernikov char abuf[INET6_ADDRSTRLEN]; 1296*e1c7783eSAlexander V. Chernikov inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, 1297*e1c7783eSAlexander V. Chernikov sizeof(abuf)); 1298*e1c7783eSAlexander V. Chernikov 1299*e1c7783eSAlexander V. Chernikov xo_emit(" {:hostname/%s}{e:address/%s}", 1300*e1c7783eSAlexander V. Chernikov namebuf, abuf); 130133841545SHajimu UMEMOTO 1302a96bd784SHajimu UMEMOTO nbi = getnbrinfo(&sin6->sin6_addr, 1303a96bd784SHajimu UMEMOTO p->if_index, 0); 1304*e1c7783eSAlexander V. Chernikov const char *state = ""; 130533841545SHajimu UMEMOTO if (nbi) { 130633841545SHajimu UMEMOTO switch (nbi->state) { 130733841545SHajimu UMEMOTO case ND6_LLINFO_REACHABLE: 130833841545SHajimu UMEMOTO case ND6_LLINFO_STALE: 130933841545SHajimu UMEMOTO case ND6_LLINFO_DELAY: 131033841545SHajimu UMEMOTO case ND6_LLINFO_PROBE: 1311*e1c7783eSAlexander V. Chernikov state = "reachable"; 131233841545SHajimu UMEMOTO break; 131333841545SHajimu UMEMOTO default: 1314*e1c7783eSAlexander V. Chernikov state = "unreachable"; 131533841545SHajimu UMEMOTO } 131633841545SHajimu UMEMOTO } else 1317*e1c7783eSAlexander V. Chernikov state = "no neighbor state"; 1318*e1c7783eSAlexander V. Chernikov xo_emit(" ({:state/%s})\n", state); 131933841545SHajimu UMEMOTO sin6++; 1320*e1c7783eSAlexander V. Chernikov xo_close_instance("advertising-routers"); 132133841545SHajimu UMEMOTO } 1322*e1c7783eSAlexander V. Chernikov xo_close_list("advertising-routers"); 132333841545SHajimu UMEMOTO } else 1324*e1c7783eSAlexander V. Chernikov xo_emit(" No advertising router\n"); 1325*e1c7783eSAlexander V. Chernikov xo_close_instance("prefix-list"); 132633841545SHajimu UMEMOTO } 132733841545SHajimu UMEMOTO free(buf); 1328*e1c7783eSAlexander V. Chernikov 1329*e1c7783eSAlexander V. Chernikov xo_close_list("prefix-list"); 13309a4365d0SYoshinobu Inoue } 13319a4365d0SYoshinobu Inoue 1332f2203c27SHiroki Sato static void 13339a4365d0SYoshinobu Inoue pfx_flush() 13349a4365d0SYoshinobu Inoue { 13359a4365d0SYoshinobu Inoue char dummyif[IFNAMSIZ+8]; 13367ae43b31SRenato Botelho int sock; 13379a4365d0SYoshinobu Inoue 13387ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1339*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 1340a96bd784SHajimu UMEMOTO strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */ 13417ae43b31SRenato Botelho if (ioctl(sock, SIOCSPFXFLUSH_IN6, (caddr_t)&dummyif) < 0) 1342*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCSPFXFLUSH_IN6)"); 13437ae43b31SRenato Botelho 13447ae43b31SRenato Botelho close(sock); 13459a4365d0SYoshinobu Inoue } 13469a4365d0SYoshinobu Inoue 1347f2203c27SHiroki Sato static void 13489a4365d0SYoshinobu Inoue rtr_flush() 13499a4365d0SYoshinobu Inoue { 13509a4365d0SYoshinobu Inoue char dummyif[IFNAMSIZ+8]; 13517ae43b31SRenato Botelho int sock; 13529a4365d0SYoshinobu Inoue 13537ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1354*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 1355a96bd784SHajimu UMEMOTO strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */ 13567ae43b31SRenato Botelho if (ioctl(sock, SIOCSRTRFLUSH_IN6, (caddr_t)&dummyif) < 0) 1357*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCSRTRFLUSH_IN6)"); 1358ccf935ddSJun-ichiro itojun Hagino 13597ae43b31SRenato Botelho close(sock); 13609a4365d0SYoshinobu Inoue } 13619a4365d0SYoshinobu Inoue 1362f2203c27SHiroki Sato static void 13639a4365d0SYoshinobu Inoue harmonize_rtr() 13649a4365d0SYoshinobu Inoue { 13659a4365d0SYoshinobu Inoue char dummyif[IFNAMSIZ+8]; 13667ae43b31SRenato Botelho int sock; 13679a4365d0SYoshinobu Inoue 13687ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1369*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 1370a96bd784SHajimu UMEMOTO strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */ 13717ae43b31SRenato Botelho if (ioctl(sock, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0) 1372*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCSNDFLUSH_IN6)"); 1373ccf935ddSJun-ichiro itojun Hagino 13747ae43b31SRenato Botelho close(sock); 13759a4365d0SYoshinobu Inoue } 1376ccf935ddSJun-ichiro itojun Hagino 1377ccf935ddSJun-ichiro itojun Hagino #ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ 1378ccf935ddSJun-ichiro itojun Hagino static void 1379bfc75db0SAndrey V. Elsukov setdefif(char *ifname) 1380ccf935ddSJun-ichiro itojun Hagino { 1381ccf935ddSJun-ichiro itojun Hagino struct in6_ndifreq ndifreq; 1382ccf935ddSJun-ichiro itojun Hagino unsigned int ifindex; 13837ae43b31SRenato Botelho int sock; 1384ccf935ddSJun-ichiro itojun Hagino 1385ccf935ddSJun-ichiro itojun Hagino if (strcasecmp(ifname, "delete") == 0) 1386ccf935ddSJun-ichiro itojun Hagino ifindex = 0; 1387ccf935ddSJun-ichiro itojun Hagino else { 1388ccf935ddSJun-ichiro itojun Hagino if ((ifindex = if_nametoindex(ifname)) == 0) 1389*e1c7783eSAlexander V. Chernikov xo_err(1, "failed to resolve i/f index for %s", ifname); 13909a4365d0SYoshinobu Inoue } 13919a4365d0SYoshinobu Inoue 13927ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1393*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 1394ccf935ddSJun-ichiro itojun Hagino 1395a96bd784SHajimu UMEMOTO strlcpy(ndifreq.ifname, "lo0", sizeof(ndifreq.ifname)); /* dummy */ 1396ccf935ddSJun-ichiro itojun Hagino ndifreq.ifindex = ifindex; 1397ccf935ddSJun-ichiro itojun Hagino 13987ae43b31SRenato Botelho if (ioctl(sock, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq) < 0) 1399*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCSDEFIFACE_IN6)"); 1400ccf935ddSJun-ichiro itojun Hagino 14017ae43b31SRenato Botelho close(sock); 1402ccf935ddSJun-ichiro itojun Hagino } 1403ccf935ddSJun-ichiro itojun Hagino 1404ccf935ddSJun-ichiro itojun Hagino static void 1405ccf935ddSJun-ichiro itojun Hagino getdefif() 1406ccf935ddSJun-ichiro itojun Hagino { 1407ccf935ddSJun-ichiro itojun Hagino struct in6_ndifreq ndifreq; 1408ccf935ddSJun-ichiro itojun Hagino char ifname[IFNAMSIZ+8]; 14097ae43b31SRenato Botelho int sock; 1410ccf935ddSJun-ichiro itojun Hagino 14117ae43b31SRenato Botelho if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 1412*e1c7783eSAlexander V. Chernikov xo_err(1, "socket"); 1413ccf935ddSJun-ichiro itojun Hagino 1414ccf935ddSJun-ichiro itojun Hagino memset(&ndifreq, 0, sizeof(ndifreq)); 1415a96bd784SHajimu UMEMOTO strlcpy(ndifreq.ifname, "lo0", sizeof(ndifreq.ifname)); /* dummy */ 1416ccf935ddSJun-ichiro itojun Hagino 14177ae43b31SRenato Botelho if (ioctl(sock, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq) < 0) 1418*e1c7783eSAlexander V. Chernikov xo_err(1, "ioctl(SIOCGDEFIFACE_IN6)"); 1419ccf935ddSJun-ichiro itojun Hagino 1420ccf935ddSJun-ichiro itojun Hagino if (ndifreq.ifindex == 0) 1421*e1c7783eSAlexander V. Chernikov xo_emit("No default interface.\n"); 1422ccf935ddSJun-ichiro itojun Hagino else { 1423ccf935ddSJun-ichiro itojun Hagino if ((if_indextoname(ndifreq.ifindex, ifname)) == NULL) 1424*e1c7783eSAlexander V. Chernikov xo_err(1, "failed to resolve ifname for index %lu", 1425ccf935ddSJun-ichiro itojun Hagino ndifreq.ifindex); 1426*e1c7783eSAlexander V. Chernikov xo_emit("ND default interface = {:default-interface/%s}\n", ifname); 1427ccf935ddSJun-ichiro itojun Hagino } 1428ccf935ddSJun-ichiro itojun Hagino 14297ae43b31SRenato Botelho close(sock); 1430ccf935ddSJun-ichiro itojun Hagino } 1431937f8ddfSRenato Botelho #endif /* SIOCSDEFIFACE_IN6 */ 1432ccf935ddSJun-ichiro itojun Hagino 14339a4365d0SYoshinobu Inoue static char * 1434bfc75db0SAndrey V. Elsukov sec2str(time_t total) 14359a4365d0SYoshinobu Inoue { 14369a4365d0SYoshinobu Inoue static char result[256]; 14379a4365d0SYoshinobu Inoue int days, hours, mins, secs; 14389a4365d0SYoshinobu Inoue int first = 1; 14399a4365d0SYoshinobu Inoue char *p = result; 1440a96bd784SHajimu UMEMOTO char *ep = &result[sizeof(result)]; 1441a96bd784SHajimu UMEMOTO int n; 14429a4365d0SYoshinobu Inoue 14439a4365d0SYoshinobu Inoue days = total / 3600 / 24; 14449a4365d0SYoshinobu Inoue hours = (total / 3600) % 24; 14459a4365d0SYoshinobu Inoue mins = (total / 60) % 60; 14469a4365d0SYoshinobu Inoue secs = total % 60; 14479a4365d0SYoshinobu Inoue 14489a4365d0SYoshinobu Inoue if (days) { 14499a4365d0SYoshinobu Inoue first = 0; 1450a96bd784SHajimu UMEMOTO n = snprintf(p, ep - p, "%dd", days); 1451a96bd784SHajimu UMEMOTO if (n < 0 || n >= ep - p) 1452a96bd784SHajimu UMEMOTO return "?"; 1453a96bd784SHajimu UMEMOTO p += n; 14549a4365d0SYoshinobu Inoue } 14559a4365d0SYoshinobu Inoue if (!first || hours) { 14569a4365d0SYoshinobu Inoue first = 0; 1457a96bd784SHajimu UMEMOTO n = snprintf(p, ep - p, "%dh", hours); 1458a96bd784SHajimu UMEMOTO if (n < 0 || n >= ep - p) 1459a96bd784SHajimu UMEMOTO return "?"; 1460a96bd784SHajimu UMEMOTO p += n; 14619a4365d0SYoshinobu Inoue } 14629a4365d0SYoshinobu Inoue if (!first || mins) { 14639a4365d0SYoshinobu Inoue first = 0; 1464a96bd784SHajimu UMEMOTO n = snprintf(p, ep - p, "%dm", mins); 1465a96bd784SHajimu UMEMOTO if (n < 0 || n >= ep - p) 1466a96bd784SHajimu UMEMOTO return "?"; 1467a96bd784SHajimu UMEMOTO p += n; 14689a4365d0SYoshinobu Inoue } 1469a96bd784SHajimu UMEMOTO snprintf(p, ep - p, "%ds", secs); 14709a4365d0SYoshinobu Inoue 14719a4365d0SYoshinobu Inoue return(result); 14729a4365d0SYoshinobu Inoue } 14739a4365d0SYoshinobu Inoue 14749a4365d0SYoshinobu Inoue /* 14759a4365d0SYoshinobu Inoue * Print the timestamp 14769a4365d0SYoshinobu Inoue * from tcpdump/util.c 14779a4365d0SYoshinobu Inoue */ 14789a4365d0SYoshinobu Inoue static void 1479bfc75db0SAndrey V. Elsukov ts_print(const struct timeval *tvp) 14809a4365d0SYoshinobu Inoue { 14817ae43b31SRenato Botelho int sec; 14829a4365d0SYoshinobu Inoue 14839a4365d0SYoshinobu Inoue /* Default */ 14847ae43b31SRenato Botelho sec = (tvp->tv_sec + thiszone) % 86400; 1485*e1c7783eSAlexander V. Chernikov xo_emit("{:tv_sec/%lld}{:tv_usec/%lld}%02d:%02d:%02d.%06u ", 1486*e1c7783eSAlexander V. Chernikov tvp->tv_sec, tvp->tv_usec, 14877ae43b31SRenato Botelho sec / 3600, (sec % 3600) / 60, sec % 60, (u_int32_t)tvp->tv_usec); 14889a4365d0SYoshinobu Inoue } 14896e6b3f7cSQing Li 14906e6b3f7cSQing Li #undef NEXTADDR 1491