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