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