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