ifmedia.c revision 140913
125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 140913 2005-01-27 16:40:12Z ambrisko $ */ 325450Speter 425450Speter/* 525450Speter * Copyright (c) 1997 Jason R. Thorpe. 625450Speter * All rights reserved. 725450Speter * 825450Speter * Redistribution and use in source and binary forms, with or without 925450Speter * modification, are permitted provided that the following conditions 1025450Speter * are met: 1125450Speter * 1. Redistributions of source code must retain the above copyright 1225450Speter * notice, this list of conditions and the following disclaimer. 1325450Speter * 2. Redistributions in binary form must reproduce the above copyright 1425450Speter * notice, this list of conditions and the following disclaimer in the 1525450Speter * documentation and/or other materials provided with the distribution. 1625450Speter * 3. All advertising materials mentioning features or use of this software 1725450Speter * must display the following acknowledgement: 1825450Speter * This product includes software developed for the NetBSD Project 1925450Speter * by Jason R. Thorpe. 2025450Speter * 4. The name of the author may not be used to endorse or promote products 2125450Speter * derived from this software without specific prior written permission. 2225450Speter * 2325450Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2425450Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2525450Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2625450Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2725450Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2825450Speter * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2925450Speter * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 3025450Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3125450Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3225450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3325450Speter * SUCH DAMAGE. 3425450Speter */ 3525450Speter 3625450Speter/* 3725450Speter * Copyright (c) 1983, 1993 3825450Speter * The Regents of the University of California. All rights reserved. 3925450Speter * 4025450Speter * Redistribution and use in source and binary forms, with or without 4125450Speter * modification, are permitted provided that the following conditions 4225450Speter * are met: 4325450Speter * 1. Redistributions of source code must retain the above copyright 4425450Speter * notice, this list of conditions and the following disclaimer. 4525450Speter * 2. Redistributions in binary form must reproduce the above copyright 4625450Speter * notice, this list of conditions and the following disclaimer in the 4725450Speter * documentation and/or other materials provided with the distribution. 4825450Speter * 3. All advertising materials mentioning features or use of this software 4925450Speter * must display the following acknowledgement: 5025450Speter * This product includes software developed by the University of 5125450Speter * California, Berkeley and its contributors. 5225450Speter * 4. Neither the name of the University nor the names of its contributors 5325450Speter * may be used to endorse or promote products derived from this software 5425450Speter * without specific prior written permission. 5525450Speter * 5625450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5725450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5825450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5925450Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6025450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6125450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6225450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6325450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6425450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6525450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6625450Speter * SUCH DAMAGE. 6725450Speter */ 6825450Speter 6925450Speter#include <sys/param.h> 7025450Speter#include <sys/ioctl.h> 7125450Speter#include <sys/socket.h> 7225450Speter#include <sys/sysctl.h> 7325450Speter#include <sys/time.h> 7425450Speter 7525450Speter#include <net/if.h> 7625450Speter#include <net/if_dl.h> 7725450Speter#include <net/if_types.h> 7825450Speter#include <net/if_media.h> 7925450Speter#include <net/route.h> 8025450Speter 8125450Speter#include <ctype.h> 8225450Speter#include <err.h> 8325450Speter#include <errno.h> 8425450Speter#include <fcntl.h> 8525450Speter#include <stdio.h> 8625450Speter#include <stdlib.h> 8725450Speter#include <string.h> 8825450Speter#include <unistd.h> 8925450Speter 9025450Speter#include "ifconfig.h" 9125450Speter 9295005Simpstatic void domediaopt(const char *, int, int); 9395005Simpstatic int get_media_subtype(int, const char *); 94114164Ssamstatic int get_media_mode(int, const char *); 9595005Simpstatic int get_media_options(int, const char *); 9695005Simpstatic int lookup_media_word(struct ifmedia_description *, const char *); 9795005Simpstatic void print_media_word(int, int); 9895005Simpstatic void print_media_word_ifconfig(int); 9925450Speter 10095005Simpstatic struct ifmedia_description *get_toptype_desc(int); 10195005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 10295005Simpstatic struct ifmedia_description *get_subtype_desc(int, 10395005Simp struct ifmedia_type_to_subtype *ttos); 10477385Sphk 105138593Ssamstatic void 106139494Ssammedia_status(int s) 10725450Speter{ 10825450Speter struct ifmediareq ifmr; 10925450Speter int *media_list, i; 11025450Speter 11125450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11225450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11325450Speter 11425450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 11525450Speter /* 11625450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 11725450Speter */ 11825450Speter return; 11925450Speter } 12025450Speter 12125450Speter if (ifmr.ifm_count == 0) { 12225450Speter warnx("%s: no media types?", name); 12325450Speter return; 12425450Speter } 12525450Speter 12625450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 12725450Speter if (media_list == NULL) 12825450Speter err(1, "malloc"); 12925450Speter ifmr.ifm_ulist = media_list; 13025450Speter 13125450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13225450Speter err(1, "SIOCGIFMEDIA"); 13325450Speter 13425450Speter printf("\tmedia: "); 13577385Sphk print_media_word(ifmr.ifm_current, 1); 13625450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 13725450Speter putchar(' '); 13825450Speter putchar('('); 13977385Sphk print_media_word(ifmr.ifm_active, 0); 14025450Speter putchar(')'); 14125450Speter } 14225450Speter 14377385Sphk putchar('\n'); 14477385Sphk 14525450Speter if (ifmr.ifm_status & IFM_AVALID) { 14677385Sphk printf("\tstatus: "); 14725450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 14825450Speter case IFM_ETHER: 14925450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15025450Speter printf("active"); 15125450Speter else 15225450Speter printf("no carrier"); 15325450Speter break; 15425450Speter 15525450Speter case IFM_FDDI: 15625450Speter case IFM_TOKEN: 15725450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15825450Speter printf("inserted"); 15925450Speter else 16025450Speter printf("no ring"); 16125450Speter break; 162114232Sharti 163114232Sharti case IFM_ATM: 164114232Sharti if (ifmr.ifm_status & IFM_ACTIVE) 165114232Sharti printf("active"); 166114232Sharti else 167114232Sharti printf("no carrier"); 168114232Sharti break; 169114232Sharti 17077217Sphk case IFM_IEEE80211: 17177217Sphk /* XXX: Different value for adhoc? */ 17277217Sphk if (ifmr.ifm_status & IFM_ACTIVE) 17377217Sphk printf("associated"); 17477217Sphk else 17577217Sphk printf("no carrier"); 17677217Sphk break; 17725450Speter } 17885853Syar putchar('\n'); 17925450Speter } 18025450Speter 18177385Sphk if (ifmr.ifm_count > 0 && supmedia) { 18277385Sphk printf("\tsupported media:\n"); 18325450Speter for (i = 0; i < ifmr.ifm_count; i++) { 18477385Sphk printf("\t\t"); 18577385Sphk print_media_word_ifconfig(media_list[i]); 18677385Sphk putchar('\n'); 18725450Speter } 18825450Speter } 18925450Speter 19025450Speter free(media_list); 19125450Speter} 19225450Speter 193140913Sambriskostatic struct ifmediareq * 194140913Sambriskogetifmediastate(int s) 19525450Speter{ 196140913Sambrisko static struct ifmediareq *ifmr = NULL; 197140913Sambrisko int *mwords; 19825450Speter 199140913Sambrisko if (ifmr == NULL) { 200140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 201140913Sambrisko if (ifmr == NULL) 202140913Sambrisko err(1, "malloc"); 20325450Speter 204140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 205140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 206140913Sambrisko sizeof(ifmr->ifm_name)); 207140913Sambrisko 208140913Sambrisko ifmr->ifm_count = 0; 209140913Sambrisko ifmr->ifm_ulist = NULL; 210140913Sambrisko 21125450Speter /* 212140913Sambrisko * We must go through the motions of reading all 213140913Sambrisko * supported media because we need to know both 214140913Sambrisko * the current media type and the top-level type. 21525450Speter */ 216140913Sambrisko 217140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 21825450Speter err(1, "SIOCGIFMEDIA"); 219140913Sambrisko } 220140913Sambrisko 221140913Sambrisko if (ifmr->ifm_count == 0) 222140913Sambrisko errx(1, "%s: no media types?", name); 223140913Sambrisko 224140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 225140913Sambrisko if (mwords == NULL) 226140913Sambrisko err(1, "malloc"); 227140913Sambrisko 228140913Sambrisko ifmr->ifm_ulist = mwords; 229140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 230140913Sambrisko err(1, "SIOCGIFMEDIA"); 23125450Speter } 23225450Speter 233140913Sambrisko return ifmr; 234140913Sambrisko} 23525450Speter 236140913Sambriskostatic void 237140913Sambriskosetifmediacallback(int s, void *arg) 238140913Sambrisko{ 239140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 240140913Sambrisko static int did_it = 0; 241140913Sambrisko 242140913Sambrisko if (!did_it) { 243140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 244140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 245140913Sambrisko free(ifmr->ifm_ulist); 246140913Sambrisko free(ifmr); 247140913Sambrisko did_it = 1; 248140913Sambrisko } 249140913Sambrisko} 250140913Sambrisko 251140913Sambriskostatic void 252140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 253140913Sambrisko{ 254140913Sambrisko struct ifmediareq *ifmr; 255140913Sambrisko int subtype; 256140913Sambrisko 257140913Sambrisko 258140913Sambrisko ifmr = getifmediastate(s); 259140913Sambrisko 26025450Speter /* 26125450Speter * We are primarily concerned with the top-level type. 26225450Speter * However, "current" may be only IFM_NONE, so we just look 26325450Speter * for the top-level type in the first "supported type" 26425450Speter * entry. 26525450Speter * 26625450Speter * (I'm assuming that all supported media types for a given 26725450Speter * interface will be the same top-level type..) 26825450Speter */ 269140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 27025450Speter 27125450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 272140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 273140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 27425450Speter 275140913Sambrisko if ((ifr.ifr_media & IFM_TMASK) == 0) { 276140913Sambrisko ifr.ifr_media &= ~IFM_GMASK; 277140913Sambrisko } 278140913Sambrisko 279140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 280140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 28125450Speter} 28225450Speter 283138593Ssamstatic void 28495005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28525450Speter{ 28625450Speter 28725450Speter domediaopt(val, 0, s); 28825450Speter} 28925450Speter 290138593Ssamstatic void 29195005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 29225450Speter{ 29325450Speter 29425450Speter domediaopt(val, 1, s); 29525450Speter} 29625450Speter 29725450Speterstatic void 29895005Simpdomediaopt(const char *val, int clear, int s) 29925450Speter{ 300140913Sambrisko struct ifmediareq *ifmr; 301140913Sambrisko int options; 30225450Speter 303140913Sambrisko ifmr = getifmediastate(s); 30425450Speter 305140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 30625450Speter 30725450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 308140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 30925450Speter if (clear) 31025450Speter ifr.ifr_media &= ~options; 31125450Speter else 31225450Speter ifr.ifr_media |= options; 31325450Speter 314140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 315140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 31625450Speter} 31725450Speter 318114164Ssam 319138593Ssamstatic void 320114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 321114164Ssam{ 322140913Sambrisko struct ifmediareq *ifmr; 323140913Sambrisko int mode; 324114164Ssam 325140913Sambrisko ifmr = getifmediastate(s); 326114164Ssam 327140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 328114164Ssam 329114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 330140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 331114164Ssam 332140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 333140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 334114164Ssam} 335114164Ssam 33625450Speter/********************************************************************** 33725450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 33825450Speter **********************************************************************/ 33925450Speter 34025450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 34125450Speter IFM_TYPE_DESCRIPTIONS; 34225450Speter 34325450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 34425450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 34525450Speter 34625450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 34725450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 34825450Speter 34925450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 35025450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 35125450Speter 35225450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 35325450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 35425450Speter 35525450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 35625450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 35725450Speter 35825450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 35925450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 36025450Speter 36125450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 36225450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 36325450Speter 36425450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 36525450Speter IFM_SUBTYPE_FDDI_ALIASES; 36625450Speter 36725450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 36825450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 36925450Speter 37077217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 37177217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 37277217Sphk 37377217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 37477217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 37577217Sphk 37677217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 37777217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 37877217Sphk 379114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 380114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 381114164Ssam 382116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 383116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 384116820Ssam 385114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 386114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 387114232Sharti 388114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 389114232Sharti IFM_SUBTYPE_ATM_ALIASES; 390114232Sharti 391114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 392114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 393114232Sharti 39425450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 39525450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 39625450Speter 39725450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 39825450Speter IFM_SUBTYPE_SHARED_ALIASES; 39925450Speter 40025450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 40125450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 40225450Speter 40325450Speterstruct ifmedia_type_to_subtype { 40425450Speter struct { 40525450Speter struct ifmedia_description *desc; 40625450Speter int alias; 40725450Speter } subtypes[5]; 40825450Speter struct { 40925450Speter struct ifmedia_description *desc; 41025450Speter int alias; 41125450Speter } options[3]; 412114164Ssam struct { 413114164Ssam struct ifmedia_description *desc; 414114164Ssam int alias; 415116820Ssam } modes[3]; 41625450Speter}; 41725450Speter 41825450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 41925450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 42025450Speter { 42125450Speter { 42225450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 42325450Speter { &ifm_subtype_shared_aliases[0], 1 }, 42425450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 42525450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 42625450Speter { NULL, 0 }, 42725450Speter }, 42825450Speter { 42925450Speter { &ifm_shared_option_descriptions[0], 0 }, 43077217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 43125450Speter { NULL, 0 }, 43225450Speter }, 433114164Ssam { 434114164Ssam { NULL, 0 }, 435114164Ssam }, 43625450Speter }, 43725450Speter { 43825450Speter { 43925450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 44025450Speter { &ifm_subtype_shared_aliases[0], 1 }, 44125450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 44225450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 44325450Speter { NULL, 0 }, 44425450Speter }, 44525450Speter { 44625450Speter { &ifm_shared_option_descriptions[0], 0 }, 44777217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 44825450Speter { NULL, 0 }, 44925450Speter }, 450114164Ssam { 451114164Ssam { NULL, 0 }, 452114164Ssam }, 45325450Speter }, 45425450Speter { 45525450Speter { 45625450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 45725450Speter { &ifm_subtype_shared_aliases[0], 1 }, 45825450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 45925450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 46025450Speter { NULL, 0 }, 46125450Speter }, 46225450Speter { 46325450Speter { &ifm_shared_option_descriptions[0], 0 }, 46477217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 46525450Speter { NULL, 0 }, 46625450Speter }, 467114164Ssam { 468114164Ssam { NULL, 0 }, 469114164Ssam }, 47025450Speter }, 47177217Sphk { 47277217Sphk { 47377217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 47477217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 47577217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 47677217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 47777217Sphk { NULL, 0 }, 47877217Sphk }, 47977217Sphk { 48077217Sphk { &ifm_shared_option_descriptions[0], 0 }, 48177217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 48277217Sphk { NULL, 0 }, 48377217Sphk }, 484114164Ssam { 485114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 486116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 487114164Ssam { NULL, 0 }, 488114164Ssam }, 48977217Sphk }, 490114232Sharti { 491114232Sharti { 492114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 493114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 494114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 495114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 496114232Sharti { NULL, 0 }, 497114232Sharti }, 498114232Sharti { 499114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 500114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 501114232Sharti { NULL, 0 }, 502114232Sharti }, 503114232Sharti { 504114232Sharti { NULL, 0 }, 505114232Sharti }, 506114232Sharti }, 50725450Speter}; 50825450Speter 50925450Speterstatic int 51095005Simpget_media_subtype(int type, const char *val) 51125450Speter{ 51225450Speter struct ifmedia_description *desc; 51325450Speter struct ifmedia_type_to_subtype *ttos; 51425450Speter int rval, i; 51525450Speter 51625450Speter /* Find the top-level interface type. */ 51725450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 51825450Speter desc->ifmt_string != NULL; desc++, ttos++) 51925450Speter if (type == desc->ifmt_word) 52025450Speter break; 52125450Speter if (desc->ifmt_string == NULL) 52225450Speter errx(1, "unknown media type 0x%x", type); 52325450Speter 52425450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 52525450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 52625450Speter if (rval != -1) 52725450Speter return (rval); 52825450Speter } 52925450Speter errx(1, "unknown media subtype: %s", val); 530114164Ssam /*NOTREACHED*/ 53125450Speter} 53225450Speter 53325450Speterstatic int 534114164Ssamget_media_mode(int type, const char *val) 535114164Ssam{ 536114164Ssam struct ifmedia_description *desc; 537114164Ssam struct ifmedia_type_to_subtype *ttos; 538114164Ssam int rval, i; 539114164Ssam 540114164Ssam /* Find the top-level interface type. */ 541114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 542114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 543114164Ssam if (type == desc->ifmt_word) 544114164Ssam break; 545114164Ssam if (desc->ifmt_string == NULL) 546114164Ssam errx(1, "unknown media mode 0x%x", type); 547114164Ssam 548114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 549114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 550114164Ssam if (rval != -1) 551114164Ssam return (rval); 552114164Ssam } 553114164Ssam return -1; 554114164Ssam} 555114164Ssam 556114164Ssamstatic int 55795005Simpget_media_options(int type, const char *val) 55825450Speter{ 55925450Speter struct ifmedia_description *desc; 56025450Speter struct ifmedia_type_to_subtype *ttos; 56125450Speter char *optlist, *optptr; 56225450Speter int option = 0, i, rval = 0; 56325450Speter 56425450Speter /* We muck with the string, so copy it. */ 56525450Speter optlist = strdup(val); 56625450Speter if (optlist == NULL) 56725450Speter err(1, "strdup"); 56825450Speter 56925450Speter /* Find the top-level interface type. */ 57025450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 57125450Speter desc->ifmt_string != NULL; desc++, ttos++) 57225450Speter if (type == desc->ifmt_word) 57325450Speter break; 57425450Speter if (desc->ifmt_string == NULL) 57525450Speter errx(1, "unknown media type 0x%x", type); 57625450Speter 57725450Speter /* 57825450Speter * Look up the options in the user-provided comma-separated 57925450Speter * list. 58025450Speter */ 58125450Speter optptr = optlist; 58225450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 58325450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 58425450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 58525450Speter if (option != -1) 58625450Speter break; 58725450Speter } 58825450Speter if (option == 0) 58925450Speter errx(1, "unknown option: %s", optptr); 59025450Speter rval |= option; 59125450Speter } 59225450Speter 59325450Speter free(optlist); 59425450Speter return (rval); 59525450Speter} 59625450Speter 59725450Speterstatic int 59895005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 59925450Speter{ 60025450Speter 60125450Speter for (; desc->ifmt_string != NULL; desc++) 60225450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 60325450Speter return (desc->ifmt_word); 60425450Speter 60525450Speter return (-1); 60625450Speter} 60725450Speter 60895005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 60925450Speter{ 61025450Speter struct ifmedia_description *desc; 61177385Sphk 61277385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 61377385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 61477385Sphk break; 61577385Sphk 61677385Sphk return desc; 61777385Sphk} 61877385Sphk 61995005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 62077385Sphk{ 62177385Sphk struct ifmedia_description *desc; 62225450Speter struct ifmedia_type_to_subtype *ttos; 62325450Speter 62425450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 62525450Speter desc->ifmt_string != NULL; desc++, ttos++) 62625450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 62725450Speter break; 62877385Sphk 62977385Sphk return ttos; 63077385Sphk} 63177385Sphk 63295005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 63395005Simp struct ifmedia_type_to_subtype *ttos) 63477385Sphk{ 63577385Sphk int i; 63677385Sphk struct ifmedia_description *desc; 63777385Sphk 63877385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 63977385Sphk if (ttos->subtypes[i].alias) 64077385Sphk continue; 64177385Sphk for (desc = ttos->subtypes[i].desc; 64277385Sphk desc->ifmt_string != NULL; desc++) { 64377385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 64477385Sphk return desc; 64577385Sphk } 64677385Sphk } 64777385Sphk 64877385Sphk return NULL; 64977385Sphk} 65077385Sphk 651114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 652114164Ssam struct ifmedia_type_to_subtype *ttos) 653114164Ssam{ 654114164Ssam int i; 655114164Ssam struct ifmedia_description *desc; 656114164Ssam 657114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 658114164Ssam if (ttos->modes[i].alias) 659114164Ssam continue; 660114164Ssam for (desc = ttos->modes[i].desc; 661114164Ssam desc->ifmt_string != NULL; desc++) { 662114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 663114164Ssam return desc; 664114164Ssam } 665114164Ssam } 666114164Ssam 667114164Ssam return NULL; 668114164Ssam} 669114164Ssam 67077385Sphkstatic void 67195005Simpprint_media_word(int ifmw, int print_toptype) 67277385Sphk{ 67377385Sphk struct ifmedia_description *desc; 67477385Sphk struct ifmedia_type_to_subtype *ttos; 67577385Sphk int seen_option = 0, i; 67677385Sphk 67777385Sphk /* Find the top-level interface type. */ 67877385Sphk desc = get_toptype_desc(ifmw); 67977385Sphk ttos = get_toptype_ttos(ifmw); 68025450Speter if (desc->ifmt_string == NULL) { 68125450Speter printf("<unknown type>"); 68225450Speter return; 68377385Sphk } else if (print_toptype) { 68477385Sphk printf("%s", desc->ifmt_string); 68525450Speter } 68625450Speter 68725450Speter /* 68825450Speter * Don't print the top-level type; it's not like we can 68925450Speter * change it, or anything. 69025450Speter */ 69125450Speter 69225450Speter /* Find subtype. */ 69377385Sphk desc = get_subtype_desc(ifmw, ttos); 69477385Sphk if (desc != NULL) 69577385Sphk goto got_subtype; 69625450Speter 69725450Speter /* Falling to here means unknown subtype. */ 69825450Speter printf("<unknown subtype>"); 69925450Speter return; 70025450Speter 70125450Speter got_subtype: 70277385Sphk if (print_toptype) 70377385Sphk putchar(' '); 70477385Sphk 70525450Speter printf("%s", desc->ifmt_string); 70625450Speter 707114164Ssam if (print_toptype) { 708114164Ssam desc = get_mode_desc(ifmw, ttos); 709116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 710114164Ssam printf(" mode %s", desc->ifmt_string); 711114164Ssam } 712114164Ssam 71325450Speter /* Find options. */ 71425450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 71525450Speter if (ttos->options[i].alias) 71625450Speter continue; 71725450Speter for (desc = ttos->options[i].desc; 71825450Speter desc->ifmt_string != NULL; desc++) { 71925450Speter if (ifmw & desc->ifmt_word) { 72025450Speter if (seen_option == 0) 72125450Speter printf(" <"); 72225450Speter printf("%s%s", seen_option++ ? "," : "", 72325450Speter desc->ifmt_string); 72425450Speter } 72525450Speter } 72625450Speter } 72725450Speter printf("%s", seen_option ? ">" : ""); 72825450Speter} 72925450Speter 73077385Sphkstatic void 73195005Simpprint_media_word_ifconfig(int ifmw) 73277385Sphk{ 73377385Sphk struct ifmedia_description *desc; 73477385Sphk struct ifmedia_type_to_subtype *ttos; 73577385Sphk int i; 73677385Sphk 73777385Sphk /* Find the top-level interface type. */ 73877385Sphk desc = get_toptype_desc(ifmw); 73977385Sphk ttos = get_toptype_ttos(ifmw); 74077385Sphk if (desc->ifmt_string == NULL) { 74177385Sphk printf("<unknown type>"); 74277385Sphk return; 74377385Sphk } 74477385Sphk 74577385Sphk /* 74677385Sphk * Don't print the top-level type; it's not like we can 74777385Sphk * change it, or anything. 74877385Sphk */ 74977385Sphk 75077385Sphk /* Find subtype. */ 75177385Sphk desc = get_subtype_desc(ifmw, ttos); 75277385Sphk if (desc != NULL) 75377385Sphk goto got_subtype; 75477385Sphk 75577385Sphk /* Falling to here means unknown subtype. */ 75677385Sphk printf("<unknown subtype>"); 75777385Sphk return; 75877385Sphk 75977385Sphk got_subtype: 76077385Sphk printf("media %s", desc->ifmt_string); 76177385Sphk 762114164Ssam desc = get_mode_desc(ifmw, ttos); 763114164Ssam if (desc != NULL) 764114164Ssam printf(" mode %s", desc->ifmt_string); 765114164Ssam 76677385Sphk /* Find options. */ 76777385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 76877385Sphk if (ttos->options[i].alias) 76977385Sphk continue; 77077385Sphk for (desc = ttos->options[i].desc; 77177385Sphk desc->ifmt_string != NULL; desc++) { 77277385Sphk if (ifmw & desc->ifmt_word) { 77377385Sphk printf(" mediaopt %s", desc->ifmt_string); 77477385Sphk } 77577385Sphk } 77677385Sphk } 77777385Sphk} 77877385Sphk 77925450Speter/********************************************************************** 78025450Speter * ...until here. 78125450Speter **********************************************************************/ 782138593Ssam 783138593Ssamstatic struct cmd media_cmds[] = { 784138593Ssam DEF_CMD_ARG("media", setmedia), 785138593Ssam DEF_CMD_ARG("mode", setmediamode), 786138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 787138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 788138593Ssam}; 789138593Ssamstatic struct afswtch af_media = { 790138593Ssam .af_name = "af_media", 791138593Ssam .af_af = AF_UNSPEC, 792139494Ssam .af_other_status = media_status, 793138593Ssam}; 794138593Ssam 795138593Ssamstatic __constructor void 796138593Ssamifmedia_ctor(void) 797138593Ssam{ 798138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 799138593Ssam int i; 800138593Ssam 801138593Ssam for (i = 0; i < N(media_cmds); i++) 802138593Ssam cmd_register(&media_cmds[i]); 803138593Ssam af_register(&af_media); 804138593Ssam#undef N 805138593Ssam} 806