1 /*
2 * CDDL HEADER START
3 *
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 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 */
25
26 /*
27 * This file contains routines that are used to modify/retrieve protocol or
28 * interface property values. It also holds all the supported properties for
29 * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
30 * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
31 *
32 * This file also contains walkers, which walks through the property table and
33 * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
34 * property in the table.
35 */
36
37 #include <unistd.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <fcntl.h>
41 #include <strings.h>
42 #include <stdlib.h>
43 #include <netinet/in.h>
128
129 { "nud", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
130 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
131 i_ipadm_get_ifprop_flags },
132
133 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
134 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
135 i_ipadm_get_ifprop_flags },
136
137 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
138 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
139
140 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
141 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
142 i_ipadm_get_hostmodel },
143
144 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
145 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
146 i_ipadm_get_hostmodel },
147
148 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
149 };
150
151 /* possible values for TCP properties `ecn' and `sack' */
152 static const char *ecn_sack_vals[] = {"never", "passive", "active", NULL};
153
154 /* Supported TCP protocol properties */
155 static ipadm_prop_desc_t ipadm_tcp_prop_table[] = {
156 { "ecn", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
157 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
158
159 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
160 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
161 i_ipadm_get_prop },
162
163 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
164 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
165
166 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
167 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
578 return (IPADM_SUCCESS);
579 }
580
581 /* ARGSUSED */
582 static ipadm_status_t
583 i_ipadm_set_ifprop_flags(ipadm_handle_t iph, const void *arg,
584 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
585 {
586 ipadm_status_t status = IPADM_SUCCESS;
587 const char *ifname = arg;
588 uint64_t on_flags = 0, off_flags = 0;
589 boolean_t on = B_FALSE;
590 sa_family_t af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
591
592 /* if we are resetting, set the value to its default value */
593 if (flags & IPADM_OPT_DEFAULT) {
594 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
595 strcmp(pdp->ipd_name, "arp") == 0 ||
596 strcmp(pdp->ipd_name, "nud") == 0) {
597 pval = IPADM_ONSTR;
598 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
599 pval = IPADM_OFFSTR;
600 } else {
601 return (IPADM_PROP_UNKNOWN);
602 }
603 }
604
605 if (strcmp(pval, IPADM_ONSTR) == 0)
606 on = B_TRUE;
607 else if (strcmp(pval, IPADM_OFFSTR) == 0)
608 on = B_FALSE;
609 else
610 return (IPADM_INVALID_ARG);
611
612 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
613 if (on)
614 off_flags = IFF_NORTEXCH;
615 else
616 on_flags = IFF_NORTEXCH;
617 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
618 if (on)
619 off_flags = IFF_NOARP;
620 else
621 on_flags = IFF_NOARP;
622 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
623 if (on)
624 off_flags = IFF_NONUD;
625 else
626 on_flags = IFF_NONUD;
627 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
628 if (on)
629 on_flags = IFF_ROUTER;
630 else
631 off_flags = IFF_ROUTER;
632 }
633
634 if (on_flags || off_flags) {
635 status = i_ipadm_set_flags(iph, ifname, af, on_flags,
636 off_flags);
637 }
638 return (status);
639 }
640
641 /* ARGSUSED */
642 static ipadm_status_t
643 i_ipadm_set_eprivport(ipadm_handle_t iph, const void *arg,
644 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
645 {
646 nvlist_t *portsnvl = NULL;
647 nvpair_t *nvp;
648 ipadm_status_t status = IPADM_SUCCESS;
649 int err;
650 uint_t count = 0;
651
980 i_ipadm_get_ifprop_flags(ipadm_handle_t iph, const void *arg,
981 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
982 uint_t valtype)
983 {
984 uint64_t intf_flags;
985 char *val;
986 size_t nbytes;
987 const char *ifname = arg;
988 sa_family_t af;
989 ipadm_status_t status = IPADM_SUCCESS;
990
991 switch (valtype) {
992 case MOD_PROP_PERM:
993 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
994 break;
995 case MOD_PROP_DEFAULT:
996 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
997 strcmp(pdp->ipd_name, "arp") == 0 ||
998 strcmp(pdp->ipd_name, "nud") == 0) {
999 val = IPADM_ONSTR;
1000 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1001 val = IPADM_OFFSTR;
1002 } else {
1003 return (IPADM_PROP_UNKNOWN);
1004 }
1005 nbytes = snprintf(buf, *bufsize, "%s", val);
1006 break;
1007 case MOD_PROP_ACTIVE:
1008 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1009 status = i_ipadm_get_flags(iph, ifname, af, &intf_flags);
1010 if (status != IPADM_SUCCESS)
1011 return (status);
1012
1013 val = IPADM_OFFSTR;
1014 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
1015 if (!(intf_flags & IFF_NORTEXCH))
1016 val = IPADM_ONSTR;
1017 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1018 if (intf_flags & IFF_ROUTER)
1019 val = IPADM_ONSTR;
1020 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
1021 if (!(intf_flags & IFF_NOARP))
1022 val = IPADM_ONSTR;
1023 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
1024 if (!(intf_flags & IFF_NONUD))
1025 val = IPADM_ONSTR;
1026 }
1027 nbytes = snprintf(buf, *bufsize, "%s", val);
1028 break;
1029 default:
1030 return (IPADM_INVALID_ARG);
1031 }
1032 if (nbytes >= *bufsize) {
1033 /* insufficient buffer space */
1034 *bufsize = nbytes + 1;
1035 status = IPADM_NO_BUFS;
1036 }
1037
1038 return (status);
1039 }
1040
1041 static void
1042 i_ipadm_perm2str(char *buf, uint_t *bufsize)
1043 {
1044 uint_t perm = atoi(buf);
1045
1681 parg.ia_cmd = IPMGMT_CMD_RESETPROP;
1682 else
1683 parg.ia_cmd = IPMGMT_CMD_SETPROP;
1684
1685 err = ipadm_door_call(iph, &parg, sizeof (parg), NULL, 0, B_FALSE);
1686
1687 /*
1688 * its fine if there were no entry in the DB to delete. The user
1689 * might be changing property value, which was not changed
1690 * persistently.
1691 */
1692 if (err == ENOENT)
1693 err = 0;
1694 return (ipadm_errno2status(err));
1695 }
1696
1697 /*
1698 * This is called from ipadm_set_ifprop() to validate the set operation.
1699 * It does the following steps:
1700 * 1. Validates the interface name.
1701 * 2. Fails if it is an IPMP meta-interface or an underlying interface.
1702 * 3. In case of a persistent operation, verifies that the
1703 * interface is persistent.
1704 */
1705 static ipadm_status_t
1706 i_ipadm_validate_if(ipadm_handle_t iph, const char *ifname,
1707 uint_t proto, uint_t flags)
1708 {
1709 sa_family_t af, other_af;
1710 ipadm_status_t status;
1711 boolean_t p_exists;
1712 boolean_t af_exists, other_af_exists, a_exists;
1713
1714 /* Check if the interface name is valid. */
1715 if (!i_ipadm_validate_ifname(iph, ifname))
1716 return (IPADM_INVALID_ARG);
1717
1718 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1719 /*
1720 * Setting properties on an IPMP meta-interface or underlying
1721 * interface is not supported.
1722 */
1723 if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname))
1724 return (IPADM_NOTSUP);
1725
1726 /* Check if interface exists in the persistent configuration. */
1727 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
1728 if (status != IPADM_SUCCESS)
1729 return (status);
1730
1731 /* Check if interface exists in the active configuration. */
1732 af_exists = ipadm_if_enabled(iph, ifname, af);
1733 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
1734 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
1735 a_exists = (af_exists || other_af_exists);
1736 if (!a_exists && p_exists)
1737 return (IPADM_OP_DISABLE_OBJ);
1738 if (!af_exists)
1739 return (IPADM_ENXIO);
1740
1741 /*
1742 * If a persistent operation is requested, check if the underlying
1743 * IP interface is persistent.
1744 */
|
1 /*
2 * CDDL HEADER START
3 *
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) 2013 by Delphix. All rights reserved.
25 * Copyright 2016 Nexenta Systems, Inc.
26 */
27
28 /*
29 * This file contains routines that are used to modify/retrieve protocol or
30 * interface property values. It also holds all the supported properties for
31 * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
32 * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
33 *
34 * This file also contains walkers, which walks through the property table and
35 * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
36 * property in the table.
37 */
38
39 #include <unistd.h>
40 #include <errno.h>
41 #include <ctype.h>
42 #include <fcntl.h>
43 #include <strings.h>
44 #include <stdlib.h>
45 #include <netinet/in.h>
130
131 { "nud", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
132 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
133 i_ipadm_get_ifprop_flags },
134
135 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
136 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
137 i_ipadm_get_ifprop_flags },
138
139 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
140 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
141
142 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
143 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
144 i_ipadm_get_hostmodel },
145
146 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
147 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
148 i_ipadm_get_hostmodel },
149
150 { "standby", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IP, 0,
151 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
152 i_ipadm_get_ifprop_flags },
153
154
155 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
156 };
157
158 /* possible values for TCP properties `ecn' and `sack' */
159 static const char *ecn_sack_vals[] = {"never", "passive", "active", NULL};
160
161 /* Supported TCP protocol properties */
162 static ipadm_prop_desc_t ipadm_tcp_prop_table[] = {
163 { "ecn", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
164 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
165
166 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
167 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
168 i_ipadm_get_prop },
169
170 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
171 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
172
173 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
174 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
585 return (IPADM_SUCCESS);
586 }
587
588 /* ARGSUSED */
589 static ipadm_status_t
590 i_ipadm_set_ifprop_flags(ipadm_handle_t iph, const void *arg,
591 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
592 {
593 ipadm_status_t status = IPADM_SUCCESS;
594 const char *ifname = arg;
595 uint64_t on_flags = 0, off_flags = 0;
596 boolean_t on = B_FALSE;
597 sa_family_t af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
598
599 /* if we are resetting, set the value to its default value */
600 if (flags & IPADM_OPT_DEFAULT) {
601 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
602 strcmp(pdp->ipd_name, "arp") == 0 ||
603 strcmp(pdp->ipd_name, "nud") == 0) {
604 pval = IPADM_ONSTR;
605 } else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
606 strcmp(pdp->ipd_name, "standby") == 0) {
607 pval = IPADM_OFFSTR;
608 } else {
609 return (IPADM_PROP_UNKNOWN);
610 }
611 }
612
613 if (strcmp(pval, IPADM_ONSTR) == 0)
614 on = B_TRUE;
615 else if (strcmp(pval, IPADM_OFFSTR) == 0)
616 on = B_FALSE;
617 else
618 return (IPADM_INVALID_ARG);
619
620 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
621 if (on)
622 off_flags = IFF_NORTEXCH;
623 else
624 on_flags = IFF_NORTEXCH;
625 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
626 if (on)
627 off_flags = IFF_NOARP;
628 else
629 on_flags = IFF_NOARP;
630 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
631 if (on)
632 off_flags = IFF_NONUD;
633 else
634 on_flags = IFF_NONUD;
635 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
636 if (on)
637 on_flags = IFF_ROUTER;
638 else
639 off_flags = IFF_ROUTER;
640 } else if (strcmp(pdp->ipd_name, "standby") == 0) {
641 if (on)
642 on_flags = IFF_STANDBY;
643 else
644 off_flags = IFF_STANDBY;
645 }
646
647 if (on_flags || off_flags) {
648 status = i_ipadm_set_flags(iph, ifname, af, on_flags,
649 off_flags);
650 }
651 return (status);
652 }
653
654 /* ARGSUSED */
655 static ipadm_status_t
656 i_ipadm_set_eprivport(ipadm_handle_t iph, const void *arg,
657 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
658 {
659 nvlist_t *portsnvl = NULL;
660 nvpair_t *nvp;
661 ipadm_status_t status = IPADM_SUCCESS;
662 int err;
663 uint_t count = 0;
664
993 i_ipadm_get_ifprop_flags(ipadm_handle_t iph, const void *arg,
994 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
995 uint_t valtype)
996 {
997 uint64_t intf_flags;
998 char *val;
999 size_t nbytes;
1000 const char *ifname = arg;
1001 sa_family_t af;
1002 ipadm_status_t status = IPADM_SUCCESS;
1003
1004 switch (valtype) {
1005 case MOD_PROP_PERM:
1006 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
1007 break;
1008 case MOD_PROP_DEFAULT:
1009 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
1010 strcmp(pdp->ipd_name, "arp") == 0 ||
1011 strcmp(pdp->ipd_name, "nud") == 0) {
1012 val = IPADM_ONSTR;
1013 } else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
1014 strcmp(pdp->ipd_name, "standby") == 0) {
1015 val = IPADM_OFFSTR;
1016 } else {
1017 return (IPADM_PROP_UNKNOWN);
1018 }
1019 nbytes = snprintf(buf, *bufsize, "%s", val);
1020 break;
1021 case MOD_PROP_ACTIVE:
1022 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1023 status = i_ipadm_get_flags(iph, ifname, af, &intf_flags);
1024 if (status != IPADM_SUCCESS)
1025 return (status);
1026
1027 val = IPADM_OFFSTR;
1028 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
1029 if (!(intf_flags & IFF_NORTEXCH))
1030 val = IPADM_ONSTR;
1031 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1032 if (intf_flags & IFF_ROUTER)
1033 val = IPADM_ONSTR;
1034 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
1035 if (!(intf_flags & IFF_NOARP))
1036 val = IPADM_ONSTR;
1037 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
1038 if (!(intf_flags & IFF_NONUD))
1039 val = IPADM_ONSTR;
1040 } else if (strcmp(pdp->ipd_name, "standby") == 0) {
1041 if (intf_flags & IFF_STANDBY)
1042 val = IPADM_ONSTR;
1043 }
1044 nbytes = snprintf(buf, *bufsize, "%s", val);
1045 break;
1046 default:
1047 return (IPADM_INVALID_ARG);
1048 }
1049 if (nbytes >= *bufsize) {
1050 /* insufficient buffer space */
1051 *bufsize = nbytes + 1;
1052 status = IPADM_NO_BUFS;
1053 }
1054
1055 return (status);
1056 }
1057
1058 static void
1059 i_ipadm_perm2str(char *buf, uint_t *bufsize)
1060 {
1061 uint_t perm = atoi(buf);
1062
1698 parg.ia_cmd = IPMGMT_CMD_RESETPROP;
1699 else
1700 parg.ia_cmd = IPMGMT_CMD_SETPROP;
1701
1702 err = ipadm_door_call(iph, &parg, sizeof (parg), NULL, 0, B_FALSE);
1703
1704 /*
1705 * its fine if there were no entry in the DB to delete. The user
1706 * might be changing property value, which was not changed
1707 * persistently.
1708 */
1709 if (err == ENOENT)
1710 err = 0;
1711 return (ipadm_errno2status(err));
1712 }
1713
1714 /*
1715 * This is called from ipadm_set_ifprop() to validate the set operation.
1716 * It does the following steps:
1717 * 1. Validates the interface name.
1718 * 2. In case of a persistent operation, verifies that the
1719 * interface is persistent.
1720 */
1721 static ipadm_status_t
1722 i_ipadm_validate_if(ipadm_handle_t iph, const char *ifname,
1723 uint_t proto, uint_t flags)
1724 {
1725 sa_family_t af, other_af;
1726 ipadm_status_t status;
1727 boolean_t p_exists;
1728 boolean_t af_exists, other_af_exists, a_exists;
1729
1730 /* Check if the interface name is valid. */
1731 if (!i_ipadm_validate_ifname(iph, ifname))
1732 return (IPADM_INVALID_ARG);
1733
1734 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1735
1736 /* Check if interface exists in the persistent configuration. */
1737 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
1738 if (status != IPADM_SUCCESS)
1739 return (status);
1740
1741 /* Check if interface exists in the active configuration. */
1742 af_exists = ipadm_if_enabled(iph, ifname, af);
1743 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
1744 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
1745 a_exists = (af_exists || other_af_exists);
1746 if (!a_exists && p_exists)
1747 return (IPADM_OP_DISABLE_OBJ);
1748 if (!af_exists)
1749 return (IPADM_ENXIO);
1750
1751 /*
1752 * If a persistent operation is requested, check if the underlying
1753 * IP interface is persistent.
1754 */
|