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