summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking/netinet/udp_usrreq.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2003-01-03 18:09:57 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2003-01-03 18:09:57 +0000
commit36799d4063c2e6e74d5d5a520aabac199913227a (patch)
tree676ad75ffd851ab3bd5c01beb39c0c0b0c348490 /cpukit/libnetworking/netinet/udp_usrreq.c
parent2003-01-03 Victor V. Vengerov <vvv@oktet.ru> (diff)
downloadrtems-36799d4063c2e6e74d5d5a520aabac199913227a.tar.bz2
2002-11-26 Chris Johns <cjohns@cybertec.com.au>
* Makefile.am: Added sys/linker_set.h * kern/Makefile.am: Added kern_mib.c and kern_sysctl.c. * kern/uipc_socket.c: OID changed from KERN_SOMAXCONN to KIPC_SOMAXCONN. * kern/uipc_socket2.c: OID changed from KERN_MAXSOCKBUF to KIPC_MAXSOCKBUF. * net/if_ethersubr.c: FreeBSD 2.2.2 does not have a _net_link node while 5.0 does. * net/if_ppp.c: Removed the TEXT_SET define as these macros are now implemented. * net/rtsock.c: Enable sysctl support plus fix the bug with the lastest FreeBSD sysctl header file. * netinet/icmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_icmp node while 5.0 does. * netinet/if_ether.c: FreeBSD 2.2.2 does not have a _net_link_ether node while 5.0 does. * netinet/igmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_igmp node while 5.0 does. * netinet/in_pcb.c: Fixed the arguments to the sysctl call. Add inp_gencnt and ipi_count. These are used when listing connections. * netinet/in_pcb.h: Added counters to aid the listing of connections. * netinet/in_var.h: Provide the _net_inet_ip and _net_inet_raw nodes. * netinet/ip_fw.c: Disable the firewall sysctl calls. * netinet/tcp_subr.c: Merge tcp_pcblist from the lastest FreeBSD source. * netinet/tcp_var.h: Add structures needed by net-snmp to list connections. * netinet/udp_usrreq.c: Merged udp_pcblist from the lastest FreeBSD source. * netinet/udp_var.h: Added the sysctl id UDPCTL_PCBLIST. Used by net-snmp. * rtems_glue.c: Call sysctl_register_all when initialising the network stack to register all the sysctl calls. These are in the special sections and required an updated linker script. * rtems/rtems_syscall.c: Add the sysctl call. * sys/kernel.h: Use the lastest FreeBSD method of handling sysctl structures. This now held in the sys/linker_set.h file. * sys/queue.h: This is from the lastest FreeBSD code with the circular code merged back in as it is not used in the lastest FreeBSD kernel. * sys/sysctl.h: The lastest sysctl. This was needed to use with the new linker set method. The FreeBSD 2.2.2 version has asm hacks. The lastest version of the FreeBSD does not have these hacks. It uses gcc attribute directives.
Diffstat (limited to 'cpukit/libnetworking/netinet/udp_usrreq.c')
-rw-r--r--cpukit/libnetworking/netinet/udp_usrreq.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/cpukit/libnetworking/netinet/udp_usrreq.c b/cpukit/libnetworking/netinet/udp_usrreq.c
index 16c5fce2df..8e28bddc25 100644
--- a/cpukit/libnetworking/netinet/udp_usrreq.c
+++ b/cpukit/libnetworking/netinet/udp_usrreq.c
@@ -455,6 +455,124 @@ release:
return (error);
}
+#ifdef __rtems__
+#define INP_INFO_RLOCK
+#define INP_INFO_RUNLOCK
+#define INP_LOCK
+#define INP_UNLOCK
+#endif
+
+static int
+udp_pcblist(SYSCTL_HANDLER_ARGS)
+{
+ int error, i, n, s;
+ struct inpcb *inp, **inp_list;
+ inp_gen_t gencnt;
+ struct xinpgen xig;
+
+ /*
+ * The process of preparing the TCB list is too time-consuming and
+ * resource-intensive to repeat twice on every request.
+ */
+ if (req->oldptr == 0) {
+ n = udbinfo.ipi_count;
+ req->oldidx = 2 * (sizeof xig)
+ + (n + n/8) * sizeof(struct xinpcb);
+ return 0;
+ }
+
+ if (req->newptr != 0)
+ return EPERM;
+
+ /*
+ * OK, now we're committed to doing something.
+ */
+ s = splnet();
+ gencnt = udbinfo.ipi_gencnt;
+ n = udbinfo.ipi_count;
+ splx(s);
+
+ sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ + n * sizeof(struct xinpcb));
+
+ xig.xig_len = sizeof xig;
+ xig.xig_count = n;
+ xig.xig_gen = gencnt;
+#if 0
+ xig.xig_sogen = so_gencnt;
+#endif
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ if (error)
+ return error;
+
+ /* ccj add the exit if count is 0 */
+ if (!n)
+ return error;
+
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
+ if (inp_list == 0)
+ return ENOMEM;
+
+ s = splnet();
+ INP_INFO_RLOCK(&udbinfo);
+ for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
+ inp = LIST_NEXT(inp, inp_list)) {
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt)
+#if 0
+ &&
+ cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
+#endif
+ inp_list[i++] = inp;
+ INP_UNLOCK(inp);
+ }
+ INP_INFO_RUNLOCK(&udbinfo);
+ splx(s);
+ n = i;
+
+ error = 0;
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt) {
+ struct xinpcb xi;
+ xi.xi_len = sizeof xi;
+ /* XXX should avoid extra copy */
+ bcopy(inp, &xi.xi_inp, sizeof *inp);
+#if 0
+ if (inp->inp_socket)
+ sotoxsocket(inp->inp_socket, &xi.xi_socket);
+#endif
+ error = SYSCTL_OUT(req, &xi, sizeof xi);
+ }
+ INP_UNLOCK(inp);
+ }
+ if (!error) {
+ /*
+ * Give the user an updated idea of our state.
+ * If the generation differs from what we told
+ * her before, she knows that something happened
+ * while we were processing this request, and it
+ * might be necessary to retry.
+ */
+ s = splnet();
+ INP_INFO_RLOCK(&udbinfo);
+ xig.xig_gen = udbinfo.ipi_gencnt;
+#if 0
+ xig.xig_sogen = so_gencnt;
+#endif
+ xig.xig_count = udbinfo.ipi_count;
+ INP_INFO_RUNLOCK(&udbinfo);
+ splx(s);
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ }
+ free(inp_list, M_TEMP);
+ return error;
+}
+
+SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
+ udp_pcblist, "S,xinpcb", "List of active UDP sockets");
+
static u_long udp_sendspace = 9216; /* really max datagram size */
/* 40 1K datagrams */
SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,