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
) {
121 struct passwd
*result
;
123 if (door_ucred(&cred
) != 0) {
125 ipmgmt_log(LOG_ERR
, "Could not get user credentials.");
128 uid
= ucred_getruid(cred
);
131 ipmgmt_log(LOG_ERR
, "Could not get user id.");
134 getpwuid_r(uid
, &pwd
, buf
, sizeof (buf
), &result
);
137 ipmgmt_log(LOG_ERR
, "Could not get password entry.");
140 if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH
,
143 ipmgmt_log(LOG_ERR
, "Not authorized for operation.");
149 /* individual handlers take care of calling door_return */
150 infop
->idi_handler((void *)argp
);
155 (void) door_return((char *)&retval
, sizeof (retval
), NULL
, 0);
159 * Handles the door command IPMGMT_CMD_GETPROP. It retrieves the persisted
160 * property value for the given property.
163 ipmgmt_getprop_handler(void *argp
)
165 ipmgmt_prop_arg_t
*pargp
= argp
;
166 ipmgmt_getprop_rval_t rval
, *rvalp
= &rval
;
168 assert(pargp
->ia_cmd
== IPMGMT_CMD_GETPROP
);
170 rvalp
->ir_err
= ipmgmt_db_walk(ipmgmt_db_getprop
, pargp
, IPADM_DB_READ
);
171 if (rvalp
->ir_err
== 0)
172 (void) strlcpy(rvalp
->ir_pval
, pargp
->ia_pval
,
173 sizeof (rvalp
->ir_pval
));
174 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
178 * Handles the door command IPMGMT_CMD_SETPROP. It persists the property value
179 * for the given property in the DB.
182 ipmgmt_setprop_handler(void *argp
)
184 ipmgmt_prop_arg_t
*pargp
= argp
;
185 ipmgmt_retval_t rval
;
186 ipadm_dbwrite_cbarg_t cb
;
187 nvlist_t
*nvl
= NULL
;
190 assert(pargp
->ia_cmd
== IPMGMT_CMD_SETPROP
);
192 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
194 if (pargp
->ia_module
[0] != '\0' &&
195 (err
= nvlist_add_string(nvl
, IPADM_NVP_PROTONAME
,
196 pargp
->ia_module
)) != 0) {
199 if (pargp
->ia_ifname
[0] != '\0' &&
200 (err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
201 pargp
->ia_ifname
)) != 0)
203 if (pargp
->ia_aobjname
[0] != '\0' &&
204 (err
= nvlist_add_string(nvl
, IPADM_NVP_AOBJNAME
,
205 pargp
->ia_aobjname
)) != 0)
207 if ((err
= nvlist_add_string(nvl
, pargp
->ia_pname
,
208 pargp
->ia_pval
)) != 0)
212 cb
.dbw_flags
= pargp
->ia_flags
;
213 err
= ipmgmt_db_walk(ipmgmt_db_update
, &cb
, IPADM_DB_WRITE
);
217 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
221 * Helper function for ipmgmt_setaddr_handler().
222 * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
225 i_ipmgmt_nvl2aobjnode(nvlist_t
*nvl
, ipmgmt_aobjmap_t
*nodep
)
227 char *aobjname
= NULL
, *ifname
= NULL
;
230 sa_family_t af
= AF_UNSPEC
;
231 ipadm_addr_type_t addrtype
= IPADM_ADDR_NONE
;
235 * Retrieve all the information needed to build '*nodep' from
238 if ((err
= nvlist_lookup_string(nvl
, IPADM_NVP_AOBJNAME
,
240 (err
= nvlist_lookup_string(nvl
, IPADM_NVP_IFNAME
, &ifname
)) != 0 ||
241 (err
= nvlist_lookup_int32(nvl
, IPADM_NVP_LIFNUM
, &lnum
)) != 0) {
244 if (nvlist_exists(nvl
, IPADM_NVP_IPV4ADDR
)) {
246 addrtype
= IPADM_ADDR_STATIC
;
247 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_DHCP
, &nvladdr
) == 0) {
251 addrtype
= IPADM_ADDR_DHCP
;
254 * ipmgmt_am_reqhost comes through in `nvl' for purposes of
255 * updating the cached representation, but it is persisted as
256 * a stand-alone DB line; so remove it after copying it.
258 if (!nvlist_exists(nvl
, IPADM_NVP_REQHOST
)) {
259 *nodep
->ipmgmt_am_reqhost
= '\0';
261 if ((err
= nvlist_lookup_string(nvl
, IPADM_NVP_REQHOST
,
265 (void) strlcpy(nodep
->ipmgmt_am_reqhost
, reqhost
,
266 sizeof (nodep
->ipmgmt_am_reqhost
));
267 (void) nvlist_remove(nvl
, IPADM_NVP_REQHOST
,
270 } else if (nvlist_exists(nvl
, IPADM_NVP_IPV6ADDR
)) {
272 addrtype
= IPADM_ADDR_STATIC
;
273 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_INTFID
, &nvladdr
) == 0) {
274 struct sockaddr_in6 sin6
= {0};
280 addrtype
= IPADM_ADDR_IPV6_ADDRCONF
;
281 if (nvlist_lookup_uint32(nvladdr
, IPADM_NVP_PREFIXLEN
,
285 if (nvlist_lookup_uint8_array(nvladdr
,
286 IPADM_NVP_IPNUMADDR
, &addr6
, &n
) != 0)
288 bcopy(addr6
, &sin6
.sin6_addr
, n
);
291 nodep
->ipmgmt_am_linklocal
= B_TRUE
;
292 nodep
->ipmgmt_am_ifid
= sin6
;
296 * populate the non-addrtype-specific `*nodep' with retrieved values.
298 (void) strlcpy(nodep
->am_ifname
, ifname
, sizeof (nodep
->am_ifname
));
299 (void) strlcpy(nodep
->am_aobjname
, aobjname
,
300 sizeof (nodep
->am_aobjname
));
301 nodep
->am_lnum
= lnum
;
302 nodep
->am_family
= af
;
303 nodep
->am_atype
= addrtype
;
304 nodep
->am_next
= NULL
;
307 * Do not store logical interface number in persistent store as it
308 * takes different value on reboot. So remove it from `nvl'.
310 if (nvlist_exists(nvl
, IPADM_NVP_LIFNUM
))
311 (void) nvlist_remove(nvl
, IPADM_NVP_LIFNUM
, DATA_TYPE_INT32
);
317 * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
318 * node to the list `aobjmap' and optionally persists the address
319 * information in the DB.
322 ipmgmt_setaddr_handler(void *argp
)
324 ipmgmt_setaddr_arg_t
*sargp
= argp
;
325 ipmgmt_retval_t rval
;
326 ipmgmt_aobjmap_t node
= {0};
327 nvlist_t
*nvl
= NULL
;
329 size_t nvlsize
= sargp
->ia_nvlsize
;
330 uint32_t flags
= sargp
->ia_flags
;
333 nvlbuf
= (char *)argp
+ sizeof (ipmgmt_setaddr_arg_t
);
334 if ((err
= nvlist_unpack(nvlbuf
, nvlsize
, &nvl
, NV_ENCODE_NATIVE
)) != 0)
336 if (flags
& (IPMGMT_ACTIVE
|IPMGMT_INIT
)) {
337 if ((err
= i_ipmgmt_nvl2aobjnode(nvl
, &node
)) != 0)
339 if (flags
& IPMGMT_INIT
)
340 node
.am_flags
= (IPMGMT_ACTIVE
|IPMGMT_PERSIST
);
342 node
.am_flags
= flags
& ~IPMGMT_PROPS_ONLY
;
343 if ((err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
)) != 0)
346 if ((flags
& IPMGMT_PERSIST
) && !(flags
& IPMGMT_PROPS_ONLY
)) {
347 ipadm_dbwrite_cbarg_t cb
;
351 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);
356 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
360 * Handles the door commands that read or modify the `aobjmap' structure.
362 * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
363 * after ensuring that the namespace is not taken. If required, also
364 * generates an `aobjname' for address object for the library to use.
365 * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
366 * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
367 * associated with that logical interface.
368 * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
369 * interface associated with that address object.
372 ipmgmt_aobjop_handler(void *argp
)
374 ipmgmt_aobjop_arg_t
*largp
= argp
;
375 ipmgmt_retval_t rval
;
376 ipmgmt_aobjop_rval_t aobjrval
;
379 ipmgmt_aobjmap_t node
;
381 char *ifname
= largp
->ia_ifname
;
382 char *aobjname
= largp
->ia_aobjname
;
383 int32_t lnum
= largp
->ia_lnum
;
384 sa_family_t af
= largp
->ia_family
;
385 ipadm_addr_type_t atype
= largp
->ia_atype
;
386 ipmgmt_aobjmap_t
*head
;
388 switch (largp
->ia_cmd
) {
389 case IPMGMT_CMD_ADDROBJ_LOOKUPADD
:
390 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
392 bzero(&node
, sizeof (node
));
393 (void) strlcpy(node
.am_aobjname
, aobjname
,
394 sizeof (node
.am_aobjname
));
395 (void) strlcpy(node
.am_ifname
, ifname
,
396 sizeof (node
.am_ifname
));
398 node
.am_atype
= atype
;
399 /* no logical number is associated with this addrobj yet */
401 /* The address object is not persisted yet. */
402 node
.am_flags
= IPMGMT_ACTIVE
;
403 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_LOOKUPADD
);
405 (void) strlcpy(aobjrval
.ir_aobjname
, node
.am_aobjname
,
406 sizeof (aobjrval
.ir_aobjname
));
409 case IPMGMT_CMD_ADDROBJ_SETLIFNUM
:
410 rsize
= sizeof (ipmgmt_retval_t
);
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
));
419 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_SETLIFNUM
);
421 case IPMGMT_CMD_ADDROBJ_ADD
:
422 rsize
= sizeof (ipmgmt_retval_t
);
424 if (aobjname
[0] == '\0' || ifname
[0] == '\0' || lnum
== -1 ||
429 bzero(&node
, sizeof (node
));
430 (void) strlcpy(node
.am_aobjname
, aobjname
,
431 sizeof (node
.am_aobjname
));
432 (void) strlcpy(node
.am_ifname
, ifname
,
433 sizeof (node
.am_ifname
));
434 node
.am_atype
= atype
;
437 /* The address object is not persisted. */
438 node
.am_flags
= IPMGMT_ACTIVE
;
439 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
);
441 case IPMGMT_CMD_AOBJNAME2ADDROBJ
:
442 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
444 bzero(&aobjrval
, sizeof (aobjrval
));
445 if (aobjname
[0] == '\0') {
449 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
450 head
= aobjmap
.aobjmap_head
;
451 for (; head
; head
= head
->am_next
) {
452 if (strcmp(head
->am_aobjname
, aobjname
) != 0)
455 * For an auto-configured interface, return
456 * the lifnum that has the link-local on it.
457 * Other logical interfaces were created for
458 * prefixes and dhcpv6 addresses and do not
461 if (head
->am_atype
!= IPADM_ADDR_IPV6_ADDRCONF
||
462 head
->ipmgmt_am_linklocal
) {
468 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
471 (void) strlcpy(aobjrval
.ir_ifname
, head
->am_ifname
,
472 sizeof (aobjrval
.ir_ifname
));
473 aobjrval
.ir_lnum
= head
->am_lnum
;
474 aobjrval
.ir_family
= head
->am_family
;
475 aobjrval
.ir_flags
= head
->am_flags
;
476 aobjrval
.ir_atype
= head
->am_atype
;
477 aobjrval
.ir_atype_cache
= head
->am_atype_cache
;
478 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
480 case IPMGMT_CMD_LIF2ADDROBJ
:
481 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
483 bzero(&aobjrval
, sizeof (aobjrval
));
484 if (ifname
[0] == '\0') {
488 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
489 head
= aobjmap
.aobjmap_head
;
490 for (; head
; head
= head
->am_next
) {
491 if (strcmp(head
->am_ifname
, ifname
) == 0 &&
492 head
->am_lnum
== lnum
&&
493 head
->am_family
== af
) {
499 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
502 (void) strlcpy(aobjrval
.ir_aobjname
, head
->am_aobjname
,
503 sizeof (aobjrval
.ir_aobjname
));
504 aobjrval
.ir_atype
= head
->am_atype
;
505 aobjrval
.ir_flags
= head
->am_flags
;
506 aobjrval
.ir_atype_cache
= head
->am_atype_cache
;
507 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
510 rsize
= sizeof (ipmgmt_retval_t
);
514 ((ipmgmt_retval_t
*)rvalp
)->ir_err
= err
;
515 (void) door_return((char *)rvalp
, rsize
, NULL
, 0);
519 * Given an interface name and family, deletes all the address objects
520 * associated with it.
523 i_ipmgmt_delif_aobjs(char *ifname
, sa_family_t af
, uint32_t flags
)
525 ipmgmt_aobjmap_t
*head
, *next
, *prev
;
530 (void) pthread_rwlock_wrlock(&aobjmap
.aobjmap_rwlock
);
531 head
= aobjmap
.aobjmap_head
;
532 for (; head
; head
= next
) {
533 next
= head
->am_next
;
534 if (strcmp(head
->am_ifname
, ifname
) != 0 ||
535 head
->am_family
!= af
) {
540 if (head
->am_flags
== (IPMGMT_ACTIVE
|IPMGMT_PERSIST
) &&
541 flags
== IPMGMT_ACTIVE
) {
543 * If the addres is present in both active and
544 * persistent store, and if we are performing
545 * a temporary delete, we update the node to
546 * indicate that the address is only present in
547 * persistent store and we proceed. Otherwise
548 * we always delete the node from aobjmap.
550 head
->am_flags
&= ~IPMGMT_ACTIVE
;
552 db_op
= IPADM_DB_WRITE
;
554 db_op
= IPADM_DB_DELETE
;
556 aobjmap
.aobjmap_head
= next
;
558 prev
->am_next
= next
;
560 (void) ipmgmt_persist_aobjmap(head
, db_op
);
561 if (db_op
== IPADM_DB_DELETE
)
564 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
568 * Handles the door command IPMGMT_CMD_SETIF. It persists the interface
569 * information in the DB.
572 ipmgmt_setif_handler(void *argp
)
574 ipmgmt_retval_t rval
;
576 rval
.ir_err
= ipmgmt_persist_if(argp
);
577 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
581 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
582 * deletes all the persisted interface configuration. It also deletes, from
583 * `aobjmap', all the address objects configured on the given interface.
586 ipmgmt_resetif_handler(void *argp
)
588 ipmgmt_if_arg_t
*rargp
= argp
;
589 ipmgmt_retval_t rval
;
590 ipmgmt_if_cbarg_t cbarg
;
591 uint32_t flags
= rargp
->ia_flags
;
594 cbarg
.cb_family
= rargp
->ia_family
;
595 cbarg
.cb_ifname
= rargp
->ia_ifname
;
596 if (flags
& IPMGMT_PERSIST
)
597 err
= ipmgmt_db_walk(ipmgmt_db_resetif
, &cbarg
,
600 if (flags
& IPMGMT_ACTIVE
)
601 i_ipmgmt_delif_aobjs(rargp
->ia_ifname
, rargp
->ia_family
,
605 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
609 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
610 * deletes all the persisted addrobj configuration. It also deletes the
611 * corresponding node, from `aobjmap'.
614 ipmgmt_resetaddr_handler(void *argp
)
616 ipmgmt_addr_arg_t
*rargp
= argp
;
617 ipmgmt_retval_t rval
;
618 ipmgmt_aobjmap_t node
;
619 uint32_t flags
= rargp
->ia_flags
;
621 ipmgmt_resetaddr_cbarg_t cbarg
;
623 cbarg
.cb_aobjname
= rargp
->ia_aobjname
;
625 if (flags
& IPMGMT_PERSIST
)
626 err
= ipmgmt_db_walk(ipmgmt_db_resetaddr
, &cbarg
,
629 if (flags
& IPMGMT_ACTIVE
) {
630 bzero(&node
, sizeof (node
));
631 (void) strlcpy(node
.am_aobjname
, rargp
->ia_aobjname
,
632 sizeof (node
.am_aobjname
));
635 * am_lnum is used only for IPv6 autoconf case, since there
636 * can be multiple nodes with the same aobjname.
638 node
.am_lnum
= rargp
->ia_lnum
;
639 node
.am_flags
= flags
;
640 (void) ipmgmt_aobjmap_op(&node
, ADDROBJ_DELETE
);
644 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
648 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
649 * address for a given `gargp->ia_aobjname'. If it is not defined then it
650 * retrieves all the addresses configured on `gargp->ia_ifname'. The
651 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
652 * handler through library.
655 ipmgmt_getaddr_handler(void *argp
)
657 size_t buflen
, onvlsize
;
659 ipmgmt_getaddr_arg_t
*gargp
= argp
;
660 ipmgmt_getaddr_cbarg_t cbarg
;
661 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
664 cbarg
.cb_ifname
= gargp
->ia_ifname
;
665 cbarg
.cb_aobjname
= gargp
->ia_aobjname
;
667 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
669 err
= ipmgmt_db_walk(ipmgmt_db_getaddr
, &cbarg
, IPADM_DB_READ
);
670 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
672 * If there is atleast one entry in the nvlist,
673 * do not return error.
680 if ((err
= nvlist_size(cbarg
.cb_onvl
, &onvlsize
,
681 NV_ENCODE_NATIVE
)) != 0) {
684 buflen
= onvlsize
+ sizeof (ipmgmt_get_rval_t
);
686 * We cannot use malloc() here because door_return never returns, and
687 * memory allocated by malloc() would get leaked. Use alloca() instead.
689 buf
= alloca(buflen
);
690 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
691 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &onvlsize
,
692 NV_ENCODE_NATIVE
, 0)) != 0) {
695 nvlist_free(cbarg
.cb_onvl
);
696 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
698 rvalp
->ir_nvlsize
= onvlsize
;
700 (void) door_return(buf
, buflen
, NULL
, 0);
703 nvlist_free(cbarg
.cb_onvl
);
705 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
709 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
713 ipmgmt_resetprop_handler(void *argp
)
715 ipmgmt_prop_arg_t
*pargp
= argp
;
716 ipmgmt_retval_t rval
;
718 assert(pargp
->ia_cmd
== IPMGMT_CMD_RESETPROP
);
720 rval
.ir_err
= ipmgmt_db_walk(ipmgmt_db_resetprop
, pargp
,
722 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
726 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
727 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.
730 ipmgmt_getif_handler(void *argp
)
732 ipmgmt_getif_arg_t
*getif
= argp
;
733 ipmgmt_getif_rval_t
*rvalp
;
734 ipmgmt_retval_t rval
;
735 ipmgmt_getif_cbarg_t cbarg
;
736 ipadm_if_info_t
*ifp
, *rifp
, *curifp
;
737 int i
, err
= 0, count
= 0;
740 assert(getif
->ia_cmd
== IPMGMT_CMD_GETIF
);
742 bzero(&cbarg
, sizeof (cbarg
));
743 cbarg
.cb_ifname
= getif
->ia_ifname
;
744 err
= ipmgmt_db_walk(ipmgmt_db_getif
, &cbarg
, IPADM_DB_READ
);
745 if (err
== ENOENT
&& cbarg
.cb_ifinfo
) {
747 * If there is atleast one entry in the nvlist,
748 * do not return error.
754 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
758 /* allocate sufficient buffer to return the interface info */
759 for (ifp
= cbarg
.cb_ifinfo
; ifp
!= NULL
; ifp
= ifp
->ifi_next
)
761 rbufsize
= sizeof (*rvalp
) + count
* sizeof (*ifp
);
762 rvalp
= alloca(rbufsize
);
763 bzero(rvalp
, rbufsize
);
765 rvalp
->ir_ifcnt
= count
;
766 rifp
= rvalp
->ir_ifinfo
;
767 ifp
= cbarg
.cb_ifinfo
;
770 * copy the interface info to buffer allocated on stack. The reason
771 * we do this is to avoid memory leak, as door_return() would never
774 for (i
= 0; i
< count
; i
++) {
775 rifp
= rvalp
->ir_ifinfo
+ i
;
776 (void) bcopy(ifp
, rifp
, sizeof (*rifp
));
777 rifp
->ifi_next
= NULL
;
778 curifp
= ifp
->ifi_next
;
783 (void) door_return((char *)rvalp
, rbufsize
, NULL
, 0);
787 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
788 * interface configuration (interface properties and addresses), for all those
789 * interfaces that need to be initialized.
792 ipmgmt_initif_handler(void *argp
)
794 ipmgmt_initif_arg_t
*initif
= argp
;
795 size_t buflen
, nvlsize
;
796 char *buf
= NULL
, *onvlbuf
, *invlbuf
;
797 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
798 ipmgmt_initif_cbarg_t cbarg
;
801 assert(initif
->ia_cmd
== IPMGMT_CMD_INITIF
);
803 bzero(&cbarg
, sizeof (cbarg
));
804 invlbuf
= (char *)argp
+ sizeof (ipmgmt_initif_arg_t
);
805 nvlsize
= initif
->ia_nvlsize
;
806 err
= nvlist_unpack(invlbuf
, nvlsize
, &cbarg
.cb_invl
, NV_ENCODE_NATIVE
);
810 cbarg
.cb_family
= initif
->ia_family
;
811 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
814 err
= ipmgmt_db_walk(ipmgmt_db_initif
, &cbarg
, IPADM_DB_READ
);
815 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
817 * If there is atleast one entry in the nvlist,
818 * do not return error.
825 if ((err
= nvlist_size(cbarg
.cb_onvl
, &nvlsize
, NV_ENCODE_NATIVE
)) != 0)
827 buflen
= nvlsize
+ sizeof (ipmgmt_get_rval_t
);
829 * We cannot use malloc() here because door_return never returns, and
830 * memory allocated by malloc() would get leaked. Use alloca() instead.
832 buf
= alloca(buflen
);
833 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
834 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &nvlsize
,
835 NV_ENCODE_NATIVE
, 0)) != 0) {
838 nvlist_free(cbarg
.cb_invl
);
839 nvlist_free(cbarg
.cb_onvl
);
840 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
842 rvalp
->ir_nvlsize
= nvlsize
;
844 (void) door_return(buf
, buflen
, NULL
, 0);
847 nvlist_free(cbarg
.cb_invl
);
848 nvlist_free(cbarg
.cb_onvl
);
850 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
854 ipmgmt_persist_if(ipmgmt_if_arg_t
*sargp
)
856 ipadm_dbwrite_cbarg_t cb
;
857 uint32_t flags
= sargp
->ia_flags
;
858 nvlist_t
*nvl
= NULL
;
860 char strval
[IPMGMT_STRSIZE
];
862 if (!(flags
& IPMGMT_PERSIST
) || sargp
->ia_family
== AF_UNSPEC
||
863 sargp
->ia_ifname
[0] == '\0') {
867 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
869 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
870 sargp
->ia_ifname
)) != 0)
872 (void) snprintf(strval
, IPMGMT_STRSIZE
, "%d", sargp
->ia_family
);
873 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_FAMILY
, strval
)) != 0)
877 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);