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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <ipmp_admin.h>
28 #include <libinetutil.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <sys/types.h>
40 typedef void offline_func_t(const char *, ipmp_handle_t
);
42 static const char *progname
;
43 static int sioc4fd
, sioc6fd
;
44 static offline_func_t do_offline
, undo_offline
;
45 static boolean_t
set_lifflags(const char *, uint64_t);
46 static boolean_t
is_offline(const char *);
47 static void warn(const char *, ...);
48 static void die(const char *, ...);
53 (void) fprintf(stderr
, gettext("Usage: %s -d | -r <ifname>\n"),
59 mpadm_errmsg(uint32_t error
)
63 return (gettext("not a physical interface or not in an "
66 return (gettext("no other functioning interfaces are in its "
69 return (ipmp_errmsg(error
));
74 main(int argc
, char **argv
)
78 offline_func_t
*ofuncp
= NULL
;
82 if ((progname
= strrchr(argv
[0], '/')) != NULL
)
87 (void) setlocale(LC_ALL
, "");
88 (void) textdomain(TEXT_DOMAIN
);
90 while ((c
= getopt(argc
, argv
, "d:r:")) != EOF
) {
98 ofuncp
= undo_offline
;
109 * Create the global V4 and V6 socket ioctl descriptors.
111 sioc4fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
112 sioc6fd
= socket(AF_INET6
, SOCK_DGRAM
, 0);
113 if (sioc4fd
== -1 || sioc6fd
== -1)
114 die("cannot create sockets");
116 if ((retval
= ipmp_open(&handle
)) != IPMP_SUCCESS
)
117 die("cannot create ipmp handle: %s\n", ipmp_errmsg(retval
));
119 (*ofuncp
)(ifname
, handle
);
122 (void) close(sioc4fd
);
123 (void) close(sioc6fd
);
125 return (EXIT_SUCCESS
);
129 * Checks whether IFF_OFFLINE is set on `ifname'.
132 is_offline(const char *ifname
)
134 struct lifreq lifr
= { 0 };
136 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
137 if (ioctl(sioc4fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
138 if (errno
!= ENXIO
||
139 ioctl(sioc6fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
140 die("cannot get interface flags on %s", ifname
);
144 return ((lifr
.lifr_flags
& IFF_OFFLINE
) != 0);
148 do_offline(const char *ifname
, ipmp_handle_t handle
)
150 ifaddrlistx_t
*ifaddrp
, *ifaddrs
;
153 if (is_offline(ifname
))
154 die("interface %s is already offline\n", ifname
);
156 if ((retval
= ipmp_offline(handle
, ifname
, 1)) != IPMP_SUCCESS
)
157 die("cannot offline %s: %s\n", ifname
, mpadm_errmsg(retval
));
160 * Get all the up addresses for `ifname' and bring them down.
162 if (ifaddrlistx(ifname
, IFF_UP
, 0, &ifaddrs
) == -1)
163 die("cannot get addresses on %s", ifname
);
165 for (ifaddrp
= ifaddrs
; ifaddrp
!= NULL
; ifaddrp
= ifaddrp
->ia_next
) {
166 if (!(ifaddrp
->ia_flags
& IFF_OFFLINE
))
167 warn("IFF_OFFLINE vanished on %s\n", ifaddrp
->ia_name
);
169 if (!set_lifflags(ifaddrp
->ia_name
,
170 ifaddrp
->ia_flags
& ~IFF_UP
))
171 warn("cannot bring down address on %s",
175 ifaddrlistx_free(ifaddrs
);
179 undo_offline(const char *ifname
, ipmp_handle_t handle
)
181 ifaddrlistx_t
*ifaddrp
, *ifaddrs
;
184 if (!is_offline(ifname
))
185 die("interface %s is not offline\n", ifname
);
188 * Get all the down addresses for `ifname' and bring them up.
190 if (ifaddrlistx(ifname
, 0, IFF_UP
, &ifaddrs
) == -1)
191 die("cannot get addresses for %s", ifname
);
193 for (ifaddrp
= ifaddrs
; ifaddrp
!= NULL
; ifaddrp
= ifaddrp
->ia_next
) {
194 if (!(ifaddrp
->ia_flags
& IFF_OFFLINE
))
195 warn("IFF_OFFLINE vanished on %s\n", ifaddrp
->ia_name
);
197 if (!set_lifflags(ifaddrp
->ia_name
, ifaddrp
->ia_flags
| IFF_UP
))
198 warn("cannot bring up address on %s", ifaddrp
->ia_name
);
201 ifaddrlistx_free(ifaddrs
);
206 if ((retval
= ipmp_undo_offline(handle
, ifname
)) != IPMP_SUCCESS
) {
207 die("cannot undo-offline %s: %s\n", ifname
,
208 mpadm_errmsg(retval
));
212 * Verify whether IFF_OFFLINE is set as a sanity check.
214 if (is_offline(ifname
))
215 warn("in.mpathd has not cleared IFF_OFFLINE on %s\n", ifname
);
219 * Change `lifname' to have `flags' set. Returns B_TRUE on success.
222 set_lifflags(const char *lifname
, uint64_t flags
)
224 struct lifreq lifr
= { 0 };
225 int fd
= (flags
& IFF_IPV4
) ? sioc4fd
: sioc6fd
;
227 (void) strlcpy(lifr
.lifr_name
, lifname
, LIFNAMSIZ
);
228 lifr
.lifr_flags
= flags
;
230 return (ioctl(fd
, SIOCSLIFFLAGS
, &lifr
) >= 0);
235 die(const char *format
, ...)
238 char *errstr
= strerror(errno
);
240 format
= gettext(format
);
241 (void) fprintf(stderr
, gettext("%s: fatal: "), progname
);
243 va_start(alist
, format
);
244 (void) vfprintf(stderr
, format
, alist
);
247 if (strchr(format
, '\n') == NULL
)
248 (void) fprintf(stderr
, ": %s\n", errstr
);
255 warn(const char *format
, ...)
258 char *errstr
= strerror(errno
);
260 format
= gettext(format
);
261 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
263 va_start(alist
, format
);
264 (void) vfprintf(stderr
, format
, alist
);
267 if (strchr(format
, '\n') == NULL
)
268 (void) fprintf(stderr
, ": %s\n", errstr
);