1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2012-2013 The FreeBSD Foundation
5 * Copyright (c) 2015-2017 Mariusz Zaborski <oshogbo@FreeBSD.org>
6 * All rights reserved.
7 *
8 * This software was developed by Pawel Jakub Dawidek under sponsorship from
9 * the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef	_LIBCASPER_H_
34#define	_LIBCASPER_H_
35
36#ifdef HAVE_CASPER
37#define WITH_CASPER
38#endif
39
40#include <sys/types.h>
41#include <sys/nv.h>
42
43#include <stdlib.h>
44#include <unistd.h>
45
46#define	CASPER_NO_UNIQ	0x00000001
47
48#ifndef	_NVLIST_T_DECLARED
49#define	_NVLIST_T_DECLARED
50struct nvlist;
51
52typedef struct nvlist nvlist_t;
53#endif
54
55#ifndef	_CAP_CHANNEL_T_DECLARED
56#define	_CAP_CHANNEL_T_DECLARED
57#ifdef WITH_CASPER
58struct cap_channel;
59
60typedef struct cap_channel cap_channel_t;
61#define	CASPER_SUPPORT	(1)
62#else
63struct cap_channel {
64	int cch_fd;
65	int cch_flags;
66};
67typedef struct cap_channel cap_channel_t;
68#define	CASPER_SUPPORT	(0)
69#endif /* ! WITH_CASPER */
70#endif /* ! _CAP_CHANNEL_T_DECLARED */
71
72__BEGIN_DECLS
73
74#ifdef WITH_CASPER
75int cap_channel_flags(const cap_channel_t *chan);
76#else
77static inline int
78cap_channel_flags(const cap_channel_t *chan)
79{
80
81	return (chan->cch_flags);
82}
83#endif
84
85static inline int
86channel_nvlist_flags(const cap_channel_t *chan)
87{
88	int flags;
89
90	flags = 0;
91	if ((cap_channel_flags(chan) & CASPER_NO_UNIQ) != 0)
92		flags |= NV_FLAG_NO_UNIQUE;
93
94	return (flags);
95}
96
97/*
98 * The functions opens unrestricted communication channel to Casper.
99 */
100#ifdef WITH_CASPER
101cap_channel_t *cap_init(void);
102#else
103static inline cap_channel_t *
104cap_init(void)
105{
106	cap_channel_t *chan;
107
108	chan = (cap_channel_t *)malloc(sizeof(*chan));
109	if (chan != NULL) {
110		chan->cch_fd = -1;
111	}
112	return (chan);
113}
114#endif
115
116/*
117 * The functions to communicate with service.
118 */
119#ifdef WITH_CASPER
120cap_channel_t	*cap_service_open(const cap_channel_t *chan, const char *name);
121int		 cap_service_limit(const cap_channel_t *chan,
122		    const char * const *names, size_t nnames);
123#else
124static inline cap_channel_t *
125cap_service_open(const cap_channel_t *chan __unused,
126    const char *name __unused)
127{
128
129	return (cap_init());
130}
131
132static inline int
133cap_service_limit(const cap_channel_t *chan __unused,
134    const char * const *names __unused, size_t nnames __unused)
135{
136
137	return (0);
138}
139#endif
140
141/*
142 * The function creates cap_channel_t based on the given socket.
143 */
144#ifdef WITH_CASPER
145cap_channel_t *cap_wrap(int sock, int flags);
146#else
147static inline cap_channel_t *
148cap_wrap(int sock, int flags)
149{
150	cap_channel_t *chan;
151
152	chan = cap_init();
153	if (chan != NULL) {
154		chan->cch_fd = sock;
155		chan->cch_flags = flags;
156	}
157	return (chan);
158}
159#endif
160
161/*
162 * The function returns communication socket and frees cap_channel_t.
163 */
164#ifdef WITH_CASPER
165int	cap_unwrap(cap_channel_t *chan, int *flags);
166#else
167static inline int
168cap_unwrap(cap_channel_t *chan)
169{
170	int fd;
171
172	fd = chan->cch_fd;
173	free(chan);
174	return (fd);
175}
176#endif
177
178/*
179 * The function clones the given capability.
180 */
181#ifdef WITH_CASPER
182cap_channel_t *cap_clone(const cap_channel_t *chan);
183#else
184static inline cap_channel_t *
185cap_clone(const cap_channel_t *chan)
186{
187	cap_channel_t *newchan;
188
189	newchan = cap_init();
190	if (newchan == NULL) {
191		return (NULL);
192	}
193
194	if (chan->cch_fd == -1) {
195		newchan->cch_fd = -1;
196	} else {
197		newchan->cch_fd = dup(chan->cch_fd);
198		if (newchan->cch_fd < 0) {
199			free(newchan);
200			newchan = NULL;
201		}
202	}
203	newchan->cch_flags = chan->cch_flags;
204
205	return (newchan);
206}
207#endif
208
209/*
210 * The function closes the given capability.
211 */
212#ifdef WITH_CASPER
213void	cap_close(cap_channel_t *chan);
214#else
215static inline void
216cap_close(cap_channel_t *chan)
217{
218
219	if (chan->cch_fd >= 0) {
220		close(chan->cch_fd);
221	}
222	free(chan);
223}
224#endif
225
226/*
227 * The function returns socket descriptor associated with the given
228 * cap_channel_t for use with select(2)/kqueue(2)/etc.
229 */
230#ifdef WITH_CASPER
231int	cap_sock(const cap_channel_t *chan);
232#else
233#define	cap_sock(chan)	(chan->cch_fd)
234#endif
235
236/*
237 * The function limits the given capability.
238 * It always destroys 'limits' on return.
239 */
240#ifdef WITH_CASPER
241int	cap_limit_set(const cap_channel_t *chan, nvlist_t *limits);
242#else
243static inline int
244cap_limit_set(const cap_channel_t *chan __unused,
245    nvlist_t *limits __unused)
246{
247
248	return (0);
249}
250#endif
251
252/*
253 * The function returns current limits of the given capability.
254 */
255#ifdef WITH_CASPER
256int	cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp);
257#else
258static inline int
259cap_limit_get(const cap_channel_t *chan __unused, nvlist_t **limitsp)
260{
261
262	*limitsp = nvlist_create(channel_nvlist_flags(chan));
263	return (0);
264}
265#endif
266
267/*
268 * Function sends nvlist over the given capability.
269 */
270#ifdef WITH_CASPER
271int	cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl);
272#else
273#define	cap_send_nvlist(chan, nvl)	(0)
274#endif
275
276/*
277 * Function receives nvlist over the given capability.
278 */
279#ifdef WITH_CASPER
280nvlist_t *cap_recv_nvlist(const cap_channel_t *chan);
281#else
282#define	cap_recv_nvlist(chan)		(nvlist_create(chan->cch_flags))
283#endif
284
285/*
286 * Function sends the given nvlist, destroys it and receives new nvlist in
287 * response over the given capability.
288 */
289#ifdef WITH_CASPER
290nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl);
291#else
292static inline nvlist_t *
293cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl)
294{
295
296	nvlist_destroy(nvl);
297	return (nvlist_create(channel_nvlist_flags(chan)));
298}
299#endif
300
301__END_DECLS
302
303#endif	/* !_LIBCASPER_H_ */
304