1 /* $NetBSD: atalk.c,v 1.13 2008/04/24 04:09:50 thorpej Exp $ */
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "from @(#)atalk.c 1.1 (Whistle) 6/6/96";
37 __RCSID("$NetBSD: atalk.c,v 1.13 2008/04/24 04:09:50 thorpej Exp $");
41 #include <sys/param.h>
42 #include <sys/queue.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
46 #include <sys/protosw.h>
47 #include <sys/sysctl.h>
49 #include <net/route.h>
52 #include <netinet/tcp_fsm.h>
54 #include <netatalk/at.h>
55 #include <netatalk/ddp_var.h>
71 * Print a summary of connections related to a Network Systems
72 * protocol. For XXX, also give state of connection.
73 * Listening processes (aflag) are suppressed unless the
74 * -a (all) flag is specified.
78 at_pr_net(const struct sockaddr_at
*sat
, int numeric
)
80 static char mybuf
[50];
83 switch (sat
->sat_addr
.s_net
) {
90 (void)snprintf(mybuf
, sizeof(mybuf
), "%hu", ntohs(sat
->sat_addr
.s_net
));
95 at_pr_host(const struct sockaddr_at
*sat
, int numeric
)
97 static char mybuf
[50];
100 switch (sat
->sat_addr
.s_node
) {
107 (void)snprintf(mybuf
, sizeof(mybuf
), "%d",
108 (unsigned int)sat
->sat_addr
.s_node
);
113 at_pr_port(const struct sockaddr_at
*sat
)
115 static char mybuf
[50];
117 switch (sat
->sat_port
) {
123 (void)snprintf(mybuf
, sizeof(mybuf
), "%d",
124 (unsigned int)sat
->sat_port
);
130 at_pr_range(const struct sockaddr_at
*sat
)
132 static char mybuf
[50];
134 if (sat
->sat_range
.r_netrange
.nr_firstnet
135 != sat
->sat_range
.r_netrange
.nr_lastnet
) {
136 (void)snprintf(mybuf
, sizeof(mybuf
), "%d-%d",
137 ntohs(sat
->sat_range
.r_netrange
.nr_firstnet
),
138 ntohs(sat
->sat_range
.r_netrange
.nr_lastnet
));
140 (void)snprintf(mybuf
, sizeof(mybuf
), "%d",
141 ntohs(sat
->sat_range
.r_netrange
.nr_firstnet
));
147 /* what == 0 for addr only == 3
154 atalk_print(const struct sockaddr
*sa
, int what
)
156 const struct sockaddr_at
*sat
= (const struct sockaddr_at
*) sa
;
157 static char mybuf
[50];
158 int numeric
= (what
& 0x08);
161 switch (what
& 0x13) {
166 (void)snprintf(mybuf
, sizeof(mybuf
), "%s",
167 at_pr_net(sat
, numeric
));
170 (void)snprintf(mybuf
, sizeof(mybuf
), "%s",
171 at_pr_host(sat
, numeric
));
174 (void)snprintf(mybuf
, sizeof(mybuf
), "%s.%s",
175 at_pr_net(sat
, numeric
),
176 at_pr_host(sat
, numeric
));
179 (void)snprintf(mybuf
, sizeof(mybuf
), "%s", at_pr_range(sat
));
182 (void)snprintf(mybuf
+ strlen(mybuf
),
183 sizeof(mybuf
) - strlen(mybuf
), ".%s", at_pr_port(sat
));
189 atalk_print2(const struct sockaddr
*sa
, const struct sockaddr
*mask
, int what
)
192 static char buf
[100];
193 const struct sockaddr_at
*sat1
, *sat2
;
194 struct sockaddr_at thesockaddr
;
195 struct sockaddr
*sa2
;
197 sat1
= (const struct sockaddr_at
*) sa
;
198 sat2
= (const struct sockaddr_at
*) mask
;
199 sa2
= (struct sockaddr
*) & thesockaddr
;
201 thesockaddr
.sat_addr
.s_net
= sat1
->sat_addr
.s_net
&
202 sat2
->sat_addr
.s_net
;
203 n
= snprintf(buf
, sizeof(buf
), "%s", atalk_print(sa2
, 1 | (what
& 8)));
204 if (n
>= (int)sizeof(buf
))
207 n
= 0; /* What else can be done ? */
208 if (sat2
->sat_addr
.s_net
!= 0xFFFF) {
209 thesockaddr
.sat_addr
.s_net
= sat1
->sat_addr
.s_net
|
210 ~sat2
->sat_addr
.s_net
;
211 l
= snprintf(buf
+ n
, sizeof(buf
) - n
,
212 "-%s", atalk_print(sa2
, 1 | (what
& 8)));
213 if (l
>= (int)(sizeof(buf
) - n
))
214 l
= sizeof(buf
) - n
- 1;
219 l
= snprintf(buf
+ n
, sizeof(buf
) - n
, ".%s",
220 atalk_print(sa
, what
& (~1)));
221 if (l
>= (int)(sizeof(buf
) - n
))
222 l
= sizeof(buf
) - n
- 1;
230 atalkprotopr(u_long off
, const char *name
)
233 struct ddpcb
*prev
, *next
;
234 struct ddpcb
*initial
;
238 if (kread(off
, (char *)&initial
, sizeof(struct ddpcb
*)) < 0)
241 prev
= (struct ddpcb
*)off
;
242 for (next
= initial
; next
!= NULL
; prev
= next
) {
243 u_long ppcb
= (u_long
)next
;
245 if (kread((u_long
)next
, (char *)&ddpcb
, sizeof(ddpcb
)) < 0)
247 next
= ddpcb
.ddp_next
;
249 if (!aflag
&& atalk_nullhost(ddpcb
.ddp_lsat
)) {
253 if (kread((u_long
)ddpcb
.ddp_socket
,
254 (char *)&sockb
, sizeof(sockb
)) < 0)
257 printf("Active ATALK connections");
259 printf(" (including servers)");
263 printf("%-8.8s ", "PCB");
265 printf("%-5.5s %-6.6s %-6.6s %*.*s %*.*s %s\n",
266 "Proto", "Recv-Q", "Send-Q",
267 -width
, width
, "Local Address",
268 -width
, width
, "Foreign Address", "(state)");
272 printf("%8lx ", ppcb
);
273 printf("%-5.5s %6ld %6ld ", name
, sockb
.so_rcv
.sb_cc
,
275 printf(" %*.*s", -width
, width
,
276 atalk_print((struct sockaddr
*)&ddpcb
.ddp_lsat
, 7));
277 printf(" %*.*s", -width
, width
,
278 atalk_print((struct sockaddr
*)&ddpcb
.ddp_fsat
, 7));
283 ((sflag==1 || (x)) ? printf("\t%llu %s%s%s\n",(unsigned long long)x,y,plural(x),z) : 0)
286 * Dump DDP statistics structure.
289 ddp_stats(u_long off
, const char *name
)
291 uint64_t ddpstat
[DDP_NSTATS
];
294 size_t size
= sizeof(ddpstat
);
296 if (sysctlbyname("net.atalk.ddp.stats", ddpstat
, &size
,
300 warnx("%s stats not available via KVM.", name
);
304 printf("%s:\n", name
);
306 ANY(ddpstat
[DDP_STAT_SHORT
], "packet", " with short headers ");
307 ANY(ddpstat
[DDP_STAT_LONG
], "packet", " with long headers ");
308 ANY(ddpstat
[DDP_STAT_NOSUM
], "packet", " with no checksum ");
309 ANY(ddpstat
[DDP_STAT_TOOSHORT
], "packet", " too short ");
310 ANY(ddpstat
[DDP_STAT_BADSUM
], "packet", " with bad checksum ");
311 ANY(ddpstat
[DDP_STAT_TOOSMALL
], "packet", " with not enough data ");
312 ANY(ddpstat
[DDP_STAT_FORWARD
], "packet", " forwarded ");
313 ANY(ddpstat
[DDP_STAT_ENCAP
], "packet", " encapsulated ");
314 ANY(ddpstat
[DDP_STAT_CANTFORWARD
], "packet", " rcvd for unreachable dest ");
315 ANY(ddpstat
[DDP_STAT_NOSOCKSPACE
], "packet", " dropped due to no socket space ");