Annotation of src/usr.bin/systat/netcmds.c, Revision 1.19
1.19 ! gilles 1: /* $OpenBSD: netcmds.c,v 1.18 2007/08/09 02:38:09 ray 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.19 ! gilles 37: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.18 2007/08/09 02:38:09 ray 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:
1.18 ray 57: #include <errno.h>
1.1 deraadt 58: #include <netdb.h>
59: #include <stdlib.h>
60: #include <string.h>
61: #include <ctype.h>
62: #include "systat.h"
63: #include "extern.h"
64:
65: #define streq(a,b) (strcmp(a,b)==0)
66:
67: static struct hitem {
1.5 itojun 68: struct sockaddr_storage addr;
1.1 deraadt 69: int onoff;
70: } *hosts;
71:
1.18 ray 72: size_t nports, nhosts;
73: int protos;
1.1 deraadt 74:
1.10 millert 75: static void changeitems(char *, int);
76: static int selectproto(char *);
77: static void showprotos(void);
78: static int selectport(long, int);
79: static void showports(void);
80: static int addrcmp(struct sockaddr *, struct sockaddr *);
81: static int selecthost(struct sockaddr *, int);
82: static void showhosts(void);
1.1 deraadt 83:
84: int
1.11 deraadt 85: netcmd(char *cmd, char *args)
1.1 deraadt 86: {
87:
88: if (prefix(cmd, "tcp") || prefix(cmd, "udp")) {
89: selectproto(cmd);
90: return (1);
91: }
92: if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
93: changeitems(args, prefix(cmd, "display"));
94: return (1);
95: }
96: if (prefix(cmd, "reset")) {
97: selectproto(0);
98: selecthost(0, 0);
1.15 cloder 99: selectport(htons(-1), 0);
1.1 deraadt 100: return (1);
101: }
102: if (prefix(cmd, "show")) {
1.16 deraadt 103: move(CMDLINE, 0);
104: clrtoeol();
1.1 deraadt 105: if (*args == '\0') {
106: showprotos();
107: showhosts();
108: showports();
109: return (1);
110: }
111: if (prefix(args, "protos"))
112: showprotos();
113: else if (prefix(args, "hosts"))
114: showhosts();
115: else if (prefix(args, "ports"))
116: showports();
117: else
118: addstr("show what?");
119: return (1);
120: }
121: return (0);
122: }
123:
124:
125: static void
1.11 deraadt 126: changeitems(char *args, int onoff)
1.1 deraadt 127: {
1.6 mpech 128: char *cp;
1.1 deraadt 129: struct servent *sp;
1.5 itojun 130: struct addrinfo hints, *res0, *res;
1.1 deraadt 131:
1.19 ! gilles 132: args[strcspn(args, "\n")] = '\0';
! 133:
1.1 deraadt 134: for (;;args = cp) {
1.17 tedu 135: for (cp = args; isspace(*cp); cp++)
1.1 deraadt 136: ;
137: args = cp;
138: for (; *cp && !isspace(*cp); cp++)
139: ;
140: if (*cp)
141: *cp++ = '\0';
142: if (cp - args == 0)
143: break;
144: sp = getservbyname(args,
145: protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
146: if (sp) {
147: selectport(sp->s_port, onoff);
148: continue;
149: }
1.5 itojun 150:
151: memset(&hints, 0, sizeof(hints));
152: hints.ai_family = PF_UNSPEC;
153: hints.ai_socktype = SOCK_DGRAM;
154: if (getaddrinfo(args, "0", &hints, &res0) != 0) {
155: error("%s: unknown host or port", args);
156: continue;
1.1 deraadt 157: }
1.5 itojun 158: for (res = res0; res; res = res->ai_next)
159: selecthost(res->ai_addr, onoff);
160: freeaddrinfo(res0);
1.1 deraadt 161: }
162: }
163:
164: static int
1.11 deraadt 165: selectproto(char *proto)
1.1 deraadt 166: {
167: int new = protos;
168:
169: if (proto == 0 || streq(proto, "all"))
170: new = TCP|UDP;
171: else if (streq(proto, "tcp"))
172: new = TCP;
173: else if (streq(proto, "udp"))
174: new = UDP;
1.4 millert 175: return (protos = new);
1.1 deraadt 176: }
177:
178: static void
1.11 deraadt 179: showprotos(void)
1.1 deraadt 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
1.11 deraadt 196: selectport(long port, int onoff)
1.1 deraadt 197: {
1.6 mpech 198: struct pitem *p;
1.1 deraadt 199:
1.15 cloder 200: if (ntohs(port) == -1) {
1.1 deraadt 201: if (ports == 0)
202: return (0);
1.16 deraadt 203: free(ports);
204: ports = NULL;
1.1 deraadt 205: nports = 0;
206: return (1);
207: }
208: for (p = ports; p < ports+nports; p++)
209: if (p->port == port) {
210: p->onoff = onoff;
211: return (0);
212: }
1.18 ray 213: if (nports + 1 > SIZE_MAX / sizeof(*p) ||
214: (p = realloc(ports, (nports + 1) * sizeof(*p))) == NULL) {
215: error("selectport: %s", strerror(ENOMEM));
216: die();
217: }
218: ports = p;
219:
1.1 deraadt 220: p = &ports[nports++];
221: p->port = port;
222: p->onoff = onoff;
223: return (1);
224: }
225:
226: int
1.11 deraadt 227: checkport(struct inpcb *inp)
1.1 deraadt 228: {
1.6 mpech 229: struct pitem *p;
1.1 deraadt 230:
231: if (ports)
232: for (p = ports; p < ports+nports; p++)
233: if (p->port == inp->inp_lport || p->port == inp->inp_fport)
234: return (p->onoff);
235: return (1);
236: }
237:
238: static void
1.11 deraadt 239: showports(void)
1.1 deraadt 240: {
1.6 mpech 241: struct pitem *p;
1.1 deraadt 242: struct servent *sp;
243:
244: for (p = ports; p < ports+nports; p++) {
245: sp = getservbyport(p->port,
1.4 millert 246: protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
1.1 deraadt 247: if (!p->onoff)
248: addch('!');
249: if (sp)
250: printw("%s ", sp->s_name);
251: else
1.15 cloder 252: printw("%d ", ntohs(p->port));
1.1 deraadt 253: }
254: }
255:
256: static int
1.11 deraadt 257: addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
1.5 itojun 258: {
259: if (sa1->sa_family != sa2->sa_family)
260: return 0;
261: if (sa1->sa_len != sa2->sa_len)
262: return 0;
263: switch (sa1->sa_family) {
264: case AF_INET:
265: if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
1.16 deraadt 266: ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
1.5 itojun 267: return 1;
268: break;
269: case AF_INET6:
270: if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
1.16 deraadt 271: &((struct sockaddr_in6 *)sa2)->sin6_addr))
1.5 itojun 272: return 1;
273: break;
274: default:
275: if (memcmp(sa1, sa2, sa1->sa_len) == 0)
276: return 1;
277: break;
278: }
279: return 0;
280: }
281:
282: static int
1.11 deraadt 283: selecthost(struct sockaddr *sa, int onoff)
1.1 deraadt 284: {
1.6 mpech 285: struct hitem *p;
1.1 deraadt 286:
1.5 itojun 287: if (sa == 0) {
1.1 deraadt 288: if (hosts == 0)
289: return (0);
1.16 deraadt 290: free(hosts);
291: hosts = NULL;
1.1 deraadt 292: nhosts = 0;
293: return (1);
294: }
295: for (p = hosts; p < hosts+nhosts; p++)
1.5 itojun 296: if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1 deraadt 297: p->onoff = onoff;
298: return (0);
299: }
1.5 itojun 300: if (sa->sa_len > sizeof(struct sockaddr_storage))
301: return (-1); /*XXX*/
1.18 ray 302: if (nhosts + 1 > SIZE_MAX / sizeof(*p) ||
303: (p = realloc(hosts, (nhosts + 1) * sizeof(*p))) == NULL) {
304: error("selecthost: %s", strerror(ENOMEM));
305: die();
306: }
307: hosts = p;
308:
1.1 deraadt 309: p = &hosts[nhosts++];
1.5 itojun 310: memcpy(&p->addr, sa, sa->sa_len);
1.1 deraadt 311: p->onoff = onoff;
312: return (1);
313: }
314:
315: int
1.11 deraadt 316: checkhost(struct inpcb *inp)
1.1 deraadt 317: {
1.6 mpech 318: struct hitem *p;
1.1 deraadt 319:
320: if (hosts)
1.5 itojun 321: for (p = hosts; p < hosts+nhosts; p++) {
1.9 deraadt 322: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
323: !(inp->inp_flags & INP_IPV6)) {
1.5 itojun 324: struct sockaddr_in *sin;
325: sin = (struct sockaddr_in *)&p->addr;
326: if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
327: sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
328: return (p->onoff);
329: }
1.9 deraadt 330: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
331: (inp->inp_flags & INP_IPV6)) {
1.5 itojun 332: struct sockaddr_in6 *sin6;
333: sin6 = (struct sockaddr_in6 *)&p->addr;
334: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
335: IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
336: return (p->onoff);
337: }
338: }
1.1 deraadt 339: return (1);
340: }
341:
342: static void
1.11 deraadt 343: showhosts(void)
1.1 deraadt 344: {
1.6 mpech 345: struct hitem *p;
1.5 itojun 346: char hbuf[NI_MAXHOST];
347: struct sockaddr *sa;
348: int flags;
1.1 deraadt 349:
1.5 itojun 350: flags = nflag ? NI_NUMERICHOST : 0;
1.1 deraadt 351: for (p = hosts; p < hosts+nhosts; p++) {
1.5 itojun 352: sa = (struct sockaddr *)&p->addr;
353: if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
1.16 deraadt 354: flags) != 0)
1.9 deraadt 355: strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1 deraadt 356: if (!p->onoff)
357: addch('!');
1.5 itojun 358: printw("%s ", hbuf);
1.1 deraadt 359: }
360: }