ifmedia.c revision 170531
1221167Sgnn/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2221167Sgnn/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 170531 2007-06-11 03:56:33Z sam $ */ 3221167Sgnn 4221167Sgnn/* 5221167Sgnn * Copyright (c) 1997 Jason R. Thorpe. 6221167Sgnn * All rights reserved. 7221167Sgnn * 8221167Sgnn * Redistribution and use in source and binary forms, with or without 9221167Sgnn * modification, are permitted provided that the following conditions 10221167Sgnn * are met: 11221167Sgnn * 1. Redistributions of source code must retain the above copyright 12221167Sgnn * notice, this list of conditions and the following disclaimer. 13221167Sgnn * 2. Redistributions in binary form must reproduce the above copyright 14221167Sgnn * notice, this list of conditions and the following disclaimer in the 15221167Sgnn * documentation and/or other materials provided with the distribution. 16221167Sgnn * 3. All advertising materials mentioning features or use of this software 17221167Sgnn * must display the following acknowledgement: 18221167Sgnn * This product includes software developed for the NetBSD Project 19221167Sgnn * by Jason R. Thorpe. 20221167Sgnn * 4. The name of the author may not be used to endorse or promote products 21221167Sgnn * derived from this software without specific prior written permission. 22221167Sgnn * 23221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24221167Sgnn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25221167Sgnn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26221167Sgnn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27221167Sgnn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28221167Sgnn * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29221167Sgnn * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30221167Sgnn * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31221167Sgnn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32221167Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33221167Sgnn * SUCH DAMAGE. 34221167Sgnn */ 35221167Sgnn 36221167Sgnn/* 37221167Sgnn * Copyright (c) 1983, 1993 38221167Sgnn * The Regents of the University of California. All rights reserved. 39221167Sgnn * 40221167Sgnn * Redistribution and use in source and binary forms, with or without 41221167Sgnn * modification, are permitted provided that the following conditions 42221167Sgnn * are met: 43221167Sgnn * 1. Redistributions of source code must retain the above copyright 44221167Sgnn * notice, this list of conditions and the following disclaimer. 45221167Sgnn * 2. Redistributions in binary form must reproduce the above copyright 46221167Sgnn * notice, this list of conditions and the following disclaimer in the 47221167Sgnn * documentation and/or other materials provided with the distribution. 48221167Sgnn * 3. All advertising materials mentioning features or use of this software 49221167Sgnn * must display the following acknowledgement: 50221167Sgnn * This product includes software developed by the University of 51221167Sgnn * California, Berkeley and its contributors. 52221167Sgnn * 4. Neither the name of the University nor the names of its contributors 53221167Sgnn * may be used to endorse or promote products derived from this software 54221167Sgnn * without specific prior written permission. 55221167Sgnn * 56221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57221167Sgnn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58221167Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59221167Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60221167Sgnn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61221167Sgnn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62221167Sgnn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63221167Sgnn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64221167Sgnn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65221167Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66221167Sgnn * SUCH DAMAGE. 67221167Sgnn */ 68221167Sgnn 69221167Sgnn#include <sys/param.h> 70221167Sgnn#include <sys/ioctl.h> 71221167Sgnn#include <sys/socket.h> 72221167Sgnn#include <sys/sysctl.h> 73221167Sgnn#include <sys/time.h> 74221167Sgnn 75221167Sgnn#include <net/if.h> 76221167Sgnn#include <net/if_dl.h> 77221167Sgnn#include <net/if_types.h> 78221167Sgnn#include <net/if_media.h> 79221167Sgnn#include <net/route.h> 80221167Sgnn 81221167Sgnn#include <ctype.h> 82221167Sgnn#include <err.h> 83221167Sgnn#include <errno.h> 84221167Sgnn#include <fcntl.h> 85221167Sgnn#include <stdio.h> 86221167Sgnn#include <stdlib.h> 87221167Sgnn#include <string.h> 88221167Sgnn#include <unistd.h> 89221167Sgnn 90221167Sgnn#include "ifconfig.h" 91221167Sgnn 92221167Sgnnstatic void domediaopt(const char *, int, int); 93221167Sgnnstatic int get_media_subtype(int, const char *); 94221167Sgnnstatic int get_media_mode(int, const char *); 95221167Sgnnstatic int get_media_options(int, const char *); 96221167Sgnnstatic int lookup_media_word(struct ifmedia_description *, const char *); 97221167Sgnnstatic void print_media_word(int, int); 98221167Sgnnstatic void print_media_word_ifconfig(int); 99221167Sgnn 100221167Sgnnstatic struct ifmedia_description *get_toptype_desc(int); 101221167Sgnnstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int); 102221167Sgnnstatic struct ifmedia_description *get_subtype_desc(int, 103221167Sgnn struct ifmedia_type_to_subtype *ttos); 104221167Sgnn 105221167Sgnnstatic void 106221167Sgnnmedia_status(int s) 107221167Sgnn{ 108221167Sgnn struct ifmediareq ifmr; 109221167Sgnn int *media_list, i; 110221167Sgnn 111221167Sgnn (void) memset(&ifmr, 0, sizeof(ifmr)); 112221167Sgnn (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 113221167Sgnn 114221167Sgnn if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 115221167Sgnn /* 116221167Sgnn * Interface doesn't support SIOC{G,S}IFMEDIA. 117221167Sgnn */ 118221167Sgnn return; 119221167Sgnn } 120221167Sgnn 121221167Sgnn if (ifmr.ifm_count == 0) { 122221167Sgnn warnx("%s: no media types?", name); 123221167Sgnn return; 124221167Sgnn } 125221167Sgnn 126221167Sgnn media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 127221167Sgnn if (media_list == NULL) 128221167Sgnn err(1, "malloc"); 129221167Sgnn ifmr.ifm_ulist = media_list; 130221167Sgnn 131221167Sgnn if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 132221167Sgnn err(1, "SIOCGIFMEDIA"); 133221167Sgnn 134221167Sgnn printf("\tmedia: "); 135221167Sgnn print_media_word(ifmr.ifm_current, 1); 136221167Sgnn if (ifmr.ifm_active != ifmr.ifm_current) { 137221167Sgnn putchar(' '); 138221167Sgnn putchar('('); 139221167Sgnn print_media_word(ifmr.ifm_active, 0); 140221167Sgnn putchar(')'); 141221167Sgnn } 142221167Sgnn 143221167Sgnn putchar('\n'); 144221167Sgnn 145221167Sgnn if (ifmr.ifm_status & IFM_AVALID) { 146221167Sgnn printf("\tstatus: "); 147221167Sgnn switch (IFM_TYPE(ifmr.ifm_active)) { 148221167Sgnn case IFM_ETHER: 149221167Sgnn case IFM_ATM: 150221167Sgnn if (ifmr.ifm_status & IFM_ACTIVE) 151221167Sgnn printf("active"); 152221167Sgnn else 153221167Sgnn printf("no carrier"); 154221167Sgnn break; 155221167Sgnn 156221167Sgnn case IFM_FDDI: 157221167Sgnn case IFM_TOKEN: 158221167Sgnn if (ifmr.ifm_status & IFM_ACTIVE) 159221167Sgnn printf("inserted"); 160221167Sgnn else 161221167Sgnn printf("no ring"); 162221167Sgnn break; 163221167Sgnn 164221167Sgnn case IFM_IEEE80211: 165221167Sgnn /* XXX: Different value for adhoc? */ 166221167Sgnn if (ifmr.ifm_status & IFM_ACTIVE) 167221167Sgnn printf("associated"); 168221167Sgnn else 169221167Sgnn printf("no carrier"); 170221167Sgnn break; 171221167Sgnn } 172221167Sgnn putchar('\n'); 173221167Sgnn } 174221167Sgnn 175221167Sgnn if (ifmr.ifm_count > 0 && supmedia) { 176221167Sgnn printf("\tsupported media:\n"); 177221167Sgnn for (i = 0; i < ifmr.ifm_count; i++) { 178221167Sgnn printf("\t\t"); 179221167Sgnn print_media_word_ifconfig(media_list[i]); 180221167Sgnn putchar('\n'); 181221167Sgnn } 182221167Sgnn } 183221167Sgnn 184221167Sgnn free(media_list); 185221167Sgnn} 186221167Sgnn 187221167Sgnnstruct ifmediareq * 188221167Sgnnifmedia_getstate(int s) 189221167Sgnn{ 190221167Sgnn static struct ifmediareq *ifmr = NULL; 191221167Sgnn int *mwords; 192221167Sgnn 193221167Sgnn if (ifmr == NULL) { 194221167Sgnn ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 195221167Sgnn if (ifmr == NULL) 196221167Sgnn err(1, "malloc"); 197221167Sgnn 198221167Sgnn (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 199221167Sgnn (void) strncpy(ifmr->ifm_name, name, 200221167Sgnn sizeof(ifmr->ifm_name)); 201221167Sgnn 202221167Sgnn ifmr->ifm_count = 0; 203221167Sgnn ifmr->ifm_ulist = NULL; 204221167Sgnn 205221167Sgnn /* 206221167Sgnn * We must go through the motions of reading all 207221167Sgnn * supported media because we need to know both 208221167Sgnn * the current media type and the top-level type. 209221167Sgnn */ 210221167Sgnn 211221167Sgnn if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 212221167Sgnn err(1, "SIOCGIFMEDIA"); 213221167Sgnn } 214221167Sgnn 215221167Sgnn if (ifmr->ifm_count == 0) 216221167Sgnn errx(1, "%s: no media types?", name); 217221167Sgnn 218221167Sgnn mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 219221167Sgnn if (mwords == NULL) 220221167Sgnn err(1, "malloc"); 221221167Sgnn 222221167Sgnn ifmr->ifm_ulist = mwords; 223221167Sgnn if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 224221167Sgnn err(1, "SIOCGIFMEDIA"); 225221167Sgnn } 226221167Sgnn 227221167Sgnn return ifmr; 228221167Sgnn} 229221167Sgnn 230221167Sgnnstatic void 231221167Sgnnsetifmediacallback(int s, void *arg) 232221167Sgnn{ 233221167Sgnn struct ifmediareq *ifmr = (struct ifmediareq *)arg; 234221167Sgnn static int did_it = 0; 235221167Sgnn 236221167Sgnn if (!did_it) { 237221167Sgnn ifr.ifr_media = ifmr->ifm_current; 238221167Sgnn if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 239221167Sgnn err(1, "SIOCSIFMEDIA (media)"); 240221167Sgnn free(ifmr->ifm_ulist); 241221167Sgnn free(ifmr); 242221167Sgnn did_it = 1; 243221167Sgnn } 244221167Sgnn} 245221167Sgnn 246221167Sgnnstatic void 247221167Sgnnsetmedia(const char *val, int d, int s, const struct afswtch *afp) 248221167Sgnn{ 249221167Sgnn struct ifmediareq *ifmr; 250221167Sgnn int subtype; 251221167Sgnn 252221167Sgnn ifmr = ifmedia_getstate(s); 253221167Sgnn 254221167Sgnn /* 255221167Sgnn * We are primarily concerned with the top-level type. 256221167Sgnn * However, "current" may be only IFM_NONE, so we just look 257221167Sgnn * for the top-level type in the first "supported type" 258221167Sgnn * entry. 259221167Sgnn * 260221167Sgnn * (I'm assuming that all supported media types for a given 261221167Sgnn * interface will be the same top-level type..) 262221167Sgnn */ 263221167Sgnn subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 264221167Sgnn 265221167Sgnn strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 266221167Sgnn ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 267221167Sgnn IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 268221167Sgnn 269221167Sgnn if ((ifr.ifr_media & IFM_TMASK) == 0) { 270221167Sgnn ifr.ifr_media &= ~IFM_GMASK; 271221167Sgnn } 272221167Sgnn 273221167Sgnn ifmr->ifm_current = ifr.ifr_media; 274221167Sgnn callback_register(setifmediacallback, (void *)ifmr); 275221167Sgnn} 276221167Sgnn 277221167Sgnnstatic void 278221167Sgnnsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 279221167Sgnn{ 280221167Sgnn 281221167Sgnn domediaopt(val, 0, s); 282221167Sgnn} 283221167Sgnn 284221167Sgnnstatic void 285221167Sgnnunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 286221167Sgnn{ 287221167Sgnn 288221167Sgnn domediaopt(val, 1, s); 289221167Sgnn} 290221167Sgnn 291221167Sgnnstatic void 292221167Sgnndomediaopt(const char *val, int clear, int s) 293221167Sgnn{ 294221167Sgnn struct ifmediareq *ifmr; 295221167Sgnn int options; 296221167Sgnn 297221167Sgnn ifmr = ifmedia_getstate(s); 298221167Sgnn 299221167Sgnn options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 300221167Sgnn 301221167Sgnn strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 302221167Sgnn ifr.ifr_media = ifmr->ifm_current; 303221167Sgnn if (clear) 304221167Sgnn ifr.ifr_media &= ~options; 305221167Sgnn else { 306221167Sgnn if (options & IFM_HDX) { 307221167Sgnn ifr.ifr_media &= ~IFM_FDX; 308221167Sgnn options &= ~IFM_HDX; 309221167Sgnn } 310221167Sgnn ifr.ifr_media |= options; 311221167Sgnn } 312221167Sgnn ifmr->ifm_current = ifr.ifr_media; 313221167Sgnn callback_register(setifmediacallback, (void *)ifmr); 314221167Sgnn} 315221167Sgnn 316221167Sgnnstatic void 317221167Sgnnsetmediainst(const char *val, int d, int s, const struct afswtch *afp) 318221167Sgnn{ 319221167Sgnn struct ifmediareq *ifmr; 320221167Sgnn int inst; 321221167Sgnn 322221167Sgnn ifmr = ifmedia_getstate(s); 323221167Sgnn 324221167Sgnn inst = atoi(val); 325221167Sgnn if (inst < 0 || inst > IFM_INST_MAX) 326221167Sgnn errx(1, "invalid media instance: %s", val); 327221167Sgnn 328221167Sgnn strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 329221167Sgnn ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 330221167Sgnn 331221167Sgnn ifmr->ifm_current = ifr.ifr_media; 332221167Sgnn callback_register(setifmediacallback, (void *)ifmr); 333221167Sgnn} 334221167Sgnn 335221167Sgnnstatic void 336221167Sgnnsetmediamode(const char *val, int d, int s, const struct afswtch *afp) 337221167Sgnn{ 338221167Sgnn struct ifmediareq *ifmr; 339221167Sgnn int mode; 340221167Sgnn 341221167Sgnn ifmr = ifmedia_getstate(s); 342221167Sgnn 343221167Sgnn mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 344221167Sgnn 345221167Sgnn strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 346221167Sgnn ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 347221167Sgnn 348221167Sgnn ifmr->ifm_current = ifr.ifr_media; 349221167Sgnn callback_register(setifmediacallback, (void *)ifmr); 350221167Sgnn} 351221167Sgnn 352221167Sgnn/********************************************************************** 353221167Sgnn * A good chunk of this is duplicated from sys/net/ifmedia.c 354221167Sgnn **********************************************************************/ 355221167Sgnn 356221167Sgnnstatic struct ifmedia_description ifm_type_descriptions[] = 357221167Sgnn IFM_TYPE_DESCRIPTIONS; 358221167Sgnn 359221167Sgnnstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 360221167Sgnn IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 361221167Sgnn 362221167Sgnnstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] = 363221167Sgnn IFM_SUBTYPE_ETHERNET_ALIASES; 364221167Sgnn 365221167Sgnnstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 366221167Sgnn IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 367221167Sgnn 368221167Sgnnstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 369221167Sgnn IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 370221167Sgnn 371221167Sgnnstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] = 372221167Sgnn IFM_SUBTYPE_TOKENRING_ALIASES; 373221167Sgnn 374221167Sgnnstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 375221167Sgnn IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 376221167Sgnn 377221167Sgnnstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] = 378221167Sgnn IFM_SUBTYPE_FDDI_DESCRIPTIONS; 379221167Sgnn 380221167Sgnnstatic struct ifmedia_description ifm_subtype_fddi_aliases[] = 381221167Sgnn IFM_SUBTYPE_FDDI_ALIASES; 382221167Sgnn 383221167Sgnnstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 384221167Sgnn IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 385221167Sgnn 386221167Sgnnstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 387221167Sgnn IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 388221167Sgnn 389221167Sgnnstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 390221167Sgnn IFM_SUBTYPE_IEEE80211_ALIASES; 391221167Sgnn 392221167Sgnnstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 393221167Sgnn IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 394221167Sgnn 395298955Spfgstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 396221167Sgnn IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 397221167Sgnn 398221167Sgnnstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 399221167Sgnn IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 400221167Sgnn 401221167Sgnnstatic struct ifmedia_description ifm_subtype_atm_descriptions[] = 402221167Sgnn IFM_SUBTYPE_ATM_DESCRIPTIONS; 403221167Sgnn 404221167Sgnnstatic struct ifmedia_description ifm_subtype_atm_aliases[] = 405221167Sgnn IFM_SUBTYPE_ATM_ALIASES; 406221167Sgnn 407221167Sgnnstatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 408221167Sgnn IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 409221167Sgnn 410221167Sgnnstatic struct ifmedia_description ifm_subtype_shared_descriptions[] = 411221167Sgnn IFM_SUBTYPE_SHARED_DESCRIPTIONS; 412221167Sgnn 413221167Sgnnstatic struct ifmedia_description ifm_subtype_shared_aliases[] = 414221167Sgnn IFM_SUBTYPE_SHARED_ALIASES; 415221167Sgnn 416221167Sgnnstatic struct ifmedia_description ifm_shared_option_descriptions[] = 417221167Sgnn IFM_SHARED_OPTION_DESCRIPTIONS; 418221167Sgnn 419221167Sgnnstruct ifmedia_type_to_subtype { 420221167Sgnn struct { 421221167Sgnn struct ifmedia_description *desc; 422221167Sgnn int alias; 423221167Sgnn } subtypes[5]; 424221167Sgnn struct { 425221167Sgnn struct ifmedia_description *desc; 426221167Sgnn int alias; 427221167Sgnn } options[3]; 428221167Sgnn struct { 429221167Sgnn struct ifmedia_description *desc; 430221167Sgnn int alias; 431221167Sgnn } modes[3]; 432221167Sgnn}; 433221167Sgnn 434221167Sgnn/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 435221167Sgnnstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 436221167Sgnn { 437221167Sgnn { 438221167Sgnn { &ifm_subtype_shared_descriptions[0], 0 }, 439221167Sgnn { &ifm_subtype_shared_aliases[0], 1 }, 440221167Sgnn { &ifm_subtype_ethernet_descriptions[0], 0 }, 441221167Sgnn { &ifm_subtype_ethernet_aliases[0], 1 }, 442221167Sgnn { NULL, 0 }, 443221167Sgnn }, 444221167Sgnn { 445221167Sgnn { &ifm_shared_option_descriptions[0], 0 }, 446221167Sgnn { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 447221167Sgnn { NULL, 0 }, 448221167Sgnn }, 449221167Sgnn { 450221167Sgnn { NULL, 0 }, 451221167Sgnn }, 452221167Sgnn }, 453221167Sgnn { 454221167Sgnn { 455221167Sgnn { &ifm_subtype_shared_descriptions[0], 0 }, 456221167Sgnn { &ifm_subtype_shared_aliases[0], 1 }, 457221167Sgnn { &ifm_subtype_tokenring_descriptions[0], 0 }, 458221167Sgnn { &ifm_subtype_tokenring_aliases[0], 1 }, 459221167Sgnn { NULL, 0 }, 460221167Sgnn }, 461221167Sgnn { 462221167Sgnn { &ifm_shared_option_descriptions[0], 0 }, 463221167Sgnn { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 464221167Sgnn { NULL, 0 }, 465221167Sgnn }, 466221167Sgnn { 467221167Sgnn { NULL, 0 }, 468221167Sgnn }, 469221167Sgnn }, 470221167Sgnn { 471221167Sgnn { 472221167Sgnn { &ifm_subtype_shared_descriptions[0], 0 }, 473221167Sgnn { &ifm_subtype_shared_aliases[0], 1 }, 474221167Sgnn { &ifm_subtype_fddi_descriptions[0], 0 }, 475221167Sgnn { &ifm_subtype_fddi_aliases[0], 1 }, 476221167Sgnn { NULL, 0 }, 477221167Sgnn }, 478221167Sgnn { 479221167Sgnn { &ifm_shared_option_descriptions[0], 0 }, 480221167Sgnn { &ifm_subtype_fddi_option_descriptions[0], 0 }, 481221167Sgnn { NULL, 0 }, 482221167Sgnn }, 483221167Sgnn { 484221167Sgnn { NULL, 0 }, 485221167Sgnn }, 486221167Sgnn }, 487221167Sgnn { 488221167Sgnn { 489221167Sgnn { &ifm_subtype_shared_descriptions[0], 0 }, 490221167Sgnn { &ifm_subtype_shared_aliases[0], 1 }, 491298955Spfg { &ifm_subtype_ieee80211_descriptions[0], 0 }, 492221167Sgnn { &ifm_subtype_ieee80211_aliases[0], 1 }, 493221167Sgnn { NULL, 0 }, 494221167Sgnn }, 495221167Sgnn { 496221167Sgnn { &ifm_shared_option_descriptions[0], 0 }, 497221167Sgnn { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 498221167Sgnn { NULL, 0 }, 499221167Sgnn }, 500221167Sgnn { 501221167Sgnn { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 502221167Sgnn { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 503221167Sgnn { NULL, 0 }, 504221167Sgnn }, 505221167Sgnn }, 506221167Sgnn { 507221167Sgnn { 508221167Sgnn { &ifm_subtype_shared_descriptions[0], 0 }, 509221167Sgnn { &ifm_subtype_shared_aliases[0], 1 }, 510221167Sgnn { &ifm_subtype_atm_descriptions[0], 0 }, 511221167Sgnn { &ifm_subtype_atm_aliases[0], 1 }, 512221167Sgnn { NULL, 0 }, 513221167Sgnn }, 514221167Sgnn { 515221167Sgnn { &ifm_shared_option_descriptions[0], 0 }, 516221167Sgnn { &ifm_subtype_atm_option_descriptions[0], 0 }, 517221167Sgnn { NULL, 0 }, 518221167Sgnn }, 519221167Sgnn { 520221167Sgnn { NULL, 0 }, 521221167Sgnn }, 522221167Sgnn }, 523221167Sgnn}; 524221167Sgnn 525221167Sgnnstatic int 526221167Sgnnget_media_subtype(int type, const char *val) 527221167Sgnn{ 528221167Sgnn struct ifmedia_description *desc; 529221167Sgnn struct ifmedia_type_to_subtype *ttos; 530221167Sgnn int rval, i; 531221167Sgnn 532221167Sgnn /* Find the top-level interface type. */ 533221167Sgnn for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 534221167Sgnn desc->ifmt_string != NULL; desc++, ttos++) 535221167Sgnn if (type == desc->ifmt_word) 536221167Sgnn break; 537221167Sgnn if (desc->ifmt_string == NULL) 538221167Sgnn errx(1, "unknown media type 0x%x", type); 539221167Sgnn 540221167Sgnn for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 541221167Sgnn rval = lookup_media_word(ttos->subtypes[i].desc, val); 542221167Sgnn if (rval != -1) 543221167Sgnn return (rval); 544221167Sgnn } 545221167Sgnn errx(1, "unknown media subtype: %s", val); 546221167Sgnn /*NOTREACHED*/ 547221167Sgnn} 548221167Sgnn 549221167Sgnnstatic int 550221167Sgnnget_media_mode(int type, const char *val) 551221167Sgnn{ 552221167Sgnn struct ifmedia_description *desc; 553221167Sgnn struct ifmedia_type_to_subtype *ttos; 554221167Sgnn int rval, i; 555221167Sgnn 556221167Sgnn /* Find the top-level interface type. */ 557221167Sgnn for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 558221167Sgnn desc->ifmt_string != NULL; desc++, ttos++) 559221167Sgnn if (type == desc->ifmt_word) 560221167Sgnn break; 561221167Sgnn if (desc->ifmt_string == NULL) 562221167Sgnn errx(1, "unknown media mode 0x%x", type); 563221167Sgnn 564221167Sgnn for (i = 0; ttos->modes[i].desc != NULL; i++) { 565221167Sgnn rval = lookup_media_word(ttos->modes[i].desc, val); 566221167Sgnn if (rval != -1) 567221167Sgnn return (rval); 568221167Sgnn } 569221167Sgnn return -1; 570221167Sgnn} 571221167Sgnn 572221167Sgnnstatic int 573221167Sgnnget_media_options(int type, const char *val) 574221167Sgnn{ 575221167Sgnn struct ifmedia_description *desc; 576221167Sgnn struct ifmedia_type_to_subtype *ttos; 577221167Sgnn char *optlist, *optptr; 578221167Sgnn int option = 0, i, rval = 0; 579221167Sgnn 580221167Sgnn /* We muck with the string, so copy it. */ 581221167Sgnn optlist = strdup(val); 582221167Sgnn if (optlist == NULL) 583221167Sgnn err(1, "strdup"); 584221167Sgnn 585221167Sgnn /* Find the top-level interface type. */ 586221167Sgnn for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 587221167Sgnn desc->ifmt_string != NULL; desc++, ttos++) 588221167Sgnn if (type == desc->ifmt_word) 589221167Sgnn break; 590221167Sgnn if (desc->ifmt_string == NULL) 591221167Sgnn errx(1, "unknown media type 0x%x", type); 592221167Sgnn 593221167Sgnn /* 594221167Sgnn * Look up the options in the user-provided comma-separated 595221167Sgnn * list. 596221167Sgnn */ 597221167Sgnn optptr = optlist; 598221167Sgnn for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 599 for (i = 0; ttos->options[i].desc != NULL; i++) { 600 option = lookup_media_word(ttos->options[i].desc, optptr); 601 if (option != -1) 602 break; 603 } 604 if (option == 0) 605 errx(1, "unknown option: %s", optptr); 606 rval |= option; 607 } 608 609 free(optlist); 610 return (rval); 611} 612 613static int 614lookup_media_word(struct ifmedia_description *desc, const char *val) 615{ 616 617 for (; desc->ifmt_string != NULL; desc++) 618 if (strcasecmp(desc->ifmt_string, val) == 0) 619 return (desc->ifmt_word); 620 621 return (-1); 622} 623 624static struct ifmedia_description *get_toptype_desc(int ifmw) 625{ 626 struct ifmedia_description *desc; 627 628 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 629 if (IFM_TYPE(ifmw) == desc->ifmt_word) 630 break; 631 632 return desc; 633} 634 635static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 636{ 637 struct ifmedia_description *desc; 638 struct ifmedia_type_to_subtype *ttos; 639 640 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 641 desc->ifmt_string != NULL; desc++, ttos++) 642 if (IFM_TYPE(ifmw) == desc->ifmt_word) 643 break; 644 645 return ttos; 646} 647 648static struct ifmedia_description *get_subtype_desc(int ifmw, 649 struct ifmedia_type_to_subtype *ttos) 650{ 651 int i; 652 struct ifmedia_description *desc; 653 654 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 655 if (ttos->subtypes[i].alias) 656 continue; 657 for (desc = ttos->subtypes[i].desc; 658 desc->ifmt_string != NULL; desc++) { 659 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 660 return desc; 661 } 662 } 663 664 return NULL; 665} 666 667static struct ifmedia_description *get_mode_desc(int ifmw, 668 struct ifmedia_type_to_subtype *ttos) 669{ 670 int i; 671 struct ifmedia_description *desc; 672 673 for (i = 0; ttos->modes[i].desc != NULL; i++) { 674 if (ttos->modes[i].alias) 675 continue; 676 for (desc = ttos->modes[i].desc; 677 desc->ifmt_string != NULL; desc++) { 678 if (IFM_MODE(ifmw) == desc->ifmt_word) 679 return desc; 680 } 681 } 682 683 return NULL; 684} 685 686static void 687print_media_word(int ifmw, int print_toptype) 688{ 689 struct ifmedia_description *desc; 690 struct ifmedia_type_to_subtype *ttos; 691 int seen_option = 0, i; 692 693 /* Find the top-level interface type. */ 694 desc = get_toptype_desc(ifmw); 695 ttos = get_toptype_ttos(ifmw); 696 if (desc->ifmt_string == NULL) { 697 printf("<unknown type>"); 698 return; 699 } else if (print_toptype) { 700 printf("%s", desc->ifmt_string); 701 } 702 703 /* 704 * Don't print the top-level type; it's not like we can 705 * change it, or anything. 706 */ 707 708 /* Find subtype. */ 709 desc = get_subtype_desc(ifmw, ttos); 710 if (desc == NULL) { 711 printf("<unknown subtype>"); 712 return; 713 } 714 715 if (print_toptype) 716 putchar(' '); 717 718 printf("%s", desc->ifmt_string); 719 720 if (print_toptype) { 721 desc = get_mode_desc(ifmw, ttos); 722 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 723 printf(" mode %s", desc->ifmt_string); 724 } 725 726 /* Find options. */ 727 for (i = 0; ttos->options[i].desc != NULL; i++) { 728 if (ttos->options[i].alias) 729 continue; 730 for (desc = ttos->options[i].desc; 731 desc->ifmt_string != NULL; desc++) { 732 if (ifmw & desc->ifmt_word) { 733 if (seen_option == 0) 734 printf(" <"); 735 printf("%s%s", seen_option++ ? "," : "", 736 desc->ifmt_string); 737 } 738 } 739 } 740 printf("%s", seen_option ? ">" : ""); 741 742 if (print_toptype && IFM_INST(ifmw) != 0) 743 printf(" instance %d", IFM_INST(ifmw)); 744} 745 746static void 747print_media_word_ifconfig(int ifmw) 748{ 749 struct ifmedia_description *desc; 750 struct ifmedia_type_to_subtype *ttos; 751 int i; 752 753 /* Find the top-level interface type. */ 754 desc = get_toptype_desc(ifmw); 755 ttos = get_toptype_ttos(ifmw); 756 if (desc->ifmt_string == NULL) { 757 printf("<unknown type>"); 758 return; 759 } 760 761 /* 762 * Don't print the top-level type; it's not like we can 763 * change it, or anything. 764 */ 765 766 /* Find subtype. */ 767 desc = get_subtype_desc(ifmw, ttos); 768 if (desc == NULL) { 769 printf("<unknown subtype>"); 770 return; 771 } 772 773 printf("media %s", desc->ifmt_string); 774 775 desc = get_mode_desc(ifmw, ttos); 776 if (desc != NULL) 777 printf(" mode %s", desc->ifmt_string); 778 779 /* Find options. */ 780 for (i = 0; ttos->options[i].desc != NULL; i++) { 781 if (ttos->options[i].alias) 782 continue; 783 for (desc = ttos->options[i].desc; 784 desc->ifmt_string != NULL; desc++) { 785 if (ifmw & desc->ifmt_word) { 786 printf(" mediaopt %s", desc->ifmt_string); 787 } 788 } 789 } 790 791 if (IFM_INST(ifmw) != 0) 792 printf(" instance %d", IFM_INST(ifmw)); 793} 794 795/********************************************************************** 796 * ...until here. 797 **********************************************************************/ 798 799static struct cmd media_cmds[] = { 800 DEF_CMD_ARG("media", setmedia), 801 DEF_CMD_ARG("mode", setmediamode), 802 DEF_CMD_ARG("mediaopt", setmediaopt), 803 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 804 DEF_CMD_ARG("inst", setmediainst), 805 DEF_CMD_ARG("instance", setmediainst), 806}; 807static struct afswtch af_media = { 808 .af_name = "af_media", 809 .af_af = AF_UNSPEC, 810 .af_other_status = media_status, 811}; 812 813static __constructor void 814ifmedia_ctor(void) 815{ 816#define N(a) (sizeof(a) / sizeof(a[0])) 817 int i; 818 819 for (i = 0; i < N(media_cmds); i++) 820 cmd_register(&media_cmds[i]); 821 af_register(&af_media); 822#undef N 823} 824