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