Annotation of src/usr.bin/systat/netcmds.c, Revision 1.18
1.18 ! ray 1: /* $OpenBSD: netcmds.c,v 1.17 2007/03/20 03:56:13 tedu 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.18 ! ray 37: static char rcsid[] = "$OpenBSD: netcmds.c,v 1.17 2007/03/20 03:56:13 tedu 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.3 millert 132: cp = strchr(args, '\n');
1.1 deraadt 133: if (cp)
134: *cp = '\0';
135: for (;;args = cp) {
1.17 tedu 136: for (cp = args; isspace(*cp); cp++)
1.1 deraadt 137: ;
138: args = cp;
139: for (; *cp && !isspace(*cp); cp++)
140: ;
141: if (*cp)
142: *cp++ = '\0';
143: if (cp - args == 0)
144: break;
145: sp = getservbyname(args,
146: protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
147: if (sp) {
148: selectport(sp->s_port, onoff);
149: continue;
150: }
1.5 itojun 151:
152: memset(&hints, 0, sizeof(hints));
153: hints.ai_family = PF_UNSPEC;
154: hints.ai_socktype = SOCK_DGRAM;
155: if (getaddrinfo(args, "0", &hints, &res0) != 0) {
156: error("%s: unknown host or port", args);
157: continue;
1.1 deraadt 158: }
1.5 itojun 159: for (res = res0; res; res = res->ai_next)
160: selecthost(res->ai_addr, onoff);
161: freeaddrinfo(res0);
1.1 deraadt 162: }
163: }
164:
165: static int
1.11 deraadt 166: selectproto(char *proto)
1.1 deraadt 167: {
168: int new = protos;
169:
170: if (proto == 0 || streq(proto, "all"))
171: new = TCP|UDP;
172: else if (streq(proto, "tcp"))
173: new = TCP;
174: else if (streq(proto, "udp"))
175: new = UDP;
1.4 millert 176: return (protos = new);
1.1 deraadt 177: }
178:
179: static void
1.11 deraadt 180: showprotos(void)
1.1 deraadt 181: {
182:
183: if ((protos&TCP) == 0)
184: addch('!');
185: addstr("tcp ");
186: if ((protos&UDP) == 0)
187: addch('!');
188: addstr("udp ");
189: }
190:
191: static struct pitem {
192: long port;
193: int onoff;
194: } *ports;
195:
196: static int
1.11 deraadt 197: selectport(long port, int onoff)
1.1 deraadt 198: {
1.6 mpech 199: struct pitem *p;
1.1 deraadt 200:
1.15 cloder 201: if (ntohs(port) == -1) {
1.1 deraadt 202: if (ports == 0)
203: return (0);
1.16 deraadt 204: free(ports);
205: ports = NULL;
1.1 deraadt 206: nports = 0;
207: return (1);
208: }
209: for (p = ports; p < ports+nports; p++)
210: if (p->port == port) {
211: p->onoff = onoff;
212: return (0);
213: }
1.18 ! ray 214: if (nports + 1 > SIZE_MAX / sizeof(*p) ||
! 215: (p = realloc(ports, (nports + 1) * sizeof(*p))) == NULL) {
! 216: error("selectport: %s", strerror(ENOMEM));
! 217: die();
! 218: }
! 219: ports = p;
! 220:
1.1 deraadt 221: p = &ports[nports++];
222: p->port = port;
223: p->onoff = onoff;
224: return (1);
225: }
226:
227: int
1.11 deraadt 228: checkport(struct inpcb *inp)
1.1 deraadt 229: {
1.6 mpech 230: struct pitem *p;
1.1 deraadt 231:
232: if (ports)
233: for (p = ports; p < ports+nports; p++)
234: if (p->port == inp->inp_lport || p->port == inp->inp_fport)
235: return (p->onoff);
236: return (1);
237: }
238:
239: static void
1.11 deraadt 240: showports(void)
1.1 deraadt 241: {
1.6 mpech 242: struct pitem *p;
1.1 deraadt 243: struct servent *sp;
244:
245: for (p = ports; p < ports+nports; p++) {
246: sp = getservbyport(p->port,
1.4 millert 247: protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
1.1 deraadt 248: if (!p->onoff)
249: addch('!');
250: if (sp)
251: printw("%s ", sp->s_name);
252: else
1.15 cloder 253: printw("%d ", ntohs(p->port));
1.1 deraadt 254: }
255: }
256:
257: static int
1.11 deraadt 258: addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
1.5 itojun 259: {
260: if (sa1->sa_family != sa2->sa_family)
261: return 0;
262: if (sa1->sa_len != sa2->sa_len)
263: return 0;
264: switch (sa1->sa_family) {
265: case AF_INET:
266: if (((struct sockaddr_in *)sa1)->sin_addr.s_addr ==
1.16 deraadt 267: ((struct sockaddr_in *)sa2)->sin_addr.s_addr)
1.5 itojun 268: return 1;
269: break;
270: case AF_INET6:
271: if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)sa1)->sin6_addr,
1.16 deraadt 272: &((struct sockaddr_in6 *)sa2)->sin6_addr))
1.5 itojun 273: return 1;
274: break;
275: default:
276: if (memcmp(sa1, sa2, sa1->sa_len) == 0)
277: return 1;
278: break;
279: }
280: return 0;
281: }
282:
283: static int
1.11 deraadt 284: selecthost(struct sockaddr *sa, int onoff)
1.1 deraadt 285: {
1.6 mpech 286: struct hitem *p;
1.1 deraadt 287:
1.5 itojun 288: if (sa == 0) {
1.1 deraadt 289: if (hosts == 0)
290: return (0);
1.16 deraadt 291: free(hosts);
292: hosts = NULL;
1.1 deraadt 293: nhosts = 0;
294: return (1);
295: }
296: for (p = hosts; p < hosts+nhosts; p++)
1.5 itojun 297: if (addrcmp((struct sockaddr *)&p->addr, sa)) {
1.1 deraadt 298: p->onoff = onoff;
299: return (0);
300: }
1.5 itojun 301: if (sa->sa_len > sizeof(struct sockaddr_storage))
302: return (-1); /*XXX*/
1.18 ! ray 303: if (nhosts + 1 > SIZE_MAX / sizeof(*p) ||
! 304: (p = realloc(hosts, (nhosts + 1) * sizeof(*p))) == NULL) {
! 305: error("selecthost: %s", strerror(ENOMEM));
! 306: die();
! 307: }
! 308: hosts = p;
! 309:
1.1 deraadt 310: p = &hosts[nhosts++];
1.5 itojun 311: memcpy(&p->addr, sa, sa->sa_len);
1.1 deraadt 312: p->onoff = onoff;
313: return (1);
314: }
315:
316: int
1.11 deraadt 317: checkhost(struct inpcb *inp)
1.1 deraadt 318: {
1.6 mpech 319: struct hitem *p;
1.1 deraadt 320:
321: if (hosts)
1.5 itojun 322: for (p = hosts; p < hosts+nhosts; p++) {
1.9 deraadt 323: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET &&
324: !(inp->inp_flags & INP_IPV6)) {
1.5 itojun 325: struct sockaddr_in *sin;
326: sin = (struct sockaddr_in *)&p->addr;
327: if (sin->sin_addr.s_addr == inp->inp_laddr.s_addr ||
328: sin->sin_addr.s_addr == inp->inp_faddr.s_addr)
329: return (p->onoff);
330: }
1.9 deraadt 331: if (((struct sockaddr *)&p->addr)->sa_family == AF_INET6 &&
332: (inp->inp_flags & INP_IPV6)) {
1.5 itojun 333: struct sockaddr_in6 *sin6;
334: sin6 = (struct sockaddr_in6 *)&p->addr;
335: if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_laddr6) ||
336: IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &inp->inp_faddr6))
337: return (p->onoff);
338: }
339: }
1.1 deraadt 340: return (1);
341: }
342:
343: static void
1.11 deraadt 344: showhosts(void)
1.1 deraadt 345: {
1.6 mpech 346: struct hitem *p;
1.5 itojun 347: char hbuf[NI_MAXHOST];
348: struct sockaddr *sa;
349: int flags;
1.1 deraadt 350:
1.5 itojun 351: flags = nflag ? NI_NUMERICHOST : 0;
1.1 deraadt 352: for (p = hosts; p < hosts+nhosts; p++) {
1.5 itojun 353: sa = (struct sockaddr *)&p->addr;
354: if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
1.16 deraadt 355: flags) != 0)
1.9 deraadt 356: strlcpy(hbuf, "(invalid)", sizeof hbuf);
1.1 deraadt 357: if (!p->onoff)
358: addch('!');
1.5 itojun 359: printw("%s ", hbuf);
1.1 deraadt 360: }
361: }