Annotation of src/usr.bin/systat/netcmds.c, Revision 1.14
1.14 ! deraadt 1: /* $OpenBSD: netcmds.c,v 1.13 2004/04/26 19:22:30 itojun 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.14 ! deraadt 37: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.13 2004/04/26 19:22:30 itojun 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: case AF_INET6:
264: if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
265: &((struct sockaddr_in6 *)sa2)->sin6_addr))
266: return 1;
267: break;
268: default:
269: if (memcmp(sa1, sa2, sa1->sa_len) == 0)
270: return 1;
271: break;
272: }
273: return 0;
274: }
275:
276: static int
1.11 deraadt 277: selecthost(struct sockaddr *sa, int onoff)
1.1 deraadt 278: {
1.6 mpech 279: struct hitem *p;
1.1 deraadt 280:
1.5 itojun 281: if (sa == 0) {
1.1 deraadt 282: if (hosts == 0)
283: return (0);
284: free((char *)hosts), hosts = 0;
285: nhosts = 0;
286: return (1);
287: }
288: for (p = hosts; p < hosts+nhosts; p++)
1.5 itojun 289: if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1 deraadt 290: p->onoff = onoff;
291: return (0);
292: }
1.5 itojun 293: if (sa->sa_len > sizeof(struct sockaddr_storage))
294: return (-1); /*XXX*/
1.1 deraadt 295: if (nhosts == 0)
296: hosts = (struct hitem *)malloc(sizeof (*p));
297: else
298: hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
299: p = &hosts[nhosts++];
1.5 itojun 300: memcpy(&p->addr, sa, sa->sa_len);
1.1 deraadt 301: p->onoff = onoff;
302: return (1);
303: }
304:
305: int
1.11 deraadt 306: checkhost(struct inpcb *inp)
1.1 deraadt 307: {
1.6 mpech 308: struct hitem *p;
1.1 deraadt 309:
310: if (hosts)
1.5 itojun 311: for (p = hosts; p < hosts+nhosts; p++) {
1.9 deraadt 312: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
313: !(inp->inp_flags & INP_IPV6)) {
1.5 itojun 314: struct sockaddr_in *sin;
315: sin = (struct sockaddr_in *)&p->addr;
316: if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
317: sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
318: return (p->onoff);
319: }
1.9 deraadt 320: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
321: (inp->inp_flags & INP_IPV6)) {
1.5 itojun 322: struct sockaddr_in6 *sin6;
323: sin6 = (struct sockaddr_in6 *)&p->addr;
324: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
325: IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
326: return (p->onoff);
327: }
328: }
1.1 deraadt 329: return (1);
330: }
331:
332: static void
1.11 deraadt 333: showhosts(void)
1.1 deraadt 334: {
1.6 mpech 335: struct hitem *p;
1.5 itojun 336: char hbuf[NI_MAXHOST];
337: struct sockaddr *sa;
338: int flags;
1.1 deraadt 339:
1.5 itojun 340: flags = nflag ? NI_NUMERICHOST : 0;
1.1 deraadt 341: for (p = hosts; p < hosts+nhosts; p++) {
1.5 itojun 342: sa = (struct sockaddr *)&p->addr;
343: if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
344: flags) != 0)
1.9 deraadt 345: strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1 deraadt 346: if (!p->onoff)
347: addch('!');
1.5 itojun 348: printw("%s ", hbuf);
1.1 deraadt 349: }
350: }