1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
5 * SPDX-License-Identifier: BSD-4-Clause
7 * Copyright (c) 1997 Jason R. Thorpe.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed for the NetBSD Project
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * Copyright (c) 1983, 1993
40 * The Regents of the University of California. All rights reserved.
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 #include <sys/param.h>
68 #include <sys/ioctl.h>
69 #include <sys/socket.h>
70 #include <sys/sysctl.h>
74 #include <net/if_dl.h>
75 #include <net/if_types.h>
76 #include <net/if_media.h>
77 #include <net/route.h>
89 #include <libifconfig.h>
93 static void domediaopt(const char *, bool, int);
94 static ifmedia_t get_media_subtype(ifmedia_t, const char *);
95 static ifmedia_t get_media_mode(ifmedia_t, const char *);
96 static ifmedia_t get_media_options(ifmedia_t, const char *);
97 static void print_media(ifmedia_t, bool);
98 static void print_media_ifconfig(ifmedia_t);
103 struct ifmediareq *ifmr;
105 if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
108 if (ifmr->ifm_count == 0) {
109 warnx("%s: no media types?", name);
114 print_media(ifmr->ifm_current, true);
115 if (ifmr->ifm_active != ifmr->ifm_current) {
118 print_media(ifmr->ifm_active, false);
124 if (ifmr->ifm_status & IFM_AVALID) {
125 struct ifdownreason ifdr;
128 status = ifconfig_media_get_status(ifmr);
129 printf("\tstatus: %s", status);
130 if (strcmp(status, "no carrier") == 0 &&
131 ifconfig_media_get_downreason(lifh, name, &ifdr) == 0) {
132 switch (ifdr.ifdr_reason) {
133 case IFDR_REASON_MSG:
134 printf(" (%s)", ifdr.ifdr_msg);
136 case IFDR_REASON_VENDOR:
137 printf(" (vendor code %d)",
148 printf("\tsupported media:\n");
149 for (size_t i = 0; i < ifmr->ifm_count; ++i) {
151 print_media_ifconfig(ifmr->ifm_ulist[i]);
160 ifmedia_getstate(void)
162 static struct ifmediareq *ifmr = NULL;
167 if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
168 errc(1, ifconfig_err_errno(lifh),
169 "%s: ifconfig_media_get_mediareq", name);
171 if (ifmr->ifm_count == 0)
172 errx(1, "%s: no media types?", name);
178 setifmediacallback(int s, void *arg)
180 struct ifmediareq *ifmr = (struct ifmediareq *)arg;
181 static bool did_it = false;
184 ifr.ifr_media = ifmr->ifm_current;
185 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
186 err(1, "SIOCSIFMEDIA (media)");
193 setmedia(const char *val, int d, int s, const struct afswtch *afp)
195 struct ifmediareq *ifmr;
198 ifmr = ifmedia_getstate();
201 * We are primarily concerned with the top-level type.
202 * However, "current" may be only IFM_NONE, so we just look
203 * for the top-level type in the first "supported type"
206 * (I'm assuming that all supported media types for a given
207 * interface will be the same top-level type..)
209 subtype = get_media_subtype(ifmr->ifm_ulist[0], val);
211 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
212 ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
213 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
215 ifmr->ifm_current = ifr.ifr_media;
216 callback_register(setifmediacallback, (void *)ifmr);
220 setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
223 domediaopt(val, false, s);
227 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
230 domediaopt(val, true, s);
234 domediaopt(const char *val, bool clear, int s)
236 struct ifmediareq *ifmr;
239 ifmr = ifmedia_getstate();
241 options = get_media_options(ifmr->ifm_ulist[0], val);
243 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
244 ifr.ifr_media = ifmr->ifm_current;
246 ifr.ifr_media &= ~options;
248 if (options & IFM_HDX) {
249 ifr.ifr_media &= ~IFM_FDX;
252 ifr.ifr_media |= options;
254 ifmr->ifm_current = ifr.ifr_media;
255 callback_register(setifmediacallback, (void *)ifmr);
259 setmediainst(const char *val, int d, int s, const struct afswtch *afp)
261 struct ifmediareq *ifmr;
264 ifmr = ifmedia_getstate();
267 if (inst < 0 || inst > (int)IFM_INST_MAX)
268 errx(1, "invalid media instance: %s", val);
270 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
271 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
273 ifmr->ifm_current = ifr.ifr_media;
274 callback_register(setifmediacallback, (void *)ifmr);
278 setmediamode(const char *val, int d, int s, const struct afswtch *afp)
280 struct ifmediareq *ifmr;
283 ifmr = ifmedia_getstate();
285 mode = get_media_mode(ifmr->ifm_ulist[0], val);
287 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
288 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
290 ifmr->ifm_current = ifr.ifr_media;
291 callback_register(setifmediacallback, (void *)ifmr);
295 get_media_subtype(ifmedia_t media, const char *val)
299 subtype = ifconfig_media_lookup_subtype(media, val);
300 if (subtype != INVALID_IFMEDIA)
304 errx(EXIT_FAILURE, "unknown media type 0x%x", media);
306 errx(EXIT_FAILURE, "unknown media subtype: %s", val);
308 err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
314 get_media_mode(ifmedia_t media, const char *val)
318 mode = ifconfig_media_lookup_mode(media, val);
319 if (mode != INVALID_IFMEDIA)
323 errx(EXIT_FAILURE, "unknown media type 0x%x", media);
325 return (INVALID_IFMEDIA);
327 err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
333 get_media_options(ifmedia_t media, const char *val)
336 const char **optnames;
342 * We muck with the string, so copy it.
346 err(EXIT_FAILURE, "strdup");
349 * Split the comma-delimited list into separate strings.
352 for (opt = opts; (opt = strtok(opt, ",")) != NULL; opt = NULL)
358 optnames = calloc(nopts, sizeof(*optnames));
359 if (optnames == NULL)
360 err(EXIT_FAILURE, "calloc");
362 for (size_t i = 0; i < nopts; ++i) {
364 opt = strchr(opt, '\0') + 1;
368 * Look up the options in the user-provided list.
370 options = ifconfig_media_lookup_options(media, optnames, nopts);
372 err(EXIT_FAILURE, "ifconfig_media_lookup_options");
374 for (size_t i = 0; i < nopts; ++i) {
375 if (options[i] == INVALID_IFMEDIA)
376 errx(EXIT_FAILURE, "unknown option: %s", optnames[i]);
386 print_media(ifmedia_t media, bool print_toptype)
388 const char *val, **options;
390 val = ifconfig_media_get_type(media);
392 printf("<unknown type>");
394 } else if (print_toptype) {
398 val = ifconfig_media_get_subtype(media);
400 printf("<unknown subtype>");
410 val = ifconfig_media_get_mode(media);
411 if (val != NULL && strcasecmp("autoselect", val) != 0)
412 printf(" mode %s", val);
415 options = ifconfig_media_get_options(media);
416 if (options != NULL && options[0] != NULL) {
417 printf(" <%s", options[0]);
418 for (size_t i = 1; options[i] != NULL; ++i)
419 printf(",%s", options[i]);
424 if (print_toptype && IFM_INST(media) != 0)
425 printf(" instance %d", IFM_INST(media));
429 print_media_ifconfig(ifmedia_t media)
431 const char *val, **options;
433 val = ifconfig_media_get_type(media);
435 printf("<unknown type>");
440 * Don't print the top-level type; it's not like we can
441 * change it, or anything.
444 val = ifconfig_media_get_subtype(media);
446 printf("<unknown subtype>");
450 printf("media %s", val);
452 val = ifconfig_media_get_mode(media);
454 printf(" mode %s", val);
456 options = ifconfig_media_get_options(media);
457 if (options != NULL && options[0] != NULL) {
458 printf(" mediaopt %s", options[0]);
459 for (size_t i = 1; options[i] != NULL; ++i)
460 printf(",%s", options[i]);
464 if (IFM_INST(media) != 0)
465 printf(" instance %d", IFM_INST(media));
468 /**********************************************************************
470 **********************************************************************/
472 static struct cmd media_cmds[] = {
473 DEF_CMD_ARG("media", setmedia),
474 DEF_CMD_ARG("mode", setmediamode),
475 DEF_CMD_ARG("mediaopt", setmediaopt),
476 DEF_CMD_ARG("-mediaopt",unsetmediaopt),
477 DEF_CMD_ARG("inst", setmediainst),
478 DEF_CMD_ARG("instance", setmediainst),
480 static struct afswtch af_media = {
481 .af_name = "af_media",
483 .af_other_status = media_status,
486 static __constructor void
491 for (i = 0; i < nitems(media_cmds); i++)
492 cmd_register(&media_cmds[i]);
493 af_register(&af_media);