tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / kern / amiga_cstat.c
blob89f5f398090282265fce5bc8d929e561fd8b0075
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
24 * Copyright (c) 1983, 1988 Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
56 #include <conf.h>
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/synch.h>
63 #include <sys/malloc.h>
64 #include <sys/syslog.h>
66 #include <kern/amiga_includes.h>
67 #include <kern/amiga_rexx.h>
68 #include <kern/amiga_config.h>
70 #include <dos/rdargs.h>
72 #include <proto/dos.h>
74 #include <net/route.h>
75 #include <netinet/in_systm.h>
76 #include <netinet/in.h>
77 #include <netinet/ip.h>
78 #include <netinet/in_pcb.h>
79 #include <netinet/ip_var.h>
80 #include <netinet/ip_icmp.h>
81 #include <netinet/icmp_var.h>
82 #include <netinet/tcp.h>
83 #include <netinet/tcp_timer.h>
84 #include <netinet/tcp_var.h>
85 #include <netinet/udp.h>
86 #include <netinet/udp_var.h>
88 #include <api/apicalls.h>
90 long count = 0;
92 int
93 ultoa(unsigned long ul,char *buffer)
95 static char buf[10];
96 char *p;
97 int len;
99 p = buf;
100 *p='\0';
102 do {
103 *++p = (ul % 10)+'0';
104 } while (ul /= 10);
106 len = p - buf;
108 while (*buffer++ = *p--)
110 return(len);
114 ltoa(long l, char *buffer)
116 int len=0;
118 if(l<0){
119 *buffer++='-';
120 l=-l;
121 len++;
123 return (len + ultoa((unsigned long)l, buffer));
127 * Allocate big enough buffer for reply
129 LONG
130 CS_Alloc(struct CSource *reply, size_t size)
132 /* do we have enough space? */
133 if (reply->CS_Length < size) {
134 char *buffer;
135 if ((buffer = bsd_malloc(size, M_TEMP, 0)) == NULL){
136 return 0;
139 * Old buffer will be freed by caller
141 reply->CS_Buffer = buffer;
142 reply->CS_Length = size;
145 return 1;
149 * getsockets(): a reply statics for all sockets
152 struct printsocket {
153 struct in_addr inp_faddr; /* u_long, far addr */
154 u_short inp_fport;
155 struct in_addr inp_laddr; /* u_long, local addr */
156 u_short inp_lport;
157 short so_type; /* SOCK_STREAM, _DGRAM... */
158 u_short so_rcv_sb_cc; /* Recv queue size */
159 u_short so_snd_sb_cc; /* Send queue */
160 short inp_ppcb_t_state; /* State of TCP connection */
163 LONG
164 getsockets(struct CSource *args, UBYTE **errstrp, struct CSource *res)
166 int i, count = 0;
167 struct inpcb *pcb;
169 struct printsocket *pps, *mem;
170 spl_t s = splnet(); /* Critical section starts here */
172 /* Count number of connections */
173 //for(pcb = udb.inp_next; pcb != &udb ; pcb = pcb->inp_next)
174 for(pcb = udb.lh_first; pcb != NULL; pcb = pcb->inp_list.le_next)
175 ++count;
176 //for(pcb = tcb.inp_next; pcb != &tcb ; pcb = pcb->inp_next)
177 for(pcb = tcb.lh_first; pcb != NULL; pcb = pcb->inp_list.le_next)
178 ++count;
180 if (count == 0) { /* return now if nothing to print */
181 splx(s);
182 return RETURN_OK;
185 /* Allocate memory */
186 mem = (struct printsocket *)
187 bsd_malloc(sizeof(struct printsocket) * (count), M_TEMP, 0);
189 if (mem == NULL) {
190 splx(s);
191 *errstrp = ERR_MEMORY;
192 return RETURN_FAIL;
195 /* Proto recv-q send-q laddr lport faddr fport state */
196 /* 1 1 4 1 4 1 8 1 4 1 8 1 4 1 1 1 = 42 chars */
197 #define STATLEN 42
198 if (!CS_Alloc(res, STATLEN * count + 1)) {
199 /* Allocation failed, free printsocket memory */
200 splx(s);
201 bsd_free(mem, M_TEMP);
202 *errstrp = ERR_MEMORY;
203 return RETURN_FAIL;
206 /* Copy information, TCP first.. */
207 //for(pcb = tcb.inp_next, pps = mem; pcb != &tcb; pcb = pcb->inp_next, ++pps){
208 for(pcb = tcb.lh_first, pps = mem; pcb != NULL; pcb = pcb->inp_list.le_next){
209 pps->inp_faddr = pcb->inp_faddr;
210 pps->inp_fport = pcb->inp_fport;
211 pps->inp_laddr = pcb->inp_laddr;
212 pps->inp_lport = pcb->inp_lport;
213 pps->so_type = pcb->inp_socket->so_type;
214 pps->so_rcv_sb_cc = pcb->inp_socket->so_rcv.sb_cc;
215 pps->so_snd_sb_cc = pcb->inp_socket->so_snd.sb_cc;
216 pps->inp_ppcb_t_state = ((struct tcpcb *)(pcb->inp_ppcb))->t_state;
218 /* ...then UDP */
219 //for(pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next, ++pps){
220 for(pcb = udb.lh_first; pcb != NULL; pcb = pcb->inp_list.le_next){
221 pps->inp_faddr = pcb->inp_faddr;
222 pps->inp_fport = pcb->inp_fport;
223 pps->inp_laddr = pcb->inp_laddr;
224 pps->inp_lport = pcb->inp_lport;
225 pps->so_type = pcb->inp_socket->so_type;
226 pps->so_rcv_sb_cc = pcb->inp_socket->so_rcv.sb_cc;
227 pps->so_snd_sb_cc = pcb->inp_socket->so_snd.sb_cc;
228 pps->inp_ppcb_t_state = 0; /* NO state for UDP */
231 splx(s); /* Critical section completed now */
234 * Print all socket entries
236 for(i = 0; i < count; i++)
237 csprintf(res, "%lc %04lx %04lx %08lx %04lx %08lx %04lx %1lx%s",
238 mem[i].so_type == SOCK_STREAM ? 't': 'u',
239 mem[i].so_rcv_sb_cc, mem[i].so_snd_sb_cc,
240 mem[i].inp_laddr.s_addr, mem[i].inp_lport,
241 mem[i].inp_faddr.s_addr, mem[i].inp_fport,
242 mem[i].inp_ppcb_t_state,
243 (i < count - 1) ? " " : "");
245 #if DIAGNOSTIC /* check for overrun */
246 if (res->CS_CurChr >= res->CS_Length)
247 log(LOG_ERR, "getsockets(): buffer overwritten by %ld bytes\n",
248 res->CS_CurChr - res->CS_Length + 1);
249 #endif
252 * free mem
254 bsd_free(mem, M_TEMP);
256 return RETURN_OK;
260 * Get ICMP history profiles
262 #include <netinet/icmp_var.h>
263 #include <netinet/ip_icmp.h>
265 extern struct icmpstat icmpstat;
267 LONG
268 read_icmphist(struct CSource *args, UBYTE **errstrp, struct CSource *res)
270 int i;
271 UBYTE *p = res->CS_Buffer;
273 for(i = 0;i <= ICMP_MAXTYPE; i++){
274 p += ultoa(icmpstat.icps_outhist[i], p);
275 *p++=' ';
278 for(i = 0;i <= ICMP_MAXTYPE; i++){
279 p += ultoa(icmpstat.icps_inhist[i], p);
280 *p++ = ' ';
282 *--p = '\0';
284 res->CS_CurChr = p - res->CS_Buffer;
285 return RETURN_OK;
289 * Get routing tables
291 #include <net/route.h>
292 #include <net/if.h>
294 #define DB(x) ;
296 /* Address families supported */
297 extern STRPTR KW_Protocols;
299 /* What is stored in the route entry */
300 #define NORMAL 0
301 #define MASK 1
302 #define DUPED 2
304 /* Our recursion depth in route tree. 32 is # of bits in IP address */
305 /* Other protocols may require deeper stack */
306 #define MAX_ROUTE_TREE_DEPTH 32
308 struct printroute {
309 struct sockaddr pr_dest;
310 struct sockaddr pr_via;
311 u_long pr_use;
312 struct ifnet *pr_ifp;
313 short pr_refcnt;
314 u_short pr_flags;
315 u_short pr_what;
318 static void cstat_rtentry(struct rtentry *rt, struct printroute *pr);
319 static void cstat_maskentry(struct radix_node *rn, struct printroute *pr);
320 static int cstat_rtree(struct radix_node *rn, struct printroute *pr, int);
321 static void cstat_rtflags(struct CSource *, const char *, register int);
323 LONG
324 getroutes(struct CSource *args, UBYTE **errstrp, struct CSource *res)
326 UBYTE Buffer[KEYWORDLEN];
327 int af, newroutes, routes = 0;
328 struct radix_node_head *rnh;
329 struct printroute *mem, *pr;
330 spl_t s;
333 * Parse address family
335 * Match the against the template. The af is the index of
336 * the matching keyword, if one is found.
338 if (ReadItem(Buffer, sizeof(Buffer), args) <= 0) {
339 *errstrp = ERR_SYNTAX;
340 return RETURN_ERROR;
342 if ((af = FindArg(KW_Protocols, Buffer)) < 0) {
343 res->CS_CurChr = 0;
344 csprintf(res, ERR_ILLEGAL_VAR, "getroutes", Buffer);
345 *errstrp = res->CS_Buffer;
346 return RETURN_WARN;
349 DB(log(LOG_DEBUG, "getroutes: getting routes for protocol %s (%ld)",
350 Buffer, af));
352 s = splnet(); /* Critical section */
354 /* Count entries in tables */
355 for (rnh = radix_node_head; rnh ; rnh = rnh->rnh_next) {
356 if (af == AF_UNSPEC || af == rnh->rnh_af) {
357 newroutes = cstat_rtree(rnh->rnh_treetop, NULL, rnh->rnh_af != AF_UNSPEC);
358 if (newroutes < 0) {
359 splx(s);
360 *errstrp = (UBYTE *)"Route tree overflow.\n";
361 return RETURN_FAIL;
363 routes += newroutes;
367 DB(log(LOG_DEBUG, "getroutes: found %ld routes", routes));
369 /* Allocate memory for entries */
370 pr = mem = (struct printroute *)
371 bsd_malloc(sizeof(struct printroute) * (routes), M_TEMP, 0);
373 if (mem == NULL) {
374 splx(s);
375 *errstrp = ERR_MEMORY;
376 return RETURN_FAIL;
379 /* Fill in printroute table */
380 for (rnh = radix_node_head; rnh ; rnh = rnh->rnh_next) {
381 if (af == AF_UNSPEC || af == rnh->rnh_af) {
382 pr += cstat_rtree(rnh->rnh_treetop, pr, rnh->rnh_af != AF_UNSPEC);
383 #if DIAGNOSTIC
384 if (pr > mem + routes) {
385 const UBYTE *msg = "cstat_rtree(): found more entries than counted!\n";
386 splx(s);
387 bsd_free(mem, M_TEMP);
388 log(LOG_ERR, msg);
389 *errstrp = (UBYTE *)msg;
390 return RETURN_FAIL;
392 #endif
395 splx(s); /* End of critical section */
397 /* Reply line has format
398 * protocol route gateway flags refcount used device/unit + separation
399 * 2 + 8 + 8 + 4 + 4 + 8 + 32 + 10 + 10 = 90 chars
401 if (!CS_Alloc(res, 90 * routes)) {
402 /* Allocation failed, free printroute memory */
403 bsd_free(mem, M_TEMP);
404 *errstrp = ERR_MEMORY;
405 return RETURN_FAIL;
408 /* cstat_rtree_print */
409 for (pr = mem; routes-- > 0 ; pr++) {
410 struct sockaddr_in *prdst_saddr = (struct sockaddr_in *)&pr->pr_dest;
411 struct sockaddr_in *prvia_saddr = (struct sockaddr_in *)&pr->pr_via;
412 csprintf(res, "%02lx %08lx %08lx ",
413 pr->pr_dest.sa_family,
414 prdst_saddr->sin_addr.s_addr,
415 prvia_saddr->sin_addr.s_addr);
416 cstat_rtflags(res, "%-8.8s ", pr->pr_flags);
417 csprintf(res, "%04lx %08lx ", pr->pr_refcnt, pr->pr_use);
418 if (pr->pr_ifp) {
419 csprintf(res, "%s%ld ", pr->pr_ifp->if_name, pr->pr_ifp->if_unit);
420 } else {
421 csprintf(res, "none ");
425 /* free printsocket structures */
426 bsd_free(mem, M_TEMP);
428 return RETURN_OK;
432 * cstat_rtree(): get a route tree to a table
434 static int
435 cstat_rtree(struct radix_node *rn, struct printroute *pr, int do_rtent)
437 short routes = 0;
438 short stack_pointer = 0;
439 struct radix_node *stack[MAX_ROUTE_TREE_DEPTH];
441 again:
442 if (rn->rn_b < 0) {
443 if ((rn->rn_flags & RNF_ROOT) == 0) {
444 if (pr) {
445 if (do_rtent)
446 cstat_rtentry((struct rtentry*)rn, pr);
447 else
448 cstat_maskentry(rn, pr);
449 pr++;
451 routes++;
453 if (rn = rn->rn_dupedkey)
454 goto again;
455 } else {
456 if (rn->rn_r) {
457 if (stack_pointer >= MAX_ROUTE_TREE_DEPTH - 1)
458 return -1;
459 stack[stack_pointer++] = rn->rn_r;
461 /* tail recursion removal */
462 if (rn = rn->rn_l) {
463 goto again;
467 /* recursion removal */
468 if (stack_pointer-- > 0) {
469 rn = stack[stack_pointer];
470 goto again;
473 DB(log(LOG_DEBUG, "rtree: found %ld routes", routes));
474 return routes;
478 * Copy rtentry into printroute
479 * assumes that rtentry and pr are valid
481 static void
482 cstat_rtentry(struct rtentry *rt, struct printroute *pr)
484 /* These should allow variable sized sockaddrs */
485 bcopy(rt_key(rt), &pr->pr_dest, sizeof(pr->pr_dest));
486 bcopy(rt->rt_gateway, &pr->pr_via, sizeof(pr->pr_via));
488 /* */
489 pr->pr_use = rt->rt_use;
490 pr->pr_refcnt = rt->rt_refcnt;
491 pr->pr_ifp = rt->rt_ifp;
492 pr->pr_flags = rt->rt_flags;
493 if (rt->rt_nodes->rn_dupedkey)
494 pr->pr_what = DUPED;
495 else
496 pr->pr_what = NORMAL;
500 * Copy netmask into printroute
501 * assumes that rn and pr are valid
503 static void
504 cstat_maskentry(struct radix_node *rn, struct printroute *pr)
506 /* These should allow variable sized sockaddrs */
507 bcopy((struct sockaddr *)rn->rn_key, &pr->pr_dest, sizeof(pr->pr_dest));
508 bzero(&pr->pr_via, sizeof(pr->pr_via));
510 pr->pr_use = 0;
511 pr->pr_refcnt = 0;
512 pr->pr_ifp = NULL;
513 pr->pr_flags = 0;
514 pr->pr_what = MASK;
518 * Definitions for showing gateway flags.
520 struct bits {
521 short b_mask;
522 char b_val;
523 } bits[] = {
524 { RTF_UP, 'U' },
525 { RTF_GATEWAY, 'G' },
526 { RTF_HOST, 'H' },
527 { RTF_DYNAMIC, 'D' },
528 { RTF_MODIFIED, 'M' },
529 { RTF_CLONING, 'C' },
530 { RTF_XRESOLVE, 'X' },
531 { RTF_LLINFO, 'L' },
532 { RTF_REJECT, 'R' },
533 { 0 }
536 static void
537 cstat_rtflags(struct CSource *res, const char *format, register int f)
539 char name[33], *flags;
540 register struct bits *p = bits;
541 for (flags = name; p->b_mask; p++)
542 if (p->b_mask & f)
543 *flags++ = p->b_val;
544 *flags = '\0';
545 if (name[0] != '\0') {
546 csprintf(res, format, name);
547 } else {
548 /* Empty string may confuse parsers */
549 csprintf(res, format, "\"\"");
553 extern char *host_name;
554 extern size_t host_namelen;
555 extern int sethostname(const char * name, size_t namelen);
556 extern struct Library *SocketBase; /* base opened by NETTRACE */
558 LONG
559 rexx_gethostname(struct CSource *args, UBYTE **errstrp, struct CSource *res)
561 __gethostname(CURRENT(res), SPACE(res), (struct SocketBase *)SocketBase);
562 res->CS_CurChr += strlen(CURRENT(res));
564 return RETURN_OK;
567 LONG
568 rexx_sethostname(struct CSource *args, UBYTE **errstrp, struct CSource *res)
570 char Buffer[MAXHOSTNAMELEN+1];
572 if (ReadItem(Buffer, sizeof(Buffer), args) <= 0) {
573 *errstrp = ERR_SYNTAX;
574 return RETURN_ERROR;
577 sethostname(Buffer, sizeof(Buffer));
578 return RETURN_OK;