1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
5 * Copyright (c) 1997 Jason R. Thorpe.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
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
37 * Copyright (c) 1983, 1993
38 * The Regents of the University of California. All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 #include <sys/param.h>
70 #include <sys/ioctl.h>
71 #include <sys/socket.h>
72 #include <sys/sysctl.h>
76 #include <net/if_dl.h>
77 #include <net/if_types.h>
78 #include <net/if_media.h>
79 #include <net/route.h>
92 static void domediaopt(const char *, int, int);
93 static int get_media_subtype(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);
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);
105 media_status(int s, struct rt_addrinfo *info __unused)
107 struct ifmediareq ifmr;
110 (void) memset(&ifmr, 0, sizeof(ifmr));
111 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
113 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
115 * Interface doesn't support SIOC{G,S}IFMEDIA.
120 if (ifmr.ifm_count == 0) {
121 warnx("%s: no media types?", name);
125 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
126 if (media_list == NULL)
128 ifmr.ifm_ulist = media_list;
130 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
131 err(1, "SIOCGIFMEDIA");
134 print_media_word(ifmr.ifm_current, 1);
135 if (ifmr.ifm_active != ifmr.ifm_current) {
138 print_media_word(ifmr.ifm_active, 0);
144 if (ifmr.ifm_status & IFM_AVALID) {
145 printf("\tstatus: ");
146 switch (IFM_TYPE(ifmr.ifm_active)) {
148 if (ifmr.ifm_status & IFM_ACTIVE)
151 printf("no carrier");
156 if (ifmr.ifm_status & IFM_ACTIVE)
162 /* XXX: Different value for adhoc? */
163 if (ifmr.ifm_status & IFM_ACTIVE)
164 printf("associated");
166 printf("no carrier");
172 if (ifmr.ifm_count > 0 && supmedia) {
173 printf("\tsupported media:\n");
174 for (i = 0; i < ifmr.ifm_count; i++) {
176 print_media_word_ifconfig(media_list[i]);
185 setmedia(const char *val, int d, int s, const struct afswtch *afp)
187 struct ifmediareq ifmr;
188 int first_type, subtype;
190 (void) memset(&ifmr, 0, sizeof(ifmr));
191 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
194 ifmr.ifm_ulist = &first_type;
195 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
197 * If we get E2BIG, the kernel is telling us
198 * that there are more, so we can ignore it.
201 err(1, "SIOCGIFMEDIA");
204 if (ifmr.ifm_count == 0)
205 errx(1, "%s: no media types?", name);
208 * We are primarily concerned with the top-level type.
209 * However, "current" may be only IFM_NONE, so we just look
210 * for the top-level type in the first "supported type"
213 * (I'm assuming that all supported media types for a given
214 * interface will be the same top-level type..)
216 subtype = get_media_subtype(IFM_TYPE(first_type), val);
218 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
219 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
220 IFM_TYPE(first_type) | subtype;
222 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
223 err(1, "SIOCSIFMEDIA");
227 setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
230 domediaopt(val, 0, s);
234 unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
237 domediaopt(val, 1, s);
241 domediaopt(const char *val, int clear, int s)
243 struct ifmediareq ifmr;
244 int *mwords, options;
246 (void) memset(&ifmr, 0, sizeof(ifmr));
247 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
250 * We must go through the motions of reading all
251 * supported media because we need to know both
252 * the current media type and the top-level type.
255 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
256 err(1, "SIOCGIFMEDIA");
258 if (ifmr.ifm_count == 0)
259 errx(1, "%s: no media types?", name);
261 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
265 ifmr.ifm_ulist = mwords;
266 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
267 err(1, "SIOCGIFMEDIA");
269 options = get_media_options(IFM_TYPE(mwords[0]), val);
273 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
274 ifr.ifr_media = ifmr.ifm_current;
276 ifr.ifr_media &= ~options;
278 ifr.ifr_media |= options;
280 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
281 err(1, "SIOCSIFMEDIA");
284 /**********************************************************************
285 * A good chunk of this is duplicated from sys/net/ifmedia.c
286 **********************************************************************/
288 static struct ifmedia_description ifm_type_descriptions[] =
289 IFM_TYPE_DESCRIPTIONS;
291 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
292 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
294 static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
295 IFM_SUBTYPE_ETHERNET_ALIASES;
297 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
298 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
300 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
301 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
303 static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
304 IFM_SUBTYPE_TOKENRING_ALIASES;
306 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
307 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
309 static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
310 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
312 static struct ifmedia_description ifm_subtype_fddi_aliases[] =
313 IFM_SUBTYPE_FDDI_ALIASES;
315 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
316 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
318 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
319 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
321 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
322 IFM_SUBTYPE_IEEE80211_ALIASES;
324 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
325 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
327 static struct ifmedia_description ifm_subtype_shared_descriptions[] =
328 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
330 static struct ifmedia_description ifm_subtype_shared_aliases[] =
331 IFM_SUBTYPE_SHARED_ALIASES;
333 static struct ifmedia_description ifm_shared_option_descriptions[] =
334 IFM_SHARED_OPTION_DESCRIPTIONS;
336 struct ifmedia_type_to_subtype {
338 struct ifmedia_description *desc;
342 struct ifmedia_description *desc;
347 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
348 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
351 { &ifm_subtype_shared_descriptions[0], 0 },
352 { &ifm_subtype_shared_aliases[0], 1 },
353 { &ifm_subtype_ethernet_descriptions[0], 0 },
354 { &ifm_subtype_ethernet_aliases[0], 1 },
358 { &ifm_shared_option_descriptions[0], 0 },
359 { &ifm_subtype_ethernet_option_descriptions[0], 0 },
365 { &ifm_subtype_shared_descriptions[0], 0 },
366 { &ifm_subtype_shared_aliases[0], 1 },
367 { &ifm_subtype_tokenring_descriptions[0], 0 },
368 { &ifm_subtype_tokenring_aliases[0], 1 },
372 { &ifm_shared_option_descriptions[0], 0 },
373 { &ifm_subtype_tokenring_option_descriptions[0], 0 },
379 { &ifm_subtype_shared_descriptions[0], 0 },
380 { &ifm_subtype_shared_aliases[0], 1 },
381 { &ifm_subtype_fddi_descriptions[0], 0 },
382 { &ifm_subtype_fddi_aliases[0], 1 },
386 { &ifm_shared_option_descriptions[0], 0 },
387 { &ifm_subtype_fddi_option_descriptions[0], 0 },
393 { &ifm_subtype_shared_descriptions[0], 0 },
394 { &ifm_subtype_shared_aliases[0], 1 },
395 { &ifm_subtype_ieee80211_descriptions[0], 0 },
396 { &ifm_subtype_ieee80211_aliases[0], 1 },
400 { &ifm_shared_option_descriptions[0], 0 },
401 { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
408 get_media_subtype(int type, const char *val)
410 struct ifmedia_description *desc;
411 struct ifmedia_type_to_subtype *ttos;
414 /* Find the top-level interface type. */
415 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
416 desc->ifmt_string != NULL; desc++, ttos++)
417 if (type == desc->ifmt_word)
419 if (desc->ifmt_string == NULL)
420 errx(1, "unknown media type 0x%x", type);
422 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
423 rval = lookup_media_word(ttos->subtypes[i].desc, val);
427 errx(1, "unknown media subtype: %s", val);
432 get_media_options(int type, const char *val)
434 struct ifmedia_description *desc;
435 struct ifmedia_type_to_subtype *ttos;
436 char *optlist, *optptr;
437 int option = 0, i, rval = 0;
439 /* We muck with the string, so copy it. */
440 optlist = strdup(val);
444 /* Find the top-level interface type. */
445 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
446 desc->ifmt_string != NULL; desc++, ttos++)
447 if (type == desc->ifmt_word)
449 if (desc->ifmt_string == NULL)
450 errx(1, "unknown media type 0x%x", type);
453 * Look up the options in the user-provided comma-separated
457 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
458 for (i = 0; ttos->options[i].desc != NULL; i++) {
459 option = lookup_media_word(ttos->options[i].desc, optptr);
464 errx(1, "unknown option: %s", optptr);
473 lookup_media_word(struct ifmedia_description *desc, const char *val)
476 for (; desc->ifmt_string != NULL; desc++)
477 if (strcasecmp(desc->ifmt_string, val) == 0)
478 return (desc->ifmt_word);
483 static struct ifmedia_description *get_toptype_desc(int ifmw)
485 struct ifmedia_description *desc;
487 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
488 if (IFM_TYPE(ifmw) == desc->ifmt_word)
494 static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
496 struct ifmedia_description *desc;
497 struct ifmedia_type_to_subtype *ttos;
499 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
500 desc->ifmt_string != NULL; desc++, ttos++)
501 if (IFM_TYPE(ifmw) == desc->ifmt_word)
507 static struct ifmedia_description *get_subtype_desc(int ifmw,
508 struct ifmedia_type_to_subtype *ttos)
511 struct ifmedia_description *desc;
513 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
514 if (ttos->subtypes[i].alias)
516 for (desc = ttos->subtypes[i].desc;
517 desc->ifmt_string != NULL; desc++) {
518 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
527 print_media_word(int ifmw, int print_toptype)
529 struct ifmedia_description *desc;
530 struct ifmedia_type_to_subtype *ttos;
531 int seen_option = 0, i;
533 /* Find the top-level interface type. */
534 desc = get_toptype_desc(ifmw);
535 ttos = get_toptype_ttos(ifmw);
536 if (desc->ifmt_string == NULL) {
537 printf("<unknown type>");
539 } else if (print_toptype) {
540 printf("%s", desc->ifmt_string);
544 * Don't print the top-level type; it's not like we can
545 * change it, or anything.
549 desc = get_subtype_desc(ifmw, ttos);
553 /* Falling to here means unknown subtype. */
554 printf("<unknown subtype>");
561 printf("%s", desc->ifmt_string);
564 for (i = 0; ttos->options[i].desc != NULL; i++) {
565 if (ttos->options[i].alias)
567 for (desc = ttos->options[i].desc;
568 desc->ifmt_string != NULL; desc++) {
569 if (ifmw & desc->ifmt_word) {
570 if (seen_option == 0)
572 printf("%s%s", seen_option++ ? "," : "",
577 printf("%s", seen_option ? ">" : "");
581 print_media_word_ifconfig(int ifmw)
583 struct ifmedia_description *desc;
584 struct ifmedia_type_to_subtype *ttos;
587 /* Find the top-level interface type. */
588 desc = get_toptype_desc(ifmw);
589 ttos = get_toptype_ttos(ifmw);
590 if (desc->ifmt_string == NULL) {
591 printf("<unknown type>");
596 * Don't print the top-level type; it's not like we can
597 * change it, or anything.
601 desc = get_subtype_desc(ifmw, ttos);
605 /* Falling to here means unknown subtype. */
606 printf("<unknown subtype>");
610 printf("media %s", desc->ifmt_string);
613 for (i = 0; ttos->options[i].desc != NULL; i++) {
614 if (ttos->options[i].alias)
616 for (desc = ttos->options[i].desc;
617 desc->ifmt_string != NULL; desc++) {
618 if (ifmw & desc->ifmt_word) {
619 printf(" mediaopt %s", desc->ifmt_string);
625 /**********************************************************************
627 **********************************************************************/