2 * Copyright (c) 2012-2013 The FreeBSD Foundation
3 * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/types.h>
35 #include <sys/socket.h>
37 #include <sys/procdesc.h>
46 #include "libcasper.h"
47 #include "libcasper_impl.h"
50 * Structure describing communication channel between two separated processes.
52 #define CAP_CHANNEL_MAGIC 0xcac8a31
55 * Magic value helps to ensure that a pointer to the right structure is
56 * passed to our functions.
59 /* Socket descriptor for IPC. */
61 /* Process descriptor for casper. */
66 cap_add_pd(cap_channel_t *chan, int pd)
79 int sock[2], serrno, pfd;
83 if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0,
88 pid = pdfork(&pfd, 0);
92 casper_main_loop(sock[1]);
97 chan = cap_wrap(sock[0]);
105 ret = cap_add_pd(chan, pfd);
123 if (!fd_is_valid(sock))
126 chan = malloc(sizeof(*chan));
128 chan->cch_sock = sock;
130 chan->cch_magic = CAP_CHANNEL_MAGIC;
137 cap_unwrap(cap_channel_t *chan)
141 assert(chan != NULL);
142 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
144 sock = chan->cch_sock;
145 if (chan->cch_pd != -1)
154 cap_clone(const cap_channel_t *chan)
156 cap_channel_t *newchan;
160 assert(chan != NULL);
161 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
163 nvl = nvlist_create(0);
164 nvlist_add_string(nvl, "cmd", "clone");
165 nvl = cap_xfer_nvlist(chan, nvl, 0);
168 if (nvlist_get_number(nvl, "error") != 0) {
169 errno = (int)nvlist_get_number(nvl, "error");
173 newsock = nvlist_take_descriptor(nvl, "sock");
175 newchan = cap_wrap(newsock);
176 if (newchan == NULL) {
188 cap_close(cap_channel_t *chan)
191 assert(chan != NULL);
192 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
195 if (chan->cch_pd != -1)
197 close(chan->cch_sock);
202 cap_sock(const cap_channel_t *chan)
205 assert(chan != NULL);
206 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
208 return (chan->cch_sock);
212 cap_limit_set(const cap_channel_t *chan, nvlist_t *limits)
217 nvlmsg = nvlist_create(0);
218 nvlist_add_string(nvlmsg, "cmd", "limit_set");
219 nvlist_add_nvlist(nvlmsg, "limits", limits);
220 nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0);
221 if (nvlmsg == NULL) {
222 nvlist_destroy(limits);
225 error = (int)nvlist_get_number(nvlmsg, "error");
226 nvlist_destroy(nvlmsg);
227 nvlist_destroy(limits);
236 cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp)
241 nvlmsg = nvlist_create(0);
242 nvlist_add_string(nvlmsg, "cmd", "limit_get");
243 nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0);
246 error = (int)nvlist_get_number(nvlmsg, "error");
248 nvlist_destroy(nvlmsg);
252 if (nvlist_exists_null(nvlmsg, "limits"))
255 *limitsp = nvlist_take_nvlist(nvlmsg, "limits");
256 nvlist_destroy(nvlmsg);
261 cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl)
264 assert(chan != NULL);
265 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
267 return (nvlist_send(chan->cch_sock, nvl));
271 cap_recv_nvlist(const cap_channel_t *chan, int flags)
274 assert(chan != NULL);
275 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
277 return (nvlist_recv(chan->cch_sock, flags));
281 cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags)
284 assert(chan != NULL);
285 assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
287 return (nvlist_xfer(chan->cch_sock, nvl, flags));
291 cap_service_open(const cap_channel_t *chan, const char *name)
293 cap_channel_t *newchan;
299 nvl = nvlist_create(0);
300 nvlist_add_string(nvl, "cmd", "open");
301 nvlist_add_string(nvl, "service", name);
302 nvl = cap_xfer_nvlist(chan, nvl, 0);
305 error = (int)nvlist_get_number(nvl, "error");
311 sock = nvlist_take_descriptor(nvl, "chanfd");
315 newchan = cap_wrap(sock);
327 cap_service_limit(const cap_channel_t *chan, const char * const *names,
333 limits = nvlist_create(0);
334 for (i = 0; i < nnames; i++)
335 nvlist_add_null(limits, names[i]);
336 return (cap_limit_set(chan, limits));