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