1 /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
2 /* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.19.2.1 2006/03/01 22:24:23 glebius Exp $ */
3 /* $DragonFly: src/sbin/ifconfig/ifmedia.c,v 1.13 2007/08/27 16:15:41 hasso Exp $ */
6 * Copyright (c) 1997 Jason R. Thorpe.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * Copyright (c) 1983, 1993
39 * The Regents of the University of California. All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Berkeley and its contributors.
53 * 4. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 #include <sys/param.h>
71 #include <sys/ioctl.h>
72 #include <sys/socket.h>
73 #include <sys/sysctl.h>
77 #include <net/if_dl.h>
78 #include <net/if_types.h>
79 #include <net/if_media.h>
80 #include <net/route.h>
93 static void domediaopt(const char *, int, int);
94 static int get_media_subtype(int, const char *);
95 static int get_media_mode(int, const char *);
96 static int get_media_options(int, const char *);
97 static int lookup_media_word(struct ifmedia_description
*, const char *);
98 static void print_media_word(int, int);
99 static void print_media_word_ifconfig(int);
101 static struct ifmedia_description
*get_toptype_desc(int);
102 static struct ifmedia_type_to_subtype
*get_toptype_ttos(int);
103 static struct ifmedia_description
*get_subtype_desc(int,
104 struct ifmedia_type_to_subtype
*ttos
);
109 struct ifmediareq ifmr
;
112 memset(&ifmr
, 0, sizeof(ifmr
));
113 strncpy(ifmr
.ifm_name
, name
, sizeof(ifmr
.ifm_name
));
115 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) < 0) {
117 * Interface doesn't support SIOC{G,S}IFMEDIA.
122 if (ifmr
.ifm_count
== 0) {
123 warnx("%s: no media types?", name
);
127 media_list
= malloc(ifmr
.ifm_count
* sizeof(int));
128 if (media_list
== NULL
)
130 ifmr
.ifm_ulist
= media_list
;
132 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) < 0)
133 err(1, "SIOCGIFMEDIA");
136 print_media_word(ifmr
.ifm_current
, 1);
137 if (ifmr
.ifm_active
!= ifmr
.ifm_current
) {
140 print_media_word(ifmr
.ifm_active
, 0);
146 if (ifmr
.ifm_status
& IFM_AVALID
) {
147 printf("\tstatus: ");
148 switch (IFM_TYPE(ifmr
.ifm_active
)) {
150 if (ifmr
.ifm_status
& IFM_ACTIVE
)
153 printf("no carrier");
157 if (ifmr
.ifm_status
& IFM_ACTIVE
)
160 printf("no carrier");
164 /* XXX: Different value for adhoc? */
165 if (ifmr
.ifm_status
& IFM_ACTIVE
)
166 printf("associated");
168 printf("no carrier");
171 if (ifmr
.ifm_status
& IFM_ACTIVE
)
180 if (ifmr
.ifm_count
> 0 && supmedia
) {
181 printf("\tsupported media:\n");
182 for (i
= 0; i
< ifmr
.ifm_count
; i
++) {
184 print_media_word_ifconfig(media_list
[i
]);
192 static struct ifmediareq
*
193 getifmediastate(int s
)
195 static struct ifmediareq
*ifmr
= NULL
;
199 ifmr
= (struct ifmediareq
*)malloc(sizeof(struct ifmediareq
));
203 (void) memset(ifmr
, 0, sizeof(struct ifmediareq
));
204 (void) strncpy(ifmr
->ifm_name
, name
,
205 sizeof(ifmr
->ifm_name
));
208 ifmr
->ifm_ulist
= NULL
;
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.
216 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)ifmr
) < 0) {
217 err(1, "SIOCGIFMEDIA");
220 if (ifmr
->ifm_count
== 0)
221 errx(1, "%s: no media types?", name
);
223 mwords
= (int *)malloc(ifmr
->ifm_count
* sizeof(int));
227 ifmr
->ifm_ulist
= mwords
;
228 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)ifmr
) < 0)
229 err(1, "SIOCGIFMEDIA");
236 setifmediacallback(int s
, void *arg
)
238 struct ifmediareq
*ifmr
= (struct ifmediareq
*)arg
;
239 static int did_it
= 0;
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
);
252 setmedia(const char *val
, int d
, int s
, const struct afswtch
*afp
)
254 struct ifmediareq
*ifmr
;
258 ifmr
= getifmediastate(s
);
261 * We are primarily concerned with the top-level type.
262 * However, "current" may be only IFM_NONE, so we just look
263 * for the top-level type in the first "supported type"
266 * (I'm assuming that all supported media types for a given
267 * interface will be the same top-level type..)
269 subtype
= get_media_subtype(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
271 strncpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
272 ifr
.ifr_media
= (ifmr
->ifm_current
& ~(IFM_NMASK
|IFM_TMASK
)) |
273 IFM_TYPE(ifmr
->ifm_ulist
[0]) | subtype
;
275 if ((ifr
.ifr_media
& IFM_TMASK
) == 0) {
276 ifr
.ifr_media
&= ~IFM_GMASK
;
279 ifmr
->ifm_current
= ifr
.ifr_media
;
280 callback_register(setifmediacallback
, (void *)ifmr
);
284 setmediaopt(const char *val
, int d
, int s
, const struct afswtch
*afp
)
287 domediaopt(val
, 0, s
);
291 unsetmediaopt(const char *val
, int d
, int s
, const struct afswtch
*afp
)
294 domediaopt(val
, 1, s
);
298 domediaopt(const char *val
, int clear
, int s
)
300 struct ifmediareq
*ifmr
;
303 ifmr
= getifmediastate(s
);
305 options
= get_media_options(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
307 strncpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
308 ifr
.ifr_media
= ifmr
->ifm_current
;
310 ifr
.ifr_media
&= ~options
;
312 ifr
.ifr_media
|= options
;
314 ifmr
->ifm_current
= ifr
.ifr_media
;
315 callback_register(setifmediacallback
, (void *)ifmr
);
320 setmediamode(const char *val
, int d
, int s
, const struct afswtch
*afp
)
322 struct ifmediareq
*ifmr
;
325 ifmr
= getifmediastate(s
);
327 mode
= get_media_mode(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
329 strncpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
330 ifr
.ifr_media
= (ifmr
->ifm_current
& ~IFM_MMASK
) | mode
;
332 ifmr
->ifm_current
= ifr
.ifr_media
;
333 callback_register(setifmediacallback
, (void *)ifmr
);
336 /**********************************************************************
337 * A good chunk of this is duplicated from sys/net/ifmedia.c
338 **********************************************************************/
340 static struct ifmedia_description ifm_type_descriptions
[] =
341 IFM_TYPE_DESCRIPTIONS
;
343 static struct ifmedia_description ifm_subtype_ethernet_descriptions
[] =
344 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS
;
346 static struct ifmedia_description ifm_subtype_ethernet_aliases
[] =
347 IFM_SUBTYPE_ETHERNET_ALIASES
;
349 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions
[] =
350 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS
;
352 static struct ifmedia_description ifm_subtype_ieee80211_descriptions
[] =
353 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS
;
355 static struct ifmedia_description ifm_subtype_ieee80211_aliases
[] =
356 IFM_SUBTYPE_IEEE80211_ALIASES
;
358 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions
[] =
359 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS
;
361 struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions
[] =
362 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS
;
364 struct ifmedia_description ifm_subtype_ieee80211_mode_aliases
[] =
365 IFM_SUBTYPE_IEEE80211_MODE_ALIASES
;
367 static struct ifmedia_description ifm_subtype_atm_descriptions
[] =
368 IFM_SUBTYPE_ATM_DESCRIPTIONS
;
370 static struct ifmedia_description ifm_subtype_atm_aliases
[] =
371 IFM_SUBTYPE_ATM_ALIASES
;
373 static struct ifmedia_description ifm_subtype_atm_option_descriptions
[] =
374 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS
;
376 static struct ifmedia_description ifm_subtype_shared_descriptions
[] =
377 IFM_SUBTYPE_SHARED_DESCRIPTIONS
;
379 static struct ifmedia_description ifm_subtype_shared_aliases
[] =
380 IFM_SUBTYPE_SHARED_ALIASES
;
382 static struct ifmedia_description ifm_shared_option_descriptions
[] =
383 IFM_SHARED_OPTION_DESCRIPTIONS
;
385 struct ifmedia_type_to_subtype
{
387 struct ifmedia_description
*desc
;
391 struct ifmedia_description
*desc
;
395 struct ifmedia_description
*desc
;
400 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
401 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes
[] = {
404 { &ifm_subtype_shared_descriptions
[0], 0 },
405 { &ifm_subtype_shared_aliases
[0], 1 },
406 { &ifm_subtype_ethernet_descriptions
[0], 0 },
407 { &ifm_subtype_ethernet_aliases
[0], 1 },
411 { &ifm_shared_option_descriptions
[0], 0 },
412 { &ifm_subtype_ethernet_option_descriptions
[0], 0 },
421 { &ifm_subtype_shared_descriptions
[0], 0 },
422 { &ifm_subtype_shared_aliases
[0], 1 },
423 { &ifm_subtype_ieee80211_descriptions
[0], 0 },
424 { &ifm_subtype_ieee80211_aliases
[0], 1 },
428 { &ifm_shared_option_descriptions
[0], 0 },
429 { &ifm_subtype_ieee80211_option_descriptions
[0], 0 },
433 { &ifm_subtype_ieee80211_mode_descriptions
[0], 0 },
434 { &ifm_subtype_ieee80211_mode_aliases
[0], 0 },
440 { &ifm_subtype_shared_descriptions
[0], 0 },
441 { &ifm_subtype_shared_aliases
[0], 1 },
442 { &ifm_subtype_atm_descriptions
[0], 0 },
443 { &ifm_subtype_atm_aliases
[0], 1 },
447 { &ifm_shared_option_descriptions
[0], 0 },
448 { &ifm_subtype_atm_option_descriptions
[0], 0 },
458 get_media_subtype(int type
, const char *val
)
460 struct ifmedia_description
*desc
;
461 struct ifmedia_type_to_subtype
*ttos
;
464 /* Find the top-level interface type. */
465 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
466 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
467 if (type
== desc
->ifmt_word
)
469 if (desc
->ifmt_string
== NULL
)
470 errx(1, "unknown media type 0x%x", type
);
472 for (i
= 0; ttos
->subtypes
[i
].desc
!= NULL
; i
++) {
473 rval
= lookup_media_word(ttos
->subtypes
[i
].desc
, val
);
477 errx(1, "unknown media subtype: %s", val
);
482 get_media_mode(int type
, const char *val
)
484 struct ifmedia_description
*desc
;
485 struct ifmedia_type_to_subtype
*ttos
;
488 /* Find the top-level interface type. */
489 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
490 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
491 if (type
== desc
->ifmt_word
)
493 if (desc
->ifmt_string
== NULL
)
494 errx(1, "unknown media mode 0x%x", type
);
496 for (i
= 0; ttos
->modes
[i
].desc
!= NULL
; i
++) {
497 rval
= lookup_media_word(ttos
->modes
[i
].desc
, val
);
505 get_media_options(int type
, const char *val
)
507 struct ifmedia_description
*desc
;
508 struct ifmedia_type_to_subtype
*ttos
;
509 char *optlist
, *optptr
;
510 int option
= 0, i
, rval
= 0;
512 /* We muck with the string, so copy it. */
513 optlist
= strdup(val
);
517 /* Find the top-level interface type. */
518 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
519 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
520 if (type
== desc
->ifmt_word
)
522 if (desc
->ifmt_string
== NULL
)
523 errx(1, "unknown media type 0x%x", type
);
526 * Look up the options in the user-provided comma-separated
530 for (; (optptr
= strtok(optptr
, ",")) != NULL
; optptr
= NULL
) {
531 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
532 option
= lookup_media_word(ttos
->options
[i
].desc
, optptr
);
537 errx(1, "unknown option: %s", optptr
);
546 lookup_media_word(struct ifmedia_description
*desc
, const char *val
)
549 for (; desc
->ifmt_string
!= NULL
; desc
++)
550 if (strcasecmp(desc
->ifmt_string
, val
) == 0)
551 return (desc
->ifmt_word
);
556 static struct ifmedia_description
*get_toptype_desc(int ifmw
)
558 struct ifmedia_description
*desc
;
560 for (desc
= ifm_type_descriptions
; desc
->ifmt_string
!= NULL
; desc
++)
561 if (IFM_TYPE(ifmw
) == desc
->ifmt_word
)
567 static struct ifmedia_type_to_subtype
*get_toptype_ttos(int ifmw
)
569 struct ifmedia_description
*desc
;
570 struct ifmedia_type_to_subtype
*ttos
;
572 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
573 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
574 if (IFM_TYPE(ifmw
) == desc
->ifmt_word
)
580 static struct ifmedia_description
*get_subtype_desc(int ifmw
,
581 struct ifmedia_type_to_subtype
*ttos
)
584 struct ifmedia_description
*desc
;
586 for (i
= 0; ttos
->subtypes
[i
].desc
!= NULL
; i
++) {
587 if (ttos
->subtypes
[i
].alias
)
589 for (desc
= ttos
->subtypes
[i
].desc
;
590 desc
->ifmt_string
!= NULL
; desc
++) {
591 if (IFM_SUBTYPE(ifmw
) == desc
->ifmt_word
)
599 static struct ifmedia_description
*get_mode_desc(int ifmw
,
600 struct ifmedia_type_to_subtype
*ttos
)
603 struct ifmedia_description
*desc
;
605 for (i
= 0; ttos
->modes
[i
].desc
!= NULL
; i
++) {
606 if (ttos
->modes
[i
].alias
)
608 for (desc
= ttos
->modes
[i
].desc
;
609 desc
->ifmt_string
!= NULL
; desc
++) {
610 if (IFM_MODE(ifmw
) == desc
->ifmt_word
)
619 print_media_word(int ifmw
, int print_toptype
)
621 struct ifmedia_description
*desc
;
622 struct ifmedia_type_to_subtype
*ttos
;
623 int seen_option
= 0, i
;
625 /* Find the top-level interface type. */
626 desc
= get_toptype_desc(ifmw
);
627 ttos
= get_toptype_ttos(ifmw
);
628 if (desc
->ifmt_string
== NULL
) {
629 printf("<unknown type>");
631 } else if (print_toptype
) {
632 printf("%s", desc
->ifmt_string
);
636 * Don't print the top-level type; it's not like we can
637 * change it, or anything.
641 desc
= get_subtype_desc(ifmw
, ttos
);
645 /* Falling to here means unknown subtype. */
646 printf("<unknown subtype>");
653 printf("%s", desc
->ifmt_string
);
656 desc
= get_mode_desc(ifmw
, ttos
);
657 if (desc
!= NULL
&& strcasecmp("autoselect", desc
->ifmt_string
))
658 printf(" mode %s", desc
->ifmt_string
);
662 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
663 if (ttos
->options
[i
].alias
)
665 for (desc
= ttos
->options
[i
].desc
;
666 desc
->ifmt_string
!= NULL
; desc
++) {
667 if (ifmw
& desc
->ifmt_word
) {
668 if (seen_option
== 0)
670 printf("%s%s", seen_option
++ ? "," : "",
675 printf("%s", seen_option
? ">" : "");
679 print_media_word_ifconfig(int ifmw
)
681 struct ifmedia_description
*desc
;
682 struct ifmedia_type_to_subtype
*ttos
;
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>");
694 * Don't print the top-level type; it's not like we can
695 * change it, or anything.
699 desc
= get_subtype_desc(ifmw
, ttos
);
703 /* Falling to here means unknown subtype. */
704 printf("<unknown subtype>");
708 printf("media %s", desc
->ifmt_string
);
710 desc
= get_mode_desc(ifmw
, ttos
);
712 printf(" mode %s", desc
->ifmt_string
);
715 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
716 if (ttos
->options
[i
].alias
)
718 for (desc
= ttos
->options
[i
].desc
;
719 desc
->ifmt_string
!= NULL
; desc
++) {
720 if (ifmw
& desc
->ifmt_word
) {
721 printf(" mediaopt %s", desc
->ifmt_string
);
727 /**********************************************************************
729 **********************************************************************/
731 static struct cmd media_cmds
[] = {
732 DEF_CMD_ARG("media", setmedia
),
733 DEF_CMD_ARG("mode", setmediamode
),
734 DEF_CMD_ARG("mediaopt", setmediaopt
),
735 DEF_CMD_ARG("-mediaopt",unsetmediaopt
),
737 static struct afswtch af_media
= {
738 .af_name
= "af_media",
740 .af_other_status
= media_status
,
743 static __constructor
void
746 #define N(a) (sizeof(a) / sizeof(a[0]))
749 for (i
= 0; i
< N(media_cmds
); i
++)
750 cmd_register(&media_cmds
[i
]);
751 af_register(&af_media
);