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 $ */
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. 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.
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
65 #include <sys/param.h>
66 #include <sys/ioctl.h>
67 #include <sys/socket.h>
68 #include <sys/sysctl.h>
72 #include <net/if_dl.h>
73 #include <net/if_types.h>
74 #include <net/if_media.h>
75 #include <net/route.h>
88 static void domediaopt(const char *, int, int);
89 static int get_media_subtype(int, const char *);
90 static int get_media_mode(int, const char *);
91 static int get_media_options(int, const char *);
92 static int lookup_media_word(struct ifmedia_description
*, const char *);
93 static void print_media_word(int, int);
94 static void print_media_word_ifconfig(int);
96 static struct ifmedia_description
*get_toptype_desc(int);
97 static struct ifmedia_type_to_subtype
*get_toptype_ttos(int);
98 static struct ifmedia_description
*get_subtype_desc(int,
99 struct ifmedia_type_to_subtype
*ttos
);
104 struct ifmediareq ifmr
;
107 memset(&ifmr
, 0, sizeof(ifmr
));
108 strlcpy(ifmr
.ifm_name
, name
, sizeof(ifmr
.ifm_name
));
110 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) < 0) {
112 * Interface doesn't support SIOC{G,S}IFMEDIA.
117 if (ifmr
.ifm_count
== 0) {
118 warnx("%s: no media types?", name
);
122 media_list
= malloc(ifmr
.ifm_count
* sizeof(int));
123 if (media_list
== NULL
)
125 ifmr
.ifm_ulist
= media_list
;
127 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) < 0)
128 err(1, "SIOCGIFMEDIA");
131 print_media_word(ifmr
.ifm_current
, 1);
132 if (ifmr
.ifm_active
!= ifmr
.ifm_current
) {
135 print_media_word(ifmr
.ifm_active
, 0);
141 if (ifmr
.ifm_status
& IFM_AVALID
) {
142 printf("\tstatus: ");
143 switch (IFM_TYPE(ifmr
.ifm_active
)) {
145 if (ifmr
.ifm_status
& IFM_ACTIVE
)
148 printf("no carrier");
152 if (ifmr
.ifm_status
& IFM_ACTIVE
)
155 printf("no carrier");
159 /* XXX: Different value for adhoc? */
160 if (ifmr
.ifm_status
& IFM_ACTIVE
)
161 printf("associated");
163 printf("no carrier");
166 if (ifmr
.ifm_status
& IFM_ACTIVE
)
175 if (ifmr
.ifm_count
> 0 && supmedia
) {
176 printf("\tsupported media:\n");
177 for (i
= 0; i
< ifmr
.ifm_count
; i
++) {
179 print_media_word_ifconfig(media_list
[i
]);
188 ifmedia_getstate(int s
)
190 static struct ifmediareq
*ifmr
= NULL
;
194 ifmr
= (struct ifmediareq
*)malloc(sizeof(struct ifmediareq
));
198 memset(ifmr
, 0, sizeof(struct ifmediareq
));
199 strlcpy(ifmr
->ifm_name
, name
, sizeof(ifmr
->ifm_name
));
202 ifmr
->ifm_ulist
= NULL
;
205 * We must go through the motions of reading all
206 * supported media because we need to know both
207 * the current media type and the top-level type.
210 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)ifmr
) < 0) {
211 err(1, "SIOCGIFMEDIA");
214 if (ifmr
->ifm_count
== 0)
215 errx(1, "%s: no media types?", name
);
217 mwords
= (int *)malloc(ifmr
->ifm_count
* sizeof(int));
221 ifmr
->ifm_ulist
= mwords
;
222 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)ifmr
) < 0)
223 err(1, "SIOCGIFMEDIA");
230 setifmediacallback(int s
, void *arg
)
232 struct ifmediareq
*ifmr
= (struct ifmediareq
*)arg
;
233 static int did_it
= 0;
236 ifr
.ifr_media
= ifmr
->ifm_current
;
237 if (ioctl(s
, SIOCSIFMEDIA
, (caddr_t
)&ifr
) < 0)
238 err(1, "SIOCSIFMEDIA (media)");
239 free(ifmr
->ifm_ulist
);
246 setmedia(const char *val
, int d
, int s
, const struct afswtch
*afp
)
248 struct ifmediareq
*ifmr
;
251 ifmr
= ifmedia_getstate(s
);
254 * We are primarily concerned with the top-level type.
255 * However, "current" may be only IFM_NONE, so we just look
256 * for the top-level type in the first "supported type"
259 * (I'm assuming that all supported media types for a given
260 * interface will be the same top-level type..)
262 subtype
= get_media_subtype(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
264 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
265 ifr
.ifr_media
= (ifmr
->ifm_current
& ~(IFM_NMASK
|IFM_TMASK
)) |
266 IFM_TYPE(ifmr
->ifm_ulist
[0]) | subtype
;
268 if ((ifr
.ifr_media
& IFM_TMASK
) == 0) {
269 ifr
.ifr_media
&= ~IFM_GMASK
;
272 ifmr
->ifm_current
= ifr
.ifr_media
;
273 callback_register(setifmediacallback
, (void *)ifmr
);
277 setmediaopt(const char *val
, int d
, int s
, const struct afswtch
*afp
)
280 domediaopt(val
, 0, s
);
284 unsetmediaopt(const char *val
, int d
, int s
, const struct afswtch
*afp
)
287 domediaopt(val
, 1, s
);
291 domediaopt(const char *val
, int clear
, int s
)
293 struct ifmediareq
*ifmr
;
296 ifmr
= ifmedia_getstate(s
);
298 options
= get_media_options(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
300 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
301 ifr
.ifr_media
= ifmr
->ifm_current
;
303 ifr
.ifr_media
&= ~options
;
305 ifr
.ifr_media
|= options
;
307 ifmr
->ifm_current
= ifr
.ifr_media
;
308 callback_register(setifmediacallback
, (void *)ifmr
);
313 setmediamode(const char *val
, int d
, int s
, const struct afswtch
*afp
)
315 struct ifmediareq
*ifmr
;
318 ifmr
= ifmedia_getstate(s
);
320 mode
= get_media_mode(IFM_TYPE(ifmr
->ifm_ulist
[0]), val
);
322 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
323 ifr
.ifr_media
= (ifmr
->ifm_current
& ~IFM_MMASK
) | mode
;
325 ifmr
->ifm_current
= ifr
.ifr_media
;
326 callback_register(setifmediacallback
, (void *)ifmr
);
329 /**********************************************************************
330 * A good chunk of this is duplicated from sys/net/ifmedia.c
331 **********************************************************************/
333 static struct ifmedia_description ifm_type_descriptions
[] =
334 IFM_TYPE_DESCRIPTIONS
;
336 static struct ifmedia_description ifm_subtype_ethernet_descriptions
[] =
337 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS
;
339 static struct ifmedia_description ifm_subtype_ethernet_aliases
[] =
340 IFM_SUBTYPE_ETHERNET_ALIASES
;
342 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions
[] =
343 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS
;
345 static struct ifmedia_description ifm_subtype_ethernet_option_alias
[] =
346 IFM_SUBTYPE_ETHERNET_OPTION_ALIAS
;
348 static struct ifmedia_description ifm_subtype_ieee80211_descriptions
[] =
349 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS
;
351 static struct ifmedia_description ifm_subtype_ieee80211_aliases
[] =
352 IFM_SUBTYPE_IEEE80211_ALIASES
;
354 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions
[] =
355 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS
;
357 struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions
[] =
358 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS
;
360 struct ifmedia_description ifm_subtype_ieee80211_mode_aliases
[] =
361 IFM_SUBTYPE_IEEE80211_MODE_ALIASES
;
363 static struct ifmedia_description ifm_subtype_atm_descriptions
[] =
364 IFM_SUBTYPE_ATM_DESCRIPTIONS
;
366 static struct ifmedia_description ifm_subtype_atm_aliases
[] =
367 IFM_SUBTYPE_ATM_ALIASES
;
369 static struct ifmedia_description ifm_subtype_atm_option_descriptions
[] =
370 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS
;
372 static struct ifmedia_description ifm_subtype_shared_descriptions
[] =
373 IFM_SUBTYPE_SHARED_DESCRIPTIONS
;
375 static struct ifmedia_description ifm_subtype_shared_aliases
[] =
376 IFM_SUBTYPE_SHARED_ALIASES
;
378 static struct ifmedia_description ifm_shared_option_descriptions
[] =
379 IFM_SHARED_OPTION_DESCRIPTIONS
;
381 struct ifmedia_type_to_subtype
{
383 struct ifmedia_description
*desc
;
387 struct ifmedia_description
*desc
;
391 struct ifmedia_description
*desc
;
396 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
397 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes
[] = {
400 { &ifm_subtype_shared_descriptions
[0], 0 },
401 { &ifm_subtype_shared_aliases
[0], 1 },
402 { &ifm_subtype_ethernet_descriptions
[0], 0 },
403 { &ifm_subtype_ethernet_aliases
[0], 1 },
407 { &ifm_shared_option_descriptions
[0], 0 },
408 { &ifm_subtype_ethernet_option_descriptions
[0], 0 },
409 { &ifm_subtype_ethernet_option_alias
[0], 1 },
418 { &ifm_subtype_shared_descriptions
[0], 0 },
419 { &ifm_subtype_shared_aliases
[0], 1 },
420 { &ifm_subtype_ieee80211_descriptions
[0], 0 },
421 { &ifm_subtype_ieee80211_aliases
[0], 1 },
425 { &ifm_shared_option_descriptions
[0], 0 },
426 { &ifm_subtype_ieee80211_option_descriptions
[0], 0 },
430 { &ifm_subtype_ieee80211_mode_descriptions
[0], 0 },
431 { &ifm_subtype_ieee80211_mode_aliases
[0], 0 },
437 { &ifm_subtype_shared_descriptions
[0], 0 },
438 { &ifm_subtype_shared_aliases
[0], 1 },
439 { &ifm_subtype_atm_descriptions
[0], 0 },
440 { &ifm_subtype_atm_aliases
[0], 1 },
444 { &ifm_shared_option_descriptions
[0], 0 },
445 { &ifm_subtype_atm_option_descriptions
[0], 0 },
455 get_media_subtype(int type
, const char *val
)
457 struct ifmedia_description
*desc
;
458 struct ifmedia_type_to_subtype
*ttos
;
461 /* Find the top-level interface type. */
462 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
463 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
464 if (type
== desc
->ifmt_word
)
466 if (desc
->ifmt_string
== NULL
)
467 errx(1, "unknown media type 0x%x", type
);
469 for (i
= 0; ttos
->subtypes
[i
].desc
!= NULL
; i
++) {
470 rval
= lookup_media_word(ttos
->subtypes
[i
].desc
, val
);
474 errx(1, "unknown media subtype: %s", val
);
479 get_media_mode(int type
, const char *val
)
481 struct ifmedia_description
*desc
;
482 struct ifmedia_type_to_subtype
*ttos
;
485 /* Find the top-level interface type. */
486 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
487 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
488 if (type
== desc
->ifmt_word
)
490 if (desc
->ifmt_string
== NULL
)
491 errx(1, "unknown media mode 0x%x", type
);
493 for (i
= 0; ttos
->modes
[i
].desc
!= NULL
; i
++) {
494 rval
= lookup_media_word(ttos
->modes
[i
].desc
, val
);
502 get_media_options(int type
, const char *val
)
504 struct ifmedia_description
*desc
;
505 struct ifmedia_type_to_subtype
*ttos
;
506 char *optlist
, *optptr
;
507 int option
= 0, i
, rval
= 0;
509 /* We muck with the string, so copy it. */
510 optlist
= strdup(val
);
514 /* Find the top-level interface type. */
515 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
516 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
517 if (type
== desc
->ifmt_word
)
519 if (desc
->ifmt_string
== NULL
)
520 errx(1, "unknown media type 0x%x", type
);
523 * Look up the options in the user-provided comma-separated
527 for (; (optptr
= strtok(optptr
, ",")) != NULL
; optptr
= NULL
) {
528 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
529 option
= lookup_media_word(ttos
->options
[i
].desc
, optptr
);
534 errx(1, "unknown option: %s", optptr
);
543 lookup_media_word(struct ifmedia_description
*desc
, const char *val
)
546 for (; desc
->ifmt_string
!= NULL
; desc
++)
547 if (strcasecmp(desc
->ifmt_string
, val
) == 0)
548 return (desc
->ifmt_word
);
553 static struct ifmedia_description
*get_toptype_desc(int ifmw
)
555 struct ifmedia_description
*desc
;
557 for (desc
= ifm_type_descriptions
; desc
->ifmt_string
!= NULL
; desc
++)
558 if (IFM_TYPE(ifmw
) == desc
->ifmt_word
)
564 static struct ifmedia_type_to_subtype
*get_toptype_ttos(int ifmw
)
566 struct ifmedia_description
*desc
;
567 struct ifmedia_type_to_subtype
*ttos
;
569 for (desc
= ifm_type_descriptions
, ttos
= ifmedia_types_to_subtypes
;
570 desc
->ifmt_string
!= NULL
; desc
++, ttos
++)
571 if (IFM_TYPE(ifmw
) == desc
->ifmt_word
)
577 static struct ifmedia_description
*get_subtype_desc(int ifmw
,
578 struct ifmedia_type_to_subtype
*ttos
)
581 struct ifmedia_description
*desc
;
583 for (i
= 0; ttos
->subtypes
[i
].desc
!= NULL
; i
++) {
584 if (ttos
->subtypes
[i
].alias
)
586 for (desc
= ttos
->subtypes
[i
].desc
;
587 desc
->ifmt_string
!= NULL
; desc
++) {
588 if (IFM_SUBTYPE(ifmw
) == desc
->ifmt_word
)
596 static struct ifmedia_description
*get_mode_desc(int ifmw
,
597 struct ifmedia_type_to_subtype
*ttos
)
600 struct ifmedia_description
*desc
;
602 for (i
= 0; ttos
->modes
[i
].desc
!= NULL
; i
++) {
603 if (ttos
->modes
[i
].alias
)
605 for (desc
= ttos
->modes
[i
].desc
;
606 desc
->ifmt_string
!= NULL
; desc
++) {
607 if (IFM_MODE(ifmw
) == desc
->ifmt_word
)
616 print_media_word(int ifmw
, int print_toptype
)
618 struct ifmedia_description
*desc
;
619 struct ifmedia_type_to_subtype
*ttos
;
620 int seen_option
= 0, i
;
622 /* Find the top-level interface type. */
623 desc
= get_toptype_desc(ifmw
);
624 ttos
= get_toptype_ttos(ifmw
);
625 if (desc
->ifmt_string
== NULL
) {
626 printf("<unknown type>");
628 } else if (print_toptype
) {
629 printf("%s", desc
->ifmt_string
);
633 * Don't print the top-level type; it's not like we can
634 * change it, or anything.
638 desc
= get_subtype_desc(ifmw
, ttos
);
642 /* Falling to here means unknown subtype. */
643 printf("<unknown subtype>");
650 printf("%s", desc
->ifmt_string
);
653 desc
= get_mode_desc(ifmw
, ttos
);
654 if (desc
!= NULL
&& strcasecmp("autoselect", desc
->ifmt_string
))
655 printf(" mode %s", desc
->ifmt_string
);
659 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
660 if (ttos
->options
[i
].alias
)
662 for (desc
= ttos
->options
[i
].desc
;
663 desc
->ifmt_string
!= NULL
; desc
++) {
664 if (ifmw
& desc
->ifmt_word
) {
665 if (seen_option
== 0)
667 printf("%s%s", seen_option
++ ? "," : "",
672 printf("%s", seen_option
? ">" : "");
676 print_media_word_ifconfig(int ifmw
)
678 struct ifmedia_description
*desc
;
679 struct ifmedia_type_to_subtype
*ttos
;
682 /* Find the top-level interface type. */
683 desc
= get_toptype_desc(ifmw
);
684 ttos
= get_toptype_ttos(ifmw
);
685 if (desc
->ifmt_string
== NULL
) {
686 printf("<unknown type>");
691 * Don't print the top-level type; it's not like we can
692 * change it, or anything.
696 desc
= get_subtype_desc(ifmw
, ttos
);
700 /* Falling to here means unknown subtype. */
701 printf("<unknown subtype>");
705 printf("media %s", desc
->ifmt_string
);
707 desc
= get_mode_desc(ifmw
, ttos
);
709 printf(" mode %s", desc
->ifmt_string
);
712 for (i
= 0; ttos
->options
[i
].desc
!= NULL
; i
++) {
713 if (ttos
->options
[i
].alias
)
715 for (desc
= ttos
->options
[i
].desc
;
716 desc
->ifmt_string
!= NULL
; desc
++) {
717 if (ifmw
& desc
->ifmt_word
) {
718 printf(" mediaopt %s", desc
->ifmt_string
);
724 /**********************************************************************
726 **********************************************************************/
728 static struct cmd media_cmds
[] = {
729 DEF_CMD_ARG("media", setmedia
),
730 DEF_CMD_ARG("mode", setmediamode
),
731 DEF_CMD_ARG("mediaopt", setmediaopt
),
732 DEF_CMD_ARG("-mediaopt",unsetmediaopt
),
734 static struct afswtch af_media
= {
735 .af_name
= "af_media",
737 .af_other_status
= media_status
,
740 static __constructor(101) void
745 for (i
= 0; i
< nitems(media_cmds
); i
++)
746 cmd_register(&media_cmds
[i
]);
747 af_register(&af_media
);