125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD$ */ 325450Speter 425450Speter/* 525450Speter * Copyright (c) 1997 Jason R. Thorpe. 625450Speter * All rights reserved. 725450Speter * 825450Speter * Redistribution and use in source and binary forms, with or without 925450Speter * modification, are permitted provided that the following conditions 1025450Speter * are met: 1125450Speter * 1. Redistributions of source code must retain the above copyright 1225450Speter * notice, this list of conditions and the following disclaimer. 1325450Speter * 2. Redistributions in binary form must reproduce the above copyright 1425450Speter * notice, this list of conditions and the following disclaimer in the 1525450Speter * documentation and/or other materials provided with the distribution. 1625450Speter * 3. All advertising materials mentioning features or use of this software 1725450Speter * must display the following acknowledgement: 1825450Speter * This product includes software developed for the NetBSD Project 1925450Speter * by Jason R. Thorpe. 2025450Speter * 4. The name of the author may not be used to endorse or promote products 2125450Speter * derived from this software without specific prior written permission. 2225450Speter * 2325450Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2425450Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2525450Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2625450Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2725450Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2825450Speter * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2925450Speter * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 3025450Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3125450Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3225450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3325450Speter * SUCH DAMAGE. 3425450Speter */ 3525450Speter 3625450Speter/* 3725450Speter * Copyright (c) 1983, 1993 3825450Speter * The Regents of the University of California. All rights reserved. 3925450Speter * 4025450Speter * Redistribution and use in source and binary forms, with or without 4125450Speter * modification, are permitted provided that the following conditions 4225450Speter * are met: 4325450Speter * 1. Redistributions of source code must retain the above copyright 4425450Speter * notice, this list of conditions and the following disclaimer. 4525450Speter * 2. Redistributions in binary form must reproduce the above copyright 4625450Speter * notice, this list of conditions and the following disclaimer in the 4725450Speter * documentation and/or other materials provided with the distribution. 4825450Speter * 4. Neither the name of the University nor the names of its contributors 4925450Speter * may be used to endorse or promote products derived from this software 5025450Speter * without specific prior written permission. 5125450Speter * 5225450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5325450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5425450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5525450Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5625450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5725450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5825450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5925450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6025450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6125450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6225450Speter * SUCH DAMAGE. 6325450Speter */ 6425450Speter 6525450Speter#include <sys/param.h> 6625450Speter#include <sys/ioctl.h> 6725450Speter#include <sys/socket.h> 6825450Speter#include <sys/sysctl.h> 6925450Speter#include <sys/time.h> 7025450Speter 7125450Speter#include <net/if.h> 7225450Speter#include <net/if_dl.h> 7325450Speter#include <net/if_types.h> 7425450Speter#include <net/if_media.h> 7525450Speter#include <net/route.h> 7625450Speter 7725450Speter#include <ctype.h> 7825450Speter#include <err.h> 7925450Speter#include <errno.h> 8025450Speter#include <fcntl.h> 8125450Speter#include <stdio.h> 8225450Speter#include <stdlib.h> 8325450Speter#include <string.h> 8425450Speter#include <unistd.h> 8525450Speter 8625450Speter#include "ifconfig.h" 8725450Speter 8895005Simpstatic void domediaopt(const char *, int, int); 8995005Simpstatic int get_media_subtype(int, const char *); 90114164Ssamstatic int get_media_mode(int, const char *); 9195005Simpstatic int get_media_options(int, const char *); 9295005Simpstatic int lookup_media_word(struct ifmedia_description *, const char *); 9395005Simpstatic void print_media_word(int, int); 9495005Simpstatic void print_media_word_ifconfig(int); 9525450Speter 9695005Simpstatic struct ifmedia_description *get_toptype_desc(int); 9795005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 9895005Simpstatic struct ifmedia_description *get_subtype_desc(int, 9995005Simp struct ifmedia_type_to_subtype *ttos); 10077385Sphk 101178354Ssam#define IFM_OPMODE(x) \ 102178354Ssam ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 103195618Srpaulo IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 104195618Srpaulo IFM_IEEE80211_MBSS)) 105178354Ssam#define IFM_IEEE80211_STA 0 106178354Ssam 107138593Ssamstatic void 108139494Ssammedia_status(int s) 10925450Speter{ 11025450Speter struct ifmediareq ifmr; 11125450Speter int *media_list, i; 11225450Speter 11325450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11425450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11525450Speter 11625450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 11725450Speter /* 11825450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 11925450Speter */ 12025450Speter return; 12125450Speter } 12225450Speter 12325450Speter if (ifmr.ifm_count == 0) { 12425450Speter warnx("%s: no media types?", name); 12525450Speter return; 12625450Speter } 12725450Speter 12825450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 12925450Speter if (media_list == NULL) 13025450Speter err(1, "malloc"); 13125450Speter ifmr.ifm_ulist = media_list; 13225450Speter 13325450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13425450Speter err(1, "SIOCGIFMEDIA"); 13525450Speter 13625450Speter printf("\tmedia: "); 13777385Sphk print_media_word(ifmr.ifm_current, 1); 13825450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 13925450Speter putchar(' '); 14025450Speter putchar('('); 14177385Sphk print_media_word(ifmr.ifm_active, 0); 14225450Speter putchar(')'); 14325450Speter } 14425450Speter 14577385Sphk putchar('\n'); 14677385Sphk 14725450Speter if (ifmr.ifm_status & IFM_AVALID) { 14877385Sphk printf("\tstatus: "); 14925450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 15025450Speter case IFM_ETHER: 151161536Sthomas case IFM_ATM: 15225450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15325450Speter printf("active"); 15425450Speter else 15525450Speter printf("no carrier"); 15625450Speter break; 15725450Speter 15825450Speter case IFM_FDDI: 15925450Speter case IFM_TOKEN: 16025450Speter if (ifmr.ifm_status & IFM_ACTIVE) 16125450Speter printf("inserted"); 16225450Speter else 16325450Speter printf("no ring"); 16425450Speter break; 165114232Sharti 16677217Sphk case IFM_IEEE80211: 167178354Ssam if (ifmr.ifm_status & IFM_ACTIVE) { 168178354Ssam /* NB: only sta mode associates */ 169178354Ssam if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 170178354Ssam printf("associated"); 171178354Ssam else 172178354Ssam printf("running"); 173178354Ssam } else 17477217Sphk printf("no carrier"); 17577217Sphk break; 17625450Speter } 17785853Syar putchar('\n'); 17825450Speter } 17925450Speter 18077385Sphk if (ifmr.ifm_count > 0 && supmedia) { 18177385Sphk printf("\tsupported media:\n"); 18225450Speter for (i = 0; i < ifmr.ifm_count; i++) { 18377385Sphk printf("\t\t"); 18477385Sphk print_media_word_ifconfig(media_list[i]); 18577385Sphk putchar('\n'); 18625450Speter } 18725450Speter } 18825450Speter 18925450Speter free(media_list); 19025450Speter} 19125450Speter 192170531Ssamstruct ifmediareq * 193170531Ssamifmedia_getstate(int s) 19425450Speter{ 195140913Sambrisko static struct ifmediareq *ifmr = NULL; 196140913Sambrisko int *mwords; 19725450Speter 198140913Sambrisko if (ifmr == NULL) { 199140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 200140913Sambrisko if (ifmr == NULL) 201140913Sambrisko err(1, "malloc"); 20225450Speter 203140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 204140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 205140913Sambrisko sizeof(ifmr->ifm_name)); 206140913Sambrisko 207140913Sambrisko ifmr->ifm_count = 0; 208140913Sambrisko ifmr->ifm_ulist = NULL; 209140913Sambrisko 21025450Speter /* 211140913Sambrisko * We must go through the motions of reading all 212140913Sambrisko * supported media because we need to know both 213140913Sambrisko * the current media type and the top-level type. 21425450Speter */ 215140913Sambrisko 216140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 21725450Speter err(1, "SIOCGIFMEDIA"); 218140913Sambrisko } 219140913Sambrisko 220140913Sambrisko if (ifmr->ifm_count == 0) 221140913Sambrisko errx(1, "%s: no media types?", name); 222140913Sambrisko 223140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 224140913Sambrisko if (mwords == NULL) 225140913Sambrisko err(1, "malloc"); 226140913Sambrisko 227140913Sambrisko ifmr->ifm_ulist = mwords; 228140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 229140913Sambrisko err(1, "SIOCGIFMEDIA"); 23025450Speter } 23125450Speter 232140913Sambrisko return ifmr; 233140913Sambrisko} 23425450Speter 235140913Sambriskostatic void 236140913Sambriskosetifmediacallback(int s, void *arg) 237140913Sambrisko{ 238140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 239140913Sambrisko static int did_it = 0; 240140913Sambrisko 241140913Sambrisko if (!did_it) { 242154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 243140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 244140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 245140913Sambrisko free(ifmr->ifm_ulist); 246140913Sambrisko free(ifmr); 247140913Sambrisko did_it = 1; 248140913Sambrisko } 249140913Sambrisko} 250140913Sambrisko 251140913Sambriskostatic void 252140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 253140913Sambrisko{ 254140913Sambrisko struct ifmediareq *ifmr; 255140913Sambrisko int subtype; 256140913Sambrisko 257170531Ssam ifmr = ifmedia_getstate(s); 258140913Sambrisko 25925450Speter /* 26025450Speter * We are primarily concerned with the top-level type. 26125450Speter * However, "current" may be only IFM_NONE, so we just look 26225450Speter * for the top-level type in the first "supported type" 26325450Speter * entry. 26425450Speter * 26525450Speter * (I'm assuming that all supported media types for a given 26625450Speter * interface will be the same top-level type..) 26725450Speter */ 268140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 26925450Speter 27025450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 271221954Smarius ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | 272140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 27325450Speter 274140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 275140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 27625450Speter} 27725450Speter 278138593Ssamstatic void 27995005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28025450Speter{ 28125450Speter 28225450Speter domediaopt(val, 0, s); 28325450Speter} 28425450Speter 285138593Ssamstatic void 28695005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 28725450Speter{ 28825450Speter 28925450Speter domediaopt(val, 1, s); 29025450Speter} 29125450Speter 29225450Speterstatic void 29395005Simpdomediaopt(const char *val, int clear, int s) 29425450Speter{ 295140913Sambrisko struct ifmediareq *ifmr; 296140913Sambrisko int options; 29725450Speter 298170531Ssam ifmr = ifmedia_getstate(s); 29925450Speter 300140913Sambrisko options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 30125450Speter 30225450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 303140913Sambrisko ifr.ifr_media = ifmr->ifm_current; 30425450Speter if (clear) 30525450Speter ifr.ifr_media &= ~options; 306165359Sjkim else { 307165359Sjkim if (options & IFM_HDX) { 308165359Sjkim ifr.ifr_media &= ~IFM_FDX; 309165359Sjkim options &= ~IFM_HDX; 310165359Sjkim } 31125450Speter ifr.ifr_media |= options; 312165359Sjkim } 313140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 314140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 31525450Speter} 31625450Speter 317166113Smariusstatic void 318166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp) 319166113Smarius{ 320166113Smarius struct ifmediareq *ifmr; 321166113Smarius int inst; 322114164Ssam 323170531Ssam ifmr = ifmedia_getstate(s); 324166113Smarius 325166113Smarius inst = atoi(val); 326194799Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 327166113Smarius errx(1, "invalid media instance: %s", val); 328166113Smarius 329166113Smarius strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 330166113Smarius ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 331166113Smarius 332166113Smarius ifmr->ifm_current = ifr.ifr_media; 333166113Smarius callback_register(setifmediacallback, (void *)ifmr); 334166113Smarius} 335166113Smarius 336138593Ssamstatic void 337114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 338114164Ssam{ 339140913Sambrisko struct ifmediareq *ifmr; 340140913Sambrisko int mode; 341114164Ssam 342170531Ssam ifmr = ifmedia_getstate(s); 343114164Ssam 344140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 345114164Ssam 346114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 347140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 348114164Ssam 349140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 350140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 351114164Ssam} 352114164Ssam 35325450Speter/********************************************************************** 35425450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 35525450Speter **********************************************************************/ 35625450Speter 35725450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 35825450Speter IFM_TYPE_DESCRIPTIONS; 35925450Speter 36025450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 36125450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 36225450Speter 36325450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 36425450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 36525450Speter 36625450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 36725450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 36825450Speter 36925450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 37025450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 37125450Speter 37225450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 37325450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 37425450Speter 37525450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 37625450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 37725450Speter 37825450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 37925450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 38025450Speter 38125450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 38225450Speter IFM_SUBTYPE_FDDI_ALIASES; 38325450Speter 38425450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 38525450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 38625450Speter 38777217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 38877217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 38977217Sphk 39077217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 39177217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 39277217Sphk 39377217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 39477217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 39577217Sphk 396114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 397114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 398114164Ssam 399116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 400116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 401116820Ssam 402114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 403114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 404114232Sharti 405114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 406114232Sharti IFM_SUBTYPE_ATM_ALIASES; 407114232Sharti 408114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 409114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 410114232Sharti 41125450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 41225450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 41325450Speter 41425450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 41525450Speter IFM_SUBTYPE_SHARED_ALIASES; 41625450Speter 41725450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 41825450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 41925450Speter 420217013Smariusstatic struct ifmedia_description ifm_shared_option_aliases[] = 421217013Smarius IFM_SHARED_OPTION_ALIASES; 422217013Smarius 42325450Speterstruct ifmedia_type_to_subtype { 42425450Speter struct { 42525450Speter struct ifmedia_description *desc; 42625450Speter int alias; 42725450Speter } subtypes[5]; 42825450Speter struct { 42925450Speter struct ifmedia_description *desc; 43025450Speter int alias; 431217013Smarius } options[4]; 432114164Ssam struct { 433114164Ssam struct ifmedia_description *desc; 434114164Ssam int alias; 435116820Ssam } modes[3]; 43625450Speter}; 43725450Speter 43825450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 43925450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 44025450Speter { 44125450Speter { 44225450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 44325450Speter { &ifm_subtype_shared_aliases[0], 1 }, 44425450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 44525450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 44625450Speter { NULL, 0 }, 44725450Speter }, 44825450Speter { 44925450Speter { &ifm_shared_option_descriptions[0], 0 }, 450217013Smarius { &ifm_shared_option_aliases[0], 1 }, 45177217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 45225450Speter { NULL, 0 }, 45325450Speter }, 454114164Ssam { 455114164Ssam { NULL, 0 }, 456114164Ssam }, 45725450Speter }, 45825450Speter { 45925450Speter { 46025450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 46125450Speter { &ifm_subtype_shared_aliases[0], 1 }, 46225450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 46325450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 46425450Speter { NULL, 0 }, 46525450Speter }, 46625450Speter { 46725450Speter { &ifm_shared_option_descriptions[0], 0 }, 468217013Smarius { &ifm_shared_option_aliases[0], 1 }, 46977217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 47025450Speter { NULL, 0 }, 47125450Speter }, 472114164Ssam { 473114164Ssam { NULL, 0 }, 474114164Ssam }, 47525450Speter }, 47625450Speter { 47725450Speter { 47825450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 47925450Speter { &ifm_subtype_shared_aliases[0], 1 }, 48025450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 48125450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 48225450Speter { NULL, 0 }, 48325450Speter }, 48425450Speter { 48525450Speter { &ifm_shared_option_descriptions[0], 0 }, 486217013Smarius { &ifm_shared_option_aliases[0], 1 }, 48777217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 48825450Speter { NULL, 0 }, 48925450Speter }, 490114164Ssam { 491114164Ssam { NULL, 0 }, 492114164Ssam }, 49325450Speter }, 49477217Sphk { 49577217Sphk { 49677217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 49777217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 49877217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 49977217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 50077217Sphk { NULL, 0 }, 50177217Sphk }, 50277217Sphk { 50377217Sphk { &ifm_shared_option_descriptions[0], 0 }, 504217013Smarius { &ifm_shared_option_aliases[0], 1 }, 50577217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 50677217Sphk { NULL, 0 }, 50777217Sphk }, 508114164Ssam { 509114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 510116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 511114164Ssam { NULL, 0 }, 512114164Ssam }, 51377217Sphk }, 514114232Sharti { 515114232Sharti { 516114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 517114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 518114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 519114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 520114232Sharti { NULL, 0 }, 521114232Sharti }, 522114232Sharti { 523114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 524217013Smarius { &ifm_shared_option_aliases[0], 1 }, 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