ifmedia.c revision 165359
125450Speter/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 165359 2006-12-19 22:50:49Z jkim $ */ 325450Speter 425450Speter/* 525450Speter * Copyright (c) 1997 Jason R. Thorpe. 625450Speter * All rights reserved. 725450Speter * 825450Speter * Redistribution and use in source and binary forms, with or without 925450Speter * modification, are permitted provided that the following conditions 1025450Speter * are met: 1125450Speter * 1. Redistributions of source code must retain the above copyright 1225450Speter * notice, this list of conditions and the following disclaimer. 1325450Speter * 2. Redistributions in binary form must reproduce the above copyright 1425450Speter * notice, this list of conditions and the following disclaimer in the 1525450Speter * documentation and/or other materials provided with the distribution. 1625450Speter * 3. All advertising materials mentioning features or use of this software 1725450Speter * must display the following acknowledgement: 1825450Speter * This product includes software developed for the NetBSD Project 1925450Speter * by Jason R. Thorpe. 2025450Speter * 4. The name of the author may not be used to endorse or promote products 2125450Speter * derived from this software without specific prior written permission. 2225450Speter * 2325450Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2425450Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2525450Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2625450Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2725450Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2825450Speter * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2925450Speter * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 3025450Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3125450Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3225450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3325450Speter * SUCH DAMAGE. 3425450Speter */ 3525450Speter 3625450Speter/* 3725450Speter * Copyright (c) 1983, 1993 3825450Speter * The Regents of the University of California. All rights reserved. 3925450Speter * 4025450Speter * Redistribution and use in source and binary forms, with or without 4125450Speter * modification, are permitted provided that the following conditions 4225450Speter * are met: 4325450Speter * 1. Redistributions of source code must retain the above copyright 4425450Speter * notice, this list of conditions and the following disclaimer. 4525450Speter * 2. Redistributions in binary form must reproduce the above copyright 4625450Speter * notice, this list of conditions and the following disclaimer in the 4725450Speter * documentation and/or other materials provided with the distribution. 4825450Speter * 3. All advertising materials mentioning features or use of this software 4925450Speter * must display the following acknowledgement: 5025450Speter * This product includes software developed by the University of 5125450Speter * California, Berkeley and its contributors. 5225450Speter * 4. Neither the name of the University nor the names of its contributors 5325450Speter * may be used to endorse or promote products derived from this software 5425450Speter * without specific prior written permission. 5525450Speter * 5625450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5725450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5825450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5925450Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6025450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6125450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6225450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6325450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6425450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6525450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6625450Speter * SUCH DAMAGE. 6725450Speter */ 6825450Speter 6925450Speter#include <sys/param.h> 7025450Speter#include <sys/ioctl.h> 7125450Speter#include <sys/socket.h> 7225450Speter#include <sys/sysctl.h> 7325450Speter#include <sys/time.h> 7425450Speter 7525450Speter#include <net/if.h> 7625450Speter#include <net/if_dl.h> 7725450Speter#include <net/if_types.h> 7825450Speter#include <net/if_media.h> 7925450Speter#include <net/route.h> 8025450Speter 8125450Speter#include <ctype.h> 8225450Speter#include <err.h> 8325450Speter#include <errno.h> 8425450Speter#include <fcntl.h> 8525450Speter#include <stdio.h> 8625450Speter#include <stdlib.h> 8725450Speter#include <string.h> 8825450Speter#include <unistd.h> 8925450Speter 9025450Speter#include "ifconfig.h" 9125450Speter 9295005Simpstatic void domediaopt(const char *, int, int); 9395005Simpstatic int get_media_subtype(int, const char *); 94114164Ssamstatic int get_media_mode(int, const char *); 9595005Simpstatic int get_media_options(int, const char *); 9695005Simpstatic int lookup_media_word(struct ifmedia_description *, const char *); 9795005Simpstatic void print_media_word(int, int); 9895005Simpstatic void print_media_word_ifconfig(int); 9925450Speter 10095005Simpstatic struct ifmedia_description *get_toptype_desc(int); 10195005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 10295005Simpstatic struct ifmedia_description *get_subtype_desc(int, 10395005Simp struct ifmedia_type_to_subtype *ttos); 10477385Sphk 105138593Ssamstatic void 106139494Ssammedia_status(int s) 10725450Speter{ 10825450Speter struct ifmediareq ifmr; 10925450Speter int *media_list, i; 11025450Speter 11125450Speter (void) memset(&ifmr, 0, sizeof(ifmr)); 11225450Speter (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 11325450Speter 11425450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 11525450Speter /* 11625450Speter * Interface doesn't support SIOC{G,S}IFMEDIA. 11725450Speter */ 11825450Speter return; 11925450Speter } 12025450Speter 12125450Speter if (ifmr.ifm_count == 0) { 12225450Speter warnx("%s: no media types?", name); 12325450Speter return; 12425450Speter } 12525450Speter 12625450Speter media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 12725450Speter if (media_list == NULL) 12825450Speter err(1, "malloc"); 12925450Speter ifmr.ifm_ulist = media_list; 13025450Speter 13125450Speter if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 13225450Speter err(1, "SIOCGIFMEDIA"); 13325450Speter 13425450Speter printf("\tmedia: "); 13577385Sphk print_media_word(ifmr.ifm_current, 1); 13625450Speter if (ifmr.ifm_active != ifmr.ifm_current) { 13725450Speter putchar(' '); 13825450Speter putchar('('); 13977385Sphk print_media_word(ifmr.ifm_active, 0); 14025450Speter putchar(')'); 14125450Speter } 14225450Speter 14377385Sphk putchar('\n'); 14477385Sphk 14525450Speter if (ifmr.ifm_status & IFM_AVALID) { 14677385Sphk printf("\tstatus: "); 14725450Speter switch (IFM_TYPE(ifmr.ifm_active)) { 14825450Speter case IFM_ETHER: 149161536Sthomas case IFM_ATM: 15025450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15125450Speter printf("active"); 15225450Speter else 15325450Speter printf("no carrier"); 15425450Speter break; 15525450Speter 15625450Speter case IFM_FDDI: 15725450Speter case IFM_TOKEN: 15825450Speter if (ifmr.ifm_status & IFM_ACTIVE) 15925450Speter printf("inserted"); 16025450Speter else 16125450Speter printf("no ring"); 16225450Speter break; 163114232Sharti 16477217Sphk case IFM_IEEE80211: 16577217Sphk /* XXX: Different value for adhoc? */ 16677217Sphk if (ifmr.ifm_status & IFM_ACTIVE) 16777217Sphk printf("associated"); 16877217Sphk else 16977217Sphk printf("no carrier"); 17077217Sphk break; 17125450Speter } 17285853Syar putchar('\n'); 17325450Speter } 17425450Speter 17577385Sphk if (ifmr.ifm_count > 0 && supmedia) { 17677385Sphk printf("\tsupported media:\n"); 17725450Speter for (i = 0; i < ifmr.ifm_count; i++) { 17877385Sphk printf("\t\t"); 17977385Sphk print_media_word_ifconfig(media_list[i]); 18077385Sphk putchar('\n'); 18125450Speter } 18225450Speter } 18325450Speter 18425450Speter free(media_list); 18525450Speter} 18625450Speter 187140913Sambriskostatic struct ifmediareq * 188140913Sambriskogetifmediastate(int s) 18925450Speter{ 190140913Sambrisko static struct ifmediareq *ifmr = NULL; 191140913Sambrisko int *mwords; 19225450Speter 193140913Sambrisko if (ifmr == NULL) { 194140913Sambrisko ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 195140913Sambrisko if (ifmr == NULL) 196140913Sambrisko err(1, "malloc"); 19725450Speter 198140913Sambrisko (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 199140913Sambrisko (void) strncpy(ifmr->ifm_name, name, 200140913Sambrisko sizeof(ifmr->ifm_name)); 201140913Sambrisko 202140913Sambrisko ifmr->ifm_count = 0; 203140913Sambrisko ifmr->ifm_ulist = NULL; 204140913Sambrisko 20525450Speter /* 206140913Sambrisko * We must go through the motions of reading all 207140913Sambrisko * supported media because we need to know both 208140913Sambrisko * the current media type and the top-level type. 20925450Speter */ 210140913Sambrisko 211140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 21225450Speter err(1, "SIOCGIFMEDIA"); 213140913Sambrisko } 214140913Sambrisko 215140913Sambrisko if (ifmr->ifm_count == 0) 216140913Sambrisko errx(1, "%s: no media types?", name); 217140913Sambrisko 218140913Sambrisko mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 219140913Sambrisko if (mwords == NULL) 220140913Sambrisko err(1, "malloc"); 221140913Sambrisko 222140913Sambrisko ifmr->ifm_ulist = mwords; 223140913Sambrisko if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 224140913Sambrisko err(1, "SIOCGIFMEDIA"); 22525450Speter } 22625450Speter 227140913Sambrisko return ifmr; 228140913Sambrisko} 22925450Speter 230140913Sambriskostatic void 231140913Sambriskosetifmediacallback(int s, void *arg) 232140913Sambrisko{ 233140913Sambrisko struct ifmediareq *ifmr = (struct ifmediareq *)arg; 234140913Sambrisko static int did_it = 0; 235140913Sambrisko 236140913Sambrisko if (!did_it) { 237154240Sambrisko ifr.ifr_media = ifmr->ifm_current; 238140913Sambrisko if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 239140913Sambrisko err(1, "SIOCSIFMEDIA (media)"); 240140913Sambrisko free(ifmr->ifm_ulist); 241140913Sambrisko free(ifmr); 242140913Sambrisko did_it = 1; 243140913Sambrisko } 244140913Sambrisko} 245140913Sambrisko 246140913Sambriskostatic void 247140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp) 248140913Sambrisko{ 249140913Sambrisko struct ifmediareq *ifmr; 250140913Sambrisko int subtype; 251140913Sambrisko 252140913Sambrisko 253140913Sambrisko ifmr = getifmediastate(s); 254140913Sambrisko 25525450Speter /* 25625450Speter * We are primarily concerned with the top-level type. 25725450Speter * However, "current" may be only IFM_NONE, so we just look 25825450Speter * for the top-level type in the first "supported type" 25925450Speter * entry. 26025450Speter * 26125450Speter * (I'm assuming that all supported media types for a given 26225450Speter * interface will be the same top-level type..) 26325450Speter */ 264140913Sambrisko subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 26525450Speter 26625450Speter strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 267140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 268140913Sambrisko IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 26925450Speter 270140913Sambrisko if ((ifr.ifr_media & IFM_TMASK) == 0) { 271140913Sambrisko ifr.ifr_media &= ~IFM_GMASK; 272140913Sambrisko } 273140913Sambrisko 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 298140913Sambrisko ifmr = getifmediastate(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 317114164Ssam 318138593Ssamstatic void 319114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 320114164Ssam{ 321140913Sambrisko struct ifmediareq *ifmr; 322140913Sambrisko int mode; 323114164Ssam 324140913Sambrisko ifmr = getifmediastate(s); 325114164Ssam 326140913Sambrisko mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 327114164Ssam 328114164Ssam strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 329140913Sambrisko ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 330114164Ssam 331140913Sambrisko ifmr->ifm_current = ifr.ifr_media; 332140913Sambrisko callback_register(setifmediacallback, (void *)ifmr); 333114164Ssam} 334114164Ssam 33525450Speter/********************************************************************** 33625450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c 33725450Speter **********************************************************************/ 33825450Speter 33925450Speterstatic struct ifmedia_description ifm_type_descriptions[] = 34025450Speter IFM_TYPE_DESCRIPTIONS; 34125450Speter 34225450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 34325450Speter IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 34425450Speter 34525450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 34625450Speter IFM_SUBTYPE_ETHERNET_ALIASES; 34725450Speter 34825450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 34925450Speter IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 35025450Speter 35125450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 35225450Speter IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 35325450Speter 35425450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 35525450Speter IFM_SUBTYPE_TOKENRING_ALIASES; 35625450Speter 35725450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 35825450Speter IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 35925450Speter 36025450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 36125450Speter IFM_SUBTYPE_FDDI_DESCRIPTIONS; 36225450Speter 36325450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 36425450Speter IFM_SUBTYPE_FDDI_ALIASES; 36525450Speter 36625450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 36725450Speter IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 36825450Speter 36977217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 37077217Sphk IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 37177217Sphk 37277217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 37377217Sphk IFM_SUBTYPE_IEEE80211_ALIASES; 37477217Sphk 37577217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 37677217Sphk IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 37777217Sphk 378114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 379114164Ssam IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 380114164Ssam 381116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 382116820Ssam IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 383116820Ssam 384114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 385114232Sharti IFM_SUBTYPE_ATM_DESCRIPTIONS; 386114232Sharti 387114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] = 388114232Sharti IFM_SUBTYPE_ATM_ALIASES; 389114232Sharti 390114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 391114232Sharti IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 392114232Sharti 39325450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 39425450Speter IFM_SUBTYPE_SHARED_DESCRIPTIONS; 39525450Speter 39625450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 39725450Speter IFM_SUBTYPE_SHARED_ALIASES; 39825450Speter 39925450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] = 40025450Speter IFM_SHARED_OPTION_DESCRIPTIONS; 40125450Speter 40225450Speterstruct ifmedia_type_to_subtype { 40325450Speter struct { 40425450Speter struct ifmedia_description *desc; 40525450Speter int alias; 40625450Speter } subtypes[5]; 40725450Speter struct { 40825450Speter struct ifmedia_description *desc; 40925450Speter int alias; 41025450Speter } options[3]; 411114164Ssam struct { 412114164Ssam struct ifmedia_description *desc; 413114164Ssam int alias; 414116820Ssam } modes[3]; 41525450Speter}; 41625450Speter 41725450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 41825450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 41925450Speter { 42025450Speter { 42125450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 42225450Speter { &ifm_subtype_shared_aliases[0], 1 }, 42325450Speter { &ifm_subtype_ethernet_descriptions[0], 0 }, 42425450Speter { &ifm_subtype_ethernet_aliases[0], 1 }, 42525450Speter { NULL, 0 }, 42625450Speter }, 42725450Speter { 42825450Speter { &ifm_shared_option_descriptions[0], 0 }, 42977217Sphk { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 43025450Speter { NULL, 0 }, 43125450Speter }, 432114164Ssam { 433114164Ssam { NULL, 0 }, 434114164Ssam }, 43525450Speter }, 43625450Speter { 43725450Speter { 43825450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 43925450Speter { &ifm_subtype_shared_aliases[0], 1 }, 44025450Speter { &ifm_subtype_tokenring_descriptions[0], 0 }, 44125450Speter { &ifm_subtype_tokenring_aliases[0], 1 }, 44225450Speter { NULL, 0 }, 44325450Speter }, 44425450Speter { 44525450Speter { &ifm_shared_option_descriptions[0], 0 }, 44677217Sphk { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 44725450Speter { NULL, 0 }, 44825450Speter }, 449114164Ssam { 450114164Ssam { NULL, 0 }, 451114164Ssam }, 45225450Speter }, 45325450Speter { 45425450Speter { 45525450Speter { &ifm_subtype_shared_descriptions[0], 0 }, 45625450Speter { &ifm_subtype_shared_aliases[0], 1 }, 45725450Speter { &ifm_subtype_fddi_descriptions[0], 0 }, 45825450Speter { &ifm_subtype_fddi_aliases[0], 1 }, 45925450Speter { NULL, 0 }, 46025450Speter }, 46125450Speter { 46225450Speter { &ifm_shared_option_descriptions[0], 0 }, 46377217Sphk { &ifm_subtype_fddi_option_descriptions[0], 0 }, 46425450Speter { NULL, 0 }, 46525450Speter }, 466114164Ssam { 467114164Ssam { NULL, 0 }, 468114164Ssam }, 46925450Speter }, 47077217Sphk { 47177217Sphk { 47277217Sphk { &ifm_subtype_shared_descriptions[0], 0 }, 47377217Sphk { &ifm_subtype_shared_aliases[0], 1 }, 47477217Sphk { &ifm_subtype_ieee80211_descriptions[0], 0 }, 47577217Sphk { &ifm_subtype_ieee80211_aliases[0], 1 }, 47677217Sphk { NULL, 0 }, 47777217Sphk }, 47877217Sphk { 47977217Sphk { &ifm_shared_option_descriptions[0], 0 }, 48077217Sphk { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 48177217Sphk { NULL, 0 }, 48277217Sphk }, 483114164Ssam { 484114164Ssam { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 485116820Ssam { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 486114164Ssam { NULL, 0 }, 487114164Ssam }, 48877217Sphk }, 489114232Sharti { 490114232Sharti { 491114232Sharti { &ifm_subtype_shared_descriptions[0], 0 }, 492114232Sharti { &ifm_subtype_shared_aliases[0], 1 }, 493114232Sharti { &ifm_subtype_atm_descriptions[0], 0 }, 494114232Sharti { &ifm_subtype_atm_aliases[0], 1 }, 495114232Sharti { NULL, 0 }, 496114232Sharti }, 497114232Sharti { 498114232Sharti { &ifm_shared_option_descriptions[0], 0 }, 499114232Sharti { &ifm_subtype_atm_option_descriptions[0], 0 }, 500114232Sharti { NULL, 0 }, 501114232Sharti }, 502114232Sharti { 503114232Sharti { NULL, 0 }, 504114232Sharti }, 505114232Sharti }, 50625450Speter}; 50725450Speter 50825450Speterstatic int 50995005Simpget_media_subtype(int type, const char *val) 51025450Speter{ 51125450Speter struct ifmedia_description *desc; 51225450Speter struct ifmedia_type_to_subtype *ttos; 51325450Speter int rval, i; 51425450Speter 51525450Speter /* Find the top-level interface type. */ 51625450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 51725450Speter desc->ifmt_string != NULL; desc++, ttos++) 51825450Speter if (type == desc->ifmt_word) 51925450Speter break; 52025450Speter if (desc->ifmt_string == NULL) 52125450Speter errx(1, "unknown media type 0x%x", type); 52225450Speter 52325450Speter for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 52425450Speter rval = lookup_media_word(ttos->subtypes[i].desc, val); 52525450Speter if (rval != -1) 52625450Speter return (rval); 52725450Speter } 52825450Speter errx(1, "unknown media subtype: %s", val); 529114164Ssam /*NOTREACHED*/ 53025450Speter} 53125450Speter 53225450Speterstatic int 533114164Ssamget_media_mode(int type, const char *val) 534114164Ssam{ 535114164Ssam struct ifmedia_description *desc; 536114164Ssam struct ifmedia_type_to_subtype *ttos; 537114164Ssam int rval, i; 538114164Ssam 539114164Ssam /* Find the top-level interface type. */ 540114164Ssam for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 541114164Ssam desc->ifmt_string != NULL; desc++, ttos++) 542114164Ssam if (type == desc->ifmt_word) 543114164Ssam break; 544114164Ssam if (desc->ifmt_string == NULL) 545114164Ssam errx(1, "unknown media mode 0x%x", type); 546114164Ssam 547114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 548114164Ssam rval = lookup_media_word(ttos->modes[i].desc, val); 549114164Ssam if (rval != -1) 550114164Ssam return (rval); 551114164Ssam } 552114164Ssam return -1; 553114164Ssam} 554114164Ssam 555114164Ssamstatic int 55695005Simpget_media_options(int type, const char *val) 55725450Speter{ 55825450Speter struct ifmedia_description *desc; 55925450Speter struct ifmedia_type_to_subtype *ttos; 56025450Speter char *optlist, *optptr; 56125450Speter int option = 0, i, rval = 0; 56225450Speter 56325450Speter /* We muck with the string, so copy it. */ 56425450Speter optlist = strdup(val); 56525450Speter if (optlist == NULL) 56625450Speter err(1, "strdup"); 56725450Speter 56825450Speter /* Find the top-level interface type. */ 56925450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 57025450Speter desc->ifmt_string != NULL; desc++, ttos++) 57125450Speter if (type == desc->ifmt_word) 57225450Speter break; 57325450Speter if (desc->ifmt_string == NULL) 57425450Speter errx(1, "unknown media type 0x%x", type); 57525450Speter 57625450Speter /* 57725450Speter * Look up the options in the user-provided comma-separated 57825450Speter * list. 57925450Speter */ 58025450Speter optptr = optlist; 58125450Speter for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 58225450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 58325450Speter option = lookup_media_word(ttos->options[i].desc, optptr); 58425450Speter if (option != -1) 58525450Speter break; 58625450Speter } 58725450Speter if (option == 0) 58825450Speter errx(1, "unknown option: %s", optptr); 58925450Speter rval |= option; 59025450Speter } 59125450Speter 59225450Speter free(optlist); 59325450Speter return (rval); 59425450Speter} 59525450Speter 59625450Speterstatic int 59795005Simplookup_media_word(struct ifmedia_description *desc, const char *val) 59825450Speter{ 59925450Speter 60025450Speter for (; desc->ifmt_string != NULL; desc++) 60125450Speter if (strcasecmp(desc->ifmt_string, val) == 0) 60225450Speter return (desc->ifmt_word); 60325450Speter 60425450Speter return (-1); 60525450Speter} 60625450Speter 60795005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw) 60825450Speter{ 60925450Speter struct ifmedia_description *desc; 61077385Sphk 61177385Sphk for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 61277385Sphk if (IFM_TYPE(ifmw) == desc->ifmt_word) 61377385Sphk break; 61477385Sphk 61577385Sphk return desc; 61677385Sphk} 61777385Sphk 61895005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 61977385Sphk{ 62077385Sphk struct ifmedia_description *desc; 62125450Speter struct ifmedia_type_to_subtype *ttos; 62225450Speter 62325450Speter for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 62425450Speter desc->ifmt_string != NULL; desc++, ttos++) 62525450Speter if (IFM_TYPE(ifmw) == desc->ifmt_word) 62625450Speter break; 62777385Sphk 62877385Sphk return ttos; 62977385Sphk} 63077385Sphk 63195005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw, 63295005Simp struct ifmedia_type_to_subtype *ttos) 63377385Sphk{ 63477385Sphk int i; 63577385Sphk struct ifmedia_description *desc; 63677385Sphk 63777385Sphk for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 63877385Sphk if (ttos->subtypes[i].alias) 63977385Sphk continue; 64077385Sphk for (desc = ttos->subtypes[i].desc; 64177385Sphk desc->ifmt_string != NULL; desc++) { 64277385Sphk if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 64377385Sphk return desc; 64477385Sphk } 64577385Sphk } 64677385Sphk 64777385Sphk return NULL; 64877385Sphk} 64977385Sphk 650114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw, 651114164Ssam struct ifmedia_type_to_subtype *ttos) 652114164Ssam{ 653114164Ssam int i; 654114164Ssam struct ifmedia_description *desc; 655114164Ssam 656114164Ssam for (i = 0; ttos->modes[i].desc != NULL; i++) { 657114164Ssam if (ttos->modes[i].alias) 658114164Ssam continue; 659114164Ssam for (desc = ttos->modes[i].desc; 660114164Ssam desc->ifmt_string != NULL; desc++) { 661114164Ssam if (IFM_MODE(ifmw) == desc->ifmt_word) 662114164Ssam return desc; 663114164Ssam } 664114164Ssam } 665114164Ssam 666114164Ssam return NULL; 667114164Ssam} 668114164Ssam 66977385Sphkstatic void 67095005Simpprint_media_word(int ifmw, int print_toptype) 67177385Sphk{ 67277385Sphk struct ifmedia_description *desc; 67377385Sphk struct ifmedia_type_to_subtype *ttos; 67477385Sphk int seen_option = 0, i; 67577385Sphk 67677385Sphk /* Find the top-level interface type. */ 67777385Sphk desc = get_toptype_desc(ifmw); 67877385Sphk ttos = get_toptype_ttos(ifmw); 67925450Speter if (desc->ifmt_string == NULL) { 68025450Speter printf("<unknown type>"); 68125450Speter return; 68277385Sphk } else if (print_toptype) { 68377385Sphk printf("%s", desc->ifmt_string); 68425450Speter } 68525450Speter 68625450Speter /* 68725450Speter * Don't print the top-level type; it's not like we can 68825450Speter * change it, or anything. 68925450Speter */ 69025450Speter 69125450Speter /* Find subtype. */ 69277385Sphk desc = get_subtype_desc(ifmw, ttos); 693161536Sthomas if (desc == NULL) { 694161536Sthomas printf("<unknown subtype>"); 695161536Sthomas return; 696161536Sthomas } 69725450Speter 69877385Sphk if (print_toptype) 69977385Sphk putchar(' '); 70077385Sphk 70125450Speter printf("%s", desc->ifmt_string); 70225450Speter 703114164Ssam if (print_toptype) { 704114164Ssam desc = get_mode_desc(ifmw, ttos); 705116820Ssam if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 706114164Ssam printf(" mode %s", desc->ifmt_string); 707114164Ssam } 708114164Ssam 70925450Speter /* Find options. */ 71025450Speter for (i = 0; ttos->options[i].desc != NULL; i++) { 71125450Speter if (ttos->options[i].alias) 71225450Speter continue; 71325450Speter for (desc = ttos->options[i].desc; 71425450Speter desc->ifmt_string != NULL; desc++) { 71525450Speter if (ifmw & desc->ifmt_word) { 71625450Speter if (seen_option == 0) 71725450Speter printf(" <"); 71825450Speter printf("%s%s", seen_option++ ? "," : "", 71925450Speter desc->ifmt_string); 72025450Speter } 72125450Speter } 72225450Speter } 72325450Speter printf("%s", seen_option ? ">" : ""); 72425450Speter} 72525450Speter 72677385Sphkstatic void 72795005Simpprint_media_word_ifconfig(int ifmw) 72877385Sphk{ 72977385Sphk struct ifmedia_description *desc; 73077385Sphk struct ifmedia_type_to_subtype *ttos; 73177385Sphk int i; 73277385Sphk 73377385Sphk /* Find the top-level interface type. */ 73477385Sphk desc = get_toptype_desc(ifmw); 73577385Sphk ttos = get_toptype_ttos(ifmw); 73677385Sphk if (desc->ifmt_string == NULL) { 73777385Sphk printf("<unknown type>"); 73877385Sphk return; 73977385Sphk } 74077385Sphk 74177385Sphk /* 74277385Sphk * Don't print the top-level type; it's not like we can 74377385Sphk * change it, or anything. 74477385Sphk */ 74577385Sphk 74677385Sphk /* Find subtype. */ 74777385Sphk desc = get_subtype_desc(ifmw, ttos); 748161536Sthomas if (desc == NULL) { 749161536Sthomas printf("<unknown subtype>"); 750161536Sthomas return; 751161536Sthomas } 75277385Sphk 75377385Sphk printf("media %s", desc->ifmt_string); 75477385Sphk 755114164Ssam desc = get_mode_desc(ifmw, ttos); 756114164Ssam if (desc != NULL) 757114164Ssam printf(" mode %s", desc->ifmt_string); 758114164Ssam 75977385Sphk /* Find options. */ 76077385Sphk for (i = 0; ttos->options[i].desc != NULL; i++) { 76177385Sphk if (ttos->options[i].alias) 76277385Sphk continue; 76377385Sphk for (desc = ttos->options[i].desc; 76477385Sphk desc->ifmt_string != NULL; desc++) { 76577385Sphk if (ifmw & desc->ifmt_word) { 76677385Sphk printf(" mediaopt %s", desc->ifmt_string); 76777385Sphk } 76877385Sphk } 76977385Sphk } 77077385Sphk} 77177385Sphk 77225450Speter/********************************************************************** 77325450Speter * ...until here. 77425450Speter **********************************************************************/ 775138593Ssam 776138593Ssamstatic struct cmd media_cmds[] = { 777138593Ssam DEF_CMD_ARG("media", setmedia), 778138593Ssam DEF_CMD_ARG("mode", setmediamode), 779138593Ssam DEF_CMD_ARG("mediaopt", setmediaopt), 780138593Ssam DEF_CMD_ARG("-mediaopt",unsetmediaopt), 781138593Ssam}; 782138593Ssamstatic struct afswtch af_media = { 783138593Ssam .af_name = "af_media", 784138593Ssam .af_af = AF_UNSPEC, 785139494Ssam .af_other_status = media_status, 786138593Ssam}; 787138593Ssam 788138593Ssamstatic __constructor void 789138593Ssamifmedia_ctor(void) 790138593Ssam{ 791138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 792138593Ssam int i; 793138593Ssam 794138593Ssam for (i = 0; i < N(media_cmds); i++) 795138593Ssam cmd_register(&media_cmds[i]); 796138593Ssam af_register(&af_media); 797138593Ssam#undef N 798138593Ssam} 799