1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
5 * Copyright (c) 1997 Jason R. Thorpe.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the NetBSD Project
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * Copyright (c) 1983, 1993
38 * The Regents of the University of California. All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * based on sbin/ifconfig/ifmedia.c r221954
68 #include <sys/param.h>
69 #include <sys/ioctl.h>
70 #include <sys/socket.h>
71 #include <sys/sysctl.h>
75 #include <net/if_dl.h>
76 #include <net/if_types.h>
77 #include <net/if_media.h>
78 #include <net/route.h>
89 void domediaopt(const char *, int, int);
90 int get_media_subtype(int, const char *);
91 int get_media_mode(int, const char *);
92 int get_media_options(int, const char *);
93 int lookup_media_word(struct ifmedia_description *, const char *);
94 void print_media_word(int, int);
95 void print_media_word_ifconfig(int);
98 static struct ifmedia_description *get_toptype_desc(int);
99 static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
100 static struct ifmedia_description *get_subtype_desc(int,
101 struct ifmedia_type_to_subtype *ttos);
103 #define IFM_OPMODE(x) \
104 ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
105 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
107 #define IFM_IEEE80211_STA 0
112 struct ifmediareq ifmr;
115 (void) memset(&ifmr, 0, sizeof(ifmr));
116 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
118 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
120 * Interface doesn't support SIOC{G,S}IFMEDIA.
125 if (ifmr.ifm_count == 0) {
126 warnx("%s: no media types?", name);
130 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
131 if (media_list == NULL)
133 ifmr.ifm_ulist = media_list;
135 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
136 err(1, "SIOCGIFMEDIA");
139 print_media_word(ifmr.ifm_current, 1);
140 if (ifmr.ifm_active != ifmr.ifm_current) {
143 print_media_word(ifmr.ifm_active, 0);
149 if (ifmr.ifm_status & IFM_AVALID) {
150 printf("\tstatus: ");
151 switch (IFM_TYPE(ifmr.ifm_active)) {
154 if (ifmr.ifm_status & IFM_ACTIVE)
157 printf("no carrier");
162 if (ifmr.ifm_status & IFM_ACTIVE)
169 if (ifmr.ifm_status & IFM_ACTIVE) {
170 /* NB: only sta mode associates */
171 if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
172 printf("associated");
176 printf("no carrier");
182 if (ifmr.ifm_count > 0 && supmedia) {
183 printf("\tsupported media:\n");
184 for (i = 0; i < ifmr.ifm_count; i++) {
186 print_media_word_ifconfig(media_list[i]);
195 ifmedia_getstate(int s)
197 static struct ifmediareq *ifmr = NULL;
201 ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
205 (void) memset(ifmr, 0, sizeof(struct ifmediareq));
206 (void) strncpy(ifmr->ifm_name, name,
207 sizeof(ifmr->ifm_name));
210 ifmr->ifm_ulist = NULL;
213 * We must go through the motions of reading all
214 * supported media because we need to know both
215 * the current media type and the top-level type.
218 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
219 err(1, "SIOCGIFMEDIA");
222 if (ifmr->ifm_count == 0)
223 errx(1, "%s: no media types?", name);
225 mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
229 ifmr->ifm_ulist = mwords;
230 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
231 err(1, "SIOCGIFMEDIA");
238 setifmediacallback(int s, void *arg)
240 struct ifmediareq *ifmr = (struct ifmediareq *)arg;
241 static int did_it = 0;
244 ifr.ifr_media = ifmr->ifm_current;
245 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
246 err(1, "SIOCSIFMEDIA (media)");
247 free(ifmr->ifm_ulist);
254 setmedia(const char *val, int d, int s, const struct afswtch *afp)
256 struct ifmediareq *ifmr;
259 ifmr = ifmedia_getstate(s);
262 * We are primarily concerned with the top-level type.
263 * However, "current" may be only IFM_NONE, so we just look
264 * for the top-level type in the first "supported type"
267 * (I'm assuming that all supported media types for a given
268 * interface will be the same top-level type..)
270 subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
272 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
273 ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
274 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
276 ifmr->ifm_current = ifr.ifr_media;
277 callback_register(setifmediacallback, (void *)ifmr);
281 setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
284 domediaopt(val, 0, s);
288 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
291 domediaopt(val, 1, s);
295 domediaopt(const char *val, int clear, int s)
297 struct ifmediareq *ifmr;
300 ifmr = ifmedia_getstate(s);
302 options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
304 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
305 ifr.ifr_media = ifmr->ifm_current;
307 ifr.ifr_media &= ~options;
309 if (options & IFM_HDX) {
310 ifr.ifr_media &= ~IFM_FDX;
313 ifr.ifr_media |= options;
315 ifmr->ifm_current = ifr.ifr_media;
316 callback_register(setifmediacallback, (void *)ifmr);
320 setmediainst(const char *val, int d, int s, const struct afswtch *afp)
322 struct ifmediareq *ifmr;
325 ifmr = ifmedia_getstate(s);
328 if (inst < 0 || inst > (int)IFM_INST_MAX)
329 errx(1, "invalid media instance: %s", val);
331 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
332 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
334 ifmr->ifm_current = ifr.ifr_media;
335 callback_register(setifmediacallback, (void *)ifmr);
339 setmediamode(const char *val, int d, int s, const struct afswtch *afp)
341 struct ifmediareq *ifmr;
344 ifmr = ifmedia_getstate(s);
346 mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
348 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
349 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
351 ifmr->ifm_current = ifr.ifr_media;
352 callback_register(setifmediacallback, (void *)ifmr);
356 /**********************************************************************
357 * A good chunk of this is duplicated from sys/net/ifmedia.c
358 **********************************************************************/
360 static struct ifmedia_description ifm_type_descriptions[] =
361 IFM_TYPE_DESCRIPTIONS;
363 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
364 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
366 static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
367 IFM_SUBTYPE_ETHERNET_ALIASES;
369 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
370 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
372 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
373 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
375 static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
376 IFM_SUBTYPE_TOKENRING_ALIASES;
378 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
379 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
381 static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
382 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
384 static struct ifmedia_description ifm_subtype_fddi_aliases[] =
385 IFM_SUBTYPE_FDDI_ALIASES;
387 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
388 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
390 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
391 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
393 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
394 IFM_SUBTYPE_IEEE80211_ALIASES;
396 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
397 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
399 static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
400 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
402 static struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
403 IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
405 static struct ifmedia_description ifm_subtype_atm_descriptions[] =
406 IFM_SUBTYPE_ATM_DESCRIPTIONS;
408 static struct ifmedia_description ifm_subtype_atm_aliases[] =
409 IFM_SUBTYPE_ATM_ALIASES;
411 static struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
412 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
414 static struct ifmedia_description ifm_subtype_shared_descriptions[] =
415 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
417 static struct ifmedia_description ifm_subtype_shared_aliases[] =
418 IFM_SUBTYPE_SHARED_ALIASES;
420 static struct ifmedia_description ifm_shared_option_descriptions[] =
421 IFM_SHARED_OPTION_DESCRIPTIONS;
423 static struct ifmedia_description ifm_shared_option_aliases[] =
424 IFM_SHARED_OPTION_ALIASES;
426 struct ifmedia_type_to_subtype {
428 struct ifmedia_description *desc;
432 struct ifmedia_description *desc;
436 struct ifmedia_description *desc;
441 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
442 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
445 { &ifm_subtype_shared_descriptions[0], 0 },
446 { &ifm_subtype_shared_aliases[0], 1 },
447 { &ifm_subtype_ethernet_descriptions[0], 0 },
448 { &ifm_subtype_ethernet_aliases[0], 1 },
452 { &ifm_shared_option_descriptions[0], 0 },
453 { &ifm_shared_option_aliases[0], 1 },
454 { &ifm_subtype_ethernet_option_descriptions[0], 0 },
463 { &ifm_subtype_shared_descriptions[0], 0 },
464 { &ifm_subtype_shared_aliases[0], 1 },
465 { &ifm_subtype_tokenring_descriptions[0], 0 },
466 { &ifm_subtype_tokenring_aliases[0], 1 },
470 { &ifm_shared_option_descriptions[0], 0 },
471 { &ifm_shared_option_aliases[0], 1 },
472 { &ifm_subtype_tokenring_option_descriptions[0], 0 },
481 { &ifm_subtype_shared_descriptions[0], 0 },
482 { &ifm_subtype_shared_aliases[0], 1 },
483 { &ifm_subtype_fddi_descriptions[0], 0 },
484 { &ifm_subtype_fddi_aliases[0], 1 },
488 { &ifm_shared_option_descriptions[0], 0 },
489 { &ifm_shared_option_aliases[0], 1 },
490 { &ifm_subtype_fddi_option_descriptions[0], 0 },
499 { &ifm_subtype_shared_descriptions[0], 0 },
500 { &ifm_subtype_shared_aliases[0], 1 },
501 { &ifm_subtype_ieee80211_descriptions[0], 0 },
502 { &ifm_subtype_ieee80211_aliases[0], 1 },
506 { &ifm_shared_option_descriptions[0], 0 },
507 { &ifm_shared_option_aliases[0], 1 },
508 { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
512 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
513 { &ifm_subtype_ieee80211_mode_aliases[0], 0 },
519 { &ifm_subtype_shared_descriptions[0], 0 },
520 { &ifm_subtype_shared_aliases[0], 1 },
521 { &ifm_subtype_atm_descriptions[0], 0 },
522 { &ifm_subtype_atm_aliases[0], 1 },
526 { &ifm_shared_option_descriptions[0], 0 },
527 { &ifm_shared_option_aliases[0], 1 },
528 { &ifm_subtype_atm_option_descriptions[0], 0 },
538 get_media_subtype(int type, const char *val)
540 struct ifmedia_description *desc;
541 struct ifmedia_type_to_subtype *ttos;
544 /* Find the top-level interface type. */
545 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
546 desc->ifmt_string != NULL; desc++, ttos++)
547 if (type == desc->ifmt_word)
549 if (desc->ifmt_string == NULL)
550 errx(1, "unknown media type 0x%x", type);
552 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
553 rval = lookup_media_word(ttos->subtypes[i].desc, val);
557 errx(1, "unknown media subtype: %s", val);
562 get_media_mode(int type, const char *val)
564 struct ifmedia_description *desc;
565 struct ifmedia_type_to_subtype *ttos;
568 /* Find the top-level interface type. */
569 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
570 desc->ifmt_string != NULL; desc++, ttos++)
571 if (type == desc->ifmt_word)
573 if (desc->ifmt_string == NULL)
574 errx(1, "unknown media mode 0x%x", type);
576 for (i = 0; ttos->modes[i].desc != NULL; i++) {
577 rval = lookup_media_word(ttos->modes[i].desc, val);
585 get_media_options(int type, const char *val)
587 struct ifmedia_description *desc;
588 struct ifmedia_type_to_subtype *ttos;
589 char *optlist, *optptr;
590 int option = 0, i, rval = 0;
592 /* We muck with the string, so copy it. */
593 optlist = strdup(val);
597 /* Find the top-level interface type. */
598 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
599 desc->ifmt_string != NULL; desc++, ttos++)
600 if (type == desc->ifmt_word)
602 if (desc->ifmt_string == NULL)
603 errx(1, "unknown media type 0x%x", type);
606 * Look up the options in the user-provided comma-separated
610 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
611 for (i = 0; ttos->options[i].desc != NULL; i++) {
612 option = lookup_media_word(ttos->options[i].desc, optptr);
617 errx(1, "unknown option: %s", optptr);
626 lookup_media_word(struct ifmedia_description *desc, const char *val)
629 for (; desc->ifmt_string != NULL; desc++)
630 if (strcasecmp(desc->ifmt_string, val) == 0)
631 return (desc->ifmt_word);
636 static struct ifmedia_description *get_toptype_desc(int ifmw)
638 struct ifmedia_description *desc;
640 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
641 if (IFM_TYPE(ifmw) == desc->ifmt_word)
647 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
649 struct ifmedia_description *desc;
650 struct ifmedia_type_to_subtype *ttos;
652 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
653 desc->ifmt_string != NULL; desc++, ttos++)
654 if (IFM_TYPE(ifmw) == desc->ifmt_word)
660 static struct ifmedia_description *get_subtype_desc(int ifmw,
661 struct ifmedia_type_to_subtype *ttos)
664 struct ifmedia_description *desc;
666 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
667 if (ttos->subtypes[i].alias)
669 for (desc = ttos->subtypes[i].desc;
670 desc->ifmt_string != NULL; desc++) {
671 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
679 static struct ifmedia_description *get_mode_desc(int ifmw,
680 struct ifmedia_type_to_subtype *ttos)
683 struct ifmedia_description *desc;
685 for (i = 0; ttos->modes[i].desc != NULL; i++) {
686 if (ttos->modes[i].alias)
688 for (desc = ttos->modes[i].desc;
689 desc->ifmt_string != NULL; desc++) {
690 if (IFM_MODE(ifmw) == desc->ifmt_word)
699 print_media_word(int ifmw, int print_toptype)
701 struct ifmedia_description *desc;
702 struct ifmedia_type_to_subtype *ttos;
703 int seen_option = 0, i;
705 /* Find the top-level interface type. */
706 desc = get_toptype_desc(ifmw);
707 ttos = get_toptype_ttos(ifmw);
708 if (desc->ifmt_string == NULL) {
709 printf("<unknown type>");
711 } else if (print_toptype) {
712 printf("%s", desc->ifmt_string);
716 * Don't print the top-level type; it's not like we can
717 * change it, or anything.
721 desc = get_subtype_desc(ifmw, ttos);
723 printf("<unknown subtype>");
730 printf("%s", desc->ifmt_string);
733 desc = get_mode_desc(ifmw, ttos);
734 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
735 printf(" mode %s", desc->ifmt_string);
739 for (i = 0; ttos->options[i].desc != NULL; i++) {
740 if (ttos->options[i].alias)
742 for (desc = ttos->options[i].desc;
743 desc->ifmt_string != NULL; desc++) {
744 if (ifmw & desc->ifmt_word) {
745 if (seen_option == 0)
747 printf("%s%s", seen_option++ ? "," : "",
752 printf("%s", seen_option ? ">" : "");
754 if (print_toptype && IFM_INST(ifmw) != 0)
755 printf(" instance %d", IFM_INST(ifmw));
759 print_media_word_ifconfig(int ifmw)
761 struct ifmedia_description *desc;
762 struct ifmedia_type_to_subtype *ttos;
763 int seen_option = 0, i;
765 /* Find the top-level interface type. */
766 desc = get_toptype_desc(ifmw);
767 ttos = get_toptype_ttos(ifmw);
768 if (desc->ifmt_string == NULL) {
769 printf("<unknown type>");
774 * Don't print the top-level type; it's not like we can
775 * change it, or anything.
779 desc = get_subtype_desc(ifmw, ttos);
781 printf("<unknown subtype>");
785 printf("media %s", desc->ifmt_string);
787 desc = get_mode_desc(ifmw, ttos);
789 printf(" mode %s", desc->ifmt_string);
792 for (i = 0; ttos->options[i].desc != NULL; i++) {
793 if (ttos->options[i].alias)
795 for (desc = ttos->options[i].desc;
796 desc->ifmt_string != NULL; desc++) {
797 if (ifmw & desc->ifmt_word) {
798 if (seen_option == 0)
799 printf(" mediaopt ");
800 printf("%s%s", seen_option++ ? "," : "",
806 if (IFM_INST(ifmw) != 0)
807 printf(" instance %d", IFM_INST(ifmw));
810 /**********************************************************************
812 **********************************************************************/