/usr.bin/netstat/atalk.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 285 lines · 215 code · 28 blank · 42 comment · 31 complexity · 8e52afd7e23b521f4ce72ef0ff45e23f MD5 · raw file

  1. /*-
  2. * Copyright (c) 1983, 1988, 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. #if 0
  30. #ifndef lint
  31. static char sccsid[] = "@(#)atalk.c 1.1 (Whistle) 6/6/96";
  32. #endif /* not lint */
  33. #endif
  34. #include <sys/cdefs.h>
  35. __FBSDID("$FreeBSD$");
  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. #include <arpa/inet.h>
  42. #include <net/route.h>
  43. #include <netatalk/at.h>
  44. #include <netatalk/ddp_var.h>
  45. #include <errno.h>
  46. #include <nlist.h>
  47. #include <netdb.h>
  48. #include <stdint.h>
  49. #include <stdio.h>
  50. #include <string.h>
  51. #include "netstat.h"
  52. struct ddpcb ddpcb;
  53. struct socket sockb;
  54. static int first = 1;
  55. /*
  56. * Print a summary of connections related to a Network Systems
  57. * protocol. For XXX, also give state of connection.
  58. * Listening processes (aflag) are suppressed unless the
  59. * -a (all) flag is specified.
  60. */
  61. static const char *
  62. at_pr_net(struct sockaddr_at *sat, int numeric)
  63. {
  64. static char mybuf[50];
  65. if (!numeric) {
  66. switch(sat->sat_addr.s_net) {
  67. case 0xffff:
  68. return "????";
  69. case ATADDR_ANYNET:
  70. return("*");
  71. }
  72. }
  73. sprintf(mybuf,"%hu",ntohs(sat->sat_addr.s_net));
  74. return mybuf;
  75. }
  76. static const char *
  77. at_pr_host(struct sockaddr_at *sat, int numeric)
  78. {
  79. static char mybuf[50];
  80. if (!numeric) {
  81. switch(sat->sat_addr.s_node) {
  82. case ATADDR_BCAST:
  83. return "bcast";
  84. case ATADDR_ANYNODE:
  85. return("*");
  86. }
  87. }
  88. sprintf(mybuf,"%d",(unsigned int)sat->sat_addr.s_node);
  89. return mybuf;
  90. }
  91. static const char *
  92. at_pr_port(struct sockaddr_at *sat)
  93. {
  94. static char mybuf[50];
  95. struct servent *serv;
  96. switch(sat->sat_port) {
  97. case ATADDR_ANYPORT:
  98. return("*");
  99. case 0xff:
  100. return "????";
  101. default:
  102. if (numeric_port) {
  103. (void)snprintf(mybuf, sizeof(mybuf), "%d",
  104. (unsigned int)sat->sat_port);
  105. } else {
  106. serv = getservbyport(sat->sat_port, "ddp");
  107. if (serv == NULL)
  108. (void)snprintf(mybuf, sizeof(mybuf), "%d",
  109. (unsigned int) sat->sat_port);
  110. else
  111. (void) snprintf(mybuf, sizeof(mybuf), "%s",
  112. serv->s_name);
  113. }
  114. }
  115. return mybuf;
  116. }
  117. static char *
  118. at_pr_range(struct sockaddr_at *sat)
  119. {
  120. static char mybuf[50];
  121. if(sat->sat_range.r_netrange.nr_firstnet
  122. != sat->sat_range.r_netrange.nr_lastnet) {
  123. sprintf(mybuf,"%d-%d",
  124. ntohs(sat->sat_range.r_netrange.nr_firstnet),
  125. ntohs(sat->sat_range.r_netrange.nr_lastnet));
  126. } else {
  127. sprintf(mybuf,"%d",
  128. ntohs(sat->sat_range.r_netrange.nr_firstnet));
  129. }
  130. return mybuf;
  131. }
  132. /* what == 0 for addr only == 3 */
  133. /* 1 for net */
  134. /* 2 for host */
  135. /* 4 for port */
  136. /* 8 for numeric only */
  137. char *
  138. atalk_print(struct sockaddr *sa, int what)
  139. {
  140. struct sockaddr_at *sat = (struct sockaddr_at *)sa;
  141. static char mybuf[50];
  142. int numeric = (what & 0x08);
  143. mybuf[0] = 0;
  144. switch (what & 0x13) {
  145. case 0:
  146. mybuf[0] = 0;
  147. break;
  148. case 1:
  149. sprintf(mybuf,"%s",at_pr_net(sat, numeric));
  150. break;
  151. case 2:
  152. sprintf(mybuf,"%s",at_pr_host(sat, numeric));
  153. break;
  154. case 3:
  155. sprintf(mybuf,"%s.%s",
  156. at_pr_net(sat, numeric),
  157. at_pr_host(sat, numeric));
  158. break;
  159. case 0x10:
  160. sprintf(mybuf,"%s", at_pr_range(sat));
  161. }
  162. if (what & 4) {
  163. sprintf(mybuf+strlen(mybuf),".%s",at_pr_port(sat));
  164. }
  165. return mybuf;
  166. }
  167. char *
  168. atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
  169. {
  170. int n;
  171. static char buf[100];
  172. struct sockaddr_at *sat1, *sat2;
  173. struct sockaddr_at thesockaddr;
  174. struct sockaddr *sa2;
  175. sat1 = (struct sockaddr_at *)sa;
  176. sat2 = (struct sockaddr_at *)mask;
  177. sa2 = (struct sockaddr *)&thesockaddr;
  178. thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net & sat2->sat_addr.s_net;
  179. snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 |(what & 8)));
  180. if(sat2->sat_addr.s_net != 0xFFFF) {
  181. thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net | ~sat2->sat_addr.s_net;
  182. n = strlen(buf);
  183. snprintf(buf + n, sizeof(buf) - n, "-%s", atalk_print(sa2, 1 |(what & 8)));
  184. }
  185. if(what & 2) {
  186. n = strlen(buf);
  187. snprintf(buf + n, sizeof(buf) - n, ".%s", atalk_print(sa, what & (~1)));
  188. }
  189. return(buf);
  190. }
  191. void
  192. atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
  193. int proto __unused)
  194. {
  195. struct ddpcb *this, *next;
  196. if (off == 0)
  197. return;
  198. kread(off, (char *)&this, sizeof (struct ddpcb *));
  199. for ( ; this != NULL; this = next) {
  200. kread((u_long)this, (char *)&ddpcb, sizeof (ddpcb));
  201. next = ddpcb.ddp_next;
  202. #if 0
  203. if (!aflag && atalk_nullhost(ddpcb.ddp_lsat) ) {
  204. continue;
  205. }
  206. #endif
  207. kread((u_long)ddpcb.ddp_socket, (char *)&sockb, sizeof (sockb));
  208. if (first) {
  209. printf("Active ATALK connections");
  210. if (aflag)
  211. printf(" (including servers)");
  212. putchar('\n');
  213. if (Aflag)
  214. printf("%-8.8s ", "PCB");
  215. printf(Aflag ?
  216. "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
  217. "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
  218. "Proto", "Recv-Q", "Send-Q",
  219. "Local Address", "Foreign Address", "(state)");
  220. first = 0;
  221. }
  222. if (Aflag)
  223. printf("%8lx ", (u_long) this);
  224. printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
  225. sockb.so_snd.sb_cc);
  226. printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
  227. (struct sockaddr *)&ddpcb.ddp_lsat,7));
  228. printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
  229. (struct sockaddr *)&ddpcb.ddp_fsat,7));
  230. putchar('\n');
  231. }
  232. }
  233. #define ANY(x,y,z) if (x || sflag <= 1) \
  234. printf("\t%lu %s%s%s\n",x,y,plural(x),z)
  235. /*
  236. * Dump DDP statistics structure.
  237. */
  238. void
  239. ddp_stats(u_long off __unused, const char *name, int af1 __unused,
  240. int proto __unused)
  241. {
  242. struct ddpstat ddpstat;
  243. if (off == 0)
  244. return;
  245. kread(off, (char *)&ddpstat, sizeof (ddpstat));
  246. printf("%s:\n", name);
  247. ANY(ddpstat.ddps_short, "packet", " with short headers ");
  248. ANY(ddpstat.ddps_long, "packet", " with long headers ");
  249. ANY(ddpstat.ddps_nosum, "packet", " with no checksum ");
  250. ANY(ddpstat.ddps_tooshort, "packet", " too short ");
  251. ANY(ddpstat.ddps_badsum, "packet", " with bad checksum ");
  252. ANY(ddpstat.ddps_toosmall, "packet", " with not enough data ");
  253. ANY(ddpstat.ddps_forward, "packet", " forwarded ");
  254. ANY(ddpstat.ddps_encap, "packet", " encapsulated ");
  255. ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest ");
  256. ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space ");
  257. }