125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: releng/10.3/sbin/ifconfig/ifmedia.c 289986 2015-10-26 03:43:28Z ngie $ */ 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; 112283758Serj int xmedia = 1; 11325450Speter 11425450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11525450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11625450Speter 117283758Serj /* 118283758Serj * Check if interface supports extended media types. 119283758Serj */ 120283758Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) 121283758Serj xmedia = 0; 122283758Serj if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 12325450Speter /* 12425450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 12525450Speter */ 12625450Speter return; 12725450Speter } 12825450Speter 12925450Speter if (ifmr.ifm_count == 0) { 13025450Speter warnx("%s: no media types?", name); 13125450Speter return; 13225450Speter } 13325450Speter 13425450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 13525450Speter if (media_list == NULL) 13625450Speter err(1, "malloc"); 13725450Speter ifmr.ifm_ulist = media_list; 13825450Speter 139283758Serj if (xmedia) { 140283758Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) 141283758Serj err(1, "SIOCGIFXMEDIA"); 142283758Serj } else { 143283758Serj if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 144283758Serj err(1, "SIOCGIFMEDIA"); 145283758Serj } 14625450Speter 14725450Speter printf("\tmedia: "); 14877385Sphk print_media_word(ifmr.ifm_current, 1); 14925450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 15025450Speter putchar(' '); 15125450Speter putchar('('); 15277385Sphk print_media_word(ifmr.ifm_active, 0); 15325450Speter putchar(')'); 15425450Speter } 15525450Speter 15677385Sphk putchar('\n'); 15777385Sphk 15825450Speter if (ifmr.ifm_status & IFM_AVALID) { 15977385Sphk printf("\tstatus: "); 16025450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 16125450Speter case IFM_ETHER: 162161536Sthomas case IFM_ATM: 16325450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16425450Speter printf("active"); 16525450Speter else 16625450Speter printf("no carrier"); 16725450Speter break; 16825450Speter 16925450Speter case IFM_FDDI: 17025450Speter case IFM_TOKEN: 17125450Speter if (ifmr.ifm_status & IFM_ACTIVE) 17225450Speter printf("inserted"); 17325450Speter else 17425450Speter printf("no ring"); 17525450Speter break; 176114232Sharti 17777217Sphk case IFM_IEEE80211: 178178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 179178354Ssam /* NB: only sta mode associates */ 180178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 181178354Ssam printf("associated"); 182178354Ssam else 183178354Ssam printf("running"); 184178354Ssam } else 18577217Sphk printf("no carrier"); 18677217Sphk break; 18725450Speter } 18885853Syar putchar('\n'); 18925450Speter } 19025450Speter 19177385Sphk if (ifmr.ifm_count > 0 && supmedia) { 19277385Sphk printf("\tsupported media:\n"); 19325450Speter for (i = 0; i < ifmr.ifm_count; i++) { 19477385Sphk printf("\t\t"); 19577385Sphk print_media_word_ifconfig(media_list[i]); 19677385Sphk putchar('\n'); 19725450Speter } 19825450Speter } 19925450Speter 20025450Speter free(media_list); 20125450Speter} 20225450Speter 203170531Ssamstruct ifmediareq * 204170531Ssamifmedia_getstate(int s) 20525450Speter{ 206140913Sambrisko static struct ifmediareq *ifmr = NULL; 207140913Sambrisko int *mwords; 208283758Serj int xmedia = 1; 20925450Speter 210140913Sambrisko if (ifmr == NULL) { 211140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 212140913Sambrisko if (ifmr == NULL) 213140913Sambrisko err(1, "malloc"); 21425450Speter 215140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 216140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 217140913Sambrisko sizeof(ifmr->ifm_name)); 218140913Sambrisko 219140913Sambrisko ifmr->ifm_count = 0; 220140913Sambrisko ifmr->ifm_ulist = NULL; 221140913Sambrisko 22225450Speter /* 223140913Sambrisko * We must go through the motions of reading all 224140913Sambrisko * supported media because we need to know both 225140913Sambrisko * the current media type and the top-level type. 22625450Speter */ 227140913Sambrisko 228283758Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) { 229283758Serj xmedia = 0; 230283758Serj } 231283758Serj if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 23225450Speter err(1, "SIOCGIFMEDIA"); 233140913Sambrisko } 234140913Sambrisko 235140913Sambrisko if (ifmr->ifm_count == 0) 236140913Sambrisko errx(1, "%s: no media types?", name); 237140913Sambrisko 238140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 239140913Sambrisko if (mwords == NULL) 240140913Sambrisko err(1, "malloc"); 241140913Sambrisko 242140913Sambrisko ifmr->ifm_ulist = mwords; 243283758Serj if (xmedia) { 244283758Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) 245283758Serj err(1, "SIOCGIFXMEDIA"); 246283758Serj } else { 247283758Serj if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 248283758Serj err(1, "SIOCGIFMEDIA"); 249283758Serj } 25025450Speter } 25125450Speter 252140913Sambrisko return ifmr; 253140913Sambrisko} 25425450Speter 255140913Sambriskostatic void 256140913Sambriskosetifmediacallback(int s, void *arg) 257140913Sambrisko{ 258140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 259140913Sambrisko static int did_it = 0; 260140913Sambrisko 261140913Sambrisko if (!did_it) { 262154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 263140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 264140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 265140913Sambrisko free(ifmr->ifm_ulist); 266140913Sambrisko free(ifmr); 267140913Sambrisko did_it = 1; 268140913Sambrisko } 269140913Sambrisko} 270140913Sambrisko 271140913Sambriskostatic void 272140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 273140913Sambrisko{ 274140913Sambrisko struct ifmediareq *ifmr; 275140913Sambrisko int subtype; 276140913Sambrisko 277170531Ssam ifmr = ifmedia_getstate(s); 278140913Sambrisko 27925450Speter /* 28025450Speter * We are primarily concerned with the top-level type. 28125450Speter * However, "current" may be only IFM_NONE, so we just look 28225450Speter * for the top-level type in the first "supported type" 28325450Speter * entry. 28425450Speter * 28525450Speter * (I'm assuming that all supported media types for a given 28625450Speter * interface will be the same top-level type..) 28725450Speter */ 288140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 28925450Speter 29025450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 291221954Smarius ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | 292140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 29325450Speter 294140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 295140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 29625450Speter} 29725450Speter 298138593Ssamstatic void 29995005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 30025450Speter{ 30125450Speter 30225450Speter domediaopt(val, 0, s); 30325450Speter} 30425450Speter 305138593Ssamstatic void 30695005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 30725450Speter{ 30825450Speter 30925450Speter domediaopt(val, 1, s); 31025450Speter} 31125450Speter 31225450Speterstatic void 31395005Simpdomediaopt(const char *val, int clear, int s) 31425450Speter{ 315140913Sambrisko struct ifmediareq *ifmr; 316140913Sambrisko int options; 31725450Speter 318170531Ssam ifmr = ifmedia_getstate(s); 31925450Speter 320140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 32125450Speter 32225450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 323140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 32425450Speter if (clear) 32525450Speter ifr.ifr_media &= ~options; 326165359Sjkim else { 327165359Sjkim if (options & IFM_HDX) { 328165359Sjkim ifr.ifr_media &= ~IFM_FDX; 329165359Sjkim options &= ~IFM_HDX; 330165359Sjkim } 33125450Speter ifr.ifr_media |= options; 332165359Sjkim } 333140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 334140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 33525450Speter} 33625450Speter 337166113Smariusstatic void 338166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 339166113Smarius{ 340166113Smarius struct ifmediareq *ifmr; 341166113Smarius int inst; 342114164Ssam 343170531Ssam ifmr = ifmedia_getstate(s); 344166113Smarius 345166113Smarius inst = atoi(val); 346194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 347166113Smarius errx(1, "invalid media instance: %s", val); 348166113Smarius 349166113Smarius strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 350166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 351166113Smarius 352166113Smarius ifmr->ifm_current = ifr.ifr_media; 353166113Smarius callback_register(setifmediacallback, (void *)ifmr); 354166113Smarius} 355166113Smarius 356138593Ssamstatic void 357114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 358114164Ssam{ 359140913Sambrisko struct ifmediareq *ifmr; 360140913Sambrisko int mode; 361114164Ssam 362170531Ssam ifmr = ifmedia_getstate(s); 363114164Ssam 364140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 365114164Ssam 366114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 367140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 368114164Ssam 369140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 370140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 371114164Ssam} 372114164Ssam 37325450Speter/********************************************************************** 37425450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 37525450Speter **********************************************************************/ 37625450Speter 37725450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 37825450Speter IFM_TYPE_DESCRIPTIONS; 37925450Speter 38025450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 38125450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 38225450Speter 38325450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 38425450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 38525450Speter 38625450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 38725450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 38825450Speter 38925450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 39025450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 39125450Speter 39225450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 39325450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 39425450Speter 39525450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 39625450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 39725450Speter 39825450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 39925450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 40025450Speter 40125450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 40225450Speter IFM_SUBTYPE_FDDI_ALIASES; 40325450Speter 40425450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 40525450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 40625450Speter 40777217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 40877217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 40977217Sphk 41077217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 41177217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 41277217Sphk 41377217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 41477217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 41577217Sphk 416114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 417114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 418114164Ssam 419116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 420116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 421116820Ssam 422114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 423114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 424114232Sharti 425114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 426114232Sharti IFM_SUBTYPE_ATM_ALIASES; 427114232Sharti 428114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 429114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 430114232Sharti 43125450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 43225450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 43325450Speter 43425450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 43525450Speter IFM_SUBTYPE_SHARED_ALIASES; 43625450Speter 43725450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 43825450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 43925450Speter 440217013Smariusstatic struct ifmedia_description ifm_shared_option_aliases[] = 441217013Smarius IFM_SHARED_OPTION_ALIASES; 442217013Smarius 44325450Speterstruct ifmedia_type_to_subtype { 44425450Speter struct { 44525450Speter struct ifmedia_description *desc; 44625450Speter int alias; 44725450Speter } subtypes[5]; 44825450Speter struct { 44925450Speter struct ifmedia_description *desc; 45025450Speter int alias; 451217013Smarius } options[4]; 452114164Ssam struct { 453114164Ssam struct ifmedia_description *desc; 454114164Ssam int alias; 455116820Ssam } modes[3]; 45625450Speter}; 45725450Speter 45825450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 45925450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 46025450Speter { 46125450Speter { 46225450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 46325450Speter { &ifm_subtype_shared_aliases[0], 1 }, 46425450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 46525450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 46625450Speter { NULL, 0 }, 46725450Speter }, 46825450Speter { 46925450Speter { &ifm_shared_option_descriptions[0], 0 }, 470217013Smarius { &ifm_shared_option_aliases[0], 1 }, 47177217Sphk { &ifm_subtype_ethernet_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_tokenring_descriptions[0], 0 }, 48325450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 48425450Speter { NULL, 0 }, 48525450Speter }, 48625450Speter { 48725450Speter { &ifm_shared_option_descriptions[0], 0 }, 488217013Smarius { &ifm_shared_option_aliases[0], 1 }, 48977217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 49025450Speter { NULL, 0 }, 49125450Speter }, 492114164Ssam { 493114164Ssam { NULL, 0 }, 494114164Ssam }, 49525450Speter }, 49625450Speter { 49725450Speter { 49825450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 49925450Speter { &ifm_subtype_shared_aliases[0], 1 }, 50025450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 50125450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 50225450Speter { NULL, 0 }, 50325450Speter }, 50425450Speter { 50525450Speter { &ifm_shared_option_descriptions[0], 0 }, 506217013Smarius { &ifm_shared_option_aliases[0], 1 }, 50777217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 50825450Speter { NULL, 0 }, 50925450Speter }, 510114164Ssam { 511114164Ssam { NULL, 0 }, 512114164Ssam }, 51325450Speter }, 51477217Sphk { 51577217Sphk { 51677217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 51777217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 51877217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 51977217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 52077217Sphk { NULL, 0 }, 52177217Sphk }, 52277217Sphk { 52377217Sphk { &ifm_shared_option_descriptions[0], 0 }, 524217013Smarius { &ifm_shared_option_aliases[0], 1 }, 52577217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 52677217Sphk { NULL, 0 }, 52777217Sphk }, 528114164Ssam { 529114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 530116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 531114164Ssam { NULL, 0 }, 532114164Ssam }, 53377217Sphk }, 534114232Sharti { 535114232Sharti { 536114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 537114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 538114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 539114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 540114232Sharti { NULL, 0 }, 541114232Sharti }, 542114232Sharti { 543114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 544217013Smarius { &ifm_shared_option_aliases[0], 1 }, 545114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 546114232Sharti { NULL, 0 }, 547114232Sharti }, 548114232Sharti { 549114232Sharti { NULL, 0 }, 550114232Sharti }, 551114232Sharti }, 55225450Speter}; 55325450Speter 55425450Speterstatic int 55595005Simpget_media_subtype(int type, const char *val) 55625450Speter{ 55725450Speter struct ifmedia_description *desc; 55825450Speter struct ifmedia_type_to_subtype *ttos; 55925450Speter int rval, i; 56025450Speter 56125450Speter /* Find the top-level interface type. */ 56225450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 56325450Speter desc->ifmt_string != NULL; desc++, ttos++) 56425450Speter if (type == desc->ifmt_word) 56525450Speter break; 56625450Speter if (desc->ifmt_string == NULL) 56725450Speter errx(1, "unknown media type 0x%x", type); 56825450Speter 56925450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 57025450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 57125450Speter if (rval != -1) 57225450Speter return (rval); 57325450Speter } 57425450Speter errx(1, "unknown media subtype: %s", val); 575114164Ssam /*NOTREACHED*/ 57625450Speter} 57725450Speter 57825450Speterstatic int 579114164Ssamget_media_mode(int type, const char *val) 580114164Ssam{ 581114164Ssam struct ifmedia_description *desc; 582114164Ssam struct ifmedia_type_to_subtype *ttos; 583114164Ssam int rval, i; 584114164Ssam 585114164Ssam /* Find the top-level interface type. */ 586114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 587114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 588114164Ssam if (type == desc->ifmt_word) 589114164Ssam break; 590114164Ssam if (desc->ifmt_string == NULL) 591114164Ssam errx(1, "unknown media mode 0x%x", type); 592114164Ssam 593114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 594114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 595114164Ssam if (rval != -1) 596114164Ssam return (rval); 597114164Ssam } 598114164Ssam return -1; 599114164Ssam} 600114164Ssam 601114164Ssamstatic int 60295005Simpget_media_options(int type, const char *val) 60325450Speter{ 60425450Speter struct ifmedia_description *desc; 60525450Speter struct ifmedia_type_to_subtype *ttos; 60625450Speter char *optlist, *optptr; 60725450Speter int option = 0, i, rval = 0; 60825450Speter 60925450Speter /* We muck with the string, so copy it. */ 61025450Speter optlist = strdup(val); 61125450Speter if (optlist == NULL) 61225450Speter err(1, "strdup"); 61325450Speter 61425450Speter /* Find the top-level interface type. */ 61525450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 61625450Speter desc->ifmt_string != NULL; desc++, ttos++) 61725450Speter if (type == desc->ifmt_word) 61825450Speter break; 61925450Speter if (desc->ifmt_string == NULL) 62025450Speter errx(1, "unknown media type 0x%x", type); 62125450Speter 62225450Speter /* 62325450Speter * Look up the options in the user-provided comma-separated 62425450Speter * list. 62525450Speter */ 62625450Speter optptr = optlist; 62725450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 62825450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 62925450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 63025450Speter if (option != -1) 63125450Speter break; 63225450Speter } 63325450Speter if (option == 0) 63425450Speter errx(1, "unknown option: %s", optptr); 63525450Speter rval |= option; 63625450Speter } 63725450Speter 63825450Speter free(optlist); 63925450Speter return (rval); 64025450Speter} 64125450Speter 64225450Speterstatic int 64395005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 64425450Speter{ 64525450Speter 64625450Speter for (; desc->ifmt_string != NULL; desc++) 64725450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 64825450Speter return (desc->ifmt_word); 64925450Speter 65025450Speter return (-1); 65125450Speter} 65225450Speter 65395005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 65425450Speter{ 65525450Speter struct ifmedia_description *desc; 65677385Sphk 65777385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 65877385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 65977385Sphk break; 66077385Sphk 66177385Sphk return desc; 66277385Sphk} 66377385Sphk 66495005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 66577385Sphk{ 66677385Sphk struct ifmedia_description *desc; 66725450Speter struct ifmedia_type_to_subtype *ttos; 66825450Speter 66925450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 67025450Speter desc->ifmt_string != NULL; desc++, ttos++) 67125450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 67225450Speter break; 67377385Sphk 67477385Sphk return ttos; 67577385Sphk} 67677385Sphk 67795005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 67895005Simp struct ifmedia_type_to_subtype *ttos) 67977385Sphk{ 68077385Sphk int i; 68177385Sphk struct ifmedia_description *desc; 68277385Sphk 68377385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 68477385Sphk if (ttos->subtypes[i].alias) 68577385Sphk continue; 68677385Sphk for (desc = ttos->subtypes[i].desc; 68777385Sphk desc->ifmt_string != NULL; desc++) { 68877385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 68977385Sphk return desc; 69077385Sphk } 69177385Sphk } 69277385Sphk 69377385Sphk return NULL; 69477385Sphk} 69577385Sphk 696114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 697114164Ssam struct ifmedia_type_to_subtype *ttos) 698114164Ssam{ 699114164Ssam int i; 700114164Ssam struct ifmedia_description *desc; 701114164Ssam 702114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 703114164Ssam if (ttos->modes[i].alias) 704114164Ssam continue; 705114164Ssam for (desc = ttos->modes[i].desc; 706114164Ssam desc->ifmt_string != NULL; desc++) { 707114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 708114164Ssam return desc; 709114164Ssam } 710114164Ssam } 711114164Ssam 712114164Ssam return NULL; 713114164Ssam} 714114164Ssam 71577385Sphkstatic void 71695005Simpprint_media_word(int ifmw, int print_toptype) 71777385Sphk{ 71877385Sphk struct ifmedia_description *desc; 71977385Sphk struct ifmedia_type_to_subtype *ttos; 72077385Sphk int seen_option = 0, i; 72177385Sphk 72277385Sphk /* Find the top-level interface type. */ 72377385Sphk desc = get_toptype_desc(ifmw); 72477385Sphk ttos = get_toptype_ttos(ifmw); 72525450Speter if (desc->ifmt_string == NULL) { 72625450Speter printf("<unknown type>"); 72725450Speter return; 72877385Sphk } else if (print_toptype) { 72977385Sphk printf("%s", desc->ifmt_string); 73025450Speter } 73125450Speter 73225450Speter /* 73325450Speter * Don't print the top-level type; it's not like we can 73425450Speter * change it, or anything. 73525450Speter */ 73625450Speter 73725450Speter /* Find subtype. */ 73877385Sphk desc = get_subtype_desc(ifmw, ttos); 739161536Sthomas if (desc == NULL) { 740161536Sthomas printf("<unknown subtype>"); 741161536Sthomas return; 742161536Sthomas } 74325450Speter 74477385Sphk if (print_toptype) 74577385Sphk putchar(' '); 74677385Sphk 74725450Speter printf("%s", desc->ifmt_string); 74825450Speter 749114164Ssam if (print_toptype) { 750114164Ssam desc = get_mode_desc(ifmw, ttos); 751116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 752114164Ssam printf(" mode %s", desc->ifmt_string); 753114164Ssam } 754114164Ssam 75525450Speter /* Find options. */ 75625450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 75725450Speter if (ttos->options[i].alias) 75825450Speter continue; 75925450Speter for (desc = ttos->options[i].desc; 76025450Speter desc->ifmt_string != NULL; desc++) { 76125450Speter if (ifmw & desc->ifmt_word) { 76225450Speter if (seen_option == 0) 76325450Speter printf(" <"); 76425450Speter printf("%s%s", seen_option++ ? "," : "", 76525450Speter desc->ifmt_string); 76625450Speter } 76725450Speter } 76825450Speter } 76925450Speter printf("%s", seen_option ? ">" : ""); 770166113Smarius 771166169Smarius if (print_toptype && IFM_INST(ifmw) != 0) 772166113Smarius printf(" instance %d", IFM_INST(ifmw)); 77325450Speter} 77425450Speter 77577385Sphkstatic void 77695005Simpprint_media_word_ifconfig(int ifmw) 77777385Sphk{ 77877385Sphk struct ifmedia_description *desc; 77977385Sphk struct ifmedia_type_to_subtype *ttos; 780215259Smarius int seen_option = 0, i; 78177385Sphk 78277385Sphk /* Find the top-level interface type. */ 78377385Sphk desc = get_toptype_desc(ifmw); 78477385Sphk ttos = get_toptype_ttos(ifmw); 78577385Sphk if (desc->ifmt_string == NULL) { 78677385Sphk printf("<unknown type>"); 78777385Sphk return; 78877385Sphk } 78977385Sphk 79077385Sphk /* 79177385Sphk * Don't print the top-level type; it's not like we can 79277385Sphk * change it, or anything. 79377385Sphk */ 79477385Sphk 79577385Sphk /* Find subtype. */ 79677385Sphk desc = get_subtype_desc(ifmw, ttos); 797161536Sthomas if (desc == NULL) { 798161536Sthomas printf("<unknown subtype>"); 799161536Sthomas return; 800161536Sthomas } 80177385Sphk 80277385Sphk printf("media %s", desc->ifmt_string); 80377385Sphk 804114164Ssam desc = get_mode_desc(ifmw, ttos); 805114164Ssam if (desc != NULL) 806114164Ssam printf(" mode %s", desc->ifmt_string); 807114164Ssam 80877385Sphk /* Find options. */ 80977385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 81077385Sphk if (ttos->options[i].alias) 81177385Sphk continue; 81277385Sphk for (desc = ttos->options[i].desc; 81377385Sphk desc->ifmt_string != NULL; desc++) { 81477385Sphk if (ifmw & desc->ifmt_word) { 815215259Smarius if (seen_option == 0) 816215259Smarius printf(" mediaopt "); 817215259Smarius printf("%s%s", seen_option++ ? "," : "", 818215259Smarius desc->ifmt_string); 81977385Sphk } 82077385Sphk } 82177385Sphk } 822166113Smarius 823166169Smarius if (IFM_INST(ifmw) != 0) 824166169Smarius printf(" instance %d", IFM_INST(ifmw)); 82577385Sphk} 82677385Sphk 82725450Speter/********************************************************************** 82825450Speter * ...until here. 82925450Speter **********************************************************************/ 830138593Ssam 831138593Ssamstatic struct cmd media_cmds[] = { 832138593Ssam DEF_CMD_ARG("media", setmedia), 833138593Ssam DEF_CMD_ARG("mode", setmediamode), 834138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 835138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 836166113Smarius DEF_CMD_ARG("inst", setmediainst), 837166113Smarius DEF_CMD_ARG("instance", setmediainst), 838138593Ssam}; 839138593Ssamstatic struct afswtch af_media = { 840138593Ssam .af_name = "af_media", 841138593Ssam .af_af = AF_UNSPEC, 842139494Ssam .af_other_status = media_status, 843138593Ssam}; 844138593Ssam 845138593Ssamstatic __constructor void 846138593Ssamifmedia_ctor(void) 847138593Ssam{ 848194799Sdelphij size_t i; 849138593Ssam 850289986Sngie for (i = 0; i < nitems(media_cmds); i++) 851138593Ssam cmd_register(&media_cmds[i]); 852138593Ssam af_register(&af_media); 853138593Ssam} 854