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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <door.h> 26 #include <errno.h> 27 #include <assert.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <zone.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <sys/aggr.h> 37 #include <sys/mman.h> 38 #include <fcntl.h> 39 #include <libdladm.h> 40 #include <libdladm_impl.h> 41 #include <libdllink.h> 42 #include <libdlmgmt.h> 43 44 /* 45 * Table of data type sizes indexed by dladm_datatype_t. 46 */ 47 static size_t dladm_datatype_size[] = { 48 0, /* DLADM_TYPE_STR, use strnlen() */ 49 sizeof (boolean_t), /* DLADM_TYPE_BOOLEAN */ 50 sizeof (uint64_t) /* DLADM_TYPE_UINT64 */ 51 }; 52 53 static dladm_status_t 54 dladm_door_call(dladm_handle_t handle, void *arg, size_t asize, void *rbuf, 55 size_t *rsizep) 56 { 57 door_arg_t darg; 58 int door_fd; 59 dladm_status_t status; 60 boolean_t reopen = B_FALSE; 61 62 darg.data_ptr = arg; 63 darg.data_size = asize; 64 darg.desc_ptr = NULL; 65 darg.desc_num = 0; 66 darg.rbuf = rbuf; 67 darg.rsize = *rsizep; 68 69 reopen: 70 /* The door descriptor is opened if it isn't already */ 71 if ((status = dladm_door_fd(handle, &door_fd)) != DLADM_STATUS_OK) 72 return (status); 73 if (door_call(door_fd, &darg) == -1) { 74 /* 75 * Stale door descriptor is possible if dlmgmtd was re-started 76 * since last door_fd open so try re-opening door file. 77 */ 78 if (!reopen && errno == EBADF) { 79 (void) close(handle->door_fd); 80 handle->door_fd = -1; 81 reopen = B_TRUE; 82 goto reopen; 83 } 84 status = dladm_errno2status(errno); 85 } 86 if (status != DLADM_STATUS_OK) 87 return (status); 88 89 if (darg.rbuf != rbuf) { 90 /* 91 * The size of the input rbuf is not big enough so that 92 * the door allocate the rbuf itself. In this case, return 93 * the required size to the caller. 94 */ 95 (void) munmap(darg.rbuf, darg.rsize); 96 *rsizep = darg.rsize; 97 return (DLADM_STATUS_TOOSMALL); 98 } else if (darg.rsize != *rsizep) { 99 return (DLADM_STATUS_FAILED); 100 } 101 102 return (dladm_errno2status(((dlmgmt_retval_t *)rbuf)->lr_err)); 103 } 104 105 /* 106 * Allocate a new linkid with the given name. Return the new linkid. 107 */ 108 dladm_status_t 109 dladm_create_datalink_id(dladm_handle_t handle, const char *link, 110 datalink_class_t class, uint32_t media, uint32_t flags, 111 datalink_id_t *linkidp) 112 { 113 dlmgmt_door_createid_t createid; 114 dlmgmt_createid_retval_t retval; 115 uint32_t dlmgmt_flags; 116 dladm_status_t status; 117 size_t sz = sizeof (retval); 118 119 if (link == NULL || class == DATALINK_CLASS_ALL || 120 !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) || 121 linkidp == NULL) { 122 return (DLADM_STATUS_BADARG); 123 } 124 125 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0; 126 dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0; 127 128 (void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN); 129 createid.ld_class = class; 130 createid.ld_media = media; 131 createid.ld_flags = dlmgmt_flags; 132 createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID; 133 createid.ld_prefix = (flags & DLADM_OPT_PREFIX); 134 135 if ((status = dladm_door_call(handle, &createid, sizeof (createid), 136 &retval, &sz)) == DLADM_STATUS_OK) { 137 *linkidp = retval.lr_linkid; 138 } 139 return (status); 140 } 141 142 /* 143 * Destroy the given link ID. 144 */ 145 dladm_status_t 146 dladm_destroy_datalink_id(dladm_handle_t handle, datalink_id_t linkid, 147 uint32_t flags) 148 { 149 dlmgmt_door_destroyid_t destroyid; 150 dlmgmt_destroyid_retval_t retval; 151 uint32_t dlmgmt_flags; 152 size_t sz = sizeof (retval); 153 154 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0; 155 dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0); 156 157 destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID; 158 destroyid.ld_linkid = linkid; 159 destroyid.ld_flags = dlmgmt_flags; 160 161 return (dladm_door_call(handle, &destroyid, sizeof (destroyid), 162 &retval, &sz)); 163 } 164 165 /* 166 * Remap a given link ID to a new name. 167 */ 168 dladm_status_t 169 dladm_remap_datalink_id(dladm_handle_t handle, datalink_id_t linkid, 170 const char *link) 171 { 172 dlmgmt_door_remapid_t remapid; 173 dlmgmt_remapid_retval_t retval; 174 size_t sz = sizeof (retval); 175 176 remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID; 177 remapid.ld_linkid = linkid; 178 (void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN); 179 180 return (dladm_door_call(handle, &remapid, sizeof (remapid), 181 &retval, &sz)); 182 } 183 184 /* 185 * Make a given link ID active. 186 */ 187 dladm_status_t 188 dladm_up_datalink_id(dladm_handle_t handle, datalink_id_t linkid) 189 { 190 dlmgmt_door_upid_t upid; 191 dlmgmt_upid_retval_t retval; 192 size_t sz = sizeof (retval); 193 194 upid.ld_cmd = DLMGMT_CMD_UP_LINKID; 195 upid.ld_linkid = linkid; 196 197 return (dladm_door_call(handle, &upid, sizeof (upid), &retval, &sz)); 198 } 199 200 /* 201 * Create a new link with the given name. Return the new link's handle 202 */ 203 dladm_status_t 204 dladm_create_conf(dladm_handle_t handle, const char *link, datalink_id_t linkid, 205 datalink_class_t class, uint32_t media, dladm_conf_t *confp) 206 { 207 dlmgmt_door_createconf_t createconf; 208 dlmgmt_createconf_retval_t retval; 209 dladm_status_t status; 210 size_t sz = sizeof (retval); 211 212 if (link == NULL || confp == NULL) 213 return (DLADM_STATUS_BADARG); 214 215 (void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN); 216 createconf.ld_class = class; 217 createconf.ld_media = media; 218 createconf.ld_linkid = linkid; 219 createconf.ld_cmd = DLMGMT_CMD_CREATECONF; 220 confp->ds_confid = DLADM_INVALID_CONF; 221 222 if ((status = dladm_door_call(handle, &createconf, sizeof (createconf), 223 &retval, &sz)) == DLADM_STATUS_OK) { 224 confp->ds_readonly = B_FALSE; 225 confp->ds_confid = retval.lr_confid; 226 } 227 return (status); 228 } 229 230 /* 231 * An active physical link reported by the dlmgmtd daemon might not be active 232 * anymore as this link might be removed during system shutdown. Check its 233 * real status by calling dladm_phys_info(). 234 */ 235 dladm_status_t 236 i_dladm_phys_status(dladm_handle_t handle, datalink_id_t linkid, 237 uint32_t *flagsp) 238 { 239 dladm_phys_attr_t dpa; 240 dladm_status_t status; 241 242 assert((*flagsp) & DLMGMT_ACTIVE); 243 244 status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE); 245 if (status == DLADM_STATUS_NOTFOUND) { 246 /* 247 * No active status, this link was removed. Update its status 248 * in the daemon and delete all active linkprops. 249 * 250 * Note that the operation could fail. If it does, return 251 * failure now since otherwise dladm_set_linkprop() might 252 * call back to i_dladm_phys_status() recursively. 253 */ 254 if ((status = dladm_destroy_datalink_id(handle, linkid, 255 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) 256 return (status); 257 258 (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0, 259 DLADM_OPT_ACTIVE); 260 261 (*flagsp) &= ~DLMGMT_ACTIVE; 262 status = DLADM_STATUS_OK; 263 } 264 return (status); 265 } 266 267 /* 268 * Walk each entry in the data link configuration repository and 269 * call fn on the linkid and arg. 270 */ 271 dladm_status_t 272 dladm_walk_datalink_id(int (*fn)(dladm_handle_t, datalink_id_t, void *), 273 dladm_handle_t handle, void *argp, datalink_class_t class, 274 datalink_media_t dmedia, uint32_t flags) 275 { 276 dlmgmt_door_getnext_t getnext; 277 dlmgmt_getnext_retval_t retval; 278 uint32_t dlmgmt_flags; 279 datalink_id_t linkid = DATALINK_INVALID_LINKID; 280 dladm_status_t status = DLADM_STATUS_OK; 281 size_t sz = sizeof (retval); 282 283 if (fn == NULL) 284 return (DLADM_STATUS_BADARG); 285 286 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0; 287 dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0); 288 289 getnext.ld_cmd = DLMGMT_CMD_GETNEXT; 290 getnext.ld_class = class; 291 getnext.ld_dmedia = dmedia; 292 getnext.ld_flags = dlmgmt_flags; 293 294 do { 295 getnext.ld_linkid = linkid; 296 if ((status = dladm_door_call(handle, &getnext, 297 sizeof (getnext), &retval, &sz)) != DLADM_STATUS_OK) { 298 /* 299 * Done with walking. If no next datalink is found, 300 * return success. 301 */ 302 if (status == DLADM_STATUS_NOTFOUND) 303 status = DLADM_STATUS_OK; 304 break; 305 } 306 307 linkid = retval.lr_linkid; 308 if ((retval.lr_class == DATALINK_CLASS_PHYS) && 309 (retval.lr_flags & DLMGMT_ACTIVE)) { 310 /* 311 * An active physical link reported by the dlmgmtd 312 * daemon might not be active anymore. Check its 313 * real status. 314 */ 315 if (i_dladm_phys_status(handle, linkid, 316 &retval.lr_flags) != DLADM_STATUS_OK) { 317 continue; 318 } 319 320 if (!(dlmgmt_flags & retval.lr_flags)) 321 continue; 322 } 323 324 if (fn(handle, linkid, argp) == DLADM_WALK_TERMINATE) 325 break; 326 } while (linkid != DATALINK_INVALID_LINKID); 327 328 return (status); 329 } 330 331 /* 332 * Get a handle of a copy of the link configuration (kept in the daemon) 333 * for the given link so it can be updated later by dladm_write_conf(). 334 */ 335 dladm_status_t 336 dladm_open_conf(dladm_handle_t handle, datalink_id_t linkid, 337 dladm_conf_t *confp) 338 { 339 dlmgmt_door_openconf_t openconf; 340 dlmgmt_openconf_retval_t retval; 341 dladm_status_t status; 342 size_t sz; 343 344 if (linkid == DATALINK_INVALID_LINKID || confp == NULL) 345 return (DLADM_STATUS_BADARG); 346 347 sz = sizeof (retval); 348 openconf.ld_linkid = linkid; 349 openconf.ld_cmd = DLMGMT_CMD_OPENCONF; 350 confp->ds_confid = DLADM_INVALID_CONF; 351 if ((status = dladm_door_call(handle, &openconf, 352 sizeof (openconf), &retval, &sz)) == DLADM_STATUS_OK) { 353 confp->ds_readonly = B_FALSE; 354 confp->ds_confid = retval.lr_confid; 355 } 356 357 return (status); 358 } 359 360 /* 361 * Get the handle of a local snapshot of the link configuration. Note that 362 * any operations with this handle are read-only, i.e., one can not update 363 * the configuration with this handle. 364 */ 365 dladm_status_t 366 dladm_getsnap_conf(dladm_handle_t handle, datalink_id_t linkid, 367 dladm_conf_t *confp) 368 { 369 dlmgmt_door_getconfsnapshot_t snapshot; 370 dlmgmt_getconfsnapshot_retval_t *retvalp; 371 char *nvlbuf; 372 dladm_status_t status; 373 int err; 374 size_t sz; 375 376 if (linkid == DATALINK_INVALID_LINKID || confp == NULL) 377 return (DLADM_STATUS_BADARG); 378 379 sz = sizeof (dlmgmt_getconfsnapshot_retval_t); 380 snapshot.ld_linkid = linkid; 381 snapshot.ld_cmd = DLMGMT_CMD_GETCONFSNAPSHOT; 382 again: 383 if ((retvalp = malloc(sz)) == NULL) 384 return (DLADM_STATUS_NOMEM); 385 386 if ((status = dladm_door_call(handle, &snapshot, sizeof (snapshot), 387 retvalp, &sz)) == DLADM_STATUS_TOOSMALL) { 388 free(retvalp); 389 goto again; 390 } 391 392 if (status != DLADM_STATUS_OK) { 393 free(retvalp); 394 return (status); 395 } 396 397 confp->ds_readonly = B_TRUE; 398 nvlbuf = (char *)retvalp + sizeof (dlmgmt_getconfsnapshot_retval_t); 399 if ((err = nvlist_unpack(nvlbuf, retvalp->lr_nvlsz, 400 &(confp->ds_nvl), 0)) != 0) { 401 status = dladm_errno2status(err); 402 } 403 free(retvalp); 404 return (status); 405 } 406 407 /* 408 * Commit the given link to the data link configuration repository so 409 * that it will persist across reboots. 410 */ 411 dladm_status_t 412 dladm_write_conf(dladm_handle_t handle, dladm_conf_t conf) 413 { 414 dlmgmt_door_writeconf_t writeconf; 415 dlmgmt_writeconf_retval_t retval; 416 size_t sz = sizeof (retval); 417 418 if (conf.ds_confid == DLADM_INVALID_CONF) 419 return (DLADM_STATUS_BADARG); 420 421 if (conf.ds_readonly) 422 return (DLADM_STATUS_DENIED); 423 424 writeconf.ld_cmd = DLMGMT_CMD_WRITECONF; 425 writeconf.ld_confid = conf.ds_confid; 426 427 return (dladm_door_call(handle, &writeconf, sizeof (writeconf), 428 &retval, &sz)); 429 } 430 431 /* 432 * Given a dladm_conf_t, get the specific configuration field 433 * 434 * If the specified dladm_conf_t is a read-only snapshot of the configuration, 435 * get a specific link propertie from that snapshot (nvl), otherwise, get 436 * the link protperty from the dlmgmtd daemon using the given confid. 437 */ 438 dladm_status_t 439 dladm_get_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr, 440 void *attrval, size_t attrsz) 441 { 442 dladm_status_t status = DLADM_STATUS_OK; 443 444 if (attrval == NULL || attrsz == 0 || attr == NULL) 445 return (DLADM_STATUS_BADARG); 446 447 if (conf.ds_readonly) { 448 uchar_t *oattrval; 449 uint32_t oattrsz; 450 int err; 451 452 if ((err = nvlist_lookup_byte_array(conf.ds_nvl, (char *)attr, 453 &oattrval, &oattrsz)) != 0) { 454 return (dladm_errno2status(err)); 455 } 456 if (oattrsz > attrsz) 457 return (DLADM_STATUS_TOOSMALL); 458 459 bcopy(oattrval, attrval, oattrsz); 460 } else { 461 dlmgmt_door_getattr_t getattr; 462 dlmgmt_getattr_retval_t retval; 463 size_t sz = sizeof (retval); 464 465 if (conf.ds_confid == DLADM_INVALID_CONF) 466 return (DLADM_STATUS_BADARG); 467 468 getattr.ld_cmd = DLMGMT_CMD_GETATTR; 469 getattr.ld_confid = conf.ds_confid; 470 (void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN); 471 472 if ((status = dladm_door_call(handle, &getattr, 473 sizeof (getattr), &retval, &sz)) != DLADM_STATUS_OK) { 474 return (status); 475 } 476 477 if (retval.lr_attrsz > attrsz) 478 return (DLADM_STATUS_TOOSMALL); 479 480 bcopy(retval.lr_attrval, attrval, retval.lr_attrsz); 481 } 482 return (status); 483 } 484 485 /* 486 * Get next property attribute from data link configuration repository. 487 * If last_attr is "", return the first property. 488 */ 489 /* ARGSUSED */ 490 dladm_status_t 491 dladm_getnext_conf_linkprop(dladm_handle_t handle, dladm_conf_t conf, 492 const char *last_attr, char *attr, void *attrval, size_t attrsz, 493 size_t *attrszp) 494 { 495 nvlist_t *nvl = conf.ds_nvl; 496 nvpair_t *last = NULL, *nvp; 497 uchar_t *oattrval; 498 uint32_t oattrsz; 499 int err; 500 501 if (nvl == NULL || attrval == NULL || attrsz == 0 || attr == NULL || 502 !conf.ds_readonly) 503 return (DLADM_STATUS_BADARG); 504 505 while ((nvp = nvlist_next_nvpair(nvl, last)) != NULL) { 506 if (last_attr[0] == '\0') 507 break; 508 if (last != NULL && strcmp(last_attr, nvpair_name(last)) == 0) 509 break; 510 last = nvp; 511 } 512 513 if (nvp == NULL) 514 return (DLADM_STATUS_NOTFOUND); 515 516 if ((err = nvpair_value_byte_array(nvp, (uchar_t **)&oattrval, 517 &oattrsz)) != 0) { 518 return (dladm_errno2status(err)); 519 } 520 521 *attrszp = oattrsz; 522 if (oattrsz > attrsz) 523 return (DLADM_STATUS_TOOSMALL); 524 525 (void) strlcpy(attr, nvpair_name(nvp), MAXLINKATTRLEN); 526 bcopy(oattrval, attrval, oattrsz); 527 return (DLADM_STATUS_OK); 528 } 529 530 /* 531 * Get the link ID that is associated with the given name. 532 */ 533 dladm_status_t 534 dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp, 535 uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap) 536 { 537 dlmgmt_door_getlinkid_t getlinkid; 538 dlmgmt_getlinkid_retval_t retval; 539 datalink_id_t linkid; 540 dladm_status_t status; 541 size_t sz = sizeof (retval); 542 543 getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; 544 (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); 545 546 if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid), 547 &retval, &sz)) != DLADM_STATUS_OK) { 548 return (status); 549 } 550 551 linkid = retval.lr_linkid; 552 if (retval.lr_class == DATALINK_CLASS_PHYS && 553 retval.lr_flags & DLMGMT_ACTIVE) { 554 /* 555 * An active physical link reported by the dlmgmtd daemon 556 * might not be active anymore. Check and set its real status. 557 */ 558 status = i_dladm_phys_status(handle, linkid, &retval.lr_flags); 559 if (status != DLADM_STATUS_OK) 560 return (status); 561 } 562 563 if (linkidp != NULL) 564 *linkidp = linkid; 565 if (flagp != NULL) { 566 *flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0; 567 *flagp |= (retval.lr_flags & DLMGMT_PERSIST) ? 568 DLADM_OPT_PERSIST : 0; 569 } 570 if (classp != NULL) 571 *classp = retval.lr_class; 572 if (mediap != NULL) 573 *mediap = retval.lr_media; 574 575 return (DLADM_STATUS_OK); 576 } 577 578 /* 579 * Get the link name that is associated with the given id. 580 */ 581 dladm_status_t 582 dladm_datalink_id2info(dladm_handle_t handle, datalink_id_t linkid, 583 uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap, char *link, 584 size_t len) 585 { 586 dlmgmt_door_getname_t getname; 587 dlmgmt_getname_retval_t retval; 588 dladm_status_t status; 589 size_t sz = sizeof (retval); 590 591 if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) || 592 (link == NULL && len != 0)) { 593 return (DLADM_STATUS_BADARG); 594 } 595 596 getname.ld_cmd = DLMGMT_CMD_GETNAME; 597 getname.ld_linkid = linkid; 598 if ((status = dladm_door_call(handle, &getname, sizeof (getname), 599 &retval, &sz)) != DLADM_STATUS_OK) { 600 return (status); 601 } 602 603 if (len != 0 && (strlen(retval.lr_link) + 1 > len)) 604 return (DLADM_STATUS_TOOSMALL); 605 606 if (retval.lr_class == DATALINK_CLASS_PHYS && 607 retval.lr_flags & DLMGMT_ACTIVE) { 608 /* 609 * An active physical link reported by the dlmgmtd daemon 610 * might not be active anymore. Check and set its real status. 611 */ 612 status = i_dladm_phys_status(handle, linkid, &retval.lr_flags); 613 if (status != DLADM_STATUS_OK) 614 return (status); 615 } 616 617 if (link != NULL) 618 (void) strlcpy(link, retval.lr_link, len); 619 if (classp != NULL) 620 *classp = retval.lr_class; 621 if (mediap != NULL) 622 *mediap = retval.lr_media; 623 if (flagp != NULL) { 624 *flagp = retval.lr_flags & DLMGMT_ACTIVE ? 625 DLADM_OPT_ACTIVE : 0; 626 *flagp |= (retval.lr_flags & DLMGMT_PERSIST) ? 627 DLADM_OPT_PERSIST : 0; 628 } 629 return (DLADM_STATUS_OK); 630 } 631 632 /* 633 * Set the given attr with the given attrval for the given link. 634 */ 635 dladm_status_t 636 dladm_set_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr, 637 dladm_datatype_t type, const void *attrval) 638 { 639 dlmgmt_door_setattr_t setattr; 640 dlmgmt_setattr_retval_t retval; 641 size_t attrsz; 642 size_t sz = sizeof (retval); 643 644 if (attr == NULL || attrval == NULL) 645 return (DLADM_STATUS_BADARG); 646 647 if (conf.ds_readonly) 648 return (DLADM_STATUS_DENIED); 649 650 if (type == DLADM_TYPE_STR) 651 attrsz = strlen(attrval) + 1; 652 else 653 attrsz = dladm_datatype_size[type]; 654 655 if (attrsz > MAXLINKATTRVALLEN) 656 return (DLADM_STATUS_TOOSMALL); 657 658 setattr.ld_cmd = DLMGMT_CMD_SETATTR; 659 setattr.ld_confid = conf.ds_confid; 660 (void) strlcpy(setattr.ld_attr, attr, MAXLINKATTRLEN); 661 setattr.ld_attrsz = (uint32_t)attrsz; 662 setattr.ld_type = type; 663 bcopy(attrval, &setattr.ld_attrval, attrsz); 664 665 return (dladm_door_call(handle, &setattr, sizeof (setattr), 666 &retval, &sz)); 667 } 668 669 /* 670 * Unset the given attr the given link. 671 */ 672 dladm_status_t 673 dladm_unset_conf_field(dladm_handle_t handle, dladm_conf_t conf, 674 const char *attr) 675 { 676 dlmgmt_door_unsetattr_t unsetattr; 677 dlmgmt_unsetattr_retval_t retval; 678 size_t sz = sizeof (retval); 679 680 if (attr == NULL) 681 return (DLADM_STATUS_BADARG); 682 683 if (conf.ds_readonly) 684 return (DLADM_STATUS_DENIED); 685 686 unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR; 687 unsetattr.ld_confid = conf.ds_confid; 688 (void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN); 689 690 return (dladm_door_call(handle, &unsetattr, sizeof (unsetattr), 691 &retval, &sz)); 692 } 693 694 /* 695 * Remove the given link ID and its entry from the data link configuration 696 * repository. 697 */ 698 dladm_status_t 699 dladm_remove_conf(dladm_handle_t handle, datalink_id_t linkid) 700 { 701 dlmgmt_door_removeconf_t removeconf; 702 dlmgmt_removeconf_retval_t retval; 703 size_t sz = sizeof (retval); 704 705 removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF; 706 removeconf.ld_linkid = linkid; 707 708 return (dladm_door_call(handle, &removeconf, sizeof (removeconf), 709 &retval, &sz)); 710 } 711 712 /* 713 * Free the contents of the link structure. 714 */ 715 void 716 dladm_destroy_conf(dladm_handle_t handle, dladm_conf_t conf) 717 { 718 dlmgmt_door_destroyconf_t dconf; 719 dlmgmt_destroyconf_retval_t retval; 720 size_t sz = sizeof (retval); 721 722 if (conf.ds_readonly) { 723 nvlist_free(conf.ds_nvl); 724 } else { 725 if (conf.ds_confid == DLADM_INVALID_CONF) 726 return; 727 728 dconf.ld_cmd = DLMGMT_CMD_DESTROYCONF; 729 dconf.ld_confid = conf.ds_confid; 730 731 (void) dladm_door_call(handle, &dconf, sizeof (dconf), 732 &retval, &sz); 733 } 734 } 735 736 dladm_status_t 737 dladm_zone_boot(dladm_handle_t handle, zoneid_t zoneid) 738 { 739 dlmgmt_door_zoneboot_t zoneboot; 740 dlmgmt_zoneboot_retval_t retval; 741 size_t sz = sizeof (retval); 742 743 zoneboot.ld_cmd = DLMGMT_CMD_ZONEBOOT; 744 zoneboot.ld_zoneid = zoneid; 745 return (dladm_door_call(handle, &zoneboot, sizeof (zoneboot), 746 &retval, &sz)); 747 } 748 749 dladm_status_t 750 dladm_zone_halt(dladm_handle_t handle, zoneid_t zoneid) 751 { 752 dlmgmt_door_zonehalt_t zonehalt; 753 dlmgmt_zonehalt_retval_t retval; 754 size_t sz = sizeof (retval); 755 756 zonehalt.ld_cmd = DLMGMT_CMD_ZONEHALT; 757 zonehalt.ld_zoneid = zoneid; 758 return (dladm_door_call(handle, &zonehalt, sizeof (zonehalt), 759 &retval, &sz)); 760 } 761