Annotation of src/usr.bin/systat/netcmds.c, Revision 1.9
1.9 ! deraadt 1: /* $OpenBSD: netcmds.c,v 1.7 2001/11/23 22:20:06 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: netcmds.c,v 1.4 1995/05/21 17:14:38 mycroft Exp $ */
3:
4: /*-
5: * Copyright (c) 1980, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "@(#)netcmds.c 8.1 (Berkeley) 6/6/93";
40: #endif
1.9 ! deraadt 41: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.7 2001/11/23 22:20:06 deraadt Exp $";
1.1 deraadt 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/socketvar.h>
50: #include <sys/mbuf.h>
51: #include <sys/protosw.h>
52:
53: #include <net/route.h>
54: #include <netinet/in.h>
55: #include <netinet/in_systm.h>
56: #include <netinet/ip.h>
57: #include <netinet/in_pcb.h>
58:
59: #include <arpa/inet.h>
60:
61: #include <netdb.h>
62: #include <stdlib.h>
63: #include <string.h>
64: #include <ctype.h>
65: #include "systat.h"
66: #include "extern.h"
67:
68: #define streq(a,b) (strcmp(a,b)==0)
69:
70: static struct hitem {
1.5 itojun 71: struct sockaddr_storage addr;
1.1 deraadt 72: int onoff;
73: } *hosts;
74:
75: int nports, nhosts, protos;
76:
77: static void changeitems __P((char *, int));
78: static int selectproto __P((char *));
79: static void showprotos __P((void));
80: static int selectport __P((long, int));
81: static void showports __P((void));
1.5 itojun 82: static int addrcmp __P((struct sockaddr *, struct sockaddr *));
83: static int selecthost __P((struct sockaddr *, int));
1.1 deraadt 84: static void showhosts __P((void));
85:
86: int
87: netcmd(cmd, args)
88: char *cmd, *args;
89: {
90:
91: if (prefix(cmd, "tcp") || prefix(cmd, "udp")) {
92: selectproto(cmd);
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:
127: static void
128: changeitems(args, onoff)
129: char *args;
130: int onoff;
131: {
1.6 mpech 132: char *cp;
1.1 deraadt 133: struct servent *sp;
1.5 itojun 134: struct addrinfo hints, *res0, *res;
1.1 deraadt 135:
1.3 millert 136: cp = strchr(args, '\n');
1.1 deraadt 137: if (cp)
138: *cp = '\0';
139: for (;;args = cp) {
140: for (cp = args; *cp && isspace(*cp); cp++)
141: ;
142: args = cp;
143: for (; *cp && !isspace(*cp); cp++)
144: ;
145: if (*cp)
146: *cp++ = '\0';
147: if (cp - args == 0)
148: break;
149: sp = getservbyname(args,
150: protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
151: if (sp) {
152: selectport(sp->s_port, onoff);
153: continue;
154: }
1.5 itojun 155:
156: memset(&hints, 0, sizeof(hints));
157: hints.ai_family = PF_UNSPEC;
158: hints.ai_socktype = SOCK_DGRAM;
159: if (getaddrinfo(args, "0", &hints, &res0) != 0) {
160: error("%s: unknown host or port", args);
161: continue;
1.1 deraadt 162: }
1.5 itojun 163: for (res = res0; res; res = res->ai_next)
164: selecthost(res->ai_addr, onoff);
165: freeaddrinfo(res0);
1.1 deraadt 166: }
167: }
168:
169: static int
170: selectproto(proto)
171: char *proto;
172: {
173: int new = protos;
174:
175: if (proto == 0 || streq(proto, "all"))
176: new = TCP|UDP;
177: else if (streq(proto, "tcp"))
178: new = TCP;
179: else if (streq(proto, "udp"))
180: new = UDP;
1.4 millert 181: return (protos = new);
1.1 deraadt 182: }
183:
184: static void
185: showprotos()
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(port, onoff)
203: long port;
204: int onoff;
205: {
1.6 mpech 206: struct pitem *p;
1.1 deraadt 207:
208: if (port == -1) {
209: if (ports == 0)
210: return (0);
211: free((char *)ports), ports = 0;
212: nports = 0;
213: return (1);
214: }
215: for (p = ports; p < ports+nports; p++)
216: if (p->port == port) {
217: p->onoff = onoff;
218: return (0);
219: }
220: if (nports == 0)
221: ports = (struct pitem *)malloc(sizeof (*p));
222: else
223: ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
224: p = &ports[nports++];
225: p->port = port;
226: p->onoff = onoff;
227: return (1);
228: }
229:
230: int
231: checkport(inp)
1.6 mpech 232: struct inpcb *inp;
1.1 deraadt 233: {
1.6 mpech 234: struct pitem *p;
1.1 deraadt 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:
243: static void
244: showports()
245: {
1.6 mpech 246: struct pitem *p;
1.1 deraadt 247: struct servent *sp;
248:
249: for (p = ports; p < ports+nports; p++) {
250: sp = getservbyport(p->port,
1.4 millert 251: protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
1.1 deraadt 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:
261: static int
1.5 itojun 262: addrcmp(sa1, sa2)
263: struct sockaddr *sa1;
264: struct sockaddr *sa2;
265: {
266: if (sa1->sa_family != sa2->sa_family)
267: return 0;
268: if (sa1->sa_len != sa2->sa_len)
269: return 0;
270: switch (sa1->sa_family) {
271: case AF_INET:
272: if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
273: ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
274: return 1;
275: break;
276: #ifdef INET6
277: case AF_INET6:
278: if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
279: &((struct sockaddr_in6 *)sa2)->sin6_addr))
280: return 1;
281: break;
282: #endif
283: default:
284: if (memcmp(sa1, sa2, sa1->sa_len) == 0)
285: return 1;
286: break;
287: }
288: return 0;
289: }
290:
291: static int
292: selecthost(sa, onoff)
293: struct sockaddr *sa;
1.1 deraadt 294: int onoff;
295: {
1.6 mpech 296: struct hitem *p;
1.1 deraadt 297:
1.5 itojun 298: if (sa == 0) {
1.1 deraadt 299: if (hosts == 0)
300: return (0);
301: free((char *)hosts), hosts = 0;
302: nhosts = 0;
303: return (1);
304: }
305: for (p = hosts; p < hosts+nhosts; p++)
1.5 itojun 306: if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1 deraadt 307: p->onoff = onoff;
308: return (0);
309: }
1.5 itojun 310: if (sa->sa_len > sizeof(struct sockaddr_storage))
311: return (-1); /*XXX*/
1.1 deraadt 312: if (nhosts == 0)
313: hosts = (struct hitem *)malloc(sizeof (*p));
314: else
315: hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
316: p = &hosts[nhosts++];
1.5 itojun 317: memcpy(&p->addr, sa, sa->sa_len);
1.1 deraadt 318: p->onoff = onoff;
319: return (1);
320: }
321:
322: int
323: checkhost(inp)
1.6 mpech 324: struct inpcb *inp;
1.1 deraadt 325: {
1.6 mpech 326: struct hitem *p;
1.1 deraadt 327:
328: if (hosts)
1.5 itojun 329: for (p = hosts; p < hosts+nhosts; p++) {
1.9 ! deraadt 330: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
! 331: !(inp->inp_flags & INP_IPV6)) {
1.5 itojun 332: struct sockaddr_in *sin;
333: sin = (struct sockaddr_in *)&p->addr;
334: if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
335: sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
336: return (p->onoff);
337: }
338: #ifdef INET6
1.9 ! deraadt 339: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
! 340: (inp->inp_flags & INP_IPV6)) {
1.5 itojun 341: struct sockaddr_in6 *sin6;
342: sin6 = (struct sockaddr_in6 *)&p->addr;
343: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
344: IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
345: return (p->onoff);
346: }
347: #endif
348: }
1.1 deraadt 349: return (1);
350: }
351:
352: static void
353: showhosts()
354: {
1.6 mpech 355: struct hitem *p;
1.5 itojun 356: char hbuf[NI_MAXHOST];
357: struct sockaddr *sa;
358: int flags;
1.1 deraadt 359:
1.5 itojun 360: #if 0
361: flags = nflag ? NI_NUMERICHOST : 0;
362: #else
363: flags = 0;
364: #endif
1.1 deraadt 365: for (p = hosts; p < hosts+nhosts; p++) {
1.5 itojun 366: sa = (struct sockaddr *)&p->addr;
367: if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
368: flags) != 0)
1.9 ! deraadt 369: strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1 deraadt 370: if (!p->onoff)
371: addch('!');
1.5 itojun 372: printw("%s ", hbuf);
1.1 deraadt 373: }
374: }