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 */
25
26 #include <door.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <zone.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/aggr.h>
38 #include <sys/mman.h>
39 #include <fcntl.h>
40 #include <libdladm.h>
41 #include <libdladm_impl.h>
42 #include <libdllink.h>
43 #include <libdlmgmt.h>
44
45 /*
46 * Table of data type sizes indexed by dladm_datatype_t.
47 */
48 static size_t dladm_datatype_size[] = {
49 0, /* DLADM_TYPE_STR, use strnlen() */
50 sizeof (boolean_t), /* DLADM_TYPE_BOOLEAN */
51 sizeof (uint64_t) /* DLADM_TYPE_UINT64 */
52 };
53
54 static dladm_status_t
55 dladm_door_call(dladm_handle_t handle, void *arg, size_t asize, void *rbuf,
56 size_t *rsizep)
57 {
58 door_arg_t darg;
59 int door_fd;
60 dladm_status_t status;
61 boolean_t reopen = B_FALSE;
62
63 darg.data_ptr = arg;
64 darg.data_size = asize;
65 darg.desc_ptr = NULL;
66 darg.desc_num = 0;
67 darg.rbuf = rbuf;
68 darg.rsize = *rsizep;
69
70 reopen:
71 /* The door descriptor is opened if it isn't already */
72 if ((status = dladm_door_fd(handle, &door_fd)) != DLADM_STATUS_OK)
73 return (status);
74 if (door_call(door_fd, &darg) == -1) {
75 /*
76 * Stale door descriptor is possible if dlmgmtd was re-started
77 * since last door_fd open so try re-opening door file.
78 */
79 if (!reopen && errno == EBADF) {
80 (void) close(handle->door_fd);
81 handle->door_fd = -1;
82 reopen = B_TRUE;
83 goto reopen;
84 }
85 status = dladm_errno2status(errno);
86 }
87 if (status != DLADM_STATUS_OK)
88 return (status);
89
90 if (darg.rbuf != rbuf) {
91 /*
92 * The size of the input rbuf is not big enough so that
93 * the door allocate the rbuf itself. In this case, return
94 * the required size to the caller.
95 */
96 (void) munmap(darg.rbuf, darg.rsize);
97 *rsizep = darg.rsize;
98 return (DLADM_STATUS_TOOSMALL);
99 } else if (darg.rsize != *rsizep) {
100 return (DLADM_STATUS_FAILED);
101 }
102
103 return (dladm_errno2status(((dlmgmt_retval_t *)rbuf)->lr_err));
104 }
105
106 /*
107 * Allocate a new linkid with the given name. Return the new linkid.
108 */
109 dladm_status_t
110 dladm_create_datalink_id(dladm_handle_t handle, const char *link,
111 datalink_class_t class, uint32_t media, uint32_t flags,
112 datalink_id_t *linkidp)
113 {
114 dlmgmt_door_createid_t createid;
115 dlmgmt_createid_retval_t retval;
116 uint32_t dlmgmt_flags;
117 dladm_status_t status;
118 size_t sz = sizeof (retval);
119
120 if (link == NULL || class == DATALINK_CLASS_ALL ||
121 !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
122 linkidp == NULL) {
123 return (DLADM_STATUS_BADARG);
124 }
125
126 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
127 dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
128 dlmgmt_flags |= (flags & DLADM_OPT_TRANSIENT) ? DLMGMT_TRANSIENT : 0;
129
130 (void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
131 createid.ld_class = class;
132 createid.ld_media = media;
133 createid.ld_flags = dlmgmt_flags;
134 createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
135 createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
136
137 if ((status = dladm_door_call(handle, &createid, sizeof (createid),
138 &retval, &sz)) == DLADM_STATUS_OK) {
139 *linkidp = retval.lr_linkid;
140 }
141 return (status);
142 }
143
144 /*
145 * Destroy the given link ID.
146 */
147 dladm_status_t
148 dladm_destroy_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
149 uint32_t flags)
150 {
151 dlmgmt_door_destroyid_t destroyid;
152 dlmgmt_destroyid_retval_t retval;
153 uint32_t dlmgmt_flags;
154 size_t sz = sizeof (retval);
155
156 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
157 dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
158
159 destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
160 destroyid.ld_linkid = linkid;
161 destroyid.ld_flags = dlmgmt_flags;
162
163 return (dladm_door_call(handle, &destroyid, sizeof (destroyid),
164 &retval, &sz));
165 }
166
167 /*
168 * Remap a given link ID to a new name.
169 */
170 dladm_status_t
171 dladm_remap_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
172 const char *link)
173 {
174 dlmgmt_door_remapid_t remapid;
175 dlmgmt_remapid_retval_t retval;
176 size_t sz = sizeof (retval);
177
178 remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
179 remapid.ld_linkid = linkid;
180 (void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
181
182 return (dladm_door_call(handle, &remapid, sizeof (remapid),
183 &retval, &sz));
184 }
185
186 /*
187 * Make a given link ID active.
188 */
189 dladm_status_t
190 dladm_up_datalink_id(dladm_handle_t handle, datalink_id_t linkid)
191 {
192 dlmgmt_door_upid_t upid;
193 dlmgmt_upid_retval_t retval;
194 size_t sz = sizeof (retval);
195
196 upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
197 upid.ld_linkid = linkid;
198
199 return (dladm_door_call(handle, &upid, sizeof (upid), &retval, &sz));
200 }
201
202 /*
203 * Create a new link with the given name. Return the new link's handle
204 */
205 dladm_status_t
206 dladm_create_conf(dladm_handle_t handle, const char *link, datalink_id_t linkid,
207 datalink_class_t class, uint32_t media, dladm_conf_t *confp)
208 {
209 dlmgmt_door_createconf_t createconf;
210 dlmgmt_createconf_retval_t retval;
211 dladm_status_t status;
212 size_t sz = sizeof (retval);
213
214 if (link == NULL || confp == NULL)
215 return (DLADM_STATUS_BADARG);
216
217 (void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
218 createconf.ld_class = class;
219 createconf.ld_media = media;
220 createconf.ld_linkid = linkid;
221 createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
222 confp->ds_confid = DLADM_INVALID_CONF;
223
224 if ((status = dladm_door_call(handle, &createconf, sizeof (createconf),
225 &retval, &sz)) == DLADM_STATUS_OK) {
226 confp->ds_readonly = B_FALSE;
227 confp->ds_confid = retval.lr_confid;
228 }
229 return (status);
230 }
231
232 /*
233 * An active physical link reported by the dlmgmtd daemon might not be active
234 * anymore as this link might be removed during system shutdown. Check its
235 * real status by calling dladm_phys_info().
236 */
237 dladm_status_t
238 i_dladm_phys_status(dladm_handle_t handle, datalink_id_t linkid,
239 uint32_t *flagsp)
240 {
241 dladm_phys_attr_t dpa;
242 dladm_status_t status;
243
244 assert((*flagsp) & DLMGMT_ACTIVE);
245
246 status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE);
247 if (status == DLADM_STATUS_NOTFOUND) {
248 /*
249 * No active status, this link was removed. Update its status
250 * in the daemon and delete all active linkprops.
251 *
252 * Note that the operation could fail. If it does, return
253 * failure now since otherwise dladm_set_linkprop() might
254 * call back to i_dladm_phys_status() recursively.
255 */
256 if ((status = dladm_destroy_datalink_id(handle, linkid,
257 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
258 return (status);
259
260 (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
261 DLADM_OPT_ACTIVE);
262
263 (*flagsp) &= ~DLMGMT_ACTIVE;
264 status = DLADM_STATUS_OK;
265 }
266 return (status);
267 }
268
269 /*
270 * Walk each entry in the data link configuration repository and
271 * call fn on the linkid and arg.
272 */
273 dladm_status_t
274 dladm_walk_datalink_id(int (*fn)(dladm_handle_t, datalink_id_t, void *),
275 dladm_handle_t handle, void *argp, datalink_class_t class,
276 datalink_media_t dmedia, uint32_t flags)
277 {
278 dlmgmt_door_getnext_t getnext;
279 dlmgmt_getnext_retval_t retval;
280 uint32_t dlmgmt_flags;
281 datalink_id_t linkid = DATALINK_INVALID_LINKID;
282 dladm_status_t status = DLADM_STATUS_OK;
283 size_t sz = sizeof (retval);
284
285 if (fn == NULL)
286 return (DLADM_STATUS_BADARG);
287
288 dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
289 dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
290 dlmgmt_flags |= ((flags & DLADM_OPT_TRANSIENT) ? DLMGMT_TRANSIENT : 0);
291
292 getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
293 getnext.ld_class = class;
294 getnext.ld_dmedia = dmedia;
295 getnext.ld_flags = dlmgmt_flags;
296
297 do {
298 getnext.ld_linkid = linkid;
299 if ((status = dladm_door_call(handle, &getnext,
300 sizeof (getnext), &retval, &sz)) != DLADM_STATUS_OK) {
301 /*
302 * Done with walking. If no next datalink is found,
303 * return success.
304 */
305 if (status == DLADM_STATUS_NOTFOUND)
306 status = DLADM_STATUS_OK;
307 break;
308 }
309
310 linkid = retval.lr_linkid;
311 if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
312 (retval.lr_flags & DLMGMT_ACTIVE)) {
313 /*
314 * An active physical link reported by the dlmgmtd
315 * daemon might not be active anymore. Check its
316 * real status.
317 */
318 if (i_dladm_phys_status(handle, linkid,
319 &retval.lr_flags) != DLADM_STATUS_OK) {
320 continue;
321 }
322
323 if (!(dlmgmt_flags & retval.lr_flags))
324 continue;
325 }
326
327 if (fn(handle, linkid, argp) == DLADM_WALK_TERMINATE)
328 break;
329 } while (linkid != DATALINK_INVALID_LINKID);
330
331 return (status);
332 }
333
334 /*
335 * Get a handle of a copy of the link configuration (kept in the daemon)
336 * for the given link so it can be updated later by dladm_write_conf().
337 */
338 dladm_status_t
339 dladm_open_conf(dladm_handle_t handle, datalink_id_t linkid,
340 dladm_conf_t *confp)
341 {
342 dlmgmt_door_openconf_t openconf;
343 dlmgmt_openconf_retval_t retval;
344 dladm_status_t status;
345 size_t sz;
346
347 if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
348 return (DLADM_STATUS_BADARG);
349
350 sz = sizeof (retval);
351 openconf.ld_linkid = linkid;
352 openconf.ld_cmd = DLMGMT_CMD_OPENCONF;
353 confp->ds_confid = DLADM_INVALID_CONF;
354 if ((status = dladm_door_call(handle, &openconf,
355 sizeof (openconf), &retval, &sz)) == DLADM_STATUS_OK) {
356 confp->ds_readonly = B_FALSE;
357 confp->ds_confid = retval.lr_confid;
358 }
359
360 return (status);
361 }
362
363 /*
364 * Get the handle of a local snapshot of the link configuration. Note that
365 * any operations with this handle are read-only, i.e., one can not update
366 * the configuration with this handle.
367 */
368 dladm_status_t
369 dladm_getsnap_conf(dladm_handle_t handle, datalink_id_t linkid,
370 dladm_conf_t *confp)
371 {
372 dlmgmt_door_getconfsnapshot_t snapshot;
373 dlmgmt_getconfsnapshot_retval_t *retvalp;
374 char *nvlbuf;
375 dladm_status_t status;
376 int err;
377 size_t sz;
378
379 if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
380 return (DLADM_STATUS_BADARG);
381
382 sz = sizeof (dlmgmt_getconfsnapshot_retval_t);
383 snapshot.ld_linkid = linkid;
384 snapshot.ld_cmd = DLMGMT_CMD_GETCONFSNAPSHOT;
385 again:
386 if ((retvalp = malloc(sz)) == NULL)
387 return (DLADM_STATUS_NOMEM);
388
389 if ((status = dladm_door_call(handle, &snapshot, sizeof (snapshot),
390 retvalp, &sz)) == DLADM_STATUS_TOOSMALL) {
391 free(retvalp);
392 goto again;
393 }
394
395 if (status != DLADM_STATUS_OK) {
396 free(retvalp);
397 return (status);
398 }
399
400 confp->ds_readonly = B_TRUE;
401 nvlbuf = (char *)retvalp + sizeof (dlmgmt_getconfsnapshot_retval_t);
402 if ((err = nvlist_unpack(nvlbuf, retvalp->lr_nvlsz,
403 &(confp->ds_nvl), 0)) != 0) {
404 status = dladm_errno2status(err);
405 }
406 free(retvalp);
407 return (status);
408 }
409
410 /*
411 * Commit the given link to the data link configuration repository so
412 * that it will persist across reboots.
413 */
414 dladm_status_t
415 dladm_write_conf(dladm_handle_t handle, dladm_conf_t conf)
416 {
417 dlmgmt_door_writeconf_t writeconf;
418 dlmgmt_writeconf_retval_t retval;
419 size_t sz = sizeof (retval);
420
421 if (conf.ds_confid == DLADM_INVALID_CONF)
422 return (DLADM_STATUS_BADARG);
423
424 if (conf.ds_readonly)
425 return (DLADM_STATUS_DENIED);
426
427 writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
428 writeconf.ld_confid = conf.ds_confid;
429
430 return (dladm_door_call(handle, &writeconf, sizeof (writeconf),
431 &retval, &sz));
432 }
433
434 /*
435 * Given a dladm_conf_t, get the specific configuration field
436 *
437 * If the specified dladm_conf_t is a read-only snapshot of the configuration,
438 * get a specific link propertie from that snapshot (nvl), otherwise, get
439 * the link protperty from the dlmgmtd daemon using the given confid.
440 */
441 dladm_status_t
442 dladm_get_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr,
443 void *attrval, size_t attrsz)
444 {
445 dladm_status_t status = DLADM_STATUS_OK;
446
447 if (attrval == NULL || attrsz == 0 || attr == NULL)
448 return (DLADM_STATUS_BADARG);
449
450 if (conf.ds_readonly) {
451 uchar_t *oattrval;
452 uint32_t oattrsz;
453 int err;
454
455 if ((err = nvlist_lookup_byte_array(conf.ds_nvl, (char *)attr,
456 &oattrval, &oattrsz)) != 0) {
457 return (dladm_errno2status(err));
458 }
459 if (oattrsz > attrsz)
460 return (DLADM_STATUS_TOOSMALL);
461
462 bcopy(oattrval, attrval, oattrsz);
463 } else {
464 dlmgmt_door_getattr_t getattr;
465 dlmgmt_getattr_retval_t retval;
466 size_t sz = sizeof (retval);
467
468 if (conf.ds_confid == DLADM_INVALID_CONF)
469 return (DLADM_STATUS_BADARG);
470
471 getattr.ld_cmd = DLMGMT_CMD_GETATTR;
472 getattr.ld_confid = conf.ds_confid;
473 (void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
474
475 if ((status = dladm_door_call(handle, &getattr,
476 sizeof (getattr), &retval, &sz)) != DLADM_STATUS_OK) {
477 return (status);
478 }
479
480 if (retval.lr_attrsz > attrsz)
481 return (DLADM_STATUS_TOOSMALL);
482
483 bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
484 }
485 return (status);
486 }
487
488 /*
489 * Get next property attribute from data link configuration repository.
490 * If last_attr is "", return the first property.
491 */
492 dladm_status_t
493 dladm_getnext_conf_linkprop(dladm_handle_t handle __unused, dladm_conf_t conf,
494 const char *last_attr, char *attr, void *attrval, size_t attrsz,
495 size_t *attrszp)
496 {
497 nvlist_t *nvl = conf.ds_nvl;
498 nvpair_t *last = NULL, *nvp;
499 uchar_t *oattrval;
500 uint32_t oattrsz;
501 int err;
502
503 if (nvl == NULL || attrval == NULL || attrsz == 0 || attr == NULL ||
504 !conf.ds_readonly)
505 return (DLADM_STATUS_BADARG);
506
507 while ((nvp = nvlist_next_nvpair(nvl, last)) != NULL) {
508 if (last_attr[0] == '\0')
509 break;
510 if (last != NULL && strcmp(last_attr, nvpair_name(last)) == 0)
511 break;
512 last = nvp;
513 }
514
515 if (nvp == NULL)
516 return (DLADM_STATUS_NOTFOUND);
517
518 if ((err = nvpair_value_byte_array(nvp, (uchar_t **)&oattrval,
519 &oattrsz)) != 0) {
520 return (dladm_errno2status(err));
521 }
522
523 *attrszp = oattrsz;
524 if (oattrsz > attrsz)
525 return (DLADM_STATUS_TOOSMALL);
526
527 (void) strlcpy(attr, nvpair_name(nvp), MAXLINKATTRLEN);
528 bcopy(oattrval, attrval, oattrsz);
529 return (DLADM_STATUS_OK);
530 }
531
532 /*
533 * Get the link ID that is associated with the given name in the current zone.
534 */
535 dladm_status_t
536 dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp,
537 uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap)
538 {
539 return (dladm_zname2info(handle, NULL, link, linkidp, flagp, classp,
540 mediap));
541 }
542
543 /*
544 * Get the link ID that is associated with the given zone/name pair.
545 */
546 dladm_status_t
547 dladm_zname2info(dladm_handle_t handle, const char *zonename, const char *link,
548 datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp,
549 uint32_t *mediap)
550 {
551 dlmgmt_door_getlinkid_t getlinkid;
552 dlmgmt_getlinkid_retval_t retval;
553 datalink_id_t linkid;
554 dladm_status_t status;
555 size_t sz = sizeof (retval);
556
557 getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
558 (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
559 if (zonename != NULL)
560 getlinkid.ld_zoneid = getzoneidbyname(zonename);
561 else
562 getlinkid.ld_zoneid = -1;
563
564 if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid),
565 &retval, &sz)) != DLADM_STATUS_OK) {
566 return (status);
567 }
568
569 linkid = retval.lr_linkid;
570 if (retval.lr_class == DATALINK_CLASS_PHYS &&
571 retval.lr_flags & DLMGMT_ACTIVE) {
572 /*
573 * An active physical link reported by the dlmgmtd daemon
574 * might not be active anymore. Check and set its real status.
575 */
576 status = i_dladm_phys_status(handle, linkid, &retval.lr_flags);
577 if (status != DLADM_STATUS_OK)
578 return (status);
579 }
580
581 if (linkidp != NULL)
582 *linkidp = linkid;
583 if (flagp != NULL) {
584 *flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
585 *flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
586 DLADM_OPT_PERSIST : 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 }