Annotation of src/usr.bin/netstat/atalk.c, Revision 1.17
1.17 ! chl 1: /* $OpenBSD: atalk.c,v 1.16 2007/12/19 01:47:00 deraadt Exp $ */
1.1 denny 2: /* $NetBSD: atalk.c,v 1.2 1997/05/22 17:21:26 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1983, 1988, 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.11 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 denny 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: #include <sys/param.h>
34: #include <sys/queue.h>
35: #include <sys/socket.h>
36: #include <sys/socketvar.h>
37: #include <sys/mbuf.h>
38: #include <sys/protosw.h>
1.15 deraadt 39: #include <sys/sysctl.h>
1.1 denny 40: #include <netdb.h>
41:
42: #include <net/route.h>
43: #include <net/if.h>
44:
45: /* #include <netinet/tcp_fsm.h> */
46:
47: #include <netatalk/at.h>
48: #include <netatalk/ddp_var.h>
49:
1.17 ! chl 50: #include <err.h>
1.1 denny 51: #include <errno.h>
52: #include <stdio.h>
53: #include <string.h>
54: #include "netstat.h"
55:
56: struct ddpcb ddpcb;
57: struct socket sockb;
58:
59: static int first = 1;
60:
1.7 millert 61: static char *at_pr_net(struct sockaddr_at *, int);
62: static char *at_pr_host(struct sockaddr_at *, int);
63: static char *at_pr_range(struct sockaddr_at *);
64: static char *at_pr_port(struct sockaddr_at *);
1.1 denny 65:
66: /*
67: * Print a summary of connections related to a Network Systems
68: * protocol. For XXX, also give state of connection.
69: * Listening processes (aflag) are suppressed unless the
70: * -a (all) flag is specified.
71: */
72:
73: static char *
1.10 deraadt 74: at_pr_net(struct sockaddr_at *sat, int numeric)
1.1 denny 75: {
76: static char mybuf[50];
77:
78: if (!numeric) {
79: switch (sat->sat_addr.s_net) {
80: case 0xffff:
81: return "????";
82: case ATADDR_ANYNET:
83: return ("*");
84: }
85: }
1.6 mickey 86: (void) snprintf(mybuf, sizeof(mybuf), "%hu",
1.1 denny 87: ntohs(sat->sat_addr.s_net));
88: return mybuf;
89: }
90:
91: static char *
1.10 deraadt 92: at_pr_host(struct sockaddr_at *sat, int numeric)
1.1 denny 93: {
94: static char mybuf[50];
95:
96: if (!numeric) {
97: switch (sat->sat_addr.s_node) {
98: case ATADDR_BCAST:
99: return "bcast";
100: case ATADDR_ANYNODE:
101: return ("*");
102: }
103: }
1.6 mickey 104: (void) snprintf(mybuf, sizeof(mybuf), "%d",
1.1 denny 105: (unsigned int) sat->sat_addr.s_node);
106: return mybuf;
107: }
108:
109: static char *
1.10 deraadt 110: at_pr_port(struct sockaddr_at *sat)
1.1 denny 111: {
112: static char mybuf[50];
113: struct servent *serv;
114:
115: switch (sat->sat_port) {
116: case ATADDR_ANYPORT:
117: return ("*");
118: case 0xff:
119: return "????";
120: default:
121: if (nflag)
122: (void) snprintf(mybuf, sizeof(mybuf), "%d",
123: (unsigned int) sat->sat_port);
124: else {
125: serv = getservbyport(sat->sat_port, "ddp");
126: if (serv == NULL)
127: (void) snprintf(mybuf, sizeof(mybuf), "%d",
128: (unsigned int) sat->sat_port);
129: else
130: (void) snprintf(mybuf, sizeof(mybuf), "%s",
131: serv->s_name);
132: }
1.6 mickey 133:
1.1 denny 134: return mybuf;
135: }
136: }
137:
138: static char *
1.10 deraadt 139: at_pr_range(struct sockaddr_at *sat)
1.1 denny 140: {
141: static char mybuf[50];
142:
1.10 deraadt 143: if (sat->sat_range.r_netrange.nr_firstnet !=
144: sat->sat_range.r_netrange.nr_lastnet) {
1.1 denny 145: (void) snprintf(mybuf, sizeof(mybuf), "%d-%d",
1.8 deraadt 146: ntohs(sat->sat_range.r_netrange.nr_firstnet),
147: ntohs(sat->sat_range.r_netrange.nr_lastnet));
1.1 denny 148: } else {
149: (void) snprintf(mybuf, sizeof(mybuf), "%d",
1.8 deraadt 150: ntohs(sat->sat_range.r_netrange.nr_firstnet));
1.1 denny 151: }
152: return mybuf;
153: }
154:
155:
156: /* what == 0 for addr only == 3
157: * 1 for net
158: * 2 for host
159: * 4 for port
160: * 8 for numeric only
161: */
162: char *
1.10 deraadt 163: atalk_print(const struct sockaddr *sa, int what)
1.1 denny 164: {
165: struct sockaddr_at *sat = (struct sockaddr_at *) sa;
166: static char mybuf[50];
167: int numeric = (what & 0x08);
168:
169: mybuf[0] = 0;
170: switch (what & 0x13) {
171: case 0:
172: mybuf[0] = 0;
173: break;
174: case 1:
175: (void) snprintf(mybuf, sizeof(mybuf), "%s",
176: at_pr_net(sat, numeric));
177: break;
178: case 2:
179: (void) snprintf(mybuf, sizeof(mybuf), "%s",
180: at_pr_host(sat, numeric));
181: break;
182: case 3:
183: (void) snprintf(mybuf, sizeof(mybuf), "%s.%s",
1.8 deraadt 184: at_pr_net(sat, numeric),
185: at_pr_host(sat, numeric));
1.1 denny 186: break;
187: case 0x10:
188: (void) snprintf(mybuf, sizeof(mybuf), "%s", at_pr_range(sat));
189: }
190: if (what & 4) {
191: (void) snprintf(mybuf + strlen(mybuf),
192: sizeof(mybuf) - strlen(mybuf), ".%s",
193: at_pr_port(sat));
194: }
195: return mybuf;
196: }
197:
198: char *
1.10 deraadt 199: atalk_print2(const struct sockaddr *sa, const struct sockaddr *mask, int what)
1.1 denny 200: {
1.6 mickey 201: size_t n, l;
1.12 deraadt 202: static char buf[100];
1.1 denny 203: struct sockaddr_at *sat1, *sat2;
204: struct sockaddr_at thesockaddr;
205: struct sockaddr *sa2;
206:
207: sat1 = (struct sockaddr_at *) sa;
208: sat2 = (struct sockaddr_at *) mask;
209: sa2 = (struct sockaddr *) & thesockaddr;
210:
211: thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net &
212: sat2->sat_addr.s_net;
1.9 deraadt 213: if ((n = snprintf(buf, sizeof(buf), "%s",
214: atalk_print(sa2, 1 | (what & 8)))) >= sizeof(buf))
1.2 millert 215: n = sizeof(buf) - 1;
1.9 deraadt 216: else if (n < 0)
1.4 brian 217: n = 0; /* What else can be done ? */
1.1 denny 218: if (sat2->sat_addr.s_net != 0xFFFF) {
219: thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net |
220: ~sat2->sat_addr.s_net;
1.9 deraadt 221: if ((l = snprintf(buf + n, sizeof(buf) - n,
222: "-%s", atalk_print(sa2, 1 | (what & 8)))) >= sizeof(buf) - n)
1.2 millert 223: l = sizeof(buf) - n - 1;
1.4 brian 224: if (l > 0)
225: n += l;
1.1 denny 226: }
1.2 millert 227: if (what & 2) {
228: l = snprintf(buf + n, sizeof(buf) - n, ".%s",
1.1 denny 229: atalk_print(sa, what & (~1)));
1.2 millert 230: if (l >= sizeof(buf) - n)
231: l = sizeof(buf) - n - 1;
1.4 brian 232: if (l > 0)
233: n += l;
1.2 millert 234: }
1.1 denny 235: return (buf);
236: }
237:
238: void
1.10 deraadt 239: atalkprotopr(u_long off, char *name)
1.1 denny 240: {
241: struct ddpcb cb;
1.5 mpech 242: struct ddpcb *prev, *next;
1.1 denny 243: struct ddpcb *initial;
244:
245: if (off == 0)
246: return;
1.13 jaredy 247: if (kread(off, &initial, sizeof(struct ddpcb *)) < 0)
1.1 denny 248: return;
249: ddpcb = cb;
250: prev = (struct ddpcb *) off;
251: for (next = initial; next != NULL; prev = next) {
1.6 mickey 252: u_long ppcb = (u_long) next;
1.1 denny 253:
1.13 jaredy 254: if (kread((u_long) next, &ddpcb, sizeof(ddpcb)) < 0)
1.1 denny 255: return;
256: next = ddpcb.ddp_next;
257: #if 0
258: if (!aflag && atalk_nullhost(ddpcb.ddp_lsat)) {
259: continue;
260: }
261: #endif
1.13 jaredy 262: if (kread((u_long) ddpcb.ddp_socket, &sockb,
263: sizeof(sockb)) < 0)
1.1 denny 264: return;
265: if (first) {
266: printf("Active ATALK connections");
267: if (aflag)
268: printf(" (including servers)");
269: putchar('\n');
270: if (Aflag)
271: printf("%-8.8s ", "PCB");
272: printf(Aflag ?
273: "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
1.8 deraadt 274: "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
275: "Proto", "Recv-Q", "Send-Q",
276: "Local Address", "Foreign Address", "(state)");
1.1 denny 277: first = 0;
278: }
279: if (Aflag)
280: printf("%8lx ", ppcb);
281: printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
1.6 mickey 282: sockb.so_snd.sb_cc);
1.1 denny 283: printf(Aflag ? " %-18.18s" : " %-22.22s", atalk_print(
1.8 deraadt 284: (struct sockaddr *) & ddpcb.ddp_lsat, 7));
1.1 denny 285: printf(Aflag ? " %-18.18s" : " %-22.22s", atalk_print(
1.8 deraadt 286: (struct sockaddr *) & ddpcb.ddp_fsat, 7));
1.1 denny 287: putchar('\n');
288: }
289: }
290:
291: #define p(f, m) if (ddpstat.f || sflag <= 1) \
1.8 deraadt 292: printf(m, ddpstat.f, plural(ddpstat.f))
1.1 denny 293: #define p2(f1, f2, m) if (ddpstat.f1 || ddpstat.f2 || sflag <= 1) \
1.8 deraadt 294: printf(m, ddpstat.f1, plural(ddpstat.f1), ddpstat.f2, plural(ddpstat.f2))
1.1 denny 295: #define p3(f, m) if (ddpstat.f || sflag <= 1) \
1.8 deraadt 296: printf(m, ddpstat.f, plurales(ddpstat.f))
1.1 denny 297:
298: /*
299: * Dump DDP statistics structure.
300: */
301: void
1.15 deraadt 302: ddp_stats(char *name)
1.1 denny 303: {
304: struct ddpstat ddpstat;
1.15 deraadt 305: int mib[] = { CTL_NET, AF_APPLETALK, ATPROTO_DDP, DDPCTL_STATS };
306: size_t len = sizeof(ddpstat);
1.1 denny 307:
1.15 deraadt 308: if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
309: &ddpstat, &len, NULL, 0) == -1) {
310: if (errno != ENOPROTOOPT)
311: warn(name);
1.1 denny 312: return;
1.15 deraadt 313: }
314:
1.1 denny 315: printf("%s:\n", name);
316: p(ddps_short, "\t%ld packet%s with short headers\n");
317: p(ddps_long, "\t%ld packet%s with long headers\n");
318: p(ddps_nosum, "\t%ld packet%s with no checksum\n");
319: p(ddps_tooshort, "\t%ld packet%s were too short\n");
320: p(ddps_badsum, "\t%ld packet%s with bad checksum\n");
321: p(ddps_toosmall, "\t%ld packet%s with not enough data\n");
322: p(ddps_forward, "\t%ld packet%s forwarded\n");
323: p(ddps_cantforward, "\t%ld packet%s rcvd for unreachable dest\n");
324: p(ddps_nosockspace, "\t%ld packet%s dropped due to no socket space\n");
325: }