Home | History | Annotate | Line # | Download | only in systat
netcmds.c revision 1.15
      1 /*	$NetBSD: netcmds.c,v 1.15 2000/04/27 00:30:51 jdc Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1980, 1992, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 #if 0
     39 static char sccsid[] = "@(#)netcmds.c	8.1 (Berkeley) 6/6/93";
     40 #endif
     41 __RCSID("$NetBSD: netcmds.c,v 1.15 2000/04/27 00:30:51 jdc Exp $");
     42 #endif /* not lint */
     43 
     44 /*
     45  * Common network command support routines.
     46  */
     47 #include <sys/param.h>
     48 #include <sys/socket.h>
     49 #include <sys/mbuf.h>
     50 #include <sys/protosw.h>
     51 
     52 #include <net/route.h>
     53 #include <netinet/in.h>
     54 #include <netinet/in_systm.h>
     55 #include <netinet/ip.h>
     56 #include <netinet/in_pcb.h>
     57 #ifdef INET6
     58 #include <netinet/ip6.h>
     59 #include <netinet6/in6_pcb.h>
     60 #endif
     61 
     62 #include <arpa/inet.h>
     63 
     64 #include <netdb.h>
     65 #include <stdlib.h>
     66 #include <string.h>
     67 #include <ctype.h>
     68 #include "systat.h"
     69 #include "extern.h"
     70 
     71 #define	streq(a,b)	(strcmp(a,b)==0)
     72 
     73 static	struct hitem {
     74 	struct	sockaddr_storage addr;
     75 	int	onoff;
     76 } *hosts = NULL;
     77 
     78 int nports, nhosts, protos;
     79 
     80 static void changeitems __P((char *, int));
     81 static void selectproto __P((char *));
     82 static void showprotos __P((void));
     83 static int selectport __P((long, int));
     84 static void showports __P((void));
     85 static int addrcmp __P((struct sockaddr *, struct sockaddr *));
     86 static int selecthost __P((struct sockaddr *, int));
     87 static void showhosts __P((void));
     88 
     89 /* please note: there are also some netstat commands in netstat.c */
     90 
     91 void
     92 netstat_display (args)
     93 	char *args;
     94 {
     95 	changeitems(args, 1);
     96 }
     97 
     98 void
     99 netstat_ignore (args)
    100 	char *args;
    101 {
    102 	changeitems(args, 0);
    103 }
    104 
    105 void
    106 netstat_reset (args)
    107 	char *args;
    108 {
    109 	selectproto(0);
    110 	selecthost(0, 0);
    111 	selectport(-1, 0);
    112 }
    113 
    114 void
    115 netstat_show (args)
    116 	char *args;
    117 {
    118 	move(CMDLINE, 0); clrtoeol();
    119 	if (!args || *args == '\0') {
    120 		showprotos();
    121 		showhosts();
    122 		showports();
    123 		return;
    124 	}
    125 	if (strstr(args, "protos") == args)
    126 		showprotos();
    127 	else if (strstr(args, "hosts") == args)
    128 		showhosts();
    129 	else if (strstr(args, "ports") == args)
    130 		showports();
    131 	else
    132 		addstr("show what?");
    133 }
    134 
    135 void
    136 netstat_tcp (args)
    137 	char *args;
    138 {
    139 	selectproto("tcp");
    140 }
    141 
    142 void
    143 netstat_udp (args)
    144 	char *args;
    145 {
    146 	selectproto("udp");
    147 }
    148 
    149 static void
    150 changeitems(args, onoff)
    151 	char *args;
    152 	int onoff;
    153 {
    154 	char *cp;
    155 	struct servent *sp;
    156 	struct addrinfo hints, *res, *res0;
    157 
    158 	cp = strchr(args, '\n');
    159 	if (cp)
    160 		*cp = '\0';
    161 	for (;;args = cp) {
    162 		for (cp = args; *cp && isspace(*cp); cp++)
    163 			;
    164 		args = cp;
    165 		for (; *cp && !isspace(*cp); cp++)
    166 			;
    167 		if (*cp)
    168 			*cp++ = '\0';
    169 		if (cp - args == 0)
    170 			break;
    171 		sp = getservbyname(args,
    172 		    protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
    173 		if (sp) {
    174 			selectport(sp->s_port, onoff);
    175 			continue;
    176 		}
    177 
    178 		memset(&hints, 0, sizeof(hints));
    179 		hints.ai_family = PF_UNSPEC;
    180 		hints.ai_socktype = SOCK_DGRAM;
    181 		if (getaddrinfo(args, "0", &hints, &res0) != 0) {
    182 			error("%s: unknown host or port", args);
    183 			continue;
    184 		}
    185 		for (res = res0; res; res = res->ai_next)
    186 			selecthost(res->ai_addr, onoff);
    187 		freeaddrinfo(res0);
    188 	}
    189 }
    190 
    191 static void
    192 selectproto(proto)
    193 	char *proto;
    194 {
    195 
    196 	if (proto == 0 || streq(proto, "all"))
    197 		protos = TCP|UDP;
    198 	else if (streq(proto, "tcp"))
    199 		protos = TCP;
    200 	else if (streq(proto, "udp"))
    201 		protos = UDP;
    202 }
    203 
    204 static void
    205 showprotos()
    206 {
    207 
    208 	if ((protos & TCP) == 0)
    209 		addch('!');
    210 	addstr("tcp ");
    211 	if ((protos & UDP) == 0)
    212 		addch('!');
    213 	addstr("udp ");
    214 }
    215 
    216 static	struct pitem {
    217 	long	port;
    218 	int	onoff;
    219 } *ports = NULL;
    220 
    221 static int
    222 selectport(port, onoff)
    223 	long port;
    224 	int onoff;
    225 {
    226 	struct pitem *p;
    227 
    228 	if (port == -1) {
    229 		if (ports == NULL)
    230 			return (0);
    231 		free(ports);
    232 		ports = NULL;
    233 		nports = 0;
    234 		return (1);
    235 	}
    236 	for (p = ports; p < ports+nports; p++)
    237 		if (p->port == port) {
    238 			p->onoff = onoff;
    239 			return (0);
    240 		}
    241 	p = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
    242 	if (p == NULL) {
    243 		error("malloc failed");
    244 		die(0);
    245 	}
    246 	ports = p;
    247 	p = &ports[nports++];
    248 	p->port = port;
    249 	p->onoff = onoff;
    250 	return (1);
    251 }
    252 
    253 int
    254 checkport(inp)
    255 	struct inpcb *inp;
    256 {
    257 	struct pitem *p;
    258 
    259 	if (ports)
    260 	for (p = ports; p < ports+nports; p++)
    261 		if (p->port == inp->inp_lport || p->port == inp->inp_fport)
    262 			return (p->onoff);
    263 	return (1);
    264 }
    265 
    266 #ifdef INET6
    267 int
    268 checkport6(in6p)
    269 	struct in6pcb *in6p;
    270 {
    271 	struct pitem *p;
    272 
    273 	if (ports)
    274 	for (p = ports; p < ports+nports; p++)
    275 		if (p->port == in6p->in6p_lport || p->port == in6p->in6p_fport)
    276 			return (p->onoff);
    277 	return (1);
    278 }
    279 #endif
    280 
    281 static void
    282 showports()
    283 {
    284 	struct pitem *p;
    285 	struct servent *sp;
    286 
    287 	for (p = ports; p < ports+nports; p++) {
    288 		sp = getservbyport(p->port,
    289 		    protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
    290 		if (!p->onoff)
    291 			addch('!');
    292 		if (sp)
    293 			printw("%s ", sp->s_name);
    294 		else
    295 			printw("%ld ", p->port);
    296 	}
    297 }
    298 
    299 static int
    300 addrcmp(sa1, sa2)
    301 	struct sockaddr *sa1;
    302 	struct sockaddr *sa2;
    303 {
    304 	if (sa1->sa_family != sa2->sa_family)
    305 		return 0;
    306 	if (sa1->sa_len != sa2->sa_len)
    307 		return 0;
    308 	switch (sa1->sa_family) {
    309 	case AF_INET:
    310 		if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
    311 				((struct sockaddr_in *)sa2)->sin_addr.s_addr)
    312 			return 1;
    313 		break;
    314 #ifdef INET6
    315 	case AF_INET6:
    316 		if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
    317 				&((struct sockaddr_in6 *)sa2)->sin6_addr))
    318 			return 1;
    319 		break;
    320 #endif
    321 	default:
    322 		if (memcmp(sa1, sa2, sa1->sa_len) == 0)
    323 			return 1;
    324 		break;
    325 	}
    326 	return 0;
    327 }
    328 
    329 static int
    330 selecthost(sa, onoff)
    331 	struct sockaddr *sa;
    332 	int onoff;
    333 {
    334 	struct hitem *p;
    335 
    336 	if (sa == 0) {
    337 		if (hosts == 0)
    338 			return (0);
    339 		free((char *)hosts), hosts = 0;
    340 		nhosts = 0;
    341 		return (1);
    342 	}
    343 	for (p = hosts; p < hosts+nhosts; p++)
    344 		if (addrcmp((struct sockaddr *)&p->addr, sa)) {
    345 			p->onoff = onoff;
    346 			return (0);
    347 		}
    348 	if (sa->sa_len > sizeof(struct sockaddr_storage))
    349 		return (-1);	/*XXX*/
    350 	p = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
    351 	if (p == NULL) {
    352 		error("malloc failed");
    353 		die(0);
    354 	}
    355 	hosts = p;
    356 	p = &hosts[nhosts++];
    357 	memcpy(&p->addr, sa, sa->sa_len);
    358 	p->onoff = onoff;
    359 	return (1);
    360 }
    361 
    362 int
    363 checkhost(inp)
    364 	struct inpcb *inp;
    365 {
    366 	struct hitem *p;
    367 	struct sockaddr_in *sin;
    368 
    369 	if (hosts)
    370 		for (p = hosts; p < hosts+nhosts; p++) {
    371 			if (((struct sockaddr *)&p->addr)->sa_family != AF_INET)
    372 				continue;
    373 			sin = (struct sockaddr_in *)&p->addr;
    374 			if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
    375 			    sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
    376 				return (p->onoff);
    377 		}
    378 	return (1);
    379 }
    380 
    381 #ifdef INET6
    382 int
    383 checkhost6(in6p)
    384 	struct in6pcb *in6p;
    385 {
    386 	struct hitem *p;
    387 	struct sockaddr_in6 *sin6;
    388 
    389 	if (hosts)
    390 		for (p = hosts; p < hosts+nhosts; p++) {
    391 			if (((struct sockaddr *)&p->addr)->sa_family != AF_INET6)
    392 				continue;
    393 			sin6 = (struct sockaddr_in6 *)&p->addr;
    394 			if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &in6p->in6p_laddr) ||
    395 			    IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &in6p->in6p_faddr))
    396 				return (p->onoff);
    397 		}
    398 	return (1);
    399 }
    400 #endif
    401 
    402 static void
    403 showhosts()
    404 {
    405 	struct hitem *p;
    406 	char hbuf[NI_MAXHOST];
    407 	struct sockaddr *sa;
    408 	int flags;
    409 
    410 #if 0
    411 	flags = nflag ? NI_NUMERICHOST : 0;
    412 #else
    413 	flags = 0;
    414 #endif
    415 	for (p = hosts; p < hosts+nhosts; p++) {
    416 		sa = (struct sockaddr *)&p->addr;
    417 		if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
    418 				flags) != 0)
    419 			strcpy(hbuf, "(invalid)");
    420 		if (!p->onoff)
    421 			addch('!');
    422 		printw("%s ", hbuf);
    423 	}
    424 }
    425