xref: /freebsd-src/sbin/hastd/proto_uds.c (revision 5c2bc3db201a4fe8d7911cf816bea104d5dc2138)
132115b10SPawel Jakub Dawidek /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
432115b10SPawel Jakub Dawidek  * Copyright (c) 2009-2010 The FreeBSD Foundation
532115b10SPawel Jakub Dawidek  *
632115b10SPawel Jakub Dawidek  * This software was developed by Pawel Jakub Dawidek under sponsorship from
732115b10SPawel Jakub Dawidek  * the FreeBSD Foundation.
832115b10SPawel Jakub Dawidek  *
932115b10SPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
1032115b10SPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
1132115b10SPawel Jakub Dawidek  * are met:
1232115b10SPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
1332115b10SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
1432115b10SPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
1532115b10SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
1632115b10SPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
1732115b10SPawel Jakub Dawidek  *
1832115b10SPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1932115b10SPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2032115b10SPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2132115b10SPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2232115b10SPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2332115b10SPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2432115b10SPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2532115b10SPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2632115b10SPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2732115b10SPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2832115b10SPawel Jakub Dawidek  * SUCH DAMAGE.
2932115b10SPawel Jakub Dawidek  */
3032115b10SPawel Jakub Dawidek 
3132115b10SPawel Jakub Dawidek #include <sys/cdefs.h>
3232115b10SPawel Jakub Dawidek /* UDS - UNIX Domain Socket */
3332115b10SPawel Jakub Dawidek 
340d8d3721SPawel Jakub Dawidek #include <sys/types.h>
35e2eabb44SPawel Jakub Dawidek #include <sys/socket.h>
3632115b10SPawel Jakub Dawidek #include <sys/un.h>
3732115b10SPawel Jakub Dawidek 
3832115b10SPawel Jakub Dawidek #include <errno.h>
3932115b10SPawel Jakub Dawidek #include <stdbool.h>
4032115b10SPawel Jakub Dawidek #include <stdint.h>
4132115b10SPawel Jakub Dawidek #include <stdio.h>
4232115b10SPawel Jakub Dawidek #include <string.h>
4332115b10SPawel Jakub Dawidek #include <unistd.h>
4432115b10SPawel Jakub Dawidek 
452c5dadc9SPawel Jakub Dawidek #include "pjdlog.h"
4632115b10SPawel Jakub Dawidek #include "proto_impl.h"
4732115b10SPawel Jakub Dawidek 
4832115b10SPawel Jakub Dawidek #define	UDS_CTX_MAGIC	0xd541c
4932115b10SPawel Jakub Dawidek struct uds_ctx {
5032115b10SPawel Jakub Dawidek 	int			uc_magic;
5132115b10SPawel Jakub Dawidek 	struct sockaddr_un	uc_sun;
5232115b10SPawel Jakub Dawidek 	int			uc_fd;
5332115b10SPawel Jakub Dawidek 	int			uc_side;
5432115b10SPawel Jakub Dawidek #define	UDS_SIDE_CLIENT		0
5532115b10SPawel Jakub Dawidek #define	UDS_SIDE_SERVER_LISTEN	1
5632115b10SPawel Jakub Dawidek #define	UDS_SIDE_SERVER_WORK	2
57f431ab18SPawel Jakub Dawidek 	pid_t			uc_owner;
5832115b10SPawel Jakub Dawidek };
5932115b10SPawel Jakub Dawidek 
6032115b10SPawel Jakub Dawidek static void uds_close(void *ctx);
6132115b10SPawel Jakub Dawidek 
6232115b10SPawel Jakub Dawidek static int
6332115b10SPawel Jakub Dawidek uds_addr(const char *addr, struct sockaddr_un *sunp)
6432115b10SPawel Jakub Dawidek {
6532115b10SPawel Jakub Dawidek 
6632115b10SPawel Jakub Dawidek 	if (addr == NULL)
6732115b10SPawel Jakub Dawidek 		return (-1);
6832115b10SPawel Jakub Dawidek 
6932115b10SPawel Jakub Dawidek 	if (strncasecmp(addr, "uds://", 6) == 0)
7032115b10SPawel Jakub Dawidek 		addr += 6;
7132115b10SPawel Jakub Dawidek 	else if (strncasecmp(addr, "unix://", 7) == 0)
7232115b10SPawel Jakub Dawidek 		addr += 7;
7332115b10SPawel Jakub Dawidek 	else if (addr[0] == '/' &&	/* If it starts from /... */
7432115b10SPawel Jakub Dawidek 	    strstr(addr, "://") == NULL)/* ...and there is no prefix... */
7532115b10SPawel Jakub Dawidek 		;			/* ...we assume its us. */
7632115b10SPawel Jakub Dawidek 	else
7732115b10SPawel Jakub Dawidek 		return (-1);
7832115b10SPawel Jakub Dawidek 
7932115b10SPawel Jakub Dawidek 	sunp->sun_family = AF_UNIX;
8032115b10SPawel Jakub Dawidek 	if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >=
8132115b10SPawel Jakub Dawidek 	    sizeof(sunp->sun_path)) {
8232115b10SPawel Jakub Dawidek 		return (ENAMETOOLONG);
8332115b10SPawel Jakub Dawidek 	}
8432115b10SPawel Jakub Dawidek 	sunp->sun_len = SUN_LEN(sunp);
8532115b10SPawel Jakub Dawidek 
8632115b10SPawel Jakub Dawidek 	return (0);
8732115b10SPawel Jakub Dawidek }
8832115b10SPawel Jakub Dawidek 
8932115b10SPawel Jakub Dawidek static int
9032115b10SPawel Jakub Dawidek uds_common_setup(const char *addr, void **ctxp, int side)
9132115b10SPawel Jakub Dawidek {
9232115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx;
9332115b10SPawel Jakub Dawidek 	int ret;
9432115b10SPawel Jakub Dawidek 
9532115b10SPawel Jakub Dawidek 	uctx = malloc(sizeof(*uctx));
9632115b10SPawel Jakub Dawidek 	if (uctx == NULL)
9732115b10SPawel Jakub Dawidek 		return (errno);
9832115b10SPawel Jakub Dawidek 
9932115b10SPawel Jakub Dawidek 	/* Parse given address. */
10032115b10SPawel Jakub Dawidek 	if ((ret = uds_addr(addr, &uctx->uc_sun)) != 0) {
10132115b10SPawel Jakub Dawidek 		free(uctx);
10232115b10SPawel Jakub Dawidek 		return (ret);
10332115b10SPawel Jakub Dawidek 	}
10432115b10SPawel Jakub Dawidek 
10532115b10SPawel Jakub Dawidek 	uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0);
10632115b10SPawel Jakub Dawidek 	if (uctx->uc_fd == -1) {
10732115b10SPawel Jakub Dawidek 		ret = errno;
10832115b10SPawel Jakub Dawidek 		free(uctx);
10932115b10SPawel Jakub Dawidek 		return (ret);
11032115b10SPawel Jakub Dawidek 	}
11132115b10SPawel Jakub Dawidek 
11232115b10SPawel Jakub Dawidek 	uctx->uc_side = side;
113f431ab18SPawel Jakub Dawidek 	uctx->uc_owner = 0;
11432115b10SPawel Jakub Dawidek 	uctx->uc_magic = UDS_CTX_MAGIC;
11532115b10SPawel Jakub Dawidek 	*ctxp = uctx;
11632115b10SPawel Jakub Dawidek 
11732115b10SPawel Jakub Dawidek 	return (0);
11832115b10SPawel Jakub Dawidek }
11932115b10SPawel Jakub Dawidek 
12032115b10SPawel Jakub Dawidek static int
1210b626a28SPawel Jakub Dawidek uds_client(const char *srcaddr, const char *dstaddr, void **ctxp)
12232115b10SPawel Jakub Dawidek {
1230b626a28SPawel Jakub Dawidek 	int ret;
12432115b10SPawel Jakub Dawidek 
1250b626a28SPawel Jakub Dawidek 	ret = uds_common_setup(dstaddr, ctxp, UDS_SIDE_CLIENT);
1260b626a28SPawel Jakub Dawidek 	if (ret != 0)
1270b626a28SPawel Jakub Dawidek 		return (ret);
1280b626a28SPawel Jakub Dawidek 
1290b626a28SPawel Jakub Dawidek 	PJDLOG_ASSERT(srcaddr == NULL);
1300b626a28SPawel Jakub Dawidek 
1310b626a28SPawel Jakub Dawidek 	return (0);
13232115b10SPawel Jakub Dawidek }
13332115b10SPawel Jakub Dawidek 
13432115b10SPawel Jakub Dawidek static int
1359d70b24bSPawel Jakub Dawidek uds_connect(void *ctx, int timeout)
13632115b10SPawel Jakub Dawidek {
13732115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
13832115b10SPawel Jakub Dawidek 
1392ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
1402ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
1412ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
1422ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_fd >= 0);
1431c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(timeout >= -1);
14432115b10SPawel Jakub Dawidek 
14532115b10SPawel Jakub Dawidek 	if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
1462b1b224dSPawel Jakub Dawidek 	    sizeof(uctx->uc_sun)) == -1) {
14732115b10SPawel Jakub Dawidek 		return (errno);
14832115b10SPawel Jakub Dawidek 	}
14932115b10SPawel Jakub Dawidek 
15032115b10SPawel Jakub Dawidek 	return (0);
15132115b10SPawel Jakub Dawidek }
15232115b10SPawel Jakub Dawidek 
15332115b10SPawel Jakub Dawidek static int
1541c193322SPawel Jakub Dawidek uds_connect_wait(void *ctx, int timeout)
1551c193322SPawel Jakub Dawidek {
1561c193322SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
1571c193322SPawel Jakub Dawidek 
1581c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
1591c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
1601c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT);
1611c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_fd >= 0);
1621c193322SPawel Jakub Dawidek 	PJDLOG_ASSERT(timeout >= 0);
1631c193322SPawel Jakub Dawidek 
1641c193322SPawel Jakub Dawidek 	return (0);
1651c193322SPawel Jakub Dawidek }
1661c193322SPawel Jakub Dawidek 
1671c193322SPawel Jakub Dawidek static int
16832115b10SPawel Jakub Dawidek uds_server(const char *addr, void **ctxp)
16932115b10SPawel Jakub Dawidek {
17032115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx;
17132115b10SPawel Jakub Dawidek 	int ret;
17232115b10SPawel Jakub Dawidek 
17332115b10SPawel Jakub Dawidek 	ret = uds_common_setup(addr, ctxp, UDS_SIDE_SERVER_LISTEN);
17432115b10SPawel Jakub Dawidek 	if (ret != 0)
17532115b10SPawel Jakub Dawidek 		return (ret);
17632115b10SPawel Jakub Dawidek 
17732115b10SPawel Jakub Dawidek 	uctx = *ctxp;
17832115b10SPawel Jakub Dawidek 
179f431ab18SPawel Jakub Dawidek 	(void)unlink(uctx->uc_sun.sun_path);
18032115b10SPawel Jakub Dawidek 	if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun,
1812b1b224dSPawel Jakub Dawidek 	    sizeof(uctx->uc_sun)) == -1) {
18232115b10SPawel Jakub Dawidek 		ret = errno;
18332115b10SPawel Jakub Dawidek 		uds_close(uctx);
18432115b10SPawel Jakub Dawidek 		return (ret);
18532115b10SPawel Jakub Dawidek 	}
186f431ab18SPawel Jakub Dawidek 	uctx->uc_owner = getpid();
1872b1b224dSPawel Jakub Dawidek 	if (listen(uctx->uc_fd, 8) == -1) {
18832115b10SPawel Jakub Dawidek 		ret = errno;
18932115b10SPawel Jakub Dawidek 		uds_close(uctx);
19032115b10SPawel Jakub Dawidek 		return (ret);
19132115b10SPawel Jakub Dawidek 	}
19232115b10SPawel Jakub Dawidek 
19332115b10SPawel Jakub Dawidek 	return (0);
19432115b10SPawel Jakub Dawidek }
19532115b10SPawel Jakub Dawidek 
19632115b10SPawel Jakub Dawidek static int
19732115b10SPawel Jakub Dawidek uds_accept(void *ctx, void **newctxp)
19832115b10SPawel Jakub Dawidek {
19932115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
20032115b10SPawel Jakub Dawidek 	struct uds_ctx *newuctx;
20132115b10SPawel Jakub Dawidek 	socklen_t fromlen;
20232115b10SPawel Jakub Dawidek 	int ret;
20332115b10SPawel Jakub Dawidek 
2042ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2052ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
2062ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN);
2072ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_fd >= 0);
20832115b10SPawel Jakub Dawidek 
20932115b10SPawel Jakub Dawidek 	newuctx = malloc(sizeof(*newuctx));
21032115b10SPawel Jakub Dawidek 	if (newuctx == NULL)
21132115b10SPawel Jakub Dawidek 		return (errno);
21232115b10SPawel Jakub Dawidek 
213f431ab18SPawel Jakub Dawidek 	fromlen = sizeof(newuctx->uc_sun);
214f431ab18SPawel Jakub Dawidek 	newuctx->uc_fd = accept(uctx->uc_fd,
215f431ab18SPawel Jakub Dawidek 	    (struct sockaddr *)&newuctx->uc_sun, &fromlen);
2162b1b224dSPawel Jakub Dawidek 	if (newuctx->uc_fd == -1) {
21732115b10SPawel Jakub Dawidek 		ret = errno;
21832115b10SPawel Jakub Dawidek 		free(newuctx);
21932115b10SPawel Jakub Dawidek 		return (ret);
22032115b10SPawel Jakub Dawidek 	}
22132115b10SPawel Jakub Dawidek 
22232115b10SPawel Jakub Dawidek 	newuctx->uc_side = UDS_SIDE_SERVER_WORK;
22332115b10SPawel Jakub Dawidek 	newuctx->uc_magic = UDS_CTX_MAGIC;
22432115b10SPawel Jakub Dawidek 	*newctxp = newuctx;
22532115b10SPawel Jakub Dawidek 
22632115b10SPawel Jakub Dawidek 	return (0);
22732115b10SPawel Jakub Dawidek }
22832115b10SPawel Jakub Dawidek 
22932115b10SPawel Jakub Dawidek static int
23001ab52c0SPawel Jakub Dawidek uds_send(void *ctx, const unsigned char *data, size_t size, int fd)
23132115b10SPawel Jakub Dawidek {
23232115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
23332115b10SPawel Jakub Dawidek 
2342ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2352ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
2362ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_fd >= 0);
23732115b10SPawel Jakub Dawidek 
23801ab52c0SPawel Jakub Dawidek 	return (proto_common_send(uctx->uc_fd, data, size, fd));
23932115b10SPawel Jakub Dawidek }
24032115b10SPawel Jakub Dawidek 
24132115b10SPawel Jakub Dawidek static int
24201ab52c0SPawel Jakub Dawidek uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
24332115b10SPawel Jakub Dawidek {
24432115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
24532115b10SPawel Jakub Dawidek 
2462ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2472ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
2482ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_fd >= 0);
24932115b10SPawel Jakub Dawidek 
25001ab52c0SPawel Jakub Dawidek 	return (proto_common_recv(uctx->uc_fd, data, size, fdp));
2518046c499SPawel Jakub Dawidek }
2528046c499SPawel Jakub Dawidek 
2538046c499SPawel Jakub Dawidek static int
25432115b10SPawel Jakub Dawidek uds_descriptor(const void *ctx)
25532115b10SPawel Jakub Dawidek {
25632115b10SPawel Jakub Dawidek 	const struct uds_ctx *uctx = ctx;
25732115b10SPawel Jakub Dawidek 
2582ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2592ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
26032115b10SPawel Jakub Dawidek 
26132115b10SPawel Jakub Dawidek 	return (uctx->uc_fd);
26232115b10SPawel Jakub Dawidek }
26332115b10SPawel Jakub Dawidek 
26432115b10SPawel Jakub Dawidek static void
26532115b10SPawel Jakub Dawidek uds_local_address(const void *ctx, char *addr, size_t size)
26632115b10SPawel Jakub Dawidek {
26732115b10SPawel Jakub Dawidek 	const struct uds_ctx *uctx = ctx;
26832115b10SPawel Jakub Dawidek 	struct sockaddr_un sun;
26932115b10SPawel Jakub Dawidek 	socklen_t sunlen;
27032115b10SPawel Jakub Dawidek 
2712ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2722ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
2732ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(addr != NULL);
27432115b10SPawel Jakub Dawidek 
27532115b10SPawel Jakub Dawidek 	sunlen = sizeof(sun);
2762b1b224dSPawel Jakub Dawidek 	if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) == -1) {
2772c5dadc9SPawel Jakub Dawidek 		PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
27832115b10SPawel Jakub Dawidek 		return;
27932115b10SPawel Jakub Dawidek 	}
2802ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
28132115b10SPawel Jakub Dawidek 	if (sun.sun_path[0] == '\0') {
2822c5dadc9SPawel Jakub Dawidek 		PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
28332115b10SPawel Jakub Dawidek 		return;
28432115b10SPawel Jakub Dawidek 	}
2852c5dadc9SPawel Jakub Dawidek 	PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size);
28632115b10SPawel Jakub Dawidek }
28732115b10SPawel Jakub Dawidek 
28832115b10SPawel Jakub Dawidek static void
28932115b10SPawel Jakub Dawidek uds_remote_address(const void *ctx, char *addr, size_t size)
29032115b10SPawel Jakub Dawidek {
29132115b10SPawel Jakub Dawidek 	const struct uds_ctx *uctx = ctx;
29232115b10SPawel Jakub Dawidek 	struct sockaddr_un sun;
29332115b10SPawel Jakub Dawidek 	socklen_t sunlen;
29432115b10SPawel Jakub Dawidek 
2952ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
2962ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
2972ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(addr != NULL);
29832115b10SPawel Jakub Dawidek 
29932115b10SPawel Jakub Dawidek 	sunlen = sizeof(sun);
3002b1b224dSPawel Jakub Dawidek 	if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) == -1) {
3012c5dadc9SPawel Jakub Dawidek 		PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
30232115b10SPawel Jakub Dawidek 		return;
30332115b10SPawel Jakub Dawidek 	}
3042ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(sun.sun_family == AF_UNIX);
30532115b10SPawel Jakub Dawidek 	if (sun.sun_path[0] == '\0') {
3062c5dadc9SPawel Jakub Dawidek 		PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size);
30732115b10SPawel Jakub Dawidek 		return;
30832115b10SPawel Jakub Dawidek 	}
30932115b10SPawel Jakub Dawidek 	snprintf(addr, size, "uds://%s", sun.sun_path);
31032115b10SPawel Jakub Dawidek }
31132115b10SPawel Jakub Dawidek 
31232115b10SPawel Jakub Dawidek static void
31332115b10SPawel Jakub Dawidek uds_close(void *ctx)
31432115b10SPawel Jakub Dawidek {
31532115b10SPawel Jakub Dawidek 	struct uds_ctx *uctx = ctx;
31632115b10SPawel Jakub Dawidek 
3172ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx != NULL);
3182ec483c5SPawel Jakub Dawidek 	PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
31932115b10SPawel Jakub Dawidek 
32032115b10SPawel Jakub Dawidek 	if (uctx->uc_fd >= 0)
32132115b10SPawel Jakub Dawidek 		close(uctx->uc_fd);
322f431ab18SPawel Jakub Dawidek 	/*
323f431ab18SPawel Jakub Dawidek 	 * Unlink the socket only if we are the owner and this is descriptor
324f431ab18SPawel Jakub Dawidek 	 * we listen on.
325f431ab18SPawel Jakub Dawidek 	 */
326f431ab18SPawel Jakub Dawidek 	if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN &&
327f431ab18SPawel Jakub Dawidek 	    uctx->uc_owner == getpid()) {
328493812eeSPawel Jakub Dawidek 		PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0');
329493812eeSPawel Jakub Dawidek 		if (unlink(uctx->uc_sun.sun_path) == -1) {
330493812eeSPawel Jakub Dawidek 			pjdlog_errno(LOG_WARNING,
331493812eeSPawel Jakub Dawidek 			    "Unable to unlink socket file %s",
332493812eeSPawel Jakub Dawidek 			    uctx->uc_sun.sun_path);
333493812eeSPawel Jakub Dawidek 		}
334f431ab18SPawel Jakub Dawidek 	}
335f431ab18SPawel Jakub Dawidek 	uctx->uc_owner = 0;
33632115b10SPawel Jakub Dawidek 	uctx->uc_magic = 0;
33732115b10SPawel Jakub Dawidek 	free(uctx);
33832115b10SPawel Jakub Dawidek }
33932115b10SPawel Jakub Dawidek 
340e2eabb44SPawel Jakub Dawidek static struct proto uds_proto = {
341e2eabb44SPawel Jakub Dawidek 	.prt_name = "uds",
342e2eabb44SPawel Jakub Dawidek 	.prt_client = uds_client,
343e2eabb44SPawel Jakub Dawidek 	.prt_connect = uds_connect,
344e2eabb44SPawel Jakub Dawidek 	.prt_connect_wait = uds_connect_wait,
345e2eabb44SPawel Jakub Dawidek 	.prt_server = uds_server,
346e2eabb44SPawel Jakub Dawidek 	.prt_accept = uds_accept,
347e2eabb44SPawel Jakub Dawidek 	.prt_send = uds_send,
348e2eabb44SPawel Jakub Dawidek 	.prt_recv = uds_recv,
349e2eabb44SPawel Jakub Dawidek 	.prt_descriptor = uds_descriptor,
350e2eabb44SPawel Jakub Dawidek 	.prt_local_address = uds_local_address,
351e2eabb44SPawel Jakub Dawidek 	.prt_remote_address = uds_remote_address,
352e2eabb44SPawel Jakub Dawidek 	.prt_close = uds_close
35332115b10SPawel Jakub Dawidek };
35432115b10SPawel Jakub Dawidek 
35532115b10SPawel Jakub Dawidek static __constructor void
35632115b10SPawel Jakub Dawidek uds_ctor(void)
35732115b10SPawel Jakub Dawidek {
35832115b10SPawel Jakub Dawidek 
35950692f84SPawel Jakub Dawidek 	proto_register(&uds_proto, false);
36032115b10SPawel Jakub Dawidek }
361