ifmedia.c revision 215259
125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 215259 2010-11-13 21:03:19Z 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 * 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 | \ 107195618Srpaulo IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 108195618Srpaulo IFM_IEEE80211_MBSS)) 109178354Ssam#define IFM_IEEE80211_STA 0 110178354Ssam 111138593Ssamstatic void 112139494Ssammedia_status(int s) 11325450Speter{ 11425450Speter struct ifmediareq ifmr; 11525450Speter int *media_list, i; 11625450Speter 11725450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11825450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11925450Speter 12025450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 12125450Speter /* 12225450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 12325450Speter */ 12425450Speter return; 12525450Speter } 12625450Speter 12725450Speter if (ifmr.ifm_count == 0) { 12825450Speter warnx("%s: no media types?", name); 12925450Speter return; 13025450Speter } 13125450Speter 13225450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 13325450Speter if (media_list == NULL) 13425450Speter err(1, "malloc"); 13525450Speter ifmr.ifm_ulist = media_list; 13625450Speter 13725450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13825450Speter err(1, "SIOCGIFMEDIA"); 13925450Speter 14025450Speter printf("\tmedia: "); 14177385Sphk print_media_word(ifmr.ifm_current, 1); 14225450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 14325450Speter putchar(' '); 14425450Speter putchar('('); 14577385Sphk print_media_word(ifmr.ifm_active, 0); 14625450Speter putchar(')'); 14725450Speter } 14825450Speter 14977385Sphk putchar('\n'); 15077385Sphk 15125450Speter if (ifmr.ifm_status & IFM_AVALID) { 15277385Sphk printf("\tstatus: "); 15325450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 15425450Speter case IFM_ETHER: 155161536Sthomas case IFM_ATM: 15625450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15725450Speter printf("active"); 15825450Speter else 15925450Speter printf("no carrier"); 16025450Speter break; 16125450Speter 16225450Speter case IFM_FDDI: 16325450Speter case IFM_TOKEN: 16425450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16525450Speter printf("inserted"); 16625450Speter else 16725450Speter printf("no ring"); 16825450Speter break; 169114232Sharti 17077217Sphk case IFM_IEEE80211: 171178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 172178354Ssam /* NB: only sta mode associates */ 173178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 174178354Ssam printf("associated"); 175178354Ssam else 176178354Ssam printf("running"); 177178354Ssam } else 17877217Sphk printf("no carrier"); 17977217Sphk break; 18025450Speter } 18185853Syar putchar('\n'); 18225450Speter } 18325450Speter 18477385Sphk if (ifmr.ifm_count > 0 && supmedia) { 18577385Sphk printf("\tsupported media:\n"); 18625450Speter for (i = 0; i < ifmr.ifm_count; i++) { 18777385Sphk printf("\t\t"); 18877385Sphk print_media_word_ifconfig(media_list[i]); 18977385Sphk putchar('\n'); 19025450Speter } 19125450Speter } 19225450Speter 19325450Speter free(media_list); 19425450Speter} 19525450Speter 196170531Ssamstruct ifmediareq * 197170531Ssamifmedia_getstate(int s) 19825450Speter{ 199140913Sambrisko static struct ifmediareq *ifmr = NULL; 200140913Sambrisko int *mwords; 20125450Speter 202140913Sambrisko if (ifmr == NULL) { 203140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 204140913Sambrisko if (ifmr == NULL) 205140913Sambrisko err(1, "malloc"); 20625450Speter 207140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 208140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 209140913Sambrisko sizeof(ifmr->ifm_name)); 210140913Sambrisko 211140913Sambrisko ifmr->ifm_count = 0; 212140913Sambrisko ifmr->ifm_ulist = NULL; 213140913Sambrisko 21425450Speter /* 215140913Sambrisko * We must go through the motions of reading all 216140913Sambrisko * supported media because we need to know both 217140913Sambrisko * the current media type and the top-level type. 21825450Speter */ 219140913Sambrisko 220140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 22125450Speter err(1, "SIOCGIFMEDIA"); 222140913Sambrisko } 223140913Sambrisko 224140913Sambrisko if (ifmr->ifm_count == 0) 225140913Sambrisko errx(1, "%s: no media types?", name); 226140913Sambrisko 227140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 228140913Sambrisko if (mwords == NULL) 229140913Sambrisko err(1, "malloc"); 230140913Sambrisko 231140913Sambrisko ifmr->ifm_ulist = mwords; 232140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 233140913Sambrisko err(1, "SIOCGIFMEDIA"); 23425450Speter } 23525450Speter 236140913Sambrisko return ifmr; 237140913Sambrisko} 23825450Speter 239140913Sambriskostatic void 240140913Sambriskosetifmediacallback(int s, void *arg) 241140913Sambrisko{ 242140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 243140913Sambrisko static int did_it = 0; 244140913Sambrisko 245140913Sambrisko if (!did_it) { 246154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 247140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 248140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 249140913Sambrisko free(ifmr->ifm_ulist); 250140913Sambrisko free(ifmr); 251140913Sambrisko did_it = 1; 252140913Sambrisko } 253140913Sambrisko} 254140913Sambrisko 255140913Sambriskostatic void 256140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 257140913Sambrisko{ 258140913Sambrisko struct ifmediareq *ifmr; 259140913Sambrisko int subtype; 260140913Sambrisko 261170531Ssam ifmr = ifmedia_getstate(s); 262140913Sambrisko 26325450Speter /* 26425450Speter * We are primarily concerned with the top-level type. 26525450Speter * However, "current" may be only IFM_NONE, so we just look 26625450Speter * for the top-level type in the first "supported type" 26725450Speter * entry. 26825450Speter * 26925450Speter * (I'm assuming that all supported media types for a given 27025450Speter * interface will be the same top-level type..) 27125450Speter */ 272140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 27325450Speter 27425450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 275140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 276140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 27725450Speter 278140913Sambrisko if ((ifr.ifr_media & IFM_TMASK) == 0) { 279140913Sambrisko ifr.ifr_media &= ~IFM_GMASK; 280140913Sambrisko } 281140913Sambrisko 282140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 283140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 28425450Speter} 28525450Speter 286138593Ssamstatic void 28795005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28825450Speter{ 28925450Speter 29025450Speter domediaopt(val, 0, s); 29125450Speter} 29225450Speter 293138593Ssamstatic void 29495005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 29525450Speter{ 29625450Speter 29725450Speter domediaopt(val, 1, s); 29825450Speter} 29925450Speter 30025450Speterstatic void 30195005Simpdomediaopt(const char *val, int clear, int s) 30225450Speter{ 303140913Sambrisko struct ifmediareq *ifmr; 304140913Sambrisko int options; 30525450Speter 306170531Ssam ifmr = ifmedia_getstate(s); 30725450Speter 308140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 30925450Speter 31025450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 311140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 31225450Speter if (clear) 31325450Speter ifr.ifr_media &= ~options; 314165359Sjkim else { 315165359Sjkim if (options & IFM_HDX) { 316165359Sjkim ifr.ifr_media &= ~IFM_FDX; 317165359Sjkim options &= ~IFM_HDX; 318165359Sjkim } 31925450Speter ifr.ifr_media |= options; 320165359Sjkim } 321140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 322140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 32325450Speter} 32425450Speter 325166113Smariusstatic void 326166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 327166113Smarius{ 328166113Smarius struct ifmediareq *ifmr; 329166113Smarius int inst; 330114164Ssam 331170531Ssam ifmr = ifmedia_getstate(s); 332166113Smarius 333166113Smarius inst = atoi(val); 334194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 335166113Smarius errx(1, "invalid media instance: %s", val); 336166113Smarius 337166113Smarius strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 338166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 339166113Smarius 340166113Smarius ifmr->ifm_current = ifr.ifr_media; 341166113Smarius callback_register(setifmediacallback, (void *)ifmr); 342166113Smarius} 343166113Smarius 344138593Ssamstatic void 345114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 346114164Ssam{ 347140913Sambrisko struct ifmediareq *ifmr; 348140913Sambrisko int mode; 349114164Ssam 350170531Ssam ifmr = ifmedia_getstate(s); 351114164Ssam 352140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 353114164Ssam 354114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 355140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 356114164Ssam 357140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 358140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 359114164Ssam} 360114164Ssam 36125450Speter/********************************************************************** 36225450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 36325450Speter **********************************************************************/ 36425450Speter 36525450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 36625450Speter IFM_TYPE_DESCRIPTIONS; 36725450Speter 36825450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 36925450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 37025450Speter 37125450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 37225450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 37325450Speter 37425450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 37525450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 37625450Speter 37725450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 37825450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 37925450Speter 38025450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 38125450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 38225450Speter 38325450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 38425450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 38525450Speter 38625450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 38725450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 38825450Speter 38925450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 39025450Speter IFM_SUBTYPE_FDDI_ALIASES; 39125450Speter 39225450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 39325450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 39425450Speter 39577217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 39677217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 39777217Sphk 39877217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 39977217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 40077217Sphk 40177217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 40277217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 40377217Sphk 404114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 405114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 406114164Ssam 407116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 408116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 409116820Ssam 410114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 411114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 412114232Sharti 413114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 414114232Sharti IFM_SUBTYPE_ATM_ALIASES; 415114232Sharti 416114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 417114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 418114232Sharti 41925450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 42025450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 42125450Speter 42225450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 42325450Speter IFM_SUBTYPE_SHARED_ALIASES; 42425450Speter 42525450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 42625450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 42725450Speter 42825450Speterstruct ifmedia_type_to_subtype { 42925450Speter struct { 43025450Speter struct ifmedia_description *desc; 43125450Speter int alias; 43225450Speter } subtypes[5]; 43325450Speter struct { 43425450Speter struct ifmedia_description *desc; 43525450Speter int alias; 43625450Speter } options[3]; 437114164Ssam struct { 438114164Ssam struct ifmedia_description *desc; 439114164Ssam int alias; 440116820Ssam } modes[3]; 44125450Speter}; 44225450Speter 44325450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 44425450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 44525450Speter { 44625450Speter { 44725450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 44825450Speter { &ifm_subtype_shared_aliases[0], 1 }, 44925450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 45025450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 45125450Speter { NULL, 0 }, 45225450Speter }, 45325450Speter { 45425450Speter { &ifm_shared_option_descriptions[0], 0 }, 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 }, 47277217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 47325450Speter { NULL, 0 }, 47425450Speter }, 475114164Ssam { 476114164Ssam { NULL, 0 }, 477114164Ssam }, 47825450Speter }, 47925450Speter { 48025450Speter { 48125450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 48225450Speter { &ifm_subtype_shared_aliases[0], 1 }, 48325450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 48425450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 48525450Speter { NULL, 0 }, 48625450Speter }, 48725450Speter { 48825450Speter { &ifm_shared_option_descriptions[0], 0 }, 48977217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 49025450Speter { NULL, 0 }, 49125450Speter }, 492114164Ssam { 493114164Ssam { NULL, 0 }, 494114164Ssam }, 49525450Speter }, 49677217Sphk { 49777217Sphk { 49877217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 49977217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 50077217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 50177217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 50277217Sphk { NULL, 0 }, 50377217Sphk }, 50477217Sphk { 50577217Sphk { &ifm_shared_option_descriptions[0], 0 }, 50677217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 50777217Sphk { NULL, 0 }, 50877217Sphk }, 509114164Ssam { 510114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 511116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 512114164Ssam { NULL, 0 }, 513114164Ssam }, 51477217Sphk }, 515114232Sharti { 516114232Sharti { 517114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 518114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 519114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 520114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 521114232Sharti { NULL, 0 }, 522114232Sharti }, 523114232Sharti { 524114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 525114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 526114232Sharti { NULL, 0 }, 527114232Sharti }, 528114232Sharti { 529114232Sharti { NULL, 0 }, 530114232Sharti }, 531114232Sharti }, 53225450Speter}; 53325450Speter 53425450Speterstatic int 53595005Simpget_media_subtype(int type, const char *val) 53625450Speter{ 53725450Speter struct ifmedia_description *desc; 53825450Speter struct ifmedia_type_to_subtype *ttos; 53925450Speter int rval, i; 54025450Speter 54125450Speter /* Find the top-level interface type. */ 54225450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 54325450Speter desc->ifmt_string != NULL; desc++, ttos++) 54425450Speter if (type == desc->ifmt_word) 54525450Speter break; 54625450Speter if (desc->ifmt_string == NULL) 54725450Speter errx(1, "unknown media type 0x%x", type); 54825450Speter 54925450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 55025450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 55125450Speter if (rval != -1) 55225450Speter return (rval); 55325450Speter } 55425450Speter errx(1, "unknown media subtype: %s", val); 555114164Ssam /*NOTREACHED*/ 55625450Speter} 55725450Speter 55825450Speterstatic int 559114164Ssamget_media_mode(int type, const char *val) 560114164Ssam{ 561114164Ssam struct ifmedia_description *desc; 562114164Ssam struct ifmedia_type_to_subtype *ttos; 563114164Ssam int rval, i; 564114164Ssam 565114164Ssam /* Find the top-level interface type. */ 566114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 567114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 568114164Ssam if (type == desc->ifmt_word) 569114164Ssam break; 570114164Ssam if (desc->ifmt_string == NULL) 571114164Ssam errx(1, "unknown media mode 0x%x", type); 572114164Ssam 573114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 574114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 575114164Ssam if (rval != -1) 576114164Ssam return (rval); 577114164Ssam } 578114164Ssam return -1; 579114164Ssam} 580114164Ssam 581114164Ssamstatic int 58295005Simpget_media_options(int type, const char *val) 58325450Speter{ 58425450Speter struct ifmedia_description *desc; 58525450Speter struct ifmedia_type_to_subtype *ttos; 58625450Speter char *optlist, *optptr; 58725450Speter int option = 0, i, rval = 0; 58825450Speter 58925450Speter /* We muck with the string, so copy it. */ 59025450Speter optlist = strdup(val); 59125450Speter if (optlist == NULL) 59225450Speter err(1, "strdup"); 59325450Speter 59425450Speter /* Find the top-level interface type. */ 59525450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 59625450Speter desc->ifmt_string != NULL; desc++, ttos++) 59725450Speter if (type == desc->ifmt_word) 59825450Speter break; 59925450Speter if (desc->ifmt_string == NULL) 60025450Speter errx(1, "unknown media type 0x%x", type); 60125450Speter 60225450Speter /* 60325450Speter * Look up the options in the user-provided comma-separated 60425450Speter * list. 60525450Speter */ 60625450Speter optptr = optlist; 60725450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 60825450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 60925450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 61025450Speter if (option != -1) 61125450Speter break; 61225450Speter } 61325450Speter if (option == 0) 61425450Speter errx(1, "unknown option: %s", optptr); 61525450Speter rval |= option; 61625450Speter } 61725450Speter 61825450Speter free(optlist); 61925450Speter return (rval); 62025450Speter} 62125450Speter 62225450Speterstatic int 62395005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 62425450Speter{ 62525450Speter 62625450Speter for (; desc->ifmt_string != NULL; desc++) 62725450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 62825450Speter return (desc->ifmt_word); 62925450Speter 63025450Speter return (-1); 63125450Speter} 63225450Speter 63395005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 63425450Speter{ 63525450Speter struct ifmedia_description *desc; 63677385Sphk 63777385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 63877385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 63977385Sphk break; 64077385Sphk 64177385Sphk return desc; 64277385Sphk} 64377385Sphk 64495005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 64577385Sphk{ 64677385Sphk struct ifmedia_description *desc; 64725450Speter struct ifmedia_type_to_subtype *ttos; 64825450Speter 64925450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 65025450Speter desc->ifmt_string != NULL; desc++, ttos++) 65125450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 65225450Speter break; 65377385Sphk 65477385Sphk return ttos; 65577385Sphk} 65677385Sphk 65795005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 65895005Simp struct ifmedia_type_to_subtype *ttos) 65977385Sphk{ 66077385Sphk int i; 66177385Sphk struct ifmedia_description *desc; 66277385Sphk 66377385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 66477385Sphk if (ttos->subtypes[i].alias) 66577385Sphk continue; 66677385Sphk for (desc = ttos->subtypes[i].desc; 66777385Sphk desc->ifmt_string != NULL; desc++) { 66877385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 66977385Sphk return desc; 67077385Sphk } 67177385Sphk } 67277385Sphk 67377385Sphk return NULL; 67477385Sphk} 67577385Sphk 676114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 677114164Ssam struct ifmedia_type_to_subtype *ttos) 678114164Ssam{ 679114164Ssam int i; 680114164Ssam struct ifmedia_description *desc; 681114164Ssam 682114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 683114164Ssam if (ttos->modes[i].alias) 684114164Ssam continue; 685114164Ssam for (desc = ttos->modes[i].desc; 686114164Ssam desc->ifmt_string != NULL; desc++) { 687114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 688114164Ssam return desc; 689114164Ssam } 690114164Ssam } 691114164Ssam 692114164Ssam return NULL; 693114164Ssam} 694114164Ssam 69577385Sphkstatic void 69695005Simpprint_media_word(int ifmw, int print_toptype) 69777385Sphk{ 69877385Sphk struct ifmedia_description *desc; 69977385Sphk struct ifmedia_type_to_subtype *ttos; 70077385Sphk int seen_option = 0, i; 70177385Sphk 70277385Sphk /* Find the top-level interface type. */ 70377385Sphk desc = get_toptype_desc(ifmw); 70477385Sphk ttos = get_toptype_ttos(ifmw); 70525450Speter if (desc->ifmt_string == NULL) { 70625450Speter printf("<unknown type>"); 70725450Speter return; 70877385Sphk } else if (print_toptype) { 70977385Sphk printf("%s", desc->ifmt_string); 71025450Speter } 71125450Speter 71225450Speter /* 71325450Speter * Don't print the top-level type; it's not like we can 71425450Speter * change it, or anything. 71525450Speter */ 71625450Speter 71725450Speter /* Find subtype. */ 71877385Sphk desc = get_subtype_desc(ifmw, ttos); 719161536Sthomas if (desc == NULL) { 720161536Sthomas printf("<unknown subtype>"); 721161536Sthomas return; 722161536Sthomas } 72325450Speter 72477385Sphk if (print_toptype) 72577385Sphk putchar(' '); 72677385Sphk 72725450Speter printf("%s", desc->ifmt_string); 72825450Speter 729114164Ssam if (print_toptype) { 730114164Ssam desc = get_mode_desc(ifmw, ttos); 731116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 732114164Ssam printf(" mode %s", desc->ifmt_string); 733114164Ssam } 734114164Ssam 73525450Speter /* Find options. */ 73625450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 73725450Speter if (ttos->options[i].alias) 73825450Speter continue; 73925450Speter for (desc = ttos->options[i].desc; 74025450Speter desc->ifmt_string != NULL; desc++) { 74125450Speter if (ifmw & desc->ifmt_word) { 74225450Speter if (seen_option == 0) 74325450Speter printf(" <"); 74425450Speter printf("%s%s", seen_option++ ? "," : "", 74525450Speter desc->ifmt_string); 74625450Speter } 74725450Speter } 74825450Speter } 74925450Speter printf("%s", seen_option ? ">" : ""); 750166113Smarius 751166169Smarius if (print_toptype && IFM_INST(ifmw) != 0) 752166113Smarius printf(" instance %d", IFM_INST(ifmw)); 75325450Speter} 75425450Speter 75577385Sphkstatic void 75695005Simpprint_media_word_ifconfig(int ifmw) 75777385Sphk{ 75877385Sphk struct ifmedia_description *desc; 75977385Sphk struct ifmedia_type_to_subtype *ttos; 760215259Smarius int seen_option = 0, i; 76177385Sphk 76277385Sphk /* Find the top-level interface type. */ 76377385Sphk desc = get_toptype_desc(ifmw); 76477385Sphk ttos = get_toptype_ttos(ifmw); 76577385Sphk if (desc->ifmt_string == NULL) { 76677385Sphk printf("<unknown type>"); 76777385Sphk return; 76877385Sphk } 76977385Sphk 77077385Sphk /* 77177385Sphk * Don't print the top-level type; it's not like we can 77277385Sphk * change it, or anything. 77377385Sphk */ 77477385Sphk 77577385Sphk /* Find subtype. */ 77677385Sphk desc = get_subtype_desc(ifmw, ttos); 777161536Sthomas if (desc == NULL) { 778161536Sthomas printf("<unknown subtype>"); 779161536Sthomas return; 780161536Sthomas } 78177385Sphk 78277385Sphk printf("media %s", desc->ifmt_string); 78377385Sphk 784114164Ssam desc = get_mode_desc(ifmw, ttos); 785114164Ssam if (desc != NULL) 786114164Ssam printf(" mode %s", desc->ifmt_string); 787114164Ssam 78877385Sphk /* Find options. */ 78977385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 79077385Sphk if (ttos->options[i].alias) 79177385Sphk continue; 79277385Sphk for (desc = ttos->options[i].desc; 79377385Sphk desc->ifmt_string != NULL; desc++) { 79477385Sphk if (ifmw & desc->ifmt_word) { 795215259Smarius if (seen_option == 0) 796215259Smarius printf(" mediaopt "); 797215259Smarius printf("%s%s", seen_option++ ? "," : "", 798215259Smarius desc->ifmt_string); 79977385Sphk } 80077385Sphk } 80177385Sphk } 802166113Smarius 803166169Smarius if (IFM_INST(ifmw) != 0) 804166169Smarius printf(" instance %d", IFM_INST(ifmw)); 80577385Sphk} 80677385Sphk 80725450Speter/********************************************************************** 80825450Speter * ...until here. 80925450Speter **********************************************************************/ 810138593Ssam 811138593Ssamstatic struct cmd media_cmds[] = { 812138593Ssam DEF_CMD_ARG("media", setmedia), 813138593Ssam DEF_CMD_ARG("mode", setmediamode), 814138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 815138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 816166113Smarius DEF_CMD_ARG("inst", setmediainst), 817166113Smarius DEF_CMD_ARG("instance", setmediainst), 818138593Ssam}; 819138593Ssamstatic struct afswtch af_media = { 820138593Ssam .af_name = "af_media", 821138593Ssam .af_af = AF_UNSPEC, 822139494Ssam .af_other_status = media_status, 823138593Ssam}; 824138593Ssam 825138593Ssamstatic __constructor void 826138593Ssamifmedia_ctor(void) 827138593Ssam{ 828138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 829194799Sdelphij size_t i; 830138593Ssam 831138593Ssam for (i = 0; i < N(media_cmds); i++) 832138593Ssam cmd_register(&media_cmds[i]); 833138593Ssam af_register(&af_media); 834138593Ssam#undef N 835138593Ssam} 836