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