125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: stable/11/sbin/ifconfig/ifmedia.c 352650 2019-09-24 06:37:01Z kib $ */ 325450Speter 4331722Seadler/* 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> 81352650Skib#include <stdbool.h> 8225450Speter#include <stdio.h> 8325450Speter#include <stdlib.h> 8425450Speter#include <string.h> 8525450Speter#include <unistd.h> 8625450Speter 8725450Speter#include "ifconfig.h" 8825450Speter 8995005Simpstatic void domediaopt(const char *, int, int); 9095005Simpstatic int get_media_subtype(int, const char *); 91114164Ssamstatic int get_media_mode(int, const char *); 9295005Simpstatic int get_media_options(int, const char *); 9395005Simpstatic int lookup_media_word(struct ifmedia_description *, const char *); 9495005Simpstatic void print_media_word(int, int); 9595005Simpstatic void print_media_word_ifconfig(int); 9625450Speter 9795005Simpstatic struct ifmedia_description *get_toptype_desc(int); 9895005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 9995005Simpstatic struct ifmedia_description *get_subtype_desc(int, 10095005Simp struct ifmedia_type_to_subtype *ttos); 10177385Sphk 102178354Ssam#define IFM_OPMODE(x) \ 103178354Ssam ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 104195618Srpaulo IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 105195618Srpaulo IFM_IEEE80211_MBSS)) 106178354Ssam#define IFM_IEEE80211_STA 0 107178354Ssam 108138593Ssamstatic void 109139494Ssammedia_status(int s) 11025450Speter{ 11125450Speter struct ifmediareq ifmr; 112352650Skib struct ifdownreason ifdr; 11325450Speter int *media_list, i; 114352650Skib bool no_carrier, xmedia; 11525450Speter 11625450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 117299873Struckman (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 118352650Skib xmedia = true; 11925450Speter 120281236Serj /* 121281236Serj * Check if interface supports extended media types. 122281236Serj */ 123281236Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) 124352650Skib xmedia = false; 125352650Skib if (!xmedia && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 12625450Speter /* 12725450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 12825450Speter */ 12925450Speter return; 13025450Speter } 13125450Speter 13225450Speter if (ifmr.ifm_count == 0) { 13325450Speter warnx("%s: no media types?", name); 13425450Speter return; 13525450Speter } 13625450Speter 13725450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 13825450Speter if (media_list == NULL) 13925450Speter err(1, "malloc"); 14025450Speter ifmr.ifm_ulist = media_list; 14125450Speter 142281236Serj if (xmedia) { 143281236Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) 144281236Serj err(1, "SIOCGIFXMEDIA"); 145281236Serj } else { 146281236Serj if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 147281236Serj err(1, "SIOCGIFMEDIA"); 148281236Serj } 14925450Speter 15025450Speter printf("\tmedia: "); 15177385Sphk print_media_word(ifmr.ifm_current, 1); 15225450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 15325450Speter putchar(' '); 15425450Speter putchar('('); 15577385Sphk print_media_word(ifmr.ifm_active, 0); 15625450Speter putchar(')'); 15725450Speter } 15825450Speter 15977385Sphk putchar('\n'); 16077385Sphk 16125450Speter if (ifmr.ifm_status & IFM_AVALID) { 162352650Skib no_carrier = false; 16377385Sphk printf("\tstatus: "); 16425450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 16525450Speter case IFM_ETHER: 166161536Sthomas case IFM_ATM: 16725450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16825450Speter printf("active"); 16925450Speter else 170352650Skib no_carrier = true; 17125450Speter break; 17225450Speter 17325450Speter case IFM_FDDI: 17425450Speter case IFM_TOKEN: 17525450Speter if (ifmr.ifm_status & IFM_ACTIVE) 17625450Speter printf("inserted"); 17725450Speter else 17825450Speter printf("no ring"); 17925450Speter break; 180114232Sharti 18177217Sphk case IFM_IEEE80211: 182178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 183178354Ssam /* NB: only sta mode associates */ 184178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 185178354Ssam printf("associated"); 186178354Ssam else 187178354Ssam printf("running"); 188178354Ssam } else 189352650Skib no_carrier = true; 19077217Sphk break; 19125450Speter } 192352650Skib if (no_carrier) { 193352650Skib printf("no carrier"); 194352650Skib memset(&ifdr, 0, sizeof(ifdr)); 195352650Skib strlcpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); 196352650Skib if (ioctl(s, SIOCGIFDOWNREASON, (caddr_t)&ifdr) == 0) { 197352650Skib switch (ifdr.ifdr_reason) { 198352650Skib case IFDR_REASON_MSG: 199352650Skib printf(" (%s)", ifdr.ifdr_msg); 200352650Skib break; 201352650Skib case IFDR_REASON_VENDOR: 202352650Skib printf(" (vendor code %d)", 203352650Skib ifdr.ifdr_vendor); 204352650Skib break; 205352650Skib default: 206352650Skib break; 207352650Skib } 208352650Skib } 209352650Skib } 21085853Syar putchar('\n'); 21125450Speter } 21225450Speter 21377385Sphk if (ifmr.ifm_count > 0 && supmedia) { 21477385Sphk printf("\tsupported media:\n"); 21525450Speter for (i = 0; i < ifmr.ifm_count; i++) { 21677385Sphk printf("\t\t"); 21777385Sphk print_media_word_ifconfig(media_list[i]); 21877385Sphk putchar('\n'); 21925450Speter } 22025450Speter } 22125450Speter 22225450Speter free(media_list); 22325450Speter} 22425450Speter 225170531Ssamstruct ifmediareq * 226170531Ssamifmedia_getstate(int s) 22725450Speter{ 228140913Sambrisko static struct ifmediareq *ifmr = NULL; 229140913Sambrisko int *mwords; 230281236Serj int xmedia = 1; 23125450Speter 232140913Sambrisko if (ifmr == NULL) { 233140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 234140913Sambrisko if (ifmr == NULL) 235140913Sambrisko err(1, "malloc"); 23625450Speter 237140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 238299873Struckman (void) strlcpy(ifmr->ifm_name, name, 239140913Sambrisko sizeof(ifmr->ifm_name)); 240140913Sambrisko 241140913Sambrisko ifmr->ifm_count = 0; 242140913Sambrisko ifmr->ifm_ulist = NULL; 243140913Sambrisko 24425450Speter /* 245140913Sambrisko * We must go through the motions of reading all 246140913Sambrisko * supported media because we need to know both 247140913Sambrisko * the current media type and the top-level type. 24825450Speter */ 249140913Sambrisko 250281236Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) { 251281236Serj xmedia = 0; 252281236Serj } 253281236Serj if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 25425450Speter err(1, "SIOCGIFMEDIA"); 255140913Sambrisko } 256140913Sambrisko 257140913Sambrisko if (ifmr->ifm_count == 0) 258140913Sambrisko errx(1, "%s: no media types?", name); 259140913Sambrisko 260140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 261140913Sambrisko if (mwords == NULL) 262140913Sambrisko err(1, "malloc"); 263140913Sambrisko 264140913Sambrisko ifmr->ifm_ulist = mwords; 265281236Serj if (xmedia) { 266281236Serj if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) 267281236Serj err(1, "SIOCGIFXMEDIA"); 268281236Serj } else { 269281236Serj if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 270281236Serj err(1, "SIOCGIFMEDIA"); 271281236Serj } 27225450Speter } 27325450Speter 274140913Sambrisko return ifmr; 275140913Sambrisko} 27625450Speter 277140913Sambriskostatic void 278140913Sambriskosetifmediacallback(int s, void *arg) 279140913Sambrisko{ 280140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 281140913Sambrisko static int did_it = 0; 282140913Sambrisko 283140913Sambrisko if (!did_it) { 284154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 285140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 286140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 287140913Sambrisko free(ifmr->ifm_ulist); 288140913Sambrisko free(ifmr); 289140913Sambrisko did_it = 1; 290140913Sambrisko } 291140913Sambrisko} 292140913Sambrisko 293140913Sambriskostatic void 294140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 295140913Sambrisko{ 296140913Sambrisko struct ifmediareq *ifmr; 297140913Sambrisko int subtype; 298140913Sambrisko 299170531Ssam ifmr = ifmedia_getstate(s); 300140913Sambrisko 30125450Speter /* 30225450Speter * We are primarily concerned with the top-level type. 30325450Speter * However, "current" may be only IFM_NONE, so we just look 30425450Speter * for the top-level type in the first "supported type" 30525450Speter * entry. 30625450Speter * 30725450Speter * (I'm assuming that all supported media types for a given 30825450Speter * interface will be the same top-level type..) 30925450Speter */ 310140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 31125450Speter 312299873Struckman strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 313221954Smarius ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | 314140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 31525450Speter 316140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 317140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 31825450Speter} 31925450Speter 320138593Ssamstatic void 32195005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 32225450Speter{ 32325450Speter 32425450Speter domediaopt(val, 0, s); 32525450Speter} 32625450Speter 327138593Ssamstatic void 32895005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 32925450Speter{ 33025450Speter 33125450Speter domediaopt(val, 1, s); 33225450Speter} 33325450Speter 33425450Speterstatic void 33595005Simpdomediaopt(const char *val, int clear, int s) 33625450Speter{ 337140913Sambrisko struct ifmediareq *ifmr; 338140913Sambrisko int options; 33925450Speter 340170531Ssam ifmr = ifmedia_getstate(s); 34125450Speter 342140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 34325450Speter 344299873Struckman strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 345140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 34625450Speter if (clear) 34725450Speter ifr.ifr_media &= ~options; 348165359Sjkim else { 349165359Sjkim if (options & IFM_HDX) { 350165359Sjkim ifr.ifr_media &= ~IFM_FDX; 351165359Sjkim options &= ~IFM_HDX; 352165359Sjkim } 35325450Speter ifr.ifr_media |= options; 354165359Sjkim } 355140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 356140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 35725450Speter} 35825450Speter 359166113Smariusstatic void 360166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 361166113Smarius{ 362166113Smarius struct ifmediareq *ifmr; 363166113Smarius int inst; 364114164Ssam 365170531Ssam ifmr = ifmedia_getstate(s); 366166113Smarius 367166113Smarius inst = atoi(val); 368194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 369166113Smarius errx(1, "invalid media instance: %s", val); 370166113Smarius 371299873Struckman strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 372166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 373166113Smarius 374166113Smarius ifmr->ifm_current = ifr.ifr_media; 375166113Smarius callback_register(setifmediacallback, (void *)ifmr); 376166113Smarius} 377166113Smarius 378138593Ssamstatic void 379114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 380114164Ssam{ 381140913Sambrisko struct ifmediareq *ifmr; 382140913Sambrisko int mode; 383114164Ssam 384170531Ssam ifmr = ifmedia_getstate(s); 385114164Ssam 386140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 387114164Ssam 388299873Struckman strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 389140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 390114164Ssam 391140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 392140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 393114164Ssam} 394114164Ssam 39525450Speter/********************************************************************** 39625450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 39725450Speter **********************************************************************/ 39825450Speter 39925450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 40025450Speter IFM_TYPE_DESCRIPTIONS; 40125450Speter 40225450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 40325450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 40425450Speter 40525450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 40625450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 40725450Speter 40825450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 40925450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 41025450Speter 41125450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 41225450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 41325450Speter 41425450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 41525450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 41625450Speter 41725450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 41825450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 41925450Speter 42025450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 42125450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 42225450Speter 42325450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 42425450Speter IFM_SUBTYPE_FDDI_ALIASES; 42525450Speter 42625450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 42725450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 42825450Speter 42977217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 43077217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 43177217Sphk 43277217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 43377217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 43477217Sphk 43577217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 43677217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 43777217Sphk 438114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 439114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 440114164Ssam 441116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 442116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 443116820Ssam 444114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 445114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 446114232Sharti 447114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 448114232Sharti IFM_SUBTYPE_ATM_ALIASES; 449114232Sharti 450114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 451114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 452114232Sharti 45325450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 45425450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 45525450Speter 45625450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 45725450Speter IFM_SUBTYPE_SHARED_ALIASES; 45825450Speter 45925450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 46025450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 46125450Speter 462217013Smariusstatic struct ifmedia_description ifm_shared_option_aliases[] = 463217013Smarius IFM_SHARED_OPTION_ALIASES; 464217013Smarius 46525450Speterstruct ifmedia_type_to_subtype { 46625450Speter struct { 46725450Speter struct ifmedia_description *desc; 46825450Speter int alias; 46925450Speter } subtypes[5]; 47025450Speter struct { 47125450Speter struct ifmedia_description *desc; 47225450Speter int alias; 473217013Smarius } options[4]; 474114164Ssam struct { 475114164Ssam struct ifmedia_description *desc; 476114164Ssam int alias; 477116820Ssam } modes[3]; 47825450Speter}; 47925450Speter 48025450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 48125450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 48225450Speter { 48325450Speter { 48425450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 48525450Speter { &ifm_subtype_shared_aliases[0], 1 }, 48625450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 48725450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 48825450Speter { NULL, 0 }, 48925450Speter }, 49025450Speter { 49125450Speter { &ifm_shared_option_descriptions[0], 0 }, 492217013Smarius { &ifm_shared_option_aliases[0], 1 }, 49377217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 49425450Speter { NULL, 0 }, 49525450Speter }, 496114164Ssam { 497114164Ssam { NULL, 0 }, 498114164Ssam }, 49925450Speter }, 50025450Speter { 50125450Speter { 50225450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 50325450Speter { &ifm_subtype_shared_aliases[0], 1 }, 50425450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 50525450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 50625450Speter { NULL, 0 }, 50725450Speter }, 50825450Speter { 50925450Speter { &ifm_shared_option_descriptions[0], 0 }, 510217013Smarius { &ifm_shared_option_aliases[0], 1 }, 51177217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 51225450Speter { NULL, 0 }, 51325450Speter }, 514114164Ssam { 515114164Ssam { NULL, 0 }, 516114164Ssam }, 51725450Speter }, 51825450Speter { 51925450Speter { 52025450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 52125450Speter { &ifm_subtype_shared_aliases[0], 1 }, 52225450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 52325450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 52425450Speter { NULL, 0 }, 52525450Speter }, 52625450Speter { 52725450Speter { &ifm_shared_option_descriptions[0], 0 }, 528217013Smarius { &ifm_shared_option_aliases[0], 1 }, 52977217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 53025450Speter { NULL, 0 }, 53125450Speter }, 532114164Ssam { 533114164Ssam { NULL, 0 }, 534114164Ssam }, 53525450Speter }, 53677217Sphk { 53777217Sphk { 53877217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 53977217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 54077217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 54177217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 54277217Sphk { NULL, 0 }, 54377217Sphk }, 54477217Sphk { 54577217Sphk { &ifm_shared_option_descriptions[0], 0 }, 546217013Smarius { &ifm_shared_option_aliases[0], 1 }, 54777217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 54877217Sphk { NULL, 0 }, 54977217Sphk }, 550114164Ssam { 551114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 552116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 553114164Ssam { NULL, 0 }, 554114164Ssam }, 55577217Sphk }, 556114232Sharti { 557114232Sharti { 558114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 559114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 560114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 561114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 562114232Sharti { NULL, 0 }, 563114232Sharti }, 564114232Sharti { 565114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 566217013Smarius { &ifm_shared_option_aliases[0], 1 }, 567114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 568114232Sharti { NULL, 0 }, 569114232Sharti }, 570114232Sharti { 571114232Sharti { NULL, 0 }, 572114232Sharti }, 573114232Sharti }, 57425450Speter}; 57525450Speter 57625450Speterstatic int 57795005Simpget_media_subtype(int type, const char *val) 57825450Speter{ 57925450Speter struct ifmedia_description *desc; 58025450Speter struct ifmedia_type_to_subtype *ttos; 58125450Speter int rval, i; 58225450Speter 58325450Speter /* Find the top-level interface type. */ 58425450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 58525450Speter desc->ifmt_string != NULL; desc++, ttos++) 58625450Speter if (type == desc->ifmt_word) 58725450Speter break; 58825450Speter if (desc->ifmt_string == NULL) 58925450Speter errx(1, "unknown media type 0x%x", type); 59025450Speter 59125450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 59225450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 59325450Speter if (rval != -1) 59425450Speter return (rval); 59525450Speter } 59625450Speter errx(1, "unknown media subtype: %s", val); 597114164Ssam /*NOTREACHED*/ 59825450Speter} 59925450Speter 60025450Speterstatic int 601114164Ssamget_media_mode(int type, const char *val) 602114164Ssam{ 603114164Ssam struct ifmedia_description *desc; 604114164Ssam struct ifmedia_type_to_subtype *ttos; 605114164Ssam int rval, i; 606114164Ssam 607114164Ssam /* Find the top-level interface type. */ 608114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 609114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 610114164Ssam if (type == desc->ifmt_word) 611114164Ssam break; 612114164Ssam if (desc->ifmt_string == NULL) 613114164Ssam errx(1, "unknown media mode 0x%x", type); 614114164Ssam 615114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 616114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 617114164Ssam if (rval != -1) 618114164Ssam return (rval); 619114164Ssam } 620114164Ssam return -1; 621114164Ssam} 622114164Ssam 623114164Ssamstatic int 62495005Simpget_media_options(int type, const char *val) 62525450Speter{ 62625450Speter struct ifmedia_description *desc; 62725450Speter struct ifmedia_type_to_subtype *ttos; 62825450Speter char *optlist, *optptr; 62925450Speter int option = 0, i, rval = 0; 63025450Speter 63125450Speter /* We muck with the string, so copy it. */ 63225450Speter optlist = strdup(val); 63325450Speter if (optlist == NULL) 63425450Speter err(1, "strdup"); 63525450Speter 63625450Speter /* Find the top-level interface type. */ 63725450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 63825450Speter desc->ifmt_string != NULL; desc++, ttos++) 63925450Speter if (type == desc->ifmt_word) 64025450Speter break; 64125450Speter if (desc->ifmt_string == NULL) 64225450Speter errx(1, "unknown media type 0x%x", type); 64325450Speter 64425450Speter /* 64525450Speter * Look up the options in the user-provided comma-separated 64625450Speter * list. 64725450Speter */ 64825450Speter optptr = optlist; 64925450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 65025450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 65125450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 65225450Speter if (option != -1) 65325450Speter break; 65425450Speter } 65525450Speter if (option == 0) 65625450Speter errx(1, "unknown option: %s", optptr); 65725450Speter rval |= option; 65825450Speter } 65925450Speter 66025450Speter free(optlist); 66125450Speter return (rval); 66225450Speter} 66325450Speter 66425450Speterstatic int 66595005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 66625450Speter{ 66725450Speter 66825450Speter for (; desc->ifmt_string != NULL; desc++) 66925450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 67025450Speter return (desc->ifmt_word); 67125450Speter 67225450Speter return (-1); 67325450Speter} 67425450Speter 67595005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 67625450Speter{ 67725450Speter struct ifmedia_description *desc; 67877385Sphk 67977385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 68077385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 68177385Sphk break; 68277385Sphk 68377385Sphk return desc; 68477385Sphk} 68577385Sphk 68695005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 68777385Sphk{ 68877385Sphk struct ifmedia_description *desc; 68925450Speter struct ifmedia_type_to_subtype *ttos; 69025450Speter 69125450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 69225450Speter desc->ifmt_string != NULL; desc++, ttos++) 69325450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 69425450Speter break; 69577385Sphk 69677385Sphk return ttos; 69777385Sphk} 69877385Sphk 69995005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 70095005Simp struct ifmedia_type_to_subtype *ttos) 70177385Sphk{ 70277385Sphk int i; 70377385Sphk struct ifmedia_description *desc; 70477385Sphk 70577385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 70677385Sphk if (ttos->subtypes[i].alias) 70777385Sphk continue; 70877385Sphk for (desc = ttos->subtypes[i].desc; 70977385Sphk desc->ifmt_string != NULL; desc++) { 71077385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 71177385Sphk return desc; 71277385Sphk } 71377385Sphk } 71477385Sphk 71577385Sphk return NULL; 71677385Sphk} 71777385Sphk 718114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 719114164Ssam struct ifmedia_type_to_subtype *ttos) 720114164Ssam{ 721114164Ssam int i; 722114164Ssam struct ifmedia_description *desc; 723114164Ssam 724114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 725114164Ssam if (ttos->modes[i].alias) 726114164Ssam continue; 727114164Ssam for (desc = ttos->modes[i].desc; 728114164Ssam desc->ifmt_string != NULL; desc++) { 729114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 730114164Ssam return desc; 731114164Ssam } 732114164Ssam } 733114164Ssam 734114164Ssam return NULL; 735114164Ssam} 736114164Ssam 73777385Sphkstatic void 73895005Simpprint_media_word(int ifmw, int print_toptype) 73977385Sphk{ 74077385Sphk struct ifmedia_description *desc; 74177385Sphk struct ifmedia_type_to_subtype *ttos; 74277385Sphk int seen_option = 0, i; 74377385Sphk 74477385Sphk /* Find the top-level interface type. */ 74577385Sphk desc = get_toptype_desc(ifmw); 74677385Sphk ttos = get_toptype_ttos(ifmw); 74725450Speter if (desc->ifmt_string == NULL) { 74825450Speter printf("<unknown type>"); 74925450Speter return; 75077385Sphk } else if (print_toptype) { 75177385Sphk printf("%s", desc->ifmt_string); 75225450Speter } 75325450Speter 75425450Speter /* 75525450Speter * Don't print the top-level type; it's not like we can 75625450Speter * change it, or anything. 75725450Speter */ 75825450Speter 75925450Speter /* Find subtype. */ 76077385Sphk desc = get_subtype_desc(ifmw, ttos); 761161536Sthomas if (desc == NULL) { 762161536Sthomas printf("<unknown subtype>"); 763161536Sthomas return; 764161536Sthomas } 76525450Speter 76677385Sphk if (print_toptype) 76777385Sphk putchar(' '); 76877385Sphk 76925450Speter printf("%s", desc->ifmt_string); 77025450Speter 771114164Ssam if (print_toptype) { 772114164Ssam desc = get_mode_desc(ifmw, ttos); 773116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 774114164Ssam printf(" mode %s", desc->ifmt_string); 775114164Ssam } 776114164Ssam 77725450Speter /* Find options. */ 77825450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 77925450Speter if (ttos->options[i].alias) 78025450Speter continue; 78125450Speter for (desc = ttos->options[i].desc; 78225450Speter desc->ifmt_string != NULL; desc++) { 78325450Speter if (ifmw & desc->ifmt_word) { 78425450Speter if (seen_option == 0) 78525450Speter printf(" <"); 78625450Speter printf("%s%s", seen_option++ ? "," : "", 78725450Speter desc->ifmt_string); 78825450Speter } 78925450Speter } 79025450Speter } 79125450Speter printf("%s", seen_option ? ">" : ""); 792166113Smarius 793166169Smarius if (print_toptype && IFM_INST(ifmw) != 0) 794166113Smarius printf(" instance %d", IFM_INST(ifmw)); 79525450Speter} 79625450Speter 79777385Sphkstatic void 79895005Simpprint_media_word_ifconfig(int ifmw) 79977385Sphk{ 80077385Sphk struct ifmedia_description *desc; 80177385Sphk struct ifmedia_type_to_subtype *ttos; 802215259Smarius int seen_option = 0, i; 80377385Sphk 80477385Sphk /* Find the top-level interface type. */ 80577385Sphk desc = get_toptype_desc(ifmw); 80677385Sphk ttos = get_toptype_ttos(ifmw); 80777385Sphk if (desc->ifmt_string == NULL) { 80877385Sphk printf("<unknown type>"); 80977385Sphk return; 81077385Sphk } 81177385Sphk 81277385Sphk /* 81377385Sphk * Don't print the top-level type; it's not like we can 81477385Sphk * change it, or anything. 81577385Sphk */ 81677385Sphk 81777385Sphk /* Find subtype. */ 81877385Sphk desc = get_subtype_desc(ifmw, ttos); 819161536Sthomas if (desc == NULL) { 820161536Sthomas printf("<unknown subtype>"); 821161536Sthomas return; 822161536Sthomas } 82377385Sphk 82477385Sphk printf("media %s", desc->ifmt_string); 82577385Sphk 826114164Ssam desc = get_mode_desc(ifmw, ttos); 827114164Ssam if (desc != NULL) 828114164Ssam printf(" mode %s", desc->ifmt_string); 829114164Ssam 83077385Sphk /* Find options. */ 83177385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 83277385Sphk if (ttos->options[i].alias) 83377385Sphk continue; 83477385Sphk for (desc = ttos->options[i].desc; 83577385Sphk desc->ifmt_string != NULL; desc++) { 83677385Sphk if (ifmw & desc->ifmt_word) { 837215259Smarius if (seen_option == 0) 838215259Smarius printf(" mediaopt "); 839215259Smarius printf("%s%s", seen_option++ ? "," : "", 840215259Smarius desc->ifmt_string); 84177385Sphk } 84277385Sphk } 84377385Sphk } 844166113Smarius 845166169Smarius if (IFM_INST(ifmw) != 0) 846166169Smarius printf(" instance %d", IFM_INST(ifmw)); 84777385Sphk} 84877385Sphk 84925450Speter/********************************************************************** 85025450Speter * ...until here. 85125450Speter **********************************************************************/ 852138593Ssam 853138593Ssamstatic struct cmd media_cmds[] = { 854138593Ssam DEF_CMD_ARG("media", setmedia), 855138593Ssam DEF_CMD_ARG("mode", setmediamode), 856138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 857138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 858166113Smarius DEF_CMD_ARG("inst", setmediainst), 859166113Smarius DEF_CMD_ARG("instance", setmediainst), 860138593Ssam}; 861138593Ssamstatic struct afswtch af_media = { 862138593Ssam .af_name = "af_media", 863138593Ssam .af_af = AF_UNSPEC, 864139494Ssam .af_other_status = media_status, 865138593Ssam}; 866138593Ssam 867138593Ssamstatic __constructor void 868138593Ssamifmedia_ctor(void) 869138593Ssam{ 870194799Sdelphij size_t i; 871138593Ssam 872288305Sngie for (i = 0; i < nitems(media_cmds); i++) 873138593Ssam cmd_register(&media_cmds[i]); 874138593Ssam af_register(&af_media); 875138593Ssam} 876