cmd-inet/usr.sbin: remove -Wno-implicit-function-declaration
[unleashed.git] / usr / src / cmd / cmd-inet / usr.sbin / if_mpadm.c
blobd3d4dc8c04c14c34a4d6e3092f272962868e0f6f
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <errno.h>
27 #include <ipmp_admin.h>
28 #include <libinetutil.h>
29 #include <locale.h>
30 #include <net/if.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.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 *, ...);
50 static void
51 usage(void)
53 (void) fprintf(stderr, gettext("Usage: %s -d | -r <ifname>\n"),
54 progname);
55 exit(EXIT_FAILURE);
58 static const char *
59 mpadm_errmsg(uint32_t error)
61 switch (error) {
62 case IPMP_EUNKIF:
63 return (gettext("not a physical interface or not in an "
64 "IPMP group"));
65 case IPMP_EMINRED:
66 return (gettext("no other functioning interfaces are in its "
67 "IPMP group"));
68 default:
69 return (ipmp_errmsg(error));
73 int
74 main(int argc, char **argv)
76 int retval;
77 ipmp_handle_t handle;
78 offline_func_t *ofuncp = NULL;
79 const char *ifname;
80 int c;
82 if ((progname = strrchr(argv[0], '/')) != NULL)
83 progname++;
84 else
85 progname = argv[0];
87 (void) setlocale(LC_ALL, "");
88 (void) textdomain(TEXT_DOMAIN);
90 while ((c = getopt(argc, argv, "d:r:")) != EOF) {
91 switch (c) {
92 case 'd':
93 ifname = optarg;
94 ofuncp = do_offline;
95 break;
96 case 'r':
97 ifname = optarg;
98 ofuncp = undo_offline;
99 break;
100 default:
101 usage();
105 if (ofuncp == NULL)
106 usage();
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);
121 ipmp_close(handle);
122 (void) close(sioc4fd);
123 (void) close(sioc6fd);
125 return (EXIT_SUCCESS);
129 * Checks whether IFF_OFFLINE is set on `ifname'.
131 boolean_t
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);
147 static void
148 do_offline(const char *ifname, ipmp_handle_t handle)
150 ifaddrlistx_t *ifaddrp, *ifaddrs;
151 int retval;
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",
172 ifaddrp->ia_name);
175 ifaddrlistx_free(ifaddrs);
178 static void
179 undo_offline(const char *ifname, ipmp_handle_t handle)
181 ifaddrlistx_t *ifaddrp, *ifaddrs;
182 int retval;
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);
204 * Undo the offline.
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.
221 static boolean_t
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);
233 /* PRINTFLIKE1 */
234 static void
235 die(const char *format, ...)
237 va_list alist;
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);
245 va_end(alist);
247 if (strchr(format, '\n') == NULL)
248 (void) fprintf(stderr, ": %s\n", errstr);
250 exit(EXIT_FAILURE);
253 /* PRINTFLIKE1 */
254 static void
255 warn(const char *format, ...)
257 va_list alist;
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);
265 va_end(alist);
267 if (strchr(format, '\n') == NULL)
268 (void) fprintf(stderr, ": %s\n", errstr);