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