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 * 4. 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 30 #include <sys/cdefs.h> 31 32 __FBSDID("$FreeBSD$"); 33 34 #ifdef lint 35 static const char sccsid[] = "@(#)netcmds.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 38 /* 39 * Common network command support routines. 40 */ 41 #include <sys/param.h> 42 #include <sys/queue.h> 43 #include <sys/socket.h> 44 #include <sys/socketvar.h> 45 #include <sys/protosw.h> 46 47 #include <net/route.h> 48 #include <netinet/in.h> 49 #include <netinet/in_systm.h> 50 #include <netinet/ip.h> 51 #include <netinet/in_pcb.h> 52 #include <arpa/inet.h> 53 54 #include <ctype.h> 55 #include <netdb.h> 56 #include <stdlib.h> 57 #include <string.h> 58 59 #include "systat.h" 60 #include "extern.h" 61 62 #define streq(a,b) (strcmp(a,b)==0) 63 64 static struct hitem { 65 struct in_addr addr; 66 int onoff; 67 } *hosts; 68 69 int nports, nhosts, protos; 70 71 static void changeitems(const char *, int); 72 static int selectproto(const char *); 73 static void showprotos(void); 74 static int selectport(long, int); 75 static void showports(void); 76 static int selecthost(struct in_addr *, int); 77 static void showhosts(void); 78 79 int 80 netcmd(const char *cmd, const char *args) 81 { 82 83 if (prefix(cmd, "proto")) { 84 if (*args == '\0') { 85 move(CMDLINE, 0); 86 clrtoeol(); 87 addstr("which proto?"); 88 } else if (!selectproto(args)) { 89 error("%s: Unknown protocol.", args); 90 } 91 return (1); 92 } 93 if (prefix(cmd, "ignore") || prefix(cmd, "display")) { 94 changeitems(args, prefix(cmd, "display")); 95 return (1); 96 } 97 if (prefix(cmd, "reset")) { 98 selectproto(0); 99 selecthost(0, 0); 100 selectport(-1, 0); 101 return (1); 102 } 103 if (prefix(cmd, "show")) { 104 move(CMDLINE, 0); clrtoeol(); 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 static void 125 changeitems(const char *args, int onoff) 126 { 127 char *cp, *tmpstr, *tmpstr1; 128 struct servent *sp; 129 struct hostent *hp; 130 struct in_addr in; 131 132 tmpstr = tmpstr1 = strdup(args); 133 cp = strchr(tmpstr1, '\n'); 134 if (cp) 135 *cp = '\0'; 136 for (;;tmpstr1 = cp) { 137 for (cp = tmpstr1; *cp && isspace(*cp); cp++) 138 ; 139 tmpstr1 = cp; 140 for (; *cp && !isspace(*cp); cp++) 141 ; 142 if (*cp) 143 *cp++ = '\0'; 144 if (cp - tmpstr1 == 0) 145 break; 146 sp = getservbyname(tmpstr1, 147 protos == TCP ? "tcp" : protos == UDP ? "udp" : 0); 148 if (sp) { 149 selectport(sp->s_port, onoff); 150 continue; 151 } 152 hp = gethostbyname(tmpstr1); 153 if (hp == 0) { 154 in.s_addr = inet_addr(tmpstr1); 155 if (in.s_addr == INADDR_NONE) { 156 error("%s: unknown host or port", tmpstr1); 157 continue; 158 } 159 } else 160 in = *(struct in_addr *)hp->h_addr; 161 selecthost(&in, onoff); 162 } 163 free(tmpstr); 164 } 165 166 static int 167 selectproto(const char *proto) 168 { 169 170 if (proto == 0 || streq(proto, "all")) 171 protos = TCP | UDP; 172 else if (streq(proto, "tcp")) 173 protos = TCP; 174 else if (streq(proto, "udp")) 175 protos = UDP; 176 else 177 return (0); 178 179 return (protos); 180 } 181 182 static void 183 showprotos(void) 184 { 185 186 if ((protos&TCP) == 0) 187 addch('!'); 188 addstr("tcp "); 189 if ((protos&UDP) == 0) 190 addch('!'); 191 addstr("udp "); 192 } 193 194 static struct pitem { 195 long port; 196 int onoff; 197 } *ports; 198 199 static int 200 selectport(long port, int onoff) 201 { 202 struct pitem *p; 203 204 if (port == -1) { 205 if (ports == 0) 206 return (0); 207 free((char *)ports), ports = 0; 208 nports = 0; 209 return (1); 210 } 211 for (p = ports; p < ports+nports; p++) 212 if (p->port == port) { 213 p->onoff = onoff; 214 return (0); 215 } 216 if (nports == 0) 217 ports = (struct pitem *)malloc(sizeof (*p)); 218 else 219 ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p)); 220 p = &ports[nports++]; 221 p->port = port; 222 p->onoff = onoff; 223 return (1); 224 } 225 226 int 227 checkport(struct inpcb *inp) 228 { 229 struct pitem *p; 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 239 showports(void) 240 { 241 struct pitem *p; 242 struct servent *sp; 243 244 for (p = ports; p < ports+nports; p++) { 245 sp = getservbyport(p->port, 246 protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp"); 247 if (!p->onoff) 248 addch('!'); 249 if (sp) 250 printw("%s ", sp->s_name); 251 else 252 printw("%d ", p->port); 253 } 254 } 255 256 static int 257 selecthost(struct in_addr *in, int onoff) 258 { 259 struct hitem *p; 260 261 if (in == 0) { 262 if (hosts == 0) 263 return (0); 264 free((char *)hosts), hosts = 0; 265 nhosts = 0; 266 return (1); 267 } 268 for (p = hosts; p < hosts+nhosts; p++) 269 if (p->addr.s_addr == in->s_addr) { 270 p->onoff = onoff; 271 return (0); 272 } 273 if (nhosts == 0) 274 hosts = (struct hitem *)malloc(sizeof (*p)); 275 else 276 hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p)); 277 p = &hosts[nhosts++]; 278 p->addr = *in; 279 p->onoff = onoff; 280 return (1); 281 } 282 283 int 284 checkhost(struct inpcb *inp) 285 { 286 struct hitem *p; 287 288 if (hosts) 289 for (p = hosts; p < hosts+nhosts; p++) 290 if (p->addr.s_addr == inp->inp_laddr.s_addr || 291 p->addr.s_addr == inp->inp_faddr.s_addr) 292 return (p->onoff); 293 return (1); 294 } 295 296 static void 297 showhosts(void) 298 { 299 struct hitem *p; 300 struct hostent *hp; 301 302 for (p = hosts; p < hosts+nhosts; p++) { 303 hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET); 304 if (!p->onoff) 305 addch('!'); 306 printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr)); 307 } 308 } 309