etc/services - sync with NetBSD-8
[minix.git] / minix / net / uds / stat.c
blob2759f631839670deb8e2b89cd273d160fb099ad7
1 /* UNIX Domain Sockets - stat.c - network status */
3 #include "uds.h"
4 #include <sys/socketvar.h>
5 #include <sys/unpcb.h>
7 /*
8 * Fill the given 'ki' structure with information about the socket 'uds'.
9 */
10 static void
11 uds_get_info(struct kinfo_pcb * ki, const struct udssock * uds)
13 struct udssock *peer;
14 socklen_t len;
15 int type;
17 type = uds_get_type(uds);
18 peer = uds_get_peer(uds);
20 ki->ki_pcbaddr = (uint64_t)(uintptr_t)uds;
21 ki->ki_ppcbaddr = (uint64_t)(uintptr_t)uds;
22 ki->ki_sockaddr = (uint64_t)(uintptr_t)&uds->uds_sock;
23 ki->ki_family = AF_UNIX;
24 ki->ki_type = type;
25 ki->ki_protocol = UDSPROTO_UDS;
26 ki->ki_pflags = 0;
27 if (uds->uds_flags & UDSF_CONNWAIT)
28 ki->ki_pflags |= UNP_CONNWAIT;
29 if (uds->uds_flags & UDSF_PASSCRED)
30 ki->ki_pflags |= UNP_WANTCRED;
31 if (type != SOCK_DGRAM && uds->uds_cred.unp_pid != -1) {
32 if (uds_is_listening(uds))
33 ki->ki_pflags |= UNP_EIDSBIND;
34 else if (uds_is_connecting(uds) || uds_is_connected(uds))
35 ki->ki_pflags |= UNP_EIDSVALID;
37 /* Not sure about NetBSD connection states. First attempt here. */
38 if (uds_is_connecting(uds))
39 ki->ki_sostate = SS_ISCONNECTING;
40 else if (uds_is_connected(uds))
41 ki->ki_sostate = SS_ISCONNECTED;
42 else if (uds_is_disconnected(uds))
43 ki->ki_sostate = SS_ISDISCONNECTED;
44 ki->ki_rcvq = uds->uds_len;
45 /* We currently mirror the peer's receive queue size when connected. */
46 if (uds_is_connected(uds))
47 ki->ki_sndq = peer->uds_len;
48 /* The source is not set for bound connection-type sockets here. */
49 if (type == SOCK_DGRAM || uds_is_listening(uds))
50 uds_make_addr(uds->uds_path, (size_t)uds->uds_pathlen,
51 &ki->ki_src, &len);
52 if (peer != NULL)
53 uds_make_addr(peer->uds_path, (size_t)peer->uds_pathlen,
54 &ki->ki_dst, &len);
55 /* TODO: we should set ki_inode and ki_vnode, but to what? */
56 ki->ki_conn = (uint64_t)(uintptr_t)peer;
57 if (!TAILQ_EMPTY(&uds->uds_queue))
58 ki->ki_refs =
59 (uint64_t)(uintptr_t)TAILQ_FIRST(&uds->uds_queue);
60 if (uds_has_link(uds))
61 ki->ki_nextref =
62 (uint64_t)(uintptr_t)TAILQ_NEXT(uds, uds_next);
66 * Remote MIB implementation of CTL_NET PF_LOCAL {SOCK_STREAM,SOCK_DGRAM,
67 * SOCK_SEQPACKET} 0. This function handles all queries on the
68 * "net.local.{stream,dgram,seqpacket}.pcblist" sysctl(7) nodes.
70 * The 0 for "pcblist" is a MINIXism: we use it to keep our arrays small.
71 * NetBSD numbers these nodes dynamically and so they have numbers above
72 * CREATE_BASE. That also means that no userland application can possibly
73 * hardcode their numbers, and must perform lookups by name. In turn, that
74 * means that we can safely change the 0 to another number if NetBSD ever
75 * introduces statically numbered nodes in these subtrees.
77 static ssize_t
78 net_local_pcblist(struct rmib_call * call, struct rmib_node * node __unused,
79 struct rmib_oldp * oldp, struct rmib_newp * newp __unused)
81 struct udssock *uds;
82 struct kinfo_pcb ki;
83 ssize_t off;
84 int r, type, size, max;
86 if (call->call_namelen != 4)
87 return EINVAL;
89 /* The first two added name fields are not used. */
91 size = call->call_name[2];
92 if (size < 0 || (size_t)size > sizeof(ki))
93 return EINVAL;
94 if (size == 0)
95 size = sizeof(ki);
96 max = call->call_name[3];
98 type = call->call_oname[2];
100 off = 0;
102 for (uds = uds_enum(NULL, type); uds != NULL;
103 uds = uds_enum(uds, type)) {
104 if (rmib_inrange(oldp, off)) {
105 memset(&ki, 0, sizeof(ki));
107 uds_get_info(&ki, uds);
109 if ((r = rmib_copyout(oldp, off, &ki, size)) < 0)
110 return r;
113 off += size;
114 if (max > 0 && --max == 0)
115 break;
119 * Margin to limit the possible effects of the inherent race condition
120 * between receiving just the data size and receiving the actual data.
122 if (oldp == NULL)
123 off += PCB_SLOP * size;
125 return off;
128 /* The CTL_NET PF_LOCAL SOCK_STREAM subtree. */
129 static struct rmib_node net_local_stream_table[] = {
130 [0] = RMIB_FUNC(RMIB_RO | CTLTYPE_NODE, 0, net_local_pcblist,
131 "pcblist", "SOCK_STREAM protocol control block list"),
134 /* The CTL_NET PF_LOCAL SOCK_DGRAM subtree. */
135 static struct rmib_node net_local_dgram_table[] = {
136 [0] = RMIB_FUNC(RMIB_RO | CTLTYPE_NODE, 0, net_local_pcblist,
137 "pcblist", "SOCK_DGRAM protocol control block list"),
140 /* The CTL_NET PF_LOCAL SOCK_SEQPACKET subtree. */
141 static struct rmib_node net_local_seqpacket_table[] = {
142 [0] = RMIB_FUNC(RMIB_RO | CTLTYPE_NODE, 0, net_local_pcblist,
143 "pcblist", "SOCK_SEQPACKET protocol control block list"),
146 /* The CTL_NET PF_LOCAL subtree. */
147 static struct rmib_node net_local_table[] = {
148 /* 1*/ [SOCK_STREAM] = RMIB_NODE(RMIB_RO, net_local_stream_table,
149 "stream", "SOCK_STREAM settings"),
150 /* 2*/ [SOCK_DGRAM] = RMIB_NODE(RMIB_RO, net_local_dgram_table,
151 "dgram", "SOCK_DGRAM settings"),
152 /* 5*/ [SOCK_SEQPACKET] = RMIB_NODE(RMIB_RO, net_local_seqpacket_table,
153 "seqpacket", "SOCK_SEQPACKET settings"),
156 static struct rmib_node net_local_node =
157 RMIB_NODE(RMIB_RO, net_local_table, "local", "PF_LOCAL related settings");
160 * Initialize the status module.
162 void
163 uds_stat_init(void)
165 const int mib[] = { CTL_NET, PF_LOCAL };
166 int r;
169 * Register our own "net.local" subtree with the MIB service.
171 * This call only returns local failures. Remote failures (in the MIB
172 * service) are silently ignored. So, we can safely panic on failure.
174 if ((r = rmib_register(mib, __arraycount(mib), &net_local_node)) != OK)
175 panic("UDS: unable to register remote MIB tree: %d", r);
179 * Clean up the status module.
181 void
182 uds_stat_cleanup(void)
185 rmib_deregister(&net_local_node);