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