1 /*- 2 * Copyright (c) 1980, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)netcmds.c 8.1 (Berkeley) 6/6/93 30 * $FreeBSD: src/usr.bin/systat/netcmds.c,v 1.9 1999/08/28 01:06:04 peter Exp $ 31 */ 32 33 /* 34 * Common network command support routines. 35 */ 36 #include <sys/param.h> 37 #include <sys/queue.h> 38 #include <sys/socket.h> 39 #include <sys/socketvar.h> 40 #include <sys/protosw.h> 41 42 #include <net/route.h> 43 #include <netinet/in.h> 44 #include <netinet/in_systm.h> 45 #include <netinet/ip.h> 46 #include <netinet/in_pcb.h> 47 #include <arpa/inet.h> 48 49 #include <netdb.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <ctype.h> 53 #include "systat.h" 54 #include "extern.h" 55 56 #define streq(a,b) (strcmp(a,b)==0) 57 58 static struct hitem { 59 struct in_addr addr; 60 int onoff; 61 } *hosts; 62 63 int nports, nhosts, protos; 64 65 static void changeitems(char *, int); 66 static int selectproto(char *); 67 static void showprotos(void); 68 static int selectport(long, int); 69 static void showports(void); 70 static int selecthost(struct in_addr *, int); 71 static void showhosts(void); 72 73 int 74 netcmd(const char *cmd, char *args) 75 { 76 77 if (prefix(cmd, "proto")) { 78 if (*args == '\0') { 79 move(CMDLINE, 0); 80 clrtoeol(); 81 addstr("which proto?"); 82 } else if (!selectproto(args)) { 83 error("%s: Unknown protocol.", args); 84 } 85 return (1); 86 } 87 if (prefix(cmd, "ignore") || prefix(cmd, "display")) { 88 changeitems(args, prefix(cmd, "display")); 89 return (1); 90 } 91 if (prefix(cmd, "reset")) { 92 selectproto(0); 93 selecthost(0, 0); 94 selectport(-1, 0); 95 return (1); 96 } 97 if (prefix(cmd, "show")) { 98 move(CMDLINE, 0); clrtoeol(); 99 if (*args == '\0') { 100 showprotos(); 101 showhosts(); 102 showports(); 103 return (1); 104 } 105 if (prefix(args, "protos")) 106 showprotos(); 107 else if (prefix(args, "hosts")) 108 showhosts(); 109 else if (prefix(args, "ports")) 110 showports(); 111 else 112 addstr("show what?"); 113 return (1); 114 } 115 return (0); 116 } 117 118 119 static void 120 changeitems(char *args, int onoff) 121 { 122 char *cp; 123 struct servent *sp; 124 struct hostent *hp; 125 struct in_addr in; 126 127 cp = strchr(args, '\n'); 128 if (cp) 129 *cp = '\0'; 130 for (;;args = cp) { 131 for (cp = args; *cp && isspace(*cp); cp++) 132 ; 133 args = cp; 134 for (; *cp && !isspace(*cp); cp++) 135 ; 136 if (*cp) 137 *cp++ = '\0'; 138 if (cp - args == 0) 139 break; 140 sp = getservbyname(args, 141 protos == TCP ? "tcp" : protos == UDP ? "udp" : 0); 142 if (sp) { 143 selectport(sp->s_port, onoff); 144 continue; 145 } 146 hp = gethostbyname(args); 147 if (hp == NULL) { 148 in.s_addr = inet_addr(args); 149 if ((int)in.s_addr == -1) { 150 error("%s: unknown host or port", args); 151 continue; 152 } 153 } else 154 in = *(struct in_addr *)hp->h_addr; 155 selecthost(&in, onoff); 156 } 157 } 158 159 static int 160 selectproto(char *proto) 161 { 162 163 if (proto == NULL || streq(proto, "all")) 164 protos = TCP | UDP; 165 else if (streq(proto, "tcp")) 166 protos = TCP; 167 else if (streq(proto, "udp")) 168 protos = UDP; 169 else 170 return (0); 171 172 return (protos); 173 } 174 175 static void 176 showprotos(void) 177 { 178 179 if ((protos&TCP) == 0) 180 addch('!'); 181 addstr("tcp "); 182 if ((protos&UDP) == 0) 183 addch('!'); 184 addstr("udp "); 185 } 186 187 static struct pitem { 188 long port; 189 int onoff; 190 } *ports; 191 192 static int 193 selectport(long port, int onoff) 194 { 195 struct pitem *p; 196 197 if (port == -1) { 198 if (ports == NULL) 199 return (0); 200 free((char *)ports), ports = NULL; 201 nports = 0; 202 return (1); 203 } 204 for (p = ports; p < ports+nports; p++) 205 if (p->port == port) { 206 p->onoff = onoff; 207 return (0); 208 } 209 if (nports == 0) 210 ports = (struct pitem *)malloc(sizeof (*p)); 211 else 212 ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p)); 213 p = &ports[nports++]; 214 p->port = port; 215 p->onoff = onoff; 216 return (1); 217 } 218 219 int 220 checkport(struct inpcb *inp) 221 { 222 struct pitem *p; 223 224 if (ports) 225 for (p = ports; p < ports+nports; p++) { 226 if (p->port == inp->inp_lport || 227 p->port == inp->inp_fport) 228 return (p->onoff); 229 } 230 return (1); 231 } 232 233 static void 234 showports(void) 235 { 236 struct pitem *p; 237 struct servent *sp; 238 239 for (p = ports; p < ports+nports; p++) { 240 sp = getservbyport(p->port, 241 protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp"); 242 if (!p->onoff) 243 addch('!'); 244 if (sp) 245 printw("%s ", sp->s_name); 246 else 247 printw("%d ", p->port); 248 } 249 } 250 251 static int 252 selecthost(struct in_addr *in, int onoff) 253 { 254 struct hitem *p; 255 256 if (in == NULL) { 257 if (hosts == NULL) 258 return (0); 259 free((char *)hosts), hosts = NULL; 260 nhosts = 0; 261 return (1); 262 } 263 for (p = hosts; p < hosts+nhosts; p++) 264 if (p->addr.s_addr == in->s_addr) { 265 p->onoff = onoff; 266 return (0); 267 } 268 if (nhosts == 0) 269 hosts = (struct hitem *)malloc(sizeof (*p)); 270 else 271 hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p)); 272 p = &hosts[nhosts++]; 273 p->addr = *in; 274 p->onoff = onoff; 275 return (1); 276 } 277 278 int 279 checkhost(struct inpcb *inp) 280 { 281 struct hitem *p; 282 283 if (hosts) 284 for (p = hosts; p < hosts+nhosts; p++) { 285 if (p->addr.s_addr == inp->inp_laddr.s_addr || 286 p->addr.s_addr == inp->inp_faddr.s_addr) 287 return (p->onoff); 288 } 289 return (1); 290 } 291 292 static void 293 showhosts(void) 294 { 295 struct hitem *p; 296 struct hostent *hp; 297 298 for (p = hosts; p < hosts+nhosts; p++) { 299 hp = gethostbyaddr(&p->addr, sizeof (p->addr), AF_INET); 300 if (!p->onoff) 301 addch('!'); 302 printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr)); 303 } 304 } 305