summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
index d226c8810c..2ac64b312e 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c
@@ -4115,14 +4115,22 @@ inetunplumb(char *arg, int64_t param)
Perror0_exit("unplumb: SIOCGLIFFLAGS");
}
flags = lifr.lifr_flags;
-
+again:
if (flags & IFF_IPMP) {
lifgroupinfo_t lifgr;
ifaddrlistx_t *ifaddrs, *ifaddrp;
/*
- * The kernel will fail the I_PUNLINK if the group still has
- * members, but check now to provide a better error message.
+ * There are two reasons the I_PUNLINK can fail with EBUSY:
+ * (1) if IP interfaces are in the group, or (2) if IPMP data
+ * addresses are administratively up. For case (1), we fail
+ * here with a specific error message. For case (2), we bring
+ * down the addresses prior to doing the I_PUNLINK. If the
+ * I_PUNLINK still fails with EBUSY then the configuration
+ * must have changed after our checks, in which case we branch
+ * back up to `again' and rerun this logic. The net effect is
+ * that unplumbing an IPMP interface will only fail with EBUSY
+ * if IP interfaces are in the group.
*/
if (ioctl(s, SIOCGLIFGROUPNAME, &lifr) == -1)
Perror0_exit("unplumb: SIOCGLIFGROUPNAME");
@@ -4173,6 +4181,12 @@ inetunplumb(char *arg, int64_t param)
if (debug)
(void) printf("arp_muxid %d\n", arp_muxid);
if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) {
+ /*
+ * See the comment before the SIOCGLIFGROUPNAME call.
+ */
+ if (errno == EBUSY && (flags & IFF_IPMP))
+ goto again;
+
if ((errno == EINVAL) &&
(flags & (IFF_NOARP | IFF_IPV6))) {
/*
@@ -4208,6 +4222,13 @@ inetunplumb(char *arg, int64_t param)
(void) ioctl(muxid_fd, SIOCSLIFMUXID, (caddr_t)&lifr);
errno = save_errno;
}
+
+ /*
+ * See the comment before the SIOCGLIFGROUPNAME call.
+ */
+ if (errno == EBUSY && (flags & IFF_IPMP))
+ goto again;
+
Perror0_exit("I_PUNLINK for ip");
}
(void) close(mux_fd);