1 1.105 martin /* $NetBSD: main.c,v 1.105 2023/08/18 13:18:17 martin Exp $ */ 2 1.8 thorpej 3 1.1 cgd /* 4 1.6 mycroft * Copyright (c) 1983, 1988, 1993 5 1.6 mycroft * Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.42 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.12 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.70 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\ 35 1.70 lukem Regents of the University of California. All rights reserved."); 36 1.1 cgd #endif /* not lint */ 37 1.1 cgd 38 1.1 cgd #ifndef lint 39 1.8 thorpej #if 0 40 1.8 thorpej static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94"; 41 1.8 thorpej #else 42 1.105 martin __RCSID("$NetBSD: main.c,v 1.105 2023/08/18 13:18:17 martin Exp $"); 43 1.8 thorpej #endif 44 1.1 cgd #endif /* not lint */ 45 1.1 cgd 46 1.1 cgd #include <sys/param.h> 47 1.6 mycroft #include <sys/file.h> 48 1.6 mycroft #include <sys/protosw.h> 49 1.1 cgd #include <sys/socket.h> 50 1.6 mycroft 51 1.37 enami #include <net/if.h> 52 1.6 mycroft #include <netinet/in.h> 53 1.6 mycroft 54 1.6 mycroft #include <ctype.h> 55 1.15 mrg #include <err.h> 56 1.1 cgd #include <errno.h> 57 1.6 mycroft #include <kvm.h> 58 1.6 mycroft #include <limits.h> 59 1.1 cgd #include <netdb.h> 60 1.1 cgd #include <nlist.h> 61 1.6 mycroft #include <paths.h> 62 1.1 cgd #include <stdio.h> 63 1.1 cgd #include <stdlib.h> 64 1.1 cgd #include <string.h> 65 1.6 mycroft #include <unistd.h> 66 1.6 mycroft #include "netstat.h" 67 1.93 christos #include "rtutil.h" 68 1.77 pooka #include "prog_ops.h" 69 1.1 cgd 70 1.100 joerg int Aflag; 71 1.100 joerg int aflag; 72 1.100 joerg int Bflag; 73 1.100 joerg int bflag; 74 1.100 joerg int dflag; 75 1.100 joerg #ifndef SMALL 76 1.100 joerg int gflag; 77 1.100 joerg #endif 78 1.100 joerg int hflag; 79 1.100 joerg int iflag; 80 1.100 joerg int Lflag; 81 1.100 joerg int lflag; 82 1.100 joerg int mflag; 83 1.100 joerg int numeric_addr; 84 1.100 joerg int numeric_port; 85 1.100 joerg int nflag; 86 1.100 joerg int Pflag; 87 1.100 joerg int pflag; 88 1.100 joerg int qflag; 89 1.100 joerg int rflag; 90 1.100 joerg int sflag; 91 1.100 joerg int tagflag; 92 1.100 joerg int tflag; 93 1.100 joerg int Vflag; 94 1.100 joerg int vflag; 95 1.100 joerg 96 1.100 joerg char *interface; 97 1.100 joerg 98 1.100 joerg int af; 99 1.100 joerg int use_sysctl; 100 1.100 joerg int force_sysctl; 101 1.100 joerg 102 1.1 cgd struct nlist nl[] = { 103 1.1 cgd #define N_MBSTAT 0 104 1.71 lukem { "_mbstat", 0, 0, 0, 0 }, 105 1.1 cgd #define N_IPSTAT 1 106 1.71 lukem { "_ipstat", 0, 0, 0, 0 }, /* not available via kvm */ 107 1.7 mycroft #define N_TCBTABLE 2 108 1.71 lukem { "_tcbtable", 0, 0, 0, 0 }, 109 1.1 cgd #define N_TCPSTAT 3 110 1.71 lukem { "_tcpstat", 0, 0, 0, 0 }, /* not available via kvm */ 111 1.7 mycroft #define N_UDBTABLE 4 112 1.71 lukem { "_udbtable", 0, 0, 0, 0 }, 113 1.1 cgd #define N_UDPSTAT 5 114 1.71 lukem { "_udpstat", 0, 0, 0, 0 }, /* not available via kvm */ 115 1.91 rmind #define N_IFNET_LIST 6 116 1.91 rmind { "_ifnet_list", 0, 0, 0, 0 }, 117 1.85 joerg #define N_ICMPSTAT 7 118 1.71 lukem { "_icmpstat", 0, 0, 0, 0 }, /* not available via kvm */ 119 1.85 joerg #define N_RTSTAT 8 120 1.71 lukem { "_rtstat", 0, 0, 0, 0 }, 121 1.85 joerg #define N_UNIXSW 9 122 1.71 lukem { "_unixsw", 0, 0, 0, 0 }, 123 1.85 joerg #define N_RTREE 10 124 1.71 lukem { "_rt_tables", 0, 0, 0, 0 }, 125 1.85 joerg #define N_NFILE 11 126 1.71 lukem { "_nfile", 0, 0, 0, 0 }, 127 1.85 joerg #define N_IGMPSTAT 12 128 1.71 lukem { "_igmpstat", 0, 0, 0, 0 }, /* not available via kvm */ 129 1.85 joerg #define N_MRTPROTO 13 130 1.71 lukem { "_ip_mrtproto", 0, 0, 0, 0 }, 131 1.85 joerg #define N_MRTSTAT 14 132 1.71 lukem { "_mrtstat", 0, 0, 0, 0 }, 133 1.85 joerg #define N_MFCHASHTBL 15 134 1.71 lukem { "_mfchashtbl", 0, 0, 0, 0 }, 135 1.85 joerg #define N_MFCHASH 16 136 1.71 lukem { "_mfchash", 0, 0, 0, 0 }, 137 1.85 joerg #define N_VIFTABLE 17 138 1.71 lukem { "_viftable", 0, 0, 0, 0 }, 139 1.85 joerg #define N_MSIZE 18 140 1.71 lukem { "_msize", 0, 0, 0, 0 }, 141 1.85 joerg #define N_MCLBYTES 19 142 1.71 lukem { "_mclbytes", 0, 0, 0, 0 }, 143 1.85 joerg #define N_DDPSTAT 20 144 1.71 lukem { "_ddpstat", 0, 0, 0, 0 }, /* not available via kvm */ 145 1.85 joerg #define N_DDPCB 21 146 1.71 lukem { "_ddpcb", 0, 0, 0, 0 }, 147 1.85 joerg #define N_MBPOOL 22 148 1.71 lukem { "_mbpool", 0, 0, 0, 0 }, 149 1.85 joerg #define N_MCLPOOL 23 150 1.71 lukem { "_mclpool", 0, 0, 0, 0 }, 151 1.85 joerg #define N_IP6STAT 24 152 1.71 lukem { "_ip6stat", 0, 0, 0, 0 }, /* not available via kvm */ 153 1.85 joerg #define N_TCP6STAT 25 154 1.71 lukem { "_tcp6stat", 0, 0, 0, 0 }, /* not available via kvm */ 155 1.85 joerg #define N_UDP6STAT 26 156 1.71 lukem { "_udp6stat", 0, 0, 0, 0 }, /* not available via kvm */ 157 1.85 joerg #define N_ICMP6STAT 27 158 1.71 lukem { "_icmp6stat", 0, 0, 0, 0 }, /* not available via kvm */ 159 1.85 joerg #define N_IPSECSTAT 28 160 1.71 lukem { "_ipsecstat", 0, 0, 0, 0 }, /* not available via kvm */ 161 1.85 joerg #define N_IPSEC6STAT 29 162 1.71 lukem { "_ipsec6stat", 0, 0, 0, 0 }, /* not available via kvm */ 163 1.85 joerg #define N_PIM6STAT 30 164 1.71 lukem { "_pim6stat", 0, 0, 0, 0 }, /* not available via kvm */ 165 1.85 joerg #define N_MRT6PROTO 31 166 1.71 lukem { "_ip6_mrtproto", 0, 0, 0, 0 }, 167 1.85 joerg #define N_MRT6STAT 32 168 1.71 lukem { "_mrt6stat", 0, 0, 0, 0 }, 169 1.85 joerg #define N_MF6CTABLE 33 170 1.71 lukem { "_mf6ctable", 0, 0, 0, 0 }, 171 1.85 joerg #define N_MIF6TABLE 34 172 1.71 lukem { "_mif6table", 0, 0, 0, 0 }, 173 1.85 joerg #define N_PFKEYSTAT 35 174 1.71 lukem { "_pfkeystat", 0, 0, 0, 0 }, /* not available via kvm */ 175 1.85 joerg #define N_ARPSTAT 36 176 1.71 lukem { "_arpstat", 0, 0, 0, 0 }, /* not available via kvm */ 177 1.85 joerg #define N_RIP6STAT 37 178 1.71 lukem { "_rip6stat", 0, 0, 0, 0 }, /* not available via kvm */ 179 1.85 joerg #define N_ARPINTRQ 38 180 1.71 lukem { "_arpintrq", 0, 0, 0, 0 }, 181 1.99 christos #define N_ATINTRQ1 39 182 1.71 lukem { "_atintrq1", 0, 0, 0, 0 }, 183 1.99 christos #define N_ATINTRQ2 40 184 1.71 lukem { "_atintrq2", 0, 0, 0, 0 }, 185 1.101 simonb #define N_PPPOEDISCINQ 41 186 1.71 lukem { "_ppoediscinq", 0, 0, 0, 0 }, 187 1.101 simonb #define N_PPPOEINQ 42 188 1.71 lukem { "_ppoeinq", 0, 0, 0, 0 }, 189 1.101 simonb #define N_HARDCLOCK_TICKS 43 190 1.71 lukem { "_hardclock_ticks", 0, 0, 0, 0 }, 191 1.101 simonb #define N_PIMSTAT 44 192 1.71 lukem { "_pimstat", 0, 0, 0, 0 }, 193 1.101 simonb #define N_CARPSTAT 45 194 1.71 lukem { "_carpstats", 0, 0, 0, 0 }, /* not available via kvm */ 195 1.101 simonb #define N_PFSYNCSTAT 46 196 1.73 degroote { "_pfsyncstats", 0, 0, 0, 0}, /* not available via kvm */ 197 1.71 lukem { "", 0, 0, 0, 0 }, 198 1.1 cgd }; 199 1.1 cgd 200 1.1 cgd struct protox { 201 1.1 cgd u_char pr_index; /* index into nlist of cb head */ 202 1.1 cgd u_char pr_sindex; /* index into nlist of stat block */ 203 1.1 cgd u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 204 1.11 christos void (*pr_cblocks) /* control blocks printing routine */ 205 1.98 christos (u_long, const char *); 206 1.11 christos void (*pr_stats) /* statistics printing routine */ 207 1.98 christos (u_long, const char *); 208 1.102 msaitoh void (*pr_istats) /* per/if statistics printing routine */ 209 1.102 msaitoh (const char *); 210 1.14 thorpej void (*pr_dump) /* PCB state dump routine */ 211 1.98 christos (u_long, const char *, u_long); 212 1.71 lukem const char *pr_name; /* well-known name */ 213 1.1 cgd } protox[] = { 214 1.7 mycroft { N_TCBTABLE, N_TCPSTAT, 1, protopr, 215 1.25 itojun tcp_stats, NULL, tcp_dump, "tcp" }, 216 1.7 mycroft { N_UDBTABLE, N_UDPSTAT, 1, protopr, 217 1.25 itojun udp_stats, NULL, 0, "udp" }, 218 1.1 cgd { -1, N_IPSTAT, 1, 0, 219 1.25 itojun ip_stats, NULL, 0, "ip" }, 220 1.1 cgd { -1, N_ICMPSTAT, 1, 0, 221 1.25 itojun icmp_stats, NULL, 0, "icmp" }, 222 1.4 brezak { -1, N_IGMPSTAT, 1, 0, 223 1.25 itojun igmp_stats, NULL, 0, "igmp" }, 224 1.52 liamjfoy { -1, N_CARPSTAT, 1, 0, 225 1.52 liamjfoy carp_stats, NULL, 0, "carp" }, 226 1.23 itojun #ifdef IPSEC 227 1.23 itojun { -1, N_IPSECSTAT, 1, 0, 228 1.83 drochner fast_ipsec_stats, NULL, 0, "ipsec" }, 229 1.23 itojun #endif 230 1.47 manu { -1, N_PIMSTAT, 1, 0, 231 1.47 manu pim_stats, NULL, 0, "pim" }, 232 1.73 degroote { -1, N_PFSYNCSTAT, 1, 0, 233 1.102 msaitoh pfsync_stats, NULL, 0, "pfsync" }, 234 1.1 cgd { -1, -1, 0, 0, 235 1.25 itojun 0, NULL, 0, 0 } 236 1.1 cgd }; 237 1.1 cgd 238 1.23 itojun #ifdef INET6 239 1.23 itojun struct protox ip6protox[] = { 240 1.23 itojun { -1, N_IP6STAT, 1, 0, 241 1.25 itojun ip6_stats, ip6_ifstats, 0, "ip6" }, 242 1.23 itojun { -1, N_ICMP6STAT, 1, 0, 243 1.25 itojun icmp6_stats, icmp6_ifstats, 0, "icmp6" }, 244 1.23 itojun #ifdef TCP6 245 1.43 itojun { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr, 246 1.25 itojun tcp6_stats, NULL, tcp6_dump, "tcp6" }, 247 1.23 itojun #else 248 1.43 itojun { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr, 249 1.88 christos tcp_stats, NULL, tcp6_dump, "tcp6" }, 250 1.23 itojun #endif 251 1.43 itojun { N_UDBTABLE, N_UDP6STAT, 1, ip6protopr, 252 1.25 itojun udp6_stats, NULL, 0, "udp6" }, 253 1.23 itojun #ifdef IPSEC 254 1.23 itojun { -1, N_IPSEC6STAT, 1, 0, 255 1.83 drochner fast_ipsec_stats, NULL, 0, "ipsec6" }, 256 1.23 itojun #endif 257 1.23 itojun { -1, N_PIM6STAT, 1, 0, 258 1.25 itojun pim6_stats, NULL, 0, "pim6" }, 259 1.34 itojun { -1, N_RIP6STAT, 1, 0, 260 1.34 itojun rip6_stats, NULL, 0, "rip6" }, 261 1.23 itojun { -1, -1, 0, 0, 262 1.25 itojun 0, NULL, 0, 0 } 263 1.23 itojun }; 264 1.23 itojun #endif 265 1.23 itojun 266 1.29 jhawk struct protox arpprotox[] = { 267 1.29 jhawk { -1, N_ARPSTAT, 1, 0, 268 1.29 jhawk arp_stats, NULL, 0, "arp" }, 269 1.31 itojun { -1, -1, 0, 0, 270 1.31 itojun 0, NULL, 0, 0 } 271 1.29 jhawk }; 272 1.29 jhawk 273 1.26 itojun #ifdef IPSEC 274 1.26 itojun struct protox pfkeyprotox[] = { 275 1.26 itojun { -1, N_PFKEYSTAT, 1, 0, 276 1.26 itojun pfkey_stats, NULL, 0, "pfkey" }, 277 1.26 itojun { -1, -1, 0, 0, 278 1.26 itojun 0, NULL, 0, 0 } 279 1.26 itojun }; 280 1.26 itojun #endif 281 1.26 itojun 282 1.18 mrg #ifndef SMALL 283 1.11 christos struct protox atalkprotox[] = { 284 1.11 christos { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, 285 1.25 itojun ddp_stats, NULL, 0, "ddp" }, 286 1.11 christos { -1, -1, 0, 0, 287 1.71 lukem 0, NULL, 0, NULL } 288 1.11 christos }; 289 1.18 mrg #endif 290 1.1 cgd 291 1.18 mrg struct protox *protoprotox[] = { protox, 292 1.23 itojun #ifdef INET6 293 1.23 itojun ip6protox, 294 1.23 itojun #endif 295 1.29 jhawk arpprotox, 296 1.26 itojun #ifdef IPSEC 297 1.26 itojun pfkeyprotox, 298 1.26 itojun #endif 299 1.18 mrg #ifndef SMALL 300 1.59 matt atalkprotox, 301 1.18 mrg #endif 302 1.18 mrg NULL }; 303 1.1 cgd 304 1.37 enami const struct softintrq { 305 1.37 enami const char *siq_name; 306 1.37 enami int siq_index; 307 1.37 enami } softintrq[] = { 308 1.37 enami { "arpintrq", N_ARPINTRQ }, 309 1.37 enami { "atintrq1", N_ATINTRQ1 }, 310 1.37 enami { "atintrq2", N_ATINTRQ2 }, 311 1.38 enami { "ppoediscinq", N_PPPOEDISCINQ }, 312 1.38 enami { "ppoeinq", N_PPPOEINQ }, 313 1.37 enami { NULL, -1 }, 314 1.37 enami }; 315 1.37 enami 316 1.98 christos static void printproto(struct protox *, const char *); 317 1.98 christos static void print_softintrq(void); 318 1.81 joerg __dead static void usage(void); 319 1.98 christos static struct protox *name2protox(const char *); 320 1.98 christos static struct protox *knownname(const char *); 321 1.78 dyoung static void prepare(const char *, const char *, struct protox *tp); 322 1.79 dyoung static kvm_t *prepare_kvmd(const char *, const char *, char *); 323 1.1 cgd 324 1.79 dyoung static kvm_t *kvmd = NULL; 325 1.62 elad gid_t egid; 326 1.71 lukem int interval; /* repeat interval for i/f stats */ 327 1.78 dyoung static const char *nlistf = NULL, *memf = NULL; 328 1.62 elad 329 1.78 dyoung kvm_t * 330 1.78 dyoung get_kvmd(void) 331 1.78 dyoung { 332 1.79 dyoung char buf[_POSIX2_LINE_MAX]; 333 1.79 dyoung 334 1.79 dyoung if (kvmd != NULL) 335 1.79 dyoung return kvmd; 336 1.79 dyoung if ((kvmd = prepare_kvmd(nlistf, memf, buf)) == NULL) 337 1.80 njoly errx(1, "kvm error: %s", buf); 338 1.79 dyoung return kvmd; 339 1.78 dyoung } 340 1.78 dyoung 341 1.78 dyoung static kvm_t * 342 1.79 dyoung prepare_kvmd(const char *nf, const char *mf, char *errbuf) 343 1.62 elad { 344 1.79 dyoung kvm_t *k; 345 1.62 elad 346 1.78 dyoung (void)setegid(egid); 347 1.79 dyoung k = kvm_openfiles(nf, mf, NULL, O_RDONLY, errbuf); 348 1.78 dyoung (void)setgid(getgid()); 349 1.79 dyoung return k; 350 1.78 dyoung } 351 1.78 dyoung 352 1.78 dyoung void 353 1.78 dyoung prepare(const char *nf, const char *mf, struct protox *tp) 354 1.78 dyoung { 355 1.79 dyoung char buf[_POSIX2_LINE_MAX]; 356 1.103 msaitoh 357 1.62 elad /* 358 1.62 elad * Try to figure out if we can use sysctl or not. 359 1.62 elad */ 360 1.92 enami if (nf != NULL || mf != NULL) { 361 1.72 elad /* Of course, we can't use sysctl with dumps. */ 362 1.72 elad if (force_sysctl) 363 1.72 elad errx(EXIT_FAILURE, "can't use sysctl with dumps"); 364 1.72 elad 365 1.92 enami /* 366 1.92 enami * If we have -M or -N, we're not dealing with live memory 367 1.92 enami * or want to use kvm interface explicitly. It is sometimes 368 1.92 enami * useful to dig inside of kernel without extending 369 1.92 enami * sysctl interface (i.e., without rebuilding kernel). 370 1.92 enami */ 371 1.62 elad use_sysctl = 0; 372 1.79 dyoung } else if (qflag || 373 1.63 elad #ifndef SMALL 374 1.62 elad gflag || 375 1.64 mlelstv #endif 376 1.64 mlelstv (pflag && tp->pr_sindex == N_PIMSTAT) || 377 1.62 elad Pflag) { 378 1.62 elad /* These flags are not yet supported via sysctl(3). */ 379 1.62 elad use_sysctl = 0; 380 1.62 elad } else { 381 1.62 elad /* We can use sysctl(3). */ 382 1.62 elad use_sysctl = 1; 383 1.62 elad } 384 1.62 elad 385 1.72 elad if (force_sysctl && !use_sysctl) { 386 1.72 elad /* Let the user know what's about to happen. */ 387 1.103 msaitoh warnx("forcing sysctl usage even though it might not be " 388 1.72 elad "supported"); 389 1.72 elad use_sysctl = 1; 390 1.72 elad } 391 1.72 elad 392 1.79 dyoung kvmd = prepare_kvmd(nf, mf, buf); 393 1.79 dyoung 394 1.62 elad if (!use_sysctl) { 395 1.78 dyoung 396 1.79 dyoung if (kvmd == NULL) 397 1.80 njoly errx(1, "kvm error: %s", buf); 398 1.62 elad if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) { 399 1.78 dyoung if (nf) 400 1.78 dyoung errx(1, "%s: no namelist", nf); 401 1.62 elad else 402 1.62 elad errx(1, "no namelist"); 403 1.62 elad } 404 1.62 elad } else 405 1.62 elad (void)setgid(getgid()); 406 1.62 elad } 407 1.1 cgd 408 1.6 mycroft int 409 1.82 matt main(int argc, char *argv[]) 410 1.1 cgd { 411 1.12 lukem struct protoent *p; 412 1.12 lukem struct protox *tp; /* for printing cblocks & stats */ 413 1.1 cgd int ch; 414 1.62 elad char *cp; 415 1.87 bad char *afname, *afnames; 416 1.14 thorpej u_long pcbaddr; 417 1.6 mycroft 418 1.77 pooka if (prog_init) { 419 1.77 pooka if (prog_init() == -1) 420 1.77 pooka err(1, "init failed"); 421 1.77 pooka force_sysctl = 1; /* cheap trick */ 422 1.77 pooka } 423 1.77 pooka 424 1.62 elad egid = getegid(); 425 1.15 mrg (void)setegid(getgid()); 426 1.12 lukem tp = NULL; 427 1.6 mycroft af = AF_UNSPEC; 428 1.87 bad afnames = NULL; 429 1.14 thorpej pcbaddr = 0; 430 1.1 cgd 431 1.37 enami while ((ch = getopt(argc, argv, 432 1.78 dyoung "AabBdf:ghI:LliM:mN:nP:p:qrsStTuVvw:X")) != -1) 433 1.37 enami switch (ch) { 434 1.1 cgd case 'A': 435 1.94 christos Aflag = RT_AFLAG; 436 1.1 cgd break; 437 1.1 cgd case 'a': 438 1.1 cgd aflag = 1; 439 1.13 kml break; 440 1.13 kml case 'b': 441 1.13 kml bflag = 1; 442 1.1 cgd break; 443 1.49 rpaulo case 'B': 444 1.49 rpaulo Bflag = 1; 445 1.49 rpaulo break; 446 1.1 cgd case 'd': 447 1.1 cgd dflag = 1; 448 1.1 cgd break; 449 1.1 cgd case 'f': 450 1.87 bad afnames = optarg; 451 1.1 cgd break; 452 1.18 mrg #ifndef SMALL 453 1.6 mycroft case 'g': 454 1.6 mycroft gflag = 1; 455 1.1 cgd break; 456 1.18 mrg #endif 457 1.74 pooka case 'h': 458 1.74 pooka hflag = 1; 459 1.74 pooka break; 460 1.9 thorpej case 'I': 461 1.1 cgd iflag = 1; 462 1.9 thorpej interface = optarg; 463 1.1 cgd break; 464 1.1 cgd case 'i': 465 1.1 cgd iflag = 1; 466 1.24 is break; 467 1.24 is case 'L': 468 1.95 christos Lflag = RT_LFLAG; 469 1.1 cgd break; 470 1.23 itojun case 'l': 471 1.23 itojun lflag = 1; 472 1.23 itojun break; 473 1.1 cgd case 'M': 474 1.6 mycroft memf = optarg; 475 1.1 cgd break; 476 1.1 cgd case 'm': 477 1.1 cgd mflag = 1; 478 1.1 cgd break; 479 1.1 cgd case 'N': 480 1.6 mycroft nlistf = optarg; 481 1.1 cgd break; 482 1.1 cgd case 'n': 483 1.93 christos numeric_addr = numeric_port = nflag = RT_NFLAG; 484 1.1 cgd break; 485 1.14 thorpej case 'P': 486 1.41 lukem errno = 0; 487 1.14 thorpej pcbaddr = strtoul(optarg, &cp, 16); 488 1.16 mrg if (*cp != '\0' || errno == ERANGE) 489 1.103 msaitoh errx(1, "invalid PCB address %s", optarg); 490 1.14 thorpej Pflag = 1; 491 1.14 thorpej break; 492 1.1 cgd case 'p': 493 1.16 mrg if ((tp = name2protox(optarg)) == NULL) 494 1.102 msaitoh errx(1, 495 1.102 msaitoh "%s: unknown or uninstrumented protocol", 496 1.16 mrg optarg); 497 1.1 cgd pflag = 1; 498 1.1 cgd break; 499 1.37 enami case 'q': 500 1.37 enami qflag = 1; 501 1.37 enami break; 502 1.1 cgd case 'r': 503 1.1 cgd rflag = 1; 504 1.1 cgd break; 505 1.1 cgd case 's': 506 1.6 mycroft ++sflag; 507 1.1 cgd break; 508 1.33 assar case 'S': 509 1.33 assar numeric_addr = 1; 510 1.33 assar break; 511 1.1 cgd case 't': 512 1.1 cgd tflag = 1; 513 1.1 cgd break; 514 1.75 kefren case 'T': 515 1.94 christos tagflag = RT_TFLAG; 516 1.75 kefren break; 517 1.1 cgd case 'u': 518 1.17 lukem af = AF_LOCAL; 519 1.1 cgd break; 520 1.78 dyoung case 'V': 521 1.78 dyoung Vflag++; 522 1.78 dyoung break; 523 1.19 kml case 'v': 524 1.94 christos vflag = RT_VFLAG; 525 1.19 kml break; 526 1.1 cgd case 'w': 527 1.1 cgd interval = atoi(optarg); 528 1.6 mycroft iflag = 1; 529 1.1 cgd break; 530 1.72 elad case 'X': 531 1.72 elad force_sysctl = 1; 532 1.72 elad break; 533 1.1 cgd case '?': 534 1.1 cgd default: 535 1.1 cgd usage(); 536 1.1 cgd } 537 1.1 cgd argv += optind; 538 1.1 cgd argc -= optind; 539 1.1 cgd 540 1.1 cgd #define BACKWARD_COMPATIBILITY 541 1.1 cgd #ifdef BACKWARD_COMPATIBILITY 542 1.1 cgd if (*argv) { 543 1.48 dsl if (isdigit((unsigned char)**argv)) { 544 1.1 cgd interval = atoi(*argv); 545 1.1 cgd if (interval <= 0) 546 1.1 cgd usage(); 547 1.1 cgd ++argv; 548 1.1 cgd iflag = 1; 549 1.1 cgd } 550 1.1 cgd if (*argv) { 551 1.6 mycroft nlistf = *argv; 552 1.6 mycroft if (*++argv) 553 1.6 mycroft memf = *argv; 554 1.1 cgd } 555 1.1 cgd } 556 1.1 cgd #endif 557 1.6 mycroft 558 1.64 mlelstv prepare(nlistf, memf, tp); 559 1.15 mrg 560 1.51 drochner #ifndef SMALL 561 1.49 rpaulo if (Bflag) { 562 1.49 rpaulo if (sflag) 563 1.105 martin nsbpf_stats(); 564 1.49 rpaulo else 565 1.105 martin nsbpf_dump(interface); 566 1.49 rpaulo exit(0); 567 1.49 rpaulo } 568 1.51 drochner #endif 569 1.49 rpaulo 570 1.1 cgd if (mflag) { 571 1.10 jonathan mbpr(nl[N_MBSTAT].n_value, nl[N_MSIZE].n_value, 572 1.21 sommerfe nl[N_MCLBYTES].n_value, nl[N_MBPOOL].n_value, 573 1.21 sommerfe nl[N_MCLPOOL].n_value); 574 1.1 cgd exit(0); 575 1.1 cgd } 576 1.14 thorpej if (Pflag) { 577 1.14 thorpej if (tp == NULL) { 578 1.14 thorpej /* Default to TCP. */ 579 1.14 thorpej tp = name2protox("tcp"); 580 1.14 thorpej } 581 1.14 thorpej if (tp->pr_dump) 582 1.86 christos (*tp->pr_dump)(nl[tp->pr_index].n_value, tp->pr_name, 583 1.86 christos pcbaddr); 584 1.14 thorpej else 585 1.14 thorpej printf("%s: no PCB dump routine\n", tp->pr_name); 586 1.14 thorpej exit(0); 587 1.14 thorpej } 588 1.1 cgd if (pflag) { 589 1.25 itojun if (iflag && tp->pr_istats) 590 1.102 msaitoh intpr(interval, nl[N_IFNET_LIST].n_value, 591 1.102 msaitoh tp->pr_istats); 592 1.25 itojun else if (tp->pr_stats) 593 1.1 cgd (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 594 1.1 cgd tp->pr_name); 595 1.1 cgd else 596 1.1 cgd printf("%s: no stats routine\n", tp->pr_name); 597 1.1 cgd exit(0); 598 1.1 cgd } 599 1.37 enami if (qflag) { 600 1.37 enami print_softintrq(); 601 1.37 enami exit(0); 602 1.37 enami } 603 1.1 cgd /* 604 1.1 cgd * Keep file descriptors open to avoid overhead 605 1.1 cgd * of open/close on each call to get* routines. 606 1.1 cgd */ 607 1.1 cgd sethostent(1); 608 1.1 cgd setnetent(1); 609 1.87 bad /* 610 1.87 bad * If -f was used afnames != NULL, loop over the address families. 611 1.87 bad * Otherwise do this at least once (with af == AF_UNSPEC). 612 1.87 bad */ 613 1.87 bad afname = NULL; 614 1.87 bad do { 615 1.87 bad if (afnames != NULL) { 616 1.87 bad afname = strsep(&afnames, ","); 617 1.87 bad if (afname == NULL) 618 1.87 bad break; /* Exit early */ 619 1.87 bad if (strcmp(afname, "inet") == 0) 620 1.87 bad af = AF_INET; 621 1.87 bad else if (strcmp(afname, "inet6") == 0) 622 1.87 bad af = AF_INET6; 623 1.87 bad else if (strcmp(afname, "arp") == 0) 624 1.87 bad af = AF_ARP; 625 1.87 bad else if (strcmp(afname, "pfkey") == 0) 626 1.87 bad af = PF_KEY; 627 1.87 bad else if (strcmp(afname, "unix") == 0 628 1.87 bad || strcmp(afname, "local") == 0) 629 1.87 bad af = AF_LOCAL; 630 1.87 bad else if (strcmp(afname, "atalk") == 0) 631 1.87 bad af = AF_APPLETALK; 632 1.87 bad else if (strcmp(afname, "mpls") == 0) 633 1.87 bad af = AF_MPLS; 634 1.87 bad else { 635 1.87 bad warnx("%s: unknown address family", 636 1.87 bad afname); 637 1.87 bad continue; 638 1.87 bad } 639 1.87 bad } 640 1.87 bad 641 1.87 bad if (iflag) { 642 1.87 bad if (af != AF_UNSPEC) 643 1.87 bad goto protostat; 644 1.25 itojun 645 1.91 rmind intpr(interval, nl[N_IFNET_LIST].n_value, NULL); 646 1.87 bad break; 647 1.87 bad } 648 1.87 bad if (rflag) { 649 1.87 bad if (sflag) 650 1.102 msaitoh rt_stats(use_sysctl ? 0 : 651 1.102 msaitoh nl[N_RTSTAT].n_value); 652 1.87 bad else { 653 1.89 christos if (use_sysctl) 654 1.94 christos p_rttables(af, 655 1.95 christos nflag|tagflag|vflag|Lflag, 0, ~0); 656 1.89 christos else 657 1.89 christos routepr(nl[N_RTREE].n_value); 658 1.87 bad } 659 1.87 bad break; 660 1.53 elad } 661 1.18 mrg #ifndef SMALL 662 1.87 bad if (gflag) { 663 1.87 bad if (sflag) { 664 1.87 bad if (af == AF_INET || af == AF_UNSPEC) 665 1.87 bad mrt_stats(nl[N_MRTPROTO].n_value, 666 1.87 bad nl[N_MRTSTAT].n_value); 667 1.23 itojun #ifdef INET6 668 1.87 bad if (af == AF_INET6 || af == AF_UNSPEC) 669 1.87 bad mrt6_stats(nl[N_MRT6PROTO].n_value, 670 1.87 bad nl[N_MRT6STAT].n_value); 671 1.23 itojun #endif 672 1.87 bad } 673 1.87 bad else { 674 1.87 bad if (af == AF_INET || af == AF_UNSPEC) 675 1.87 bad mroutepr(nl[N_MRTPROTO].n_value, 676 1.87 bad nl[N_MFCHASHTBL].n_value, 677 1.87 bad nl[N_MFCHASH].n_value, 678 1.87 bad nl[N_VIFTABLE].n_value); 679 1.23 itojun #ifdef INET6 680 1.87 bad if (af == AF_INET6 || af == AF_UNSPEC) 681 1.87 bad mroute6pr(nl[N_MRT6PROTO].n_value, 682 1.87 bad nl[N_MF6CTABLE].n_value, 683 1.87 bad nl[N_MIF6TABLE].n_value); 684 1.23 itojun #endif 685 1.87 bad } 686 1.87 bad break; 687 1.23 itojun } 688 1.18 mrg #endif 689 1.87 bad protostat: 690 1.87 bad if (af == AF_INET || af == AF_UNSPEC) { 691 1.87 bad setprotoent(1); 692 1.87 bad setservent(1); 693 1.87 bad /* ugh, this is O(MN) ... why do we do this? */ 694 1.87 bad while ((p = getprotoent()) != NULL) { 695 1.87 bad for (tp = protox; tp->pr_name; tp++) 696 1.87 bad if (strcmp(tp->pr_name, p->p_name) == 0) 697 1.87 bad break; 698 1.87 bad if (tp->pr_name == 0 || tp->pr_wanted == 0) 699 1.87 bad continue; 700 1.87 bad printproto(tp, p->p_name); 701 1.87 bad tp->pr_wanted = 0; 702 1.87 bad } 703 1.87 bad endprotoent(); 704 1.6 mycroft for (tp = protox; tp->pr_name; tp++) 705 1.87 bad if (tp->pr_wanted) 706 1.87 bad printproto(tp, tp->pr_name); 707 1.6 mycroft } 708 1.87 bad #ifdef INET6 709 1.87 bad if (af == AF_INET6 || af == AF_UNSPEC) 710 1.87 bad for (tp = ip6protox; tp->pr_name; tp++) 711 1.87 bad printproto(tp, tp->pr_name); 712 1.87 bad #endif 713 1.87 bad if (af == AF_ARP || af == AF_UNSPEC) 714 1.87 bad for (tp = arpprotox; tp->pr_name; tp++) 715 1.23 itojun printproto(tp, tp->pr_name); 716 1.26 itojun #ifdef IPSEC 717 1.87 bad if (af == PF_KEY || af == AF_UNSPEC) 718 1.87 bad for (tp = pfkeyprotox; tp->pr_name; tp++) 719 1.87 bad printproto(tp, tp->pr_name); 720 1.23 itojun #endif 721 1.18 mrg #ifndef SMALL 722 1.87 bad if (af == AF_APPLETALK || af == AF_UNSPEC) 723 1.87 bad for (tp = atalkprotox; tp->pr_name; tp++) 724 1.87 bad printproto(tp, tp->pr_name); 725 1.87 bad if ((af == AF_LOCAL || af == AF_UNSPEC) && !sflag) 726 1.87 bad unixpr(nl[N_UNIXSW].n_value); 727 1.18 mrg #endif 728 1.87 bad } while (afnames != NULL && afname != NULL); 729 1.6 mycroft exit(0); 730 1.6 mycroft } 731 1.4 brezak 732 1.6 mycroft /* 733 1.6 mycroft * Print out protocol statistics or control blocks (per sflag). 734 1.6 mycroft * If the interface was not specifically requested, and the symbol 735 1.6 mycroft * is not in the namelist, ignore this one. 736 1.6 mycroft */ 737 1.6 mycroft static void 738 1.82 matt printproto(struct protox *tp, const char *name) 739 1.6 mycroft { 740 1.98 christos void (*pr)(u_long, const char *); 741 1.6 mycroft u_long off; 742 1.1 cgd 743 1.6 mycroft if (sflag) { 744 1.25 itojun if (iflag) { 745 1.25 itojun if (tp->pr_istats) 746 1.91 rmind intpr(interval, nl[N_IFNET_LIST].n_value, 747 1.102 msaitoh tp->pr_istats); 748 1.25 itojun return; 749 1.25 itojun } 750 1.25 itojun else { 751 1.25 itojun pr = tp->pr_stats; 752 1.25 itojun off = nl[tp->pr_sindex].n_value; 753 1.25 itojun } 754 1.6 mycroft } else { 755 1.6 mycroft pr = tp->pr_cblocks; 756 1.6 mycroft off = nl[tp->pr_index].n_value; 757 1.1 cgd } 758 1.103 msaitoh if (pr != NULL && ((off || af != AF_UNSPEC) || use_sysctl)) 759 1.6 mycroft (*pr)(off, name); 760 1.6 mycroft } 761 1.6 mycroft 762 1.6 mycroft /* 763 1.37 enami * Print softintrq status. 764 1.37 enami */ 765 1.37 enami void 766 1.82 matt print_softintrq(void) 767 1.37 enami { 768 1.37 enami struct ifqueue intrq, *ifq = &intrq; 769 1.37 enami const struct softintrq *siq; 770 1.37 enami u_long off; 771 1.37 enami 772 1.37 enami for (siq = softintrq; siq->siq_name != NULL; siq++) { 773 1.37 enami off = nl[siq->siq_index].n_value; 774 1.37 enami if (off == 0) 775 1.37 enami continue; 776 1.37 enami 777 1.37 enami kread(off, (char *)ifq, sizeof(*ifq)); 778 1.37 enami printf("%s:\n", siq->siq_name); 779 1.37 enami printf("\tqueue length: %d\n", ifq->ifq_len); 780 1.37 enami printf("\tmaximum queue length: %d\n", ifq->ifq_maxlen); 781 1.104 msaitoh printf("\tpackets dropped: %" PRIu64 "\n", ifq->ifq_drops); 782 1.37 enami } 783 1.37 enami } 784 1.37 enami 785 1.37 enami /* 786 1.6 mycroft * Read kernel memory, return 0 on success. 787 1.6 mycroft */ 788 1.6 mycroft int 789 1.82 matt kread(u_long addr, char *buf, int size) 790 1.6 mycroft { 791 1.6 mycroft 792 1.6 mycroft if (kvm_read(kvmd, addr, buf, size) != size) { 793 1.35 itojun warnx("%s", kvm_geterr(kvmd)); 794 1.102 msaitoh return -1; 795 1.1 cgd } 796 1.102 msaitoh return 0; 797 1.1 cgd } 798 1.1 cgd 799 1.71 lukem const char * 800 1.82 matt plural(int n) 801 1.1 cgd { 802 1.16 mrg 803 1.1 cgd return (n != 1 ? "s" : ""); 804 1.1 cgd } 805 1.1 cgd 806 1.71 lukem const char * 807 1.82 matt plurales(int n) 808 1.6 mycroft { 809 1.16 mrg 810 1.6 mycroft return (n != 1 ? "es" : ""); 811 1.39 thorpej } 812 1.39 thorpej 813 1.39 thorpej int 814 1.39 thorpej get_hardticks(void) 815 1.39 thorpej { 816 1.39 thorpej int hardticks; 817 1.39 thorpej 818 1.39 thorpej kread(nl[N_HARDCLOCK_TICKS].n_value, (char *)&hardticks, 819 1.39 thorpej sizeof(hardticks)); 820 1.102 msaitoh return hardticks; 821 1.6 mycroft } 822 1.6 mycroft 823 1.1 cgd /* 824 1.1 cgd * Find the protox for the given "well-known" name. 825 1.1 cgd */ 826 1.6 mycroft static struct protox * 827 1.82 matt knownname(const char *name) 828 1.1 cgd { 829 1.1 cgd struct protox **tpp, *tp; 830 1.1 cgd 831 1.1 cgd for (tpp = protoprotox; *tpp; tpp++) 832 1.6 mycroft for (tp = *tpp; tp->pr_name; tp++) 833 1.6 mycroft if (strcmp(tp->pr_name, name) == 0) 834 1.102 msaitoh return tp; 835 1.102 msaitoh return NULL; 836 1.1 cgd } 837 1.1 cgd 838 1.1 cgd /* 839 1.1 cgd * Find the protox corresponding to name. 840 1.1 cgd */ 841 1.6 mycroft static struct protox * 842 1.82 matt name2protox(const char *name) 843 1.1 cgd { 844 1.1 cgd struct protox *tp; 845 1.1 cgd char **alias; /* alias from p->aliases */ 846 1.1 cgd struct protoent *p; 847 1.1 cgd 848 1.1 cgd /* 849 1.1 cgd * Try to find the name in the list of "well-known" names. If that 850 1.1 cgd * fails, check if name is an alias for an Internet protocol. 851 1.1 cgd */ 852 1.11 christos if ((tp = knownname(name)) != NULL) 853 1.102 msaitoh return tp; 854 1.1 cgd 855 1.1 cgd setprotoent(1); /* make protocol lookup cheaper */ 856 1.11 christos while ((p = getprotoent()) != NULL) { 857 1.1 cgd /* assert: name not same as p->name */ 858 1.1 cgd for (alias = p->p_aliases; *alias; alias++) 859 1.1 cgd if (strcmp(name, *alias) == 0) { 860 1.1 cgd endprotoent(); 861 1.102 msaitoh return knownname(p->p_name); 862 1.1 cgd } 863 1.1 cgd } 864 1.1 cgd endprotoent(); 865 1.102 msaitoh return NULL; 866 1.1 cgd } 867 1.1 cgd 868 1.6 mycroft static void 869 1.82 matt usage(void) 870 1.1 cgd { 871 1.32 cgd const char *progname = getprogname(); 872 1.32 cgd 873 1.1 cgd (void)fprintf(stderr, 874 1.87 bad "usage: %s [-Aan] [-f address_family[,family ...]] [-M core] [-N system]\n", progname); 875 1.1 cgd (void)fprintf(stderr, 876 1.102 msaitoh " %s [-bdgiLmnqrsSv] [-f address_family[,family ...]] [-M core] [-N system]\n", 877 1.32 cgd progname); 878 1.1 cgd (void)fprintf(stderr, 879 1.36 soren " %s [-dn] [-I interface] [-M core] [-N system] [-w wait]\n", progname); 880 1.1 cgd (void)fprintf(stderr, 881 1.36 soren " %s [-p protocol] [-M core] [-N system]\n", progname); 882 1.14 thorpej (void)fprintf(stderr, 883 1.36 soren " %s [-p protocol] [-M core] [-N system] -P pcbaddr\n", progname); 884 1.36 soren (void)fprintf(stderr, 885 1.36 soren " %s [-p protocol] [-i] [-I Interface] \n", progname); 886 1.36 soren (void)fprintf(stderr, 887 1.87 bad " %s [-s] [-f address_family[,family ...]] [-i] [-I Interface]\n", progname); 888 1.49 rpaulo (void)fprintf(stderr, 889 1.49 rpaulo " %s [-s] [-B] [-I interface]\n", progname); 890 1.1 cgd exit(1); 891 1.1 cgd } 892