1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ 2 /* $FreeBSD$ */ 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 92 static void domediaopt(const char *, int, int); 93 static int get_media_subtype(int, const char *); 94 static int get_media_mode(int, const char *); 95 static int get_media_options(int, const char *); 96 static int lookup_media_word(struct ifmedia_description *, const char *); 97 static void print_media_word(int, int); 98 static void print_media_word_ifconfig(int); 99 100 static struct ifmedia_description *get_toptype_desc(int); 101 static struct ifmedia_type_to_subtype *get_toptype_ttos(int); 102 static struct ifmedia_description *get_subtype_desc(int, 103 struct ifmedia_type_to_subtype *ttos); 104 105 static void 106 media_status(int s) 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 163 case IFM_ATM: 164 if (ifmr.ifm_status & IFM_ACTIVE) 165 printf("active"); 166 else 167 printf("no carrier"); 168 break; 169 170 case IFM_IEEE80211: 171 /* XXX: Different value for adhoc? */ 172 if (ifmr.ifm_status & IFM_ACTIVE) 173 printf("associated"); 174 else 175 printf("no carrier"); 176 break; 177 } 178 putchar('\n'); 179 } 180 181 if (ifmr.ifm_count > 0 && supmedia) { 182 printf("\tsupported media:\n"); 183 for (i = 0; i < ifmr.ifm_count; i++) { 184 printf("\t\t"); 185 print_media_word_ifconfig(media_list[i]); 186 putchar('\n'); 187 } 188 } 189 190 free(media_list); 191 } 192 193 static struct ifmediareq * 194 getifmediastate(int s) 195 { 196 static struct ifmediareq *ifmr = NULL; 197 int *mwords; 198 199 if (ifmr == NULL) { 200 ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 201 if (ifmr == NULL) 202 err(1, "malloc"); 203 204 (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 205 (void) strncpy(ifmr->ifm_name, name, 206 sizeof(ifmr->ifm_name)); 207 208 ifmr->ifm_count = 0; 209 ifmr->ifm_ulist = NULL; 210 211 /* 212 * We must go through the motions of reading all 213 * supported media because we need to know both 214 * the current media type and the top-level type. 215 */ 216 217 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 218 err(1, "SIOCGIFMEDIA"); 219 } 220 221 if (ifmr->ifm_count == 0) 222 errx(1, "%s: no media types?", name); 223 224 mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 225 if (mwords == NULL) 226 err(1, "malloc"); 227 228 ifmr->ifm_ulist = mwords; 229 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 230 err(1, "SIOCGIFMEDIA"); 231 } 232 233 return ifmr; 234 } 235 236 static void 237 setifmediacallback(int s, void *arg) 238 { 239 struct ifmediareq *ifmr = (struct ifmediareq *)arg; 240 static int did_it = 0; 241 242 if (!did_it) { 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_tokenring_descriptions[] = 353 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 354 355 static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 356 IFM_SUBTYPE_TOKENRING_ALIASES; 357 358 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 359 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 360 361 static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 362 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 363 364 static struct ifmedia_description ifm_subtype_fddi_aliases[] = 365 IFM_SUBTYPE_FDDI_ALIASES; 366 367 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 368 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 369 370 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 371 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 372 373 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 374 IFM_SUBTYPE_IEEE80211_ALIASES; 375 376 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 377 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 378 379 struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 380 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 381 382 struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 383 IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 384 385 static struct ifmedia_description ifm_subtype_atm_descriptions[] = 386 IFM_SUBTYPE_ATM_DESCRIPTIONS; 387 388 static struct ifmedia_description ifm_subtype_atm_aliases[] = 389 IFM_SUBTYPE_ATM_ALIASES; 390 391 static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 392 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 393 394 static struct ifmedia_description ifm_subtype_shared_descriptions[] = 395 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 396 397 static struct ifmedia_description ifm_subtype_shared_aliases[] = 398 IFM_SUBTYPE_SHARED_ALIASES; 399 400 static struct ifmedia_description ifm_shared_option_descriptions[] = 401 IFM_SHARED_OPTION_DESCRIPTIONS; 402 403 struct ifmedia_type_to_subtype { 404 struct { 405 struct ifmedia_description *desc; 406 int alias; 407 } subtypes[5]; 408 struct { 409 struct ifmedia_description *desc; 410 int alias; 411 } options[3]; 412 struct { 413 struct ifmedia_description *desc; 414 int alias; 415 } modes[3]; 416 }; 417 418 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 419 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 420 { 421 { 422 { &ifm_subtype_shared_descriptions[0], 0 }, 423 { &ifm_subtype_shared_aliases[0], 1 }, 424 { &ifm_subtype_ethernet_descriptions[0], 0 }, 425 { &ifm_subtype_ethernet_aliases[0], 1 }, 426 { NULL, 0 }, 427 }, 428 { 429 { &ifm_shared_option_descriptions[0], 0 }, 430 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 431 { NULL, 0 }, 432 }, 433 { 434 { NULL, 0 }, 435 }, 436 }, 437 { 438 { 439 { &ifm_subtype_shared_descriptions[0], 0 }, 440 { &ifm_subtype_shared_aliases[0], 1 }, 441 { &ifm_subtype_tokenring_descriptions[0], 0 }, 442 { &ifm_subtype_tokenring_aliases[0], 1 }, 443 { NULL, 0 }, 444 }, 445 { 446 { &ifm_shared_option_descriptions[0], 0 }, 447 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 448 { NULL, 0 }, 449 }, 450 { 451 { NULL, 0 }, 452 }, 453 }, 454 { 455 { 456 { &ifm_subtype_shared_descriptions[0], 0 }, 457 { &ifm_subtype_shared_aliases[0], 1 }, 458 { &ifm_subtype_fddi_descriptions[0], 0 }, 459 { &ifm_subtype_fddi_aliases[0], 1 }, 460 { NULL, 0 }, 461 }, 462 { 463 { &ifm_shared_option_descriptions[0], 0 }, 464 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 465 { NULL, 0 }, 466 }, 467 { 468 { NULL, 0 }, 469 }, 470 }, 471 { 472 { 473 { &ifm_subtype_shared_descriptions[0], 0 }, 474 { &ifm_subtype_shared_aliases[0], 1 }, 475 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 476 { &ifm_subtype_ieee80211_aliases[0], 1 }, 477 { NULL, 0 }, 478 }, 479 { 480 { &ifm_shared_option_descriptions[0], 0 }, 481 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 482 { NULL, 0 }, 483 }, 484 { 485 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 486 { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 487 { NULL, 0 }, 488 }, 489 }, 490 { 491 { 492 { &ifm_subtype_shared_descriptions[0], 0 }, 493 { &ifm_subtype_shared_aliases[0], 1 }, 494 { &ifm_subtype_atm_descriptions[0], 0 }, 495 { &ifm_subtype_atm_aliases[0], 1 }, 496 { NULL, 0 }, 497 }, 498 { 499 { &ifm_shared_option_descriptions[0], 0 }, 500 { &ifm_subtype_atm_option_descriptions[0], 0 }, 501 { NULL, 0 }, 502 }, 503 { 504 { NULL, 0 }, 505 }, 506 }, 507 }; 508 509 static int 510 get_media_subtype(int type, const char *val) 511 { 512 struct ifmedia_description *desc; 513 struct ifmedia_type_to_subtype *ttos; 514 int rval, i; 515 516 /* Find the top-level interface type. */ 517 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 518 desc->ifmt_string != NULL; desc++, ttos++) 519 if (type == desc->ifmt_word) 520 break; 521 if (desc->ifmt_string == NULL) 522 errx(1, "unknown media type 0x%x", type); 523 524 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 525 rval = lookup_media_word(ttos->subtypes[i].desc, val); 526 if (rval != -1) 527 return (rval); 528 } 529 errx(1, "unknown media subtype: %s", val); 530 /*NOTREACHED*/ 531 } 532 533 static int 534 get_media_mode(int type, const char *val) 535 { 536 struct ifmedia_description *desc; 537 struct ifmedia_type_to_subtype *ttos; 538 int rval, i; 539 540 /* Find the top-level interface type. */ 541 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 542 desc->ifmt_string != NULL; desc++, ttos++) 543 if (type == desc->ifmt_word) 544 break; 545 if (desc->ifmt_string == NULL) 546 errx(1, "unknown media mode 0x%x", type); 547 548 for (i = 0; ttos->modes[i].desc != NULL; i++) { 549 rval = lookup_media_word(ttos->modes[i].desc, val); 550 if (rval != -1) 551 return (rval); 552 } 553 return -1; 554 } 555 556 static int 557 get_media_options(int type, const char *val) 558 { 559 struct ifmedia_description *desc; 560 struct ifmedia_type_to_subtype *ttos; 561 char *optlist, *optptr; 562 int option = 0, i, rval = 0; 563 564 /* We muck with the string, so copy it. */ 565 optlist = strdup(val); 566 if (optlist == NULL) 567 err(1, "strdup"); 568 569 /* Find the top-level interface type. */ 570 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 571 desc->ifmt_string != NULL; desc++, ttos++) 572 if (type == desc->ifmt_word) 573 break; 574 if (desc->ifmt_string == NULL) 575 errx(1, "unknown media type 0x%x", type); 576 577 /* 578 * Look up the options in the user-provided comma-separated 579 * list. 580 */ 581 optptr = optlist; 582 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 583 for (i = 0; ttos->options[i].desc != NULL; i++) { 584 option = lookup_media_word(ttos->options[i].desc, optptr); 585 if (option != -1) 586 break; 587 } 588 if (option == 0) 589 errx(1, "unknown option: %s", optptr); 590 rval |= option; 591 } 592 593 free(optlist); 594 return (rval); 595 } 596 597 static int 598 lookup_media_word(struct ifmedia_description *desc, const char *val) 599 { 600 601 for (; desc->ifmt_string != NULL; desc++) 602 if (strcasecmp(desc->ifmt_string, val) == 0) 603 return (desc->ifmt_word); 604 605 return (-1); 606 } 607 608 static struct ifmedia_description *get_toptype_desc(int ifmw) 609 { 610 struct ifmedia_description *desc; 611 612 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 613 if (IFM_TYPE(ifmw) == desc->ifmt_word) 614 break; 615 616 return desc; 617 } 618 619 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 620 { 621 struct ifmedia_description *desc; 622 struct ifmedia_type_to_subtype *ttos; 623 624 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 625 desc->ifmt_string != NULL; desc++, ttos++) 626 if (IFM_TYPE(ifmw) == desc->ifmt_word) 627 break; 628 629 return ttos; 630 } 631 632 static struct ifmedia_description *get_subtype_desc(int ifmw, 633 struct ifmedia_type_to_subtype *ttos) 634 { 635 int i; 636 struct ifmedia_description *desc; 637 638 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 639 if (ttos->subtypes[i].alias) 640 continue; 641 for (desc = ttos->subtypes[i].desc; 642 desc->ifmt_string != NULL; desc++) { 643 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 644 return desc; 645 } 646 } 647 648 return NULL; 649 } 650 651 static struct ifmedia_description *get_mode_desc(int ifmw, 652 struct ifmedia_type_to_subtype *ttos) 653 { 654 int i; 655 struct ifmedia_description *desc; 656 657 for (i = 0; ttos->modes[i].desc != NULL; i++) { 658 if (ttos->modes[i].alias) 659 continue; 660 for (desc = ttos->modes[i].desc; 661 desc->ifmt_string != NULL; desc++) { 662 if (IFM_MODE(ifmw) == desc->ifmt_word) 663 return desc; 664 } 665 } 666 667 return NULL; 668 } 669 670 static void 671 print_media_word(int ifmw, int print_toptype) 672 { 673 struct ifmedia_description *desc; 674 struct ifmedia_type_to_subtype *ttos; 675 int seen_option = 0, i; 676 677 /* Find the top-level interface type. */ 678 desc = get_toptype_desc(ifmw); 679 ttos = get_toptype_ttos(ifmw); 680 if (desc->ifmt_string == NULL) { 681 printf("<unknown type>"); 682 return; 683 } else if (print_toptype) { 684 printf("%s", desc->ifmt_string); 685 } 686 687 /* 688 * Don't print the top-level type; it's not like we can 689 * change it, or anything. 690 */ 691 692 /* Find subtype. */ 693 desc = get_subtype_desc(ifmw, ttos); 694 if (desc != NULL) 695 goto got_subtype; 696 697 /* Falling to here means unknown subtype. */ 698 printf("<unknown subtype>"); 699 return; 700 701 got_subtype: 702 if (print_toptype) 703 putchar(' '); 704 705 printf("%s", desc->ifmt_string); 706 707 if (print_toptype) { 708 desc = get_mode_desc(ifmw, ttos); 709 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 710 printf(" mode %s", desc->ifmt_string); 711 } 712 713 /* Find options. */ 714 for (i = 0; ttos->options[i].desc != NULL; i++) { 715 if (ttos->options[i].alias) 716 continue; 717 for (desc = ttos->options[i].desc; 718 desc->ifmt_string != NULL; desc++) { 719 if (ifmw & desc->ifmt_word) { 720 if (seen_option == 0) 721 printf(" <"); 722 printf("%s%s", seen_option++ ? "," : "", 723 desc->ifmt_string); 724 } 725 } 726 } 727 printf("%s", seen_option ? ">" : ""); 728 } 729 730 static void 731 print_media_word_ifconfig(int ifmw) 732 { 733 struct ifmedia_description *desc; 734 struct ifmedia_type_to_subtype *ttos; 735 int i; 736 737 /* Find the top-level interface type. */ 738 desc = get_toptype_desc(ifmw); 739 ttos = get_toptype_ttos(ifmw); 740 if (desc->ifmt_string == NULL) { 741 printf("<unknown type>"); 742 return; 743 } 744 745 /* 746 * Don't print the top-level type; it's not like we can 747 * change it, or anything. 748 */ 749 750 /* Find subtype. */ 751 desc = get_subtype_desc(ifmw, ttos); 752 if (desc != NULL) 753 goto got_subtype; 754 755 /* Falling to here means unknown subtype. */ 756 printf("<unknown subtype>"); 757 return; 758 759 got_subtype: 760 printf("media %s", desc->ifmt_string); 761 762 desc = get_mode_desc(ifmw, ttos); 763 if (desc != NULL) 764 printf(" mode %s", desc->ifmt_string); 765 766 /* Find options. */ 767 for (i = 0; ttos->options[i].desc != NULL; i++) { 768 if (ttos->options[i].alias) 769 continue; 770 for (desc = ttos->options[i].desc; 771 desc->ifmt_string != NULL; desc++) { 772 if (ifmw & desc->ifmt_word) { 773 printf(" mediaopt %s", desc->ifmt_string); 774 } 775 } 776 } 777 } 778 779 /********************************************************************** 780 * ...until here. 781 **********************************************************************/ 782 783 static struct cmd media_cmds[] = { 784 DEF_CMD_ARG("media", setmedia), 785 DEF_CMD_ARG("mode", setmediamode), 786 DEF_CMD_ARG("mediaopt", setmediaopt), 787 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 788 }; 789 static struct afswtch af_media = { 790 .af_name = "af_media", 791 .af_af = AF_UNSPEC, 792 .af_other_status = media_status, 793 }; 794 795 static __constructor void 796 ifmedia_ctor(void) 797 { 798 #define N(a) (sizeof(a) / sizeof(a[0])) 799 int i; 800 801 for (i = 0; i < N(media_cmds); i++) 802 cmd_register(&media_cmds[i]); 803 af_register(&af_media); 804 #undef N 805 } 806