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