1 1.32 ozaki /* $NetBSD: netstat.c,v 1.32 2022/10/28 05:27:17 ozaki-r Exp $ */ 2 1.2 jtc 3 1.1 jtc /*- 4 1.1 jtc * Copyright (c) 1980, 1992, 1993 5 1.1 jtc * The Regents of the University of California. All rights reserved. 6 1.1 jtc * 7 1.1 jtc * Redistribution and use in source and binary forms, with or without 8 1.1 jtc * modification, are permitted provided that the following conditions 9 1.1 jtc * are met: 10 1.1 jtc * 1. Redistributions of source code must retain the above copyright 11 1.1 jtc * notice, this list of conditions and the following disclaimer. 12 1.1 jtc * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jtc * notice, this list of conditions and the following disclaimer in the 14 1.1 jtc * documentation and/or other materials provided with the distribution. 15 1.24 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 jtc * may be used to endorse or promote products derived from this software 17 1.1 jtc * without specific prior written permission. 18 1.1 jtc * 19 1.1 jtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 jtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 jtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 jtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 jtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 jtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 jtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 jtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 jtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 jtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 jtc * SUCH DAMAGE. 30 1.1 jtc */ 31 1.1 jtc 32 1.7 mrg #include <sys/cdefs.h> 33 1.1 jtc #ifndef lint 34 1.2 jtc #if 0 35 1.1 jtc static char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; 36 1.2 jtc #endif 37 1.32 ozaki __RCSID("$NetBSD: netstat.c,v 1.32 2022/10/28 05:27:17 ozaki-r Exp $"); 38 1.1 jtc #endif /* not lint */ 39 1.1 jtc 40 1.1 jtc /* 41 1.1 jtc * netstat 42 1.1 jtc */ 43 1.1 jtc #include <sys/param.h> 44 1.1 jtc #include <sys/socketvar.h> 45 1.1 jtc #include <sys/mbuf.h> 46 1.1 jtc #include <sys/protosw.h> 47 1.1 jtc 48 1.1 jtc #include <netinet/in.h> 49 1.7 mrg 50 1.7 mrg #include <arpa/inet.h> 51 1.1 jtc #include <net/route.h> 52 1.7 mrg 53 1.1 jtc #include <netinet/in_systm.h> 54 1.1 jtc #include <netinet/ip.h> 55 1.1 jtc #include <netinet/in_pcb.h> 56 1.1 jtc #include <netinet/ip_icmp.h> 57 1.1 jtc #include <netinet/icmp_var.h> 58 1.1 jtc #include <netinet/ip_var.h> 59 1.15 itojun #ifdef INET6 60 1.15 itojun #include <netinet/ip6.h> 61 1.15 itojun #include <netinet6/in6_pcb.h> 62 1.15 itojun #endif 63 1.1 jtc #include <netinet/tcp.h> 64 1.1 jtc #include <netinet/tcp_seq.h> 65 1.1 jtc #define TCPSTATES 66 1.1 jtc #include <netinet/tcp_fsm.h> 67 1.1 jtc #include <netinet/tcp_timer.h> 68 1.1 jtc #include <netinet/tcp_var.h> 69 1.1 jtc #include <netinet/tcp_debug.h> 70 1.1 jtc #include <netinet/udp.h> 71 1.1 jtc #include <netinet/udp_var.h> 72 1.1 jtc 73 1.1 jtc #include <netdb.h> 74 1.1 jtc #include <stdlib.h> 75 1.1 jtc #include <string.h> 76 1.20 simonb 77 1.1 jtc #include "systat.h" 78 1.1 jtc #include "extern.h" 79 1.1 jtc 80 1.19 ad static void fetchnetstat4(void *, int); 81 1.27 dsl static void enter(struct inpcb *, struct socket *, int, const char *); 82 1.19 ad static const char *inetname(struct in_addr); 83 1.27 dsl static void inetprint(struct in_addr *, int, const char *); 84 1.19 ad #ifdef INET6 85 1.19 ad static void fetchnetstat6(void *, int); 86 1.31 ozaki static void enter6(struct inpcb *, struct socket *, int, const char *); 87 1.19 ad static const char *inet6name(struct in6_addr *); 88 1.27 dsl static void inet6print(struct in6_addr *, int, const char *); 89 1.15 itojun #endif 90 1.1 jtc 91 1.1 jtc #define streq(a,b) (strcmp(a,b)==0) 92 1.1 jtc 93 1.1 jtc struct netinfo { 94 1.1 jtc struct netinfo *ni_forw, *ni_prev; 95 1.15 itojun int ni_family; 96 1.1 jtc short ni_line; /* line on screen */ 97 1.1 jtc short ni_seen; /* 0 when not present in list */ 98 1.1 jtc short ni_flags; 99 1.1 jtc #define NIF_LACHG 0x1 /* local address changed */ 100 1.1 jtc #define NIF_FACHG 0x2 /* foreign address changed */ 101 1.1 jtc short ni_state; /* tcp state */ 102 1.27 dsl const char *ni_proto; /* protocol */ 103 1.1 jtc struct in_addr ni_laddr; /* local address */ 104 1.15 itojun #ifdef INET6 105 1.15 itojun struct in6_addr ni_laddr6; /* local address */ 106 1.15 itojun #endif 107 1.1 jtc long ni_lport; /* local port */ 108 1.1 jtc struct in_addr ni_faddr; /* foreign address */ 109 1.15 itojun #ifdef INET6 110 1.15 itojun struct in6_addr ni_faddr6; /* foreign address */ 111 1.15 itojun #endif 112 1.1 jtc long ni_fport; /* foreign port */ 113 1.1 jtc long ni_rcvcc; /* rcv buffer character count */ 114 1.1 jtc long ni_sndcc; /* snd buffer character count */ 115 1.1 jtc }; 116 1.1 jtc 117 1.1 jtc static struct { 118 1.1 jtc struct netinfo *ni_forw, *ni_prev; 119 1.1 jtc } netcb; 120 1.1 jtc 121 1.26 christos struct netinfo *nhead; 122 1.26 christos 123 1.1 jtc static int aflag = 0; 124 1.16 itojun int nflag = 0; 125 1.1 jtc static int lastrow = 1; 126 1.1 jtc 127 1.9 mrg WINDOW * 128 1.19 ad opennetstat(void) 129 1.9 mrg { 130 1.9 mrg 131 1.9 mrg sethostent(1); 132 1.9 mrg setnetent(1); 133 1.21 dsl return (subwin(stdscr, -1, 0, 5, 0)); 134 1.9 mrg } 135 1.9 mrg 136 1.1 jtc void 137 1.19 ad closenetstat(WINDOW *w) 138 1.1 jtc { 139 1.8 lukem struct netinfo *p; 140 1.1 jtc 141 1.1 jtc endhostent(); 142 1.1 jtc endnetent(); 143 1.26 christos p = netcb.ni_forw; 144 1.26 christos while (p != nhead) { 145 1.1 jtc if (p->ni_line != -1) 146 1.1 jtc lastrow--; 147 1.1 jtc p->ni_line = -1; 148 1.1 jtc p = p->ni_forw; 149 1.1 jtc } 150 1.5 scottr if (w != NULL) { 151 1.1 jtc wclear(w); 152 1.1 jtc wrefresh(w); 153 1.1 jtc delwin(w); 154 1.1 jtc } 155 1.1 jtc } 156 1.1 jtc 157 1.1 jtc static struct nlist namelist[] = { 158 1.3 cgd #define X_TCBTABLE 0 159 1.28 christos { .n_name = "_tcbtable" }, 160 1.3 cgd #define X_UDBTABLE 1 161 1.28 christos { .n_name = "_udbtable" }, 162 1.28 christos { .n_name = NULL }, 163 1.1 jtc }; 164 1.1 jtc 165 1.1 jtc int 166 1.19 ad initnetstat(void) 167 1.1 jtc { 168 1.17 itojun int n; 169 1.17 itojun 170 1.17 itojun n = kvm_nlist(kd, namelist); 171 1.17 itojun if (n < 0) { 172 1.1 jtc nlisterr(namelist); 173 1.1 jtc return(0); 174 1.17 itojun } else if (n == sizeof(namelist) / sizeof(namelist[0]) - 1) { 175 1.1 jtc error("No symbols in namelist"); 176 1.1 jtc return(0); 177 1.1 jtc } 178 1.17 itojun 179 1.26 christos nhead = (struct netinfo *)(void *)&netcb; 180 1.26 christos 181 1.26 christos netcb.ni_forw = netcb.ni_prev = nhead; 182 1.1 jtc protos = TCP|UDP; 183 1.1 jtc return(1); 184 1.1 jtc } 185 1.1 jtc 186 1.1 jtc void 187 1.19 ad fetchnetstat(void) 188 1.1 jtc { 189 1.8 lukem struct netinfo *p; 190 1.1 jtc 191 1.3 cgd if (namelist[X_TCBTABLE].n_value == 0) 192 1.1 jtc return; 193 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) 194 1.1 jtc p->ni_seen = 0; 195 1.17 itojun 196 1.17 itojun if ((protos & (TCP | UDP)) == 0) { 197 1.1 jtc error("No protocols to display"); 198 1.1 jtc return; 199 1.1 jtc } 200 1.17 itojun if ((protos & TCP) && namelist[X_TCBTABLE].n_type) 201 1.17 itojun fetchnetstat4(NPTR(X_TCBTABLE), 1); 202 1.17 itojun if ((protos & UDP) && namelist[X_UDBTABLE].n_type) 203 1.17 itojun fetchnetstat4(NPTR(X_UDBTABLE), 0); 204 1.17 itojun #ifdef INET6 205 1.25 itojun if ((protos & TCP) && namelist[X_TCBTABLE].n_type) 206 1.25 itojun fetchnetstat6(NPTR(X_TCBTABLE), 1); 207 1.25 itojun if ((protos & UDP) && namelist[X_UDBTABLE].n_type) 208 1.25 itojun fetchnetstat6(NPTR(X_UDBTABLE), 0); 209 1.17 itojun #endif 210 1.17 itojun } 211 1.17 itojun 212 1.17 itojun static void 213 1.19 ad fetchnetstat4(void *off, int istcp) 214 1.17 itojun { 215 1.17 itojun struct inpcbtable pcbtable; 216 1.31 ozaki struct inpcb **pprev, *next; 217 1.17 itojun struct netinfo *p; 218 1.32 ozaki struct inpcb *inpcbp, *inp; 219 1.32 ozaki struct in4pcb in4pcb; 220 1.17 itojun struct socket sockb; 221 1.17 itojun struct tcpcb tcpcb; 222 1.17 itojun 223 1.11 ross KREAD(off, &pcbtable, sizeof pcbtable); 224 1.29 mlelstv pprev = &((struct inpcbtable *)off)->inpt_queue.tqh_first; 225 1.29 mlelstv next = TAILQ_FIRST(&pcbtable.inpt_queue); 226 1.29 mlelstv while (next != TAILQ_END(&pcbtable.inpt_queue)) { 227 1.29 mlelstv inpcbp = (struct inpcb *)next; 228 1.32 ozaki KREAD(inpcbp, &in4pcb, sizeof (in4pcb)); 229 1.32 ozaki inp = (struct inpcb *)&in4pcb; 230 1.32 ozaki if (inp->inp_queue.tqe_prev != pprev) { 231 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) 232 1.1 jtc p->ni_seen = 1; 233 1.1 jtc error("Kernel state in transition"); 234 1.1 jtc return; 235 1.1 jtc } 236 1.31 ozaki pprev = &next->inp_queue.tqe_next; 237 1.32 ozaki next = inp->inp_queue.tqe_next; 238 1.3 cgd 239 1.32 ozaki if (inp->inp_af != AF_INET) 240 1.25 itojun continue; 241 1.32 ozaki if (!aflag && inet_lnaof(in4p_laddr(inp)) == INADDR_ANY) 242 1.1 jtc continue; 243 1.32 ozaki if (nhosts && !checkhost(inp)) 244 1.1 jtc continue; 245 1.32 ozaki if (nports && !checkport(inp)) 246 1.1 jtc continue; 247 1.32 ozaki KREAD(inp->inp_socket, &sockb, sizeof (sockb)); 248 1.1 jtc if (istcp) { 249 1.32 ozaki KREAD(inp->inp_ppcb, &tcpcb, sizeof (tcpcb)); 250 1.32 ozaki enter(inp, &sockb, tcpcb.t_state, "tcp"); 251 1.1 jtc } else 252 1.32 ozaki enter(inp, &sockb, 0, "udp"); 253 1.1 jtc } 254 1.17 itojun } 255 1.15 itojun 256 1.15 itojun #ifdef INET6 257 1.17 itojun static void 258 1.19 ad fetchnetstat6(void *off, int istcp) 259 1.17 itojun { 260 1.25 itojun struct inpcbtable pcbtable; 261 1.31 ozaki struct inpcb **pprev, *next; 262 1.17 itojun struct netinfo *p; 263 1.17 itojun struct socket sockb; 264 1.17 itojun struct tcpcb tcpcb; 265 1.32 ozaki struct inpcb *inp, *inpcbp; 266 1.32 ozaki struct in6pcb in6pcb; 267 1.17 itojun 268 1.25 itojun KREAD(off, &pcbtable, sizeof pcbtable); 269 1.29 mlelstv pprev = &((struct inpcbtable *)off)->inpt_queue.tqh_first; 270 1.29 mlelstv next = TAILQ_FIRST(&pcbtable.inpt_queue); 271 1.29 mlelstv while (next != TAILQ_END(&pcbtable.inpt_queue)) { 272 1.31 ozaki inpcbp = (struct inpcb *)next; 273 1.32 ozaki KREAD(inpcbp, &in6pcb, sizeof (in6pcb)); 274 1.32 ozaki inp = (struct inpcb *)&in6pcb; 275 1.32 ozaki if (inp->inp_queue.tqe_prev != pprev) { 276 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) 277 1.15 itojun p->ni_seen = 1; 278 1.15 itojun error("Kernel state in transition"); 279 1.15 itojun return; 280 1.15 itojun } 281 1.31 ozaki pprev = &next->inp_queue.tqe_next; 282 1.32 ozaki next = inp->inp_queue.tqe_next; 283 1.15 itojun 284 1.32 ozaki if (inp->inp_af != AF_INET6) 285 1.25 itojun continue; 286 1.32 ozaki if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&in6p_laddr(inp))) 287 1.15 itojun continue; 288 1.32 ozaki if (nhosts && !checkhost(inp)) 289 1.15 itojun continue; 290 1.32 ozaki if (nports && !checkport(inp)) 291 1.15 itojun continue; 292 1.32 ozaki KREAD(inp->inp_socket, &sockb, sizeof (sockb)); 293 1.15 itojun if (istcp) { 294 1.32 ozaki KREAD(inp->inp_ppcb, &tcpcb, sizeof (tcpcb)); 295 1.32 ozaki enter6(inp, &sockb, tcpcb.t_state, "tcp"); 296 1.15 itojun } else 297 1.32 ozaki enter6(inp, &sockb, 0, "udp"); 298 1.15 itojun } 299 1.17 itojun } 300 1.15 itojun #endif /*INET6*/ 301 1.1 jtc 302 1.1 jtc static void 303 1.27 dsl enter(struct inpcb *inp, struct socket *so, int state, const char *proto) 304 1.1 jtc { 305 1.8 lukem struct netinfo *p; 306 1.1 jtc 307 1.1 jtc /* 308 1.1 jtc * Only take exact matches, any sockets with 309 1.1 jtc * previously unbound addresses will be deleted 310 1.1 jtc * below in the display routine because they 311 1.1 jtc * will appear as ``not seen'' in the kernel 312 1.1 jtc * data structures. 313 1.1 jtc */ 314 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) { 315 1.15 itojun if (p->ni_family != AF_INET) 316 1.15 itojun continue; 317 1.1 jtc if (!streq(proto, p->ni_proto)) 318 1.1 jtc continue; 319 1.1 jtc if (p->ni_lport != inp->inp_lport || 320 1.32 ozaki p->ni_laddr.s_addr != in4p_laddr(inp).s_addr) 321 1.1 jtc continue; 322 1.32 ozaki if (p->ni_faddr.s_addr == in4p_faddr(inp).s_addr && 323 1.1 jtc p->ni_fport == inp->inp_fport) 324 1.1 jtc break; 325 1.1 jtc } 326 1.26 christos if (p == nhead) { 327 1.1 jtc if ((p = malloc(sizeof(*p))) == NULL) { 328 1.1 jtc error("Out of memory"); 329 1.1 jtc return; 330 1.1 jtc } 331 1.26 christos p->ni_prev = nhead; 332 1.1 jtc p->ni_forw = netcb.ni_forw; 333 1.1 jtc netcb.ni_forw->ni_prev = p; 334 1.1 jtc netcb.ni_forw = p; 335 1.1 jtc p->ni_line = -1; 336 1.32 ozaki p->ni_laddr = in4p_laddr(inp); 337 1.1 jtc p->ni_lport = inp->inp_lport; 338 1.32 ozaki p->ni_faddr = in4p_faddr(inp); 339 1.1 jtc p->ni_fport = inp->inp_fport; 340 1.1 jtc p->ni_proto = proto; 341 1.23 dsl p->ni_flags = NIF_LACHG | NIF_FACHG; 342 1.15 itojun p->ni_family = AF_INET; 343 1.1 jtc } 344 1.1 jtc p->ni_rcvcc = so->so_rcv.sb_cc; 345 1.1 jtc p->ni_sndcc = so->so_snd.sb_cc; 346 1.1 jtc p->ni_state = state; 347 1.1 jtc p->ni_seen = 1; 348 1.1 jtc } 349 1.1 jtc 350 1.15 itojun #ifdef INET6 351 1.15 itojun static void 352 1.31 ozaki enter6(struct inpcb *inp, struct socket *so, int state, const char *proto) 353 1.15 itojun { 354 1.15 itojun struct netinfo *p; 355 1.15 itojun 356 1.15 itojun /* 357 1.15 itojun * Only take exact matches, any sockets with 358 1.15 itojun * previously unbound addresses will be deleted 359 1.15 itojun * below in the display routine because they 360 1.15 itojun * will appear as ``not seen'' in the kernel 361 1.15 itojun * data structures. 362 1.15 itojun */ 363 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) { 364 1.15 itojun if (p->ni_family != AF_INET6) 365 1.15 itojun continue; 366 1.15 itojun if (!streq(proto, p->ni_proto)) 367 1.15 itojun continue; 368 1.31 ozaki if (p->ni_lport != inp->inp_lport || 369 1.32 ozaki !IN6_ARE_ADDR_EQUAL(&p->ni_laddr6, &in6p_laddr(inp))) 370 1.15 itojun continue; 371 1.32 ozaki if (IN6_ARE_ADDR_EQUAL(&p->ni_faddr6, &in6p_faddr(inp)) && 372 1.31 ozaki p->ni_fport == inp->inp_fport) 373 1.15 itojun break; 374 1.15 itojun } 375 1.26 christos if (p == nhead) { 376 1.15 itojun if ((p = malloc(sizeof(*p))) == NULL) { 377 1.15 itojun error("Out of memory"); 378 1.15 itojun return; 379 1.15 itojun } 380 1.26 christos p->ni_prev = nhead; 381 1.15 itojun p->ni_forw = netcb.ni_forw; 382 1.15 itojun netcb.ni_forw->ni_prev = p; 383 1.15 itojun netcb.ni_forw = p; 384 1.15 itojun p->ni_line = -1; 385 1.32 ozaki p->ni_laddr6 = in6p_laddr(inp); 386 1.31 ozaki p->ni_lport = inp->inp_lport; 387 1.32 ozaki p->ni_faddr6 = in6p_faddr(inp); 388 1.31 ozaki p->ni_fport = inp->inp_fport; 389 1.15 itojun p->ni_proto = proto; 390 1.23 dsl p->ni_flags = NIF_LACHG | NIF_FACHG; 391 1.15 itojun p->ni_family = AF_INET6; 392 1.15 itojun } 393 1.15 itojun p->ni_rcvcc = so->so_rcv.sb_cc; 394 1.15 itojun p->ni_sndcc = so->so_snd.sb_cc; 395 1.15 itojun p->ni_state = state; 396 1.15 itojun p->ni_seen = 1; 397 1.15 itojun } 398 1.15 itojun #endif 399 1.15 itojun 400 1.1 jtc /* column locations */ 401 1.1 jtc #define LADDR 0 402 1.1 jtc #define FADDR LADDR+23 403 1.1 jtc #define PROTO FADDR+23 404 1.1 jtc #define RCVCC PROTO+6 405 1.1 jtc #define SNDCC RCVCC+7 406 1.1 jtc #define STATE SNDCC+7 407 1.1 jtc 408 1.1 jtc void 409 1.19 ad labelnetstat(void) 410 1.1 jtc { 411 1.23 dsl struct netinfo *p; 412 1.9 mrg 413 1.3 cgd if (namelist[X_TCBTABLE].n_type == 0) 414 1.1 jtc return; 415 1.1 jtc wmove(wnd, 0, 0); wclrtobot(wnd); 416 1.1 jtc mvwaddstr(wnd, 0, LADDR, "Local Address"); 417 1.1 jtc mvwaddstr(wnd, 0, FADDR, "Foreign Address"); 418 1.1 jtc mvwaddstr(wnd, 0, PROTO, "Proto"); 419 1.1 jtc mvwaddstr(wnd, 0, RCVCC, "Recv-Q"); 420 1.1 jtc mvwaddstr(wnd, 0, SNDCC, "Send-Q"); 421 1.1 jtc mvwaddstr(wnd, 0, STATE, "(state)"); 422 1.23 dsl 423 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) { 424 1.23 dsl if (p->ni_line == -1) 425 1.23 dsl continue; 426 1.23 dsl p->ni_flags |= NIF_LACHG | NIF_FACHG; 427 1.23 dsl } 428 1.1 jtc } 429 1.1 jtc 430 1.1 jtc void 431 1.19 ad shownetstat(void) 432 1.1 jtc { 433 1.8 lukem struct netinfo *p, *q; 434 1.1 jtc 435 1.1 jtc /* 436 1.1 jtc * First, delete any connections that have gone 437 1.1 jtc * away and adjust the position of connections 438 1.1 jtc * below to reflect the deleted line. 439 1.1 jtc */ 440 1.1 jtc p = netcb.ni_forw; 441 1.26 christos while (p != nhead) { 442 1.1 jtc if (p->ni_line == -1 || p->ni_seen) { 443 1.1 jtc p = p->ni_forw; 444 1.1 jtc continue; 445 1.1 jtc } 446 1.26 christos wmove(wnd, p->ni_line, 0); 447 1.26 christos wdeleteln(wnd); 448 1.26 christos for (q = netcb.ni_forw; q != nhead; q = q->ni_forw) 449 1.1 jtc if (q != p && q->ni_line > p->ni_line) { 450 1.1 jtc q->ni_line--; 451 1.1 jtc /* this shouldn't be necessary */ 452 1.23 dsl q->ni_flags |= NIF_LACHG | NIF_FACHG; 453 1.1 jtc } 454 1.1 jtc lastrow--; 455 1.1 jtc q = p->ni_forw; 456 1.1 jtc p->ni_prev->ni_forw = p->ni_forw; 457 1.1 jtc p->ni_forw->ni_prev = p->ni_prev; 458 1.1 jtc free(p); 459 1.1 jtc p = q; 460 1.1 jtc } 461 1.1 jtc /* 462 1.1 jtc * Update existing connections and add new ones. 463 1.1 jtc */ 464 1.26 christos for (p = netcb.ni_forw; p != nhead; p = p->ni_forw) { 465 1.1 jtc if (p->ni_line == -1) { 466 1.1 jtc /* 467 1.1 jtc * Add a new entry if possible. 468 1.1 jtc */ 469 1.6 jtc if (lastrow > getmaxy(wnd)) 470 1.1 jtc continue; 471 1.1 jtc p->ni_line = lastrow++; 472 1.23 dsl p->ni_flags |= NIF_LACHG | NIF_FACHG; 473 1.1 jtc } 474 1.1 jtc if (p->ni_flags & NIF_LACHG) { 475 1.1 jtc wmove(wnd, p->ni_line, LADDR); 476 1.15 itojun switch (p->ni_family) { 477 1.15 itojun case AF_INET: 478 1.15 itojun inetprint(&p->ni_laddr, p->ni_lport, 479 1.15 itojun p->ni_proto); 480 1.15 itojun break; 481 1.15 itojun #ifdef INET6 482 1.15 itojun case AF_INET6: 483 1.15 itojun inet6print(&p->ni_laddr6, p->ni_lport, 484 1.15 itojun p->ni_proto); 485 1.15 itojun break; 486 1.15 itojun #endif 487 1.15 itojun } 488 1.1 jtc p->ni_flags &= ~NIF_LACHG; 489 1.1 jtc } 490 1.1 jtc if (p->ni_flags & NIF_FACHG) { 491 1.1 jtc wmove(wnd, p->ni_line, FADDR); 492 1.15 itojun switch (p->ni_family) { 493 1.15 itojun case AF_INET: 494 1.15 itojun inetprint(&p->ni_faddr, p->ni_fport, 495 1.15 itojun p->ni_proto); 496 1.15 itojun break; 497 1.15 itojun #ifdef INET6 498 1.15 itojun case AF_INET6: 499 1.15 itojun inet6print(&p->ni_faddr6, p->ni_fport, 500 1.15 itojun p->ni_proto); 501 1.15 itojun break; 502 1.15 itojun #endif 503 1.15 itojun } 504 1.1 jtc p->ni_flags &= ~NIF_FACHG; 505 1.1 jtc } 506 1.1 jtc mvwaddstr(wnd, p->ni_line, PROTO, p->ni_proto); 507 1.15 itojun #ifdef INET6 508 1.15 itojun if (p->ni_family == AF_INET6) 509 1.15 itojun waddstr(wnd, "6"); 510 1.15 itojun #endif 511 1.18 jdc mvwprintw(wnd, p->ni_line, RCVCC, "%6ld", p->ni_rcvcc); 512 1.18 jdc mvwprintw(wnd, p->ni_line, SNDCC, "%6ld", p->ni_sndcc); 513 1.10 ross if (streq(p->ni_proto, "tcp")) { 514 1.1 jtc if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES) 515 1.1 jtc mvwprintw(wnd, p->ni_line, STATE, "%d", 516 1.1 jtc p->ni_state); 517 1.1 jtc else 518 1.1 jtc mvwaddstr(wnd, p->ni_line, STATE, 519 1.1 jtc tcpstates[p->ni_state]); 520 1.10 ross } 521 1.1 jtc wclrtoeol(wnd); 522 1.1 jtc } 523 1.6 jtc if (lastrow < getmaxy(wnd)) { 524 1.1 jtc wmove(wnd, lastrow, 0); wclrtobot(wnd); 525 1.6 jtc wmove(wnd, getmaxy(wnd), 0); wdeleteln(wnd); /* XXX */ 526 1.1 jtc } 527 1.1 jtc } 528 1.1 jtc 529 1.1 jtc /* 530 1.1 jtc * Pretty print an Internet address (net address + port). 531 1.1 jtc * If the nflag was specified, use numbers instead of names. 532 1.1 jtc */ 533 1.1 jtc static void 534 1.27 dsl inetprint(struct in_addr *in, int port, const char *proto) 535 1.1 jtc { 536 1.1 jtc struct servent *sp = 0; 537 1.7 mrg char line[80], *cp; 538 1.1 jtc 539 1.9 mrg (void)snprintf(line, sizeof line, "%.*s.", 16, inetname(*in)); 540 1.8 lukem cp = strchr(line, '\0'); 541 1.1 jtc if (!nflag && port) 542 1.1 jtc sp = getservbyport(port, proto); 543 1.1 jtc if (sp || port == 0) 544 1.9 mrg (void)snprintf(cp, line + sizeof line - cp, "%.8s", 545 1.9 mrg sp ? sp->s_name : "*"); 546 1.1 jtc else 547 1.9 mrg (void)snprintf(cp, line + sizeof line - cp, "%d", 548 1.9 mrg ntohs((u_short)port)); 549 1.1 jtc /* pad to full column to clear any garbage */ 550 1.8 lukem cp = strchr(line, '\0'); 551 1.1 jtc while (cp - line < 22) 552 1.1 jtc *cp++ = ' '; 553 1.1 jtc *cp = '\0'; 554 1.1 jtc waddstr(wnd, line); 555 1.1 jtc } 556 1.1 jtc 557 1.15 itojun #ifdef INET6 558 1.15 itojun static void 559 1.27 dsl inet6print(struct in6_addr *in6, int port, const char *proto) 560 1.15 itojun { 561 1.15 itojun struct servent *sp = 0; 562 1.15 itojun char line[80], *cp; 563 1.15 itojun 564 1.15 itojun (void)snprintf(line, sizeof line, "%.*s.", 16, inet6name(in6)); 565 1.15 itojun cp = strchr(line, '\0'); 566 1.15 itojun if (!nflag && port) 567 1.15 itojun sp = getservbyport(port, proto); 568 1.15 itojun if (sp || port == 0) 569 1.15 itojun (void)snprintf(cp, line + sizeof line - cp, "%.8s", 570 1.15 itojun sp ? sp->s_name : "*"); 571 1.15 itojun else 572 1.15 itojun (void)snprintf(cp, line + sizeof line - cp, "%d", 573 1.15 itojun ntohs((u_short)port)); 574 1.15 itojun /* pad to full column to clear any garbage */ 575 1.15 itojun cp = strchr(line, '\0'); 576 1.15 itojun while (cp - line < 22) 577 1.15 itojun *cp++ = ' '; 578 1.15 itojun *cp = '\0'; 579 1.15 itojun waddstr(wnd, line); 580 1.15 itojun } 581 1.15 itojun #endif 582 1.15 itojun 583 1.1 jtc /* 584 1.1 jtc * Construct an Internet address representation. 585 1.1 jtc * If the nflag has been supplied, give 586 1.1 jtc * numeric value, otherwise try for symbolic name. 587 1.1 jtc */ 588 1.15 itojun static const char * 589 1.19 ad inetname(struct in_addr in) 590 1.1 jtc { 591 1.1 jtc char *cp = 0; 592 1.1 jtc static char line[50]; 593 1.1 jtc struct hostent *hp; 594 1.1 jtc struct netent *np; 595 1.1 jtc 596 1.1 jtc if (!nflag && in.s_addr != INADDR_ANY) { 597 1.1 jtc int net = inet_netof(in); 598 1.1 jtc int lna = inet_lnaof(in); 599 1.1 jtc 600 1.1 jtc if (lna == INADDR_ANY) { 601 1.1 jtc np = getnetbyaddr(net, AF_INET); 602 1.1 jtc if (np) 603 1.1 jtc cp = np->n_name; 604 1.1 jtc } 605 1.1 jtc if (cp == 0) { 606 1.1 jtc hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); 607 1.1 jtc if (hp) 608 1.1 jtc cp = hp->h_name; 609 1.1 jtc } 610 1.1 jtc } 611 1.1 jtc if (in.s_addr == INADDR_ANY) 612 1.22 itojun strlcpy(line, "*", sizeof(line)); 613 1.1 jtc else if (cp) 614 1.22 itojun strlcpy(line, cp, sizeof(line)); 615 1.1 jtc else { 616 1.1 jtc in.s_addr = ntohl(in.s_addr); 617 1.1 jtc #define C(x) ((x) & 0xff) 618 1.9 mrg (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 619 1.9 mrg C(in.s_addr >> 24), C(in.s_addr >> 16), 620 1.9 mrg C(in.s_addr >> 8), C(in.s_addr)); 621 1.9 mrg #undef C 622 1.1 jtc } 623 1.1 jtc return (line); 624 1.1 jtc } 625 1.15 itojun 626 1.15 itojun #ifdef INET6 627 1.15 itojun static const char * 628 1.19 ad inet6name(struct in6_addr *in6) 629 1.15 itojun { 630 1.15 itojun static char line[NI_MAXHOST]; 631 1.15 itojun struct sockaddr_in6 sin6; 632 1.15 itojun int flags; 633 1.15 itojun 634 1.15 itojun if (nflag) 635 1.15 itojun flags = NI_NUMERICHOST; 636 1.15 itojun else 637 1.15 itojun flags = 0; 638 1.15 itojun if (IN6_IS_ADDR_UNSPECIFIED(in6)) 639 1.15 itojun return "*"; 640 1.15 itojun memset(&sin6, 0, sizeof(sin6)); 641 1.15 itojun sin6.sin6_family = AF_INET6; 642 1.15 itojun sin6.sin6_len = sizeof(struct sockaddr_in6); 643 1.15 itojun sin6.sin6_addr = *in6; 644 1.15 itojun if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 645 1.15 itojun line, sizeof(line), NULL, 0, flags) == 0) 646 1.15 itojun return line; 647 1.15 itojun return "?"; 648 1.15 itojun } 649 1.15 itojun #endif 650 1.1 jtc 651 1.12 jwise /* please note: there are also some netstat commands in netcmds.c */ 652 1.12 jwise 653 1.12 jwise void 654 1.19 ad netstat_all(char *args) 655 1.12 jwise { 656 1.12 jwise aflag = !aflag; 657 1.12 jwise fetchnetstat(); 658 1.12 jwise shownetstat(); 659 1.12 jwise refresh(); 660 1.12 jwise } 661 1.12 jwise 662 1.12 jwise void 663 1.19 ad netstat_names(char *args) 664 1.12 jwise { 665 1.12 jwise 666 1.12 jwise if (nflag == 0) 667 1.12 jwise return; 668 1.12 jwise 669 1.12 jwise nflag = 0; 670 1.12 jwise wclear(wnd); 671 1.12 jwise labelnetstat(); 672 1.12 jwise shownetstat(); 673 1.12 jwise refresh(); 674 1.12 jwise } 675 1.12 jwise 676 1.12 jwise void 677 1.19 ad netstat_numbers(char *args) 678 1.1 jtc { 679 1.1 jtc 680 1.13 itojun if (nflag != 0) 681 1.12 jwise return; 682 1.12 jwise 683 1.13 itojun nflag = 1; 684 1.12 jwise wclear(wnd); 685 1.12 jwise labelnetstat(); 686 1.1 jtc shownetstat(); 687 1.1 jtc refresh(); 688 1.1 jtc } 689