1/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2/* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.25.6.1 2008/11/25 02:59:29 kensmith Exp $ */ 3 4/* 5 * Copyright (c) 1997 Jason R. Thorpe. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed for the NetBSD Project 19 * by Jason R. Thorpe. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36/* 37 * Copyright (c) 1983, 1993 38 * The Regents of the University of California. All rights reserved. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. All advertising materials mentioning features or use of this software 49 * must display the following acknowledgement: 50 * This product includes software developed by the University of 51 * California, Berkeley and its contributors. 52 * 4. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 */ 68 69#include <sys/param.h> 70#include <sys/ioctl.h> 71#include <sys/socket.h> 72#include <sys/sysctl.h> 73#include <sys/time.h> 74 75#include <net/if.h> 76#include <net/if_dl.h> 77#include <net/if_types.h> 78#include <net/if_media.h> 79#include <net/route.h> 80 81#include <ctype.h> 82#include <err.h> 83#include <errno.h> 84#include <fcntl.h> 85#include <stdio.h> 86#include <stdlib.h> 87#include <string.h> 88#include <unistd.h> 89 90#include "ifconfig.h" 91 92static void domediaopt(const char *, int, int); 93static int get_media_subtype(int, const char *); 94#ifdef notdef 95static int get_media_mode(int, const char *); 96#endif 97static int get_media_options(int, const char *); 98static int lookup_media_word(struct ifmedia_description *, const char *); 99static void print_media_word(int, int); 100static void print_media_word_ifconfig(int); 101 102static struct ifmedia_description *get_toptype_desc(int); 103static struct ifmedia_type_to_subtype *get_toptype_ttos(int); 104static struct ifmedia_description *get_subtype_desc(int, 105 struct ifmedia_type_to_subtype *ttos); 106 107static void 108media_status(int s) 109{ 110 struct ifmediareq ifmr; 111 int *media_list, i; 112 113 (void) memset(&ifmr, 0, sizeof(ifmr)); 114 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 115 116 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 117 /* 118 * Interface doesn't support SIOC{G,S}IFMEDIA. 119 */ 120 return; 121 } 122 123 if (ifmr.ifm_count == 0) { 124 warnx("%s: no media types?", name); 125 return; 126 } 127 128 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 129 if (media_list == NULL) 130 err(1, "malloc"); 131 ifmr.ifm_ulist = media_list; 132 133 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 134 err(1, "SIOCGIFMEDIA"); 135 136 printf("\tmedia: "); 137 print_media_word(ifmr.ifm_current, 1); 138 if (ifmr.ifm_active != ifmr.ifm_current) { 139 putchar(' '); 140 putchar('('); 141 print_media_word(ifmr.ifm_active, 0); 142 putchar(')'); 143 } 144 145 putchar('\n'); 146 147 if (ifmr.ifm_status & IFM_AVALID) { 148 printf("\tstatus: "); 149#ifdef notdef 150 switch (IFM_TYPE(ifmr.ifm_active)) { 151 case IFM_ETHER: 152 case IFM_ATM: 153 if (ifmr.ifm_status & IFM_ACTIVE) 154 printf("active"); 155 else 156 printf("no carrier"); 157 break; 158 159 case IFM_FDDI: 160 case IFM_TOKEN: 161 if (ifmr.ifm_status & IFM_ACTIVE) 162 printf("inserted"); 163 else 164 printf("no ring"); 165 break; 166 167 case IFM_IEEE80211: 168 /* XXX: Different value for adhoc? */ 169 if (ifmr.ifm_status & IFM_ACTIVE) 170 printf("associated"); 171 else 172 printf("no carrier"); 173 break; 174 } 175#else 176 if (ifmr.ifm_status & IFM_ACTIVE) 177 printf("active"); 178 else 179 printf("inactive"); 180#endif 181 putchar('\n'); 182 } 183 184 if (ifmr.ifm_count > 0 && supmedia) { 185 printf("\tsupported media:\n"); 186 for (i = 0; i < ifmr.ifm_count; i++) { 187 printf("\t\t"); 188 print_media_word_ifconfig(media_list[i]); 189 putchar('\n'); 190 } 191 } 192 193 free(media_list); 194} 195 196struct ifmediareq * 197ifmedia_getstate(int s) 198{ 199 static struct ifmediareq *ifmr = NULL; 200 int *mwords; 201 202 if (ifmr == NULL) { 203 ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 204 if (ifmr == NULL) 205 err(1, "malloc"); 206 207 (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 208 (void) strncpy(ifmr->ifm_name, name, 209 sizeof(ifmr->ifm_name)); 210 211 ifmr->ifm_count = 0; 212 ifmr->ifm_ulist = NULL; 213 214 /* 215 * We must go through the motions of reading all 216 * supported media because we need to know both 217 * the current media type and the top-level type. 218 */ 219 220 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 221 err(1, "SIOCGIFMEDIA"); 222 } 223 224 if (ifmr->ifm_count == 0) 225 errx(1, "%s: no media types?", name); 226 227 mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 228 if (mwords == NULL) 229 err(1, "malloc"); 230 231 ifmr->ifm_ulist = mwords; 232 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 233 err(1, "SIOCGIFMEDIA"); 234 } 235 236 return ifmr; 237} 238 239static void 240setifmediacallback(int s, void *arg) 241{ 242 struct ifmediareq *ifmr = (struct ifmediareq *)arg; 243 static int did_it = 0; 244 245 if (!did_it) { 246 ifr.ifr_media = ifmr->ifm_current; 247 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 248 err(1, "SIOCSIFMEDIA (media)"); 249 free(ifmr->ifm_ulist); 250 free(ifmr); 251 did_it = 1; 252 } 253} 254 255static void 256setmedia(const char *val, int d, int s, const struct afswtch *afp) 257{ 258 struct ifmediareq *ifmr; 259 int subtype; 260 261 ifmr = ifmedia_getstate(s); 262 263 /* 264 * We are primarily concerned with the top-level type. 265 * However, "current" may be only IFM_NONE, so we just look 266 * for the top-level type in the first "supported type" 267 * entry. 268 * 269 * (I'm assuming that all supported media types for a given 270 * interface will be the same top-level type..) 271 */ 272 subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 273 274 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 275 ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 276 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 277 278 if ((ifr.ifr_media & IFM_TMASK) == 0) { 279 ifr.ifr_media &= ~IFM_GMASK; 280 } 281 282 ifmr->ifm_current = ifr.ifr_media; 283 callback_register(setifmediacallback, (void *)ifmr); 284} 285 286static void 287setmediaopt(const char *val, int d, int s, const struct afswtch *afp) 288{ 289 290 domediaopt(val, 0, s); 291} 292 293static void 294unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 295{ 296 297 domediaopt(val, 1, s); 298} 299 300static void 301domediaopt(const char *val, int clear, int s) 302{ 303 struct ifmediareq *ifmr; 304 int options; 305 306 ifmr = ifmedia_getstate(s); 307 308 options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 309 310 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 311 ifr.ifr_media = ifmr->ifm_current; 312 if (clear) 313 ifr.ifr_media &= ~options; 314 else { 315 if (options & IFM_HDX) { 316 ifr.ifr_media &= ~IFM_FDX; 317 options &= ~IFM_HDX; 318 } 319 ifr.ifr_media |= options; 320 } 321 ifmr->ifm_current = ifr.ifr_media; 322 callback_register(setifmediacallback, (void *)ifmr); 323} 324 325static void 326setmediainst(const char *val, int d, int s, const struct afswtch *afp) 327{ 328 struct ifmediareq *ifmr; 329 int inst; 330 331 ifmr = ifmedia_getstate(s); 332 333 inst = atoi(val); 334 if (inst < 0 || inst > IFM_INST_MAX) 335 errx(1, "invalid media instance: %s", val); 336 337 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 338 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 339 340 ifmr->ifm_current = ifr.ifr_media; 341 callback_register(setifmediacallback, (void *)ifmr); 342} 343 344#ifdef notdef 345static void 346setmediamode(const char *val, int d, int s, const struct afswtch *afp) 347{ 348 struct ifmediareq *ifmr; 349 int mode; 350 351 ifmr = ifmedia_getstate(s); 352 353 mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 354 355 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 356 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 357 358 ifmr->ifm_current = ifr.ifr_media; 359 callback_register(setifmediacallback, (void *)ifmr); 360} 361#endif 362 363/********************************************************************** 364 * A good chunk of this is duplicated from sys/net/ifmedia.c 365 **********************************************************************/ 366 367static struct ifmedia_description ifm_type_descriptions[] = 368 IFM_TYPE_DESCRIPTIONS; 369 370static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 371 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 372 373static struct ifmedia_description ifm_subtype_ethernet_aliases[] = 374 IFM_SUBTYPE_ETHERNET_ALIASES; 375 376static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 377 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 378 379static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 380 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 381 382static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 383 IFM_SUBTYPE_TOKENRING_ALIASES; 384 385static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 386 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 387 388static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 389 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 390 391static struct ifmedia_description ifm_subtype_fddi_aliases[] = 392 IFM_SUBTYPE_FDDI_ALIASES; 393 394static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 395 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 396 397static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 398 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 399 400static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 401 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 402 403#ifdef notdef 404static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 405IFM_SUBTYPE_IEEE80211_ALIASES; 406 407struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 408 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 409 410struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 411 IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 412 413static struct ifmedia_description ifm_subtype_atm_descriptions[] = 414 IFM_SUBTYPE_ATM_DESCRIPTIONS; 415 416static struct ifmedia_description ifm_subtype_atm_aliases[] = 417 IFM_SUBTYPE_ATM_ALIASES; 418 419static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 420 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 421#endif 422 423static struct ifmedia_description ifm_subtype_shared_descriptions[] = 424 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 425 426static struct ifmedia_description ifm_subtype_shared_aliases[] = 427 IFM_SUBTYPE_SHARED_ALIASES; 428 429static struct ifmedia_description ifm_shared_option_descriptions[] = 430 IFM_SHARED_OPTION_DESCRIPTIONS; 431 432struct ifmedia_type_to_subtype { 433 struct { 434 struct ifmedia_description *desc; 435 int alias; 436 } subtypes[5]; 437 struct { 438 struct ifmedia_description *desc; 439 int alias; 440 } options[3]; 441 struct { 442 struct ifmedia_description *desc; 443 int alias; 444 } modes[3]; 445}; 446 447/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 448static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 449 { 450 { 451 { &ifm_subtype_shared_descriptions[0], 0 }, 452 { &ifm_subtype_shared_aliases[0], 1 }, 453 { &ifm_subtype_ethernet_descriptions[0], 0 }, 454 { &ifm_subtype_ethernet_aliases[0], 1 }, 455 { NULL, 0 }, 456 }, 457 { 458 { &ifm_shared_option_descriptions[0], 0 }, 459 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 460 { NULL, 0 }, 461 }, 462 { 463 { NULL, 0 }, 464 }, 465 }, 466 { 467 { 468 { &ifm_subtype_shared_descriptions[0], 0 }, 469 { &ifm_subtype_shared_aliases[0], 1 }, 470 { &ifm_subtype_tokenring_descriptions[0], 0 }, 471 { &ifm_subtype_tokenring_aliases[0], 1 }, 472 { NULL, 0 }, 473 }, 474 { 475 { &ifm_shared_option_descriptions[0], 0 }, 476 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 477 { NULL, 0 }, 478 }, 479 { 480 { NULL, 0 }, 481 }, 482 }, 483 { 484 { 485 { &ifm_subtype_shared_descriptions[0], 0 }, 486 { &ifm_subtype_shared_aliases[0], 1 }, 487 { &ifm_subtype_fddi_descriptions[0], 0 }, 488 { &ifm_subtype_fddi_aliases[0], 1 }, 489 { NULL, 0 }, 490 }, 491 { 492 { &ifm_shared_option_descriptions[0], 0 }, 493 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 494 { NULL, 0 }, 495 }, 496 { 497 { NULL, 0 }, 498 }, 499 }, 500#ifdef __APPLE__ 501 { 502 { 503 { &ifm_subtype_shared_descriptions[0], 0 }, 504 { &ifm_subtype_shared_aliases[0], 1 }, 505 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 506 { NULL, 0 }, 507 }, 508 { 509 { &ifm_shared_option_descriptions[0], 0 }, 510 { &ifm_subtype_ieee80211_option_descriptions[0], 1 }, 511 { NULL, 0 }, 512 }, 513 { 514 { NULL, 0 }, 515 }, 516 }, 517#else /* __APPLE__ */ 518#ifdef notdef 519 { 520 { 521 { &ifm_subtype_shared_descriptions[0], 0 }, 522 { &ifm_subtype_shared_aliases[0], 1 }, 523 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 524 { &ifm_subtype_ieee80211_aliases[0], 1 }, 525 { NULL, 0 }, 526 }, 527 { 528 { &ifm_shared_option_descriptions[0], 0 }, 529 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 530 { NULL, 0 }, 531 }, 532 { 533 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 534 { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 535 { NULL, 0 }, 536 }, 537 }, 538 { 539 { 540 { &ifm_subtype_shared_descriptions[0], 0 }, 541 { &ifm_subtype_shared_aliases[0], 1 }, 542 { &ifm_subtype_atm_descriptions[0], 0 }, 543 { &ifm_subtype_atm_aliases[0], 1 }, 544 { NULL, 0 }, 545 }, 546 { 547 { &ifm_shared_option_descriptions[0], 0 }, 548 { &ifm_subtype_atm_option_descriptions[0], 0 }, 549 { NULL, 0 }, 550 }, 551 { 552 { NULL, 0 }, 553 }, 554 }, 555#endif 556#endif /* __APPLE__ */ 557}; 558 559static int 560get_media_subtype(int type, const char *val) 561{ 562 struct ifmedia_description *desc; 563 struct ifmedia_type_to_subtype *ttos; 564 int rval, i; 565 566 /* Find the top-level interface type. */ 567 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 568 desc->ifmt_string != NULL; desc++, ttos++) 569 if (type == desc->ifmt_word) 570 break; 571 if (desc->ifmt_string == NULL) 572 errx(1, "unknown media type 0x%x", type); 573 574 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 575 rval = lookup_media_word(ttos->subtypes[i].desc, val); 576 if (rval != -1) 577 return (rval); 578 } 579 errx(1, "unknown media subtype: %s", val); 580 /*NOTREACHED*/ 581} 582 583#ifdef notdef 584static int 585get_media_mode(int type, const char *val) 586{ 587 struct ifmedia_description *desc; 588 struct ifmedia_type_to_subtype *ttos; 589 int rval, i; 590 591 /* Find the top-level interface type. */ 592 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 593 desc->ifmt_string != NULL; desc++, ttos++) 594 if (type == desc->ifmt_word) 595 break; 596 if (desc->ifmt_string == NULL) 597 errx(1, "unknown media mode 0x%x", type); 598 599 for (i = 0; ttos->modes[i].desc != NULL; i++) { 600 rval = lookup_media_word(ttos->modes[i].desc, val); 601 if (rval != -1) 602 return (rval); 603 } 604 return -1; 605} 606#endif 607 608static int 609get_media_options(int type, const char *val) 610{ 611 struct ifmedia_description *desc; 612 struct ifmedia_type_to_subtype *ttos; 613 char *optlist, *optptr; 614 int option = 0, i, rval = 0; 615 616 /* We muck with the string, so copy it. */ 617 optlist = strdup(val); 618 if (optlist == NULL) 619 err(1, "strdup"); 620 621 /* Find the top-level interface type. */ 622 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 623 desc->ifmt_string != NULL; desc++, ttos++) 624 if (type == desc->ifmt_word) 625 break; 626 if (desc->ifmt_string == NULL) 627 errx(1, "unknown media type 0x%x", type); 628 629 /* 630 * Look up the options in the user-provided comma-separated 631 * list. 632 */ 633 optptr = optlist; 634 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 635 for (i = 0; ttos->options[i].desc != NULL; i++) { 636 option = lookup_media_word(ttos->options[i].desc, optptr); 637 if (option != -1) 638 break; 639 } 640 if (option == 0) 641 errx(1, "unknown option: %s", optptr); 642 rval |= option; 643 } 644 645 free(optlist); 646 return (rval); 647} 648 649static int 650lookup_media_word(struct ifmedia_description *desc, const char *val) 651{ 652 653 for (; desc->ifmt_string != NULL; desc++) 654 if (strcasecmp(desc->ifmt_string, val) == 0) 655 return (desc->ifmt_word); 656 657 return (-1); 658} 659 660static struct ifmedia_description *get_toptype_desc(int ifmw) 661{ 662 struct ifmedia_description *desc; 663 664 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 665 if (IFM_TYPE(ifmw) == desc->ifmt_word) 666 break; 667 668 return desc; 669} 670 671static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 672{ 673 struct ifmedia_description *desc; 674 struct ifmedia_type_to_subtype *ttos; 675 676 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 677 desc->ifmt_string != NULL; desc++, ttos++) 678 if (IFM_TYPE(ifmw) == desc->ifmt_word) 679 break; 680 681 return ttos; 682} 683 684static struct ifmedia_description *get_subtype_desc(int ifmw, 685 struct ifmedia_type_to_subtype *ttos) 686{ 687 int i; 688 struct ifmedia_description *desc; 689 690 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 691 if (ttos->subtypes[i].alias) 692 continue; 693 for (desc = ttos->subtypes[i].desc; 694 desc->ifmt_string != NULL; desc++) { 695 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 696 return desc; 697 } 698 } 699 700 return NULL; 701} 702 703#ifdef notdef 704static struct ifmedia_description *get_mode_desc(int ifmw, 705 struct ifmedia_type_to_subtype *ttos) 706{ 707 int i; 708 struct ifmedia_description *desc; 709 710 for (i = 0; ttos->modes[i].desc != NULL; i++) { 711 if (ttos->modes[i].alias) 712 continue; 713 for (desc = ttos->modes[i].desc; 714 desc->ifmt_string != NULL; desc++) { 715 if (IFM_MODE(ifmw) == desc->ifmt_word) 716 return desc; 717 } 718 } 719 720 return NULL; 721} 722#endif 723 724static void 725print_media_word(int ifmw, int print_toptype) 726{ 727 struct ifmedia_description *desc; 728 struct ifmedia_type_to_subtype *ttos; 729 int seen_option = 0, i; 730 731 /* Find the top-level interface type. */ 732 desc = get_toptype_desc(ifmw); 733 ttos = get_toptype_ttos(ifmw); 734 if (desc->ifmt_string == NULL) { 735 printf("<unknown type>"); 736 return; 737#ifdef notdef 738 } else if (print_toptype) { 739 printf("%s", desc->ifmt_string); 740#endif 741 } 742 743 /* 744 * Don't print the top-level type; it's not like we can 745 * change it, or anything. 746 */ 747 748 /* Find subtype. */ 749 desc = get_subtype_desc(ifmw, ttos); 750 if (desc == NULL) { 751 printf("<unknown subtype>"); 752 return; 753 } 754 755#ifdef notdef 756 if (print_toptype) 757 putchar(' '); 758#endif 759 760 printf("%s", desc->ifmt_string); 761 762#ifdef notdef 763 if (print_toptype) { 764 desc = get_mode_desc(ifmw, ttos); 765 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 766 printf(" mode %s", desc->ifmt_string); 767 } 768#endif 769 /* Find options. */ 770 for (i = 0; ttos->options[i].desc != NULL; i++) { 771 if (ttos->options[i].alias) 772 continue; 773 for (desc = ttos->options[i].desc; 774 desc->ifmt_string != NULL; desc++) { 775 if (ifmw & desc->ifmt_word) { 776 if (seen_option == 0) 777 printf(" <"); 778 printf("%s%s", seen_option++ ? "," : "", 779 desc->ifmt_string); 780 } 781 } 782 } 783 printf("%s", seen_option ? ">" : ""); 784 785#ifdef notdef 786 if (print_toptype && IFM_INST(ifmw) != 0) 787 printf(" instance %d", IFM_INST(ifmw)); 788#endif 789} 790 791static void 792print_media_word_ifconfig(int ifmw) 793{ 794 struct ifmedia_description *desc; 795 struct ifmedia_type_to_subtype *ttos; 796 int i; 797 798 /* Find the top-level interface type. */ 799 desc = get_toptype_desc(ifmw); 800 ttos = get_toptype_ttos(ifmw); 801 if (desc->ifmt_string == NULL) { 802 printf("<unknown type>"); 803 return; 804 } 805 806 /* 807 * Don't print the top-level type; it's not like we can 808 * change it, or anything. 809 */ 810 811 /* Find subtype. */ 812 desc = get_subtype_desc(ifmw, ttos); 813 if (desc == NULL) { 814 printf("<unknown subtype>"); 815 return; 816 } 817 818 printf("media %s", desc->ifmt_string); 819 820#ifdef notdef 821 desc = get_mode_desc(ifmw, ttos); 822 if (desc != NULL) 823 printf(" mode %s", desc->ifmt_string); 824#endif 825 826 /* Find options. */ 827 for (i = 0; ttos->options[i].desc != NULL; i++) { 828 if (ttos->options[i].alias) 829 continue; 830 for (desc = ttos->options[i].desc; 831 desc->ifmt_string != NULL; desc++) { 832 if (ifmw & desc->ifmt_word) { 833 printf(" mediaopt %s", desc->ifmt_string); 834 } 835 } 836 } 837 838 if (IFM_INST(ifmw) != 0) 839 printf(" instance %d", IFM_INST(ifmw)); 840} 841 842/********************************************************************** 843 * ...until here. 844 **********************************************************************/ 845 846static struct cmd media_cmds[] = { 847 DEF_CMD_ARG("media", setmedia), 848#ifdef notdef 849 DEF_CMD_ARG("mode", setmediamode), 850#endif 851 DEF_CMD_ARG("mediaopt", setmediaopt), 852 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 853 DEF_CMD_ARG("inst", setmediainst), 854 DEF_CMD_ARG("instance", setmediainst), 855}; 856static struct afswtch af_media = { 857 .af_name = "af_media", 858 .af_af = AF_UNSPEC, 859 .af_other_status = media_status, 860}; 861 862static __constructor void 863ifmedia_ctor(void) 864{ 865#define N(a) (sizeof(a) / sizeof(a[0])) 866 int i; 867 868 for (i = 0; i < N(media_cmds); i++) 869 cmd_register(&media_cmds[i]); 870 af_register(&af_media); 871#undef N 872} 873