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