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