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