1139804Simp/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2139013Sdavidxu/* $FreeBSD$ */ 3112904Sjeff 4112904Sjeff/* 5112904Sjeff * Copyright (c) 1997 Jason R. Thorpe. 6112904Sjeff * All rights reserved. 7112904Sjeff * 8112904Sjeff * Redistribution and use in source and binary forms, with or without 9112904Sjeff * modification, are permitted provided that the following conditions 10112904Sjeff * are met: 11112904Sjeff * 1. Redistributions of source code must retain the above copyright 12112904Sjeff * notice, this list of conditions and the following disclaimer. 13112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright 14112904Sjeff * notice, this list of conditions and the following disclaimer in the 15112904Sjeff * documentation and/or other materials provided with the distribution. 16112904Sjeff * 3. All advertising materials mentioning features or use of this software 17112904Sjeff * must display the following acknowledgement: 18112904Sjeff * This product includes software developed for the NetBSD Project 19112904Sjeff * by Jason R. Thorpe. 20112904Sjeff * 4. The name of the author may not be used to endorse or promote products 21112904Sjeff * derived from this software without specific prior written permission. 22112904Sjeff * 23112904Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24112904Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25112904Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26112904Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27112904Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28116182Sobrien * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29116182Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30116182Sobrien * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31162536Sdavidxu * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32112904Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33112904Sjeff * SUCH DAMAGE. 34131431Smarcel */ 35112904Sjeff 36115765Sjeff/* 37112904Sjeff * Copyright (c) 1983, 1993 38164033Srwatson * The Regents of the University of California. All rights reserved. 39112904Sjeff * 40161678Sdavidxu * Redistribution and use in source and binary forms, with or without 41165369Sdavidxu * modification, are permitted provided that the following conditions 42161678Sdavidxu * are met: 43112904Sjeff * 1. Redistributions of source code must retain the above copyright 44112904Sjeff * notice, this list of conditions and the following disclaimer. 45112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright 46216641Sdavidxu * notice, this list of conditions and the following disclaimer in the 47139013Sdavidxu * documentation and/or other materials provided with the distribution. 48112904Sjeff * 4. Neither the name of the University nor the names of its contributors 49112904Sjeff * may be used to endorse or promote products derived from this software 50139013Sdavidxu * without specific prior written permission. 51139013Sdavidxu * 52139013Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53139013Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54139013Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55139013Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56165369Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57165369Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58205014Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59162536Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60162536Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61162536Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62179970Sdavidxu * SUCH DAMAGE. 63179970Sdavidxu */ 64179970Sdavidxu/* 65161678Sdavidxu * based on sbin/ifconfig/ifmedia.c r221954 66161678Sdavidxu */ 67161678Sdavidxu 68161678Sdavidxu#include <sys/param.h> 69161678Sdavidxu#include <sys/ioctl.h> 70161678Sdavidxu#include <sys/socket.h> 71161678Sdavidxu#include <sys/sysctl.h> 72161678Sdavidxu#include <sys/time.h> 73161678Sdavidxu 74161678Sdavidxu#include <net/if.h> 75161678Sdavidxu#include <net/if_dl.h> 76161678Sdavidxu#include <net/if_types.h> 77161678Sdavidxu#include <net/if_media.h> 78161678Sdavidxu#include <net/route.h> 79161678Sdavidxu 80161678Sdavidxu#include <ctype.h> 81161678Sdavidxu#include <err.h> 82161678Sdavidxu#include <errno.h> 83161678Sdavidxu#include <fcntl.h> 84161678Sdavidxu#include <stdio.h> 85161678Sdavidxu#include <stdlib.h> 86161678Sdavidxu#include <string.h> 87115765Sjeff#include <unistd.h> 88161678Sdavidxu 89161678Sdavidxuvoid domediaopt(const char *, int, int); 90161678Sdavidxuint get_media_subtype(int, const char *); 91161678Sdavidxuint get_media_mode(int, const char *); 92161678Sdavidxuint get_media_options(int, const char *); 93161678Sdavidxuint lookup_media_word(struct ifmedia_description *, const char *); 94161678Sdavidxuvoid print_media_word(int, int); 95161678Sdavidxuvoid print_media_word_ifconfig(int); 96161678Sdavidxu 97161678Sdavidxu#if 0 98161678Sdavidxustatic struct ifmedia_description *get_toptype_desc(int); 99161678Sdavidxustatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 100161678Sdavidxustatic struct ifmedia_description *get_subtype_desc(int, 101161678Sdavidxu struct ifmedia_type_to_subtype *ttos); 102161678Sdavidxu 103170300Sjeff#define IFM_OPMODE(x) \ 104170300Sjeff ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 105161678Sdavidxu IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 106161678Sdavidxu IFM_IEEE80211_MBSS)) 107161678Sdavidxu#define IFM_IEEE80211_STA 0 108161678Sdavidxu 109161678Sdavidxustatic void 110161678Sdavidxumedia_status(int s) 111161678Sdavidxu{ 112161678Sdavidxu struct ifmediareq ifmr; 113161678Sdavidxu int *media_list, i; 114161742Sdavidxu 115161678Sdavidxu (void) memset(&ifmr, 0, sizeof(ifmr)); 116201991Sdavidxu (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 117201991Sdavidxu 118201991Sdavidxu if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 119201991Sdavidxu /* 120201991Sdavidxu * Interface doesn't support SIOC{G,S}IFMEDIA. 121201991Sdavidxu */ 122115765Sjeff return; 123115765Sjeff } 124161678Sdavidxu 125161678Sdavidxu if (ifmr.ifm_count == 0) { 126201991Sdavidxu warnx("%s: no media types?", name); 127201991Sdavidxu return; 128201991Sdavidxu } 129201991Sdavidxu 130201991Sdavidxu media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 131201991Sdavidxu if (media_list == NULL) 132201991Sdavidxu err(1, "malloc"); 133201991Sdavidxu ifmr.ifm_ulist = media_list; 134201991Sdavidxu 135201991Sdavidxu if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 136161678Sdavidxu err(1, "SIOCGIFMEDIA"); 137138224Sdavidxu 138161678Sdavidxu printf("\tmedia: "); 139161678Sdavidxu print_media_word(ifmr.ifm_current, 1); 140161678Sdavidxu if (ifmr.ifm_active != ifmr.ifm_current) { 141161678Sdavidxu putchar(' '); 142201991Sdavidxu putchar('('); 143177848Sdavidxu print_media_word(ifmr.ifm_active, 0); 144177848Sdavidxu putchar(')'); 145161678Sdavidxu } 146201991Sdavidxu 147201991Sdavidxu putchar('\n'); 148161678Sdavidxu 149161678Sdavidxu if (ifmr.ifm_status & IFM_AVALID) { 150161678Sdavidxu printf("\tstatus: "); 151161678Sdavidxu switch (IFM_TYPE(ifmr.ifm_active)) { 152158377Sdavidxu case IFM_ETHER: 153161678Sdavidxu case IFM_ATM: 154161678Sdavidxu if (ifmr.ifm_status & IFM_ACTIVE) 155161678Sdavidxu printf("active"); 156201991Sdavidxu else 157138224Sdavidxu printf("no carrier"); 158115765Sjeff break; 159161678Sdavidxu 160189756Sdavidxu case IFM_FDDI: 161161678Sdavidxu case IFM_TOKEN: 162161678Sdavidxu if (ifmr.ifm_status & IFM_ACTIVE) 163161678Sdavidxu printf("inserted"); 164161678Sdavidxu else 165161678Sdavidxu printf("no ring"); 166161678Sdavidxu break; 167161678Sdavidxu 168161678Sdavidxu case IFM_IEEE80211: 169161678Sdavidxu if (ifmr.ifm_status & IFM_ACTIVE) { 170161678Sdavidxu /* NB: only sta mode associates */ 171163709Sjb if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 172163709Sjb printf("associated"); 173163709Sjb else 174161678Sdavidxu printf("running"); 175138224Sdavidxu } else 176216678Sdavidxu printf("no carrier"); 177216678Sdavidxu break; 178115765Sjeff } 179161678Sdavidxu putchar('\n'); 180161678Sdavidxu } 181161678Sdavidxu 182177848Sdavidxu if (ifmr.ifm_count > 0 && supmedia) { 183177848Sdavidxu printf("\tsupported media:\n"); 184161678Sdavidxu for (i = 0; i < ifmr.ifm_count; i++) { 185179421Sdavidxu printf("\t\t"); 186138224Sdavidxu print_media_word_ifconfig(media_list[i]); 187161678Sdavidxu putchar('\n'); 188115310Sjeff } 189161678Sdavidxu } 190161678Sdavidxu 191161678Sdavidxu free(media_list); 192161678Sdavidxu} 193161678Sdavidxu 194161678Sdavidxustruct ifmediareq * 195161678Sdavidxuifmedia_getstate(int s) 196139013Sdavidxu{ 197139013Sdavidxu static struct ifmediareq *ifmr = NULL; 198139257Sdavidxu int *mwords; 199139257Sdavidxu 200177848Sdavidxu if (ifmr == NULL) { 201177848Sdavidxu ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 202161678Sdavidxu if (ifmr == NULL) 203139257Sdavidxu err(1, "malloc"); 204163697Sdavidxu 205161678Sdavidxu (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 206161678Sdavidxu (void) strncpy(ifmr->ifm_name, name, 207161678Sdavidxu sizeof(ifmr->ifm_name)); 208161678Sdavidxu 209161678Sdavidxu ifmr->ifm_count = 0; 210161678Sdavidxu ifmr->ifm_ulist = NULL; 211115310Sjeff 212177848Sdavidxu /* 213177848Sdavidxu * We must go through the motions of reading all 214177848Sdavidxu * supported media because we need to know both 215177848Sdavidxu * the current media type and the top-level type. 216170300Sjeff */ 217170300Sjeff 218161678Sdavidxu if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 219161678Sdavidxu err(1, "SIOCGIFMEDIA"); 220161678Sdavidxu } 221179421Sdavidxu 222138224Sdavidxu if (ifmr->ifm_count == 0) 223161678Sdavidxu errx(1, "%s: no media types?", name); 224161678Sdavidxu 225179421Sdavidxu mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 226179421Sdavidxu if (mwords == NULL) 227179421Sdavidxu err(1, "malloc"); 228179421Sdavidxu 229201991Sdavidxu ifmr->ifm_ulist = mwords; 230201991Sdavidxu if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 231201991Sdavidxu err(1, "SIOCGIFMEDIA"); 232179421Sdavidxu } 233179421Sdavidxu 234179421Sdavidxu return ifmr; 235179421Sdavidxu} 236161678Sdavidxu 237170300Sjeffstatic void 238161678Sdavidxusetifmediacallback(int s, void *arg) 239161678Sdavidxu{ 240161678Sdavidxu struct ifmediareq *ifmr = (struct ifmediareq *)arg; 241161678Sdavidxu static int did_it = 0; 242143149Sdavidxu 243143149Sdavidxu if (!did_it) { 244143149Sdavidxu ifr.ifr_media = ifmr->ifm_current; 245161678Sdavidxu if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 246161678Sdavidxu err(1, "SIOCSIFMEDIA (media)"); 247161678Sdavidxu free(ifmr->ifm_ulist); 248201991Sdavidxu free(ifmr); 249201991Sdavidxu did_it = 1; 250161678Sdavidxu } 251161678Sdavidxu} 252161678Sdavidxu 253143149Sdavidxustatic void 254143149Sdavidxusetmedia(const char *val, int d, int s, const struct afswtch *afp) 255143149Sdavidxu{ 256143149Sdavidxu struct ifmediareq *ifmr; 257143149Sdavidxu int subtype; 258201991Sdavidxu 259201991Sdavidxu ifmr = ifmedia_getstate(s); 260143149Sdavidxu 261143149Sdavidxu /* 262143149Sdavidxu * We are primarily concerned with the top-level type. 263161678Sdavidxu * However, "current" may be only IFM_NONE, so we just look 264139013Sdavidxu * for the top-level type in the first "supported type" 265138224Sdavidxu * entry. 266161678Sdavidxu * 267161678Sdavidxu * (I'm assuming that all supported media types for a given 268138224Sdavidxu * interface will be the same top-level type..) 269138224Sdavidxu */ 270161678Sdavidxu subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 271161678Sdavidxu 272139013Sdavidxu strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 273201886Sdavidxu ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | 274179421Sdavidxu IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 275179421Sdavidxu 276139013Sdavidxu ifmr->ifm_current = ifr.ifr_media; 277139013Sdavidxu callback_register(setifmediacallback, (void *)ifmr); 278161678Sdavidxu} 279177848Sdavidxu 280161678Sdavidxustatic void 281138224Sdavidxusetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 282177848Sdavidxu{ 283139257Sdavidxu 284161678Sdavidxu domediaopt(val, 0, s); 285139257Sdavidxu} 286161678Sdavidxu 287177848Sdavidxustatic void 288139257Sdavidxuunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 289139257Sdavidxu{ 290161678Sdavidxu 291177848Sdavidxu domediaopt(val, 1, s); 292161678Sdavidxu} 293139257Sdavidxu 294177848Sdavidxustatic void 295139257Sdavidxudomediaopt(const char *val, int clear, int s) 296161678Sdavidxu{ 297139257Sdavidxu struct ifmediareq *ifmr; 298161678Sdavidxu int options; 299177848Sdavidxu 300139257Sdavidxu ifmr = ifmedia_getstate(s); 301139257Sdavidxu 302161678Sdavidxu options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 303177848Sdavidxu 304177848Sdavidxu strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 305161678Sdavidxu ifr.ifr_media = ifmr->ifm_current; 306139257Sdavidxu if (clear) 307177848Sdavidxu ifr.ifr_media &= ~options; 308138224Sdavidxu else { 309161678Sdavidxu if (options & IFM_HDX) { 310161678Sdavidxu ifr.ifr_media &= ~IFM_FDX; 311161678Sdavidxu options &= ~IFM_HDX; 312177848Sdavidxu } 313177848Sdavidxu ifr.ifr_media |= options; 314177880Sdavidxu } 315177880Sdavidxu ifmr->ifm_current = ifr.ifr_media; 316177880Sdavidxu callback_register(setifmediacallback, (void *)ifmr); 317177880Sdavidxu} 318177880Sdavidxu 319177880Sdavidxustatic void 320177880Sdavidxusetmediainst(const char *val, int d, int s, const struct afswtch *afp) 321177880Sdavidxu{ 322177880Sdavidxu struct ifmediareq *ifmr; 323177848Sdavidxu int inst; 324177880Sdavidxu 325177880Sdavidxu ifmr = ifmedia_getstate(s); 326177848Sdavidxu 327177848Sdavidxu inst = atoi(val); 328177848Sdavidxu if (inst < 0 || inst > (int)IFM_INST_MAX) 329177848Sdavidxu errx(1, "invalid media instance: %s", val); 330177848Sdavidxu 331177848Sdavidxu strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 332138224Sdavidxu ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 333138224Sdavidxu 334161678Sdavidxu ifmr->ifm_current = ifr.ifr_media; 335177848Sdavidxu callback_register(setifmediacallback, (void *)ifmr); 336161678Sdavidxu} 337138225Sdavidxu 338177848Sdavidxustatic void 339138224Sdavidxusetmediamode(const char *val, int d, int s, const struct afswtch *afp) 340161678Sdavidxu{ 341161678Sdavidxu struct ifmediareq *ifmr; 342161678Sdavidxu int mode; 343177848Sdavidxu 344177848Sdavidxu ifmr = ifmedia_getstate(s); 345177848Sdavidxu 346177848Sdavidxu mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 347177848Sdavidxu 348138224Sdavidxu strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 349138224Sdavidxu ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 350201991Sdavidxu 351201991Sdavidxu ifmr->ifm_current = ifr.ifr_media; 352201991Sdavidxu callback_register(setifmediacallback, (void *)ifmr); 353201991Sdavidxu} 354201991Sdavidxu#endif 355201991Sdavidxu 356201991Sdavidxu/********************************************************************** 357201991Sdavidxu * A good chunk of this is duplicated from sys/net/ifmedia.c 358201991Sdavidxu **********************************************************************/ 359201991Sdavidxu 360201991Sdavidxustatic struct ifmedia_description ifm_type_descriptions[] = 361201991Sdavidxu IFM_TYPE_DESCRIPTIONS; 362201991Sdavidxu 363201991Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 364201991Sdavidxu IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 365201991Sdavidxu 366139013Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 367177848Sdavidxu IFM_SUBTYPE_ETHERNET_ALIASES; 368115765Sjeff 369201991Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 370161678Sdavidxu IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 371139013Sdavidxu 372161678Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 373161678Sdavidxu IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 374201991Sdavidxu 375203744Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 376201991Sdavidxu IFM_SUBTYPE_TOKENRING_ALIASES; 377201991Sdavidxu 378201991Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 379201991Sdavidxu IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 380201991Sdavidxu 381201991Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 382201991Sdavidxu IFM_SUBTYPE_FDDI_DESCRIPTIONS; 383201991Sdavidxu 384201991Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 385201991Sdavidxu IFM_SUBTYPE_FDDI_ALIASES; 386201991Sdavidxu 387158718Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 388201991Sdavidxu IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 389201991Sdavidxu 390139013Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 391139013Sdavidxu IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 392139013Sdavidxu 393177848Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 394139013Sdavidxu IFM_SUBTYPE_IEEE80211_ALIASES; 395161678Sdavidxu 396201991Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 397161678Sdavidxu IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 398161678Sdavidxu 399161678Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 400158718Sdavidxu IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 401201991Sdavidxu 402201991Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 403201991Sdavidxu IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 404158718Sdavidxu 405201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 406201991Sdavidxu IFM_SUBTYPE_ATM_DESCRIPTIONS; 407201991Sdavidxu 408201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_aliases[] = 409201991Sdavidxu IFM_SUBTYPE_ATM_ALIASES; 410201991Sdavidxu 411201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 412201991Sdavidxu IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 413201991Sdavidxu 414201991Sdavidxustatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 415201991Sdavidxu IFM_SUBTYPE_SHARED_DESCRIPTIONS; 416139013Sdavidxu 417139013Sdavidxustatic struct ifmedia_description ifm_subtype_shared_aliases[] = 418139013Sdavidxu IFM_SUBTYPE_SHARED_ALIASES; 419161678Sdavidxu 420161678Sdavidxustatic struct ifmedia_description ifm_shared_option_descriptions[] = 421161678Sdavidxu IFM_SHARED_OPTION_DESCRIPTIONS; 422139013Sdavidxu 423139013Sdavidxustatic struct ifmedia_description ifm_shared_option_aliases[] = 424139013Sdavidxu IFM_SHARED_OPTION_ALIASES; 425161678Sdavidxu 426201991Sdavidxustruct ifmedia_type_to_subtype { 427115765Sjeff struct { 428161678Sdavidxu struct ifmedia_description *desc; 429161678Sdavidxu int alias; 430201991Sdavidxu } subtypes[5]; 431201991Sdavidxu struct { 432201991Sdavidxu struct ifmedia_description *desc; 433201991Sdavidxu int alias; 434115765Sjeff } options[4]; 435115765Sjeff struct { 436161678Sdavidxu struct ifmedia_description *desc; 437161678Sdavidxu int alias; 438161678Sdavidxu } modes[3]; 439161678Sdavidxu}; 440139257Sdavidxu 441161678Sdavidxu/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 442161678Sdavidxustatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 443161678Sdavidxu { 444201991Sdavidxu { 445161678Sdavidxu { &ifm_subtype_shared_descriptions[0], 0 }, 446161678Sdavidxu { &ifm_subtype_shared_aliases[0], 1 }, 447161678Sdavidxu { &ifm_subtype_ethernet_descriptions[0], 0 }, 448161678Sdavidxu { &ifm_subtype_ethernet_aliases[0], 1 }, 449201991Sdavidxu { NULL, 0 }, 450201991Sdavidxu }, 451201991Sdavidxu { 452201991Sdavidxu { &ifm_shared_option_descriptions[0], 0 }, 453161678Sdavidxu { &ifm_shared_option_aliases[0], 1 }, 454201991Sdavidxu { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 455161678Sdavidxu { NULL, 0 }, 456161678Sdavidxu }, 457161678Sdavidxu { 458161678Sdavidxu { NULL, 0 }, 459161678Sdavidxu }, 460177848Sdavidxu }, 461161678Sdavidxu { 462177848Sdavidxu { 463115765Sjeff { &ifm_subtype_shared_descriptions[0], 0 }, 464161678Sdavidxu { &ifm_subtype_shared_aliases[0], 1 }, 465201991Sdavidxu { &ifm_subtype_tokenring_descriptions[0], 0 }, 466201991Sdavidxu { &ifm_subtype_tokenring_aliases[0], 1 }, 467161678Sdavidxu { NULL, 0 }, 468115765Sjeff }, 469139257Sdavidxu { 470161678Sdavidxu { &ifm_shared_option_descriptions[0], 0 }, 471161678Sdavidxu { &ifm_shared_option_aliases[0], 1 }, 472201991Sdavidxu { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 473201991Sdavidxu { NULL, 0 }, 474201991Sdavidxu }, 475177848Sdavidxu { 476161678Sdavidxu { NULL, 0 }, 477139257Sdavidxu }, 478201991Sdavidxu }, 479139013Sdavidxu { 480139013Sdavidxu { 481139257Sdavidxu { &ifm_subtype_shared_descriptions[0], 0 }, 482138224Sdavidxu { &ifm_subtype_shared_aliases[0], 1 }, 483138224Sdavidxu { &ifm_subtype_fddi_descriptions[0], 0 }, 484177848Sdavidxu { &ifm_subtype_fddi_aliases[0], 1 }, 485161678Sdavidxu { NULL, 0 }, 486161678Sdavidxu }, 487161678Sdavidxu { 488161678Sdavidxu { &ifm_shared_option_descriptions[0], 0 }, 489161678Sdavidxu { &ifm_shared_option_aliases[0], 1 }, 490161678Sdavidxu { &ifm_subtype_fddi_option_descriptions[0], 0 }, 491161678Sdavidxu { NULL, 0 }, 492161678Sdavidxu }, 493161678Sdavidxu { 494161678Sdavidxu { NULL, 0 }, 495161678Sdavidxu }, 496161678Sdavidxu }, 497161678Sdavidxu { 498161678Sdavidxu { 499161678Sdavidxu { &ifm_subtype_shared_descriptions[0], 0 }, 500161678Sdavidxu { &ifm_subtype_shared_aliases[0], 1 }, 501161678Sdavidxu { &ifm_subtype_ieee80211_descriptions[0], 0 }, 502161678Sdavidxu { &ifm_subtype_ieee80211_aliases[0], 1 }, 503138224Sdavidxu { NULL, 0 }, 504161678Sdavidxu }, 505138224Sdavidxu { 506161678Sdavidxu { &ifm_shared_option_descriptions[0], 0 }, 507161678Sdavidxu { &ifm_shared_option_aliases[0], 1 }, 508161678Sdavidxu { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 509161678Sdavidxu { NULL, 0 }, 510161678Sdavidxu }, 511161678Sdavidxu { 512161678Sdavidxu { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 513161678Sdavidxu { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 514139751Sdavidxu { NULL, 0 }, 515139751Sdavidxu }, 516139751Sdavidxu }, 517138224Sdavidxu { 518138224Sdavidxu { 519161678Sdavidxu { &ifm_subtype_shared_descriptions[0], 0 }, 520161678Sdavidxu { &ifm_subtype_shared_aliases[0], 1 }, 521161678Sdavidxu { &ifm_subtype_atm_descriptions[0], 0 }, 522218969Sjhb { &ifm_subtype_atm_aliases[0], 1 }, 523161678Sdavidxu { NULL, 0 }, 524139013Sdavidxu }, 525161678Sdavidxu { 526139013Sdavidxu { &ifm_shared_option_descriptions[0], 0 }, 527139013Sdavidxu { &ifm_shared_option_aliases[0], 1 }, 528139013Sdavidxu { &ifm_subtype_atm_option_descriptions[0], 0 }, 529139013Sdavidxu { NULL, 0 }, 530139013Sdavidxu }, 531139013Sdavidxu { 532161678Sdavidxu { NULL, 0 }, 533161678Sdavidxu }, 534161678Sdavidxu }, 535161678Sdavidxu}; 536161678Sdavidxu 537163677Sdavidxuint 538163677Sdavidxuget_media_subtype(int type, const char *val) 539161678Sdavidxu{ 540161678Sdavidxu struct ifmedia_description *desc; 541161678Sdavidxu struct ifmedia_type_to_subtype *ttos; 542161678Sdavidxu int rval, i; 543161678Sdavidxu 544161678Sdavidxu /* Find the top-level interface type. */ 545161678Sdavidxu for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 546161678Sdavidxu desc->ifmt_string != NULL; desc++, ttos++) 547161678Sdavidxu if (type == desc->ifmt_word) 548161678Sdavidxu break; 549161678Sdavidxu if (desc->ifmt_string == NULL) 550161678Sdavidxu errx(1, "unknown media type 0x%x", type); 551161678Sdavidxu 552161678Sdavidxu for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 553161678Sdavidxu rval = lookup_media_word(ttos->subtypes[i].desc, val); 554161678Sdavidxu if (rval != -1) 555161678Sdavidxu return (rval); 556161678Sdavidxu } 557161678Sdavidxu errx(1, "unknown media subtype: %s", val); 558161678Sdavidxu /*NOTREACHED*/ 559139013Sdavidxu} 560139013Sdavidxu 561161678Sdavidxuint 562139013Sdavidxuget_media_mode(int type, const char *val) 563139013Sdavidxu{ 564139013Sdavidxu struct ifmedia_description *desc; 565161678Sdavidxu struct ifmedia_type_to_subtype *ttos; 566161678Sdavidxu int rval, i; 567161678Sdavidxu 568218969Sjhb /* Find the top-level interface type. */ 569139013Sdavidxu for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 570139013Sdavidxu desc->ifmt_string != NULL; desc++, ttos++) 571161678Sdavidxu if (type == desc->ifmt_word) 572139013Sdavidxu break; 573139013Sdavidxu if (desc->ifmt_string == NULL) 574139013Sdavidxu errx(1, "unknown media mode 0x%x", type); 575161678Sdavidxu 576161678Sdavidxu for (i = 0; ttos->modes[i].desc != NULL; i++) { 577161678Sdavidxu rval = lookup_media_word(ttos->modes[i].desc, val); 578139013Sdavidxu if (rval != -1) 579163449Sdavidxu return (rval); 580112904Sjeff } 581143149Sdavidxu return -1; 582163449Sdavidxu} 583163449Sdavidxu 584138224Sdavidxuint 585112904Sjeffget_media_options(int type, const char *val) 586143149Sdavidxu{ 587161678Sdavidxu struct ifmedia_description *desc; 588112904Sjeff struct ifmedia_type_to_subtype *ttos; 589161678Sdavidxu char *optlist, *optptr; 590112904Sjeff int option = 0, i, rval = 0; 591112904Sjeff 592112904Sjeff /* We muck with the string, so copy it. */ 593112904Sjeff optlist = strdup(val); 594112904Sjeff if (optlist == NULL) 595112904Sjeff err(1, "strdup"); 596163449Sdavidxu 597112904Sjeff /* Find the top-level interface type. */ 598138224Sdavidxu for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 599138224Sdavidxu desc->ifmt_string != NULL; desc++, ttos++) 600138224Sdavidxu if (type == desc->ifmt_word) 601138224Sdavidxu break; 602115765Sjeff if (desc->ifmt_string == NULL) 603115765Sjeff errx(1, "unknown media type 0x%x", type); 604115765Sjeff 605115765Sjeff /* 606115765Sjeff * Look up the options in the user-provided comma-separated 607115765Sjeff * list. 608163449Sdavidxu */ 609139013Sdavidxu optptr = optlist; 610115765Sjeff for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 611138224Sdavidxu for (i = 0; ttos->options[i].desc != NULL; i++) { 612138224Sdavidxu option = lookup_media_word(ttos->options[i].desc, optptr); 613138224Sdavidxu if (option != -1) 614115765Sjeff break; 615115765Sjeff } 616115765Sjeff if (option == 0) 617115765Sjeff errx(1, "unknown option: %s", optptr); 618115765Sjeff rval |= option; 619115765Sjeff } 620112904Sjeff 621112904Sjeff free(optlist); 622138224Sdavidxu return (rval); 623138224Sdavidxu} 624138224Sdavidxu 625138224Sdavidxuint 626161678Sdavidxulookup_media_word(struct ifmedia_description *desc, const char *val) 627138224Sdavidxu{ 628112904Sjeff 629161678Sdavidxu for (; desc->ifmt_string != NULL; desc++) 630161678Sdavidxu if (strcasecmp(desc->ifmt_string, val) == 0) 631161678Sdavidxu return (desc->ifmt_word); 632161678Sdavidxu 633161678Sdavidxu return (-1); 634161678Sdavidxu} 635161678Sdavidxu 636161678Sdavidxustatic struct ifmedia_description *get_toptype_desc(int ifmw) 637161678Sdavidxu{ 638161678Sdavidxu struct ifmedia_description *desc; 639112904Sjeff 640112904Sjeff for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 641112904Sjeff if (IFM_TYPE(ifmw) == desc->ifmt_word) 642112904Sjeff break; 643112904Sjeff 644112904Sjeff return desc; 645163449Sdavidxu} 646112904Sjeff 647112904Sjeffstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 648112967Sjake{ 649143149Sdavidxu struct ifmedia_description *desc; 650143149Sdavidxu struct ifmedia_type_to_subtype *ttos; 651143149Sdavidxu 652143149Sdavidxu for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 653115765Sjeff desc->ifmt_string != NULL; desc++, ttos++) 654112904Sjeff if (IFM_TYPE(ifmw) == desc->ifmt_word) 655112904Sjeff break; 656112904Sjeff 657115765Sjeff return ttos; 658117685Smtm} 659117685Smtm 660112904Sjeffstatic struct ifmedia_description *get_subtype_desc(int ifmw, 661143149Sdavidxu struct ifmedia_type_to_subtype *ttos) 662161678Sdavidxu{ 663161678Sdavidxu int i; 664143149Sdavidxu struct ifmedia_description *desc; 665143149Sdavidxu 666143149Sdavidxu for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 667112904Sjeff if (ttos->subtypes[i].alias) 668117743Smtm continue; 669117743Smtm for (desc = ttos->subtypes[i].desc; 670112904Sjeff desc->ifmt_string != NULL; desc++) { 671112904Sjeff if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 672161678Sdavidxu return desc; 673161678Sdavidxu } 674161678Sdavidxu } 675139013Sdavidxu 676163449Sdavidxu return NULL; 677140245Sdavidxu} 678112904Sjeff 679140245Sdavidxustatic struct ifmedia_description *get_mode_desc(int ifmw, 680139013Sdavidxu struct ifmedia_type_to_subtype *ttos) 681140245Sdavidxu{ 682139013Sdavidxu int i; 683140245Sdavidxu struct ifmedia_description *desc; 684162536Sdavidxu 685162030Sdavidxu for (i = 0; ttos->modes[i].desc != NULL; i++) { 686162030Sdavidxu if (ttos->modes[i].alias) 687162030Sdavidxu continue; 688139013Sdavidxu for (desc = ttos->modes[i].desc; 689140245Sdavidxu desc->ifmt_string != NULL; desc++) { 690140245Sdavidxu if (IFM_MODE(ifmw) == desc->ifmt_word) 691140245Sdavidxu return desc; 692139013Sdavidxu } 693162536Sdavidxu } 694140245Sdavidxu 695140245Sdavidxu return NULL; 696140245Sdavidxu} 697140245Sdavidxu 698139751Sdavidxuvoid 699139013Sdavidxuprint_media_word(int ifmw, int print_toptype) 700139013Sdavidxu{ 701140245Sdavidxu struct ifmedia_description *desc; 702140245Sdavidxu struct ifmedia_type_to_subtype *ttos; 703140245Sdavidxu int seen_option = 0, i; 704139013Sdavidxu 705162030Sdavidxu /* Find the top-level interface type. */ 706162030Sdavidxu desc = get_toptype_desc(ifmw); 707162030Sdavidxu ttos = get_toptype_ttos(ifmw); 708139013Sdavidxu if (desc->ifmt_string == NULL) { 709139013Sdavidxu printf("<unknown type>"); 710139013Sdavidxu return; 711139013Sdavidxu } else if (print_toptype) { 712161678Sdavidxu printf("%s", desc->ifmt_string); 713161678Sdavidxu } 714161678Sdavidxu 715139013Sdavidxu /* 716163449Sdavidxu * Don't print the top-level type; it's not like we can 717139013Sdavidxu * change it, or anything. 718139013Sdavidxu */ 719163449Sdavidxu 720163449Sdavidxu /* Find subtype. */ 721139257Sdavidxu desc = get_subtype_desc(ifmw, ttos); 722139257Sdavidxu if (desc == NULL) { 723112904Sjeff printf("<unknown subtype>"); 724112904Sjeff return; 725112904Sjeff } 726112904Sjeff 727163449Sdavidxu if (print_toptype) 728161678Sdavidxu putchar(' '); 729115765Sjeff 730115765Sjeff printf("%s", desc->ifmt_string); 731139013Sdavidxu 732115765Sjeff if (print_toptype) { 733112904Sjeff desc = get_mode_desc(ifmw, ttos); 734161678Sdavidxu if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 735161678Sdavidxu printf(" mode %s", desc->ifmt_string); 736163449Sdavidxu } 737161678Sdavidxu 738161678Sdavidxu /* Find options. */ 739161678Sdavidxu for (i = 0; ttos->options[i].desc != NULL; i++) { 740161678Sdavidxu if (ttos->options[i].alias) 741161855Sdavidxu continue; 742161678Sdavidxu for (desc = ttos->options[i].desc; 743161678Sdavidxu desc->ifmt_string != NULL; desc++) { 744117685Smtm if (ifmw & desc->ifmt_word) { 745161678Sdavidxu if (seen_option == 0) 746161678Sdavidxu printf(" <"); 747139257Sdavidxu printf("%s%s", seen_option++ ? "," : "", 748139257Sdavidxu desc->ifmt_string); 749139257Sdavidxu } 750139257Sdavidxu } 751139257Sdavidxu } 752139257Sdavidxu printf("%s", seen_option ? ">" : ""); 753139257Sdavidxu 754117743Smtm if (print_toptype && IFM_INST(ifmw) != 0) 755117743Smtm printf(" instance %d", IFM_INST(ifmw)); 756117743Smtm} 757117743Smtm 758117743Smtmvoid 759163449Sdavidxuprint_media_word_ifconfig(int ifmw) 760163449Sdavidxu{ 761139257Sdavidxu struct ifmedia_description *desc; 762161678Sdavidxu struct ifmedia_type_to_subtype *ttos; 763139257Sdavidxu int seen_option = 0, i; 764139257Sdavidxu 765139257Sdavidxu /* Find the top-level interface type. */ 766115765Sjeff desc = get_toptype_desc(ifmw); 767115765Sjeff ttos = get_toptype_ttos(ifmw); 768138224Sdavidxu if (desc->ifmt_string == NULL) { 769138224Sdavidxu printf("<unknown type>"); 770115765Sjeff return; 771112904Sjeff } 772139013Sdavidxu 773205014Snwhitehorn /* 774162536Sdavidxu * Don't print the top-level type; it's not like we can 775161678Sdavidxu * change it, or anything. 776162536Sdavidxu */ 777162536Sdavidxu 778162536Sdavidxu /* Find subtype. */ 779162536Sdavidxu desc = get_subtype_desc(ifmw, ttos); 780162536Sdavidxu if (desc == NULL) { 781162536Sdavidxu printf("<unknown subtype>"); 782162536Sdavidxu return; 783162536Sdavidxu } 784162536Sdavidxu 785162536Sdavidxu printf("media %s", desc->ifmt_string); 786162536Sdavidxu 787162536Sdavidxu desc = get_mode_desc(ifmw, ttos); 788162536Sdavidxu if (desc != NULL) 789162536Sdavidxu printf(" mode %s", desc->ifmt_string); 790162536Sdavidxu 791162536Sdavidxu /* Find options. */ 792162536Sdavidxu for (i = 0; ttos->options[i].desc != NULL; i++) { 793162536Sdavidxu if (ttos->options[i].alias) 794162536Sdavidxu continue; 795162536Sdavidxu for (desc = ttos->options[i].desc; 796162536Sdavidxu desc->ifmt_string != NULL; desc++) { 797162536Sdavidxu if (ifmw & desc->ifmt_word) { 798162536Sdavidxu if (seen_option == 0) 799162536Sdavidxu printf(" mediaopt "); 800162536Sdavidxu printf("%s%s", seen_option++ ? "," : "", 801162536Sdavidxu desc->ifmt_string); 802162536Sdavidxu } 803162536Sdavidxu } 804162536Sdavidxu } 805162536Sdavidxu 806162536Sdavidxu if (IFM_INST(ifmw) != 0) 807162536Sdavidxu printf(" instance %d", IFM_INST(ifmw)); 808162536Sdavidxu} 809162536Sdavidxu 810162536Sdavidxu/********************************************************************** 811162536Sdavidxu * ...until here. 812162536Sdavidxu **********************************************************************/ 813162536Sdavidxu