xref: /unit/src/nxt_socket_msg.h (revision 1996)
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
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
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
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