Annotation of src/usr.bin/netstat/atalk.c, Revision 1.2
1.1 denny 1: /* $NetBSD: atalk.c,v 1.2 1997/05/22 17:21:26 christos Exp $ */
2:
3: /*
4: * Copyright (c) 1983, 1988, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: #if 0
38: static char sccsid[] = "from @(#)atalk.c 1.1 (Whistle) 6/6/96";
39: #else
40: static char rcsid[] = "$NetBSD: atalk.c,v 1.2 1997/05/22 17:21:26 christos Exp $";
41: #endif
42: #endif /* not lint */
43:
44: #include <sys/param.h>
45: #include <sys/queue.h>
46: #include <sys/socket.h>
47: #include <sys/socketvar.h>
48: #include <sys/mbuf.h>
49: #include <sys/protosw.h>
50: #include <netdb.h>
51:
52: #include <net/route.h>
53: #include <net/if.h>
54:
55: /* #include <netinet/tcp_fsm.h> */
56:
57: #include <netatalk/at.h>
58: #include <netatalk/ddp_var.h>
59:
60: #include <nlist.h>
61: #include <errno.h>
62: #include <stdio.h>
63: #include <string.h>
64: #include "netstat.h"
65:
66: struct ddpcb ddpcb;
67: struct socket sockb;
68:
69: static int first = 1;
70:
71: static char *at_pr_net __P((struct sockaddr_at *, int));
72: static char *at_pr_host __P((struct sockaddr_at *, int));
73: static char *at_pr_range __P((struct sockaddr_at *));
74: static char *at_pr_port __P((struct sockaddr_at *));
75:
76: /*
77: * Print a summary of connections related to a Network Systems
78: * protocol. For XXX, also give state of connection.
79: * Listening processes (aflag) are suppressed unless the
80: * -a (all) flag is specified.
81: */
82:
83: static char *
84: at_pr_net(sat, numeric)
85: struct sockaddr_at *sat;
86: int numeric;
87: {
88: static char mybuf[50];
89:
90: if (!numeric) {
91: switch (sat->sat_addr.s_net) {
92: case 0xffff:
93: return "????";
94: case ATADDR_ANYNET:
95: return ("*");
96: }
97: }
98: (void) snprintf(mybuf, sizeof(mybuf), "%hu",
99: ntohs(sat->sat_addr.s_net));
100: return mybuf;
101: }
102:
103: static char *
104: at_pr_host(sat, numeric)
105: struct sockaddr_at *sat;
106: int numeric;
107: {
108: static char mybuf[50];
109:
110: if (!numeric) {
111: switch (sat->sat_addr.s_node) {
112: case ATADDR_BCAST:
113: return "bcast";
114: case ATADDR_ANYNODE:
115: return ("*");
116: }
117: }
118: (void) snprintf(mybuf, sizeof(mybuf), "%d",
119: (unsigned int) sat->sat_addr.s_node);
120: return mybuf;
121: }
122:
123: static char *
124: at_pr_port(sat)
125: struct sockaddr_at *sat;
126: {
127: static char mybuf[50];
128: struct servent *serv;
129:
130: switch (sat->sat_port) {
131: case ATADDR_ANYPORT:
132: return ("*");
133: case 0xff:
134: return "????";
135: default:
136: if (nflag)
137: (void) snprintf(mybuf, sizeof(mybuf), "%d",
138: (unsigned int) sat->sat_port);
139: else {
140: serv = getservbyport(sat->sat_port, "ddp");
141: if (serv == NULL)
142: (void) snprintf(mybuf, sizeof(mybuf), "%d",
143: (unsigned int) sat->sat_port);
144: else
145: (void) snprintf(mybuf, sizeof(mybuf), "%s",
146: serv->s_name);
147: }
148:
149: return mybuf;
150: }
151: }
152:
153: static char *
154: at_pr_range(sat)
155: struct sockaddr_at *sat;
156: {
157: static char mybuf[50];
158:
159: if (sat->sat_range.r_netrange.nr_firstnet
160: != sat->sat_range.r_netrange.nr_lastnet) {
161: (void) snprintf(mybuf, sizeof(mybuf), "%d-%d",
162: ntohs(sat->sat_range.r_netrange.nr_firstnet),
163: ntohs(sat->sat_range.r_netrange.nr_lastnet));
164: } else {
165: (void) snprintf(mybuf, sizeof(mybuf), "%d",
166: ntohs(sat->sat_range.r_netrange.nr_firstnet));
167: }
168: return mybuf;
169: }
170:
171:
172: /* what == 0 for addr only == 3
173: * 1 for net
174: * 2 for host
175: * 4 for port
176: * 8 for numeric only
177: */
178: char *
179: atalk_print(sa, what)
180: const struct sockaddr *sa;
181: int what;
182: {
183: struct sockaddr_at *sat = (struct sockaddr_at *) sa;
184: static char mybuf[50];
185: int numeric = (what & 0x08);
186:
187: mybuf[0] = 0;
188: switch (what & 0x13) {
189: case 0:
190: mybuf[0] = 0;
191: break;
192: case 1:
193: (void) snprintf(mybuf, sizeof(mybuf), "%s",
194: at_pr_net(sat, numeric));
195: break;
196: case 2:
197: (void) snprintf(mybuf, sizeof(mybuf), "%s",
198: at_pr_host(sat, numeric));
199: break;
200: case 3:
201: (void) snprintf(mybuf, sizeof(mybuf), "%s.%s",
202: at_pr_net(sat, numeric),
203: at_pr_host(sat, numeric));
204: break;
205: case 0x10:
206: (void) snprintf(mybuf, sizeof(mybuf), "%s", at_pr_range(sat));
207: }
208: if (what & 4) {
209: (void) snprintf(mybuf + strlen(mybuf),
210: sizeof(mybuf) - strlen(mybuf), ".%s",
211: at_pr_port(sat));
212: }
213: return mybuf;
214: }
215:
216: char *
217: atalk_print2(sa, mask, what)
218: const struct sockaddr *sa;
219: const struct sockaddr *mask;
220: int what;
221: {
1.2 ! millert 222: size_t n, l;
1.1 denny 223: static char buf[100];
224: struct sockaddr_at *sat1, *sat2;
225: struct sockaddr_at thesockaddr;
226: struct sockaddr *sa2;
227:
228: sat1 = (struct sockaddr_at *) sa;
229: sat2 = (struct sockaddr_at *) mask;
230: sa2 = (struct sockaddr *) & thesockaddr;
231:
232: thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net &
233: sat2->sat_addr.s_net;
234: n = snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 | (what & 8)));
1.2 ! millert 235: if (n >= sizeof(buf))
! 236: n = sizeof(buf) - 1;
1.1 denny 237: if (sat2->sat_addr.s_net != 0xFFFF) {
238: thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net |
239: ~sat2->sat_addr.s_net;
1.2 ! millert 240: l = snprintf(buf + n, sizeof(buf) - n,
1.1 denny 241: "-%s", atalk_print(sa2, 1 | (what & 8)));
1.2 ! millert 242: if (l >= sizeof(buf) - n)
! 243: l = sizeof(buf) - n - 1;
! 244: n += l;
1.1 denny 245: }
1.2 ! millert 246: if (what & 2) {
! 247: l = snprintf(buf + n, sizeof(buf) - n, ".%s",
1.1 denny 248: atalk_print(sa, what & (~1)));
1.2 ! millert 249: if (l >= sizeof(buf) - n)
! 250: l = sizeof(buf) - n - 1;
! 251: n += l;
! 252: }
1.1 denny 253: return (buf);
254: }
255:
256: void
257: atalkprotopr(off, name)
258: u_long off;
259: char *name;
260: {
261: struct ddpcb cb;
262: register struct ddpcb *prev, *next;
263: struct ddpcb *initial;
264:
265: if (off == 0)
266: return;
267: if (kread(off, (char *) &initial, sizeof(struct ddpcb *)) < 0)
268: return;
269: ddpcb = cb;
270: prev = (struct ddpcb *) off;
271: for (next = initial; next != NULL; prev = next) {
272: u_long ppcb = (u_long) next;
273:
274: if (kread((u_long) next, (char *) &ddpcb, sizeof(ddpcb)) < 0)
275: return;
276: next = ddpcb.ddp_next;
277: #if 0
278: if (!aflag && atalk_nullhost(ddpcb.ddp_lsat)) {
279: continue;
280: }
281: #endif
282: if (kread((u_long) ddpcb.ddp_socket,
283: (char *) &sockb, sizeof(sockb)) < 0)
284: return;
285: if (first) {
286: printf("Active ATALK connections");
287: if (aflag)
288: printf(" (including servers)");
289: putchar('\n');
290: if (Aflag)
291: printf("%-8.8s ", "PCB");
292: printf(Aflag ?
293: "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
294: "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
295: "Proto", "Recv-Q", "Send-Q",
296: "Local Address", "Foreign Address", "(state)");
297: first = 0;
298: }
299: if (Aflag)
300: printf("%8lx ", ppcb);
301: printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
302: sockb.so_snd.sb_cc);
303: printf(Aflag ? " %-18.18s" : " %-22.22s", atalk_print(
304: (struct sockaddr *) & ddpcb.ddp_lsat, 7));
305: printf(Aflag ? " %-18.18s" : " %-22.22s", atalk_print(
306: (struct sockaddr *) & ddpcb.ddp_fsat, 7));
307: putchar('\n');
308: }
309: }
310:
311: #define p(f, m) if (ddpstat.f || sflag <= 1) \
312: printf(m, ddpstat.f, plural(ddpstat.f))
313: #define p2(f1, f2, m) if (ddpstat.f1 || ddpstat.f2 || sflag <= 1) \
314: printf(m, ddpstat.f1, plural(ddpstat.f1), ddpstat.f2, plural(ddpstat.f2))
315: #define p3(f, m) if (ddpstat.f || sflag <= 1) \
316: printf(m, ddpstat.f, plurales(ddpstat.f))
317:
318: /*
319: * Dump DDP statistics structure.
320: */
321: void
322: ddp_stats(off, name)
323: u_long off;
324: char *name;
325: {
326: struct ddpstat ddpstat;
327:
328: if (off == 0)
329: return;
330: if (kread(off, (char *) &ddpstat, sizeof(ddpstat)) < 0)
331: return;
332: printf("%s:\n", name);
333: p(ddps_short, "\t%ld packet%s with short headers\n");
334: p(ddps_long, "\t%ld packet%s with long headers\n");
335: p(ddps_nosum, "\t%ld packet%s with no checksum\n");
336: p(ddps_tooshort, "\t%ld packet%s were too short\n");
337: p(ddps_badsum, "\t%ld packet%s with bad checksum\n");
338: p(ddps_toosmall, "\t%ld packet%s with not enough data\n");
339: p(ddps_forward, "\t%ld packet%s forwarded\n");
340: p(ddps_cantforward, "\t%ld packet%s rcvd for unreachable dest\n");
341: p(ddps_nosockspace, "\t%ld packet%s dropped due to no socket space\n");
342: }