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