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 = 0, 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 for (i = 0; ttos->options[i].desc != NULL; i++) { 591 option = lookup_media_word(ttos->options[i].desc, optptr); 592 if (option != -1) 593 break; 594 } 595 if (option == 0) 596 errx(1, "unknown option: %s", optptr); 597 rval |= option; 598 } 599 600 free(optlist); 601 return (rval); 602 } 603 604 static int 605 lookup_media_word(struct ifmedia_description *desc, const char *val) 606 { 607 608 for (; desc->ifmt_string != NULL; desc++) 609 if (strcasecmp(desc->ifmt_string, val) == 0) 610 return (desc->ifmt_word); 611 612 return (-1); 613 } 614 615 static struct ifmedia_description *get_toptype_desc(int ifmw) 616 { 617 struct ifmedia_description *desc; 618 619 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) 620 if (IFM_TYPE(ifmw) == desc->ifmt_word) 621 break; 622 623 return desc; 624 } 625 626 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) 627 { 628 struct ifmedia_description *desc; 629 struct ifmedia_type_to_subtype *ttos; 630 631 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 632 desc->ifmt_string != NULL; desc++, ttos++) 633 if (IFM_TYPE(ifmw) == desc->ifmt_word) 634 break; 635 636 return ttos; 637 } 638 639 static struct ifmedia_description *get_subtype_desc(int ifmw, 640 struct ifmedia_type_to_subtype *ttos) 641 { 642 int i; 643 struct ifmedia_description *desc; 644 645 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 646 if (ttos->subtypes[i].alias) 647 continue; 648 for (desc = ttos->subtypes[i].desc; 649 desc->ifmt_string != NULL; desc++) { 650 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 651 return desc; 652 } 653 } 654 655 return NULL; 656 } 657 658 static struct ifmedia_description *get_mode_desc(int ifmw, 659 struct ifmedia_type_to_subtype *ttos) 660 { 661 int i; 662 struct ifmedia_description *desc; 663 664 for (i = 0; ttos->modes[i].desc != NULL; i++) { 665 if (ttos->modes[i].alias) 666 continue; 667 for (desc = ttos->modes[i].desc; 668 desc->ifmt_string != NULL; desc++) { 669 if (IFM_MODE(ifmw) == desc->ifmt_word) 670 return desc; 671 } 672 } 673 674 return NULL; 675 } 676 677 static void 678 print_media_word(int ifmw, int print_toptype) 679 { 680 struct ifmedia_description *desc; 681 struct ifmedia_type_to_subtype *ttos; 682 int seen_option = 0, i; 683 684 /* Find the top-level interface type. */ 685 desc = get_toptype_desc(ifmw); 686 ttos = get_toptype_ttos(ifmw); 687 if (desc->ifmt_string == NULL) { 688 printf("<unknown type>"); 689 return; 690 } else if (print_toptype) { 691 printf("%s", desc->ifmt_string); 692 } 693 694 /* 695 * Don't print the top-level type; it's not like we can 696 * change it, or anything. 697 */ 698 699 /* Find subtype. */ 700 desc = get_subtype_desc(ifmw, ttos); 701 if (desc == NULL) { 702 printf("<unknown subtype>"); 703 return; 704 } 705 706 if (print_toptype) 707 putchar(' '); 708 709 printf("%s", desc->ifmt_string); 710 711 if (print_toptype) { 712 desc = get_mode_desc(ifmw, ttos); 713 if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) 714 printf(" mode %s", desc->ifmt_string); 715 } 716 717 /* Find options. */ 718 for (i = 0; ttos->options[i].desc != NULL; i++) { 719 if (ttos->options[i].alias) 720 continue; 721 for (desc = ttos->options[i].desc; 722 desc->ifmt_string != NULL; desc++) { 723 if (ifmw & desc->ifmt_word) { 724 if (seen_option == 0) 725 printf(" <"); 726 printf("%s%s", seen_option++ ? "," : "", 727 desc->ifmt_string); 728 } 729 } 730 } 731 printf("%s", seen_option ? ">" : ""); 732 733 if (print_toptype && IFM_INST(ifmw) != 0) 734 printf(" instance %d", IFM_INST(ifmw)); 735 } 736 737 static void 738 print_media_word_ifconfig(int ifmw) 739 { 740 struct ifmedia_description *desc; 741 struct ifmedia_type_to_subtype *ttos; 742 int seen_option = 0, i; 743 744 /* Find the top-level interface type. */ 745 desc = get_toptype_desc(ifmw); 746 ttos = get_toptype_ttos(ifmw); 747 if (desc->ifmt_string == NULL) { 748 printf("<unknown type>"); 749 return; 750 } 751 752 /* 753 * Don't print the top-level type; it's not like we can 754 * change it, or anything. 755 */ 756 757 /* Find subtype. */ 758 desc = get_subtype_desc(ifmw, ttos); 759 if (desc == NULL) { 760 printf("<unknown subtype>"); 761 return; 762 } 763 764 printf("media %s", desc->ifmt_string); 765 766 desc = get_mode_desc(ifmw, ttos); 767 if (desc != NULL) 768 printf(" mode %s", desc->ifmt_string); 769 770 /* Find options. */ 771 for (i = 0; ttos->options[i].desc != NULL; i++) { 772 if (ttos->options[i].alias) 773 continue; 774 for (desc = ttos->options[i].desc; 775 desc->ifmt_string != NULL; desc++) { 776 if (ifmw & desc->ifmt_word) { 777 if (seen_option == 0) 778 printf(" mediaopt "); 779 printf("%s%s", seen_option++ ? "," : "", 780 desc->ifmt_string); 781 } 782 } 783 } 784 785 if (IFM_INST(ifmw) != 0) 786 printf(" instance %d", IFM_INST(ifmw)); 787 } 788 789 /********************************************************************** 790 * ...until here. 791 **********************************************************************/ 792 793 static struct cmd media_cmds[] = { 794 DEF_CMD_ARG("media", setmedia), 795 DEF_CMD_ARG("mode", setmediamode), 796 DEF_CMD_ARG("mediaopt", setmediaopt), 797 DEF_CMD_ARG("-mediaopt",unsetmediaopt), 798 DEF_CMD_ARG("inst", setmediainst), 799 DEF_CMD_ARG("instance", setmediainst), 800 }; 801 static struct afswtch af_media = { 802 .af_name = "af_media", 803 .af_af = AF_UNSPEC, 804 .af_other_status = media_status, 805 }; 806 807 static __constructor void 808 ifmedia_ctor(void) 809 { 810 size_t i; 811 812 for (i = 0; i < nitems(media_cmds); i++) 813 cmd_register(&media_cmds[i]); 814 af_register(&af_media); 815 } 816