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
33
34 /*
35 * Common network command support routines.
36 */
37 #include <sys/param.h>
38 #include <sys/queue.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/protosw.h>
42
43 #include <net/route.h>
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/ip.h>
47 #include <netinet/in_pcb.h>
48 #include <arpa/inet.h>
49
50 #include <ctype.h>
51 #include <netdb.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #include "systat.h"
56 #include "extern.h"
57
58 #define streq(a,b) (strcmp(a,b)==0)
59
60 static struct hitem {
61 struct in_addr addr;
62 int onoff;
63 } *hosts;
64
65 int nports, nhosts, protos;
66
67 static void changeitems(const char *, int);
68 static int selectproto(const char *);
69 static void showprotos(void);
70 static int selectport(long, int);
71 static void showports(void);
72 static int selecthost(struct in_addr *, int);
73 static void showhosts(void);
74
75 int
netcmd(const char * cmd,const char * args)76 netcmd(const char *cmd, const char *args)
77 {
78
79 if (prefix(cmd, "proto")) {
80 if (*args == '\0') {
81 move(CMDLINE, 0);
82 clrtoeol();
83 addstr("which proto?");
84 } else if (!selectproto(args)) {
85 error("%s: Unknown protocol.", args);
86 }
87 return (1);
88 }
89 if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
90 changeitems(args, prefix(cmd, "display"));
91 return (1);
92 }
93 if (prefix(cmd, "reset")) {
94 selectproto(0);
95 selecthost(0, 0);
96 selectport(-1, 0);
97 return (1);
98 }
99 if (prefix(cmd, "show")) {
100 move(CMDLINE, 0); clrtoeol();
101 if (*args == '\0') {
102 showprotos();
103 showhosts();
104 showports();
105 return (1);
106 }
107 if (prefix(args, "protos"))
108 showprotos();
109 else if (prefix(args, "hosts"))
110 showhosts();
111 else if (prefix(args, "ports"))
112 showports();
113 else
114 addstr("show what?");
115 return (1);
116 }
117 return (0);
118 }
119
120 static void
changeitems(const char * args,int onoff)121 changeitems(const char *args, int onoff)
122 {
123 char *cp, *tmpstr, *tmpstr1;
124 struct servent *sp;
125 struct hostent *hp;
126 struct in_addr in;
127
128 tmpstr = tmpstr1 = strdup(args);
129 cp = strchr(tmpstr1, '\n');
130 if (cp)
131 *cp = '\0';
132 for (;;tmpstr1 = cp) {
133 for (cp = tmpstr1; *cp && isspace(*cp); cp++)
134 ;
135 tmpstr1 = cp;
136 for (; *cp && !isspace(*cp); cp++)
137 ;
138 if (*cp)
139 *cp++ = '\0';
140 if (cp - tmpstr1 == 0)
141 break;
142 sp = getservbyname(tmpstr1,
143 protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
144 if (sp) {
145 selectport(sp->s_port, onoff);
146 continue;
147 }
148 hp = gethostbyname(tmpstr1);
149 if (hp == NULL) {
150 in.s_addr = inet_addr(tmpstr1);
151 if (in.s_addr == INADDR_NONE) {
152 error("%s: unknown host or port", tmpstr1);
153 continue;
154 }
155 } else
156 in = *(struct in_addr *)hp->h_addr;
157 selecthost(&in, onoff);
158 }
159 free(tmpstr);
160 }
161
162 static int
selectproto(const char * proto)163 selectproto(const char *proto)
164 {
165
166 if (proto == NULL || streq(proto, "all"))
167 protos = TCP | UDP;
168 else if (streq(proto, "tcp"))
169 protos = TCP;
170 else if (streq(proto, "udp"))
171 protos = UDP;
172 else
173 return (0);
174
175 return (protos);
176 }
177
178 static void
showprotos(void)179 showprotos(void)
180 {
181
182 if ((protos&TCP) == 0)
183 addch('!');
184 addstr("tcp ");
185 if ((protos&UDP) == 0)
186 addch('!');
187 addstr("udp ");
188 }
189
190 static struct pitem {
191 long port;
192 int onoff;
193 } *ports;
194
195 static int
selectport(long port,int onoff)196 selectport(long port, int onoff)
197 {
198 struct pitem *p;
199
200 if (port == -1) {
201 if (ports == NULL)
202 return (0);
203 free((char *)ports), ports = 0;
204 nports = 0;
205 return (1);
206 }
207 for (p = ports; p < ports + nports; p++)
208 if (p->port == port) {
209 p->onoff = onoff;
210 return (0);
211 }
212 if (nports == 0)
213 ports = (struct pitem *)malloc(sizeof (*p));
214 else
215 ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
216 p = &ports[nports++];
217 p->port = port;
218 p->onoff = onoff;
219 return (1);
220 }
221
222 int
checkport(struct in_conninfo * inc)223 checkport(struct in_conninfo *inc)
224 {
225 struct pitem *p;
226
227 if (ports)
228 for (p = ports; p < ports+nports; p++)
229 if (p->port == inc->inc_lport || p->port == inc->inc_fport)
230 return (p->onoff);
231 return (1);
232 }
233
234 static void
showports(void)235 showports(void)
236 {
237 struct pitem *p;
238 struct servent *sp;
239
240 for (p = ports; p < ports+nports; p++) {
241 sp = getservbyport(p->port,
242 protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
243 if (!p->onoff)
244 addch('!');
245 if (sp)
246 printw("%s ", sp->s_name);
247 else
248 printw("%ld ", p->port);
249 }
250 }
251
252 static int
selecthost(struct in_addr * in,int onoff)253 selecthost(struct in_addr *in, int onoff)
254 {
255 struct hitem *p;
256
257 if (in == NULL) {
258 if (hosts == NULL)
259 return (0);
260 free((char *)hosts), hosts = 0;
261 nhosts = 0;
262 return (1);
263 }
264 for (p = hosts; p < hosts+nhosts; p++)
265 if (p->addr.s_addr == in->s_addr) {
266 p->onoff = onoff;
267 return (0);
268 }
269 if (nhosts == 0)
270 hosts = (struct hitem *)malloc(sizeof (*p));
271 else
272 hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
273 p = &hosts[nhosts++];
274 p->addr = *in;
275 p->onoff = onoff;
276 return (1);
277 }
278
279 int
checkhost(struct in_conninfo * inc)280 checkhost(struct in_conninfo *inc)
281 {
282 struct hitem *p;
283
284 if (hosts)
285 for (p = hosts; p < hosts+nhosts; p++)
286 if (p->addr.s_addr == inc->inc_laddr.s_addr ||
287 p->addr.s_addr == inc->inc_faddr.s_addr)
288 return (p->onoff);
289 return (1);
290 }
291
292 static void
showhosts(void)293 showhosts(void)
294 {
295 struct hitem *p;
296 struct hostent *hp;
297
298 for (p = hosts; p < hosts+nhosts; p++) {
299 hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET);
300 if (!p->onoff)
301 addch('!');
302 printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr));
303 }
304 }
305