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