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
dladm_door_call(dladm_handle_t handle,void * arg,size_t asize,void * rbuf,size_t * rsizep)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
dladm_create_datalink_id(dladm_handle_t handle,const char * link,datalink_class_t class,uint32_t media,uint32_t flags,datalink_id_t * linkidp)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
dladm_destroy_datalink_id(dladm_handle_t handle,datalink_id_t linkid,uint32_t flags)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
dladm_remap_datalink_id(dladm_handle_t handle,datalink_id_t linkid,const char * link)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
dladm_up_datalink_id(dladm_handle_t handle,datalink_id_t linkid)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
dladm_create_conf(dladm_handle_t handle,const char * link,datalink_id_t linkid,datalink_class_t class,uint32_t media,dladm_conf_t * confp)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
i_dladm_phys_status(dladm_handle_t handle,datalink_id_t linkid,uint32_t * flagsp)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
dladm_walk_datalink_id(int (* fn)(dladm_handle_t,datalink_id_t,void *),dladm_handle_t handle,void * argp,datalink_class_t class,datalink_media_t dmedia,uint32_t flags)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
dladm_open_conf(dladm_handle_t handle,datalink_id_t linkid,dladm_conf_t * confp)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
dladm_getsnap_conf(dladm_handle_t handle,datalink_id_t linkid,dladm_conf_t * confp)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), NV_ENCODE_NATIVE)) != 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
dladm_write_conf(dladm_handle_t handle,dladm_conf_t conf)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
dladm_get_conf_field(dladm_handle_t handle,dladm_conf_t conf,const char * attr,void * attrval,size_t attrsz)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
dladm_getnext_conf_linkprop(dladm_handle_t handle,dladm_conf_t conf,const char * last_attr,char * attr,void * attrval,size_t attrsz,size_t * attrszp)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)) != NULL) {
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
dladm_name2info(dladm_handle_t handle,const char * link,datalink_id_t * linkidp,uint32_t * flagp,datalink_class_t * classp,uint32_t * mediap)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
dladm_datalink_id2info(dladm_handle_t handle,datalink_id_t linkid,uint32_t * flagp,datalink_class_t * classp,uint32_t * mediap,char * link,size_t len)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
dladm_set_conf_field(dladm_handle_t handle,dladm_conf_t conf,const char * attr,dladm_datatype_t type,const void * attrval)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 = 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
dladm_unset_conf_field(dladm_handle_t handle,dladm_conf_t conf,const char * attr)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
dladm_remove_conf(dladm_handle_t handle,datalink_id_t linkid)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
dladm_destroy_conf(dladm_handle_t handle,dladm_conf_t conf)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
dladm_zone_boot(dladm_handle_t handle,zoneid_t zoneid)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
dladm_zone_halt(dladm_handle_t handle,zoneid_t zoneid)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