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