ifmedia.c revision 217013
125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 217013 2011-01-05 15:28:30Z marius $ */ 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 * 4. Neither the name of the University nor the names of its contributors 4925450Speter * may be used to endorse or promote products derived from this software 5025450Speter * without specific prior written permission. 5125450Speter * 5225450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5325450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5425450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5525450Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5625450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5725450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5825450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5925450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6025450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6125450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6225450Speter * SUCH DAMAGE. 6325450Speter */ 6425450Speter 6525450Speter#include <sys/param.h> 6625450Speter#include <sys/ioctl.h> 6725450Speter#include <sys/socket.h> 6825450Speter#include <sys/sysctl.h> 6925450Speter#include <sys/time.h> 7025450Speter 7125450Speter#include <net/if.h> 7225450Speter#include <net/if_dl.h> 7325450Speter#include <net/if_types.h> 7425450Speter#include <net/if_media.h> 7525450Speter#include <net/route.h> 7625450Speter 7725450Speter#include <ctype.h> 7825450Speter#include <err.h> 7925450Speter#include <errno.h> 8025450Speter#include <fcntl.h> 8125450Speter#include <stdio.h> 8225450Speter#include <stdlib.h> 8325450Speter#include <string.h> 8425450Speter#include <unistd.h> 8525450Speter 8625450Speter#include "ifconfig.h" 8725450Speter 8895005Simpstatic void domediaopt(const char *, int, int); 8995005Simpstatic int get_media_subtype(int, const char *); 90114164Ssamstatic int get_media_mode(int, const char *); 9195005Simpstatic int get_media_options(int, const char *); 9295005Simpstatic int lookup_media_word(struct ifmedia_description *, const char *); 9395005Simpstatic void print_media_word(int, int); 9495005Simpstatic void print_media_word_ifconfig(int); 9525450Speter 9695005Simpstatic struct ifmedia_description *get_toptype_desc(int); 9795005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 9895005Simpstatic struct ifmedia_description *get_subtype_desc(int, 9995005Simp struct ifmedia_type_to_subtype *ttos); 10077385Sphk 101178354Ssam#define IFM_OPMODE(x) \ 102178354Ssam ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 103195618Srpaulo IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 104195618Srpaulo IFM_IEEE80211_MBSS)) 105178354Ssam#define IFM_IEEE80211_STA 0 106178354Ssam 107138593Ssamstatic void 108139494Ssammedia_status(int s) 10925450Speter{ 11025450Speter struct ifmediareq ifmr; 11125450Speter int *media_list, i; 11225450Speter 11325450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11425450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11525450Speter 11625450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 11725450Speter /* 11825450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 11925450Speter */ 12025450Speter return; 12125450Speter } 12225450Speter 12325450Speter if (ifmr.ifm_count == 0) { 12425450Speter warnx("%s: no media types?", name); 12525450Speter return; 12625450Speter } 12725450Speter 12825450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 12925450Speter if (media_list == NULL) 13025450Speter err(1, "malloc"); 13125450Speter ifmr.ifm_ulist = media_list; 13225450Speter 13325450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13425450Speter err(1, "SIOCGIFMEDIA"); 13525450Speter 13625450Speter printf("\tmedia: "); 13777385Sphk print_media_word(ifmr.ifm_current, 1); 13825450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 13925450Speter putchar(' '); 14025450Speter putchar('('); 14177385Sphk print_media_word(ifmr.ifm_active, 0); 14225450Speter putchar(')'); 14325450Speter } 14425450Speter 14577385Sphk putchar('\n'); 14677385Sphk 14725450Speter if (ifmr.ifm_status & IFM_AVALID) { 14877385Sphk printf("\tstatus: "); 14925450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 15025450Speter case IFM_ETHER: 151161536Sthomas case IFM_ATM: 15225450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15325450Speter printf("active"); 15425450Speter else 15525450Speter printf("no carrier"); 15625450Speter break; 15725450Speter 15825450Speter case IFM_FDDI: 15925450Speter case IFM_TOKEN: 16025450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16125450Speter printf("inserted"); 16225450Speter else 16325450Speter printf("no ring"); 16425450Speter break; 165114232Sharti 16677217Sphk case IFM_IEEE80211: 167178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 168178354Ssam /* NB: only sta mode associates */ 169178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 170178354Ssam printf("associated"); 171178354Ssam else 172178354Ssam printf("running"); 173178354Ssam } else 17477217Sphk printf("no carrier"); 17577217Sphk break; 17625450Speter } 17785853Syar putchar('\n'); 17825450Speter } 17925450Speter 18077385Sphk if (ifmr.ifm_count > 0 && supmedia) { 18177385Sphk printf("\tsupported media:\n"); 18225450Speter for (i = 0; i < ifmr.ifm_count; i++) { 18377385Sphk printf("\t\t"); 18477385Sphk print_media_word_ifconfig(media_list[i]); 18577385Sphk putchar('\n'); 18625450Speter } 18725450Speter } 18825450Speter 18925450Speter free(media_list); 19025450Speter} 19125450Speter 192170531Ssamstruct ifmediareq * 193170531Ssamifmedia_getstate(int s) 19425450Speter{ 195140913Sambrisko static struct ifmediareq *ifmr = NULL; 196140913Sambrisko int *mwords; 19725450Speter 198140913Sambrisko if (ifmr == NULL) { 199140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 200140913Sambrisko if (ifmr == NULL) 201140913Sambrisko err(1, "malloc"); 20225450Speter 203140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 204140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 205140913Sambrisko sizeof(ifmr->ifm_name)); 206140913Sambrisko 207140913Sambrisko ifmr->ifm_count = 0; 208140913Sambrisko ifmr->ifm_ulist = NULL; 209140913Sambrisko 21025450Speter /* 211140913Sambrisko * We must go through the motions of reading all 212140913Sambrisko * supported media because we need to know both 213140913Sambrisko * the current media type and the top-level type. 21425450Speter */ 215140913Sambrisko 216140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 21725450Speter err(1, "SIOCGIFMEDIA"); 218140913Sambrisko } 219140913Sambrisko 220140913Sambrisko if (ifmr->ifm_count == 0) 221140913Sambrisko errx(1, "%s: no media types?", name); 222140913Sambrisko 223140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 224140913Sambrisko if (mwords == NULL) 225140913Sambrisko err(1, "malloc"); 226140913Sambrisko 227140913Sambrisko ifmr->ifm_ulist = mwords; 228140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 229140913Sambrisko err(1, "SIOCGIFMEDIA"); 23025450Speter } 23125450Speter 232140913Sambrisko return ifmr; 233140913Sambrisko} 23425450Speter 235140913Sambriskostatic void 236140913Sambriskosetifmediacallback(int s, void *arg) 237140913Sambrisko{ 238140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 239140913Sambrisko static int did_it = 0; 240140913Sambrisko 241140913Sambrisko if (!did_it) { 242154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 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 257170531Ssam ifmr = ifmedia_getstate(s); 258140913Sambrisko 25925450Speter /* 26025450Speter * We are primarily concerned with the top-level type. 26125450Speter * However, "current" may be only IFM_NONE, so we just look 26225450Speter * for the top-level type in the first "supported type" 26325450Speter * entry. 26425450Speter * 26525450Speter * (I'm assuming that all supported media types for a given 26625450Speter * interface will be the same top-level type..) 26725450Speter */ 268140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 26925450Speter 27025450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 271140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 272140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 27325450Speter 274140913Sambrisko if ((ifr.ifr_media & IFM_TMASK) == 0) { 275215272Smarius ifr.ifr_media &= ~(IFM_GMASK | IFM_OMASK); 276140913Sambrisko } 277140913Sambrisko 278140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 279140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 28025450Speter} 28125450Speter 282138593Ssamstatic void 28395005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28425450Speter{ 28525450Speter 28625450Speter domediaopt(val, 0, s); 28725450Speter} 28825450Speter 289138593Ssamstatic void 29095005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 29125450Speter{ 29225450Speter 29325450Speter domediaopt(val, 1, s); 29425450Speter} 29525450Speter 29625450Speterstatic void 29795005Simpdomediaopt(const char *val, int clear, int s) 29825450Speter{ 299140913Sambrisko struct ifmediareq *ifmr; 300140913Sambrisko int options; 30125450Speter 302170531Ssam ifmr = ifmedia_getstate(s); 30325450Speter 304140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 30525450Speter 30625450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 307140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 30825450Speter if (clear) 30925450Speter ifr.ifr_media &= ~options; 310165359Sjkim else { 311165359Sjkim if (options & IFM_HDX) { 312165359Sjkim ifr.ifr_media &= ~IFM_FDX; 313165359Sjkim options &= ~IFM_HDX; 314165359Sjkim } 31525450Speter ifr.ifr_media |= options; 316165359Sjkim } 317140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 318140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 31925450Speter} 32025450Speter 321166113Smariusstatic void 322166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 323166113Smarius{ 324166113Smarius struct ifmediareq *ifmr; 325166113Smarius int inst; 326114164Ssam 327170531Ssam ifmr = ifmedia_getstate(s); 328166113Smarius 329166113Smarius inst = atoi(val); 330194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 331166113Smarius errx(1, "invalid media instance: %s", val); 332166113Smarius 333166113Smarius strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 334166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 335166113Smarius 336166113Smarius ifmr->ifm_current = ifr.ifr_media; 337166113Smarius callback_register(setifmediacallback, (void *)ifmr); 338166113Smarius} 339166113Smarius 340138593Ssamstatic void 341114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 342114164Ssam{ 343140913Sambrisko struct ifmediareq *ifmr; 344140913Sambrisko int mode; 345114164Ssam 346170531Ssam ifmr = ifmedia_getstate(s); 347114164Ssam 348140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 349114164Ssam 350114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 351140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 352114164Ssam 353140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 354140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 355114164Ssam} 356114164Ssam 35725450Speter/********************************************************************** 35825450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 35925450Speter **********************************************************************/ 36025450Speter 36125450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 36225450Speter IFM_TYPE_DESCRIPTIONS; 36325450Speter 36425450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 36525450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 36625450Speter 36725450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 36825450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 36925450Speter 37025450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 37125450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 37225450Speter 37325450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 37425450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 37525450Speter 37625450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 37725450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 37825450Speter 37925450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 38025450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 38125450Speter 38225450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 38325450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 38425450Speter 38525450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 38625450Speter IFM_SUBTYPE_FDDI_ALIASES; 38725450Speter 38825450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 38925450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 39025450Speter 39177217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 39277217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 39377217Sphk 39477217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 39577217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 39677217Sphk 39777217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 39877217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 39977217Sphk 400114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 401114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 402114164Ssam 403116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 404116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 405116820Ssam 406114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 407114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 408114232Sharti 409114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 410114232Sharti IFM_SUBTYPE_ATM_ALIASES; 411114232Sharti 412114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 413114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 414114232Sharti 41525450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 41625450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 41725450Speter 41825450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 41925450Speter IFM_SUBTYPE_SHARED_ALIASES; 42025450Speter 42125450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 42225450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 42325450Speter 424217013Smariusstatic struct ifmedia_description ifm_shared_option_aliases[] = 425217013Smarius IFM_SHARED_OPTION_ALIASES; 426217013Smarius 42725450Speterstruct ifmedia_type_to_subtype { 42825450Speter struct { 42925450Speter struct ifmedia_description *desc; 43025450Speter int alias; 43125450Speter } subtypes[5]; 43225450Speter struct { 43325450Speter struct ifmedia_description *desc; 43425450Speter int alias; 435217013Smarius } options[4]; 436114164Ssam struct { 437114164Ssam struct ifmedia_description *desc; 438114164Ssam int alias; 439116820Ssam } modes[3]; 44025450Speter}; 44125450Speter 44225450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 44325450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 44425450Speter { 44525450Speter { 44625450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 44725450Speter { &ifm_subtype_shared_aliases[0], 1 }, 44825450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 44925450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 45025450Speter { NULL, 0 }, 45125450Speter }, 45225450Speter { 45325450Speter { &ifm_shared_option_descriptions[0], 0 }, 454217013Smarius { &ifm_shared_option_aliases[0], 1 }, 45577217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 45625450Speter { NULL, 0 }, 45725450Speter }, 458114164Ssam { 459114164Ssam { NULL, 0 }, 460114164Ssam }, 46125450Speter }, 46225450Speter { 46325450Speter { 46425450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 46525450Speter { &ifm_subtype_shared_aliases[0], 1 }, 46625450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 46725450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 46825450Speter { NULL, 0 }, 46925450Speter }, 47025450Speter { 47125450Speter { &ifm_shared_option_descriptions[0], 0 }, 472217013Smarius { &ifm_shared_option_aliases[0], 1 }, 47377217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 47425450Speter { NULL, 0 }, 47525450Speter }, 476114164Ssam { 477114164Ssam { NULL, 0 }, 478114164Ssam }, 47925450Speter }, 48025450Speter { 48125450Speter { 48225450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 48325450Speter { &ifm_subtype_shared_aliases[0], 1 }, 48425450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 48525450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 48625450Speter { NULL, 0 }, 48725450Speter }, 48825450Speter { 48925450Speter { &ifm_shared_option_descriptions[0], 0 }, 490217013Smarius { &ifm_shared_option_aliases[0], 1 }, 49177217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 49225450Speter { NULL, 0 }, 49325450Speter }, 494114164Ssam { 495114164Ssam { NULL, 0 }, 496114164Ssam }, 49725450Speter }, 49877217Sphk { 49977217Sphk { 50077217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 50177217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 50277217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 50377217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 50477217Sphk { NULL, 0 }, 50577217Sphk }, 50677217Sphk { 50777217Sphk { &ifm_shared_option_descriptions[0], 0 }, 508217013Smarius { &ifm_shared_option_aliases[0], 1 }, 50977217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 51077217Sphk { NULL, 0 }, 51177217Sphk }, 512114164Ssam { 513114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 514116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 515114164Ssam { NULL, 0 }, 516114164Ssam }, 51777217Sphk }, 518114232Sharti { 519114232Sharti { 520114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 521114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 522114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 523114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 524114232Sharti { NULL, 0 }, 525114232Sharti }, 526114232Sharti { 527114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 528217013Smarius { &ifm_shared_option_aliases[0], 1 }, 529114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 530114232Sharti { NULL, 0 }, 531114232Sharti }, 532114232Sharti { 533114232Sharti { NULL, 0 }, 534114232Sharti }, 535114232Sharti }, 53625450Speter}; 53725450Speter 53825450Speterstatic int 53995005Simpget_media_subtype(int type, const char *val) 54025450Speter{ 54125450Speter struct ifmedia_description *desc; 54225450Speter struct ifmedia_type_to_subtype *ttos; 54325450Speter int rval, i; 54425450Speter 54525450Speter /* Find the top-level interface type. */ 54625450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 54725450Speter desc->ifmt_string != NULL; desc++, ttos++) 54825450Speter if (type == desc->ifmt_word) 54925450Speter break; 55025450Speter if (desc->ifmt_string == NULL) 55125450Speter errx(1, "unknown media type 0x%x", type); 55225450Speter 55325450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 55425450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 55525450Speter if (rval != -1) 55625450Speter return (rval); 55725450Speter } 55825450Speter errx(1, "unknown media subtype: %s", val); 559114164Ssam /*NOTREACHED*/ 56025450Speter} 56125450Speter 56225450Speterstatic int 563114164Ssamget_media_mode(int type, const char *val) 564114164Ssam{ 565114164Ssam struct ifmedia_description *desc; 566114164Ssam struct ifmedia_type_to_subtype *ttos; 567114164Ssam int rval, i; 568114164Ssam 569114164Ssam /* Find the top-level interface type. */ 570114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 571114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 572114164Ssam if (type == desc->ifmt_word) 573114164Ssam break; 574114164Ssam if (desc->ifmt_string == NULL) 575114164Ssam errx(1, "unknown media mode 0x%x", type); 576114164Ssam 577114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 578114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 579114164Ssam if (rval != -1) 580114164Ssam return (rval); 581114164Ssam } 582114164Ssam return -1; 583114164Ssam} 584114164Ssam 585114164Ssamstatic int 58695005Simpget_media_options(int type, const char *val) 58725450Speter{ 58825450Speter struct ifmedia_description *desc; 58925450Speter struct ifmedia_type_to_subtype *ttos; 59025450Speter char *optlist, *optptr; 59125450Speter int option = 0, i, rval = 0; 59225450Speter 59325450Speter /* We muck with the string, so copy it. */ 59425450Speter optlist = strdup(val); 59525450Speter if (optlist == NULL) 59625450Speter err(1, "strdup"); 59725450Speter 59825450Speter /* Find the top-level interface type. */ 59925450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 60025450Speter desc->ifmt_string != NULL; desc++, ttos++) 60125450Speter if (type == desc->ifmt_word) 60225450Speter break; 60325450Speter if (desc->ifmt_string == NULL) 60425450Speter errx(1, "unknown media type 0x%x", type); 60525450Speter 60625450Speter /* 60725450Speter * Look up the options in the user-provided comma-separated 60825450Speter * list. 60925450Speter */ 61025450Speter optptr = optlist; 61125450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 61225450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 61325450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 61425450Speter if (option != -1) 61525450Speter break; 61625450Speter } 61725450Speter if (option == 0) 61825450Speter errx(1, "unknown option: %s", optptr); 61925450Speter rval |= option; 62025450Speter } 62125450Speter 62225450Speter free(optlist); 62325450Speter return (rval); 62425450Speter} 62525450Speter 62625450Speterstatic int 62795005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 62825450Speter{ 62925450Speter 63025450Speter for (; desc->ifmt_string != NULL; desc++) 63125450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 63225450Speter return (desc->ifmt_word); 63325450Speter 63425450Speter return (-1); 63525450Speter} 63625450Speter 63795005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 63825450Speter{ 63925450Speter struct ifmedia_description *desc; 64077385Sphk 64177385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 64277385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 64377385Sphk break; 64477385Sphk 64577385Sphk return desc; 64677385Sphk} 64777385Sphk 64895005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 64977385Sphk{ 65077385Sphk struct ifmedia_description *desc; 65125450Speter struct ifmedia_type_to_subtype *ttos; 65225450Speter 65325450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 65425450Speter desc->ifmt_string != NULL; desc++, ttos++) 65525450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 65625450Speter break; 65777385Sphk 65877385Sphk return ttos; 65977385Sphk} 66077385Sphk 66195005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 66295005Simp struct ifmedia_type_to_subtype *ttos) 66377385Sphk{ 66477385Sphk int i; 66577385Sphk struct ifmedia_description *desc; 66677385Sphk 66777385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 66877385Sphk if (ttos->subtypes[i].alias) 66977385Sphk continue; 67077385Sphk for (desc = ttos->subtypes[i].desc; 67177385Sphk desc->ifmt_string != NULL; desc++) { 67277385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 67377385Sphk return desc; 67477385Sphk } 67577385Sphk } 67677385Sphk 67777385Sphk return NULL; 67877385Sphk} 67977385Sphk 680114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 681114164Ssam struct ifmedia_type_to_subtype *ttos) 682114164Ssam{ 683114164Ssam int i; 684114164Ssam struct ifmedia_description *desc; 685114164Ssam 686114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 687114164Ssam if (ttos->modes[i].alias) 688114164Ssam continue; 689114164Ssam for (desc = ttos->modes[i].desc; 690114164Ssam desc->ifmt_string != NULL; desc++) { 691114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 692114164Ssam return desc; 693114164Ssam } 694114164Ssam } 695114164Ssam 696114164Ssam return NULL; 697114164Ssam} 698114164Ssam 69977385Sphkstatic void 70095005Simpprint_media_word(int ifmw, int print_toptype) 70177385Sphk{ 70277385Sphk struct ifmedia_description *desc; 70377385Sphk struct ifmedia_type_to_subtype *ttos; 70477385Sphk int seen_option = 0, i; 70577385Sphk 70677385Sphk /* Find the top-level interface type. */ 70777385Sphk desc = get_toptype_desc(ifmw); 70877385Sphk ttos = get_toptype_ttos(ifmw); 70925450Speter if (desc->ifmt_string == NULL) { 71025450Speter printf("<unknown type>"); 71125450Speter return; 71277385Sphk } else if (print_toptype) { 71377385Sphk printf("%s", desc->ifmt_string); 71425450Speter } 71525450Speter 71625450Speter /* 71725450Speter * Don't print the top-level type; it's not like we can 71825450Speter * change it, or anything. 71925450Speter */ 72025450Speter 72125450Speter /* Find subtype. */ 72277385Sphk desc = get_subtype_desc(ifmw, ttos); 723161536Sthomas if (desc == NULL) { 724161536Sthomas printf("<unknown subtype>"); 725161536Sthomas return; 726161536Sthomas } 72725450Speter 72877385Sphk if (print_toptype) 72977385Sphk putchar(' '); 73077385Sphk 73125450Speter printf("%s", desc->ifmt_string); 73225450Speter 733114164Ssam if (print_toptype) { 734114164Ssam desc = get_mode_desc(ifmw, ttos); 735116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 736114164Ssam printf(" mode %s", desc->ifmt_string); 737114164Ssam } 738114164Ssam 73925450Speter /* Find options. */ 74025450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 74125450Speter if (ttos->options[i].alias) 74225450Speter continue; 74325450Speter for (desc = ttos->options[i].desc; 74425450Speter desc->ifmt_string != NULL; desc++) { 74525450Speter if (ifmw & desc->ifmt_word) { 74625450Speter if (seen_option == 0) 74725450Speter printf(" <"); 74825450Speter printf("%s%s", seen_option++ ? "," : "", 74925450Speter desc->ifmt_string); 75025450Speter } 75125450Speter } 75225450Speter } 75325450Speter printf("%s", seen_option ? ">" : ""); 754166113Smarius 755166169Smarius if (print_toptype && IFM_INST(ifmw) != 0) 756166113Smarius printf(" instance %d", IFM_INST(ifmw)); 75725450Speter} 75825450Speter 75977385Sphkstatic void 76095005Simpprint_media_word_ifconfig(int ifmw) 76177385Sphk{ 76277385Sphk struct ifmedia_description *desc; 76377385Sphk struct ifmedia_type_to_subtype *ttos; 764215259Smarius int seen_option = 0, i; 76577385Sphk 76677385Sphk /* Find the top-level interface type. */ 76777385Sphk desc = get_toptype_desc(ifmw); 76877385Sphk ttos = get_toptype_ttos(ifmw); 76977385Sphk if (desc->ifmt_string == NULL) { 77077385Sphk printf("<unknown type>"); 77177385Sphk return; 77277385Sphk } 77377385Sphk 77477385Sphk /* 77577385Sphk * Don't print the top-level type; it's not like we can 77677385Sphk * change it, or anything. 77777385Sphk */ 77877385Sphk 77977385Sphk /* Find subtype. */ 78077385Sphk desc = get_subtype_desc(ifmw, ttos); 781161536Sthomas if (desc == NULL) { 782161536Sthomas printf("<unknown subtype>"); 783161536Sthomas return; 784161536Sthomas } 78577385Sphk 78677385Sphk printf("media %s", desc->ifmt_string); 78777385Sphk 788114164Ssam desc = get_mode_desc(ifmw, ttos); 789114164Ssam if (desc != NULL) 790114164Ssam printf(" mode %s", desc->ifmt_string); 791114164Ssam 79277385Sphk /* Find options. */ 79377385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 79477385Sphk if (ttos->options[i].alias) 79577385Sphk continue; 79677385Sphk for (desc = ttos->options[i].desc; 79777385Sphk desc->ifmt_string != NULL; desc++) { 79877385Sphk if (ifmw & desc->ifmt_word) { 799215259Smarius if (seen_option == 0) 800215259Smarius printf(" mediaopt "); 801215259Smarius printf("%s%s", seen_option++ ? "," : "", 802215259Smarius desc->ifmt_string); 80377385Sphk } 80477385Sphk } 80577385Sphk } 806166113Smarius 807166169Smarius if (IFM_INST(ifmw) != 0) 808166169Smarius printf(" instance %d", IFM_INST(ifmw)); 80977385Sphk} 81077385Sphk 81125450Speter/********************************************************************** 81225450Speter * ...until here. 81325450Speter **********************************************************************/ 814138593Ssam 815138593Ssamstatic struct cmd media_cmds[] = { 816138593Ssam DEF_CMD_ARG("media", setmedia), 817138593Ssam DEF_CMD_ARG("mode", setmediamode), 818138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 819138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 820166113Smarius DEF_CMD_ARG("inst", setmediainst), 821166113Smarius DEF_CMD_ARG("instance", setmediainst), 822138593Ssam}; 823138593Ssamstatic struct afswtch af_media = { 824138593Ssam .af_name = "af_media", 825138593Ssam .af_af = AF_UNSPEC, 826139494Ssam .af_other_status = media_status, 827138593Ssam}; 828138593Ssam 829138593Ssamstatic __constructor void 830138593Ssamifmedia_ctor(void) 831138593Ssam{ 832138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 833194799Sdelphij size_t i; 834138593Ssam 835138593Ssam for (i = 0; i < N(media_cmds); i++) 836138593Ssam cmd_register(&media_cmds[i]); 837138593Ssam af_register(&af_media); 838138593Ssam#undef N 839138593Ssam} 840