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
50 struct nvlist;
51
52 typedef struct nvlist nvlist_t;
53 #endif
54
55 #ifndef _CAP_CHANNEL_T_DECLARED
56 #define _CAP_CHANNEL_T_DECLARED
57 #ifdef WITH_CASPER
58 struct cap_channel;
59
60 typedef struct cap_channel cap_channel_t;
61 #define CASPER_SUPPORT (1)
62 #else
63 struct cap_channel {
64 int cch_fd;
65 int cch_flags;
66 };
67 typedef 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
75 int cap_channel_flags(const cap_channel_t *chan);
76 #else
77 static inline int
78 cap_channel_flags(const cap_channel_t *chan)
79 {
80
81 return (chan->cch_flags);
82 }
83 #endif
84
85 static inline int
channel_nvlist_flags(const cap_channel_t * chan)86 channel_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
101 cap_channel_t *cap_init(void);
102 #else
103 static inline cap_channel_t *
cap_init(void)104 cap_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
120 cap_channel_t *cap_service_open(const cap_channel_t *chan, const char *name);
121 int cap_service_limit(const cap_channel_t *chan,
122 const char * const *names, size_t nnames);
123 #else
124 static inline cap_channel_t *
cap_service_open(const cap_channel_t * chan __unused,const char * name __unused)125 cap_service_open(const cap_channel_t *chan __unused,
126 const char *name __unused)
127 {
128
129 return (cap_init());
130 }
131
132 static inline int
cap_service_limit(const cap_channel_t * chan __unused,const char * const * names __unused,size_t nnames __unused)133 cap_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
145 cap_channel_t *cap_wrap(int sock, int flags);
146 #else
147 static inline cap_channel_t *
cap_wrap(int sock,int flags)148 cap_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
165 int cap_unwrap(cap_channel_t *chan, int *flags);
166 #else
167 static inline int
cap_unwrap(cap_channel_t * chan)168 cap_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
182 cap_channel_t *cap_clone(const cap_channel_t *chan);
183 #else
184 static inline cap_channel_t *
cap_clone(const cap_channel_t * chan)185 cap_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
213 void cap_close(cap_channel_t *chan);
214 #else
215 static inline void
cap_close(cap_channel_t * chan)216 cap_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
231 int 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
241 int cap_limit_set(const cap_channel_t *chan, nvlist_t *limits);
242 #else
243 static inline int
cap_limit_set(const cap_channel_t * chan __unused,nvlist_t * limits __unused)244 cap_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
256 int cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp);
257 #else
258 static inline int
cap_limit_get(const cap_channel_t * chan __unused,nvlist_t ** limitsp)259 cap_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
271 int 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
280 nvlist_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
290 nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl);
291 #else
292 static inline nvlist_t *
cap_xfer_nvlist(const cap_channel_t * chan,nvlist_t * nvl)293 cap_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