/usr.bin/systat/netcmds.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 308 lines · 244 code · 33 blank · 31 comment · 79 complexity · f95dd1c133ee2881c8940c4b4e0e3a2c MD5 · raw file

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