11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1980, 1992, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
3087715Smarkm#include <sys/cdefs.h>
311590Srgrimes
3287715Smarkm__FBSDID("$FreeBSD$");
3387715Smarkm
3487715Smarkm#ifdef lint
3587715Smarkmstatic const char sccsid[] = "@(#)netcmds.c	8.1 (Berkeley) 6/6/93";
3687715Smarkm#endif
3787715Smarkm
381590Srgrimes/*
391590Srgrimes * Common network command support routines.
401590Srgrimes */
411590Srgrimes#include <sys/param.h>
4214543Sdg#include <sys/queue.h>
431590Srgrimes#include <sys/socket.h>
441590Srgrimes#include <sys/socketvar.h>
451590Srgrimes#include <sys/protosw.h>
461590Srgrimes
471590Srgrimes#include <net/route.h>
481590Srgrimes#include <netinet/in.h>
491590Srgrimes#include <netinet/in_systm.h>
501590Srgrimes#include <netinet/ip.h>
511590Srgrimes#include <netinet/in_pcb.h>
5236916Speter#include <arpa/inet.h>
531590Srgrimes
5487715Smarkm#include <ctype.h>
551590Srgrimes#include <netdb.h>
561590Srgrimes#include <stdlib.h>
571590Srgrimes#include <string.h>
5887715Smarkm
591590Srgrimes#include "systat.h"
601590Srgrimes#include "extern.h"
611590Srgrimes
621590Srgrimes#define	streq(a,b)	(strcmp(a,b)==0)
631590Srgrimes
641590Srgrimesstatic	struct hitem {
651590Srgrimes	struct	in_addr addr;
661590Srgrimes	int	onoff;
671590Srgrimes} *hosts;
681590Srgrimes
691590Srgrimesint nports, nhosts, protos;
701590Srgrimes
7192922Simpstatic void changeitems(const char *, int);
7292922Simpstatic int selectproto(const char *);
7392922Simpstatic void showprotos(void);
7492922Simpstatic int selectport(long, int);
7592922Simpstatic void showports(void);
7692922Simpstatic int selecthost(struct in_addr *, int);
7792922Simpstatic void showhosts(void);
781590Srgrimes
791590Srgrimesint
80175387Sdelphijnetcmd(const char *cmd, const char *args)
811590Srgrimes{
821590Srgrimes
8331522Ssteve	if (prefix(cmd, "proto")) {
8431522Ssteve		if (*args == '\0') {
8531522Ssteve			move(CMDLINE, 0);
8631522Ssteve			clrtoeol();
8731522Ssteve			addstr("which proto?");
8831522Ssteve		} else if (!selectproto(args)) {
8931522Ssteve			error("%s: Unknown protocol.", args);
9031522Ssteve		}
911590Srgrimes		return (1);
921590Srgrimes	}
931590Srgrimes	if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
941590Srgrimes		changeitems(args, prefix(cmd, "display"));
951590Srgrimes		return (1);
961590Srgrimes	}
971590Srgrimes	if (prefix(cmd, "reset")) {
981590Srgrimes		selectproto(0);
991590Srgrimes		selecthost(0, 0);
1001590Srgrimes		selectport(-1, 0);
1011590Srgrimes		return (1);
1021590Srgrimes	}
1031590Srgrimes	if (prefix(cmd, "show")) {
1041590Srgrimes		move(CMDLINE, 0); clrtoeol();
1051590Srgrimes		if (*args == '\0') {
1061590Srgrimes			showprotos();
1071590Srgrimes			showhosts();
1081590Srgrimes			showports();
1091590Srgrimes			return (1);
1101590Srgrimes		}
1111590Srgrimes		if (prefix(args, "protos"))
1121590Srgrimes			showprotos();
1131590Srgrimes		else if (prefix(args, "hosts"))
1141590Srgrimes			showhosts();
1151590Srgrimes		else if (prefix(args, "ports"))
1161590Srgrimes			showports();
1171590Srgrimes		else
1181590Srgrimes			addstr("show what?");
1191590Srgrimes		return (1);
1201590Srgrimes	}
1211590Srgrimes	return (0);
1221590Srgrimes}
1231590Srgrimes
1241590Srgrimes
1251590Srgrimesstatic void
126175387Sdelphijchangeitems(const char *args, int onoff)
1271590Srgrimes{
12887715Smarkm	char *cp, *tmpstr, *tmpstr1;
1291590Srgrimes	struct servent *sp;
1301590Srgrimes	struct hostent *hp;
1311590Srgrimes	struct in_addr in;
1321590Srgrimes
13387715Smarkm	tmpstr = tmpstr1 = strdup(args);
13487715Smarkm	cp = index(tmpstr1, '\n');
1351590Srgrimes	if (cp)
1361590Srgrimes		*cp = '\0';
13787715Smarkm	for (;;tmpstr1 = cp) {
13887715Smarkm		for (cp = tmpstr1; *cp && isspace(*cp); cp++)
1391590Srgrimes			;
14087715Smarkm		tmpstr1 = cp;
1411590Srgrimes		for (; *cp && !isspace(*cp); cp++)
1421590Srgrimes			;
1431590Srgrimes		if (*cp)
1441590Srgrimes			*cp++ = '\0';
14587715Smarkm		if (cp - tmpstr1 == 0)
1461590Srgrimes			break;
14787715Smarkm		sp = getservbyname(tmpstr1,
1481590Srgrimes		    protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
1491590Srgrimes		if (sp) {
1501590Srgrimes			selectport(sp->s_port, onoff);
1511590Srgrimes			continue;
1521590Srgrimes		}
15387715Smarkm		hp = gethostbyname(tmpstr1);
1541590Srgrimes		if (hp == 0) {
15587715Smarkm			in.s_addr = inet_addr(tmpstr1);
15687715Smarkm			if ((int)in.s_addr == -1) {
15787715Smarkm				error("%s: unknown host or port", tmpstr1);
1581590Srgrimes				continue;
1591590Srgrimes			}
1601590Srgrimes		} else
1611590Srgrimes			in = *(struct in_addr *)hp->h_addr;
1621590Srgrimes		selecthost(&in, onoff);
1631590Srgrimes	}
16487715Smarkm	free(tmpstr);
1651590Srgrimes}
1661590Srgrimes
1671590Srgrimesstatic int
168175387Sdelphijselectproto(const char *proto)
1691590Srgrimes{
1701590Srgrimes
1711590Srgrimes	if (proto == 0 || streq(proto, "all"))
17231522Ssteve		protos = TCP | UDP;
1731590Srgrimes	else if (streq(proto, "tcp"))
17431522Ssteve		protos = TCP;
1751590Srgrimes	else if (streq(proto, "udp"))
17631522Ssteve		protos = UDP;
17731522Ssteve	else
17831522Ssteve		return (0);
17931522Ssteve
18031522Ssteve	return (protos);
1811590Srgrimes}
1821590Srgrimes
1831590Srgrimesstatic void
184175387Sdelphijshowprotos(void)
1851590Srgrimes{
1861590Srgrimes
1871590Srgrimes	if ((protos&TCP) == 0)
1881590Srgrimes		addch('!');
1891590Srgrimes	addstr("tcp ");
1901590Srgrimes	if ((protos&UDP) == 0)
1911590Srgrimes		addch('!');
1921590Srgrimes	addstr("udp ");
1931590Srgrimes}
1941590Srgrimes
1951590Srgrimesstatic	struct pitem {
1961590Srgrimes	long	port;
1971590Srgrimes	int	onoff;
1981590Srgrimes} *ports;
1991590Srgrimes
2001590Srgrimesstatic int
201175387Sdelphijselectport(long port, int onoff)
2021590Srgrimes{
203175387Sdelphij	struct pitem *p;
2041590Srgrimes
2051590Srgrimes	if (port == -1) {
2061590Srgrimes		if (ports == 0)
2071590Srgrimes			return (0);
2081590Srgrimes		free((char *)ports), ports = 0;
2091590Srgrimes		nports = 0;
2101590Srgrimes		return (1);
2111590Srgrimes	}
2121590Srgrimes	for (p = ports; p < ports+nports; p++)
2131590Srgrimes		if (p->port == port) {
2141590Srgrimes			p->onoff = onoff;
2151590Srgrimes			return (0);
2161590Srgrimes		}
2171590Srgrimes	if (nports == 0)
2181590Srgrimes		ports = (struct pitem *)malloc(sizeof (*p));
2191590Srgrimes	else
2201590Srgrimes		ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
2211590Srgrimes	p = &ports[nports++];
2221590Srgrimes	p->port = port;
2231590Srgrimes	p->onoff = onoff;
2241590Srgrimes	return (1);
2251590Srgrimes}
2261590Srgrimes
2271590Srgrimesint
228175387Sdelphijcheckport(struct inpcb *inp)
2291590Srgrimes{
230175387Sdelphij	struct pitem *p;
2311590Srgrimes
2321590Srgrimes	if (ports)
2331590Srgrimes	for (p = ports; p < ports+nports; p++)
2341590Srgrimes		if (p->port == inp->inp_lport || p->port == inp->inp_fport)
2351590Srgrimes			return (p->onoff);
2361590Srgrimes	return (1);
2371590Srgrimes}
2381590Srgrimes
2391590Srgrimesstatic void
240175387Sdelphijshowports(void)
2411590Srgrimes{
242175387Sdelphij	struct pitem *p;
2431590Srgrimes	struct servent *sp;
2441590Srgrimes
2451590Srgrimes	for (p = ports; p < ports+nports; p++) {
2461590Srgrimes		sp = getservbyport(p->port,
24774671Stmm		    protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
2481590Srgrimes		if (!p->onoff)
2491590Srgrimes			addch('!');
2501590Srgrimes		if (sp)
2511590Srgrimes			printw("%s ", sp->s_name);
2521590Srgrimes		else
2531590Srgrimes			printw("%d ", p->port);
2541590Srgrimes	}
2551590Srgrimes}
2561590Srgrimes
2571590Srgrimesstatic int
258175387Sdelphijselecthost(struct in_addr *in, int onoff)
2591590Srgrimes{
260175387Sdelphij	struct hitem *p;
2611590Srgrimes
2621590Srgrimes	if (in == 0) {
2631590Srgrimes		if (hosts == 0)
2641590Srgrimes			return (0);
2651590Srgrimes		free((char *)hosts), hosts = 0;
2661590Srgrimes		nhosts = 0;
2671590Srgrimes		return (1);
2681590Srgrimes	}
2691590Srgrimes	for (p = hosts; p < hosts+nhosts; p++)
2701590Srgrimes		if (p->addr.s_addr == in->s_addr) {
2711590Srgrimes			p->onoff = onoff;
2721590Srgrimes			return (0);
2731590Srgrimes		}
2741590Srgrimes	if (nhosts == 0)
2751590Srgrimes		hosts = (struct hitem *)malloc(sizeof (*p));
2761590Srgrimes	else
2771590Srgrimes		hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
2781590Srgrimes	p = &hosts[nhosts++];
2791590Srgrimes	p->addr = *in;
2801590Srgrimes	p->onoff = onoff;
2811590Srgrimes	return (1);
2821590Srgrimes}
2831590Srgrimes
2841590Srgrimesint
285175387Sdelphijcheckhost(struct inpcb *inp)
2861590Srgrimes{
287175387Sdelphij	struct hitem *p;
2881590Srgrimes
2891590Srgrimes	if (hosts)
2901590Srgrimes	for (p = hosts; p < hosts+nhosts; p++)
2911590Srgrimes		if (p->addr.s_addr == inp->inp_laddr.s_addr ||
2921590Srgrimes		    p->addr.s_addr == inp->inp_faddr.s_addr)
2931590Srgrimes			return (p->onoff);
2941590Srgrimes	return (1);
2951590Srgrimes}
2961590Srgrimes
2971590Srgrimesstatic void
298175387Sdelphijshowhosts(void)
2991590Srgrimes{
300175387Sdelphij	struct hitem *p;
3011590Srgrimes	struct hostent *hp;
3021590Srgrimes
3031590Srgrimes	for (p = hosts; p < hosts+nhosts; p++) {
3041590Srgrimes		hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET);
3051590Srgrimes		if (!p->onoff)
3061590Srgrimes			addch('!');
3071590Srgrimes		printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr));
3081590Srgrimes	}
3091590Srgrimes}
310