ifmedia.c revision 221954
154359Sroberto/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2285612Sdelphij/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 221954 2011-05-15 12:51:00Z marius $ */ 3285612Sdelphij 454359Sroberto/* 575202Sphk * Copyright (c) 1997 Jason R. Thorpe. 654359Sroberto * All rights reserved. 7285612Sdelphij * 854359Sroberto * Redistribution and use in source and binary forms, with or without 954359Sroberto * modification, are permitted provided that the following conditions 10285612Sdelphij * are met: 11285612Sdelphij * 1. Redistributions of source code must retain the above copyright 12285612Sdelphij * notice, this list of conditions and the following disclaimer. 13285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 14285612Sdelphij * notice, this list of conditions and the following disclaimer in the 15285612Sdelphij * documentation and/or other materials provided with the distribution. 16285612Sdelphij * 3. All advertising materials mentioning features or use of this software 17285612Sdelphij * must display the following acknowledgement: 18285612Sdelphij * This product includes software developed for the NetBSD Project 1954359Sroberto * by Jason R. Thorpe. 2054359Sroberto * 4. The name of the author may not be used to endorse or promote products 2154359Sroberto * derived from this software without specific prior written permission. 2254359Sroberto * 23182007Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2454359Sroberto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25285612Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26285612Sdelphij * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27285612Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28285612Sdelphij * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29285612Sdelphij * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30285612Sdelphij * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31289997Sglebius * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32285612Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33285612Sdelphij * SUCH DAMAGE. 34285612Sdelphij */ 3554359Sroberto 3654359Sroberto/* 3754359Sroberto * Copyright (c) 1983, 1993 3854359Sroberto * The Regents of the University of California. All rights reserved. 3954359Sroberto * 4054359Sroberto * Redistribution and use in source and binary forms, with or without 4182502Sroberto * modification, are permitted provided that the following conditions 42285612Sdelphij * are met: 4382502Sroberto * 1. Redistributions of source code must retain the above copyright 44285612Sdelphij * notice, this list of conditions and the following disclaimer. 4554359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 4654359Sroberto * notice, this list of conditions and the following disclaimer in the 47285612Sdelphij * documentation and/or other materials provided with the distribution. 48285612Sdelphij * 4. Neither the name of the University nor the names of its contributors 4954359Sroberto * may be used to endorse or promote products derived from this software 50285612Sdelphij * without specific prior written permission. 5154359Sroberto * 5254359Sroberto * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5354359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54285612Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55132455Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56285612Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57132455Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58285612Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59285612Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60285612Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61285612Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62285612Sdelphij * SUCH DAMAGE. 63285612Sdelphij */ 64285612Sdelphij 65285612Sdelphij#include <sys/param.h> 66285612Sdelphij#include <sys/ioctl.h> 67285612Sdelphij#include <sys/socket.h> 68285612Sdelphij#include <sys/sysctl.h> 69285612Sdelphij#include <sys/time.h> 70285612Sdelphij 71285612Sdelphij#include <net/if.h> 72285612Sdelphij#include <net/if_dl.h> 73285612Sdelphij#include <net/if_types.h> 74285612Sdelphij#include <net/if_media.h> 75285612Sdelphij#include <net/route.h> 76285612Sdelphij 77294569Sdelphij#include <ctype.h> 7854359Sroberto#include <err.h> 79285612Sdelphij#include <errno.h> 8054359Sroberto#include <fcntl.h> 81285612Sdelphij#include <stdio.h> 82285612Sdelphij#include <stdlib.h> 83285612Sdelphij#include <string.h> 84285612Sdelphij#include <unistd.h> 85285612Sdelphij 86285612Sdelphij#include "ifconfig.h" 87285612Sdelphij 88285612Sdelphijstatic void domediaopt(const char *, int, int); 89285612Sdelphijstatic int get_media_subtype(int, const char *); 90285612Sdelphijstatic int get_media_mode(int, const char *); 91285612Sdelphijstatic int get_media_options(int, const char *); 92285612Sdelphijstatic int lookup_media_word(struct ifmedia_description *, const char *); 93285612Sdelphijstatic void print_media_word(int, int); 94285612Sdelphijstatic void print_media_word_ifconfig(int); 95285612Sdelphij 96285612Sdelphijstatic struct ifmedia_description *get_toptype_desc(int); 97285612Sdelphijstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 98285612Sdelphijstatic struct ifmedia_description *get_subtype_desc(int, 99285612Sdelphij struct ifmedia_type_to_subtype *ttos); 100285612Sdelphij 101285612Sdelphij#define IFM_OPMODE(x) \ 102285612Sdelphij ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 103285612Sdelphij IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 104285612Sdelphij IFM_IEEE80211_MBSS)) 105285612Sdelphij#define IFM_IEEE80211_STA 0 106285612Sdelphij 107285612Sdelphijstatic void 108285612Sdelphijmedia_status(int s) 109285612Sdelphij{ 110285612Sdelphij struct ifmediareq ifmr; 111285612Sdelphij int *media_list, i; 112285612Sdelphij 11354359Sroberto (void) memset(&ifmr, 0, sizeof(ifmr)); 114294569Sdelphij (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 115294569Sdelphij 116285612Sdelphij if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 117285612Sdelphij /* 118285612Sdelphij * Interface doesn't support SIOC{G,S}IFMEDIA. 119285612Sdelphij */ 120285612Sdelphij return; 121285612Sdelphij } 122310419Sdelphij 123310419Sdelphij if (ifmr.ifm_count == 0) { 124285612Sdelphij warnx("%s: no media types?", name); 125285612Sdelphij return; 126285612Sdelphij } 127285612Sdelphij 128285612Sdelphij media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 129310419Sdelphij if (media_list == NULL) 130285612Sdelphij err(1, "malloc"); 13154359Sroberto ifmr.ifm_ulist = media_list; 13254359Sroberto 13354359Sroberto if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 134285612Sdelphij err(1, "SIOCGIFMEDIA"); 135285612Sdelphij 136285612Sdelphij printf("\tmedia: "); 137285612Sdelphij print_media_word(ifmr.ifm_current, 1); 138285612Sdelphij if (ifmr.ifm_active != ifmr.ifm_current) { 139285612Sdelphij putchar(' '); 140285612Sdelphij putchar('('); 141285612Sdelphij print_media_word(ifmr.ifm_active, 0); 142285612Sdelphij putchar(')'); 143285612Sdelphij } 144285612Sdelphij 145285612Sdelphij putchar('\n'); 146285612Sdelphij 147285612Sdelphij if (ifmr.ifm_status & IFM_AVALID) { 148285612Sdelphij printf("\tstatus: "); 149285612Sdelphij switch (IFM_TYPE(ifmr.ifm_active)) { 150285612Sdelphij case IFM_ETHER: 151285612Sdelphij case IFM_ATM: 152285612Sdelphij if (ifmr.ifm_status & IFM_ACTIVE) 153285612Sdelphij printf("active"); 154285612Sdelphij else 155285612Sdelphij printf("no carrier"); 156285612Sdelphij break; 157285612Sdelphij 158285612Sdelphij case IFM_FDDI: 159285612Sdelphij case IFM_TOKEN: 160285612Sdelphij if (ifmr.ifm_status & IFM_ACTIVE) 161285612Sdelphij printf("inserted"); 162285612Sdelphij else 163285612Sdelphij printf("no ring"); 164285612Sdelphij break; 165285612Sdelphij 166285612Sdelphij case IFM_IEEE80211: 167285612Sdelphij if (ifmr.ifm_status & IFM_ACTIVE) { 168285612Sdelphij /* NB: only sta mode associates */ 169285612Sdelphij if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 170285612Sdelphij printf("associated"); 171285612Sdelphij else 172285612Sdelphij printf("running"); 173285612Sdelphij } else 174285612Sdelphij printf("no carrier"); 175285612Sdelphij break; 176285612Sdelphij } 177285612Sdelphij putchar('\n'); 178285612Sdelphij } 179330567Sgordon 180330567Sgordon if (ifmr.ifm_count > 0 && supmedia) { 181330567Sgordon printf("\tsupported media:\n"); 182330567Sgordon for (i = 0; i < ifmr.ifm_count; i++) { 183330567Sgordon printf("\t\t"); 184330567Sgordon print_media_word_ifconfig(media_list[i]); 185330567Sgordon putchar('\n'); 186330567Sgordon } 187330567Sgordon } 188330567Sgordon 189330567Sgordon free(media_list); 190330567Sgordon} 191330567Sgordon 192330567Sgordonstruct ifmediareq * 193330567Sgordonifmedia_getstate(int s) 194330567Sgordon{ 195330567Sgordon static struct ifmediareq *ifmr = NULL; 196330567Sgordon int *mwords; 197330567Sgordon 198330567Sgordon if (ifmr == NULL) { 199330567Sgordon ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 200330567Sgordon if (ifmr == NULL) 201330567Sgordon err(1, "malloc"); 202330567Sgordon 203330567Sgordon (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 204330567Sgordon (void) strncpy(ifmr->ifm_name, name, 205330567Sgordon sizeof(ifmr->ifm_name)); 206330567Sgordon 207330567Sgordon ifmr->ifm_count = 0; 208330567Sgordon ifmr->ifm_ulist = NULL; 209330567Sgordon 210285612Sdelphij /* 211285612Sdelphij * We must go through the motions of reading all 212330567Sgordon * supported media because we need to know both 213330567Sgordon * the current media type and the top-level type. 214330567Sgordon */ 215330567Sgordon 216330567Sgordon if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 217330567Sgordon err(1, "SIOCGIFMEDIA"); 218330567Sgordon } 219330567Sgordon 220330567Sgordon if (ifmr->ifm_count == 0) 221330567Sgordon errx(1, "%s: no media types?", name); 222330567Sgordon 223330567Sgordon mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 224330567Sgordon if (mwords == NULL) 225330567Sgordon err(1, "malloc"); 226330567Sgordon 227330567Sgordon ifmr->ifm_ulist = mwords; 228330567Sgordon if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 229330567Sgordon err(1, "SIOCGIFMEDIA"); 230330567Sgordon } 231285612Sdelphij 232285612Sdelphij return ifmr; 233285612Sdelphij} 234285612Sdelphij 235285612Sdelphijstatic void 236285612Sdelphijsetifmediacallback(int s, void *arg) 237285612Sdelphij{ 238285612Sdelphij struct ifmediareq *ifmr = (struct ifmediareq *)arg; 239285612Sdelphij static int did_it = 0; 240285612Sdelphij 241285612Sdelphij if (!did_it) { 242285612Sdelphij ifr.ifr_media = ifmr->ifm_current; 243285612Sdelphij if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 244285612Sdelphij err(1, "SIOCSIFMEDIA (media)"); 245285612Sdelphij free(ifmr->ifm_ulist); 246285612Sdelphij free(ifmr); 247285612Sdelphij did_it = 1; 248285612Sdelphij } 249285612Sdelphij} 250285612Sdelphij 251285612Sdelphijstatic void 252285612Sdelphijsetmedia(const char *val, int d, int s, const struct afswtch *afp) 253285612Sdelphij{ 254285612Sdelphij struct ifmediareq *ifmr; 255285612Sdelphij int subtype; 256285612Sdelphij 257285612Sdelphij ifmr = ifmedia_getstate(s); 258285612Sdelphij 259285612Sdelphij /* 260285612Sdelphij * We are primarily concerned with the top-level type. 261285612Sdelphij * However, "current" may be only IFM_NONE, so we just look 262285612Sdelphij * for the top-level type in the first "supported type" 263285612Sdelphij * entry. 264285612Sdelphij * 265285612Sdelphij * (I'm assuming that all supported media types for a given 266285612Sdelphij * interface will be the same top-level type..) 267285612Sdelphij */ 268285612Sdelphij subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 269285612Sdelphij 270285612Sdelphij strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 271285612Sdelphij ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | 272285612Sdelphij IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 273285612Sdelphij 274285612Sdelphij ifmr->ifm_current = ifr.ifr_media; 275285612Sdelphij callback_register(setifmediacallback, (void *)ifmr); 276285612Sdelphij} 277285612Sdelphij 278285612Sdelphijstatic void 279285612Sdelphijsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 280285612Sdelphij{ 281285612Sdelphij 282285612Sdelphij domediaopt(val, 0, s); 283285612Sdelphij} 284285612Sdelphij 285285612Sdelphijstatic void 286285612Sdelphijunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 287285612Sdelphij{ 288285612Sdelphij 289285612Sdelphij domediaopt(val, 1, s); 290285612Sdelphij} 291285612Sdelphij 292285612Sdelphijstatic void 293285612Sdelphijdomediaopt(const char *val, int clear, int s) 294285612Sdelphij{ 295285612Sdelphij struct ifmediareq *ifmr; 296285612Sdelphij int options; 297285612Sdelphij 298285612Sdelphij ifmr = ifmedia_getstate(s); 299285612Sdelphij 300285612Sdelphij options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 301285612Sdelphij 302285612Sdelphij strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 303285612Sdelphij ifr.ifr_media = ifmr->ifm_current; 304285612Sdelphij if (clear) 305285612Sdelphij ifr.ifr_media &= ~options; 306285612Sdelphij else { 307285612Sdelphij if (options & IFM_HDX) { 308285612Sdelphij ifr.ifr_media &= ~IFM_FDX; 309285612Sdelphij options &= ~IFM_HDX; 310285612Sdelphij } 311285612Sdelphij ifr.ifr_media |= options; 312285612Sdelphij } 313285612Sdelphij ifmr->ifm_current = ifr.ifr_media; 314285612Sdelphij callback_register(setifmediacallback, (void *)ifmr); 315285612Sdelphij} 316285612Sdelphij 317285612Sdelphijstatic void 318285612Sdelphijsetmediainst(const char *val, int d, int s, const struct afswtch *afp) 319285612Sdelphij{ 320285612Sdelphij struct ifmediareq *ifmr; 321285612Sdelphij int inst; 322285612Sdelphij 323285612Sdelphij ifmr = ifmedia_getstate(s); 324285612Sdelphij 325285612Sdelphij inst = atoi(val); 326285612Sdelphij if (inst < 0 || inst > (int)IFM_INST_MAX) 327285612Sdelphij errx(1, "invalid media instance: %s", val); 328285612Sdelphij 329285612Sdelphij strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 330285612Sdelphij ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 331285612Sdelphij 332285612Sdelphij ifmr->ifm_current = ifr.ifr_media; 33382502Sroberto callback_register(setifmediacallback, (void *)ifmr); 33482502Sroberto} 33554359Sroberto 336285612Sdelphijstatic void 33754359Srobertosetmediamode(const char *val, int d, int s, const struct afswtch *afp) 33854359Sroberto{ 33954359Sroberto struct ifmediareq *ifmr; 34054359Sroberto int mode; 34154359Sroberto 342285612Sdelphij ifmr = ifmedia_getstate(s); 34354359Sroberto 34454359Sroberto mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 345285612Sdelphij 34654359Sroberto strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 347285612Sdelphij ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 348285612Sdelphij 349285612Sdelphij ifmr->ifm_current = ifr.ifr_media; 350285612Sdelphij callback_register(setifmediacallback, (void *)ifmr); 351285612Sdelphij} 352285612Sdelphij 353285612Sdelphij/********************************************************************** 354285612Sdelphij * A good chunk of this is duplicated from sys/net/ifmedia.c 355285612Sdelphij **********************************************************************/ 356285612Sdelphij 357285612Sdelphijstatic struct ifmedia_description ifm_type_descriptions[] = 358285612Sdelphij IFM_TYPE_DESCRIPTIONS; 359285612Sdelphij 360285612Sdelphijstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 361285612Sdelphij IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 362285612Sdelphij 363285612Sdelphijstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 364285612Sdelphij IFM_SUBTYPE_ETHERNET_ALIASES; 365285612Sdelphij 366285612Sdelphijstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 367285612Sdelphij IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 368285612Sdelphij 369285612Sdelphijstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 370285612Sdelphij IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 371285612Sdelphij 372285612Sdelphijstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 373285612Sdelphij IFM_SUBTYPE_TOKENRING_ALIASES; 374285612Sdelphij 375285612Sdelphijstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 376285612Sdelphij IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 377285612Sdelphij 378285612Sdelphijstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 379285612Sdelphij IFM_SUBTYPE_FDDI_DESCRIPTIONS; 380285612Sdelphij 381330567Sgordonstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 382330567Sgordon IFM_SUBTYPE_FDDI_ALIASES; 383330567Sgordon 384330567Sgordonstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 385330567Sgordon IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 386330567Sgordon 387330567Sgordonstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 388330567Sgordon IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 389330567Sgordon 390330567Sgordonstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 391330567Sgordon IFM_SUBTYPE_IEEE80211_ALIASES; 392330567Sgordon 393330567Sgordonstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 394330567Sgordon IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 395330567Sgordon 396330567Sgordonstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 397330567Sgordon IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 398330567Sgordon 399330567Sgordonstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 400330567Sgordon IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 401330567Sgordon 402330567Sgordonstatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 403330567Sgordon IFM_SUBTYPE_ATM_DESCRIPTIONS; 404330567Sgordon 405330567Sgordonstatic struct ifmedia_description ifm_subtype_atm_aliases[] = 406330567Sgordon IFM_SUBTYPE_ATM_ALIASES; 407330567Sgordon 408330567Sgordonstatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 409330567Sgordon IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 410330567Sgordon 411330567Sgordonstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 412330567Sgordon IFM_SUBTYPE_SHARED_DESCRIPTIONS; 413330567Sgordon 414330567Sgordonstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 415330567Sgordon IFM_SUBTYPE_SHARED_ALIASES; 416330567Sgordon 417330567Sgordonstatic struct ifmedia_description ifm_shared_option_descriptions[] = 418330567Sgordon IFM_SHARED_OPTION_DESCRIPTIONS; 419330567Sgordon 420330567Sgordonstatic struct ifmedia_description ifm_shared_option_aliases[] = 421330567Sgordon IFM_SHARED_OPTION_ALIASES; 422330567Sgordon 423330567Sgordonstruct ifmedia_type_to_subtype { 424330567Sgordon struct { 425330567Sgordon struct ifmedia_description *desc; 426330567Sgordon int alias; 427330567Sgordon } subtypes[5]; 428330567Sgordon struct { 429289997Sglebius struct ifmedia_description *desc; 430330567Sgordon int alias; 431330567Sgordon } options[4]; 432289997Sglebius struct { 433285612Sdelphij struct ifmedia_description *desc; 434285612Sdelphij int alias; 435285612Sdelphij } modes[3]; 436285612Sdelphij}; 437285612Sdelphij 438285612Sdelphij/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 439285612Sdelphijstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 440285612Sdelphij { 441285612Sdelphij { 442285612Sdelphij { &ifm_subtype_shared_descriptions[0], 0 }, 443330567Sgordon { &ifm_subtype_shared_aliases[0], 1 }, 44454359Sroberto { &ifm_subtype_ethernet_descriptions[0], 0 }, 44554359Sroberto { &ifm_subtype_ethernet_aliases[0], 1 }, 446285612Sdelphij { NULL, 0 }, 44754359Sroberto }, 44854359Sroberto { 44982502Sroberto { &ifm_shared_option_descriptions[0], 0 }, 45082502Sroberto { &ifm_shared_option_aliases[0], 1 }, 45154359Sroberto { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 452285612Sdelphij { NULL, 0 }, 45382502Sroberto }, 45454359Sroberto { 45554359Sroberto { NULL, 0 }, 45654359Sroberto }, 45754359Sroberto }, 45854359Sroberto { 45954359Sroberto { 46054359Sroberto { &ifm_subtype_shared_descriptions[0], 0 }, 46154359Sroberto { &ifm_subtype_shared_aliases[0], 1 }, 46254359Sroberto { &ifm_subtype_tokenring_descriptions[0], 0 }, 463285612Sdelphij { &ifm_subtype_tokenring_aliases[0], 1 }, 464285612Sdelphij { NULL, 0 }, 46554359Sroberto }, 466285612Sdelphij { 46754359Sroberto { &ifm_shared_option_descriptions[0], 0 }, 46854359Sroberto { &ifm_shared_option_aliases[0], 1 }, 46982502Sroberto { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 470182007Sroberto { NULL, 0 }, 47154359Sroberto }, 472285612Sdelphij { 473285612Sdelphij { NULL, 0 }, 474285612Sdelphij }, 475285612Sdelphij }, 476285612Sdelphij { 477285612Sdelphij { 478132455Sroberto { &ifm_subtype_shared_descriptions[0], 0 }, 479285612Sdelphij { &ifm_subtype_shared_aliases[0], 1 }, 480285612Sdelphij { &ifm_subtype_fddi_descriptions[0], 0 }, 481132455Sroberto { &ifm_subtype_fddi_aliases[0], 1 }, 482285612Sdelphij { NULL, 0 }, 483132455Sroberto }, 484132455Sroberto { 485285612Sdelphij { &ifm_shared_option_descriptions[0], 0 }, 48654359Sroberto { &ifm_shared_option_aliases[0], 1 }, 48754359Sroberto { &ifm_subtype_fddi_option_descriptions[0], 0 }, 48854359Sroberto { NULL, 0 }, 48954359Sroberto }, 49054359Sroberto { 49154359Sroberto { NULL, 0 }, 49254359Sroberto }, 493285612Sdelphij }, 49482502Sroberto { 49582502Sroberto { 49682502Sroberto { &ifm_subtype_shared_descriptions[0], 0 }, 497285612Sdelphij { &ifm_subtype_shared_aliases[0], 1 }, 49882502Sroberto { &ifm_subtype_ieee80211_descriptions[0], 0 }, 49982502Sroberto { &ifm_subtype_ieee80211_aliases[0], 1 }, 50082502Sroberto { NULL, 0 }, 50182502Sroberto }, 50282502Sroberto { 50382502Sroberto { &ifm_shared_option_descriptions[0], 0 }, 50482502Sroberto { &ifm_shared_option_aliases[0], 1 }, 50582502Sroberto { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 50682502Sroberto { NULL, 0 }, 50782502Sroberto }, 50882502Sroberto { 509285612Sdelphij { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 51082502Sroberto { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 51182502Sroberto { NULL, 0 }, 51282502Sroberto }, 51382502Sroberto }, 514285612Sdelphij { 51582502Sroberto { 516182007Sroberto { &ifm_subtype_shared_descriptions[0], 0 }, 51782502Sroberto { &ifm_subtype_shared_aliases[0], 1 }, 51882502Sroberto { &ifm_subtype_atm_descriptions[0], 0 }, 51982502Sroberto { &ifm_subtype_atm_aliases[0], 1 }, 52082502Sroberto { NULL, 0 }, 52182502Sroberto }, 52282502Sroberto { 523285612Sdelphij { &ifm_shared_option_descriptions[0], 0 }, 524285612Sdelphij { &ifm_shared_option_aliases[0], 1 }, 52582502Sroberto { &ifm_subtype_atm_option_descriptions[0], 0 }, 52682502Sroberto { NULL, 0 }, 52782502Sroberto }, 528285612Sdelphij { 52982502Sroberto { NULL, 0 }, 53082502Sroberto }, 531182007Sroberto }, 532285612Sdelphij}; 533285612Sdelphij 534285612Sdelphijstatic int 535285612Sdelphijget_media_subtype(int type, const char *val) 536285612Sdelphij{ 537285612Sdelphij struct ifmedia_description *desc; 538285612Sdelphij struct ifmedia_type_to_subtype *ttos; 539285612Sdelphij int rval, i; 540285612Sdelphij 541285612Sdelphij /* Find the top-level interface type. */ 542285612Sdelphij for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 543285612Sdelphij desc->ifmt_string != NULL; desc++, ttos++) 544285612Sdelphij if (type == desc->ifmt_word) 545285612Sdelphij break; 546285612Sdelphij if (desc->ifmt_string == NULL) 547285612Sdelphij errx(1, "unknown media type 0x%x", type); 548285612Sdelphij 549285612Sdelphij for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 550285612Sdelphij rval = lookup_media_word(ttos->subtypes[i].desc, val); 551285612Sdelphij if (rval != -1) 552285612Sdelphij return (rval); 553285612Sdelphij } 554285612Sdelphij errx(1, "unknown media subtype: %s", val); 555285612Sdelphij /*NOTREACHED*/ 55654359Sroberto} 55754359Sroberto 55854359Srobertostatic int 55954359Srobertoget_media_mode(int type, const char *val) 56054359Sroberto{ 56154359Sroberto struct ifmedia_description *desc; 562285612Sdelphij struct ifmedia_type_to_subtype *ttos; 56354359Sroberto int rval, i; 56454359Sroberto 565285612Sdelphij /* Find the top-level interface type. */ 56654359Sroberto for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 56754359Sroberto desc->ifmt_string != NULL; desc++, ttos++) 568285612Sdelphij if (type == desc->ifmt_word) 569285612Sdelphij break; 57082502Sroberto if (desc->ifmt_string == NULL) 57154359Sroberto errx(1, "unknown media mode 0x%x", type); 57254359Sroberto 57354359Sroberto for (i = 0; ttos->modes[i].desc != NULL; i++) { 57454359Sroberto rval = lookup_media_word(ttos->modes[i].desc, val); 57554359Sroberto if (rval != -1) 576285612Sdelphij return (rval); 577285612Sdelphij } 57854359Sroberto return -1; 579182007Sroberto} 58054359Sroberto 58154359Srobertostatic int 58254359Srobertoget_media_options(int type, const char *val) 58354359Sroberto{ 584285612Sdelphij struct ifmedia_description *desc; 58554359Sroberto struct ifmedia_type_to_subtype *ttos; 58682502Sroberto char *optlist, *optptr; 58782502Sroberto int option = 0, i, rval = 0; 58882502Sroberto 58982502Sroberto /* We muck with the string, so copy it. */ 59082502Sroberto optlist = strdup(val); 59182502Sroberto if (optlist == NULL) 59254359Sroberto err(1, "strdup"); 593285612Sdelphij 59454359Sroberto /* Find the top-level interface type. */ 59554359Sroberto for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 59654359Sroberto desc->ifmt_string != NULL; desc++, ttos++) 597285612Sdelphij if (type == desc->ifmt_word) 598132455Sroberto break; 599285612Sdelphij if (desc->ifmt_string == NULL) 600285612Sdelphij errx(1, "unknown media type 0x%x", type); 601182007Sroberto 602285612Sdelphij /* 603132455Sroberto * Look up the options in the user-provided comma-separated 604285612Sdelphij * list. 60554359Sroberto */ 60654359Sroberto optptr = optlist; 60754359Sroberto for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 60854359Sroberto for (i = 0; ttos->options[i].desc != NULL; i++) { 60954359Sroberto option = lookup_media_word(ttos->options[i].desc, optptr); 61054359Sroberto if (option != -1) 61154359Sroberto break; 61254359Sroberto } 613285612Sdelphij if (option == 0) 61482502Sroberto errx(1, "unknown option: %s", optptr); 61582502Sroberto rval |= option; 61682502Sroberto } 61782502Sroberto 61882502Sroberto free(optlist); 61982502Sroberto return (rval); 62082502Sroberto} 62182502Sroberto 62282502Srobertostatic int 62382502Srobertolookup_media_word(struct ifmedia_description *desc, const char *val) 62482502Sroberto{ 62582502Sroberto 62682502Sroberto for (; desc->ifmt_string != NULL; desc++) 62782502Sroberto if (strcasecmp(desc->ifmt_string, val) == 0) 62882502Sroberto return (desc->ifmt_word); 62954359Sroberto 63054359Sroberto return (-1); 63154359Sroberto} 63254359Sroberto 63354359Srobertostatic struct ifmedia_description *get_toptype_desc(int ifmw) 63454359Sroberto{ 635285612Sdelphij struct ifmedia_description *desc; 63654359Sroberto 63782502Sroberto for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 63854359Sroberto if (IFM_TYPE(ifmw) == desc->ifmt_word) 63954359Sroberto break; 64054359Sroberto 64154359Sroberto return desc; 64254359Sroberto} 64354359Sroberto 64454359Srobertostatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 64554359Sroberto{ 64654359Sroberto struct ifmedia_description *desc; 64754359Sroberto struct ifmedia_type_to_subtype *ttos; 64854359Sroberto 64954359Sroberto for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 65054359Sroberto desc->ifmt_string != NULL; desc++, ttos++) 65154359Sroberto if (IFM_TYPE(ifmw) == desc->ifmt_word) 652285612Sdelphij break; 653285612Sdelphij 654285612Sdelphij return ttos; 655285612Sdelphij} 656285612Sdelphij 65754359Srobertostatic struct ifmedia_description *get_subtype_desc(int ifmw, 65854359Sroberto struct ifmedia_type_to_subtype *ttos) 65982502Sroberto{ 66054359Sroberto int i; 66154359Sroberto struct ifmedia_description *desc; 66254359Sroberto 66382502Sroberto for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 66454359Sroberto if (ttos->subtypes[i].alias) 66554359Sroberto continue; 666285612Sdelphij for (desc = ttos->subtypes[i].desc; 66754359Sroberto desc->ifmt_string != NULL; desc++) { 66854359Sroberto if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 669285612Sdelphij return desc; 670285612Sdelphij } 67154359Sroberto } 67254359Sroberto 67354359Sroberto return NULL; 67454359Sroberto} 67554359Sroberto 67654359Srobertostatic struct ifmedia_description *get_mode_desc(int ifmw, 67782502Sroberto struct ifmedia_type_to_subtype *ttos) 67882502Sroberto{ 67982502Sroberto int i; 68082502Sroberto struct ifmedia_description *desc; 68154359Sroberto 68254359Sroberto for (i = 0; ttos->modes[i].desc != NULL; i++) { 683285612Sdelphij if (ttos->modes[i].alias) 68454359Sroberto continue; 68554359Sroberto for (desc = ttos->modes[i].desc; 68654359Sroberto desc->ifmt_string != NULL; desc++) { 68754359Sroberto if (IFM_MODE(ifmw) == desc->ifmt_word) 68854359Sroberto return desc; 68954359Sroberto } 69054359Sroberto } 69154359Sroberto 69254359Sroberto return NULL; 69354359Sroberto} 69454359Sroberto 69554359Srobertostatic void 69682502Srobertoprint_media_word(int ifmw, int print_toptype) 69782502Sroberto{ 69882502Sroberto struct ifmedia_description *desc; 69954359Sroberto struct ifmedia_type_to_subtype *ttos; 700285612Sdelphij int seen_option = 0, i; 701285612Sdelphij 702285612Sdelphij /* Find the top-level interface type. */ 70354359Sroberto desc = get_toptype_desc(ifmw); 704285612Sdelphij ttos = get_toptype_ttos(ifmw); 70554359Sroberto if (desc->ifmt_string == NULL) { 70654359Sroberto printf("<unknown type>"); 707285612Sdelphij return; 708285612Sdelphij } else if (print_toptype) { 70954359Sroberto printf("%s", desc->ifmt_string); 71054359Sroberto } 71154359Sroberto 712285612Sdelphij /* 713285612Sdelphij * Don't print the top-level type; it's not like we can 714285612Sdelphij * change it, or anything. 71554359Sroberto */ 716182007Sroberto 717285612Sdelphij /* Find subtype. */ 718285612Sdelphij desc = get_subtype_desc(ifmw, ttos); 719285612Sdelphij if (desc == NULL) { 72054359Sroberto printf("<unknown subtype>"); 72154359Sroberto return; 722285612Sdelphij } 723285612Sdelphij 72454359Sroberto if (print_toptype) 725182007Sroberto putchar(' '); 726182007Sroberto 727285612Sdelphij printf("%s", desc->ifmt_string); 728285612Sdelphij 729285612Sdelphij if (print_toptype) { 730285612Sdelphij desc = get_mode_desc(ifmw, ttos); 731285612Sdelphij if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 732285612Sdelphij printf(" mode %s", desc->ifmt_string); 73354359Sroberto } 73454359Sroberto 735182007Sroberto /* Find options. */ 736182007Sroberto for (i = 0; ttos->options[i].desc != NULL; i++) { 73756746Sroberto if (ttos->options[i].alias) 738285612Sdelphij continue; 73956746Sroberto for (desc = ttos->options[i].desc; 740285612Sdelphij desc->ifmt_string != NULL; desc++) { 74182502Sroberto if (ifmw & desc->ifmt_word) { 742106166Sroberto if (seen_option == 0) 743106166Sroberto printf(" <"); 744106166Sroberto printf("%s%s", seen_option++ ? "," : "", 745106427Sroberto desc->ifmt_string); 746106427Sroberto } 747285612Sdelphij } 748285612Sdelphij } 74954359Sroberto printf("%s", seen_option ? ">" : ""); 750285612Sdelphij 75154359Sroberto if (print_toptype && IFM_INST(ifmw) != 0) 75254359Sroberto printf(" instance %d", IFM_INST(ifmw)); 75354359Sroberto} 75454359Sroberto 75554359Srobertostatic void 75682502Srobertoprint_media_word_ifconfig(int ifmw) 75754359Sroberto{ 75854359Sroberto struct ifmedia_description *desc; 75954359Sroberto struct ifmedia_type_to_subtype *ttos; 76054359Sroberto int seen_option = 0, i; 76154359Sroberto 76254359Sroberto /* Find the top-level interface type. */ 76354359Sroberto desc = get_toptype_desc(ifmw); 76454359Sroberto ttos = get_toptype_ttos(ifmw); 76554359Sroberto if (desc->ifmt_string == NULL) { 76654359Sroberto printf("<unknown type>"); 76754359Sroberto return; 76854359Sroberto } 76954359Sroberto 77054359Sroberto /* 771285612Sdelphij * Don't print the top-level type; it's not like we can 772285612Sdelphij * change it, or anything. 77354359Sroberto */ 77454359Sroberto 775285612Sdelphij /* Find subtype. */ 776285612Sdelphij desc = get_subtype_desc(ifmw, ttos); 77754359Sroberto if (desc == NULL) { 778285612Sdelphij printf("<unknown subtype>"); 77954359Sroberto return; 78054359Sroberto } 781285612Sdelphij 78254359Sroberto printf("media %s", desc->ifmt_string); 78354359Sroberto 78454359Sroberto desc = get_mode_desc(ifmw, ttos); 78582502Sroberto if (desc != NULL) 78654359Sroberto printf(" mode %s", desc->ifmt_string); 78754359Sroberto 78854359Sroberto /* Find options. */ 78954359Sroberto for (i = 0; ttos->options[i].desc != NULL; i++) { 79054359Sroberto if (ttos->options[i].alias) 79154359Sroberto continue; 79254359Sroberto for (desc = ttos->options[i].desc; 79354359Sroberto desc->ifmt_string != NULL; desc++) { 79482502Sroberto if (ifmw & desc->ifmt_word) { 795285612Sdelphij if (seen_option == 0) 796285612Sdelphij printf(" mediaopt "); 79754359Sroberto printf("%s%s", seen_option++ ? "," : "", 79854359Sroberto desc->ifmt_string); 79954359Sroberto } 800285612Sdelphij } 80154359Sroberto } 802285612Sdelphij 80354359Sroberto if (IFM_INST(ifmw) != 0) 80454359Sroberto printf(" instance %d", IFM_INST(ifmw)); 80554359Sroberto} 80654359Sroberto 80782502Sroberto/********************************************************************** 80854359Sroberto * ...until here. 80954359Sroberto **********************************************************************/ 81054359Sroberto 811285612Sdelphijstatic struct cmd media_cmds[] = { 81254359Sroberto DEF_CMD_ARG("media", setmedia), 81354359Sroberto DEF_CMD_ARG("mode", setmediamode), 81454359Sroberto DEF_CMD_ARG("mediaopt", setmediaopt), 81554359Sroberto DEF_CMD_ARG("-mediaopt",unsetmediaopt), 81654359Sroberto DEF_CMD_ARG("inst", setmediainst), 81754359Sroberto DEF_CMD_ARG("instance", setmediainst), 81854359Sroberto}; 819285612Sdelphijstatic struct afswtch af_media = { 820285612Sdelphij .af_name = "af_media", 821285612Sdelphij .af_af = AF_UNSPEC, 822285612Sdelphij .af_other_status = media_status, 82354359Sroberto}; 82454359Sroberto 82554359Srobertostatic __constructor void 82654359Srobertoifmedia_ctor(void) 82754359Sroberto{ 82854359Sroberto#define N(a) (sizeof(a) / sizeof(a[0])) 829285612Sdelphij size_t i; 83054359Sroberto 83154359Sroberto for (i = 0; i < N(media_cmds); i++) 83254359Sroberto cmd_register(&media_cmds[i]); 83354359Sroberto af_register(&af_media); 83454359Sroberto#undef N 83554359Sroberto} 83654359Sroberto