Deleted Added
full compact
proto_uds.c (218474) proto_uds.c (219818)
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
30#include <sys/cdefs.h>
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
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sbin/hastd/proto_uds.c 218474 2011-02-09 08:01:10Z pjd $");
31__FBSDID("$FreeBSD: head/sbin/hastd/proto_uds.c 219818 2011-03-21 08:54:59Z pjd $");
32
33/* UDS - UNIX Domain Socket */
34
35#include <sys/types.h>
36#include <sys/un.h>
37
38#include <errno.h>
39#include <stdbool.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <string.h>
43#include <unistd.h>
44
45#include "hast.h"
46#include "pjdlog.h"
47#include "proto_impl.h"
48
49#define UDS_CTX_MAGIC 0xd541c
50struct uds_ctx {
51 int uc_magic;
52 struct sockaddr_un uc_sun;
53 int uc_fd;
54 int uc_side;
55#define UDS_SIDE_CLIENT 0
56#define UDS_SIDE_SERVER_LISTEN 1
57#define UDS_SIDE_SERVER_WORK 2
58 pid_t uc_owner;
59};
60
61static void uds_close(void *ctx);
62
63static int
64uds_addr(const char *addr, struct sockaddr_un *sunp)
65{
66
67 if (addr == NULL)
68 return (-1);
69
70 if (strncasecmp(addr, "uds://", 6) == 0)
71 addr += 6;
72 else if (strncasecmp(addr, "unix://", 7) == 0)
73 addr += 7;
74 else if (addr[0] == '/' && /* If it starts from /... */
75 strstr(addr, "://") == NULL)/* ...and there is no prefix... */
76 ; /* ...we assume its us. */
77 else
78 return (-1);
79
80 sunp->sun_family = AF_UNIX;
81 if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >=
82 sizeof(sunp->sun_path)) {
83 return (ENAMETOOLONG);
84 }
85 sunp->sun_len = SUN_LEN(sunp);
86
87 return (0);
88}
89
90static int
91uds_common_setup(const char *addr, void **ctxp, int side)
92{
93 struct uds_ctx *uctx;
94 int ret;
95
96 uctx = malloc(sizeof(*uctx));
97 if (uctx == NULL)
98 return (errno);
99
100 /* Parse given address. */
101 if ((ret = uds_addr(addr, &uctx->uc_sun)) != 0) {
102 free(uctx);
103 return (ret);
104 }
105
106 uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0);
107 if (uctx->uc_fd == -1) {
108 ret = errno;
109 free(uctx);
110 return (ret);
111 }
112
113 uctx->uc_side = side;
114 uctx->uc_owner = 0;
115 uctx->uc_magic = UDS_CTX_MAGIC;
116 *ctxp = uctx;
117
118 return (0);
119}
120
121static int
32
33/* UDS - UNIX Domain Socket */
34
35#include <sys/types.h>
36#include <sys/un.h>
37
38#include <errno.h>
39#include <stdbool.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <string.h>
43#include <unistd.h>
44
45#include "hast.h"
46#include "pjdlog.h"
47#include "proto_impl.h"
48
49#define UDS_CTX_MAGIC 0xd541c
50struct uds_ctx {
51 int uc_magic;
52 struct sockaddr_un uc_sun;
53 int uc_fd;
54 int uc_side;
55#define UDS_SIDE_CLIENT 0
56#define UDS_SIDE_SERVER_LISTEN 1
57#define UDS_SIDE_SERVER_WORK 2
58 pid_t uc_owner;
59};
60
61static void uds_close(void *ctx);
62
63static int
64uds_addr(const char *addr, struct sockaddr_un *sunp)
65{
66
67 if (addr == NULL)
68 return (-1);
69
70 if (strncasecmp(addr, "uds://", 6) == 0)
71 addr += 6;
72 else if (strncasecmp(addr, "unix://", 7) == 0)
73 addr += 7;
74 else if (addr[0] == '/' && /* If it starts from /... */
75 strstr(addr, "://") == NULL)/* ...and there is no prefix... */
76 ; /* ...we assume its us. */
77 else
78 return (-1);
79
80 sunp->sun_family = AF_UNIX;
81 if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >=
82 sizeof(sunp->sun_path)) {
83 return (ENAMETOOLONG);
84 }
85 sunp->sun_len = SUN_LEN(sunp);
86
87 return (0);
88}
89
90static int
91uds_common_setup(const char *addr, void **ctxp, int side)
92{
93 struct uds_ctx *uctx;
94 int ret;
95
96 uctx = malloc(sizeof(*uctx));
97 if (uctx == NULL)
98 return (errno);
99
100 /* Parse given address. */
101 if ((ret = uds_addr(addr, &uctx->uc_sun)) != 0) {
102 free(uctx);
103 return (ret);
104 }
105
106 uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0);
107 if (uctx->uc_fd == -1) {
108 ret = errno;
109 free(uctx);
110 return (ret);
111 }
112
113 uctx->uc_side = side;
114 uctx->uc_owner = 0;
115 uctx->uc_magic = UDS_CTX_MAGIC;
116 *ctxp = uctx;
117
118 return (0);
119}
120
121static int
122uds_client(const char *addr, void **ctxp)
122uds_client(const char *srcaddr, const char *dstaddr, void **ctxp)
123{
123{
124 int ret;
124
125
125 return (uds_common_setup(addr, ctxp, UDS_SIDE_CLIENT));
126 ret = uds_common_setup(dstaddr, ctxp, UDS_SIDE_CLIENT);
127 if (ret != 0)
128 return (ret);
129
130 PJDLOG_ASSERT(srcaddr == NULL);
131
132 return (0);
126}
127
128static int
129uds_connect(void *ctx, int timeout)
130{
131 struct uds_ctx *uctx = ctx;
132
133 PJDLOG_ASSERT(uctx != NULL);
134 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
135 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
136 PJDLOG_ASSERT(uctx->uc_fd >= 0);
137 PJDLOG_ASSERT(timeout >= -1);
138
139 if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
140 sizeof(uctx->uc_sun)) < 0) {
141 return (errno);
142 }
143
144 return (0);
145}
146
147static int
148uds_connect_wait(void *ctx, int timeout)
149{
150 struct uds_ctx *uctx = ctx;
151
152 PJDLOG_ASSERT(uctx != NULL);
153 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
154 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
155 PJDLOG_ASSERT(uctx->uc_fd >= 0);
156 PJDLOG_ASSERT(timeout >= 0);
157
158 return (0);
159}
160
161static int
162uds_server(const char *addr, void **ctxp)
163{
164 struct uds_ctx *uctx;
165 int ret;
166
167 ret = uds_common_setup(addr, ctxp, UDS_SIDE_SERVER_LISTEN);
168 if (ret != 0)
169 return (ret);
170
171 uctx = *ctxp;
172
173 (void)unlink(uctx->uc_sun.sun_path);
174 if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
175 sizeof(uctx->uc_sun)) < 0) {
176 ret = errno;
177 uds_close(uctx);
178 return (ret);
179 }
180 uctx->uc_owner = getpid();
181 if (listen(uctx->uc_fd, 8) < 0) {
182 ret = errno;
183 uds_close(uctx);
184 return (ret);
185 }
186
187 return (0);
188}
189
190static int
191uds_accept(void *ctx, void **newctxp)
192{
193 struct uds_ctx *uctx = ctx;
194 struct uds_ctx *newuctx;
195 socklen_t fromlen;
196 int ret;
197
198 PJDLOG_ASSERT(uctx != NULL);
199 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
200 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN);
201 PJDLOG_ASSERT(uctx->uc_fd >= 0);
202
203 newuctx = malloc(sizeof(*newuctx));
204 if (newuctx == NULL)
205 return (errno);
206
207 fromlen = sizeof(newuctx->uc_sun);
208 newuctx->uc_fd = accept(uctx->uc_fd,
209 (struct sockaddr *)&newuctx->uc_sun, &fromlen);
210 if (newuctx->uc_fd < 0) {
211 ret = errno;
212 free(newuctx);
213 return (ret);
214 }
215
216 newuctx->uc_side = UDS_SIDE_SERVER_WORK;
217 newuctx->uc_magic = UDS_CTX_MAGIC;
218 *newctxp = newuctx;
219
220 return (0);
221}
222
223static int
224uds_send(void *ctx, const unsigned char *data, size_t size, int fd)
225{
226 struct uds_ctx *uctx = ctx;
227
228 PJDLOG_ASSERT(uctx != NULL);
229 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
230 PJDLOG_ASSERT(uctx->uc_fd >= 0);
231
232 return (proto_common_send(uctx->uc_fd, data, size, fd));
233}
234
235static int
236uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
237{
238 struct uds_ctx *uctx = ctx;
239
240 PJDLOG_ASSERT(uctx != NULL);
241 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
242 PJDLOG_ASSERT(uctx->uc_fd >= 0);
243
244 return (proto_common_recv(uctx->uc_fd, data, size, fdp));
245}
246
247static int
248uds_descriptor(const void *ctx)
249{
250 const struct uds_ctx *uctx = ctx;
251
252 PJDLOG_ASSERT(uctx != NULL);
253 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
254
255 return (uctx->uc_fd);
256}
257
258static void
259uds_local_address(const void *ctx, char *addr, size_t size)
260{
261 const struct uds_ctx *uctx = ctx;
262 struct sockaddr_un sun;
263 socklen_t sunlen;
264
265 PJDLOG_ASSERT(uctx != NULL);
266 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
267 PJDLOG_ASSERT(addr != NULL);
268
269 sunlen = sizeof(sun);
270 if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
271 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
272 return;
273 }
274 PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
275 if (sun.sun_path[0] == '\0') {
276 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
277 return;
278 }
279 PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size);
280}
281
282static void
283uds_remote_address(const void *ctx, char *addr, size_t size)
284{
285 const struct uds_ctx *uctx = ctx;
286 struct sockaddr_un sun;
287 socklen_t sunlen;
288
289 PJDLOG_ASSERT(uctx != NULL);
290 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
291 PJDLOG_ASSERT(addr != NULL);
292
293 sunlen = sizeof(sun);
294 if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
295 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
296 return;
297 }
298 PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
299 if (sun.sun_path[0] == '\0') {
300 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
301 return;
302 }
303 snprintf(addr, size, "uds://%s", sun.sun_path);
304}
305
306static void
307uds_close(void *ctx)
308{
309 struct uds_ctx *uctx = ctx;
310
311 PJDLOG_ASSERT(uctx != NULL);
312 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
313
314 if (uctx->uc_fd >= 0)
315 close(uctx->uc_fd);
316 /*
317 * Unlink the socket only if we are the owner and this is descriptor
318 * we listen on.
319 */
320 if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN &&
321 uctx->uc_owner == getpid()) {
322 PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0');
323 if (unlink(uctx->uc_sun.sun_path) == -1) {
324 pjdlog_errno(LOG_WARNING,
325 "Unable to unlink socket file %s",
326 uctx->uc_sun.sun_path);
327 }
328 }
329 uctx->uc_owner = 0;
330 uctx->uc_magic = 0;
331 free(uctx);
332}
333
334static struct hast_proto uds_proto = {
335 .hp_name = "uds",
336 .hp_client = uds_client,
337 .hp_connect = uds_connect,
338 .hp_connect_wait = uds_connect_wait,
339 .hp_server = uds_server,
340 .hp_accept = uds_accept,
341 .hp_send = uds_send,
342 .hp_recv = uds_recv,
343 .hp_descriptor = uds_descriptor,
344 .hp_local_address = uds_local_address,
345 .hp_remote_address = uds_remote_address,
346 .hp_close = uds_close
347};
348
349static __constructor void
350uds_ctor(void)
351{
352
353 proto_register(&uds_proto, false);
354}
133}
134
135static int
136uds_connect(void *ctx, int timeout)
137{
138 struct uds_ctx *uctx = ctx;
139
140 PJDLOG_ASSERT(uctx != NULL);
141 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
142 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
143 PJDLOG_ASSERT(uctx->uc_fd >= 0);
144 PJDLOG_ASSERT(timeout >= -1);
145
146 if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
147 sizeof(uctx->uc_sun)) < 0) {
148 return (errno);
149 }
150
151 return (0);
152}
153
154static int
155uds_connect_wait(void *ctx, int timeout)
156{
157 struct uds_ctx *uctx = ctx;
158
159 PJDLOG_ASSERT(uctx != NULL);
160 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
161 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
162 PJDLOG_ASSERT(uctx->uc_fd >= 0);
163 PJDLOG_ASSERT(timeout >= 0);
164
165 return (0);
166}
167
168static int
169uds_server(const char *addr, void **ctxp)
170{
171 struct uds_ctx *uctx;
172 int ret;
173
174 ret = uds_common_setup(addr, ctxp, UDS_SIDE_SERVER_LISTEN);
175 if (ret != 0)
176 return (ret);
177
178 uctx = *ctxp;
179
180 (void)unlink(uctx->uc_sun.sun_path);
181 if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
182 sizeof(uctx->uc_sun)) < 0) {
183 ret = errno;
184 uds_close(uctx);
185 return (ret);
186 }
187 uctx->uc_owner = getpid();
188 if (listen(uctx->uc_fd, 8) < 0) {
189 ret = errno;
190 uds_close(uctx);
191 return (ret);
192 }
193
194 return (0);
195}
196
197static int
198uds_accept(void *ctx, void **newctxp)
199{
200 struct uds_ctx *uctx = ctx;
201 struct uds_ctx *newuctx;
202 socklen_t fromlen;
203 int ret;
204
205 PJDLOG_ASSERT(uctx != NULL);
206 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
207 PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN);
208 PJDLOG_ASSERT(uctx->uc_fd >= 0);
209
210 newuctx = malloc(sizeof(*newuctx));
211 if (newuctx == NULL)
212 return (errno);
213
214 fromlen = sizeof(newuctx->uc_sun);
215 newuctx->uc_fd = accept(uctx->uc_fd,
216 (struct sockaddr *)&newuctx->uc_sun, &fromlen);
217 if (newuctx->uc_fd < 0) {
218 ret = errno;
219 free(newuctx);
220 return (ret);
221 }
222
223 newuctx->uc_side = UDS_SIDE_SERVER_WORK;
224 newuctx->uc_magic = UDS_CTX_MAGIC;
225 *newctxp = newuctx;
226
227 return (0);
228}
229
230static int
231uds_send(void *ctx, const unsigned char *data, size_t size, int fd)
232{
233 struct uds_ctx *uctx = ctx;
234
235 PJDLOG_ASSERT(uctx != NULL);
236 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
237 PJDLOG_ASSERT(uctx->uc_fd >= 0);
238
239 return (proto_common_send(uctx->uc_fd, data, size, fd));
240}
241
242static int
243uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
244{
245 struct uds_ctx *uctx = ctx;
246
247 PJDLOG_ASSERT(uctx != NULL);
248 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
249 PJDLOG_ASSERT(uctx->uc_fd >= 0);
250
251 return (proto_common_recv(uctx->uc_fd, data, size, fdp));
252}
253
254static int
255uds_descriptor(const void *ctx)
256{
257 const struct uds_ctx *uctx = ctx;
258
259 PJDLOG_ASSERT(uctx != NULL);
260 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
261
262 return (uctx->uc_fd);
263}
264
265static void
266uds_local_address(const void *ctx, char *addr, size_t size)
267{
268 const struct uds_ctx *uctx = ctx;
269 struct sockaddr_un sun;
270 socklen_t sunlen;
271
272 PJDLOG_ASSERT(uctx != NULL);
273 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
274 PJDLOG_ASSERT(addr != NULL);
275
276 sunlen = sizeof(sun);
277 if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
278 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
279 return;
280 }
281 PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
282 if (sun.sun_path[0] == '\0') {
283 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
284 return;
285 }
286 PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size);
287}
288
289static void
290uds_remote_address(const void *ctx, char *addr, size_t size)
291{
292 const struct uds_ctx *uctx = ctx;
293 struct sockaddr_un sun;
294 socklen_t sunlen;
295
296 PJDLOG_ASSERT(uctx != NULL);
297 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
298 PJDLOG_ASSERT(addr != NULL);
299
300 sunlen = sizeof(sun);
301 if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) {
302 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
303 return;
304 }
305 PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
306 if (sun.sun_path[0] == '\0') {
307 PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
308 return;
309 }
310 snprintf(addr, size, "uds://%s", sun.sun_path);
311}
312
313static void
314uds_close(void *ctx)
315{
316 struct uds_ctx *uctx = ctx;
317
318 PJDLOG_ASSERT(uctx != NULL);
319 PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
320
321 if (uctx->uc_fd >= 0)
322 close(uctx->uc_fd);
323 /*
324 * Unlink the socket only if we are the owner and this is descriptor
325 * we listen on.
326 */
327 if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN &&
328 uctx->uc_owner == getpid()) {
329 PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0');
330 if (unlink(uctx->uc_sun.sun_path) == -1) {
331 pjdlog_errno(LOG_WARNING,
332 "Unable to unlink socket file %s",
333 uctx->uc_sun.sun_path);
334 }
335 }
336 uctx->uc_owner = 0;
337 uctx->uc_magic = 0;
338 free(uctx);
339}
340
341static struct hast_proto uds_proto = {
342 .hp_name = "uds",
343 .hp_client = uds_client,
344 .hp_connect = uds_connect,
345 .hp_connect_wait = uds_connect_wait,
346 .hp_server = uds_server,
347 .hp_accept = uds_accept,
348 .hp_send = uds_send,
349 .hp_recv = uds_recv,
350 .hp_descriptor = uds_descriptor,
351 .hp_local_address = uds_local_address,
352 .hp_remote_address = uds_remote_address,
353 .hp_close = uds_close
354};
355
356static __constructor void
357uds_ctor(void)
358{
359
360 proto_register(&uds_proto, false);
361}