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.
24 * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
28 * Main door handler functions used by ipmgmtd to process the different door
29 * call requests, issued by the library libipadm.so.
34 #include <auth_attr.h>
42 #include <libnvpair.h>
43 #include "ipmgmt_impl.h"
45 /* Handler declaration for each door command */
46 typedef void ipmgmt_door_handler_t(void *argp
);
48 static ipmgmt_door_handler_t ipmgmt_getaddr_handler
,
49 ipmgmt_getprop_handler
,
51 ipmgmt_initif_handler
,
52 ipmgmt_aobjop_handler
,
53 ipmgmt_resetaddr_handler
,
55 ipmgmt_resetif_handler
,
56 ipmgmt_resetprop_handler
,
57 ipmgmt_setaddr_handler
,
58 ipmgmt_setprop_handler
;
60 typedef struct ipmgmt_door_info_s
{
63 ipmgmt_door_handler_t
*idi_handler
;
66 /* maps door commands to door handler functions */
67 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl
[] = {
68 { IPMGMT_CMD_SETPROP
, B_TRUE
, ipmgmt_setprop_handler
},
69 { IPMGMT_CMD_SETIF
, B_TRUE
, ipmgmt_setif_handler
},
70 { IPMGMT_CMD_SETADDR
, B_TRUE
, ipmgmt_setaddr_handler
},
71 { IPMGMT_CMD_GETPROP
, B_FALSE
, ipmgmt_getprop_handler
},
72 { IPMGMT_CMD_GETIF
, B_FALSE
, ipmgmt_getif_handler
},
73 { IPMGMT_CMD_GETADDR
, B_FALSE
, ipmgmt_getaddr_handler
},
74 { IPMGMT_CMD_RESETIF
, B_TRUE
, ipmgmt_resetif_handler
},
75 { IPMGMT_CMD_RESETADDR
, B_TRUE
, ipmgmt_resetaddr_handler
},
76 { IPMGMT_CMD_RESETPROP
, B_TRUE
, ipmgmt_resetprop_handler
},
77 { IPMGMT_CMD_INITIF
, B_TRUE
, ipmgmt_initif_handler
},
78 { IPMGMT_CMD_ADDROBJ_LOOKUPADD
, B_TRUE
, ipmgmt_aobjop_handler
},
79 { IPMGMT_CMD_ADDROBJ_SETLIFNUM
, B_TRUE
, ipmgmt_aobjop_handler
},
80 { IPMGMT_CMD_ADDROBJ_ADD
, B_TRUE
, ipmgmt_aobjop_handler
},
81 { IPMGMT_CMD_AOBJNAME2ADDROBJ
, B_FALSE
, ipmgmt_aobjop_handler
},
82 { IPMGMT_CMD_LIF2ADDROBJ
, B_FALSE
, ipmgmt_aobjop_handler
},
87 * The main server procedure function that gets invoked for any of the incoming
88 * door commands. Inside this function we identify the incoming command and
89 * invoke the right door handler function.
93 ipmgmt_handler(void *cookie
, char *argp
, size_t argsz
, door_desc_t
*dp
,
96 ipmgmt_door_info_t
*infop
= NULL
;
97 ipmgmt_retval_t retval
;
100 ucred_t
*cred
= NULL
;
102 for (i
= 0; i_ipmgmt_door_info_tbl
[i
].idi_cmd
!= 0; i
++) {
103 if (i_ipmgmt_door_info_tbl
[i
].idi_cmd
==
104 ((ipmgmt_arg_t
*)(void *)argp
)->ia_cmd
) {
105 infop
= &i_ipmgmt_door_info_tbl
[i
];
111 ipmgmt_log(LOG_ERR
, "Invalid door command specified");
116 /* check for solaris.network.interface.config authorization */
117 if (infop
->idi_set
) {
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 if (getpwuid_r(uid
, &pwd
, buf
, sizeof (buf
)) ==
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 sa_family_t af
= AF_UNSPEC
;
230 ipadm_addr_type_t addrtype
= IPADM_ADDR_NONE
;
234 * Retrieve all the information needed to build '*nodep' from
237 if ((err
= nvlist_lookup_string(nvl
, IPADM_NVP_AOBJNAME
,
239 (err
= nvlist_lookup_string(nvl
, IPADM_NVP_IFNAME
, &ifname
)) != 0 ||
240 (err
= nvlist_lookup_int32(nvl
, IPADM_NVP_LIFNUM
, &lnum
)) != 0) {
243 if (nvlist_exists(nvl
, IPADM_NVP_IPV4ADDR
)) {
245 addrtype
= IPADM_ADDR_STATIC
;
246 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_DHCP
, &nvladdr
) == 0) {
250 addrtype
= IPADM_ADDR_DHCP
;
253 * ipmgmt_am_reqhost comes through in `nvl' for purposes of
254 * updating the cached representation, but it is persisted as
255 * a stand-alone DB line; so remove it after copying it.
257 if (!nvlist_exists(nvl
, IPADM_NVP_REQHOST
)) {
258 *nodep
->ipmgmt_am_reqhost
= '\0';
260 if ((err
= nvlist_lookup_string(nvl
, IPADM_NVP_REQHOST
,
264 (void) strlcpy(nodep
->ipmgmt_am_reqhost
, reqhost
,
265 sizeof (nodep
->ipmgmt_am_reqhost
));
266 (void) nvlist_remove(nvl
, IPADM_NVP_REQHOST
,
269 } else if (nvlist_exists(nvl
, IPADM_NVP_IPV6ADDR
)) {
271 addrtype
= IPADM_ADDR_STATIC
;
272 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_INTFID
, &nvladdr
) == 0) {
273 struct sockaddr_in6 sin6
= {0};
279 addrtype
= IPADM_ADDR_IPV6_ADDRCONF
;
280 if (nvlist_lookup_uint32(nvladdr
, IPADM_NVP_PREFIXLEN
,
284 if (nvlist_lookup_uint8_array(nvladdr
,
285 IPADM_NVP_IPNUMADDR
, &addr6
, &n
) != 0)
287 bcopy(addr6
, &sin6
.sin6_addr
, n
);
290 nodep
->ipmgmt_am_linklocal
= B_TRUE
;
291 nodep
->ipmgmt_am_ifid
= sin6
;
295 * populate the non-addrtype-specific `*nodep' with retrieved values.
297 (void) strlcpy(nodep
->am_ifname
, ifname
, sizeof (nodep
->am_ifname
));
298 (void) strlcpy(nodep
->am_aobjname
, aobjname
,
299 sizeof (nodep
->am_aobjname
));
300 nodep
->am_lnum
= lnum
;
301 nodep
->am_family
= af
;
302 nodep
->am_atype
= addrtype
;
303 nodep
->am_next
= NULL
;
306 * Do not store logical interface number in persistent store as it
307 * takes different value on reboot. So remove it from `nvl'.
309 if (nvlist_exists(nvl
, IPADM_NVP_LIFNUM
))
310 (void) nvlist_remove(nvl
, IPADM_NVP_LIFNUM
, DATA_TYPE_INT32
);
316 * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
317 * node to the list `aobjmap' and optionally persists the address
318 * information in the DB.
321 ipmgmt_setaddr_handler(void *argp
)
323 ipmgmt_setaddr_arg_t
*sargp
= argp
;
324 ipmgmt_retval_t rval
;
325 ipmgmt_aobjmap_t node
= {0};
326 nvlist_t
*nvl
= NULL
;
328 size_t nvlsize
= sargp
->ia_nvlsize
;
329 uint32_t flags
= sargp
->ia_flags
;
332 nvlbuf
= (char *)argp
+ sizeof (ipmgmt_setaddr_arg_t
);
333 if ((err
= nvlist_unpack(nvlbuf
, nvlsize
, &nvl
, NV_ENCODE_NATIVE
)) != 0)
335 if (flags
& (IPMGMT_ACTIVE
|IPMGMT_INIT
)) {
336 if ((err
= i_ipmgmt_nvl2aobjnode(nvl
, &node
)) != 0)
338 if (flags
& IPMGMT_INIT
)
339 node
.am_flags
= (IPMGMT_ACTIVE
|IPMGMT_PERSIST
);
341 node
.am_flags
= flags
& ~IPMGMT_PROPS_ONLY
;
342 if ((err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
)) != 0)
345 if ((flags
& IPMGMT_PERSIST
) && !(flags
& IPMGMT_PROPS_ONLY
)) {
346 ipadm_dbwrite_cbarg_t cb
;
350 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);
355 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
359 * Handles the door commands that read or modify the `aobjmap' structure.
361 * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
362 * after ensuring that the namespace is not taken. If required, also
363 * generates an `aobjname' for address object for the library to use.
364 * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
365 * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
366 * associated with that logical interface.
367 * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
368 * interface associated with that address object.
371 ipmgmt_aobjop_handler(void *argp
)
373 ipmgmt_aobjop_arg_t
*largp
= argp
;
374 ipmgmt_retval_t rval
;
375 ipmgmt_aobjop_rval_t aobjrval
;
378 ipmgmt_aobjmap_t node
;
380 char *ifname
= largp
->ia_ifname
;
381 char *aobjname
= largp
->ia_aobjname
;
382 int32_t lnum
= largp
->ia_lnum
;
383 sa_family_t af
= largp
->ia_family
;
384 ipadm_addr_type_t atype
= largp
->ia_atype
;
385 ipmgmt_aobjmap_t
*head
;
387 switch (largp
->ia_cmd
) {
388 case IPMGMT_CMD_ADDROBJ_LOOKUPADD
:
389 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
391 bzero(&node
, sizeof (node
));
392 (void) strlcpy(node
.am_aobjname
, aobjname
,
393 sizeof (node
.am_aobjname
));
394 (void) strlcpy(node
.am_ifname
, ifname
,
395 sizeof (node
.am_ifname
));
397 node
.am_atype
= atype
;
398 /* no logical number is associated with this addrobj yet */
400 /* The address object is not persisted yet. */
401 node
.am_flags
= IPMGMT_ACTIVE
;
402 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_LOOKUPADD
);
404 (void) strlcpy(aobjrval
.ir_aobjname
, node
.am_aobjname
,
405 sizeof (aobjrval
.ir_aobjname
));
408 case IPMGMT_CMD_ADDROBJ_SETLIFNUM
:
409 rsize
= sizeof (ipmgmt_retval_t
);
411 bzero(&node
, sizeof (node
));
412 (void) strlcpy(node
.am_aobjname
, aobjname
,
413 sizeof (node
.am_aobjname
));
414 (void) strlcpy(node
.am_ifname
, ifname
,
415 sizeof (node
.am_ifname
));
418 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_SETLIFNUM
);
420 case IPMGMT_CMD_ADDROBJ_ADD
:
421 rsize
= sizeof (ipmgmt_retval_t
);
423 if (aobjname
[0] == '\0' || ifname
[0] == '\0' || lnum
== -1 ||
428 bzero(&node
, sizeof (node
));
429 (void) strlcpy(node
.am_aobjname
, aobjname
,
430 sizeof (node
.am_aobjname
));
431 (void) strlcpy(node
.am_ifname
, ifname
,
432 sizeof (node
.am_ifname
));
433 node
.am_atype
= atype
;
436 /* The address object is not persisted. */
437 node
.am_flags
= IPMGMT_ACTIVE
;
438 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
);
440 case IPMGMT_CMD_AOBJNAME2ADDROBJ
:
441 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
443 bzero(&aobjrval
, sizeof (aobjrval
));
444 if (aobjname
[0] == '\0') {
448 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
449 head
= aobjmap
.aobjmap_head
;
450 for (; head
; head
= head
->am_next
) {
451 if (strcmp(head
->am_aobjname
, aobjname
) != 0)
454 * For an auto-configured interface, return
455 * the lifnum that has the link-local on it.
456 * Other logical interfaces were created for
457 * prefixes and dhcpv6 addresses and do not
460 if (head
->am_atype
!= IPADM_ADDR_IPV6_ADDRCONF
||
461 head
->ipmgmt_am_linklocal
) {
467 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
470 (void) strlcpy(aobjrval
.ir_ifname
, head
->am_ifname
,
471 sizeof (aobjrval
.ir_ifname
));
472 aobjrval
.ir_lnum
= head
->am_lnum
;
473 aobjrval
.ir_family
= head
->am_family
;
474 aobjrval
.ir_flags
= head
->am_flags
;
475 aobjrval
.ir_atype
= head
->am_atype
;
476 aobjrval
.ir_atype_cache
= head
->am_atype_cache
;
477 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
479 case IPMGMT_CMD_LIF2ADDROBJ
:
480 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
482 bzero(&aobjrval
, sizeof (aobjrval
));
483 if (ifname
[0] == '\0') {
487 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
488 head
= aobjmap
.aobjmap_head
;
489 for (; head
; head
= head
->am_next
) {
490 if (strcmp(head
->am_ifname
, ifname
) == 0 &&
491 head
->am_lnum
== lnum
&&
492 head
->am_family
== af
) {
498 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
501 (void) strlcpy(aobjrval
.ir_aobjname
, head
->am_aobjname
,
502 sizeof (aobjrval
.ir_aobjname
));
503 aobjrval
.ir_atype
= head
->am_atype
;
504 aobjrval
.ir_flags
= head
->am_flags
;
505 aobjrval
.ir_atype_cache
= head
->am_atype_cache
;
506 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
509 rsize
= sizeof (ipmgmt_retval_t
);
513 ((ipmgmt_retval_t
*)rvalp
)->ir_err
= err
;
514 (void) door_return((char *)rvalp
, rsize
, NULL
, 0);
518 * Given an interface name and family, deletes all the address objects
519 * associated with it.
522 i_ipmgmt_delif_aobjs(char *ifname
, sa_family_t af
, uint32_t flags
)
524 ipmgmt_aobjmap_t
*head
, *next
, *prev
;
529 (void) pthread_rwlock_wrlock(&aobjmap
.aobjmap_rwlock
);
530 head
= aobjmap
.aobjmap_head
;
531 for (; head
; head
= next
) {
532 next
= head
->am_next
;
533 if (strcmp(head
->am_ifname
, ifname
) != 0 ||
534 head
->am_family
!= af
) {
539 if (head
->am_flags
== (IPMGMT_ACTIVE
|IPMGMT_PERSIST
) &&
540 flags
== IPMGMT_ACTIVE
) {
542 * If the addres is present in both active and
543 * persistent store, and if we are performing
544 * a temporary delete, we update the node to
545 * indicate that the address is only present in
546 * persistent store and we proceed. Otherwise
547 * we always delete the node from aobjmap.
549 head
->am_flags
&= ~IPMGMT_ACTIVE
;
551 db_op
= IPADM_DB_WRITE
;
553 db_op
= IPADM_DB_DELETE
;
555 aobjmap
.aobjmap_head
= next
;
557 prev
->am_next
= next
;
559 (void) ipmgmt_persist_aobjmap(head
, db_op
);
560 if (db_op
== IPADM_DB_DELETE
)
563 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
567 * Handles the door command IPMGMT_CMD_SETIF. It persists the interface
568 * information in the DB.
571 ipmgmt_setif_handler(void *argp
)
573 ipmgmt_retval_t rval
;
575 rval
.ir_err
= ipmgmt_persist_if(argp
);
576 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
580 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
581 * deletes all the persisted interface configuration. It also deletes, from
582 * `aobjmap', all the address objects configured on the given interface.
585 ipmgmt_resetif_handler(void *argp
)
587 ipmgmt_if_arg_t
*rargp
= argp
;
588 ipmgmt_retval_t rval
;
589 ipmgmt_if_cbarg_t cbarg
;
590 uint32_t flags
= rargp
->ia_flags
;
593 cbarg
.cb_family
= rargp
->ia_family
;
594 cbarg
.cb_ifname
= rargp
->ia_ifname
;
595 if (flags
& IPMGMT_PERSIST
)
596 err
= ipmgmt_db_walk(ipmgmt_db_resetif
, &cbarg
,
599 if (flags
& IPMGMT_ACTIVE
)
600 i_ipmgmt_delif_aobjs(rargp
->ia_ifname
, rargp
->ia_family
,
604 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
608 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
609 * deletes all the persisted addrobj configuration. It also deletes the
610 * corresponding node, from `aobjmap'.
613 ipmgmt_resetaddr_handler(void *argp
)
615 ipmgmt_addr_arg_t
*rargp
= argp
;
616 ipmgmt_retval_t rval
;
617 ipmgmt_aobjmap_t node
;
618 uint32_t flags
= rargp
->ia_flags
;
620 ipmgmt_resetaddr_cbarg_t cbarg
;
622 cbarg
.cb_aobjname
= rargp
->ia_aobjname
;
624 if (flags
& IPMGMT_PERSIST
)
625 err
= ipmgmt_db_walk(ipmgmt_db_resetaddr
, &cbarg
,
628 if (flags
& IPMGMT_ACTIVE
) {
629 bzero(&node
, sizeof (node
));
630 (void) strlcpy(node
.am_aobjname
, rargp
->ia_aobjname
,
631 sizeof (node
.am_aobjname
));
634 * am_lnum is used only for IPv6 autoconf case, since there
635 * can be multiple nodes with the same aobjname.
637 node
.am_lnum
= rargp
->ia_lnum
;
638 node
.am_flags
= flags
;
639 (void) ipmgmt_aobjmap_op(&node
, ADDROBJ_DELETE
);
643 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
647 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
648 * address for a given `gargp->ia_aobjname'. If it is not defined then it
649 * retrieves all the addresses configured on `gargp->ia_ifname'. The
650 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
651 * handler through library.
654 ipmgmt_getaddr_handler(void *argp
)
656 size_t buflen
, onvlsize
;
658 ipmgmt_getaddr_arg_t
*gargp
= argp
;
659 ipmgmt_getaddr_cbarg_t cbarg
;
660 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
663 cbarg
.cb_ifname
= gargp
->ia_ifname
;
664 cbarg
.cb_aobjname
= gargp
->ia_aobjname
;
666 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
668 err
= ipmgmt_db_walk(ipmgmt_db_getaddr
, &cbarg
, IPADM_DB_READ
);
669 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
671 * If there is atleast one entry in the nvlist,
672 * do not return error.
679 if ((err
= nvlist_size(cbarg
.cb_onvl
, &onvlsize
,
680 NV_ENCODE_NATIVE
)) != 0) {
683 buflen
= onvlsize
+ sizeof (ipmgmt_get_rval_t
);
685 * We cannot use malloc() here because door_return never returns, and
686 * memory allocated by malloc() would get leaked. Use alloca() instead.
688 buf
= alloca(buflen
);
689 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
690 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &onvlsize
,
691 NV_ENCODE_NATIVE
, 0)) != 0) {
694 nvlist_free(cbarg
.cb_onvl
);
695 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
697 rvalp
->ir_nvlsize
= onvlsize
;
699 (void) door_return(buf
, buflen
, NULL
, 0);
702 nvlist_free(cbarg
.cb_onvl
);
704 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
708 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
712 ipmgmt_resetprop_handler(void *argp
)
714 ipmgmt_prop_arg_t
*pargp
= argp
;
715 ipmgmt_retval_t rval
;
717 assert(pargp
->ia_cmd
== IPMGMT_CMD_RESETPROP
);
719 rval
.ir_err
= ipmgmt_db_walk(ipmgmt_db_resetprop
, pargp
,
721 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
725 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
726 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.
729 ipmgmt_getif_handler(void *argp
)
731 ipmgmt_getif_arg_t
*getif
= argp
;
732 ipmgmt_getif_rval_t
*rvalp
;
733 ipmgmt_retval_t rval
;
734 ipmgmt_getif_cbarg_t cbarg
;
735 ipadm_if_info_t
*ifp
, *rifp
, *curifp
;
736 int i
, err
= 0, count
= 0;
739 assert(getif
->ia_cmd
== IPMGMT_CMD_GETIF
);
741 bzero(&cbarg
, sizeof (cbarg
));
742 cbarg
.cb_ifname
= getif
->ia_ifname
;
743 err
= ipmgmt_db_walk(ipmgmt_db_getif
, &cbarg
, IPADM_DB_READ
);
744 if (err
== ENOENT
&& cbarg
.cb_ifinfo
) {
746 * If there is atleast one entry in the nvlist,
747 * do not return error.
753 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
757 /* allocate sufficient buffer to return the interface info */
758 for (ifp
= cbarg
.cb_ifinfo
; ifp
!= NULL
; ifp
= ifp
->ifi_next
)
760 rbufsize
= sizeof (*rvalp
) + count
* sizeof (*ifp
);
761 rvalp
= alloca(rbufsize
);
762 bzero(rvalp
, rbufsize
);
764 rvalp
->ir_ifcnt
= count
;
765 rifp
= rvalp
->ir_ifinfo
;
766 ifp
= cbarg
.cb_ifinfo
;
769 * copy the interface info to buffer allocated on stack. The reason
770 * we do this is to avoid memory leak, as door_return() would never
773 for (i
= 0; i
< count
; i
++) {
774 rifp
= rvalp
->ir_ifinfo
+ i
;
775 (void) bcopy(ifp
, rifp
, sizeof (*rifp
));
776 rifp
->ifi_next
= NULL
;
777 curifp
= ifp
->ifi_next
;
782 (void) door_return((char *)rvalp
, rbufsize
, NULL
, 0);
786 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
787 * interface configuration (interface properties and addresses), for all those
788 * interfaces that need to be initialized.
791 ipmgmt_initif_handler(void *argp
)
793 ipmgmt_initif_arg_t
*initif
= argp
;
794 size_t buflen
, nvlsize
;
795 char *buf
= NULL
, *onvlbuf
, *invlbuf
;
796 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
797 ipmgmt_initif_cbarg_t cbarg
;
800 assert(initif
->ia_cmd
== IPMGMT_CMD_INITIF
);
802 bzero(&cbarg
, sizeof (cbarg
));
803 invlbuf
= (char *)argp
+ sizeof (ipmgmt_initif_arg_t
);
804 nvlsize
= initif
->ia_nvlsize
;
805 err
= nvlist_unpack(invlbuf
, nvlsize
, &cbarg
.cb_invl
, NV_ENCODE_NATIVE
);
809 cbarg
.cb_family
= initif
->ia_family
;
810 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
813 err
= ipmgmt_db_walk(ipmgmt_db_initif
, &cbarg
, IPADM_DB_READ
);
814 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
816 * If there is atleast one entry in the nvlist,
817 * do not return error.
824 if ((err
= nvlist_size(cbarg
.cb_onvl
, &nvlsize
, NV_ENCODE_NATIVE
)) != 0)
826 buflen
= nvlsize
+ sizeof (ipmgmt_get_rval_t
);
828 * We cannot use malloc() here because door_return never returns, and
829 * memory allocated by malloc() would get leaked. Use alloca() instead.
831 buf
= alloca(buflen
);
832 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
833 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &nvlsize
,
834 NV_ENCODE_NATIVE
, 0)) != 0) {
837 nvlist_free(cbarg
.cb_invl
);
838 nvlist_free(cbarg
.cb_onvl
);
839 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
841 rvalp
->ir_nvlsize
= nvlsize
;
843 (void) door_return(buf
, buflen
, NULL
, 0);
846 nvlist_free(cbarg
.cb_invl
);
847 nvlist_free(cbarg
.cb_onvl
);
849 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
853 ipmgmt_persist_if(ipmgmt_if_arg_t
*sargp
)
855 ipadm_dbwrite_cbarg_t cb
;
856 uint32_t flags
= sargp
->ia_flags
;
857 nvlist_t
*nvl
= NULL
;
859 char strval
[IPMGMT_STRSIZE
];
861 if (!(flags
& IPMGMT_PERSIST
) || sargp
->ia_family
== AF_UNSPEC
||
862 sargp
->ia_ifname
[0] == '\0') {
866 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
868 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
869 sargp
->ia_ifname
)) != 0)
871 (void) snprintf(strval
, IPMGMT_STRSIZE
, "%d", sargp
->ia_family
);
872 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_FAMILY
, strval
)) != 0)
876 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);