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