2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
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,
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
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
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>
93 ultoa(unsigned long ul
,char *buffer
)
103 *++p
= (ul
% 10)+'0';
108 while (*buffer
++ = *p
--)
114 ltoa(long l
, char *buffer
)
123 return (len
+ ultoa((unsigned long)l
, buffer
));
127 * Allocate big enough buffer for reply
130 CS_Alloc(struct CSource
*reply
, size_t size
)
132 /* do we have enough space? */
133 if (reply
->CS_Length
< size
) {
135 if ((buffer
= bsd_malloc(size
, M_TEMP
, 0)) == NULL
){
139 * Old buffer will be freed by caller
141 reply
->CS_Buffer
= buffer
;
142 reply
->CS_Length
= size
;
149 * getsockets(): a reply statics for all sockets
153 struct in_addr inp_faddr
; /* u_long, far addr */
155 struct in_addr inp_laddr
; /* u_long, local addr */
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 */
164 getsockets(struct CSource
*args
, UBYTE
**errstrp
, struct CSource
*res
)
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
)
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
)
180 if (count
== 0) { /* return now if nothing to print */
185 /* Allocate memory */
186 mem
= (struct printsocket
*)
187 bsd_malloc(sizeof(struct printsocket
) * (count
), M_TEMP
, 0);
191 *errstrp
= ERR_MEMORY
;
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 */
198 if (!CS_Alloc(res
, STATLEN
* count
+ 1)) {
199 /* Allocation failed, free printsocket memory */
201 bsd_free(mem
, M_TEMP
);
202 *errstrp
= ERR_MEMORY
;
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
;
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);
254 bsd_free(mem
, M_TEMP
);
260 * Get ICMP history profiles
262 #include <netinet/icmp_var.h>
263 #include <netinet/ip_icmp.h>
265 extern struct icmpstat icmpstat
;
268 read_icmphist(struct CSource
*args
, UBYTE
**errstrp
, struct CSource
*res
)
271 UBYTE
*p
= res
->CS_Buffer
;
273 for(i
= 0;i
<= ICMP_MAXTYPE
; i
++){
274 p
+= ultoa(icmpstat
.icps_outhist
[i
], p
);
278 for(i
= 0;i
<= ICMP_MAXTYPE
; i
++){
279 p
+= ultoa(icmpstat
.icps_inhist
[i
], p
);
284 res
->CS_CurChr
= p
- res
->CS_Buffer
;
291 #include <net/route.h>
296 /* Address families supported */
297 extern STRPTR KW_Protocols
;
299 /* What is stored in the route entry */
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
309 struct sockaddr pr_dest
;
310 struct sockaddr pr_via
;
312 struct ifnet
*pr_ifp
;
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);
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
;
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
;
342 if ((af
= FindArg(KW_Protocols
, Buffer
)) < 0) {
344 csprintf(res
, ERR_ILLEGAL_VAR
, "getroutes", Buffer
);
345 *errstrp
= res
->CS_Buffer
;
349 DB(log(LOG_DEBUG
, "getroutes: getting routes for protocol %s (%ld)",
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
);
360 *errstrp
= (UBYTE
*)"Route tree overflow.\n";
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);
375 *errstrp
= ERR_MEMORY
;
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
);
384 if (pr
> mem
+ routes
) {
385 const UBYTE
*msg
= "cstat_rtree(): found more entries than counted!\n";
387 bsd_free(mem
, M_TEMP
);
389 *errstrp
= (UBYTE
*)msg
;
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
;
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
);
419 csprintf(res
, "%s%ld ", pr
->pr_ifp
->if_name
, pr
->pr_ifp
->if_unit
);
421 csprintf(res
, "none ");
425 /* free printsocket structures */
426 bsd_free(mem
, M_TEMP
);
432 * cstat_rtree(): get a route tree to a table
435 cstat_rtree(struct radix_node
*rn
, struct printroute
*pr
, int do_rtent
)
438 short stack_pointer
= 0;
439 struct radix_node
*stack
[MAX_ROUTE_TREE_DEPTH
];
443 if ((rn
->rn_flags
& RNF_ROOT
) == 0) {
446 cstat_rtentry((struct rtentry
*)rn
, pr
);
448 cstat_maskentry(rn
, pr
);
453 if (rn
= rn
->rn_dupedkey
)
457 if (stack_pointer
>= MAX_ROUTE_TREE_DEPTH
- 1)
459 stack
[stack_pointer
++] = rn
->rn_r
;
461 /* tail recursion removal */
467 /* recursion removal */
468 if (stack_pointer
-- > 0) {
469 rn
= stack
[stack_pointer
];
473 DB(log(LOG_DEBUG
, "rtree: found %ld routes", routes
));
478 * Copy rtentry into printroute
479 * assumes that rtentry and pr are valid
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
));
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
)
496 pr
->pr_what
= NORMAL
;
500 * Copy netmask into printroute
501 * assumes that rn and pr are valid
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
));
518 * Definitions for showing gateway flags.
525 { RTF_GATEWAY
, 'G' },
527 { RTF_DYNAMIC
, 'D' },
528 { RTF_MODIFIED
, 'M' },
529 { RTF_CLONING
, 'C' },
530 { RTF_XRESOLVE
, 'X' },
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
++)
545 if (name
[0] != '\0') {
546 csprintf(res
, format
, name
);
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 */
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
));
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
;
577 sethostname(Buffer
, sizeof(Buffer
));