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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Main door handler functions used by ipmgmtd to process the different door
28 * call requests, issued by the library libipadm.so.
29 */
30
31 #include <alloca.h>
32 #include <pwd.h>
33 #include <auth_attr.h>
34 #include <secdb.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <errno.h>
40 #include <assert.h>
41 #include <libnvpair.h>
42 #include "ipmgmt_impl.h"
43
44 /* Handler declaration for each door command */
45 typedef void ipmgmt_door_handler_t(void *argp);
46
47 static ipmgmt_door_handler_t ipmgmt_getaddr_handler,
48 ipmgmt_getprop_handler,
49 ipmgmt_getif_handler,
50 ipmgmt_initif_handler,
51 ipmgmt_aobjop_handler,
52 ipmgmt_resetaddr_handler,
53 ipmgmt_setif_handler,
54 ipmgmt_resetif_handler,
55 ipmgmt_resetprop_handler,
56 ipmgmt_setaddr_handler,
57 ipmgmt_setprop_handler;
58
59 typedef struct ipmgmt_door_info_s {
60 uint_t idi_cmd;
61 boolean_t idi_set;
62 ipmgmt_door_handler_t *idi_handler;
63 } ipmgmt_door_info_t;
64
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 },
82 { 0, 0, NULL },
83 };
84
85 /*
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.
89 */
90 /* ARGSUSED */
91 void
92 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
93 uint_t n_desc)
94 {
95 ipmgmt_door_info_t *infop = NULL;
96 ipmgmt_retval_t retval;
97 int i;
98 uint_t err;
99 ucred_t *cred = NULL;
100
101 for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {
559 rval.ir_err = ipmgmt_persist_if(argp);
560 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
561 }
562
563 /*
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.
567 */
568 static void
569 ipmgmt_resetif_handler(void *argp)
570 {
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;
575 int err = 0;
576
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,
581 IPADM_DB_DELETE);
582
583 if (flags & IPMGMT_ACTIVE)
584 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
585 flags);
586
587 rval.ir_err = err;
588 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
589 }
590
591 /*
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'.
595 */
596 static void
597 ipmgmt_resetaddr_handler(void *argp)
598 {
620 */
621 node.am_lnum = rargp->ia_lnum;
622 node.am_flags = flags;
623 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
624 }
625
626 rval.ir_err = err;
627 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
628 }
629
630 /*
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.
636 */
637 static void
638 ipmgmt_getaddr_handler(void *argp)
639 {
640 size_t buflen, onvlsize;
641 char *buf, *onvlbuf;
642 ipmgmt_getaddr_arg_t *gargp = argp;
643 ipmgmt_getaddr_cbarg_t cbarg;
644 ipmgmt_get_rval_t rval, *rvalp = &rval;
645 int err = 0;
646
647 cbarg.cb_ifname = gargp->ia_ifname;
648 cbarg.cb_aobjname = gargp->ia_aobjname;
649 cbarg.cb_ocnt = 0;
650 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
651 goto fail;
652 err = ipmgmt_db_walk(ipmgmt_db_getaddr, &cbarg, IPADM_DB_READ);
653 if (err == ENOENT && cbarg.cb_ocnt > 0) {
654 /*
655 * If there is atleast one entry in the nvlist,
656 * do not return error.
657 */
658 err = 0;
659 }
660 if (err != 0)
661 goto fail;
662
663 if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize,
664 NV_ENCODE_NATIVE)) != 0) {
665 goto fail;
666 }
667 buflen = onvlsize + sizeof (ipmgmt_get_rval_t);
668 /*
669 * We cannot use malloc() here because door_return never returns, and
670 * memory allocated by malloc() would get leaked. Use alloca() instead.
671 */
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) {
676 goto fail;
677 }
678 nvlist_free(cbarg.cb_onvl);
679 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
680 rvalp->ir_err = 0;
681 rvalp->ir_nvlsize = onvlsize;
682
683 (void) door_return(buf, buflen, NULL, 0);
684 return;
685 fail:
686 nvlist_free(cbarg.cb_onvl);
687 rvalp->ir_err = err;
688 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
689 }
690
691 /*
692 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
693 * from the DB.
694 */
695 static void
696 ipmgmt_resetprop_handler(void *argp)
697 {
698 ipmgmt_prop_arg_t *pargp = argp;
699 ipmgmt_retval_t rval;
700
701 assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
702
703 rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
704 IPADM_DB_DELETE);
705 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
706 }
707
708 /*
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.
711 */
712 static void
713 ipmgmt_getif_handler(void *argp)
714 {
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;
721 size_t rbufsize;
722
723 assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
724
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) {
729 /*
730 * If there is atleast one entry in the nvlist,
731 * do not return error.
732 */
733 err = 0;
734 }
735 if (err != 0) {
736 rval.ir_err = err;
737 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
738 return;
739 }
740
741 /* allocate sufficient buffer to return the interface info */
742 for (ifp = cbarg.cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next)
743 ++count;
744 rbufsize = sizeof (*rvalp) + count * sizeof (*ifp);
745 rvalp = alloca(rbufsize);
746 bzero(rvalp, rbufsize);
747
748 rvalp->ir_ifcnt = count;
749 rifp = rvalp->ir_ifinfo;
750 ifp = cbarg.cb_ifinfo;
751
752 /*
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
755 * return
756 */
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;
762 free(ifp);
763 ifp = curifp;
764 }
765 rvalp->ir_err = err;
766 (void) door_return((char *)rvalp, rbufsize, NULL, 0);
767 }
768
769 /*
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.
773 */
774 static void
775 ipmgmt_initif_handler(void *argp)
776 {
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;
782 int err;
783
784 assert(initif->ia_cmd == IPMGMT_CMD_INITIF);
785
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);
790 if (err != 0)
791 goto fail;
792
793 cbarg.cb_family = initif->ia_family;
794 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
795 goto fail;
796
797 err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
798 if (err == ENOENT && cbarg.cb_ocnt > 0) {
799 /*
800 * If there is atleast one entry in the nvlist,
801 * do not return error.
802 */
803 err = 0;
804 }
805 if (err != 0)
806 goto fail;
807
808 if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
809 goto fail;
810 buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
811 /*
812 * We cannot use malloc() here because door_return never returns, and
813 * memory allocated by malloc() would get leaked. Use alloca() instead.
814 */
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) {
819 goto fail;
820 }
822 nvlist_free(cbarg.cb_onvl);
823 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
824 rvalp->ir_err = 0;
825 rvalp->ir_nvlsize = nvlsize;
826
827 (void) door_return(buf, buflen, NULL, 0);
828 return;
829 fail:
830 nvlist_free(cbarg.cb_invl);
831 nvlist_free(cbarg.cb_onvl);
832 rvalp->ir_err = err;
833 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
834 }
835
836 int
837 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
838 {
839 ipadm_dbwrite_cbarg_t cb;
840 uint32_t flags = sargp->ia_flags;
841 nvlist_t *nvl = NULL;
842 int err = 0;
843 char strval[IPMGMT_STRSIZE];
844
845 if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
846 sargp->ia_ifname[0] == '\0') {
847 err = EINVAL;
848 goto ret;
849 }
850 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
851 goto ret;
852 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
853 sargp->ia_ifname)) != 0)
854 goto ret;
855 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
856 if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
857 goto ret;
858 cb.dbw_nvl = nvl;
859 cb.dbw_flags = 0;
860 err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
861 ret:
862 nvlist_free(nvl);
863 return (err);
864 }
|
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 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * Main door handler functions used by ipmgmtd to process the different door
29 * call requests, issued by the library libipadm.so.
30 */
31
32 #include <alloca.h>
33 #include <pwd.h>
34 #include <auth_attr.h>
35 #include <secdb.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <errno.h>
41 #include <assert.h>
42 #include <libnvpair.h>
43 #include "ipmgmt_impl.h"
44
45
46 static void ipmgmt_common_handler(char *, char *, db_wfunc_t *);
47
48 /* Handler declaration for each door command */
49 typedef void ipmgmt_door_handler_t(void *argp);
50
51 static ipmgmt_door_handler_t ipmgmt_getaddr_handler,
52 ipmgmt_getprop_handler,
53 ipmgmt_getif_handler,
54 ipmgmt_initif_handler,
55 ipmgmt_aobjop_handler,
56 ipmgmt_resetaddr_handler,
57 ipmgmt_setif_handler,
58 ipmgmt_resetif_handler,
59 ipmgmt_resetprop_handler,
60 ipmgmt_setaddr_handler,
61 ipmgmt_setprop_handler,
62 ipmgmt_ipmp_update_handler;
63
64 typedef struct ipmgmt_door_info_s {
65 uint_t idi_cmd;
66 boolean_t idi_set;
67 ipmgmt_door_handler_t *idi_handler;
68 } ipmgmt_door_info_t;
69
70 /* maps door commands to door handler functions */
71 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
72 { IPMGMT_CMD_SETPROP, B_TRUE, ipmgmt_setprop_handler },
73 { IPMGMT_CMD_SETIF, B_TRUE, ipmgmt_setif_handler },
74 { IPMGMT_CMD_SETADDR, B_TRUE, ipmgmt_setaddr_handler },
75 { IPMGMT_CMD_GETPROP, B_FALSE, ipmgmt_getprop_handler },
76 { IPMGMT_CMD_GETIF, B_FALSE, ipmgmt_getif_handler },
77 { IPMGMT_CMD_GETADDR, B_FALSE, ipmgmt_getaddr_handler },
78 { IPMGMT_CMD_RESETIF, B_TRUE, ipmgmt_resetif_handler },
79 { IPMGMT_CMD_RESETADDR, B_TRUE, ipmgmt_resetaddr_handler },
80 { IPMGMT_CMD_RESETPROP, B_TRUE, ipmgmt_resetprop_handler },
81 { IPMGMT_CMD_INITIF, B_TRUE, ipmgmt_initif_handler },
82 { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE, ipmgmt_aobjop_handler },
83 { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE, ipmgmt_aobjop_handler },
84 { IPMGMT_CMD_ADDROBJ_ADD, B_TRUE, ipmgmt_aobjop_handler },
85 { IPMGMT_CMD_AOBJNAME2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler },
86 { IPMGMT_CMD_LIF2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler },
87 { IPMGMT_CMD_IPMP_UPDATE, B_FALSE, ipmgmt_ipmp_update_handler},
88 { 0, 0, NULL },
89 };
90
91 /*
92 * The main server procedure function that gets invoked for any of the incoming
93 * door commands. Inside this function we identify the incoming command and
94 * invoke the right door handler function.
95 */
96 /* ARGSUSED */
97 void
98 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
99 uint_t n_desc)
100 {
101 ipmgmt_door_info_t *infop = NULL;
102 ipmgmt_retval_t retval;
103 int i;
104 uint_t err;
105 ucred_t *cred = NULL;
106
107 for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {
565 rval.ir_err = ipmgmt_persist_if(argp);
566 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
567 }
568
569 /*
570 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
571 * deletes all the persisted interface configuration. It also deletes, from
572 * `aobjmap', all the address objects configured on the given interface.
573 */
574 static void
575 ipmgmt_resetif_handler(void *argp)
576 {
577 ipmgmt_if_arg_t *rargp = argp;
578 ipmgmt_retval_t rval;
579 ipmgmt_if_cbarg_t cbarg;
580 uint32_t flags = rargp->ia_flags;
581 int err = 0;
582
583 cbarg.cb_family = rargp->ia_family;
584 cbarg.cb_ifname = rargp->ia_ifname;
585
586 cbarg.cb_ipv4exists = B_TRUE;
587 cbarg.cb_ipv6exists = B_TRUE;
588
589 if (flags & IPMGMT_PERSIST)
590 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
591 IPADM_DB_DELETE);
592
593 if (flags & IPMGMT_ACTIVE)
594 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
595 flags);
596
597 rval.ir_err = err;
598 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
599 }
600
601 /*
602 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
603 * deletes all the persisted addrobj configuration. It also deletes the
604 * corresponding node, from `aobjmap'.
605 */
606 static void
607 ipmgmt_resetaddr_handler(void *argp)
608 {
630 */
631 node.am_lnum = rargp->ia_lnum;
632 node.am_flags = flags;
633 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
634 }
635
636 rval.ir_err = err;
637 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
638 }
639
640 /*
641 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
642 * address for a given `gargp->ia_aobjname'. If it is not defined then it
643 * retrieves all the addresses configured on `gargp->ia_ifname'. The
644 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
645 * handler through library.
646 */
647 static void
648 ipmgmt_getaddr_handler(void *argp)
649 {
650 ipmgmt_getaddr_arg_t *gargp = argp;
651
652 ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname,
653 ipmgmt_db_getaddr);
654 }
655
656 /*
657 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
658 * from the DB.
659 */
660 static void
661 ipmgmt_resetprop_handler(void *argp)
662 {
663 ipmgmt_prop_arg_t *pargp = argp;
664 ipmgmt_retval_t rval;
665
666 assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
667
668 rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
669 IPADM_DB_DELETE);
670 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
671 }
672
673 /*
674 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
675 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support and
676 * returns the info as a nvlist
677 */
678 static void
679 ipmgmt_getif_handler(void *argp)
680 {
681 ipmgmt_getif_arg_t *getif = argp;
682
683 assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
684
685 ipmgmt_common_handler(getif->ia_ifname, NULL,
686 ipmgmt_db_getif);
687 }
688
689 /*
690 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
691 * interface configuration (interface properties and addresses), for all those
692 * interfaces that need to be initialized.
693 */
694 static void
695 ipmgmt_initif_handler(void *argp)
696 {
697 ipmgmt_initif_arg_t *initif = argp;
698 size_t buflen, nvlsize;
699 char *buf = NULL, *onvlbuf, *invlbuf;
700 ipmgmt_get_rval_t rval, *rvalp = &rval;
701 ipmgmt_initif_cbarg_t cbarg;
702 int err;
703
704 assert(initif->ia_cmd == IPMGMT_CMD_INITIF);
705
706 bzero(&cbarg, sizeof (cbarg));
707 invlbuf = (char *)argp + sizeof (ipmgmt_initif_arg_t);
708 nvlsize = initif->ia_nvlsize;
709 err = nvlist_unpack(invlbuf, nvlsize, &cbarg.cb_invl, NV_ENCODE_NATIVE);
710 if (err != 0)
711 goto fail;
712
713 cbarg.cb_family = initif->ia_family;
714 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
715 goto fail;
716
717 err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
718 if (err == ENOENT && cbarg.cb_ocnt > 0) {
719 /*
720 * If there is at least one entry in the nvlist,
721 * do not return error.
722 */
723 err = 0;
724 }
725 if (err != 0)
726 goto fail;
727
728 if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
729 goto fail;
730 buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
731 /*
732 * We cannot use malloc() here because door_return never returns, and
733 * memory allocated by malloc() would get leaked. Use alloca() instead.
734 */
735 buf = alloca(buflen);
736 onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
737 if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &nvlsize,
738 NV_ENCODE_NATIVE, 0)) != 0) {
739 goto fail;
740 }
742 nvlist_free(cbarg.cb_onvl);
743 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
744 rvalp->ir_err = 0;
745 rvalp->ir_nvlsize = nvlsize;
746
747 (void) door_return(buf, buflen, NULL, 0);
748 return;
749 fail:
750 nvlist_free(cbarg.cb_invl);
751 nvlist_free(cbarg.cb_onvl);
752 rvalp->ir_err = err;
753 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
754 }
755
756 int
757 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
758 {
759 ipadm_dbwrite_cbarg_t cb;
760 uint32_t flags = sargp->ia_flags;
761 nvlist_t *nvl = NULL;
762 char strval[IPMGMT_STRSIZE];
763 int err = 0;
764
765 if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
766 sargp->ia_ifname[0] == '\0') {
767 err = EINVAL;
768 goto ret;
769 }
770 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
771 goto ret;
772
773 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
774 sargp->ia_ifname)) != 0)
775 goto ret;
776
777 if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family,
778 IPMGMT_APPEND)) != 0)
779 goto ret;
780
781 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_ifclass);
782 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFCLASS, strval)) != 0)
783 goto ret;
784
785 cb.dbw_nvl = nvl;
786 cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF;
787 err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
788 ret:
789 nvlist_free(nvl);
790 return (err);
791 }
792
793 /*
794 * The helper for ipmgmt_getif_handler and ipmgmt_getaddr_handler
795 */
796 static void
797 ipmgmt_common_handler(char *if_name, char *aobj_name, db_wfunc_t worker)
798 {
799 ipmgmt_get_rval_t rval, *rvalp = &rval;
800 ipmgmt_get_cbarg_t cbarg;
801 int err = 0;
802 size_t buflen, onvlsize;
803 char *buf, *onvlbuf;
804
805 cbarg.cb_ifname = if_name;
806 cbarg.cb_aobjname = aobj_name;
807 cbarg.cb_ocnt = 0;
808
809 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
810 goto fail;
811
812 err = ipmgmt_db_walk(worker, &cbarg, IPADM_DB_READ);
813 if (err == ENOENT && cbarg.cb_ocnt > 0) {
814 /*
815 * If there is atleast one entry in the nvlist,
816 * do not return error.
817 */
818 err = 0;
819 }
820 if (err != 0)
821 goto fail;
822
823 if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize,
824 NV_ENCODE_NATIVE)) != 0)
825 goto fail;
826
827 buflen = onvlsize + sizeof (ipmgmt_get_rval_t);
828 /* We cannot use malloc() here because door_return never returns */
829 buf = alloca(buflen);
830 onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
831 if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf,
832 &onvlsize, NV_ENCODE_NATIVE, 0)) != 0)
833 goto fail;
834
835 nvlist_free(cbarg.cb_onvl);
836 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
837 rvalp->ir_err = 0;
838 rvalp->ir_nvlsize = onvlsize;
839
840 (void) door_return(buf, buflen, NULL, 0);
841 return;
842
843 fail:
844 nvlist_free(cbarg.cb_onvl);
845 rvalp->ir_err = err;
846 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
847 }
848
849 /*
850 * Handles the door command IPMGMT_CMD_IPMP_UPDATE
851 */
852 static void
853 ipmgmt_ipmp_update_handler(void *argp)
854 {
855 ipmgmt_ipmp_update_arg_t *uargp = argp;
856 ipmgmt_retval_t rval;
857 ipadm_dbwrite_cbarg_t cb;
858
859 boolean_t gif_exists;
860 char gifname[LIFNAMSIZ];
861 nvlist_t *nvl = NULL;
862 uint32_t flags = uargp->ia_flags;
863 int err = 0;
864
865 assert(uargp->ia_cmd == IPMGMT_CMD_IPMP_UPDATE);
866
867 gif_exists = ipmgmt_persist_if_exists(uargp->ia_gifname,
868 AF_UNSPEC);
869
870 if (!ipmgmt_persist_if_exists(uargp->ia_mifname, AF_UNSPEC)) {
871 err = EINVAL;
872 goto ret;
873 }
874
875 ipmgmt_get_group_interface(uargp->ia_mifname, gifname, LIFNAMSIZ);
876
877 if (flags & IPMGMT_APPEND) {
878 /* group interface should be available in the DB */
879 if (!gif_exists) {
880 err = ENOENT;
881 goto ret;
882 }
883
884 if (gifname[0] != '\0') {
885 err = EEXIST;
886 goto ret;
887 }
888 }
889
890 if (flags & IPMGMT_REMOVE) {
891 /* We cannot remove something that does not exist */
892 if (!gif_exists || gifname[0] == '\0') {
893 err = ENOENT;
894 goto ret;
895 }
896 if (strcmp(uargp->ia_gifname, gifname) != 0) {
897 err = EINVAL;
898 goto ret;
899 }
900 }
901
902 if (flags & IPMGMT_PERSIST) {
903
904 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
905 goto ret;
906
907 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
908 uargp->ia_gifname)) != 0)
909 goto ret;
910
911 if ((err = nvlist_add_string(nvl, IPADM_NVP_MIFNAMES,
912 uargp->ia_mifname)) != 0)
913 goto ret;
914
915 if ((err = nvlist_add_string(nvl, IPADM_NVP_GIFNAME,
916 uargp->ia_gifname)) != 0)
917 goto ret;
918
919 cb.dbw_nvl = nvl;
920 cb.dbw_flags = flags | IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP;
921 err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
922 }
923 ret:
924 nvlist_free(nvl);
925 rval.ir_err = err;
926 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
927 }
|