1*1996St.nateldemoura@f5.com /*
2*1996St.nateldemoura@f5.com * Copyright (C) NGINX, Inc.
3*1996St.nateldemoura@f5.com */
4*1996St.nateldemoura@f5.com
5*1996St.nateldemoura@f5.com #ifndef _NXT_SOCKET_MSG_H_INCLUDED_
6*1996St.nateldemoura@f5.com #define _NXT_SOCKET_MSG_H_INCLUDED_
7*1996St.nateldemoura@f5.com
8*1996St.nateldemoura@f5.com #if (NXT_HAVE_UCRED)
9*1996St.nateldemoura@f5.com #include <sys/un.h>
10*1996St.nateldemoura@f5.com #endif
11*1996St.nateldemoura@f5.com
12*1996St.nateldemoura@f5.com
13*1996St.nateldemoura@f5.com #if (NXT_HAVE_UCRED)
14*1996St.nateldemoura@f5.com #define NXT_CRED_USECMSG 1
15*1996St.nateldemoura@f5.com #define NXT_CRED_CMSGTYPE SCM_CREDENTIALS
16*1996St.nateldemoura@f5.com #define NXT_CRED_GETPID(u) (u->pid)
17*1996St.nateldemoura@f5.com
18*1996St.nateldemoura@f5.com typedef struct ucred nxt_socket_cred_t;
19*1996St.nateldemoura@f5.com
20*1996St.nateldemoura@f5.com #elif (NXT_HAVE_MSGHDR_CMSGCRED)
21*1996St.nateldemoura@f5.com #define NXT_CRED_USECMSG 1
22*1996St.nateldemoura@f5.com #define NXT_CRED_CMSGTYPE SCM_CREDS
23*1996St.nateldemoura@f5.com #define NXT_CRED_GETPID(u) (u->cmcred_pid)
24*1996St.nateldemoura@f5.com
25*1996St.nateldemoura@f5.com typedef struct cmsgcred nxt_socket_cred_t;
26*1996St.nateldemoura@f5.com #endif
27*1996St.nateldemoura@f5.com
28*1996St.nateldemoura@f5.com #if (NXT_CRED_USECMSG)
29*1996St.nateldemoura@f5.com #define NXT_OOB_RECV_SIZE \
30*1996St.nateldemoura@f5.com (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t)))
31*1996St.nateldemoura@f5.com #else
32*1996St.nateldemoura@f5.com #define NXT_OOB_RECV_SIZE \
33*1996St.nateldemoura@f5.com CMSG_SPACE(2 * sizeof(int))
34*1996St.nateldemoura@f5.com #endif
35*1996St.nateldemoura@f5.com
36*1996St.nateldemoura@f5.com #if (NXT_HAVE_MSGHDR_CMSGCRED)
37*1996St.nateldemoura@f5.com #define NXT_OOB_SEND_SIZE \
38*1996St.nateldemoura@f5.com (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t)))
39*1996St.nateldemoura@f5.com #else
40*1996St.nateldemoura@f5.com #define NXT_OOB_SEND_SIZE \
41*1996St.nateldemoura@f5.com CMSG_SPACE(2 * sizeof(int))
42*1996St.nateldemoura@f5.com #endif
43*1996St.nateldemoura@f5.com
44*1996St.nateldemoura@f5.com
45*1996St.nateldemoura@f5.com typedef struct {
46*1996St.nateldemoura@f5.com size_t size;
47*1996St.nateldemoura@f5.com u_char buf[NXT_OOB_RECV_SIZE];
48*1996St.nateldemoura@f5.com } nxt_recv_oob_t;
49*1996St.nateldemoura@f5.com
50*1996St.nateldemoura@f5.com
51*1996St.nateldemoura@f5.com typedef struct {
52*1996St.nateldemoura@f5.com size_t size;
53*1996St.nateldemoura@f5.com u_char buf[NXT_OOB_SEND_SIZE];
54*1996St.nateldemoura@f5.com } nxt_send_oob_t;
55*1996St.nateldemoura@f5.com
56*1996St.nateldemoura@f5.com
57*1996St.nateldemoura@f5.com /**
58*1996St.nateldemoura@f5.com * The nxt_sendmsg is a wrapper for sendmsg.
59*1996St.nateldemoura@f5.com * The oob struct must be initialized using nxt_socket_msg_oob_init().
60*1996St.nateldemoura@f5.com */
61*1996St.nateldemoura@f5.com NXT_EXPORT ssize_t nxt_sendmsg(nxt_socket_t s, nxt_iobuf_t *iob,
62*1996St.nateldemoura@f5.com nxt_uint_t niob, const nxt_send_oob_t *oob);
63*1996St.nateldemoura@f5.com
64*1996St.nateldemoura@f5.com /**
65*1996St.nateldemoura@f5.com * The nxt_recvmsg is a wrapper for recvmsg.
66*1996St.nateldemoura@f5.com * The oob buffer must be consumed by using nxt_socket_msg_oob_get().
67*1996St.nateldemoura@f5.com */
68*1996St.nateldemoura@f5.com NXT_EXPORT ssize_t nxt_recvmsg(nxt_socket_t s,
69*1996St.nateldemoura@f5.com nxt_iobuf_t *iob, nxt_uint_t niob, nxt_recv_oob_t *oob);
70*1996St.nateldemoura@f5.com
71*1996St.nateldemoura@f5.com
72*1996St.nateldemoura@f5.com nxt_inline void
nxt_socket_msg_oob_init(nxt_send_oob_t * oob,int * fds)73*1996St.nateldemoura@f5.com nxt_socket_msg_oob_init(nxt_send_oob_t *oob, int *fds)
74*1996St.nateldemoura@f5.com {
75*1996St.nateldemoura@f5.com int nfds;
76*1996St.nateldemoura@f5.com struct cmsghdr *cmsg;
77*1996St.nateldemoura@f5.com
78*1996St.nateldemoura@f5.com #if (NXT_HAVE_MSGHDR_CMSGCRED)
79*1996St.nateldemoura@f5.com cmsg = (struct cmsghdr *) (oob->buf);
80*1996St.nateldemoura@f5.com /*
81*1996St.nateldemoura@f5.com * Fill all padding fields with 0.
82*1996St.nateldemoura@f5.com * Code in Go 1.11 validate cmsghdr using padding field as part of len.
83*1996St.nateldemoura@f5.com * See Cmsghdr definition and socketControlMessageHeaderAndData function.
84*1996St.nateldemoura@f5.com */
85*1996St.nateldemoura@f5.com nxt_memzero(cmsg, sizeof(struct cmsghdr));
86*1996St.nateldemoura@f5.com
87*1996St.nateldemoura@f5.com cmsg->cmsg_len = CMSG_LEN(sizeof(nxt_socket_cred_t));
88*1996St.nateldemoura@f5.com cmsg->cmsg_level = SOL_SOCKET;
89*1996St.nateldemoura@f5.com cmsg->cmsg_type = NXT_CRED_CMSGTYPE;
90*1996St.nateldemoura@f5.com
91*1996St.nateldemoura@f5.com oob->size = CMSG_SPACE(sizeof(nxt_socket_cred_t));
92*1996St.nateldemoura@f5.com
93*1996St.nateldemoura@f5.com #else
94*1996St.nateldemoura@f5.com oob->size = 0;
95*1996St.nateldemoura@f5.com #endif
96*1996St.nateldemoura@f5.com
97*1996St.nateldemoura@f5.com nfds = (fds[0] != -1 ? 1 : 0) + (fds[1] != -1 ? 1 : 0);
98*1996St.nateldemoura@f5.com
99*1996St.nateldemoura@f5.com if (nfds == 0) {
100*1996St.nateldemoura@f5.com return;
101*1996St.nateldemoura@f5.com }
102*1996St.nateldemoura@f5.com
103*1996St.nateldemoura@f5.com cmsg = (struct cmsghdr *) (oob->buf + oob->size);
104*1996St.nateldemoura@f5.com
105*1996St.nateldemoura@f5.com nxt_memzero(cmsg, sizeof(struct cmsghdr));
106*1996St.nateldemoura@f5.com
107*1996St.nateldemoura@f5.com cmsg->cmsg_len = CMSG_LEN(nfds * sizeof(int));
108*1996St.nateldemoura@f5.com cmsg->cmsg_level = SOL_SOCKET;
109*1996St.nateldemoura@f5.com cmsg->cmsg_type = SCM_RIGHTS;
110*1996St.nateldemoura@f5.com
111*1996St.nateldemoura@f5.com /*
112*1996St.nateldemoura@f5.com * nxt_memcpy() is used instead of simple
113*1996St.nateldemoura@f5.com * *(int *) CMSG_DATA(&cmsg.cm) = fd;
114*1996St.nateldemoura@f5.com * because GCC 4.4 with -O2/3/s optimization may issue a warning:
115*1996St.nateldemoura@f5.com * dereferencing type-punned pointer will break strict-aliasing rules
116*1996St.nateldemoura@f5.com *
117*1996St.nateldemoura@f5.com * Fortunately, GCC with -O1 compiles this nxt_memcpy()
118*1996St.nateldemoura@f5.com * in the same simple assignment as in the code above.
119*1996St.nateldemoura@f5.com */
120*1996St.nateldemoura@f5.com nxt_memcpy(CMSG_DATA(cmsg), fds, nfds * sizeof(int));
121*1996St.nateldemoura@f5.com
122*1996St.nateldemoura@f5.com oob->size += CMSG_SPACE(nfds * sizeof(int));
123*1996St.nateldemoura@f5.com }
124*1996St.nateldemoura@f5.com
125*1996St.nateldemoura@f5.com
126*1996St.nateldemoura@f5.com nxt_inline nxt_int_t
nxt_socket_msg_oob_get_fds(nxt_recv_oob_t * oob,nxt_fd_t * fd)127*1996St.nateldemoura@f5.com nxt_socket_msg_oob_get_fds(nxt_recv_oob_t *oob, nxt_fd_t *fd)
128*1996St.nateldemoura@f5.com {
129*1996St.nateldemoura@f5.com size_t size;
130*1996St.nateldemoura@f5.com struct msghdr msg;
131*1996St.nateldemoura@f5.com struct cmsghdr *cmsg;
132*1996St.nateldemoura@f5.com
133*1996St.nateldemoura@f5.com msg.msg_control = oob->buf;
134*1996St.nateldemoura@f5.com msg.msg_controllen = oob->size;
135*1996St.nateldemoura@f5.com
136*1996St.nateldemoura@f5.com for (cmsg = CMSG_FIRSTHDR(&msg);
137*1996St.nateldemoura@f5.com cmsg != NULL;
138*1996St.nateldemoura@f5.com cmsg = CMSG_NXTHDR(&msg, cmsg))
139*1996St.nateldemoura@f5.com {
140*1996St.nateldemoura@f5.com size = cmsg->cmsg_len - CMSG_LEN(0);
141*1996St.nateldemoura@f5.com
142*1996St.nateldemoura@f5.com if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
143*1996St.nateldemoura@f5.com if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) {
144*1996St.nateldemoura@f5.com return NXT_ERROR;
145*1996St.nateldemoura@f5.com }
146*1996St.nateldemoura@f5.com
147*1996St.nateldemoura@f5.com nxt_memcpy(fd, CMSG_DATA(cmsg), size);
148*1996St.nateldemoura@f5.com
149*1996St.nateldemoura@f5.com return NXT_OK;
150*1996St.nateldemoura@f5.com }
151*1996St.nateldemoura@f5.com }
152*1996St.nateldemoura@f5.com
153*1996St.nateldemoura@f5.com return NXT_OK;
154*1996St.nateldemoura@f5.com }
155*1996St.nateldemoura@f5.com
156*1996St.nateldemoura@f5.com
157*1996St.nateldemoura@f5.com nxt_inline nxt_int_t
nxt_socket_msg_oob_get(nxt_recv_oob_t * oob,nxt_fd_t * fd,nxt_pid_t * pid)158*1996St.nateldemoura@f5.com nxt_socket_msg_oob_get(nxt_recv_oob_t *oob, nxt_fd_t *fd, nxt_pid_t *pid)
159*1996St.nateldemoura@f5.com {
160*1996St.nateldemoura@f5.com size_t size;
161*1996St.nateldemoura@f5.com struct msghdr msg;
162*1996St.nateldemoura@f5.com struct cmsghdr *cmsg;
163*1996St.nateldemoura@f5.com
164*1996St.nateldemoura@f5.com if (oob->size == 0) {
165*1996St.nateldemoura@f5.com return NXT_OK;
166*1996St.nateldemoura@f5.com }
167*1996St.nateldemoura@f5.com
168*1996St.nateldemoura@f5.com #if (NXT_CRED_USECMSG)
169*1996St.nateldemoura@f5.com *pid = -1;
170*1996St.nateldemoura@f5.com #endif
171*1996St.nateldemoura@f5.com
172*1996St.nateldemoura@f5.com msg.msg_control = oob->buf;
173*1996St.nateldemoura@f5.com msg.msg_controllen = oob->size;
174*1996St.nateldemoura@f5.com
175*1996St.nateldemoura@f5.com for (cmsg = CMSG_FIRSTHDR(&msg);
176*1996St.nateldemoura@f5.com cmsg != NULL;
177*1996St.nateldemoura@f5.com cmsg = CMSG_NXTHDR(&msg, cmsg))
178*1996St.nateldemoura@f5.com {
179*1996St.nateldemoura@f5.com size = cmsg->cmsg_len - CMSG_LEN(0);
180*1996St.nateldemoura@f5.com
181*1996St.nateldemoura@f5.com if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
182*1996St.nateldemoura@f5.com if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) {
183*1996St.nateldemoura@f5.com return NXT_ERROR;
184*1996St.nateldemoura@f5.com }
185*1996St.nateldemoura@f5.com
186*1996St.nateldemoura@f5.com nxt_memcpy(fd, CMSG_DATA(cmsg), size);
187*1996St.nateldemoura@f5.com
188*1996St.nateldemoura@f5.com #if (!NXT_CRED_USECMSG)
189*1996St.nateldemoura@f5.com break;
190*1996St.nateldemoura@f5.com #endif
191*1996St.nateldemoura@f5.com }
192*1996St.nateldemoura@f5.com
193*1996St.nateldemoura@f5.com #if (NXT_CRED_USECMSG)
194*1996St.nateldemoura@f5.com else if (cmsg->cmsg_level == SOL_SOCKET
195*1996St.nateldemoura@f5.com && cmsg->cmsg_type == NXT_CRED_CMSGTYPE)
196*1996St.nateldemoura@f5.com {
197*1996St.nateldemoura@f5.com nxt_socket_cred_t *creds;
198*1996St.nateldemoura@f5.com
199*1996St.nateldemoura@f5.com if (nxt_slow_path(size != sizeof(nxt_socket_cred_t))) {
200*1996St.nateldemoura@f5.com return NXT_ERROR;
201*1996St.nateldemoura@f5.com }
202*1996St.nateldemoura@f5.com
203*1996St.nateldemoura@f5.com creds = (nxt_socket_cred_t *) CMSG_DATA(cmsg);
204*1996St.nateldemoura@f5.com *pid = NXT_CRED_GETPID(creds);
205*1996St.nateldemoura@f5.com }
206*1996St.nateldemoura@f5.com #endif
207*1996St.nateldemoura@f5.com }
208*1996St.nateldemoura@f5.com
209*1996St.nateldemoura@f5.com #if (NXT_CRED_USECMSG)
210*1996St.nateldemoura@f5.com /* For platforms supporting credential passing, it's enforced */
211*1996St.nateldemoura@f5.com if (nxt_slow_path(*pid == -1)) {
212*1996St.nateldemoura@f5.com return NXT_ERROR;
213*1996St.nateldemoura@f5.com }
214*1996St.nateldemoura@f5.com #endif
215*1996St.nateldemoura@f5.com
216*1996St.nateldemoura@f5.com return NXT_OK;
217*1996St.nateldemoura@f5.com }
218*1996St.nateldemoura@f5.com
219*1996St.nateldemoura@f5.com
220*1996St.nateldemoura@f5.com #endif /* _NXT_SOCKET_MSG_H_INCLUDED_ */
221