ifmedia.c revision 194799
125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 194799 2009-06-23 23:49:52Z delphij $ */ 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 105178354Ssam#define IFM_OPMODE(x) \ 106178354Ssam ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 107178354Ssam IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR)) 108178354Ssam#define IFM_IEEE80211_STA 0 109178354Ssam 110138593Ssamstatic void 111139494Ssammedia_status(int s) 11225450Speter{ 11325450Speter struct ifmediareq ifmr; 11425450Speter int *media_list, i; 11525450Speter 11625450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11725450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11825450Speter 11925450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 12025450Speter /* 12125450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 12225450Speter */ 12325450Speter return; 12425450Speter } 12525450Speter 12625450Speter if (ifmr.ifm_count == 0) { 12725450Speter warnx("%s: no media types?", name); 12825450Speter return; 12925450Speter } 13025450Speter 13125450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 13225450Speter if (media_list == NULL) 13325450Speter err(1, "malloc"); 13425450Speter ifmr.ifm_ulist = media_list; 13525450Speter 13625450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13725450Speter err(1, "SIOCGIFMEDIA"); 13825450Speter 13925450Speter printf("\tmedia: "); 14077385Sphk print_media_word(ifmr.ifm_current, 1); 14125450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 14225450Speter putchar(' '); 14325450Speter putchar('('); 14477385Sphk print_media_word(ifmr.ifm_active, 0); 14525450Speter putchar(')'); 14625450Speter } 14725450Speter 14877385Sphk putchar('\n'); 14977385Sphk 15025450Speter if (ifmr.ifm_status & IFM_AVALID) { 15177385Sphk printf("\tstatus: "); 15225450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 15325450Speter case IFM_ETHER: 154161536Sthomas case IFM_ATM: 15525450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15625450Speter printf("active"); 15725450Speter else 15825450Speter printf("no carrier"); 15925450Speter break; 16025450Speter 16125450Speter case IFM_FDDI: 16225450Speter case IFM_TOKEN: 16325450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16425450Speter printf("inserted"); 16525450Speter else 16625450Speter printf("no ring"); 16725450Speter break; 168114232Sharti 16977217Sphk case IFM_IEEE80211: 170178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 171178354Ssam /* NB: only sta mode associates */ 172178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 173178354Ssam printf("associated"); 174178354Ssam else 175178354Ssam printf("running"); 176178354Ssam } else 17777217Sphk printf("no carrier"); 17877217Sphk break; 17925450Speter } 18085853Syar putchar('\n'); 18125450Speter } 18225450Speter 18377385Sphk if (ifmr.ifm_count > 0 && supmedia) { 18477385Sphk printf("\tsupported media:\n"); 18525450Speter for (i = 0; i < ifmr.ifm_count; i++) { 18677385Sphk printf("\t\t"); 18777385Sphk print_media_word_ifconfig(media_list[i]); 18877385Sphk putchar('\n'); 18925450Speter } 19025450Speter } 19125450Speter 19225450Speter free(media_list); 19325450Speter} 19425450Speter 195170531Ssamstruct ifmediareq * 196170531Ssamifmedia_getstate(int s) 19725450Speter{ 198140913Sambrisko static struct ifmediareq *ifmr = NULL; 199140913Sambrisko int *mwords; 20025450Speter 201140913Sambrisko if (ifmr == NULL) { 202140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 203140913Sambrisko if (ifmr == NULL) 204140913Sambrisko err(1, "malloc"); 20525450Speter 206140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 207140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 208140913Sambrisko sizeof(ifmr->ifm_name)); 209140913Sambrisko 210140913Sambrisko ifmr->ifm_count = 0; 211140913Sambrisko ifmr->ifm_ulist = NULL; 212140913Sambrisko 21325450Speter /* 214140913Sambrisko * We must go through the motions of reading all 215140913Sambrisko * supported media because we need to know both 216140913Sambrisko * the current media type and the top-level type. 21725450Speter */ 218140913Sambrisko 219140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 22025450Speter err(1, "SIOCGIFMEDIA"); 221140913Sambrisko } 222140913Sambrisko 223140913Sambrisko if (ifmr->ifm_count == 0) 224140913Sambrisko errx(1, "%s: no media types?", name); 225140913Sambrisko 226140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 227140913Sambrisko if (mwords == NULL) 228140913Sambrisko err(1, "malloc"); 229140913Sambrisko 230140913Sambrisko ifmr->ifm_ulist = mwords; 231140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 232140913Sambrisko err(1, "SIOCGIFMEDIA"); 23325450Speter } 23425450Speter 235140913Sambrisko return ifmr; 236140913Sambrisko} 23725450Speter 238140913Sambriskostatic void 239140913Sambriskosetifmediacallback(int s, void *arg) 240140913Sambrisko{ 241140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 242140913Sambrisko static int did_it = 0; 243140913Sambrisko 244140913Sambrisko if (!did_it) { 245154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 246140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 247140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 248140913Sambrisko free(ifmr->ifm_ulist); 249140913Sambrisko free(ifmr); 250140913Sambrisko did_it = 1; 251140913Sambrisko } 252140913Sambrisko} 253140913Sambrisko 254140913Sambriskostatic void 255140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 256140913Sambrisko{ 257140913Sambrisko struct ifmediareq *ifmr; 258140913Sambrisko int subtype; 259140913Sambrisko 260170531Ssam ifmr = ifmedia_getstate(s); 261140913Sambrisko 26225450Speter /* 26325450Speter * We are primarily concerned with the top-level type. 26425450Speter * However, "current" may be only IFM_NONE, so we just look 26525450Speter * for the top-level type in the first "supported type" 26625450Speter * entry. 26725450Speter * 26825450Speter * (I'm assuming that all supported media types for a given 26925450Speter * interface will be the same top-level type..) 27025450Speter */ 271140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 27225450Speter 27325450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 274140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 275140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 27625450Speter 277140913Sambrisko if ((ifr.ifr_media & IFM_TMASK) == 0) { 278140913Sambrisko ifr.ifr_media &= ~IFM_GMASK; 279140913Sambrisko } 280140913Sambrisko 281140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 282140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 28325450Speter} 28425450Speter 285138593Ssamstatic void 28695005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28725450Speter{ 28825450Speter 28925450Speter domediaopt(val, 0, s); 29025450Speter} 29125450Speter 292138593Ssamstatic void 29395005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 29425450Speter{ 29525450Speter 29625450Speter domediaopt(val, 1, s); 29725450Speter} 29825450Speter 29925450Speterstatic void 30095005Simpdomediaopt(const char *val, int clear, int s) 30125450Speter{ 302140913Sambrisko struct ifmediareq *ifmr; 303140913Sambrisko int options; 30425450Speter 305170531Ssam ifmr = ifmedia_getstate(s); 30625450Speter 307140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 30825450Speter 30925450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 310140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 31125450Speter if (clear) 31225450Speter ifr.ifr_media &= ~options; 313165359Sjkim else { 314165359Sjkim if (options & IFM_HDX) { 315165359Sjkim ifr.ifr_media &= ~IFM_FDX; 316165359Sjkim options &= ~IFM_HDX; 317165359Sjkim } 31825450Speter ifr.ifr_media |= options; 319165359Sjkim } 320140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 321140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 32225450Speter} 32325450Speter 324166113Smariusstatic void 325166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 326166113Smarius{ 327166113Smarius struct ifmediareq *ifmr; 328166113Smarius int inst; 329114164Ssam 330170531Ssam ifmr = ifmedia_getstate(s); 331166113Smarius 332166113Smarius inst = atoi(val); 333194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 334166113Smarius errx(1, "invalid media instance: %s", val); 335166113Smarius 336166113Smarius strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 337166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 338166113Smarius 339166113Smarius ifmr->ifm_current = ifr.ifr_media; 340166113Smarius callback_register(setifmediacallback, (void *)ifmr); 341166113Smarius} 342166113Smarius 343138593Ssamstatic void 344114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 345114164Ssam{ 346140913Sambrisko struct ifmediareq *ifmr; 347140913Sambrisko int mode; 348114164Ssam 349170531Ssam ifmr = ifmedia_getstate(s); 350114164Ssam 351140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 352114164Ssam 353114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 354140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 355114164Ssam 356140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 357140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 358114164Ssam} 359114164Ssam 36025450Speter/********************************************************************** 36125450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 36225450Speter **********************************************************************/ 36325450Speter 36425450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 36525450Speter IFM_TYPE_DESCRIPTIONS; 36625450Speter 36725450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 36825450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 36925450Speter 37025450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 37125450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 37225450Speter 37325450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 37425450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 37525450Speter 37625450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 37725450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 37825450Speter 37925450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 38025450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 38125450Speter 38225450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 38325450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 38425450Speter 38525450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 38625450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 38725450Speter 38825450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 38925450Speter IFM_SUBTYPE_FDDI_ALIASES; 39025450Speter 39125450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 39225450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 39325450Speter 39477217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 39577217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 39677217Sphk 39777217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 39877217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 39977217Sphk 40077217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 40177217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 40277217Sphk 403114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 404114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 405114164Ssam 406116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 407116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 408116820Ssam 409114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 410114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 411114232Sharti 412114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 413114232Sharti IFM_SUBTYPE_ATM_ALIASES; 414114232Sharti 415114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 416114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 417114232Sharti 41825450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 41925450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 42025450Speter 42125450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 42225450Speter IFM_SUBTYPE_SHARED_ALIASES; 42325450Speter 42425450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 42525450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 42625450Speter 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; 43525450Speter } options[3]; 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 }, 45477217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 45525450Speter { NULL, 0 }, 45625450Speter }, 457114164Ssam { 458114164Ssam { NULL, 0 }, 459114164Ssam }, 46025450Speter }, 46125450Speter { 46225450Speter { 46325450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 46425450Speter { &ifm_subtype_shared_aliases[0], 1 }, 46525450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 46625450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 46725450Speter { NULL, 0 }, 46825450Speter }, 46925450Speter { 47025450Speter { &ifm_shared_option_descriptions[0], 0 }, 47177217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 47225450Speter { NULL, 0 }, 47325450Speter }, 474114164Ssam { 475114164Ssam { NULL, 0 }, 476114164Ssam }, 47725450Speter }, 47825450Speter { 47925450Speter { 48025450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 48125450Speter { &ifm_subtype_shared_aliases[0], 1 }, 48225450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 48325450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 48425450Speter { NULL, 0 }, 48525450Speter }, 48625450Speter { 48725450Speter { &ifm_shared_option_descriptions[0], 0 }, 48877217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 48925450Speter { NULL, 0 }, 49025450Speter }, 491114164Ssam { 492114164Ssam { NULL, 0 }, 493114164Ssam }, 49425450Speter }, 49577217Sphk { 49677217Sphk { 49777217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 49877217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 49977217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 50077217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 50177217Sphk { NULL, 0 }, 50277217Sphk }, 50377217Sphk { 50477217Sphk { &ifm_shared_option_descriptions[0], 0 }, 50577217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 50677217Sphk { NULL, 0 }, 50777217Sphk }, 508114164Ssam { 509114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 510116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 511114164Ssam { NULL, 0 }, 512114164Ssam }, 51377217Sphk }, 514114232Sharti { 515114232Sharti { 516114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 517114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 518114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 519114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 520114232Sharti { NULL, 0 }, 521114232Sharti }, 522114232Sharti { 523114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 524114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 525114232Sharti { NULL, 0 }, 526114232Sharti }, 527114232Sharti { 528114232Sharti { NULL, 0 }, 529114232Sharti }, 530114232Sharti }, 53125450Speter}; 53225450Speter 53325450Speterstatic int 53495005Simpget_media_subtype(int type, const char *val) 53525450Speter{ 53625450Speter struct ifmedia_description *desc; 53725450Speter struct ifmedia_type_to_subtype *ttos; 53825450Speter int rval, i; 53925450Speter 54025450Speter /* Find the top-level interface type. */ 54125450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 54225450Speter desc->ifmt_string != NULL; desc++, ttos++) 54325450Speter if (type == desc->ifmt_word) 54425450Speter break; 54525450Speter if (desc->ifmt_string == NULL) 54625450Speter errx(1, "unknown media type 0x%x", type); 54725450Speter 54825450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 54925450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 55025450Speter if (rval != -1) 55125450Speter return (rval); 55225450Speter } 55325450Speter errx(1, "unknown media subtype: %s", val); 554114164Ssam /*NOTREACHED*/ 55525450Speter} 55625450Speter 55725450Speterstatic int 558114164Ssamget_media_mode(int type, const char *val) 559114164Ssam{ 560114164Ssam struct ifmedia_description *desc; 561114164Ssam struct ifmedia_type_to_subtype *ttos; 562114164Ssam int rval, i; 563114164Ssam 564114164Ssam /* Find the top-level interface type. */ 565114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 566114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 567114164Ssam if (type == desc->ifmt_word) 568114164Ssam break; 569114164Ssam if (desc->ifmt_string == NULL) 570114164Ssam errx(1, "unknown media mode 0x%x", type); 571114164Ssam 572114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 573114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 574114164Ssam if (rval != -1) 575114164Ssam return (rval); 576114164Ssam } 577114164Ssam return -1; 578114164Ssam} 579114164Ssam 580114164Ssamstatic int 58195005Simpget_media_options(int type, const char *val) 58225450Speter{ 58325450Speter struct ifmedia_description *desc; 58425450Speter struct ifmedia_type_to_subtype *ttos; 58525450Speter char *optlist, *optptr; 58625450Speter int option = 0, i, rval = 0; 58725450Speter 58825450Speter /* We muck with the string, so copy it. */ 58925450Speter optlist = strdup(val); 59025450Speter if (optlist == NULL) 59125450Speter err(1, "strdup"); 59225450Speter 59325450Speter /* Find the top-level interface type. */ 59425450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 59525450Speter desc->ifmt_string != NULL; desc++, ttos++) 59625450Speter if (type == desc->ifmt_word) 59725450Speter break; 59825450Speter if (desc->ifmt_string == NULL) 59925450Speter errx(1, "unknown media type 0x%x", type); 60025450Speter 60125450Speter /* 60225450Speter * Look up the options in the user-provided comma-separated 60325450Speter * list. 60425450Speter */ 60525450Speter optptr = optlist; 60625450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 60725450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 60825450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 60925450Speter if (option != -1) 61025450Speter break; 61125450Speter } 61225450Speter if (option == 0) 61325450Speter errx(1, "unknown option: %s", optptr); 61425450Speter rval |= option; 61525450Speter } 61625450Speter 61725450Speter free(optlist); 61825450Speter return (rval); 61925450Speter} 62025450Speter 62125450Speterstatic int 62295005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 62325450Speter{ 62425450Speter 62525450Speter for (; desc->ifmt_string != NULL; desc++) 62625450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 62725450Speter return (desc->ifmt_word); 62825450Speter 62925450Speter return (-1); 63025450Speter} 63125450Speter 63295005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 63325450Speter{ 63425450Speter struct ifmedia_description *desc; 63577385Sphk 63677385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 63777385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 63877385Sphk break; 63977385Sphk 64077385Sphk return desc; 64177385Sphk} 64277385Sphk 64395005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 64477385Sphk{ 64577385Sphk struct ifmedia_description *desc; 64625450Speter struct ifmedia_type_to_subtype *ttos; 64725450Speter 64825450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 64925450Speter desc->ifmt_string != NULL; desc++, ttos++) 65025450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 65125450Speter break; 65277385Sphk 65377385Sphk return ttos; 65477385Sphk} 65577385Sphk 65695005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 65795005Simp struct ifmedia_type_to_subtype *ttos) 65877385Sphk{ 65977385Sphk int i; 66077385Sphk struct ifmedia_description *desc; 66177385Sphk 66277385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 66377385Sphk if (ttos->subtypes[i].alias) 66477385Sphk continue; 66577385Sphk for (desc = ttos->subtypes[i].desc; 66677385Sphk desc->ifmt_string != NULL; desc++) { 66777385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 66877385Sphk return desc; 66977385Sphk } 67077385Sphk } 67177385Sphk 67277385Sphk return NULL; 67377385Sphk} 67477385Sphk 675114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 676114164Ssam struct ifmedia_type_to_subtype *ttos) 677114164Ssam{ 678114164Ssam int i; 679114164Ssam struct ifmedia_description *desc; 680114164Ssam 681114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 682114164Ssam if (ttos->modes[i].alias) 683114164Ssam continue; 684114164Ssam for (desc = ttos->modes[i].desc; 685114164Ssam desc->ifmt_string != NULL; desc++) { 686114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 687114164Ssam return desc; 688114164Ssam } 689114164Ssam } 690114164Ssam 691114164Ssam return NULL; 692114164Ssam} 693114164Ssam 69477385Sphkstatic void 69595005Simpprint_media_word(int ifmw, int print_toptype) 69677385Sphk{ 69777385Sphk struct ifmedia_description *desc; 69877385Sphk struct ifmedia_type_to_subtype *ttos; 69977385Sphk int seen_option = 0, i; 70077385Sphk 70177385Sphk /* Find the top-level interface type. */ 70277385Sphk desc = get_toptype_desc(ifmw); 70377385Sphk ttos = get_toptype_ttos(ifmw); 70425450Speter if (desc->ifmt_string == NULL) { 70525450Speter printf("<unknown type>"); 70625450Speter return; 70777385Sphk } else if (print_toptype) { 70877385Sphk printf("%s", desc->ifmt_string); 70925450Speter } 71025450Speter 71125450Speter /* 71225450Speter * Don't print the top-level type; it's not like we can 71325450Speter * change it, or anything. 71425450Speter */ 71525450Speter 71625450Speter /* Find subtype. */ 71777385Sphk desc = get_subtype_desc(ifmw, ttos); 718161536Sthomas if (desc == NULL) { 719161536Sthomas printf("<unknown subtype>"); 720161536Sthomas return; 721161536Sthomas } 72225450Speter 72377385Sphk if (print_toptype) 72477385Sphk putchar(' '); 72577385Sphk 72625450Speter printf("%s", desc->ifmt_string); 72725450Speter 728114164Ssam if (print_toptype) { 729114164Ssam desc = get_mode_desc(ifmw, ttos); 730116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 731114164Ssam printf(" mode %s", desc->ifmt_string); 732114164Ssam } 733114164Ssam 73425450Speter /* Find options. */ 73525450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 73625450Speter if (ttos->options[i].alias) 73725450Speter continue; 73825450Speter for (desc = ttos->options[i].desc; 73925450Speter desc->ifmt_string != NULL; desc++) { 74025450Speter if (ifmw & desc->ifmt_word) { 74125450Speter if (seen_option == 0) 74225450Speter printf(" <"); 74325450Speter printf("%s%s", seen_option++ ? "," : "", 74425450Speter desc->ifmt_string); 74525450Speter } 74625450Speter } 74725450Speter } 74825450Speter printf("%s", seen_option ? ">" : ""); 749166113Smarius 750166169Smarius if (print_toptype && IFM_INST(ifmw) != 0) 751166113Smarius printf(" instance %d", IFM_INST(ifmw)); 75225450Speter} 75325450Speter 75477385Sphkstatic void 75595005Simpprint_media_word_ifconfig(int ifmw) 75677385Sphk{ 75777385Sphk struct ifmedia_description *desc; 75877385Sphk struct ifmedia_type_to_subtype *ttos; 75977385Sphk int i; 76077385Sphk 76177385Sphk /* Find the top-level interface type. */ 76277385Sphk desc = get_toptype_desc(ifmw); 76377385Sphk ttos = get_toptype_ttos(ifmw); 76477385Sphk if (desc->ifmt_string == NULL) { 76577385Sphk printf("<unknown type>"); 76677385Sphk return; 76777385Sphk } 76877385Sphk 76977385Sphk /* 77077385Sphk * Don't print the top-level type; it's not like we can 77177385Sphk * change it, or anything. 77277385Sphk */ 77377385Sphk 77477385Sphk /* Find subtype. */ 77577385Sphk desc = get_subtype_desc(ifmw, ttos); 776161536Sthomas if (desc == NULL) { 777161536Sthomas printf("<unknown subtype>"); 778161536Sthomas return; 779161536Sthomas } 78077385Sphk 78177385Sphk printf("media %s", desc->ifmt_string); 78277385Sphk 783114164Ssam desc = get_mode_desc(ifmw, ttos); 784114164Ssam if (desc != NULL) 785114164Ssam printf(" mode %s", desc->ifmt_string); 786114164Ssam 78777385Sphk /* Find options. */ 78877385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 78977385Sphk if (ttos->options[i].alias) 79077385Sphk continue; 79177385Sphk for (desc = ttos->options[i].desc; 79277385Sphk desc->ifmt_string != NULL; desc++) { 79377385Sphk if (ifmw & desc->ifmt_word) { 79477385Sphk printf(" mediaopt %s", desc->ifmt_string); 79577385Sphk } 79677385Sphk } 79777385Sphk } 798166113Smarius 799166169Smarius if (IFM_INST(ifmw) != 0) 800166169Smarius printf(" instance %d", IFM_INST(ifmw)); 80177385Sphk} 80277385Sphk 80325450Speter/********************************************************************** 80425450Speter * ...until here. 80525450Speter **********************************************************************/ 806138593Ssam 807138593Ssamstatic struct cmd media_cmds[] = { 808138593Ssam DEF_CMD_ARG("media", setmedia), 809138593Ssam DEF_CMD_ARG("mode", setmediamode), 810138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 811138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 812166113Smarius DEF_CMD_ARG("inst", setmediainst), 813166113Smarius DEF_CMD_ARG("instance", setmediainst), 814138593Ssam}; 815138593Ssamstatic struct afswtch af_media = { 816138593Ssam .af_name = "af_media", 817138593Ssam .af_af = AF_UNSPEC, 818139494Ssam .af_other_status = media_status, 819138593Ssam}; 820138593Ssam 821138593Ssamstatic __constructor void 822138593Ssamifmedia_ctor(void) 823138593Ssam{ 824138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 825194799Sdelphij size_t i; 826138593Ssam 827138593Ssam for (i = 0; i < N(media_cmds); i++) 828138593Ssam cmd_register(&media_cmds[i]); 829138593Ssam af_register(&af_media); 830138593Ssam#undef N 831138593Ssam} 832