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.
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.
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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 * Main door handler functions used by ipmgmtd to process the different door
28 * call requests, issued by the library libipadm.so.
33 #include <auth_attr.h>
41 #include <libnvpair.h>
42 #include "ipmgmt_impl.h"
44 /* Handler declaration for each door command */
45 typedef void ipmgmt_door_handler_t(void *argp
);
47 static ipmgmt_door_handler_t ipmgmt_getaddr_handler
,
48 ipmgmt_getprop_handler
,
50 ipmgmt_initif_handler
,
51 ipmgmt_aobjop_handler
,
52 ipmgmt_resetaddr_handler
,
54 ipmgmt_resetif_handler
,
55 ipmgmt_resetprop_handler
,
56 ipmgmt_setaddr_handler
,
57 ipmgmt_setprop_handler
;
59 typedef struct ipmgmt_door_info_s
{
62 ipmgmt_door_handler_t
*idi_handler
;
65 /* maps door commands to door handler functions */
66 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl
[] = {
67 { IPMGMT_CMD_SETPROP
, B_TRUE
, ipmgmt_setprop_handler
},
68 { IPMGMT_CMD_SETIF
, B_TRUE
, ipmgmt_setif_handler
},
69 { IPMGMT_CMD_SETADDR
, B_TRUE
, ipmgmt_setaddr_handler
},
70 { IPMGMT_CMD_GETPROP
, B_FALSE
, ipmgmt_getprop_handler
},
71 { IPMGMT_CMD_GETIF
, B_FALSE
, ipmgmt_getif_handler
},
72 { IPMGMT_CMD_GETADDR
, B_FALSE
, ipmgmt_getaddr_handler
},
73 { IPMGMT_CMD_RESETIF
, B_TRUE
, ipmgmt_resetif_handler
},
74 { IPMGMT_CMD_RESETADDR
, B_TRUE
, ipmgmt_resetaddr_handler
},
75 { IPMGMT_CMD_RESETPROP
, B_TRUE
, ipmgmt_resetprop_handler
},
76 { IPMGMT_CMD_INITIF
, B_TRUE
, ipmgmt_initif_handler
},
77 { IPMGMT_CMD_ADDROBJ_LOOKUPADD
, B_TRUE
, ipmgmt_aobjop_handler
},
78 { IPMGMT_CMD_ADDROBJ_SETLIFNUM
, B_TRUE
, ipmgmt_aobjop_handler
},
79 { IPMGMT_CMD_ADDROBJ_ADD
, B_TRUE
, ipmgmt_aobjop_handler
},
80 { IPMGMT_CMD_AOBJNAME2ADDROBJ
, B_FALSE
, ipmgmt_aobjop_handler
},
81 { IPMGMT_CMD_LIF2ADDROBJ
, B_FALSE
, ipmgmt_aobjop_handler
},
86 * The main server procedure function that gets invoked for any of the incoming
87 * door commands. Inside this function we identify the incoming command and
88 * invoke the right door handler function.
92 ipmgmt_handler(void *cookie
, char *argp
, size_t argsz
, door_desc_t
*dp
,
95 ipmgmt_door_info_t
*infop
= NULL
;
96 ipmgmt_retval_t retval
;
101 for (i
= 0; i_ipmgmt_door_info_tbl
[i
].idi_cmd
!= 0; i
++) {
102 if (i_ipmgmt_door_info_tbl
[i
].idi_cmd
==
103 ((ipmgmt_arg_t
*)(void *)argp
)->ia_cmd
) {
104 infop
= &i_ipmgmt_door_info_tbl
[i
];
110 ipmgmt_log(LOG_ERR
, "Invalid door command specified");
115 /* check for solaris.network.interface.config authorization */
116 if (infop
->idi_set
) {
120 struct passwd
*result
;
122 if (door_ucred(&cred
) != 0) {
124 ipmgmt_log(LOG_ERR
, "Could not get user credentials.");
127 uid
= ucred_getruid(cred
);
130 ipmgmt_log(LOG_ERR
, "Could not get user id.");
133 getpwuid_r(uid
, &pwd
, buf
, sizeof (buf
), &result
);
136 ipmgmt_log(LOG_ERR
, "Could not get password entry.");
139 if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH
,
142 ipmgmt_log(LOG_ERR
, "Not authorized for operation.");
148 /* individual handlers take care of calling door_return */
149 infop
->idi_handler((void *)argp
);
154 (void) door_return((char *)&retval
, sizeof (retval
), NULL
, 0);
158 * Handles the door command IPMGMT_CMD_GETPROP. It retrieves the persisted
159 * property value for the given property.
162 ipmgmt_getprop_handler(void *argp
)
164 ipmgmt_prop_arg_t
*pargp
= argp
;
165 ipmgmt_getprop_rval_t rval
, *rvalp
= &rval
;
167 assert(pargp
->ia_cmd
== IPMGMT_CMD_GETPROP
);
169 rvalp
->ir_err
= ipmgmt_db_walk(ipmgmt_db_getprop
, pargp
, IPADM_DB_READ
);
170 if (rvalp
->ir_err
== 0)
171 (void) strlcpy(rvalp
->ir_pval
, pargp
->ia_pval
,
172 sizeof (rvalp
->ir_pval
));
173 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
177 * Handles the door command IPMGMT_CMD_SETPROP. It persists the property value
178 * for the given property in the DB.
181 ipmgmt_setprop_handler(void *argp
)
183 ipmgmt_prop_arg_t
*pargp
= argp
;
184 ipmgmt_retval_t rval
;
185 ipadm_dbwrite_cbarg_t cb
;
186 nvlist_t
*nvl
= NULL
;
189 assert(pargp
->ia_cmd
== IPMGMT_CMD_SETPROP
);
191 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
193 if (pargp
->ia_module
[0] != '\0' &&
194 (err
= nvlist_add_string(nvl
, IPADM_NVP_PROTONAME
,
195 pargp
->ia_module
)) != 0) {
198 if (pargp
->ia_ifname
[0] != '\0' &&
199 (err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
200 pargp
->ia_ifname
)) != 0)
202 if (pargp
->ia_aobjname
[0] != '\0' &&
203 (err
= nvlist_add_string(nvl
, IPADM_NVP_AOBJNAME
,
204 pargp
->ia_aobjname
)) != 0)
206 if ((err
= nvlist_add_string(nvl
, pargp
->ia_pname
,
207 pargp
->ia_pval
)) != 0)
211 cb
.dbw_flags
= pargp
->ia_flags
;
212 err
= ipmgmt_db_walk(ipmgmt_db_update
, &cb
, IPADM_DB_WRITE
);
216 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
220 * Helper function for ipmgmt_setaddr_handler().
221 * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
224 i_ipmgmt_nvl2aobjnode(nvlist_t
*nvl
, ipmgmt_aobjmap_t
*nodep
)
226 char *aobjname
= NULL
, *ifname
= NULL
;
229 struct sockaddr_storage addr
;
231 sa_family_t af
= AF_UNSPEC
;
232 ipadm_addr_type_t addrtype
= IPADM_ADDR_NONE
;
236 * Retrieve all the information needed to build '*nodep' from
239 if ((err
= nvlist_lookup_string(nvl
, IPADM_NVP_AOBJNAME
,
241 (err
= nvlist_lookup_string(nvl
, IPADM_NVP_IFNAME
, &ifname
)) != 0 ||
242 (err
= nvlist_lookup_int32(nvl
, IPADM_NVP_LIFNUM
, &lnum
)) != 0) {
245 if (nvlist_exists(nvl
, IPADM_NVP_IPV4ADDR
)) {
247 addrtype
= IPADM_ADDR_STATIC
;
248 } else if (nvlist_exists(nvl
, IPADM_NVP_DHCP
)) {
250 addrtype
= IPADM_ADDR_DHCP
;
251 } else if (nvlist_exists(nvl
, IPADM_NVP_IPV6ADDR
)) {
253 addrtype
= IPADM_ADDR_STATIC
;
254 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_INTFID
, &nvladdr
) == 0) {
255 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&addr
;
260 addrtype
= IPADM_ADDR_IPV6_ADDRCONF
;
261 if (nvlist_lookup_uint32(nvladdr
, IPADM_NVP_PREFIXLEN
,
265 if (nvlist_lookup_uint8_array(nvladdr
,
266 IPADM_NVP_IPNUMADDR
, &addr6
, &n
) != 0)
268 bcopy(addr6
, &sin6
->sin6_addr
, n
);
270 bzero(&sin6
->sin6_addr
, sizeof (sin6
->sin6_addr
));
275 * populate the `*nodep' with retrieved values.
277 (void) strlcpy(nodep
->am_ifname
, ifname
, sizeof (nodep
->am_ifname
));
278 (void) strlcpy(nodep
->am_aobjname
, aobjname
,
279 sizeof (nodep
->am_aobjname
));
280 nodep
->am_lnum
= lnum
;
281 nodep
->am_family
= af
;
282 nodep
->am_atype
= addrtype
;
283 if (addrtype
== IPADM_ADDR_IPV6_ADDRCONF
) {
284 nodep
->am_linklocal
= B_TRUE
;
285 nodep
->am_ifid
= addr
;
287 nodep
->am_next
= NULL
;
290 * Do not store logical interface number in persistent store as it
291 * takes different value on reboot. So remove it from `nvl'.
293 if (nvlist_exists(nvl
, IPADM_NVP_LIFNUM
))
294 (void) nvlist_remove(nvl
, IPADM_NVP_LIFNUM
, DATA_TYPE_INT32
);
300 * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
301 * node to the list `aobjmap' and then persists the address information in the
305 ipmgmt_setaddr_handler(void *argp
)
307 ipmgmt_setaddr_arg_t
*sargp
= argp
;
308 ipmgmt_retval_t rval
;
309 ipmgmt_aobjmap_t node
;
310 nvlist_t
*nvl
= NULL
;
312 size_t nvlsize
= sargp
->ia_nvlsize
;
313 uint32_t flags
= sargp
->ia_flags
;
316 nvlbuf
= (char *)argp
+ sizeof (ipmgmt_setaddr_arg_t
);
317 if ((err
= nvlist_unpack(nvlbuf
, nvlsize
, &nvl
, NV_ENCODE_NATIVE
)) != 0)
319 if (flags
& (IPMGMT_ACTIVE
|IPMGMT_INIT
)) {
320 if ((err
= i_ipmgmt_nvl2aobjnode(nvl
, &node
)) != 0)
322 if (flags
& IPMGMT_INIT
)
323 node
.am_flags
= (IPMGMT_ACTIVE
|IPMGMT_PERSIST
);
325 node
.am_flags
= flags
;
326 if ((err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
)) != 0)
329 if (flags
& IPMGMT_PERSIST
) {
330 ipadm_dbwrite_cbarg_t cb
;
334 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);
339 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
343 * Handles the door commands that modify the `aobjmap' structure.
345 * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
346 * after ensuring that the namespace is not taken. If required, also
347 * generates an `aobjname' for address object for the library to use.
348 * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
349 * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
350 * associated with that logical interface.
351 * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
352 * interface associated with that address object.
355 ipmgmt_aobjop_handler(void *argp
)
357 ipmgmt_aobjop_arg_t
*largp
= argp
;
358 ipmgmt_retval_t rval
;
359 ipmgmt_aobjop_rval_t aobjrval
;
362 ipmgmt_aobjmap_t node
;
364 char *ifname
= largp
->ia_ifname
;
365 char *aobjname
= largp
->ia_aobjname
;
366 int32_t lnum
= largp
->ia_lnum
;
367 sa_family_t af
= largp
->ia_family
;
368 ipadm_addr_type_t atype
= largp
->ia_atype
;
369 ipmgmt_aobjmap_t
*head
;
371 switch (largp
->ia_cmd
) {
372 case IPMGMT_CMD_ADDROBJ_LOOKUPADD
:
373 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
375 bzero(&node
, sizeof (node
));
376 (void) strlcpy(node
.am_aobjname
, aobjname
,
377 sizeof (node
.am_aobjname
));
378 (void) strlcpy(node
.am_ifname
, ifname
,
379 sizeof (node
.am_ifname
));
381 node
.am_atype
= atype
;
382 /* no logical number is associated with this addrobj yet */
384 /* The address object is not persisted yet. */
385 node
.am_flags
= IPMGMT_ACTIVE
;
386 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_LOOKUPADD
);
388 (void) strlcpy(aobjrval
.ir_aobjname
, node
.am_aobjname
,
389 sizeof (aobjrval
.ir_aobjname
));
392 case IPMGMT_CMD_ADDROBJ_SETLIFNUM
:
393 rsize
= sizeof (ipmgmt_retval_t
);
395 bzero(&node
, sizeof (node
));
396 (void) strlcpy(node
.am_aobjname
, aobjname
,
397 sizeof (node
.am_aobjname
));
398 (void) strlcpy(node
.am_ifname
, ifname
,
399 sizeof (node
.am_ifname
));
402 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_SETLIFNUM
);
404 case IPMGMT_CMD_ADDROBJ_ADD
:
405 rsize
= sizeof (ipmgmt_retval_t
);
407 if (aobjname
[0] == '\0' || ifname
[0] == '\0' || lnum
== -1 ||
412 bzero(&node
, sizeof (node
));
413 (void) strlcpy(node
.am_aobjname
, aobjname
,
414 sizeof (node
.am_aobjname
));
415 (void) strlcpy(node
.am_ifname
, ifname
,
416 sizeof (node
.am_ifname
));
417 node
.am_atype
= atype
;
420 /* The address object is not persisted. */
421 node
.am_flags
= IPMGMT_ACTIVE
;
422 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
);
424 case IPMGMT_CMD_AOBJNAME2ADDROBJ
:
425 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
427 bzero(&aobjrval
, sizeof (aobjrval
));
428 if (aobjname
[0] == '\0') {
432 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
433 head
= aobjmap
.aobjmap_head
;
434 for (; head
; head
= head
->am_next
) {
435 if (strcmp(head
->am_aobjname
, aobjname
) != 0)
438 * For an auto-configured interface, return
439 * the lifnum that has the link-local on it.
440 * Other logical interfaces were created for
441 * prefixes and dhcpv6 addresses and do not
444 if (head
->am_atype
!= IPADM_ADDR_IPV6_ADDRCONF
||
445 head
->am_linklocal
) {
451 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
454 (void) strlcpy(aobjrval
.ir_ifname
, head
->am_ifname
,
455 sizeof (aobjrval
.ir_ifname
));
456 aobjrval
.ir_lnum
= head
->am_lnum
;
457 aobjrval
.ir_family
= head
->am_family
;
458 aobjrval
.ir_flags
= head
->am_flags
;
459 aobjrval
.ir_atype
= head
->am_atype
;
460 if (head
->am_atype
== IPADM_ADDR_IPV6_ADDRCONF
&&
462 aobjrval
.ir_ifid
= head
->am_ifid
;
463 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
465 case IPMGMT_CMD_LIF2ADDROBJ
:
466 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
468 bzero(&aobjrval
, sizeof (aobjrval
));
469 if (ifname
[0] == '\0') {
473 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
474 head
= aobjmap
.aobjmap_head
;
475 for (; head
; head
= head
->am_next
) {
476 if (strcmp(head
->am_ifname
, ifname
) == 0 &&
477 head
->am_lnum
== lnum
&&
478 head
->am_family
== af
) {
484 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
487 (void) strlcpy(aobjrval
.ir_aobjname
, head
->am_aobjname
,
488 sizeof (aobjrval
.ir_aobjname
));
489 aobjrval
.ir_atype
= head
->am_atype
;
490 aobjrval
.ir_flags
= head
->am_flags
;
491 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
494 rsize
= sizeof (ipmgmt_retval_t
);
498 ((ipmgmt_retval_t
*)rvalp
)->ir_err
= err
;
499 (void) door_return((char *)rvalp
, rsize
, NULL
, 0);
503 * Given an interface name and family, deletes all the address objects
504 * associated with it.
507 i_ipmgmt_delif_aobjs(char *ifname
, sa_family_t af
, uint32_t flags
)
509 ipmgmt_aobjmap_t
*head
, *next
, *prev
;
514 (void) pthread_rwlock_wrlock(&aobjmap
.aobjmap_rwlock
);
515 head
= aobjmap
.aobjmap_head
;
516 for (; head
; head
= next
) {
517 next
= head
->am_next
;
518 if (strcmp(head
->am_ifname
, ifname
) != 0 ||
519 head
->am_family
!= af
) {
524 if (head
->am_flags
== (IPMGMT_ACTIVE
|IPMGMT_PERSIST
) &&
525 flags
== IPMGMT_ACTIVE
) {
527 * If the addres is present in both active and
528 * persistent store, and if we are performing
529 * a temporary delete, we update the node to
530 * indicate that the address is only present in
531 * persistent store and we proceed. Otherwise
532 * we always delete the node from aobjmap.
534 head
->am_flags
&= ~IPMGMT_ACTIVE
;
536 db_op
= IPADM_DB_WRITE
;
538 db_op
= IPADM_DB_DELETE
;
540 aobjmap
.aobjmap_head
= next
;
542 prev
->am_next
= next
;
544 (void) ipmgmt_persist_aobjmap(head
, db_op
);
545 if (db_op
== IPADM_DB_DELETE
)
548 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
552 * Handles the door command IPMGMT_CMD_SETIF. It persists the interface
553 * information in the DB.
556 ipmgmt_setif_handler(void *argp
)
558 ipmgmt_retval_t rval
;
560 rval
.ir_err
= ipmgmt_persist_if(argp
);
561 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
565 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
566 * deletes all the persisted interface configuration. It also deletes, from
567 * `aobjmap', all the address objects configured on the given interface.
570 ipmgmt_resetif_handler(void *argp
)
572 ipmgmt_if_arg_t
*rargp
= argp
;
573 ipmgmt_retval_t rval
;
574 ipmgmt_if_cbarg_t cbarg
;
575 uint32_t flags
= rargp
->ia_flags
;
578 cbarg
.cb_family
= rargp
->ia_family
;
579 cbarg
.cb_ifname
= rargp
->ia_ifname
;
580 if (flags
& IPMGMT_PERSIST
)
581 err
= ipmgmt_db_walk(ipmgmt_db_resetif
, &cbarg
,
584 if (flags
& IPMGMT_ACTIVE
)
585 i_ipmgmt_delif_aobjs(rargp
->ia_ifname
, rargp
->ia_family
,
589 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
593 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
594 * deletes all the persisted addrobj configuration. It also deletes the
595 * corresponding node, from `aobjmap'.
598 ipmgmt_resetaddr_handler(void *argp
)
600 ipmgmt_addr_arg_t
*rargp
= argp
;
601 ipmgmt_retval_t rval
;
602 ipmgmt_aobjmap_t node
;
603 uint32_t flags
= rargp
->ia_flags
;
605 ipmgmt_resetaddr_cbarg_t cbarg
;
607 cbarg
.cb_aobjname
= rargp
->ia_aobjname
;
609 if (flags
& IPMGMT_PERSIST
)
610 err
= ipmgmt_db_walk(ipmgmt_db_resetaddr
, &cbarg
,
613 if (flags
& IPMGMT_ACTIVE
) {
614 bzero(&node
, sizeof (node
));
615 (void) strlcpy(node
.am_aobjname
, rargp
->ia_aobjname
,
616 sizeof (node
.am_aobjname
));
619 * am_lnum is used only for IPv6 autoconf case, since there
620 * can be multiple nodes with the same aobjname.
622 node
.am_lnum
= rargp
->ia_lnum
;
623 node
.am_flags
= flags
;
624 (void) ipmgmt_aobjmap_op(&node
, ADDROBJ_DELETE
);
628 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
632 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
633 * address for a given `gargp->ia_aobjname'. If it is not defined then it
634 * retrieves all the addresses configured on `gargp->ia_ifname'. The
635 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
636 * handler through library.
639 ipmgmt_getaddr_handler(void *argp
)
641 size_t buflen
, onvlsize
;
643 ipmgmt_getaddr_arg_t
*gargp
= argp
;
644 ipmgmt_getaddr_cbarg_t cbarg
;
645 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
648 cbarg
.cb_ifname
= gargp
->ia_ifname
;
649 cbarg
.cb_aobjname
= gargp
->ia_aobjname
;
651 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
653 err
= ipmgmt_db_walk(ipmgmt_db_getaddr
, &cbarg
, IPADM_DB_READ
);
654 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
656 * If there is atleast one entry in the nvlist,
657 * do not return error.
664 if ((err
= nvlist_size(cbarg
.cb_onvl
, &onvlsize
,
665 NV_ENCODE_NATIVE
)) != 0) {
668 buflen
= onvlsize
+ sizeof (ipmgmt_get_rval_t
);
670 * We cannot use malloc() here because door_return never returns, and
671 * memory allocated by malloc() would get leaked. Use alloca() instead.
673 buf
= alloca(buflen
);
674 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
675 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &onvlsize
,
676 NV_ENCODE_NATIVE
, 0)) != 0) {
679 nvlist_free(cbarg
.cb_onvl
);
680 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
682 rvalp
->ir_nvlsize
= onvlsize
;
684 (void) door_return(buf
, buflen
, NULL
, 0);
687 nvlist_free(cbarg
.cb_onvl
);
689 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
693 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
697 ipmgmt_resetprop_handler(void *argp
)
699 ipmgmt_prop_arg_t
*pargp
= argp
;
700 ipmgmt_retval_t rval
;
702 assert(pargp
->ia_cmd
== IPMGMT_CMD_RESETPROP
);
704 rval
.ir_err
= ipmgmt_db_walk(ipmgmt_db_resetprop
, pargp
,
706 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
710 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
711 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.
714 ipmgmt_getif_handler(void *argp
)
716 ipmgmt_getif_arg_t
*getif
= argp
;
717 ipmgmt_getif_rval_t
*rvalp
;
718 ipmgmt_retval_t rval
;
719 ipmgmt_getif_cbarg_t cbarg
;
720 ipadm_if_info_t
*ifp
, *rifp
, *curifp
;
721 int i
, err
= 0, count
= 0;
724 assert(getif
->ia_cmd
== IPMGMT_CMD_GETIF
);
726 bzero(&cbarg
, sizeof (cbarg
));
727 cbarg
.cb_ifname
= getif
->ia_ifname
;
728 err
= ipmgmt_db_walk(ipmgmt_db_getif
, &cbarg
, IPADM_DB_READ
);
729 if (err
== ENOENT
&& cbarg
.cb_ifinfo
) {
731 * If there is atleast one entry in the nvlist,
732 * do not return error.
738 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
742 /* allocate sufficient buffer to return the interface info */
743 for (ifp
= cbarg
.cb_ifinfo
; ifp
!= NULL
; ifp
= ifp
->ifi_next
)
745 rbufsize
= sizeof (*rvalp
) + count
* sizeof (*ifp
);
746 rvalp
= alloca(rbufsize
);
747 bzero(rvalp
, rbufsize
);
749 rvalp
->ir_ifcnt
= count
;
750 rifp
= rvalp
->ir_ifinfo
;
751 ifp
= cbarg
.cb_ifinfo
;
754 * copy the interface info to buffer allocated on stack. The reason
755 * we do this is to avoid memory leak, as door_return() would never
758 for (i
= 0; i
< count
; i
++) {
759 rifp
= rvalp
->ir_ifinfo
+ i
;
760 (void) bcopy(ifp
, rifp
, sizeof (*rifp
));
761 rifp
->ifi_next
= NULL
;
762 curifp
= ifp
->ifi_next
;
767 (void) door_return((char *)rvalp
, rbufsize
, NULL
, 0);
771 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
772 * interface configuration (interface properties and addresses), for all those
773 * interfaces that need to be initialized.
776 ipmgmt_initif_handler(void *argp
)
778 ipmgmt_initif_arg_t
*initif
= argp
;
779 size_t buflen
, nvlsize
;
780 char *buf
= NULL
, *onvlbuf
, *invlbuf
;
781 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
782 ipmgmt_initif_cbarg_t cbarg
;
785 assert(initif
->ia_cmd
== IPMGMT_CMD_INITIF
);
787 bzero(&cbarg
, sizeof (cbarg
));
788 invlbuf
= (char *)argp
+ sizeof (ipmgmt_initif_arg_t
);
789 nvlsize
= initif
->ia_nvlsize
;
790 err
= nvlist_unpack(invlbuf
, nvlsize
, &cbarg
.cb_invl
, NV_ENCODE_NATIVE
);
794 cbarg
.cb_family
= initif
->ia_family
;
795 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
798 err
= ipmgmt_db_walk(ipmgmt_db_initif
, &cbarg
, IPADM_DB_READ
);
799 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
801 * If there is atleast one entry in the nvlist,
802 * do not return error.
809 if ((err
= nvlist_size(cbarg
.cb_onvl
, &nvlsize
, NV_ENCODE_NATIVE
)) != 0)
811 buflen
= nvlsize
+ sizeof (ipmgmt_get_rval_t
);
813 * We cannot use malloc() here because door_return never returns, and
814 * memory allocated by malloc() would get leaked. Use alloca() instead.
816 buf
= alloca(buflen
);
817 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
818 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &nvlsize
,
819 NV_ENCODE_NATIVE
, 0)) != 0) {
822 nvlist_free(cbarg
.cb_invl
);
823 nvlist_free(cbarg
.cb_onvl
);
824 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
826 rvalp
->ir_nvlsize
= nvlsize
;
828 (void) door_return(buf
, buflen
, NULL
, 0);
831 nvlist_free(cbarg
.cb_invl
);
832 nvlist_free(cbarg
.cb_onvl
);
834 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
838 ipmgmt_persist_if(ipmgmt_if_arg_t
*sargp
)
840 ipadm_dbwrite_cbarg_t cb
;
841 uint32_t flags
= sargp
->ia_flags
;
842 nvlist_t
*nvl
= NULL
;
844 char strval
[IPMGMT_STRSIZE
];
846 if (!(flags
& IPMGMT_PERSIST
) || sargp
->ia_family
== AF_UNSPEC
||
847 sargp
->ia_ifname
[0] == '\0') {
851 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
853 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
854 sargp
->ia_ifname
)) != 0)
856 (void) snprintf(strval
, IPMGMT_STRSIZE
, "%d", sargp
->ia_family
);
857 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_FAMILY
, strval
)) != 0)
861 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);