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