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