Annotation of src/usr.bin/systat/netcmds.c, Revision 1.12
1.12 ! millert 1: /* $OpenBSD: netcmds.c,v 1.11 2002/06/18 00:46:47 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.
1.12 ! millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)netcmds.c 8.1 (Berkeley) 6/6/93";
36: #endif
1.12 ! millert 37: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.11 2002/06/18 00:46:47 deraadt Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
40: /*
41: * Common network command support routines.
42: */
43: #include <sys/param.h>
44: #include <sys/socket.h>
45: #include <sys/socketvar.h>
46: #include <sys/mbuf.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:
55: #include <arpa/inet.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:
66: static struct hitem {
1.5 itojun 67: struct sockaddr_storage addr;
1.1 deraadt 68: int onoff;
69: } *hosts;
70:
71: int nports, nhosts, protos;
72:
1.10 millert 73: static void changeitems(char *, int);
74: static int selectproto(char *);
75: static void showprotos(void);
76: static int selectport(long, int);
77: static void showports(void);
78: static int addrcmp(struct sockaddr *, struct sockaddr *);
79: static int selecthost(struct sockaddr *, int);
80: static void showhosts(void);
1.1 deraadt 81:
82: int
1.11 deraadt 83: netcmd(char *cmd, char *args)
1.1 deraadt 84: {
85:
86: if (prefix(cmd, "tcp") || prefix(cmd, "udp")) {
87: selectproto(cmd);
88: return (1);
89: }
90: if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
91: changeitems(args, prefix(cmd, "display"));
92: return (1);
93: }
94: if (prefix(cmd, "reset")) {
95: selectproto(0);
96: selecthost(0, 0);
97: selectport(-1, 0);
98: return (1);
99: }
100: if (prefix(cmd, "show")) {
101: move(CMDLINE, 0); clrtoeol();
102: if (*args == '\0') {
103: showprotos();
104: showhosts();
105: showports();
106: return (1);
107: }
108: if (prefix(args, "protos"))
109: showprotos();
110: else if (prefix(args, "hosts"))
111: showhosts();
112: else if (prefix(args, "ports"))
113: showports();
114: else
115: addstr("show what?");
116: return (1);
117: }
118: return (0);
119: }
120:
121:
122: static void
1.11 deraadt 123: changeitems(char *args, int onoff)
1.1 deraadt 124: {
1.6 mpech 125: char *cp;
1.1 deraadt 126: struct servent *sp;
1.5 itojun 127: struct addrinfo hints, *res0, *res;
1.1 deraadt 128:
1.3 millert 129: cp = strchr(args, '\n');
1.1 deraadt 130: if (cp)
131: *cp = '\0';
132: for (;;args = cp) {
133: for (cp = args; *cp && isspace(*cp); cp++)
134: ;
135: args = cp;
136: for (; *cp && !isspace(*cp); cp++)
137: ;
138: if (*cp)
139: *cp++ = '\0';
140: if (cp - args == 0)
141: break;
142: sp = getservbyname(args,
143: protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
144: if (sp) {
145: selectport(sp->s_port, onoff);
146: continue;
147: }
1.5 itojun 148:
149: memset(&hints, 0, sizeof(hints));
150: hints.ai_family = PF_UNSPEC;
151: hints.ai_socktype = SOCK_DGRAM;
152: if (getaddrinfo(args, "0", &hints, &res0) != 0) {
153: error("%s: unknown host or port", args);
154: continue;
1.1 deraadt 155: }
1.5 itojun 156: for (res = res0; res; res = res->ai_next)
157: selecthost(res->ai_addr, onoff);
158: freeaddrinfo(res0);
1.1 deraadt 159: }
160: }
161:
162: static int
1.11 deraadt 163: selectproto(char *proto)
1.1 deraadt 164: {
165: int new = protos;
166:
167: if (proto == 0 || streq(proto, "all"))
168: new = TCP|UDP;
169: else if (streq(proto, "tcp"))
170: new = TCP;
171: else if (streq(proto, "udp"))
172: new = UDP;
1.4 millert 173: return (protos = new);
1.1 deraadt 174: }
175:
176: static void
1.11 deraadt 177: showprotos(void)
1.1 deraadt 178: {
179:
180: if ((protos&TCP) == 0)
181: addch('!');
182: addstr("tcp ");
183: if ((protos&UDP) == 0)
184: addch('!');
185: addstr("udp ");
186: }
187:
188: static struct pitem {
189: long port;
190: int onoff;
191: } *ports;
192:
193: static int
1.11 deraadt 194: selectport(long port, int onoff)
1.1 deraadt 195: {
1.6 mpech 196: struct pitem *p;
1.1 deraadt 197:
198: if (port == -1) {
199: if (ports == 0)
200: return (0);
201: free((char *)ports), ports = 0;
202: nports = 0;
203: return (1);
204: }
205: for (p = ports; p < ports+nports; p++)
206: if (p->port == port) {
207: p->onoff = onoff;
208: return (0);
209: }
210: if (nports == 0)
211: ports = (struct pitem *)malloc(sizeof (*p));
212: else
213: ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
214: p = &ports[nports++];
215: p->port = port;
216: p->onoff = onoff;
217: return (1);
218: }
219:
220: int
1.11 deraadt 221: checkport(struct inpcb *inp)
1.1 deraadt 222: {
1.6 mpech 223: struct pitem *p;
1.1 deraadt 224:
225: if (ports)
226: for (p = ports; p < ports+nports; p++)
227: if (p->port == inp->inp_lport || p->port == inp->inp_fport)
228: return (p->onoff);
229: return (1);
230: }
231:
232: static void
1.11 deraadt 233: showports(void)
1.1 deraadt 234: {
1.6 mpech 235: struct pitem *p;
1.1 deraadt 236: struct servent *sp;
237:
238: for (p = ports; p < ports+nports; p++) {
239: sp = getservbyport(p->port,
1.4 millert 240: protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
1.1 deraadt 241: if (!p->onoff)
242: addch('!');
243: if (sp)
244: printw("%s ", sp->s_name);
245: else
246: printw("%d ", p->port);
247: }
248: }
249:
250: static int
1.11 deraadt 251: addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
1.5 itojun 252: {
253: if (sa1->sa_family != sa2->sa_family)
254: return 0;
255: if (sa1->sa_len != sa2->sa_len)
256: return 0;
257: switch (sa1->sa_family) {
258: case AF_INET:
259: if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
260: ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
261: return 1;
262: break;
263: #ifdef INET6
264: case AF_INET6:
265: if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
266: &((struct sockaddr_in6 *)sa2)->sin6_addr))
267: return 1;
268: break;
269: #endif
270: default:
271: if (memcmp(sa1, sa2, sa1->sa_len) == 0)
272: return 1;
273: break;
274: }
275: return 0;
276: }
277:
278: static int
1.11 deraadt 279: selecthost(struct sockaddr *sa, int onoff)
1.1 deraadt 280: {
1.6 mpech 281: struct hitem *p;
1.1 deraadt 282:
1.5 itojun 283: if (sa == 0) {
1.1 deraadt 284: if (hosts == 0)
285: return (0);
286: free((char *)hosts), hosts = 0;
287: nhosts = 0;
288: return (1);
289: }
290: for (p = hosts; p < hosts+nhosts; p++)
1.5 itojun 291: if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1 deraadt 292: p->onoff = onoff;
293: return (0);
294: }
1.5 itojun 295: if (sa->sa_len > sizeof(struct sockaddr_storage))
296: return (-1); /*XXX*/
1.1 deraadt 297: if (nhosts == 0)
298: hosts = (struct hitem *)malloc(sizeof (*p));
299: else
300: hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
301: p = &hosts[nhosts++];
1.5 itojun 302: memcpy(&p->addr, sa, sa->sa_len);
1.1 deraadt 303: p->onoff = onoff;
304: return (1);
305: }
306:
307: int
1.11 deraadt 308: checkhost(struct inpcb *inp)
1.1 deraadt 309: {
1.6 mpech 310: struct hitem *p;
1.1 deraadt 311:
312: if (hosts)
1.5 itojun 313: for (p = hosts; p < hosts+nhosts; p++) {
1.9 deraadt 314: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
315: !(inp->inp_flags & INP_IPV6)) {
1.5 itojun 316: struct sockaddr_in *sin;
317: sin = (struct sockaddr_in *)&p->addr;
318: if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
319: sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
320: return (p->onoff);
321: }
322: #ifdef INET6
1.9 deraadt 323: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
324: (inp->inp_flags & INP_IPV6)) {
1.5 itojun 325: struct sockaddr_in6 *sin6;
326: sin6 = (struct sockaddr_in6 *)&p->addr;
327: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
328: IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
329: return (p->onoff);
330: }
331: #endif
332: }
1.1 deraadt 333: return (1);
334: }
335:
336: static void
1.11 deraadt 337: showhosts(void)
1.1 deraadt 338: {
1.6 mpech 339: struct hitem *p;
1.5 itojun 340: char hbuf[NI_MAXHOST];
341: struct sockaddr *sa;
342: int flags;
1.1 deraadt 343:
1.5 itojun 344: #if 0
345: flags = nflag ? NI_NUMERICHOST : 0;
346: #else
347: flags = 0;
348: #endif
1.1 deraadt 349: for (p = hosts; p < hosts+nhosts; p++) {
1.5 itojun 350: sa = (struct sockaddr *)&p->addr;
351: if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
352: flags) != 0)
1.9 deraadt 353: strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1 deraadt 354: if (!p->onoff)
355: addch('!');
1.5 itojun 356: printw("%s ", hbuf);
1.1 deraadt 357: }
358: }