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
) {
121 if (door_ucred(&cred
) != 0) {
123 ipmgmt_log(LOG_ERR
, "Could not get user credentials.");
126 uid
= ucred_getruid(cred
);
129 ipmgmt_log(LOG_ERR
, "Could not get user id.");
132 if (getpwuid_r(uid
, &pwd
, buf
, sizeof (buf
)) ==
135 ipmgmt_log(LOG_ERR
, "Could not get password entry.");
138 if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH
,
141 ipmgmt_log(LOG_ERR
, "Not authorized for operation.");
147 /* individual handlers take care of calling door_return */
148 infop
->idi_handler((void *)argp
);
153 (void) door_return((char *)&retval
, sizeof (retval
), NULL
, 0);
157 * Handles the door command IPMGMT_CMD_GETPROP. It retrieves the persisted
158 * property value for the given property.
161 ipmgmt_getprop_handler(void *argp
)
163 ipmgmt_prop_arg_t
*pargp
= argp
;
164 ipmgmt_getprop_rval_t rval
, *rvalp
= &rval
;
166 assert(pargp
->ia_cmd
== IPMGMT_CMD_GETPROP
);
168 rvalp
->ir_err
= ipmgmt_db_walk(ipmgmt_db_getprop
, pargp
, IPADM_DB_READ
);
169 if (rvalp
->ir_err
== 0)
170 (void) strlcpy(rvalp
->ir_pval
, pargp
->ia_pval
,
171 sizeof (rvalp
->ir_pval
));
172 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
176 * Handles the door command IPMGMT_CMD_SETPROP. It persists the property value
177 * for the given property in the DB.
180 ipmgmt_setprop_handler(void *argp
)
182 ipmgmt_prop_arg_t
*pargp
= argp
;
183 ipmgmt_retval_t rval
;
184 ipadm_dbwrite_cbarg_t cb
;
185 nvlist_t
*nvl
= NULL
;
188 assert(pargp
->ia_cmd
== IPMGMT_CMD_SETPROP
);
190 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
192 if (pargp
->ia_module
[0] != '\0' &&
193 (err
= nvlist_add_string(nvl
, IPADM_NVP_PROTONAME
,
194 pargp
->ia_module
)) != 0) {
197 if (pargp
->ia_ifname
[0] != '\0' &&
198 (err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
199 pargp
->ia_ifname
)) != 0)
201 if (pargp
->ia_aobjname
[0] != '\0' &&
202 (err
= nvlist_add_string(nvl
, IPADM_NVP_AOBJNAME
,
203 pargp
->ia_aobjname
)) != 0)
205 if ((err
= nvlist_add_string(nvl
, pargp
->ia_pname
,
206 pargp
->ia_pval
)) != 0)
210 cb
.dbw_flags
= pargp
->ia_flags
;
211 err
= ipmgmt_db_walk(ipmgmt_db_update
, &cb
, IPADM_DB_WRITE
);
215 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
219 * Helper function for ipmgmt_setaddr_handler().
220 * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
223 i_ipmgmt_nvl2aobjnode(nvlist_t
*nvl
, ipmgmt_aobjmap_t
*nodep
)
225 char *aobjname
= NULL
, *ifname
= NULL
;
228 struct sockaddr_storage addr
;
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_exists(nvl
, IPADM_NVP_DHCP
)) {
249 addrtype
= IPADM_ADDR_DHCP
;
250 } else if (nvlist_exists(nvl
, IPADM_NVP_IPV6ADDR
)) {
252 addrtype
= IPADM_ADDR_STATIC
;
253 } else if (nvlist_lookup_nvlist(nvl
, IPADM_NVP_INTFID
, &nvladdr
) == 0) {
254 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&addr
;
259 addrtype
= IPADM_ADDR_IPV6_ADDRCONF
;
260 if (nvlist_lookup_uint32(nvladdr
, IPADM_NVP_PREFIXLEN
,
264 if (nvlist_lookup_uint8_array(nvladdr
,
265 IPADM_NVP_IPNUMADDR
, &addr6
, &n
) != 0)
267 bcopy(addr6
, &sin6
->sin6_addr
, n
);
269 bzero(&sin6
->sin6_addr
, sizeof (sin6
->sin6_addr
));
274 * populate the `*nodep' with retrieved values.
276 (void) strlcpy(nodep
->am_ifname
, ifname
, sizeof (nodep
->am_ifname
));
277 (void) strlcpy(nodep
->am_aobjname
, aobjname
,
278 sizeof (nodep
->am_aobjname
));
279 nodep
->am_lnum
= lnum
;
280 nodep
->am_family
= af
;
281 nodep
->am_atype
= addrtype
;
282 if (addrtype
== IPADM_ADDR_IPV6_ADDRCONF
) {
283 nodep
->am_linklocal
= B_TRUE
;
284 nodep
->am_ifid
= addr
;
286 nodep
->am_next
= NULL
;
289 * Do not store logical interface number in persistent store as it
290 * takes different value on reboot. So remove it from `nvl'.
292 if (nvlist_exists(nvl
, IPADM_NVP_LIFNUM
))
293 (void) nvlist_remove(nvl
, IPADM_NVP_LIFNUM
, DATA_TYPE_INT32
);
299 * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
300 * node to the list `aobjmap' and then persists the address information in the
304 ipmgmt_setaddr_handler(void *argp
)
306 ipmgmt_setaddr_arg_t
*sargp
= argp
;
307 ipmgmt_retval_t rval
;
308 ipmgmt_aobjmap_t node
;
309 nvlist_t
*nvl
= NULL
;
311 size_t nvlsize
= sargp
->ia_nvlsize
;
312 uint32_t flags
= sargp
->ia_flags
;
315 nvlbuf
= (char *)argp
+ sizeof (ipmgmt_setaddr_arg_t
);
316 if ((err
= nvlist_unpack(nvlbuf
, nvlsize
, &nvl
, NV_ENCODE_NATIVE
)) != 0)
318 if (flags
& (IPMGMT_ACTIVE
|IPMGMT_INIT
)) {
319 if ((err
= i_ipmgmt_nvl2aobjnode(nvl
, &node
)) != 0)
321 if (flags
& IPMGMT_INIT
)
322 node
.am_flags
= (IPMGMT_ACTIVE
|IPMGMT_PERSIST
);
324 node
.am_flags
= flags
;
325 if ((err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
)) != 0)
328 if (flags
& IPMGMT_PERSIST
) {
329 ipadm_dbwrite_cbarg_t cb
;
333 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);
338 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
342 * Handles the door commands that modify the `aobjmap' structure.
344 * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
345 * after ensuring that the namespace is not taken. If required, also
346 * generates an `aobjname' for address object for the library to use.
347 * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
348 * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
349 * associated with that logical interface.
350 * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
351 * interface associated with that address object.
354 ipmgmt_aobjop_handler(void *argp
)
356 ipmgmt_aobjop_arg_t
*largp
= argp
;
357 ipmgmt_retval_t rval
;
358 ipmgmt_aobjop_rval_t aobjrval
;
361 ipmgmt_aobjmap_t node
;
363 char *ifname
= largp
->ia_ifname
;
364 char *aobjname
= largp
->ia_aobjname
;
365 int32_t lnum
= largp
->ia_lnum
;
366 sa_family_t af
= largp
->ia_family
;
367 ipadm_addr_type_t atype
= largp
->ia_atype
;
368 ipmgmt_aobjmap_t
*head
;
370 switch (largp
->ia_cmd
) {
371 case IPMGMT_CMD_ADDROBJ_LOOKUPADD
:
372 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
374 bzero(&node
, sizeof (node
));
375 (void) strlcpy(node
.am_aobjname
, aobjname
,
376 sizeof (node
.am_aobjname
));
377 (void) strlcpy(node
.am_ifname
, ifname
,
378 sizeof (node
.am_ifname
));
380 node
.am_atype
= atype
;
381 /* no logical number is associated with this addrobj yet */
383 /* The address object is not persisted yet. */
384 node
.am_flags
= IPMGMT_ACTIVE
;
385 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_LOOKUPADD
);
387 (void) strlcpy(aobjrval
.ir_aobjname
, node
.am_aobjname
,
388 sizeof (aobjrval
.ir_aobjname
));
391 case IPMGMT_CMD_ADDROBJ_SETLIFNUM
:
392 rsize
= sizeof (ipmgmt_retval_t
);
394 bzero(&node
, sizeof (node
));
395 (void) strlcpy(node
.am_aobjname
, aobjname
,
396 sizeof (node
.am_aobjname
));
397 (void) strlcpy(node
.am_ifname
, ifname
,
398 sizeof (node
.am_ifname
));
401 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_SETLIFNUM
);
403 case IPMGMT_CMD_ADDROBJ_ADD
:
404 rsize
= sizeof (ipmgmt_retval_t
);
406 if (aobjname
[0] == '\0' || ifname
[0] == '\0' || lnum
== -1 ||
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
));
416 node
.am_atype
= atype
;
419 /* The address object is not persisted. */
420 node
.am_flags
= IPMGMT_ACTIVE
;
421 err
= ipmgmt_aobjmap_op(&node
, ADDROBJ_ADD
);
423 case IPMGMT_CMD_AOBJNAME2ADDROBJ
:
424 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
426 bzero(&aobjrval
, sizeof (aobjrval
));
427 if (aobjname
[0] == '\0') {
431 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
432 head
= aobjmap
.aobjmap_head
;
433 for (; head
; head
= head
->am_next
) {
434 if (strcmp(head
->am_aobjname
, aobjname
) != 0)
437 * For an auto-configured interface, return
438 * the lifnum that has the link-local on it.
439 * Other logical interfaces were created for
440 * prefixes and dhcpv6 addresses and do not
443 if (head
->am_atype
!= IPADM_ADDR_IPV6_ADDRCONF
||
444 head
->am_linklocal
) {
450 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
453 (void) strlcpy(aobjrval
.ir_ifname
, head
->am_ifname
,
454 sizeof (aobjrval
.ir_ifname
));
455 aobjrval
.ir_lnum
= head
->am_lnum
;
456 aobjrval
.ir_family
= head
->am_family
;
457 aobjrval
.ir_flags
= head
->am_flags
;
458 aobjrval
.ir_atype
= head
->am_atype
;
459 if (head
->am_atype
== IPADM_ADDR_IPV6_ADDRCONF
&&
461 aobjrval
.ir_ifid
= head
->am_ifid
;
462 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
464 case IPMGMT_CMD_LIF2ADDROBJ
:
465 rsize
= sizeof (ipmgmt_aobjop_rval_t
);
467 bzero(&aobjrval
, sizeof (aobjrval
));
468 if (ifname
[0] == '\0') {
472 (void) pthread_rwlock_rdlock(&aobjmap
.aobjmap_rwlock
);
473 head
= aobjmap
.aobjmap_head
;
474 for (; head
; head
= head
->am_next
) {
475 if (strcmp(head
->am_ifname
, ifname
) == 0 &&
476 head
->am_lnum
== lnum
&&
477 head
->am_family
== af
) {
483 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
486 (void) strlcpy(aobjrval
.ir_aobjname
, head
->am_aobjname
,
487 sizeof (aobjrval
.ir_aobjname
));
488 aobjrval
.ir_atype
= head
->am_atype
;
489 aobjrval
.ir_flags
= head
->am_flags
;
490 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
493 rsize
= sizeof (ipmgmt_retval_t
);
497 ((ipmgmt_retval_t
*)rvalp
)->ir_err
= err
;
498 (void) door_return((char *)rvalp
, rsize
, NULL
, 0);
502 * Given an interface name and family, deletes all the address objects
503 * associated with it.
506 i_ipmgmt_delif_aobjs(char *ifname
, sa_family_t af
, uint32_t flags
)
508 ipmgmt_aobjmap_t
*head
, *next
, *prev
;
513 (void) pthread_rwlock_wrlock(&aobjmap
.aobjmap_rwlock
);
514 head
= aobjmap
.aobjmap_head
;
515 for (; head
; head
= next
) {
516 next
= head
->am_next
;
517 if (strcmp(head
->am_ifname
, ifname
) != 0 ||
518 head
->am_family
!= af
) {
523 if (head
->am_flags
== (IPMGMT_ACTIVE
|IPMGMT_PERSIST
) &&
524 flags
== IPMGMT_ACTIVE
) {
526 * If the addres is present in both active and
527 * persistent store, and if we are performing
528 * a temporary delete, we update the node to
529 * indicate that the address is only present in
530 * persistent store and we proceed. Otherwise
531 * we always delete the node from aobjmap.
533 head
->am_flags
&= ~IPMGMT_ACTIVE
;
535 db_op
= IPADM_DB_WRITE
;
537 db_op
= IPADM_DB_DELETE
;
539 aobjmap
.aobjmap_head
= next
;
541 prev
->am_next
= next
;
543 (void) ipmgmt_persist_aobjmap(head
, db_op
);
544 if (db_op
== IPADM_DB_DELETE
)
547 (void) pthread_rwlock_unlock(&aobjmap
.aobjmap_rwlock
);
551 * Handles the door command IPMGMT_CMD_SETIF. It persists the interface
552 * information in the DB.
555 ipmgmt_setif_handler(void *argp
)
557 ipmgmt_retval_t rval
;
559 rval
.ir_err
= ipmgmt_persist_if(argp
);
560 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
564 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
565 * deletes all the persisted interface configuration. It also deletes, from
566 * `aobjmap', all the address objects configured on the given interface.
569 ipmgmt_resetif_handler(void *argp
)
571 ipmgmt_if_arg_t
*rargp
= argp
;
572 ipmgmt_retval_t rval
;
573 ipmgmt_if_cbarg_t cbarg
;
574 uint32_t flags
= rargp
->ia_flags
;
577 cbarg
.cb_family
= rargp
->ia_family
;
578 cbarg
.cb_ifname
= rargp
->ia_ifname
;
579 if (flags
& IPMGMT_PERSIST
)
580 err
= ipmgmt_db_walk(ipmgmt_db_resetif
, &cbarg
,
583 if (flags
& IPMGMT_ACTIVE
)
584 i_ipmgmt_delif_aobjs(rargp
->ia_ifname
, rargp
->ia_family
,
588 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
592 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
593 * deletes all the persisted addrobj configuration. It also deletes the
594 * corresponding node, from `aobjmap'.
597 ipmgmt_resetaddr_handler(void *argp
)
599 ipmgmt_addr_arg_t
*rargp
= argp
;
600 ipmgmt_retval_t rval
;
601 ipmgmt_aobjmap_t node
;
602 uint32_t flags
= rargp
->ia_flags
;
604 ipmgmt_resetaddr_cbarg_t cbarg
;
606 cbarg
.cb_aobjname
= rargp
->ia_aobjname
;
608 if (flags
& IPMGMT_PERSIST
)
609 err
= ipmgmt_db_walk(ipmgmt_db_resetaddr
, &cbarg
,
612 if (flags
& IPMGMT_ACTIVE
) {
613 bzero(&node
, sizeof (node
));
614 (void) strlcpy(node
.am_aobjname
, rargp
->ia_aobjname
,
615 sizeof (node
.am_aobjname
));
618 * am_lnum is used only for IPv6 autoconf case, since there
619 * can be multiple nodes with the same aobjname.
621 node
.am_lnum
= rargp
->ia_lnum
;
622 node
.am_flags
= flags
;
623 (void) ipmgmt_aobjmap_op(&node
, ADDROBJ_DELETE
);
627 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
631 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
632 * address for a given `gargp->ia_aobjname'. If it is not defined then it
633 * retrieves all the addresses configured on `gargp->ia_ifname'. The
634 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
635 * handler through library.
638 ipmgmt_getaddr_handler(void *argp
)
640 size_t buflen
, onvlsize
;
642 ipmgmt_getaddr_arg_t
*gargp
= argp
;
643 ipmgmt_getaddr_cbarg_t cbarg
;
644 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
647 cbarg
.cb_ifname
= gargp
->ia_ifname
;
648 cbarg
.cb_aobjname
= gargp
->ia_aobjname
;
650 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
652 err
= ipmgmt_db_walk(ipmgmt_db_getaddr
, &cbarg
, IPADM_DB_READ
);
653 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
655 * If there is atleast one entry in the nvlist,
656 * do not return error.
663 if ((err
= nvlist_size(cbarg
.cb_onvl
, &onvlsize
,
664 NV_ENCODE_NATIVE
)) != 0) {
667 buflen
= onvlsize
+ sizeof (ipmgmt_get_rval_t
);
669 * We cannot use malloc() here because door_return never returns, and
670 * memory allocated by malloc() would get leaked. Use alloca() instead.
672 buf
= alloca(buflen
);
673 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
674 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &onvlsize
,
675 NV_ENCODE_NATIVE
, 0)) != 0) {
678 nvlist_free(cbarg
.cb_onvl
);
679 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
681 rvalp
->ir_nvlsize
= onvlsize
;
683 (void) door_return(buf
, buflen
, NULL
, 0);
686 nvlist_free(cbarg
.cb_onvl
);
688 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
692 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
696 ipmgmt_resetprop_handler(void *argp
)
698 ipmgmt_prop_arg_t
*pargp
= argp
;
699 ipmgmt_retval_t rval
;
701 assert(pargp
->ia_cmd
== IPMGMT_CMD_RESETPROP
);
703 rval
.ir_err
= ipmgmt_db_walk(ipmgmt_db_resetprop
, pargp
,
705 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
709 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
710 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.
713 ipmgmt_getif_handler(void *argp
)
715 ipmgmt_getif_arg_t
*getif
= argp
;
716 ipmgmt_getif_rval_t
*rvalp
;
717 ipmgmt_retval_t rval
;
718 ipmgmt_getif_cbarg_t cbarg
;
719 ipadm_if_info_t
*ifp
, *rifp
, *curifp
;
720 int i
, err
= 0, count
= 0;
723 assert(getif
->ia_cmd
== IPMGMT_CMD_GETIF
);
725 bzero(&cbarg
, sizeof (cbarg
));
726 cbarg
.cb_ifname
= getif
->ia_ifname
;
727 err
= ipmgmt_db_walk(ipmgmt_db_getif
, &cbarg
, IPADM_DB_READ
);
728 if (err
== ENOENT
&& cbarg
.cb_ifinfo
) {
730 * If there is atleast one entry in the nvlist,
731 * do not return error.
737 (void) door_return((char *)&rval
, sizeof (rval
), NULL
, 0);
741 /* allocate sufficient buffer to return the interface info */
742 for (ifp
= cbarg
.cb_ifinfo
; ifp
!= NULL
; ifp
= ifp
->ifi_next
)
744 rbufsize
= sizeof (*rvalp
) + count
* sizeof (*ifp
);
745 rvalp
= alloca(rbufsize
);
746 bzero(rvalp
, rbufsize
);
748 rvalp
->ir_ifcnt
= count
;
749 rifp
= rvalp
->ir_ifinfo
;
750 ifp
= cbarg
.cb_ifinfo
;
753 * copy the interface info to buffer allocated on stack. The reason
754 * we do this is to avoid memory leak, as door_return() would never
757 for (i
= 0; i
< count
; i
++) {
758 rifp
= rvalp
->ir_ifinfo
+ i
;
759 (void) bcopy(ifp
, rifp
, sizeof (*rifp
));
760 rifp
->ifi_next
= NULL
;
761 curifp
= ifp
->ifi_next
;
766 (void) door_return((char *)rvalp
, rbufsize
, NULL
, 0);
770 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
771 * interface configuration (interface properties and addresses), for all those
772 * interfaces that need to be initialized.
775 ipmgmt_initif_handler(void *argp
)
777 ipmgmt_initif_arg_t
*initif
= argp
;
778 size_t buflen
, nvlsize
;
779 char *buf
= NULL
, *onvlbuf
, *invlbuf
;
780 ipmgmt_get_rval_t rval
, *rvalp
= &rval
;
781 ipmgmt_initif_cbarg_t cbarg
;
784 assert(initif
->ia_cmd
== IPMGMT_CMD_INITIF
);
786 bzero(&cbarg
, sizeof (cbarg
));
787 invlbuf
= (char *)argp
+ sizeof (ipmgmt_initif_arg_t
);
788 nvlsize
= initif
->ia_nvlsize
;
789 err
= nvlist_unpack(invlbuf
, nvlsize
, &cbarg
.cb_invl
, NV_ENCODE_NATIVE
);
793 cbarg
.cb_family
= initif
->ia_family
;
794 if (nvlist_alloc(&cbarg
.cb_onvl
, NV_UNIQUE_NAME
, 0) != 0)
797 err
= ipmgmt_db_walk(ipmgmt_db_initif
, &cbarg
, IPADM_DB_READ
);
798 if (err
== ENOENT
&& cbarg
.cb_ocnt
> 0) {
800 * If there is atleast one entry in the nvlist,
801 * do not return error.
808 if ((err
= nvlist_size(cbarg
.cb_onvl
, &nvlsize
, NV_ENCODE_NATIVE
)) != 0)
810 buflen
= nvlsize
+ sizeof (ipmgmt_get_rval_t
);
812 * We cannot use malloc() here because door_return never returns, and
813 * memory allocated by malloc() would get leaked. Use alloca() instead.
815 buf
= alloca(buflen
);
816 onvlbuf
= buf
+ sizeof (ipmgmt_get_rval_t
);
817 if ((err
= nvlist_pack(cbarg
.cb_onvl
, &onvlbuf
, &nvlsize
,
818 NV_ENCODE_NATIVE
, 0)) != 0) {
821 nvlist_free(cbarg
.cb_invl
);
822 nvlist_free(cbarg
.cb_onvl
);
823 rvalp
= (ipmgmt_get_rval_t
*)(void *)buf
;
825 rvalp
->ir_nvlsize
= nvlsize
;
827 (void) door_return(buf
, buflen
, NULL
, 0);
830 nvlist_free(cbarg
.cb_invl
);
831 nvlist_free(cbarg
.cb_onvl
);
833 (void) door_return((char *)rvalp
, sizeof (*rvalp
), NULL
, 0);
837 ipmgmt_persist_if(ipmgmt_if_arg_t
*sargp
)
839 ipadm_dbwrite_cbarg_t cb
;
840 uint32_t flags
= sargp
->ia_flags
;
841 nvlist_t
*nvl
= NULL
;
843 char strval
[IPMGMT_STRSIZE
];
845 if (!(flags
& IPMGMT_PERSIST
) || sargp
->ia_family
== AF_UNSPEC
||
846 sargp
->ia_ifname
[0] == '\0') {
850 if ((err
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0)) != 0)
852 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_IFNAME
,
853 sargp
->ia_ifname
)) != 0)
855 (void) snprintf(strval
, IPMGMT_STRSIZE
, "%d", sargp
->ia_family
);
856 if ((err
= nvlist_add_string(nvl
, IPADM_NVP_FAMILY
, strval
)) != 0)
860 err
= ipmgmt_db_walk(ipmgmt_db_add
, &cb
, IPADM_DB_WRITE
);