netcmds.c revision 175387
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 175387 2008-01-16 19:27:43Z delphij $");
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(const char *, int);
76static int selectproto(const char *);
77static void showprotos(void);
78static int selectport(long, int);
79static void showports(void);
80static int selecthost(struct in_addr *, int);
81static void showhosts(void);
82
83int
84netcmd(const char *cmd, const char *args)
85{
86
87	if (prefix(cmd, "proto")) {
88		if (*args == '\0') {
89			move(CMDLINE, 0);
90			clrtoeol();
91			addstr("which proto?");
92		} else if (!selectproto(args)) {
93			error("%s: Unknown protocol.", args);
94		}
95		return (1);
96	}
97	if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
98		changeitems(args, prefix(cmd, "display"));
99		return (1);
100	}
101	if (prefix(cmd, "reset")) {
102		selectproto(0);
103		selecthost(0, 0);
104		selectport(-1, 0);
105		return (1);
106	}
107	if (prefix(cmd, "show")) {
108		move(CMDLINE, 0); clrtoeol();
109		if (*args == '\0') {
110			showprotos();
111			showhosts();
112			showports();
113			return (1);
114		}
115		if (prefix(args, "protos"))
116			showprotos();
117		else if (prefix(args, "hosts"))
118			showhosts();
119		else if (prefix(args, "ports"))
120			showports();
121		else
122			addstr("show what?");
123		return (1);
124	}
125	return (0);
126}
127
128
129static void
130changeitems(const char *args, int onoff)
131{
132	char *cp, *tmpstr, *tmpstr1;
133	struct servent *sp;
134	struct hostent *hp;
135	struct in_addr in;
136
137	tmpstr = tmpstr1 = strdup(args);
138	cp = index(tmpstr1, '\n');
139	if (cp)
140		*cp = '\0';
141	for (;;tmpstr1 = cp) {
142		for (cp = tmpstr1; *cp && isspace(*cp); cp++)
143			;
144		tmpstr1 = cp;
145		for (; *cp && !isspace(*cp); cp++)
146			;
147		if (*cp)
148			*cp++ = '\0';
149		if (cp - tmpstr1 == 0)
150			break;
151		sp = getservbyname(tmpstr1,
152		    protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
153		if (sp) {
154			selectport(sp->s_port, onoff);
155			continue;
156		}
157		hp = gethostbyname(tmpstr1);
158		if (hp == 0) {
159			in.s_addr = inet_addr(tmpstr1);
160			if ((int)in.s_addr == -1) {
161				error("%s: unknown host or port", tmpstr1);
162				continue;
163			}
164		} else
165			in = *(struct in_addr *)hp->h_addr;
166		selecthost(&in, onoff);
167	}
168	free(tmpstr);
169}
170
171static int
172selectproto(const char *proto)
173{
174
175	if (proto == 0 || streq(proto, "all"))
176		protos = TCP | UDP;
177	else if (streq(proto, "tcp"))
178		protos = TCP;
179	else if (streq(proto, "udp"))
180		protos = UDP;
181	else
182		return (0);
183
184	return (protos);
185}
186
187static void
188showprotos(void)
189{
190
191	if ((protos&TCP) == 0)
192		addch('!');
193	addstr("tcp ");
194	if ((protos&UDP) == 0)
195		addch('!');
196	addstr("udp ");
197}
198
199static	struct pitem {
200	long	port;
201	int	onoff;
202} *ports;
203
204static int
205selectport(long port, int onoff)
206{
207	struct pitem *p;
208
209	if (port == -1) {
210		if (ports == 0)
211			return (0);
212		free((char *)ports), ports = 0;
213		nports = 0;
214		return (1);
215	}
216	for (p = ports; p < ports+nports; p++)
217		if (p->port == port) {
218			p->onoff = onoff;
219			return (0);
220		}
221	if (nports == 0)
222		ports = (struct pitem *)malloc(sizeof (*p));
223	else
224		ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
225	p = &ports[nports++];
226	p->port = port;
227	p->onoff = onoff;
228	return (1);
229}
230
231int
232checkport(struct inpcb *inp)
233{
234	struct pitem *p;
235
236	if (ports)
237	for (p = ports; p < ports+nports; p++)
238		if (p->port == inp->inp_lport || p->port == inp->inp_fport)
239			return (p->onoff);
240	return (1);
241}
242
243static void
244showports(void)
245{
246	struct pitem *p;
247	struct servent *sp;
248
249	for (p = ports; p < ports+nports; p++) {
250		sp = getservbyport(p->port,
251		    protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
252		if (!p->onoff)
253			addch('!');
254		if (sp)
255			printw("%s ", sp->s_name);
256		else
257			printw("%d ", p->port);
258	}
259}
260
261static int
262selecthost(struct in_addr *in, int onoff)
263{
264	struct hitem *p;
265
266	if (in == 0) {
267		if (hosts == 0)
268			return (0);
269		free((char *)hosts), hosts = 0;
270		nhosts = 0;
271		return (1);
272	}
273	for (p = hosts; p < hosts+nhosts; p++)
274		if (p->addr.s_addr == in->s_addr) {
275			p->onoff = onoff;
276			return (0);
277		}
278	if (nhosts == 0)
279		hosts = (struct hitem *)malloc(sizeof (*p));
280	else
281		hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
282	p = &hosts[nhosts++];
283	p->addr = *in;
284	p->onoff = onoff;
285	return (1);
286}
287
288int
289checkhost(struct inpcb *inp)
290{
291	struct hitem *p;
292
293	if (hosts)
294	for (p = hosts; p < hosts+nhosts; p++)
295		if (p->addr.s_addr == inp->inp_laddr.s_addr ||
296		    p->addr.s_addr == inp->inp_faddr.s_addr)
297			return (p->onoff);
298	return (1);
299}
300
301static void
302showhosts(void)
303{
304	struct hitem *p;
305	struct hostent *hp;
306
307	for (p = hosts; p < hosts+nhosts; p++) {
308		hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET);
309		if (!p->onoff)
310			addch('!');
311		printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr));
312	}
313}
314