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