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 * 4. 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 #define IFM_OPMODE(x) \ 102 ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 103 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 104 IFM_IEEE80211_MBSS)) 105 #define IFM_IEEE80211_STA 0 106 107 static void 108 media_status(int s) 109 { 110 struct ifmediareq ifmr; 111 int *media_list, i; 112 113 (void) memset(&ifmr, 0, sizeof(ifmr)); 114 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 115 116 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 117 /* 118 * Interface doesn't support SIOC{G,S}IFMEDIA. 119 */ 120 return; 121 } 122 123 if (ifmr.ifm_count == 0) { 124 warnx("%s: no media types?", name); 125 return; 126 } 127 128 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 129 if (media_list == NULL) 130 err(1, "malloc"); 131 ifmr.ifm_ulist = media_list; 132 133 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 134 err(1, "SIOCGIFMEDIA"); 135 136 printf("\tmedia: "); 137 print_media_word(ifmr.ifm_current, 1); 138 if (ifmr.ifm_active != ifmr.ifm_current) { 139 putchar(' '); 140 putchar('('); 141 print_media_word(ifmr.ifm_active, 0); 142 putchar(')'); 143 } 144 145 putchar('\n'); 146 147 if (ifmr.ifm_status & IFM_AVALID) { 148 printf("\tstatus: "); 149 switch (IFM_TYPE(ifmr.ifm_active)) { 150 case IFM_ETHER: 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_FDDI: 159 case IFM_TOKEN: 160 if (ifmr.ifm_status & IFM_ACTIVE) 161 printf("inserted"); 162 else 163 printf("no ring"); 164 break; 165 166 case IFM_IEEE80211: 167 if (ifmr.ifm_status & IFM_ACTIVE) { 168 /* NB: only sta mode associates */ 169 if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) 170 printf("associated"); 171 else 172 printf("running"); 173 } else 174 printf("no carrier"); 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 struct ifmediareq * 193 ifmedia_getstate(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 ifmr = ifmedia_getstate(s); 258 259 /* 260 * We are primarily concerned with the top-level type. 261 * However, "current" may be only IFM_NONE, so we just look 262 * for the top-level type in the first "supported type" 263 * entry. 264 * 265 * (I'm assuming that all supported media types for a given 266 * interface will be the same top-level type..) 267 */ 268 subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); 269 270 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 271 ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 272 IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; 273 274 if ((ifr.ifr_media & IFM_TMASK) == 0) { 275 ifr.ifr_media &= ~(IFM_GMASK | IFM_OMASK); 276 } 277 278 ifmr->ifm_current = ifr.ifr_media; 279 callback_register(setifmediacallback, (void *)ifmr); 280 } 281 282 static void 283 setmediaopt(const char *val, int d, int s, const struct afswtch *afp) 284 { 285 286 domediaopt(val, 0, s); 287 } 288 289 static void 290 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) 291 { 292 293 domediaopt(val, 1, s); 294 } 295 296 static void 297 domediaopt(const char *val, int clear, int s) 298 { 299 struct ifmediareq *ifmr; 300 int options; 301 302 ifmr = ifmedia_getstate(s); 303 304 options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); 305 306 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 307 ifr.ifr_media = ifmr->ifm_current; 308 if (clear) 309 ifr.ifr_media &= ~options; 310 else { 311 if (options & IFM_HDX) { 312 ifr.ifr_media &= ~IFM_FDX; 313 options &= ~IFM_HDX; 314 } 315 ifr.ifr_media |= options; 316 } 317 ifmr->ifm_current = ifr.ifr_media; 318 callback_register(setifmediacallback, (void *)ifmr); 319 } 320 321 static void 322 setmediainst(const char *val, int d, int s, const struct afswtch *afp) 323 { 324 struct ifmediareq *ifmr; 325 int inst; 326 327 ifmr = ifmedia_getstate(s); 328 329 inst = atoi(val); 330 if (inst < 0 || inst > (int)IFM_INST_MAX) 331 errx(1, "invalid media instance: %s", val); 332 333 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 334 ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; 335 336 ifmr->ifm_current = ifr.ifr_media; 337 callback_register(setifmediacallback, (void *)ifmr); 338 } 339 340 static void 341 setmediamode(const char *val, int d, int s, const struct afswtch *afp) 342 { 343 struct ifmediareq *ifmr; 344 int mode; 345 346 ifmr = ifmedia_getstate(s); 347 348 mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); 349 350 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 351 ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; 352 353 ifmr->ifm_current = ifr.ifr_media; 354 callback_register(setifmediacallback, (void *)ifmr); 355 } 356 357 /********************************************************************** 358 * A good chunk of this is duplicated from sys/net/ifmedia.c 359 **********************************************************************/ 360 361 static struct ifmedia_description ifm_type_descriptions[] = 362 IFM_TYPE_DESCRIPTIONS; 363 364 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 365 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 366 367 static struct ifmedia_description ifm_subtype_ethernet_aliases[] = 368 IFM_SUBTYPE_ETHERNET_ALIASES; 369 370 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 371 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 372 373 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 374 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 375 376 static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 377 IFM_SUBTYPE_TOKENRING_ALIASES; 378 379 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 380 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 381 382 static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 383 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 384 385 static struct ifmedia_description ifm_subtype_fddi_aliases[] = 386 IFM_SUBTYPE_FDDI_ALIASES; 387 388 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 389 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 390 391 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 392 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 393 394 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 395 IFM_SUBTYPE_IEEE80211_ALIASES; 396 397 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 398 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 399 400 struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 401 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 402 403 struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 404 IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 405 406 static struct ifmedia_description ifm_subtype_atm_descriptions[] = 407 IFM_SUBTYPE_ATM_DESCRIPTIONS; 408 409 static struct ifmedia_description ifm_subtype_atm_aliases[] = 410 IFM_SUBTYPE_ATM_ALIASES; 411 412 static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 413 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 414 415 static struct ifmedia_description ifm_subtype_shared_descriptions[] = 416 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 417 418 static struct ifmedia_description ifm_subtype_shared_aliases[] = 419 IFM_SUBTYPE_SHARED_ALIASES; 420 421 static struct ifmedia_description ifm_shared_option_descriptions[] = 422 IFM_SHARED_OPTION_DESCRIPTIONS; 423 424 static struct ifmedia_description ifm_shared_option_aliases[] = 425 IFM_SHARED_OPTION_ALIASES; 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[4]; 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_shared_option_aliases[0], 1 }, 455 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 456 { NULL, 0 }, 457 }, 458 { 459 { NULL, 0 }, 460 }, 461 }, 462 { 463 { 464 { &ifm_subtype_shared_descriptions[0], 0 }, 465 { &ifm_subtype_shared_aliases[0], 1 }, 466 { &ifm_subtype_tokenring_descriptions[0], 0 }, 467 { &ifm_subtype_tokenring_aliases[0], 1 }, 468 { NULL, 0 }, 469 }, 470 { 471 { &ifm_shared_option_descriptions[0], 0 }, 472 { &ifm_shared_option_aliases[0], 1 }, 473 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 474 { NULL, 0 }, 475 }, 476 { 477 { NULL, 0 }, 478 }, 479 }, 480 { 481 { 482 { &ifm_subtype_shared_descriptions[0], 0 }, 483 { &ifm_subtype_shared_aliases[0], 1 }, 484 { &ifm_subtype_fddi_descriptions[0], 0 }, 485 { &ifm_subtype_fddi_aliases[0], 1 }, 486 { NULL, 0 }, 487 }, 488 { 489 { &ifm_shared_option_descriptions[0], 0 }, 490 { &ifm_shared_option_aliases[0], 1 }, 491 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 492 { NULL, 0 }, 493 }, 494 { 495 { NULL, 0 }, 496 }, 497 }, 498 { 499 { 500 { &ifm_subtype_shared_descriptions[0], 0 }, 501 { &ifm_subtype_shared_aliases[0], 1 }, 502 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 503 { &ifm_subtype_ieee80211_aliases[0], 1 }, 504 { NULL, 0 }, 505 }, 506 { 507 { &ifm_shared_option_descriptions[0], 0 }, 508 { &ifm_shared_option_aliases[0], 1 }, 509 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 510 { NULL, 0 }, 511 }, 512 { 513 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 514 { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 515 { NULL, 0 }, 516 }, 517 }, 518 { 519 { 520 { &ifm_subtype_shared_descriptions[0], 0 }, 521 { &ifm_subtype_shared_aliases[0], 1 }, 522 { &ifm_subtype_atm_descriptions[0], 0 }, 523 { &ifm_subtype_atm_aliases[0], 1 }, 524 { NULL, 0 }, 525 }, 526 { 527 { &ifm_shared_option_descriptions[0], 0 }, 528 { &ifm_shared_option_aliases[0], 1 }, 529 { &ifm_subtype_atm_option_descriptions[0], 0 }, 530 { NULL, 0 }, 531 }, 532 { 533 { NULL, 0 }, 534 }, 535 }, 536 }; 537 538 static int 539 get_media_subtype(int type, const char *val) 540 { 541 struct ifmedia_description *desc; 542 struct ifmedia_type_to_subtype *ttos; 543 int rval, i; 544 545 /* Find the top-level interface type. */ 546 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 547 desc->ifmt_string != NULL; desc++, ttos++) 548 if (type == desc->ifmt_word) 549 break; 550 if (desc->ifmt_string == NULL) 551 errx(1, "unknown media type 0x%x", type); 552 553 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 554 rval = lookup_media_word(ttos->subtypes[i].desc, val); 555 if (rval != -1) 556 return (rval); 557 } 558 errx(1, "unknown media subtype: %s", val); 559 /*NOTREACHED*/ 560 } 561 562 static int 563 get_media_mode(int type, const char *val) 564 { 565 struct ifmedia_description *desc; 566 struct ifmedia_type_to_subtype *ttos; 567 int rval, i; 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 mode 0x%x", type); 576 577 for (i = 0; ttos->modes[i].desc != NULL; i++) { 578 rval = lookup_media_word(ttos->modes[i].desc, val); 579 if (rval != -1) 580 return (rval); 581 } 582 return -1; 583 } 584 585 static int 586 get_media_options(int type, const char *val) 587 { 588 struct ifmedia_description *desc; 589 struct ifmedia_type_to_subtype *ttos; 590 char *optlist, *optptr; 591 int option = 0, i, rval = 0; 592 593 /* We muck with the string, so copy it. */ 594 optlist = strdup(val); 595 if (optlist == NULL) 596 err(1, "strdup"); 597 598 /* Find the top-level interface type. */ 599 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 600 desc->ifmt_string != NULL; desc++, ttos++) 601 if (type == desc->ifmt_word) 602 break; 603 if (desc->ifmt_string == NULL) 604 errx(1, "unknown media type 0x%x", type); 605 606 /* 607 * Look up the options in the user-provided comma-separated 608 * list. 609 */ 610 optptr = optlist; 611 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { 612 for (i = 0; ttos->options[i].desc != NULL; i++) { 613 option = lookup_media_word(ttos->options[i].desc, optptr); 614 if (option != -1) 615 break; 616 } 617 if (option == 0) 618 errx(1, "unknown option: %s", optptr); 619 rval |= option; 620 } 621 622 free(optlist); 623 return (rval); 624 } 625 626 static int 627 lookup_media_word(struct ifmedia_description *desc, const char *val) 628 { 629 630 for (; desc->ifmt_string != NULL; desc++) 631 if (strcasecmp(desc->ifmt_string, val) == 0) 632 return (desc->ifmt_word); 633 634 return (-1); 635 } 636 637 static struct ifmedia_description *get_toptype_desc(int ifmw) 638 { 639 struct ifmedia_description *desc; 640 641 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 642 if (IFM_TYPE(ifmw) == desc->ifmt_word) 643 break; 644 645 return desc; 646 } 647 648 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 649 { 650 struct ifmedia_description *desc; 651 struct ifmedia_type_to_subtype *ttos; 652 653 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 654 desc->ifmt_string != NULL; desc++, ttos++) 655 if (IFM_TYPE(ifmw) == desc->ifmt_word) 656 break; 657 658 return ttos; 659 } 660 661 static struct ifmedia_description *get_subtype_desc(int ifmw, 662 struct ifmedia_type_to_subtype *ttos) 663 { 664 int i; 665 struct ifmedia_description *desc; 666 667 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 668 if (ttos->subtypes[i].alias) 669 continue; 670 for (desc = ttos->subtypes[i].desc; 671 desc->ifmt_string != NULL; desc++) { 672 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 673 return desc; 674 } 675 } 676 677 return NULL; 678 } 679 680 static struct ifmedia_description *get_mode_desc(int ifmw, 681 struct ifmedia_type_to_subtype *ttos) 682 { 683 int i; 684 struct ifmedia_description *desc; 685 686 for (i = 0; ttos->modes[i].desc != NULL; i++) { 687 if (ttos->modes[i].alias) 688 continue; 689 for (desc = ttos->modes[i].desc; 690 desc->ifmt_string != NULL; desc++) { 691 if (IFM_MODE(ifmw) == desc->ifmt_word) 692 return desc; 693 } 694 } 695 696 return NULL; 697 } 698 699 static void 700 print_media_word(int ifmw, int print_toptype) 701 { 702 struct ifmedia_description *desc; 703 struct ifmedia_type_to_subtype *ttos; 704 int seen_option = 0, i; 705 706 /* Find the top-level interface type. */ 707 desc = get_toptype_desc(ifmw); 708 ttos = get_toptype_ttos(ifmw); 709 if (desc->ifmt_string == NULL) { 710 printf("<unknown type>"); 711 return; 712 } else if (print_toptype) { 713 printf("%s", desc->ifmt_string); 714 } 715 716 /* 717 * Don't print the top-level type; it's not like we can 718 * change it, or anything. 719 */ 720 721 /* Find subtype. */ 722 desc = get_subtype_desc(ifmw, ttos); 723 if (desc == NULL) { 724 printf("<unknown subtype>"); 725 return; 726 } 727 728 if (print_toptype) 729 putchar(' '); 730 731 printf("%s", desc->ifmt_string); 732 733 if (print_toptype) { 734 desc = get_mode_desc(ifmw, ttos); 735 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 736 printf(" mode %s", desc->ifmt_string); 737 } 738 739 /* Find options. */ 740 for (i = 0; ttos->options[i].desc != NULL; i++) { 741 if (ttos->options[i].alias) 742 continue; 743 for (desc = ttos->options[i].desc; 744 desc->ifmt_string != NULL; desc++) { 745 if (ifmw & desc->ifmt_word) { 746 if (seen_option == 0) 747 printf(" <"); 748 printf("%s%s", seen_option++ ? "," : "", 749 desc->ifmt_string); 750 } 751 } 752 } 753 printf("%s", seen_option ? ">" : ""); 754 755 if (print_toptype && IFM_INST(ifmw) != 0) 756 printf(" instance %d", IFM_INST(ifmw)); 757 } 758 759 static void 760 print_media_word_ifconfig(int ifmw) 761 { 762 struct ifmedia_description *desc; 763 struct ifmedia_type_to_subtype *ttos; 764 int seen_option = 0, i; 765 766 /* Find the top-level interface type. */ 767 desc = get_toptype_desc(ifmw); 768 ttos = get_toptype_ttos(ifmw); 769 if (desc->ifmt_string == NULL) { 770 printf("<unknown type>"); 771 return; 772 } 773 774 /* 775 * Don't print the top-level type; it's not like we can 776 * change it, or anything. 777 */ 778 779 /* Find subtype. */ 780 desc = get_subtype_desc(ifmw, ttos); 781 if (desc == NULL) { 782 printf("<unknown subtype>"); 783 return; 784 } 785 786 printf("media %s", desc->ifmt_string); 787 788 desc = get_mode_desc(ifmw, ttos); 789 if (desc != NULL) 790 printf(" mode %s", desc->ifmt_string); 791 792 /* Find options. */ 793 for (i = 0; ttos->options[i].desc != NULL; i++) { 794 if (ttos->options[i].alias) 795 continue; 796 for (desc = ttos->options[i].desc; 797 desc->ifmt_string != NULL; desc++) { 798 if (ifmw & desc->ifmt_word) { 799 if (seen_option == 0) 800 printf(" mediaopt "); 801 printf("%s%s", seen_option++ ? "," : "", 802 desc->ifmt_string); 803 } 804 } 805 } 806 807 if (IFM_INST(ifmw) != 0) 808 printf(" instance %d", IFM_INST(ifmw)); 809 } 810 811 /********************************************************************** 812 * ...until here. 813 **********************************************************************/ 814 815 static struct cmd media_cmds[] = { 816 DEF_CMD_ARG("media", setmedia), 817 DEF_CMD_ARG("mode", setmediamode), 818 DEF_CMD_ARG("mediaopt", setmediaopt), 819 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 820 DEF_CMD_ARG("inst", setmediainst), 821 DEF_CMD_ARG("instance", setmediainst), 822 }; 823 static struct afswtch af_media = { 824 .af_name = "af_media", 825 .af_af = AF_UNSPEC, 826 .af_other_status = media_status, 827 }; 828 829 static __constructor void 830 ifmedia_ctor(void) 831 { 832 #define N(a) (sizeof(a) / sizeof(a[0])) 833 size_t i; 834 835 for (i = 0; i < N(media_cmds); i++) 836 cmd_register(&media_cmds[i]); 837 af_register(&af_media); 838 #undef N 839 } 840