netcmds.c revision 87715
1/*-
2 * Copyright (c) 1980, 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35
36__FBSDID("$FreeBSD: head/usr.bin/systat/netcmds.c 87715 2001-12-12 00:13:37Z markm $");
37
38#ifdef lint
39static const char sccsid[] = "@(#)netcmds.c	8.1 (Berkeley) 6/6/93";
40#endif
41
42/*
43 * Common network command support routines.
44 */
45#include <sys/param.h>
46#include <sys/queue.h>
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/protosw.h>
50
51#include <net/route.h>
52#include <netinet/in.h>
53#include <netinet/in_systm.h>
54#include <netinet/ip.h>
55#include <netinet/in_pcb.h>
56#include <arpa/inet.h>
57
58#include <ctype.h>
59#include <netdb.h>
60#include <stdlib.h>
61#include <string.h>
62
63#include "systat.h"
64#include "extern.h"
65
66#define	streq(a,b)	(strcmp(a,b)==0)
67
68static	struct hitem {
69	struct	in_addr addr;
70	int	onoff;
71} *hosts;
72
73int nports, nhosts, protos;
74
75static void changeitems __P((const char *, int));
76static int selectproto __P((const char *));
77static void showprotos __P((void));
78static int selectport __P((long, int));
79static void showports __P((void));
80static int selecthost __P((struct in_addr *, int));
81static void showhosts __P((void));
82
83int
84netcmd(cmd, args)
85	const char *cmd, *args;
86{
87
88	if (prefix(cmd, "proto")) {
89		if (*args == '\0') {
90			move(CMDLINE, 0);
91			clrtoeol();
92			addstr("which proto?");
93		} else if (!selectproto(args)) {
94			error("%s: Unknown protocol.", args);
95		}
96		return (1);
97	}
98	if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
99		changeitems(args, prefix(cmd, "display"));
100		return (1);
101	}
102	if (prefix(cmd, "reset")) {
103		selectproto(0);
104		selecthost(0, 0);
105		selectport(-1, 0);
106		return (1);
107	}
108	if (prefix(cmd, "show")) {
109		move(CMDLINE, 0); clrtoeol();
110		if (*args == '\0') {
111			showprotos();
112			showhosts();
113			showports();
114			return (1);
115		}
116		if (prefix(args, "protos"))
117			showprotos();
118		else if (prefix(args, "hosts"))
119			showhosts();
120		else if (prefix(args, "ports"))
121			showports();
122		else
123			addstr("show what?");
124		return (1);
125	}
126	return (0);
127}
128
129
130static void
131changeitems(args, onoff)
132	const char *args;
133	int onoff;
134{
135	char *cp, *tmpstr, *tmpstr1;
136	struct servent *sp;
137	struct hostent *hp;
138	struct in_addr in;
139
140	tmpstr = tmpstr1 = strdup(args);
141	cp = index(tmpstr1, '\n');
142	if (cp)
143		*cp = '\0';
144	for (;;tmpstr1 = cp) {
145		for (cp = tmpstr1; *cp && isspace(*cp); cp++)
146			;
147		tmpstr1 = cp;
148		for (; *cp && !isspace(*cp); cp++)
149			;
150		if (*cp)
151			*cp++ = '\0';
152		if (cp - tmpstr1 == 0)
153			break;
154		sp = getservbyname(tmpstr1,
155		    protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
156		if (sp) {
157			selectport(sp->s_port, onoff);
158			continue;
159		}
160		hp = gethostbyname(tmpstr1);
161		if (hp == 0) {
162			in.s_addr = inet_addr(tmpstr1);
163			if ((int)in.s_addr == -1) {
164				error("%s: unknown host or port", tmpstr1);
165				continue;
166			}
167		} else
168			in = *(struct in_addr *)hp->h_addr;
169		selecthost(&in, onoff);
170	}
171	free(tmpstr);
172}
173
174static int
175selectproto(proto)
176	const char *proto;
177{
178
179	if (proto == 0 || streq(proto, "all"))
180		protos = TCP | UDP;
181	else if (streq(proto, "tcp"))
182		protos = TCP;
183	else if (streq(proto, "udp"))
184		protos = UDP;
185	else
186		return (0);
187
188	return (protos);
189}
190
191static void
192showprotos()
193{
194
195	if ((protos&TCP) == 0)
196		addch('!');
197	addstr("tcp ");
198	if ((protos&UDP) == 0)
199		addch('!');
200	addstr("udp ");
201}
202
203static	struct pitem {
204	long	port;
205	int	onoff;
206} *ports;
207
208static int
209selectport(port, onoff)
210	long port;
211	int onoff;
212{
213	register struct pitem *p;
214
215	if (port == -1) {
216		if (ports == 0)
217			return (0);
218		free((char *)ports), ports = 0;
219		nports = 0;
220		return (1);
221	}
222	for (p = ports; p < ports+nports; p++)
223		if (p->port == port) {
224			p->onoff = onoff;
225			return (0);
226		}
227	if (nports == 0)
228		ports = (struct pitem *)malloc(sizeof (*p));
229	else
230		ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
231	p = &ports[nports++];
232	p->port = port;
233	p->onoff = onoff;
234	return (1);
235}
236
237int
238checkport(inp)
239	register struct inpcb *inp;
240{
241	register struct pitem *p;
242
243	if (ports)
244	for (p = ports; p < ports+nports; p++)
245		if (p->port == inp->inp_lport || p->port == inp->inp_fport)
246			return (p->onoff);
247	return (1);
248}
249
250static void
251showports()
252{
253	register struct pitem *p;
254	struct servent *sp;
255
256	for (p = ports; p < ports+nports; p++) {
257		sp = getservbyport(p->port,
258		    protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
259		if (!p->onoff)
260			addch('!');
261		if (sp)
262			printw("%s ", sp->s_name);
263		else
264			printw("%d ", p->port);
265	}
266}
267
268static int
269selecthost(in, onoff)
270	struct in_addr *in;
271	int onoff;
272{
273	register struct hitem *p;
274
275	if (in == 0) {
276		if (hosts == 0)
277			return (0);
278		free((char *)hosts), hosts = 0;
279		nhosts = 0;
280		return (1);
281	}
282	for (p = hosts; p < hosts+nhosts; p++)
283		if (p->addr.s_addr == in->s_addr) {
284			p->onoff = onoff;
285			return (0);
286		}
287	if (nhosts == 0)
288		hosts = (struct hitem *)malloc(sizeof (*p));
289	else
290		hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
291	p = &hosts[nhosts++];
292	p->addr = *in;
293	p->onoff = onoff;
294	return (1);
295}
296
297int
298checkhost(inp)
299	register struct inpcb *inp;
300{
301	register struct hitem *p;
302
303	if (hosts)
304	for (p = hosts; p < hosts+nhosts; p++)
305		if (p->addr.s_addr == inp->inp_laddr.s_addr ||
306		    p->addr.s_addr == inp->inp_faddr.s_addr)
307			return (p->onoff);
308	return (1);
309}
310
311static void
312showhosts()
313{
314	register struct hitem *p;
315	struct hostent *hp;
316
317	for (p = hosts; p < hosts+nhosts; p++) {
318		hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET);
319		if (!p->onoff)
320			addch('!');
321		printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr));
322	}
323}
324