1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
2 /* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.6.2.3 2001/11/14 04:35:07 yar Exp $ */
3 /* $DragonFly: src/sbin/ifconfig/ifmedia.c,v 1.4 2003/11/01 17:15:59 drhodus Exp $ */
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 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Berkeley and its contributors.
53 * 4. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 #include <sys/param.h>
71 #include <sys/ioctl.h>
72 #include <sys/socket.h>
73 #include <sys/sysctl.h>
77 #include <net/if_dl.h>
78 #include <net/if_types.h>
79 #include <net/if_media.h>
80 #include <net/route.h>
93 static void domediaopt(const char *, int, int);
94 static int get_media_subtype(int, const char *);
95 static int get_media_options(int, const char *);
96 static int lookup_media_word(struct ifmedia_description *, const char *);
97 static void print_media_word(int, int);
98 static void print_media_word_ifconfig(int);
100 static struct ifmedia_description *get_toptype_desc(int);
101 static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
102 static struct ifmedia_description *get_subtype_desc __P((int,
103 struct ifmedia_type_to_subtype *ttos));
106 media_status(int s, struct rt_addrinfo *info __unused)
108 struct ifmediareq ifmr;
111 (void) memset(&ifmr, 0, sizeof(ifmr));
112 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
114 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
116 * Interface doesn't support SIOC{G,S}IFMEDIA.
121 if (ifmr.ifm_count == 0) {
122 warnx("%s: no media types?", name);
126 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
127 if (media_list == NULL)
129 ifmr.ifm_ulist = media_list;
131 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
132 err(1, "SIOCGIFMEDIA");
135 print_media_word(ifmr.ifm_current, 1);
136 if (ifmr.ifm_active != ifmr.ifm_current) {
139 print_media_word(ifmr.ifm_active, 0);
145 if (ifmr.ifm_status & IFM_AVALID) {
146 printf("\tstatus: ");
147 switch (IFM_TYPE(ifmr.ifm_active)) {
149 if (ifmr.ifm_status & IFM_ACTIVE)
152 printf("no carrier");
157 if (ifmr.ifm_status & IFM_ACTIVE)
163 /* XXX: Different value for adhoc? */
164 if (ifmr.ifm_status & IFM_ACTIVE)
165 printf("associated");
167 printf("no carrier");
173 if (ifmr.ifm_count > 0 && supmedia) {
174 printf("\tsupported media:\n");
175 for (i = 0; i < ifmr.ifm_count; i++) {
177 print_media_word_ifconfig(media_list[i]);
186 setmedia(const char *val, int d, int s, const struct afswtch *afp)
188 struct ifmediareq ifmr;
189 int first_type, subtype;
191 (void) memset(&ifmr, 0, sizeof(ifmr));
192 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
195 ifmr.ifm_ulist = &first_type;
196 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
198 * If we get E2BIG, the kernel is telling us
199 * that there are more, so we can ignore it.
202 err(1, "SIOCGIFMEDIA");
205 if (ifmr.ifm_count == 0)
206 errx(1, "%s: no media types?", name);
209 * We are primarily concerned with the top-level type.
210 * However, "current" may be only IFM_NONE, so we just look
211 * for the top-level type in the first "supported type"
214 * (I'm assuming that all supported media types for a given
215 * interface will be the same top-level type..)
217 subtype = get_media_subtype(IFM_TYPE(first_type), val);
219 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
220 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
221 IFM_TYPE(first_type) | subtype;
223 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
224 err(1, "SIOCSIFMEDIA");
228 setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
231 domediaopt(val, 0, s);
235 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
238 domediaopt(val, 1, s);
242 domediaopt(const char *val, int clear, int s)
244 struct ifmediareq ifmr;
245 int *mwords, options;
247 (void) memset(&ifmr, 0, sizeof(ifmr));
248 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
251 * We must go through the motions of reading all
252 * supported media because we need to know both
253 * the current media type and the top-level type.
256 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
257 err(1, "SIOCGIFMEDIA");
259 if (ifmr.ifm_count == 0)
260 errx(1, "%s: no media types?", name);
262 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
266 ifmr.ifm_ulist = mwords;
267 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
268 err(1, "SIOCGIFMEDIA");
270 options = get_media_options(IFM_TYPE(mwords[0]), val);
274 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
275 ifr.ifr_media = ifmr.ifm_current;
277 ifr.ifr_media &= ~options;
279 ifr.ifr_media |= options;
281 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
282 err(1, "SIOCSIFMEDIA");
285 /**********************************************************************
286 * A good chunk of this is duplicated from sys/net/ifmedia.c
287 **********************************************************************/
289 static struct ifmedia_description ifm_type_descriptions[] =
290 IFM_TYPE_DESCRIPTIONS;
292 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
293 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
295 static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
296 IFM_SUBTYPE_ETHERNET_ALIASES;
298 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
299 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
301 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
302 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
304 static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
305 IFM_SUBTYPE_TOKENRING_ALIASES;
307 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
308 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
310 static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
311 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
313 static struct ifmedia_description ifm_subtype_fddi_aliases[] =
314 IFM_SUBTYPE_FDDI_ALIASES;
316 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
317 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
319 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
320 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
322 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
323 IFM_SUBTYPE_IEEE80211_ALIASES;
325 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
326 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
328 static struct ifmedia_description ifm_subtype_shared_descriptions[] =
329 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
331 static struct ifmedia_description ifm_subtype_shared_aliases[] =
332 IFM_SUBTYPE_SHARED_ALIASES;
334 static struct ifmedia_description ifm_shared_option_descriptions[] =
335 IFM_SHARED_OPTION_DESCRIPTIONS;
337 struct ifmedia_type_to_subtype {
339 struct ifmedia_description *desc;
343 struct ifmedia_description *desc;
348 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
349 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
352 { &ifm_subtype_shared_descriptions[0], 0 },
353 { &ifm_subtype_shared_aliases[0], 1 },
354 { &ifm_subtype_ethernet_descriptions[0], 0 },
355 { &ifm_subtype_ethernet_aliases[0], 1 },
359 { &ifm_shared_option_descriptions[0], 0 },
360 { &ifm_subtype_ethernet_option_descriptions[0], 0 },
366 { &ifm_subtype_shared_descriptions[0], 0 },
367 { &ifm_subtype_shared_aliases[0], 1 },
368 { &ifm_subtype_tokenring_descriptions[0], 0 },
369 { &ifm_subtype_tokenring_aliases[0], 1 },
373 { &ifm_shared_option_descriptions[0], 0 },
374 { &ifm_subtype_tokenring_option_descriptions[0], 0 },
380 { &ifm_subtype_shared_descriptions[0], 0 },
381 { &ifm_subtype_shared_aliases[0], 1 },
382 { &ifm_subtype_fddi_descriptions[0], 0 },
383 { &ifm_subtype_fddi_aliases[0], 1 },
387 { &ifm_shared_option_descriptions[0], 0 },
388 { &ifm_subtype_fddi_option_descriptions[0], 0 },
394 { &ifm_subtype_shared_descriptions[0], 0 },
395 { &ifm_subtype_shared_aliases[0], 1 },
396 { &ifm_subtype_ieee80211_descriptions[0], 0 },
397 { &ifm_subtype_ieee80211_aliases[0], 1 },
401 { &ifm_shared_option_descriptions[0], 0 },
402 { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
409 get_media_subtype(int type, const char *val)
411 struct ifmedia_description *desc;
412 struct ifmedia_type_to_subtype *ttos;
415 /* Find the top-level interface type. */
416 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
417 desc->ifmt_string != NULL; desc++, ttos++)
418 if (type == desc->ifmt_word)
420 if (desc->ifmt_string == NULL)
421 errx(1, "unknown media type 0x%x", type);
423 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
424 rval = lookup_media_word(ttos->subtypes[i].desc, val);
428 errx(1, "unknown media subtype: %s", val);
433 get_media_options(int type, const char *val)
435 struct ifmedia_description *desc;
436 struct ifmedia_type_to_subtype *ttos;
437 char *optlist, *optptr;
438 int option = 0, i, rval = 0;
440 /* We muck with the string, so copy it. */
441 optlist = strdup(val);
445 /* Find the top-level interface type. */
446 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
447 desc->ifmt_string != NULL; desc++, ttos++)
448 if (type == desc->ifmt_word)
450 if (desc->ifmt_string == NULL)
451 errx(1, "unknown media type 0x%x", type);
454 * Look up the options in the user-provided comma-separated
458 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
459 for (i = 0; ttos->options[i].desc != NULL; i++) {
460 option = lookup_media_word(ttos->options[i].desc, optptr);
465 errx(1, "unknown option: %s", optptr);
474 lookup_media_word(struct ifmedia_description *desc, const char *val)
477 for (; desc->ifmt_string != NULL; desc++)
478 if (strcasecmp(desc->ifmt_string, val) == 0)
479 return (desc->ifmt_word);
484 static struct ifmedia_description *get_toptype_desc(int ifmw)
486 struct ifmedia_description *desc;
488 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
489 if (IFM_TYPE(ifmw) == desc->ifmt_word)
495 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
497 struct ifmedia_description *desc;
498 struct ifmedia_type_to_subtype *ttos;
500 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
501 desc->ifmt_string != NULL; desc++, ttos++)
502 if (IFM_TYPE(ifmw) == desc->ifmt_word)
508 static struct ifmedia_description *get_subtype_desc(int ifmw,
509 struct ifmedia_type_to_subtype *ttos)
512 struct ifmedia_description *desc;
514 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
515 if (ttos->subtypes[i].alias)
517 for (desc = ttos->subtypes[i].desc;
518 desc->ifmt_string != NULL; desc++) {
519 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
528 print_media_word(int ifmw, int print_toptype)
530 struct ifmedia_description *desc;
531 struct ifmedia_type_to_subtype *ttos;
532 int seen_option = 0, i;
534 /* Find the top-level interface type. */
535 desc = get_toptype_desc(ifmw);
536 ttos = get_toptype_ttos(ifmw);
537 if (desc->ifmt_string == NULL) {
538 printf("<unknown type>");
540 } else if (print_toptype) {
541 printf("%s", desc->ifmt_string);
545 * Don't print the top-level type; it's not like we can
546 * change it, or anything.
550 desc = get_subtype_desc(ifmw, ttos);
554 /* Falling to here means unknown subtype. */
555 printf("<unknown subtype>");
562 printf("%s", desc->ifmt_string);
565 for (i = 0; ttos->options[i].desc != NULL; i++) {
566 if (ttos->options[i].alias)
568 for (desc = ttos->options[i].desc;
569 desc->ifmt_string != NULL; desc++) {
570 if (ifmw & desc->ifmt_word) {
571 if (seen_option == 0)
573 printf("%s%s", seen_option++ ? "," : "",
578 printf("%s", seen_option ? ">" : "");
582 print_media_word_ifconfig(int ifmw)
584 struct ifmedia_description *desc;
585 struct ifmedia_type_to_subtype *ttos;
588 /* Find the top-level interface type. */
589 desc = get_toptype_desc(ifmw);
590 ttos = get_toptype_ttos(ifmw);
591 if (desc->ifmt_string == NULL) {
592 printf("<unknown type>");
597 * Don't print the top-level type; it's not like we can
598 * change it, or anything.
602 desc = get_subtype_desc(ifmw, ttos);
606 /* Falling to here means unknown subtype. */
607 printf("<unknown subtype>");
611 printf("media %s", desc->ifmt_string);
614 for (i = 0; ttos->options[i].desc != NULL; i++) {
615 if (ttos->options[i].alias)
617 for (desc = ttos->options[i].desc;
618 desc->ifmt_string != NULL; desc++) {
619 if (ifmw & desc->ifmt_word) {
620 printf(" mediaopt %s", desc->ifmt_string);
626 /**********************************************************************
628 **********************************************************************/