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