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