]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/openbsm/bin/auditdistd/proto_socketpair.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / openbsm / bin / auditdistd / proto_socketpair.c
1 /*-
2  * Copyright (c) 2009-2010 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_socketpair.c#1 $
30  */
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #include "pjdlog.h"
43 #include "proto_impl.h"
44
45 #define SP_CTX_MAGIC    0x50c3741
46 struct sp_ctx {
47         int                     sp_magic;
48         int                     sp_fd[2];
49         int                     sp_side;
50 #define SP_SIDE_UNDEF           0
51 #define SP_SIDE_CLIENT          1
52 #define SP_SIDE_SERVER          2
53 };
54
55 static void sp_close(void *ctx);
56
57 static int
58 sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
59 {
60         struct sp_ctx *spctx;
61         int error;
62
63         PJDLOG_ASSERT(dstaddr != NULL);
64         PJDLOG_ASSERT(timeout >= -1);
65
66         if (strcmp(dstaddr, "socketpair://") != 0)
67                 return (-1);
68
69         PJDLOG_ASSERT(srcaddr == NULL);
70
71         spctx = malloc(sizeof(*spctx));
72         if (spctx == NULL)
73                 return (errno);
74
75         if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) {
76                 error = errno;
77                 free(spctx);
78                 return (error);
79         }
80
81         spctx->sp_side = SP_SIDE_UNDEF;
82         spctx->sp_magic = SP_CTX_MAGIC;
83         *ctxp = spctx;
84
85         return (0);
86 }
87
88 static int
89 sp_wrap(int fd, bool client, void **ctxp)
90 {
91         struct sp_ctx *spctx;
92
93         PJDLOG_ASSERT(fd >= 0);
94
95         spctx = malloc(sizeof(*spctx));
96         if (spctx == NULL)
97                 return (errno);
98
99         if (client) {
100                 spctx->sp_side = SP_SIDE_CLIENT;
101                 spctx->sp_fd[0] = fd;
102                 spctx->sp_fd[1] = -1;
103         } else {
104                 spctx->sp_side = SP_SIDE_SERVER;
105                 spctx->sp_fd[0] = -1;
106                 spctx->sp_fd[1] = fd;
107         }
108         spctx->sp_magic = SP_CTX_MAGIC;
109         *ctxp = spctx;
110
111         return (0);
112 }
113
114 static int
115 sp_send(void *ctx, const unsigned char *data, size_t size, int fd)
116 {
117         struct sp_ctx *spctx = ctx;
118         int sock;
119
120         PJDLOG_ASSERT(spctx != NULL);
121         PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
122
123         switch (spctx->sp_side) {
124         case SP_SIDE_UNDEF:
125                 /*
126                  * If the first operation done by the caller is proto_send(),
127                  * we assume this is the client.
128                  */
129                 /* FALLTHROUGH */
130                 spctx->sp_side = SP_SIDE_CLIENT;
131                 /* Close other end. */
132                 close(spctx->sp_fd[1]);
133                 spctx->sp_fd[1] = -1;
134         case SP_SIDE_CLIENT:
135                 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
136                 sock = spctx->sp_fd[0];
137                 break;
138         case SP_SIDE_SERVER:
139                 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
140                 sock = spctx->sp_fd[1];
141                 break;
142         default:
143                 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
144         }
145
146         /* Someone is just trying to decide about side. */
147         if (data == NULL)
148                 return (0);
149
150         return (proto_common_send(sock, data, size, fd));
151 }
152
153 static int
154 sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
155 {
156         struct sp_ctx *spctx = ctx;
157         int sock;
158
159         PJDLOG_ASSERT(spctx != NULL);
160         PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
161
162         switch (spctx->sp_side) {
163         case SP_SIDE_UNDEF:
164                 /*
165                  * If the first operation done by the caller is proto_recv(),
166                  * we assume this is the server.
167                  */
168                 /* FALLTHROUGH */
169                 spctx->sp_side = SP_SIDE_SERVER;
170                 /* Close other end. */
171                 close(spctx->sp_fd[0]);
172                 spctx->sp_fd[0] = -1;
173         case SP_SIDE_SERVER:
174                 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
175                 sock = spctx->sp_fd[1];
176                 break;
177         case SP_SIDE_CLIENT:
178                 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
179                 sock = spctx->sp_fd[0];
180                 break;
181         default:
182                 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
183         }
184
185         /* Someone is just trying to decide about side. */
186         if (data == NULL)
187                 return (0);
188
189         return (proto_common_recv(sock, data, size, fdp));
190 }
191
192 static int
193 sp_descriptor(const void *ctx)
194 {
195         const struct sp_ctx *spctx = ctx;
196
197         PJDLOG_ASSERT(spctx != NULL);
198         PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
199         PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT ||
200             spctx->sp_side == SP_SIDE_SERVER);
201
202         switch (spctx->sp_side) {
203         case SP_SIDE_CLIENT:
204                 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
205                 return (spctx->sp_fd[0]);
206         case SP_SIDE_SERVER:
207                 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
208                 return (spctx->sp_fd[1]);
209         }
210
211         PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
212 }
213
214 static void
215 sp_close(void *ctx)
216 {
217         struct sp_ctx *spctx = ctx;
218
219         PJDLOG_ASSERT(spctx != NULL);
220         PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
221
222         switch (spctx->sp_side) {
223         case SP_SIDE_UNDEF:
224                 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
225                 close(spctx->sp_fd[0]);
226                 spctx->sp_fd[0] = -1;
227                 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
228                 close(spctx->sp_fd[1]);
229                 spctx->sp_fd[1] = -1;
230                 break;
231         case SP_SIDE_CLIENT:
232                 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
233                 close(spctx->sp_fd[0]);
234                 spctx->sp_fd[0] = -1;
235                 PJDLOG_ASSERT(spctx->sp_fd[1] == -1);
236                 break;
237         case SP_SIDE_SERVER:
238                 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
239                 close(spctx->sp_fd[1]);
240                 spctx->sp_fd[1] = -1;
241                 PJDLOG_ASSERT(spctx->sp_fd[0] == -1);
242                 break;
243         default:
244                 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
245         }
246
247         spctx->sp_magic = 0;
248         free(spctx);
249 }
250
251 static struct proto sp_proto = {
252         .prt_name = "socketpair",
253         .prt_connect = sp_connect,
254         .prt_wrap = sp_wrap,
255         .prt_send = sp_send,
256         .prt_recv = sp_recv,
257         .prt_descriptor = sp_descriptor,
258         .prt_close = sp_close
259 };
260
261 static __constructor void
262 sp_ctor(void)
263 {
264
265         proto_register(&sp_proto, false);
266 }