ifmedia.c revision 114164
1/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 114164 2003-04-28 16:37:38Z sam $ */ 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 *); 94static int get_media_mode(int, const char *); 95static int get_media_options(int, const char *); 96static int lookup_media_word(struct ifmedia_description *, const char *); 97static void print_media_word(int, int); 98static void print_media_word_ifconfig(int); 99 100static struct ifmedia_description *get_toptype_desc(int); 101static struct ifmedia_type_to_subtype *get_toptype_ttos(int); 102static struct ifmedia_description *get_subtype_desc(int, 103 struct ifmedia_type_to_subtype *ttos); 104 105void 106media_status(int s, struct rt_addrinfo *info __unused) 107{ 108 struct ifmediareq ifmr; 109 int *media_list, i; 110 111 (void) memset(&ifmr, 0, sizeof(ifmr)); 112 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 113 114 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 115 /* 116 * Interface doesn't support SIOC{G,S}IFMEDIA. 117 */ 118 return; 119 } 120 121 if (ifmr.ifm_count == 0) { 122 warnx("%s: no media types?", name); 123 return; 124 } 125 126 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 127 if (media_list == NULL) 128 err(1, "malloc"); 129 ifmr.ifm_ulist = media_list; 130 131 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 132 err(1, "SIOCGIFMEDIA"); 133 134 printf("\tmedia: "); 135 print_media_word(ifmr.ifm_current, 1); 136 if (ifmr.ifm_active != ifmr.ifm_current) { 137 putchar(' '); 138 putchar('('); 139 print_media_word(ifmr.ifm_active, 0); 140 putchar(')'); 141 } 142 143 putchar('\n'); 144 145 if (ifmr.ifm_status & IFM_AVALID) { 146 printf("\tstatus: "); 147 switch (IFM_TYPE(ifmr.ifm_active)) { 148 case IFM_ETHER: 149 if (ifmr.ifm_status & IFM_ACTIVE) 150 printf("active"); 151 else 152 printf("no carrier"); 153 break; 154 155 case IFM_FDDI: 156 case IFM_TOKEN: 157 if (ifmr.ifm_status & IFM_ACTIVE) 158 printf("inserted"); 159 else 160 printf("no ring"); 161 break; 162 case IFM_IEEE80211: 163 /* XXX: Different value for adhoc? */ 164 if (ifmr.ifm_status & IFM_ACTIVE) 165 printf("associated"); 166 else 167 printf("no carrier"); 168 break; 169 } 170 putchar('\n'); 171 } 172 173 if (ifmr.ifm_count > 0 && supmedia) { 174 printf("\tsupported media:\n"); 175 for (i = 0; i < ifmr.ifm_count; i++) { 176 printf("\t\t"); 177 print_media_word_ifconfig(media_list[i]); 178 putchar('\n'); 179 } 180 } 181 182 free(media_list); 183} 184 185void 186setmedia(const char *val, int d, int s, const struct afswtch *afp) 187{ 188 struct ifmediareq ifmr; 189 int first_type, subtype; 190 191 (void) memset(&ifmr, 0, sizeof(ifmr)); 192 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 193 194 ifmr.ifm_count = 1; 195 ifmr.ifm_ulist = &first_type; 196 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 197 /* 198 * If we get E2BIG, the kernel is telling us 199 * that there are more, so we can ignore it. 200 */ 201 if (errno != E2BIG) 202 err(1, "SIOCGIFMEDIA"); 203 } 204 205 if (ifmr.ifm_count == 0) 206 errx(1, "%s: no media types?", name); 207 208 /* 209 * We are primarily concerned with the top-level type. 210 * However, "current" may be only IFM_NONE, so we just look 211 * for the top-level type in the first "supported type" 212 * entry. 213 * 214 * (I'm assuming that all supported media types for a given 215 * interface will be the same top-level type..) 216 */ 217 subtype = get_media_subtype(IFM_TYPE(first_type), val); 218 219 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 220 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 221 IFM_TYPE(first_type) | subtype; 222 223 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 224 err(1, "SIOCSIFMEDIA (media)"); 225} 226 227void 228setmediaopt(const char *val, int d, int s, const struct afswtch *afp) 229{ 230 231 domediaopt(val, 0, s); 232} 233 234void 235unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 236{ 237 238 domediaopt(val, 1, s); 239} 240 241static void 242domediaopt(const char *val, int clear, int s) 243{ 244 struct ifmediareq ifmr; 245 int *mwords, options; 246 247 (void) memset(&ifmr, 0, sizeof(ifmr)); 248 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 249 250 /* 251 * We must go through the motions of reading all 252 * supported media because we need to know both 253 * the current media type and the top-level type. 254 */ 255 256 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 257 err(1, "SIOCGIFMEDIA"); 258 259 if (ifmr.ifm_count == 0) 260 errx(1, "%s: no media types?", name); 261 262 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); 263 if (mwords == NULL) 264 err(1, "malloc"); 265 266 ifmr.ifm_ulist = mwords; 267 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 268 err(1, "SIOCGIFMEDIA"); 269 270 options = get_media_options(IFM_TYPE(mwords[0]), val); 271 272 free(mwords); 273 274 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 275 ifr.ifr_media = ifmr.ifm_current; 276 if (clear) 277 ifr.ifr_media &= ~options; 278 else 279 ifr.ifr_media |= options; 280 281 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 282 err(1, "SIOCSIFMEDIA (mediaopt)"); 283} 284 285 286void 287setmediamode(const char *val, int d, int s, const struct afswtch *afp) 288{ 289 struct ifmediareq ifmr; 290 int *mwords, mode; 291 292 (void) memset(&ifmr, 0, sizeof(ifmr)); 293 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 294 295 /* 296 * We must go through the motions of reading all 297 * supported media because we need to know both 298 * the current media type and the top-level type. 299 */ 300 301 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 302 err(1, "SIOCGIFMEDIA"); 303 304 if (ifmr.ifm_count == 0) 305 errx(1, "%s: no media types?", name); 306 307 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); 308 if (mwords == NULL) 309 err(1, "malloc"); 310 311 ifmr.ifm_ulist = mwords; 312 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 313 err(1, "SIOCGIFMEDIA"); 314 315 mode = get_media_mode(IFM_TYPE(mwords[0]), val); 316 317 free(mwords); 318 319 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 320 ifr.ifr_media = ifmr.ifm_current; 321 ifr.ifr_media = (ifmr.ifm_current & ~IFM_MMASK) | IFM_MAKEMODE(mode); 322 323 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 324 err(1, "SIOCSIFMEDIA (mode)"); 325} 326 327/********************************************************************** 328 * A good chunk of this is duplicated from sys/net/ifmedia.c 329 **********************************************************************/ 330 331static struct ifmedia_description ifm_type_descriptions[] = 332 IFM_TYPE_DESCRIPTIONS; 333 334static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 335 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 336 337static struct ifmedia_description ifm_subtype_ethernet_aliases[] = 338 IFM_SUBTYPE_ETHERNET_ALIASES; 339 340static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 341 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 342 343static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 344 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 345 346static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 347 IFM_SUBTYPE_TOKENRING_ALIASES; 348 349static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 350 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 351 352static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 353 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 354 355static struct ifmedia_description ifm_subtype_fddi_aliases[] = 356 IFM_SUBTYPE_FDDI_ALIASES; 357 358static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 359 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 360 361static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 362 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 363 364static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 365 IFM_SUBTYPE_IEEE80211_ALIASES; 366 367static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 368 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 369 370struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 371 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 372 373static struct ifmedia_description ifm_subtype_shared_descriptions[] = 374 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 375 376static struct ifmedia_description ifm_subtype_shared_aliases[] = 377 IFM_SUBTYPE_SHARED_ALIASES; 378 379static struct ifmedia_description ifm_shared_option_descriptions[] = 380 IFM_SHARED_OPTION_DESCRIPTIONS; 381 382struct ifmedia_type_to_subtype { 383 struct { 384 struct ifmedia_description *desc; 385 int alias; 386 } subtypes[5]; 387 struct { 388 struct ifmedia_description *desc; 389 int alias; 390 } options[3]; 391 struct { 392 struct ifmedia_description *desc; 393 int alias; 394 } modes[2]; 395}; 396 397/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 398static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 399 { 400 { 401 { &ifm_subtype_shared_descriptions[0], 0 }, 402 { &ifm_subtype_shared_aliases[0], 1 }, 403 { &ifm_subtype_ethernet_descriptions[0], 0 }, 404 { &ifm_subtype_ethernet_aliases[0], 1 }, 405 { NULL, 0 }, 406 }, 407 { 408 { &ifm_shared_option_descriptions[0], 0 }, 409 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 410 { NULL, 0 }, 411 }, 412 { 413 { NULL, 0 }, 414 }, 415 }, 416 { 417 { 418 { &ifm_subtype_shared_descriptions[0], 0 }, 419 { &ifm_subtype_shared_aliases[0], 1 }, 420 { &ifm_subtype_tokenring_descriptions[0], 0 }, 421 { &ifm_subtype_tokenring_aliases[0], 1 }, 422 { NULL, 0 }, 423 }, 424 { 425 { &ifm_shared_option_descriptions[0], 0 }, 426 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 427 { NULL, 0 }, 428 }, 429 { 430 { NULL, 0 }, 431 }, 432 }, 433 { 434 { 435 { &ifm_subtype_shared_descriptions[0], 0 }, 436 { &ifm_subtype_shared_aliases[0], 1 }, 437 { &ifm_subtype_fddi_descriptions[0], 0 }, 438 { &ifm_subtype_fddi_aliases[0], 1 }, 439 { NULL, 0 }, 440 }, 441 { 442 { &ifm_shared_option_descriptions[0], 0 }, 443 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 444 { NULL, 0 }, 445 }, 446 { 447 { NULL, 0 }, 448 }, 449 }, 450 { 451 { 452 { &ifm_subtype_shared_descriptions[0], 0 }, 453 { &ifm_subtype_shared_aliases[0], 1 }, 454 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 455 { &ifm_subtype_ieee80211_aliases[0], 1 }, 456 { NULL, 0 }, 457 }, 458 { 459 { &ifm_shared_option_descriptions[0], 0 }, 460 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 461 { NULL, 0 }, 462 }, 463 { 464 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 465 { NULL, 0 }, 466 }, 467 }, 468}; 469 470static int 471get_media_subtype(int type, const char *val) 472{ 473 struct ifmedia_description *desc; 474 struct ifmedia_type_to_subtype *ttos; 475 int rval, i; 476 477 /* Find the top-level interface type. */ 478 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 479 desc->ifmt_string != NULL; desc++, ttos++) 480 if (type == desc->ifmt_word) 481 break; 482 if (desc->ifmt_string == NULL) 483 errx(1, "unknown media type 0x%x", type); 484 485 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 486 rval = lookup_media_word(ttos->subtypes[i].desc, val); 487 if (rval != -1) 488 return (rval); 489 } 490 errx(1, "unknown media subtype: %s", val); 491 /*NOTREACHED*/ 492} 493 494static int 495get_media_mode(int type, const char *val) 496{ 497 struct ifmedia_description *desc; 498 struct ifmedia_type_to_subtype *ttos; 499 int rval, i; 500 501 /* Find the top-level interface type. */ 502 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 503 desc->ifmt_string != NULL; desc++, ttos++) 504 if (type == desc->ifmt_word) 505 break; 506 if (desc->ifmt_string == NULL) 507 errx(1, "unknown media mode 0x%x", type); 508 509 for (i = 0; ttos->modes[i].desc != NULL; i++) { 510 rval = lookup_media_word(ttos->modes[i].desc, val); 511 if (rval != -1) 512 return (rval); 513 } 514 return -1; 515} 516 517static int 518get_media_options(int type, const char *val) 519{ 520 struct ifmedia_description *desc; 521 struct ifmedia_type_to_subtype *ttos; 522 char *optlist, *optptr; 523 int option = 0, i, rval = 0; 524 525 /* We muck with the string, so copy it. */ 526 optlist = strdup(val); 527 if (optlist == NULL) 528 err(1, "strdup"); 529 530 /* Find the top-level interface type. */ 531 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 532 desc->ifmt_string != NULL; desc++, ttos++) 533 if (type == desc->ifmt_word) 534 break; 535 if (desc->ifmt_string == NULL) 536 errx(1, "unknown media type 0x%x", type); 537 538 /* 539 * Look up the options in the user-provided comma-separated 540 * list. 541 */ 542 optptr = optlist; 543 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 544 for (i = 0; ttos->options[i].desc != NULL; i++) { 545 option = lookup_media_word(ttos->options[i].desc, optptr); 546 if (option != -1) 547 break; 548 } 549 if (option == 0) 550 errx(1, "unknown option: %s", optptr); 551 rval |= option; 552 } 553 554 free(optlist); 555 return (rval); 556} 557 558static int 559lookup_media_word(struct ifmedia_description *desc, const char *val) 560{ 561 562 for (; desc->ifmt_string != NULL; desc++) 563 if (strcasecmp(desc->ifmt_string, val) == 0) 564 return (desc->ifmt_word); 565 566 return (-1); 567} 568 569static struct ifmedia_description *get_toptype_desc(int ifmw) 570{ 571 struct ifmedia_description *desc; 572 573 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 574 if (IFM_TYPE(ifmw) == desc->ifmt_word) 575 break; 576 577 return desc; 578} 579 580static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 581{ 582 struct ifmedia_description *desc; 583 struct ifmedia_type_to_subtype *ttos; 584 585 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 586 desc->ifmt_string != NULL; desc++, ttos++) 587 if (IFM_TYPE(ifmw) == desc->ifmt_word) 588 break; 589 590 return ttos; 591} 592 593static struct ifmedia_description *get_subtype_desc(int ifmw, 594 struct ifmedia_type_to_subtype *ttos) 595{ 596 int i; 597 struct ifmedia_description *desc; 598 599 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 600 if (ttos->subtypes[i].alias) 601 continue; 602 for (desc = ttos->subtypes[i].desc; 603 desc->ifmt_string != NULL; desc++) { 604 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 605 return desc; 606 } 607 } 608 609 return NULL; 610} 611 612static struct ifmedia_description *get_mode_desc(int ifmw, 613 struct ifmedia_type_to_subtype *ttos) 614{ 615 int i; 616 struct ifmedia_description *desc; 617 618 for (i = 0; ttos->modes[i].desc != NULL; i++) { 619 if (ttos->modes[i].alias) 620 continue; 621 for (desc = ttos->modes[i].desc; 622 desc->ifmt_string != NULL; desc++) { 623 if (IFM_MODE(ifmw) == desc->ifmt_word) 624 return desc; 625 } 626 } 627 628 return NULL; 629} 630 631static void 632print_media_word(int ifmw, int print_toptype) 633{ 634 struct ifmedia_description *desc; 635 struct ifmedia_type_to_subtype *ttos; 636 int seen_option = 0, i; 637 638 /* Find the top-level interface type. */ 639 desc = get_toptype_desc(ifmw); 640 ttos = get_toptype_ttos(ifmw); 641 if (desc->ifmt_string == NULL) { 642 printf("<unknown type>"); 643 return; 644 } else if (print_toptype) { 645 printf("%s", desc->ifmt_string); 646 } 647 648 /* 649 * Don't print the top-level type; it's not like we can 650 * change it, or anything. 651 */ 652 653 /* Find subtype. */ 654 desc = get_subtype_desc(ifmw, ttos); 655 if (desc != NULL) 656 goto got_subtype; 657 658 /* Falling to here means unknown subtype. */ 659 printf("<unknown subtype>"); 660 return; 661 662 got_subtype: 663 if (print_toptype) 664 putchar(' '); 665 666 printf("%s", desc->ifmt_string); 667 668 if (print_toptype) { 669 desc = get_mode_desc(ifmw, ttos); 670 if (desc != NULL) 671 printf(" mode %s", desc->ifmt_string); 672 } 673 674 /* Find options. */ 675 for (i = 0; ttos->options[i].desc != NULL; i++) { 676 if (ttos->options[i].alias) 677 continue; 678 for (desc = ttos->options[i].desc; 679 desc->ifmt_string != NULL; desc++) { 680 if (ifmw & desc->ifmt_word) { 681 if (seen_option == 0) 682 printf(" <"); 683 printf("%s%s", seen_option++ ? "," : "", 684 desc->ifmt_string); 685 } 686 } 687 } 688 printf("%s", seen_option ? ">" : ""); 689} 690 691static void 692print_media_word_ifconfig(int ifmw) 693{ 694 struct ifmedia_description *desc; 695 struct ifmedia_type_to_subtype *ttos; 696 int i; 697 698 /* Find the top-level interface type. */ 699 desc = get_toptype_desc(ifmw); 700 ttos = get_toptype_ttos(ifmw); 701 if (desc->ifmt_string == NULL) { 702 printf("<unknown type>"); 703 return; 704 } 705 706 /* 707 * Don't print the top-level type; it's not like we can 708 * change it, or anything. 709 */ 710 711 /* Find subtype. */ 712 desc = get_subtype_desc(ifmw, ttos); 713 if (desc != NULL) 714 goto got_subtype; 715 716 /* Falling to here means unknown subtype. */ 717 printf("<unknown subtype>"); 718 return; 719 720 got_subtype: 721 printf("media %s", desc->ifmt_string); 722 723 desc = get_mode_desc(ifmw, ttos); 724 if (desc != NULL) 725 printf(" mode %s", desc->ifmt_string); 726 727 /* Find options. */ 728 for (i = 0; ttos->options[i].desc != NULL; i++) { 729 if (ttos->options[i].alias) 730 continue; 731 for (desc = ttos->options[i].desc; 732 desc->ifmt_string != NULL; desc++) { 733 if (ifmw & desc->ifmt_word) { 734 printf(" mediaopt %s", desc->ifmt_string); 735 } 736 } 737 } 738} 739 740/********************************************************************** 741 * ...until here. 742 **********************************************************************/ 743