]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/netstat/atalk.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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  * 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
32 static 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
59 struct  ddpcb ddpcb;
60 struct  socket sockb;
61
62 static  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
71 static const char *
72 at_pr_net(struct sockaddr_at *sat, int numeric)
73 {
74 static  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
88 static const char *
89 at_pr_host(struct sockaddr_at *sat, int numeric)
90 {
91 static  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
105 static const char *
106 at_pr_port(struct sockaddr_at *sat)
107 {
108 static  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
133 static char *
134 at_pr_range(struct sockaddr_at *sat)
135 {
136 static  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 */
156 char *
157 atalk_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
188 char *
189 atalk_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
215 void
216 atalkprotopr(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  */
265 void
266 ddp_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 }