1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
4 * SPDX-License-Identifier: BSD-4-Clause
6 * Copyright (c) 1997 Jason R. Thorpe.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * Copyright (c) 1983, 1993
39 * The Regents of the University of California. All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 #include <sys/param.h>
67 #include <sys/ioctl.h>
68 #include <sys/socket.h>
69 #include <sys/sysctl.h>
73 #include <net/if_dl.h>
74 #include <net/if_types.h>
75 #include <net/if_media.h>
76 #include <net/route.h>
88 #include <libifconfig.h>
92 static void domediaopt(const char *, bool, int);
93 static ifmedia_t get_media_subtype(ifmedia_t, const char *);
94 static ifmedia_t get_media_mode(ifmedia_t, const char *);
95 static ifmedia_t get_media_options(ifmedia_t, const char *);
96 static void print_media(ifmedia_t, bool);
97 static void print_media_ifconfig(ifmedia_t);
102 struct ifmediareq *ifmr;
104 if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
107 if (ifmr->ifm_count == 0) {
108 warnx("%s: no media types?", name);
113 print_media(ifmr->ifm_current, true);
114 if (ifmr->ifm_active != ifmr->ifm_current) {
117 print_media(ifmr->ifm_active, false);
123 if (ifmr->ifm_status & IFM_AVALID) {
124 struct ifdownreason ifdr;
127 status = ifconfig_media_get_status(ifmr);
128 printf("\tstatus: %s", status);
129 if (strcmp(status, "no carrier") == 0 &&
130 ifconfig_media_get_downreason(lifh, name, &ifdr) == 0) {
131 switch (ifdr.ifdr_reason) {
132 case IFDR_REASON_MSG:
133 printf(" (%s)", ifdr.ifdr_msg);
135 case IFDR_REASON_VENDOR:
136 printf(" (vendor code %d)",
147 printf("\tsupported media:\n");
148 for (size_t i = 0; i < ifmr->ifm_count; ++i) {
150 print_media_ifconfig(ifmr->ifm_ulist[i]);
159 ifmedia_getstate(void)
161 static struct ifmediareq *ifmr = NULL;
166 if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
167 errc(1, ifconfig_err_errno(lifh),
168 "%s: ifconfig_media_get_mediareq", name);
170 if (ifmr->ifm_count == 0)
171 errx(1, "%s: no media types?", name);
177 setifmediacallback(int s, void *arg)
179 struct ifmediareq *ifmr = (struct ifmediareq *)arg;
180 static bool did_it = false;
183 ifr.ifr_media = ifmr->ifm_current;
184 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
185 err(1, "SIOCSIFMEDIA (media)");
192 setmedia(const char *val, int d, int s, const struct afswtch *afp)
194 struct ifmediareq *ifmr;
197 ifmr = ifmedia_getstate();
200 * We are primarily concerned with the top-level type.
201 * However, "current" may be only IFM_NONE, so we just look
202 * for the top-level type in the first "supported type"
205 * (I'm assuming that all supported media types for a given
206 * interface will be the same top-level type..)
208 subtype = get_media_subtype(ifmr->ifm_ulist[0], val);
210 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
211 ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
212 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
214 ifmr->ifm_current = ifr.ifr_media;
215 callback_register(setifmediacallback, (void *)ifmr);
219 setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
222 domediaopt(val, false, s);
226 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
229 domediaopt(val, true, s);
233 domediaopt(const char *val, bool clear, int s)
235 struct ifmediareq *ifmr;
238 ifmr = ifmedia_getstate();
240 options = get_media_options(ifmr->ifm_ulist[0], val);
242 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
243 ifr.ifr_media = ifmr->ifm_current;
245 ifr.ifr_media &= ~options;
247 if (options & IFM_HDX) {
248 ifr.ifr_media &= ~IFM_FDX;
251 ifr.ifr_media |= options;
253 ifmr->ifm_current = ifr.ifr_media;
254 callback_register(setifmediacallback, (void *)ifmr);
258 setmediainst(const char *val, int d, int s, const struct afswtch *afp)
260 struct ifmediareq *ifmr;
263 ifmr = ifmedia_getstate();
266 if (inst < 0 || inst > (int)IFM_INST_MAX)
267 errx(1, "invalid media instance: %s", val);
269 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
270 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
272 ifmr->ifm_current = ifr.ifr_media;
273 callback_register(setifmediacallback, (void *)ifmr);
277 setmediamode(const char *val, int d, int s, const struct afswtch *afp)
279 struct ifmediareq *ifmr;
282 ifmr = ifmedia_getstate();
284 mode = get_media_mode(ifmr->ifm_ulist[0], val);
286 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
287 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
289 ifmr->ifm_current = ifr.ifr_media;
290 callback_register(setifmediacallback, (void *)ifmr);
294 get_media_subtype(ifmedia_t media, const char *val)
298 subtype = ifconfig_media_lookup_subtype(media, val);
299 if (subtype != INVALID_IFMEDIA)
303 errx(EXIT_FAILURE, "unknown media type 0x%x", media);
305 errx(EXIT_FAILURE, "unknown media subtype: %s", val);
307 err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
313 get_media_mode(ifmedia_t media, const char *val)
317 mode = ifconfig_media_lookup_mode(media, val);
318 if (mode != INVALID_IFMEDIA)
322 errx(EXIT_FAILURE, "unknown media type 0x%x", media);
324 return (INVALID_IFMEDIA);
326 err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
332 get_media_options(ifmedia_t media, const char *val)
335 const char **optnames;
341 * We muck with the string, so copy it.
345 err(EXIT_FAILURE, "strdup");
348 * Split the comma-delimited list into separate strings.
351 for (opt = opts; (opt = strtok(opt, ",")) != NULL; opt = NULL)
357 optnames = calloc(nopts, sizeof(*optnames));
358 if (optnames == NULL)
359 err(EXIT_FAILURE, "calloc");
361 for (size_t i = 0; i < nopts; ++i) {
363 opt = strchr(opt, '\0') + 1;
367 * Look up the options in the user-provided list.
369 options = ifconfig_media_lookup_options(media, optnames, nopts);
371 err(EXIT_FAILURE, "ifconfig_media_lookup_options");
373 for (size_t i = 0; i < nopts; ++i) {
374 if (options[i] == INVALID_IFMEDIA)
375 errx(EXIT_FAILURE, "unknown option: %s", optnames[i]);
385 print_media(ifmedia_t media, bool print_toptype)
387 const char *val, **options;
389 val = ifconfig_media_get_type(media);
391 printf("<unknown type>");
393 } else if (print_toptype) {
397 val = ifconfig_media_get_subtype(media);
399 printf("<unknown subtype>");
409 val = ifconfig_media_get_mode(media);
410 if (val != NULL && strcasecmp("autoselect", val) != 0)
411 printf(" mode %s", val);
414 options = ifconfig_media_get_options(media);
415 if (options != NULL && options[0] != NULL) {
416 printf(" <%s", options[0]);
417 for (size_t i = 1; options[i] != NULL; ++i)
418 printf(",%s", options[i]);
423 if (print_toptype && IFM_INST(media) != 0)
424 printf(" instance %d", IFM_INST(media));
428 print_media_ifconfig(ifmedia_t media)
430 const char *val, **options;
432 val = ifconfig_media_get_type(media);
434 printf("<unknown type>");
439 * Don't print the top-level type; it's not like we can
440 * change it, or anything.
443 val = ifconfig_media_get_subtype(media);
445 printf("<unknown subtype>");
449 printf("media %s", val);
451 val = ifconfig_media_get_mode(media);
453 printf(" mode %s", val);
455 options = ifconfig_media_get_options(media);
456 if (options != NULL && options[0] != NULL) {
457 printf(" mediaopt %s", options[0]);
458 for (size_t i = 1; options[i] != NULL; ++i)
459 printf(",%s", options[i]);
463 if (IFM_INST(media) != 0)
464 printf(" instance %d", IFM_INST(media));
467 /**********************************************************************
469 **********************************************************************/
471 static struct cmd media_cmds[] = {
472 DEF_CMD_ARG("media", setmedia),
473 DEF_CMD_ARG("mode", setmediamode),
474 DEF_CMD_ARG("mediaopt", setmediaopt),
475 DEF_CMD_ARG("-mediaopt",unsetmediaopt),
476 DEF_CMD_ARG("inst", setmediainst),
477 DEF_CMD_ARG("instance", setmediainst),
479 static struct afswtch af_media = {
480 .af_name = "af_media",
482 .af_other_status = media_status,
485 static __constructor void
490 for (i = 0; i < nitems(media_cmds); i++)
491 cmd_register(&media_cmds[i]);
492 af_register(&af_media);