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 #define IFM_OPMODE(x) \ 106 ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 107 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR)) 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_FDDI: 162 case IFM_TOKEN: 163 if (ifmr.ifm_status & IFM_ACTIVE) 164 printf("inserted"); 165 else 166 printf("no ring"); 167 break; 168 169 case IFM_IEEE80211: 170 if (ifmr.ifm_status & IFM_ACTIVE) { 171 /* NB: only sta mode associates */ 172 if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 173 printf("associated"); 174 else 175 printf("running"); 176 } else 177 printf("no carrier"); 178 break; 179 } 180 putchar('\n'); 181 } 182 183 if (ifmr.ifm_count > 0 && supmedia) { 184 printf("\tsupported media:\n"); 185 for (i = 0; i < ifmr.ifm_count; i++) { 186 printf("\t\t"); 187 print_media_word_ifconfig(media_list[i]); 188 putchar('\n'); 189 } 190 } 191 192 free(media_list); 193 } 194 195 struct ifmediareq * 196 ifmedia_getstate(int s) 197 { 198 static struct ifmediareq *ifmr = NULL; 199 int *mwords; 200 201 if (ifmr == NULL) { 202 ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); 203 if (ifmr == NULL) 204 err(1, "malloc"); 205 206 (void) memset(ifmr, 0, sizeof(struct ifmediareq)); 207 (void) strncpy(ifmr->ifm_name, name, 208 sizeof(ifmr->ifm_name)); 209 210 ifmr->ifm_count = 0; 211 ifmr->ifm_ulist = NULL; 212 213 /* 214 * We must go through the motions of reading all 215 * supported media because we need to know both 216 * the current media type and the top-level type. 217 */ 218 219 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { 220 err(1, "SIOCGIFMEDIA"); 221 } 222 223 if (ifmr->ifm_count == 0) 224 errx(1, "%s: no media types?", name); 225 226 mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); 227 if (mwords == NULL) 228 err(1, "malloc"); 229 230 ifmr->ifm_ulist = mwords; 231 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) 232 err(1, "SIOCGIFMEDIA"); 233 } 234 235 return ifmr; 236 } 237 238 static void 239 setifmediacallback(int s, void *arg) 240 { 241 struct ifmediareq *ifmr = (struct ifmediareq *)arg; 242 static int did_it = 0; 243 244 if (!did_it) { 245 ifr.ifr_media = ifmr->ifm_current; 246 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 247 err(1, "SIOCSIFMEDIA (media)"); 248 free(ifmr->ifm_ulist); 249 free(ifmr); 250 did_it = 1; 251 } 252 } 253 254 static void 255 setmedia(const char *val, int d, int s, const struct afswtch *afp) 256 { 257 struct ifmediareq *ifmr; 258 int subtype; 259 260 ifmr = ifmedia_getstate(s); 261 262 /* 263 * We are primarily concerned with the top-level type. 264 * However, "current" may be only IFM_NONE, so we just look 265 * for the top-level type in the first "supported type" 266 * entry. 267 * 268 * (I'm assuming that all supported media types for a given 269 * interface will be the same top-level type..) 270 */ 271 subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 272 273 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 274 ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 275 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 276 277 if ((ifr.ifr_media & IFM_TMASK) == 0) { 278 ifr.ifr_media &= ~IFM_GMASK; 279 } 280 281 ifmr->ifm_current = ifr.ifr_media; 282 callback_register(setifmediacallback, (void *)ifmr); 283 } 284 285 static void 286 setmediaopt(const char *val, int d, int s, const struct afswtch *afp) 287 { 288 289 domediaopt(val, 0, s); 290 } 291 292 static void 293 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 294 { 295 296 domediaopt(val, 1, s); 297 } 298 299 static void 300 domediaopt(const char *val, int clear, int s) 301 { 302 struct ifmediareq *ifmr; 303 int options; 304 305 ifmr = ifmedia_getstate(s); 306 307 options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 308 309 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 310 ifr.ifr_media = ifmr->ifm_current; 311 if (clear) 312 ifr.ifr_media &= ~options; 313 else { 314 if (options & IFM_HDX) { 315 ifr.ifr_media &= ~IFM_FDX; 316 options &= ~IFM_HDX; 317 } 318 ifr.ifr_media |= options; 319 } 320 ifmr->ifm_current = ifr.ifr_media; 321 callback_register(setifmediacallback, (void *)ifmr); 322 } 323 324 static void 325 setmediainst(const char *val, int d, int s, const struct afswtch *afp) 326 { 327 struct ifmediareq *ifmr; 328 int inst; 329 330 ifmr = ifmedia_getstate(s); 331 332 inst = atoi(val); 333 if (inst < 0 || inst > IFM_INST_MAX) 334 errx(1, "invalid media instance: %s", val); 335 336 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 337 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 338 339 ifmr->ifm_current = ifr.ifr_media; 340 callback_register(setifmediacallback, (void *)ifmr); 341 } 342 343 static void 344 setmediamode(const char *val, int d, int s, const struct afswtch *afp) 345 { 346 struct ifmediareq *ifmr; 347 int mode; 348 349 ifmr = ifmedia_getstate(s); 350 351 mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 352 353 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 354 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 355 356 ifmr->ifm_current = ifr.ifr_media; 357 callback_register(setifmediacallback, (void *)ifmr); 358 } 359 360 /********************************************************************** 361 * A good chunk of this is duplicated from sys/net/ifmedia.c 362 **********************************************************************/ 363 364 static struct ifmedia_description ifm_type_descriptions[] = 365 IFM_TYPE_DESCRIPTIONS; 366 367 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 368 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 369 370 static struct ifmedia_description ifm_subtype_ethernet_aliases[] = 371 IFM_SUBTYPE_ETHERNET_ALIASES; 372 373 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 374 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 375 376 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 377 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 378 379 static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 380 IFM_SUBTYPE_TOKENRING_ALIASES; 381 382 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 383 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 384 385 static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 386 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 387 388 static struct ifmedia_description ifm_subtype_fddi_aliases[] = 389 IFM_SUBTYPE_FDDI_ALIASES; 390 391 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 392 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 393 394 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 395 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 396 397 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 398 IFM_SUBTYPE_IEEE80211_ALIASES; 399 400 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 401 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 402 403 struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 404 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 405 406 struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 407 IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 408 409 static struct ifmedia_description ifm_subtype_atm_descriptions[] = 410 IFM_SUBTYPE_ATM_DESCRIPTIONS; 411 412 static struct ifmedia_description ifm_subtype_atm_aliases[] = 413 IFM_SUBTYPE_ATM_ALIASES; 414 415 static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 416 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 417 418 static struct ifmedia_description ifm_subtype_shared_descriptions[] = 419 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 420 421 static struct ifmedia_description ifm_subtype_shared_aliases[] = 422 IFM_SUBTYPE_SHARED_ALIASES; 423 424 static struct ifmedia_description ifm_shared_option_descriptions[] = 425 IFM_SHARED_OPTION_DESCRIPTIONS; 426 427 struct ifmedia_type_to_subtype { 428 struct { 429 struct ifmedia_description *desc; 430 int alias; 431 } subtypes[5]; 432 struct { 433 struct ifmedia_description *desc; 434 int alias; 435 } options[3]; 436 struct { 437 struct ifmedia_description *desc; 438 int alias; 439 } modes[3]; 440 }; 441 442 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 443 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 444 { 445 { 446 { &ifm_subtype_shared_descriptions[0], 0 }, 447 { &ifm_subtype_shared_aliases[0], 1 }, 448 { &ifm_subtype_ethernet_descriptions[0], 0 }, 449 { &ifm_subtype_ethernet_aliases[0], 1 }, 450 { NULL, 0 }, 451 }, 452 { 453 { &ifm_shared_option_descriptions[0], 0 }, 454 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 455 { NULL, 0 }, 456 }, 457 { 458 { NULL, 0 }, 459 }, 460 }, 461 { 462 { 463 { &ifm_subtype_shared_descriptions[0], 0 }, 464 { &ifm_subtype_shared_aliases[0], 1 }, 465 { &ifm_subtype_tokenring_descriptions[0], 0 }, 466 { &ifm_subtype_tokenring_aliases[0], 1 }, 467 { NULL, 0 }, 468 }, 469 { 470 { &ifm_shared_option_descriptions[0], 0 }, 471 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 472 { NULL, 0 }, 473 }, 474 { 475 { NULL, 0 }, 476 }, 477 }, 478 { 479 { 480 { &ifm_subtype_shared_descriptions[0], 0 }, 481 { &ifm_subtype_shared_aliases[0], 1 }, 482 { &ifm_subtype_fddi_descriptions[0], 0 }, 483 { &ifm_subtype_fddi_aliases[0], 1 }, 484 { NULL, 0 }, 485 }, 486 { 487 { &ifm_shared_option_descriptions[0], 0 }, 488 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 489 { NULL, 0 }, 490 }, 491 { 492 { NULL, 0 }, 493 }, 494 }, 495 { 496 { 497 { &ifm_subtype_shared_descriptions[0], 0 }, 498 { &ifm_subtype_shared_aliases[0], 1 }, 499 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 500 { &ifm_subtype_ieee80211_aliases[0], 1 }, 501 { NULL, 0 }, 502 }, 503 { 504 { &ifm_shared_option_descriptions[0], 0 }, 505 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 506 { NULL, 0 }, 507 }, 508 { 509 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 510 { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 511 { NULL, 0 }, 512 }, 513 }, 514 { 515 { 516 { &ifm_subtype_shared_descriptions[0], 0 }, 517 { &ifm_subtype_shared_aliases[0], 1 }, 518 { &ifm_subtype_atm_descriptions[0], 0 }, 519 { &ifm_subtype_atm_aliases[0], 1 }, 520 { NULL, 0 }, 521 }, 522 { 523 { &ifm_shared_option_descriptions[0], 0 }, 524 { &ifm_subtype_atm_option_descriptions[0], 0 }, 525 { NULL, 0 }, 526 }, 527 { 528 { NULL, 0 }, 529 }, 530 }, 531 }; 532 533 static int 534 get_media_subtype(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 type 0x%x", type); 547 548 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 549 rval = lookup_media_word(ttos->subtypes[i].desc, val); 550 if (rval != -1) 551 return (rval); 552 } 553 errx(1, "unknown media subtype: %s", val); 554 /*NOTREACHED*/ 555 } 556 557 static int 558 get_media_mode(int type, const char *val) 559 { 560 struct ifmedia_description *desc; 561 struct ifmedia_type_to_subtype *ttos; 562 int rval, i; 563 564 /* Find the top-level interface type. */ 565 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 566 desc->ifmt_string != NULL; desc++, ttos++) 567 if (type == desc->ifmt_word) 568 break; 569 if (desc->ifmt_string == NULL) 570 errx(1, "unknown media mode 0x%x", type); 571 572 for (i = 0; ttos->modes[i].desc != NULL; i++) { 573 rval = lookup_media_word(ttos->modes[i].desc, val); 574 if (rval != -1) 575 return (rval); 576 } 577 return -1; 578 } 579 580 static int 581 get_media_options(int type, const char *val) 582 { 583 struct ifmedia_description *desc; 584 struct ifmedia_type_to_subtype *ttos; 585 char *optlist, *optptr; 586 int option = 0, i, rval = 0; 587 588 /* We muck with the string, so copy it. */ 589 optlist = strdup(val); 590 if (optlist == NULL) 591 err(1, "strdup"); 592 593 /* Find the top-level interface type. */ 594 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 595 desc->ifmt_string != NULL; desc++, ttos++) 596 if (type == desc->ifmt_word) 597 break; 598 if (desc->ifmt_string == NULL) 599 errx(1, "unknown media type 0x%x", type); 600 601 /* 602 * Look up the options in the user-provided comma-separated 603 * list. 604 */ 605 optptr = optlist; 606 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 607 for (i = 0; ttos->options[i].desc != NULL; i++) { 608 option = lookup_media_word(ttos->options[i].desc, optptr); 609 if (option != -1) 610 break; 611 } 612 if (option == 0) 613 errx(1, "unknown option: %s", optptr); 614 rval |= option; 615 } 616 617 free(optlist); 618 return (rval); 619 } 620 621 static int 622 lookup_media_word(struct ifmedia_description *desc, const char *val) 623 { 624 625 for (; desc->ifmt_string != NULL; desc++) 626 if (strcasecmp(desc->ifmt_string, val) == 0) 627 return (desc->ifmt_word); 628 629 return (-1); 630 } 631 632 static struct ifmedia_description *get_toptype_desc(int ifmw) 633 { 634 struct ifmedia_description *desc; 635 636 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 637 if (IFM_TYPE(ifmw) == desc->ifmt_word) 638 break; 639 640 return desc; 641 } 642 643 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 644 { 645 struct ifmedia_description *desc; 646 struct ifmedia_type_to_subtype *ttos; 647 648 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 649 desc->ifmt_string != NULL; desc++, ttos++) 650 if (IFM_TYPE(ifmw) == desc->ifmt_word) 651 break; 652 653 return ttos; 654 } 655 656 static struct ifmedia_description *get_subtype_desc(int ifmw, 657 struct ifmedia_type_to_subtype *ttos) 658 { 659 int i; 660 struct ifmedia_description *desc; 661 662 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 663 if (ttos->subtypes[i].alias) 664 continue; 665 for (desc = ttos->subtypes[i].desc; 666 desc->ifmt_string != NULL; desc++) { 667 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 668 return desc; 669 } 670 } 671 672 return NULL; 673 } 674 675 static struct ifmedia_description *get_mode_desc(int ifmw, 676 struct ifmedia_type_to_subtype *ttos) 677 { 678 int i; 679 struct ifmedia_description *desc; 680 681 for (i = 0; ttos->modes[i].desc != NULL; i++) { 682 if (ttos->modes[i].alias) 683 continue; 684 for (desc = ttos->modes[i].desc; 685 desc->ifmt_string != NULL; desc++) { 686 if (IFM_MODE(ifmw) == desc->ifmt_word) 687 return desc; 688 } 689 } 690 691 return NULL; 692 } 693 694 static void 695 print_media_word(int ifmw, int print_toptype) 696 { 697 struct ifmedia_description *desc; 698 struct ifmedia_type_to_subtype *ttos; 699 int seen_option = 0, i; 700 701 /* Find the top-level interface type. */ 702 desc = get_toptype_desc(ifmw); 703 ttos = get_toptype_ttos(ifmw); 704 if (desc->ifmt_string == NULL) { 705 printf("<unknown type>"); 706 return; 707 } else if (print_toptype) { 708 printf("%s", desc->ifmt_string); 709 } 710 711 /* 712 * Don't print the top-level type; it's not like we can 713 * change it, or anything. 714 */ 715 716 /* Find subtype. */ 717 desc = get_subtype_desc(ifmw, ttos); 718 if (desc == NULL) { 719 printf("<unknown subtype>"); 720 return; 721 } 722 723 if (print_toptype) 724 putchar(' '); 725 726 printf("%s", desc->ifmt_string); 727 728 if (print_toptype) { 729 desc = get_mode_desc(ifmw, ttos); 730 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 731 printf(" mode %s", desc->ifmt_string); 732 } 733 734 /* Find options. */ 735 for (i = 0; ttos->options[i].desc != NULL; i++) { 736 if (ttos->options[i].alias) 737 continue; 738 for (desc = ttos->options[i].desc; 739 desc->ifmt_string != NULL; desc++) { 740 if (ifmw & desc->ifmt_word) { 741 if (seen_option == 0) 742 printf(" <"); 743 printf("%s%s", seen_option++ ? "," : "", 744 desc->ifmt_string); 745 } 746 } 747 } 748 printf("%s", seen_option ? ">" : ""); 749 750 if (print_toptype && IFM_INST(ifmw) != 0) 751 printf(" instance %d", IFM_INST(ifmw)); 752 } 753 754 static void 755 print_media_word_ifconfig(int ifmw) 756 { 757 struct ifmedia_description *desc; 758 struct ifmedia_type_to_subtype *ttos; 759 int i; 760 761 /* Find the top-level interface type. */ 762 desc = get_toptype_desc(ifmw); 763 ttos = get_toptype_ttos(ifmw); 764 if (desc->ifmt_string == NULL) { 765 printf("<unknown type>"); 766 return; 767 } 768 769 /* 770 * Don't print the top-level type; it's not like we can 771 * change it, or anything. 772 */ 773 774 /* Find subtype. */ 775 desc = get_subtype_desc(ifmw, ttos); 776 if (desc == NULL) { 777 printf("<unknown subtype>"); 778 return; 779 } 780 781 printf("media %s", desc->ifmt_string); 782 783 desc = get_mode_desc(ifmw, ttos); 784 if (desc != NULL) 785 printf(" mode %s", desc->ifmt_string); 786 787 /* Find options. */ 788 for (i = 0; ttos->options[i].desc != NULL; i++) { 789 if (ttos->options[i].alias) 790 continue; 791 for (desc = ttos->options[i].desc; 792 desc->ifmt_string != NULL; desc++) { 793 if (ifmw & desc->ifmt_word) { 794 printf(" mediaopt %s", desc->ifmt_string); 795 } 796 } 797 } 798 799 if (IFM_INST(ifmw) != 0) 800 printf(" instance %d", IFM_INST(ifmw)); 801 } 802 803 /********************************************************************** 804 * ...until here. 805 **********************************************************************/ 806 807 static struct cmd media_cmds[] = { 808 DEF_CMD_ARG("media", setmedia), 809 DEF_CMD_ARG("mode", setmediamode), 810 DEF_CMD_ARG("mediaopt", setmediaopt), 811 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 812 DEF_CMD_ARG("inst", setmediainst), 813 DEF_CMD_ARG("instance", setmediainst), 814 }; 815 static struct afswtch af_media = { 816 .af_name = "af_media", 817 .af_af = AF_UNSPEC, 818 .af_other_status = media_status, 819 }; 820 821 static __constructor void 822 ifmedia_ctor(void) 823 { 824 #define N(a) (sizeof(a) / sizeof(a[0])) 825 int i; 826 827 for (i = 0; i < N(media_cmds); i++) 828 cmd_register(&media_cmds[i]); 829 af_register(&af_media); 830 #undef N 831 } 832