1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/ctfs.h>
29 #include <sys/contract.h>
30 #include <string.h>
31 #include <libnvpair.h>
32 #include <assert.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <libcontract.h>
36 #include "libcontract_impl.h"
37
38 /*
39 * Common template routines
40 */
41
42 int
ct_tmpl_activate(int fd)43 ct_tmpl_activate(int fd)
44 {
45 if (ioctl(fd, CT_TACTIVATE) == -1)
46 return (errno);
47 return (0);
48 }
49
50 int
ct_tmpl_clear(int fd)51 ct_tmpl_clear(int fd)
52 {
53 if (ioctl(fd, CT_TCLEAR) == -1)
54 return (errno);
55 return (0);
56 }
57
58 int
ct_tmpl_create(int fd,ctid_t * ctidp)59 ct_tmpl_create(int fd, ctid_t *ctidp)
60 {
61 ctid_t ctid = ioctl(fd, CT_TCREATE);
62 if (ctid == -1)
63 return (errno);
64 *ctidp = ctid;
65 return (0);
66 }
67
68 int
ct_tmpl_set_internal(int fd,uint_t id,uintptr_t value)69 ct_tmpl_set_internal(int fd, uint_t id, uintptr_t value)
70 {
71 ct_param_t param;
72 uint64_t param_value = value;
73
74 param.ctpm_id = id;
75 param.ctpm_size = sizeof (uint64_t);
76 param.ctpm_value = ¶m_value;
77 if (ioctl(fd, CT_TSET, ¶m) == -1)
78 return (errno);
79
80 return (0);
81 }
82
83 int
ct_tmpl_set_internal_string(int fd,uint_t id,const char * value)84 ct_tmpl_set_internal_string(int fd, uint_t id, const char *value)
85 {
86 ct_param_t param;
87
88 if (value == NULL)
89 return (EINVAL);
90 param.ctpm_id = id;
91 param.ctpm_size = strlen(value) + 1;
92 param.ctpm_value = (void *)value;
93 if (ioctl(fd, CT_TSET, ¶m) == -1)
94 return (errno);
95
96 return (0);
97 }
98
99 int
ct_tmpl_set_critical(int fd,uint_t events)100 ct_tmpl_set_critical(int fd, uint_t events)
101 {
102 return (ct_tmpl_set_internal(fd, CTP_EV_CRITICAL, events));
103 }
104
105 int
ct_tmpl_set_informative(int fd,uint_t events)106 ct_tmpl_set_informative(int fd, uint_t events)
107 {
108 return (ct_tmpl_set_internal(fd, CTP_EV_INFO, events));
109 }
110
111 int
ct_tmpl_set_cookie(int fd,uint64_t cookie)112 ct_tmpl_set_cookie(int fd, uint64_t cookie)
113 {
114 ct_param_t param;
115 uint64_t param_value = cookie;
116
117 param.ctpm_id = CTP_COOKIE;
118 param.ctpm_size = sizeof (uint64_t);
119 param.ctpm_value = ¶m_value;
120 if (ioctl(fd, CT_TSET, ¶m) == -1)
121 return (errno);
122 return (0);
123 }
124
125 int
ct_tmpl_get_internal(int fd,uint_t id,uint_t * value)126 ct_tmpl_get_internal(int fd, uint_t id, uint_t *value)
127 {
128 ct_param_t param;
129 uint64_t param_value;
130
131 param.ctpm_id = id;
132 param.ctpm_size = sizeof (uint64_t);
133 param.ctpm_value = ¶m_value;
134 if (ioctl(fd, CT_TGET, ¶m) == -1)
135 return (errno);
136 *value = param_value;
137 return (0);
138 }
139
140 int
ct_tmpl_get_internal_string(int fd,uint32_t id,char * buf,size_t size)141 ct_tmpl_get_internal_string(int fd, uint32_t id, char *buf, size_t size)
142 {
143 ct_param_t param;
144
145 param.ctpm_id = id;
146 param.ctpm_size = size;
147 param.ctpm_value = buf;
148 if (ioctl(fd, CT_TGET, ¶m) == -1)
149 return (-1);
150 return (param.ctpm_size);
151 }
152
153 int
ct_tmpl_get_critical(int fd,uint_t * events)154 ct_tmpl_get_critical(int fd, uint_t *events)
155 {
156 return (ct_tmpl_get_internal(fd, CTP_EV_CRITICAL, events));
157 }
158
159 int
ct_tmpl_get_informative(int fd,uint_t * events)160 ct_tmpl_get_informative(int fd, uint_t *events)
161 {
162 return (ct_tmpl_get_internal(fd, CTP_EV_INFO, events));
163 }
164
165 int
ct_tmpl_get_cookie(int fd,uint64_t * cookie)166 ct_tmpl_get_cookie(int fd, uint64_t *cookie)
167 {
168 ct_param_t param;
169
170 param.ctpm_id = CTP_COOKIE;
171 param.ctpm_size = sizeof (uint64_t);
172 param.ctpm_value = cookie;
173 if (ioctl(fd, CT_TGET, ¶m) == -1)
174 return (errno);
175 return (0);
176 }
177
178 /*
179 * Common ctl routines
180 */
181
182 int
ct_ctl_adopt(int fd)183 ct_ctl_adopt(int fd)
184 {
185 if (ioctl(fd, CT_CADOPT) == -1)
186 return (errno);
187 return (0);
188 }
189
190 int
ct_ctl_abandon(int fd)191 ct_ctl_abandon(int fd)
192 {
193 if (ioctl(fd, CT_CABANDON) == -1)
194 return (errno);
195 return (0);
196 }
197
198 /*ARGSUSED*/
199 int
ct_ctl_newct(int cfd,ctevid_t evid,int tfd)200 ct_ctl_newct(int cfd, ctevid_t evid, int tfd)
201 {
202 if (ioctl(cfd, CT_CNEWCT, tfd) == -1)
203 return (errno);
204 return (0);
205 }
206
207 int
ct_ctl_ack(int fd,ctevid_t event)208 ct_ctl_ack(int fd, ctevid_t event)
209 {
210 if (ioctl(fd, CT_CACK, &event) == -1)
211 return (errno);
212 return (0);
213 }
214
215 int
ct_ctl_nack(int fd,ctevid_t event)216 ct_ctl_nack(int fd, ctevid_t event)
217 {
218 if (ioctl(fd, CT_CNACK, &event) == -1)
219 return (errno);
220 return (0);
221 }
222
223 int
ct_ctl_qack(int fd,ctevid_t event)224 ct_ctl_qack(int fd, ctevid_t event)
225 {
226 if (ioctl(fd, CT_CQREQ, &event) == -1)
227 return (errno);
228 return (0);
229 }
230
231 /*
232 * Common status routines
233 */
234
235 int
ct_status_read(int fd,int detail,ct_stathdl_t * stathdl)236 ct_status_read(int fd, int detail, ct_stathdl_t *stathdl)
237 {
238 char *status_buffer = NULL;
239 int status_nbytes = 0;
240 struct ctlib_status_info *info;
241 int error;
242
243 info = malloc(sizeof (struct ctlib_status_info));
244 if (info == NULL)
245 return (errno);
246
247 info->status.ctst_detail = detail;
248 if (detail != CTD_COMMON) {
249 for (;;) {
250 info->status.ctst_nbytes = status_nbytes;
251 info->status.ctst_buffer = status_buffer;
252 do
253 error = ioctl(fd, CT_SSTATUS, &info->status);
254 while (error == -1 && errno == EINTR);
255 if (error == -1)
256 goto errout;
257 if (info->status.ctst_nbytes <= status_nbytes)
258 break;
259
260 if (status_buffer)
261 free(status_buffer);
262 status_nbytes = info->status.ctst_nbytes;
263 status_buffer = malloc(status_nbytes);
264 if (status_buffer == NULL)
265 goto errout;
266 }
267 if ((errno = nvlist_unpack(info->status.ctst_buffer,
268 info->status.ctst_nbytes, &info->nvl, 0)) != 0)
269 goto errout;
270
271 free(status_buffer);
272 status_buffer = NULL;
273
274 } else {
275 info->status.ctst_nbytes = 0;
276 info->nvl = NULL;
277 if (ioctl(fd, CT_SSTATUS, &info->status) == -1)
278 goto errout;
279 }
280
281 *stathdl = info;
282 return (0);
283
284 errout:
285 error = errno;
286 if (status_buffer)
287 free(status_buffer);
288 if (info)
289 free(info);
290 return (error);
291 }
292
293 void
ct_status_free(ct_stathdl_t stathdl)294 ct_status_free(ct_stathdl_t stathdl)
295 {
296 struct ctlib_status_info *info = stathdl;
297
298 if (info->nvl) {
299 assert(info->status.ctst_detail != CTD_COMMON);
300 nvlist_free(info->nvl);
301 }
302
303 free(info);
304 }
305
306 ctid_t
ct_status_get_id(ct_stathdl_t stathdl)307 ct_status_get_id(ct_stathdl_t stathdl)
308 {
309 struct ctlib_status_info *info = stathdl;
310 return (info->status.ctst_id);
311 }
312
313 zoneid_t
ct_status_get_zoneid(ct_stathdl_t stathdl)314 ct_status_get_zoneid(ct_stathdl_t stathdl)
315 {
316 struct ctlib_status_info *info = stathdl;
317 return (info->status.ctst_zoneid);
318 }
319
320 const char *
ct_status_get_type(ct_stathdl_t stathdl)321 ct_status_get_type(ct_stathdl_t stathdl)
322 {
323 struct ctlib_status_info *info = stathdl;
324 return (types[info->status.ctst_type].type_name);
325 }
326
327 id_t
ct_status_get_holder(ct_stathdl_t stathdl)328 ct_status_get_holder(ct_stathdl_t stathdl)
329 {
330 struct ctlib_status_info *info = stathdl;
331 return (info->status.ctst_holder);
332 }
333
334 ctstate_t
ct_status_get_state(ct_stathdl_t stathdl)335 ct_status_get_state(ct_stathdl_t stathdl)
336 {
337 struct ctlib_status_info *info = stathdl;
338 return (info->status.ctst_state);
339 }
340
341 int
ct_status_get_nevents(ct_stathdl_t stathdl)342 ct_status_get_nevents(ct_stathdl_t stathdl)
343 {
344 struct ctlib_status_info *info = stathdl;
345 return (info->status.ctst_nevents);
346 }
347
348 int
ct_status_get_ntime(ct_stathdl_t stathdl)349 ct_status_get_ntime(ct_stathdl_t stathdl)
350 {
351 struct ctlib_status_info *info = stathdl;
352 return (info->status.ctst_ntime);
353 }
354
355 int
ct_status_get_qtime(ct_stathdl_t stathdl)356 ct_status_get_qtime(ct_stathdl_t stathdl)
357 {
358 struct ctlib_status_info *info = stathdl;
359 return (info->status.ctst_qtime);
360 }
361
362 ctevid_t
ct_status_get_nevid(ct_stathdl_t stathdl)363 ct_status_get_nevid(ct_stathdl_t stathdl)
364 {
365 struct ctlib_status_info *info = stathdl;
366 return (info->status.ctst_nevid);
367 }
368
369 uint_t
ct_status_get_informative(ct_stathdl_t stathdl)370 ct_status_get_informative(ct_stathdl_t stathdl)
371 {
372 struct ctlib_status_info *info = stathdl;
373 return (info->status.ctst_informative);
374 }
375
376 uint_t
ct_status_get_critical(ct_stathdl_t stathdl)377 ct_status_get_critical(ct_stathdl_t stathdl)
378 {
379 struct ctlib_status_info *info = stathdl;
380 return (info->status.ctst_critical);
381 }
382
383 uint64_t
ct_status_get_cookie(ct_stathdl_t stathdl)384 ct_status_get_cookie(ct_stathdl_t stathdl)
385 {
386 struct ctlib_status_info *info = stathdl;
387 return (info->status.ctst_cookie);
388 }
389
390 /*
391 * Common event routines
392 */
393
394 static int
unpack_and_merge(nvlist_t ** nvl,char * buffer,size_t len)395 unpack_and_merge(nvlist_t **nvl, char *buffer, size_t len)
396 {
397 nvlist_t *tmpnvl;
398 int error;
399
400 if ((error = nvlist_unpack(buffer, len, &tmpnvl, 0)) != 0)
401 return (error);
402
403 if (*nvl == NULL) {
404 *nvl = tmpnvl;
405 return (0);
406 }
407
408 error = nvlist_merge(*nvl, tmpnvl, 0);
409 nvlist_free(tmpnvl);
410 return (error);
411 }
412
413 static int
ct_event_read_internal(int fd,int cmd,ct_evthdl_t * evt)414 ct_event_read_internal(int fd, int cmd, ct_evthdl_t *evt)
415 {
416 char *event_buffer = NULL;
417 int event_nbytes = 0;
418 struct ctlib_event_info *info;
419 ct_event_t *event;
420 int error;
421
422 info = malloc(sizeof (struct ctlib_event_info));
423 if (info == NULL)
424 return (errno);
425 info->nvl = NULL;
426 event = &info->event;
427
428 for (;;) {
429 event->ctev_nbytes = event_nbytes;
430 event->ctev_buffer = event_buffer;
431 do
432 error = ioctl(fd, cmd, event);
433 while (error == -1 && errno == EINTR);
434 if (error == -1) {
435 error = errno;
436 goto errout;
437 }
438 if (event->ctev_nbytes <= event_nbytes)
439 break;
440
441 if (event_buffer)
442 free(event_buffer);
443 event_nbytes = event->ctev_nbytes;
444 event_buffer = malloc(event_nbytes);
445 if (event_buffer == NULL) {
446 error = errno;
447 goto errout;
448 }
449 }
450
451 if (event->ctev_goffset > 0 && (error = unpack_and_merge(&info->nvl,
452 event->ctev_buffer, event->ctev_goffset)) != 0)
453 goto errout;
454
455 if (event->ctev_goffset < event->ctev_nbytes &&
456 (error = unpack_and_merge(&info->nvl,
457 event->ctev_buffer + event->ctev_goffset,
458 event->ctev_nbytes - event->ctev_goffset)) != 0)
459 goto errout;
460
461 free(event_buffer);
462
463 *evt = info;
464 return (0);
465
466 errout:
467 if (event_buffer)
468 free(event_buffer);
469 if (info) {
470 if (info->nvl)
471 nvlist_free(info->nvl);
472 free(info);
473 }
474 return (error);
475 }
476
477 int
ct_event_read(int fd,ct_evthdl_t * evthdl)478 ct_event_read(int fd, ct_evthdl_t *evthdl)
479 {
480 return (ct_event_read_internal(fd, CT_ERECV, evthdl));
481 }
482
483 int
ct_event_read_critical(int fd,ct_evthdl_t * evthdl)484 ct_event_read_critical(int fd, ct_evthdl_t *evthdl)
485 {
486 return (ct_event_read_internal(fd, CT_ECRECV, evthdl));
487 }
488
489 int
ct_event_reset(int fd)490 ct_event_reset(int fd)
491 {
492 if (ioctl(fd, CT_ERESET) == -1)
493 return (errno);
494 return (0);
495 }
496
497 int
ct_event_reliable(int fd)498 ct_event_reliable(int fd)
499 {
500 if (ioctl(fd, CT_ERELIABLE) == -1)
501 return (errno);
502 return (0);
503 }
504
505 void
ct_event_free(ct_evthdl_t evthdl)506 ct_event_free(ct_evthdl_t evthdl)
507 {
508 struct ctlib_event_info *info = evthdl;
509
510 if (info->nvl)
511 nvlist_free(info->nvl);
512 free(info);
513 }
514
515
516 uint_t
ct_event_get_flags(ct_evthdl_t evthdl)517 ct_event_get_flags(ct_evthdl_t evthdl)
518 {
519 struct ctlib_event_info *info = evthdl;
520 return (info->event.ctev_flags);
521 }
522
523 ctid_t
ct_event_get_ctid(ct_evthdl_t evthdl)524 ct_event_get_ctid(ct_evthdl_t evthdl)
525 {
526 struct ctlib_event_info *info = evthdl;
527 return (info->event.ctev_id);
528 }
529
530 ctevid_t
ct_event_get_evid(ct_evthdl_t evthdl)531 ct_event_get_evid(ct_evthdl_t evthdl)
532 {
533 struct ctlib_event_info *info = evthdl;
534 return (info->event.ctev_evid);
535 }
536
537 uint_t
ct_event_get_type(ct_evthdl_t evthdl)538 ct_event_get_type(ct_evthdl_t evthdl)
539 {
540 struct ctlib_event_info *info = evthdl;
541 return (info->event.ctev_type);
542 }
543
544 int
ct_event_get_nevid(ct_evthdl_t evthdl,ctevid_t * evidp)545 ct_event_get_nevid(ct_evthdl_t evthdl, ctevid_t *evidp)
546 {
547 struct ctlib_event_info *info = evthdl;
548 if (info->nvl == NULL ||
549 nvlist_lookup_uint64(info->nvl, CTS_NEVID, evidp))
550 return (EINVAL);
551 return (0);
552 }
553
554 int
ct_event_get_newct(ct_evthdl_t evthdl,ctid_t * ctidp)555 ct_event_get_newct(ct_evthdl_t evthdl, ctid_t *ctidp)
556 {
557 struct ctlib_event_info *info = evthdl;
558 if (info->nvl == NULL ||
559 nvlist_lookup_int32(info->nvl, CTS_NEWCT, (int *)ctidp))
560 return (EINVAL);
561 return (0);
562 }
563