ifmedia.c revision 166169
125450Speter/*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 166169 2007-01-22 13:42:07Z marius $ */
325450Speter
425450Speter/*
525450Speter * Copyright (c) 1997 Jason R. Thorpe.
625450Speter * All rights reserved.
725450Speter *
825450Speter * Redistribution and use in source and binary forms, with or without
925450Speter * modification, are permitted provided that the following conditions
1025450Speter * are met:
1125450Speter * 1. Redistributions of source code must retain the above copyright
1225450Speter *    notice, this list of conditions and the following disclaimer.
1325450Speter * 2. Redistributions in binary form must reproduce the above copyright
1425450Speter *    notice, this list of conditions and the following disclaimer in the
1525450Speter *    documentation and/or other materials provided with the distribution.
1625450Speter * 3. All advertising materials mentioning features or use of this software
1725450Speter *    must display the following acknowledgement:
1825450Speter *      This product includes software developed for the NetBSD Project
1925450Speter *	by Jason R. Thorpe.
2025450Speter * 4. The name of the author may not be used to endorse or promote products
2125450Speter *    derived from this software without specific prior written permission.
2225450Speter *
2325450Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2425450Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2525450Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2625450Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2725450Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2825450Speter * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2925450Speter * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
3025450Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3125450Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3225450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3325450Speter * SUCH DAMAGE.
3425450Speter */
3525450Speter
3625450Speter/*
3725450Speter * Copyright (c) 1983, 1993
3825450Speter *	The Regents of the University of California.  All rights reserved.
3925450Speter *
4025450Speter * Redistribution and use in source and binary forms, with or without
4125450Speter * modification, are permitted provided that the following conditions
4225450Speter * are met:
4325450Speter * 1. Redistributions of source code must retain the above copyright
4425450Speter *    notice, this list of conditions and the following disclaimer.
4525450Speter * 2. Redistributions in binary form must reproduce the above copyright
4625450Speter *    notice, this list of conditions and the following disclaimer in the
4725450Speter *    documentation and/or other materials provided with the distribution.
4825450Speter * 3. All advertising materials mentioning features or use of this software
4925450Speter *    must display the following acknowledgement:
5025450Speter *	This product includes software developed by the University of
5125450Speter *	California, Berkeley and its contributors.
5225450Speter * 4. Neither the name of the University nor the names of its contributors
5325450Speter *    may be used to endorse or promote products derived from this software
5425450Speter *    without specific prior written permission.
5525450Speter *
5625450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5725450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5825450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5925450Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6025450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6125450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6225450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6325450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6425450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6525450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6625450Speter * SUCH DAMAGE.
6725450Speter */
6825450Speter
6925450Speter#include <sys/param.h>
7025450Speter#include <sys/ioctl.h>
7125450Speter#include <sys/socket.h>
7225450Speter#include <sys/sysctl.h>
7325450Speter#include <sys/time.h>
7425450Speter
7525450Speter#include <net/if.h>
7625450Speter#include <net/if_dl.h>
7725450Speter#include <net/if_types.h>
7825450Speter#include <net/if_media.h>
7925450Speter#include <net/route.h>
8025450Speter
8125450Speter#include <ctype.h>
8225450Speter#include <err.h>
8325450Speter#include <errno.h>
8425450Speter#include <fcntl.h>
8525450Speter#include <stdio.h>
8625450Speter#include <stdlib.h>
8725450Speter#include <string.h>
8825450Speter#include <unistd.h>
8925450Speter
9025450Speter#include "ifconfig.h"
9125450Speter
9295005Simpstatic void	domediaopt(const char *, int, int);
9395005Simpstatic int	get_media_subtype(int, const char *);
94114164Ssamstatic int	get_media_mode(int, const char *);
9595005Simpstatic int	get_media_options(int, const char *);
9695005Simpstatic int	lookup_media_word(struct ifmedia_description *, const char *);
9795005Simpstatic void	print_media_word(int, int);
9895005Simpstatic void	print_media_word_ifconfig(int);
9925450Speter
10095005Simpstatic struct ifmedia_description *get_toptype_desc(int);
10195005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int);
10295005Simpstatic struct ifmedia_description *get_subtype_desc(int,
10395005Simp    struct ifmedia_type_to_subtype *ttos);
10477385Sphk
105138593Ssamstatic void
106139494Ssammedia_status(int s)
10725450Speter{
10825450Speter	struct ifmediareq ifmr;
10925450Speter	int *media_list, i;
11025450Speter
11125450Speter	(void) memset(&ifmr, 0, sizeof(ifmr));
11225450Speter	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
11325450Speter
11425450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
11525450Speter		/*
11625450Speter		 * Interface doesn't support SIOC{G,S}IFMEDIA.
11725450Speter		 */
11825450Speter		return;
11925450Speter	}
12025450Speter
12125450Speter	if (ifmr.ifm_count == 0) {
12225450Speter		warnx("%s: no media types?", name);
12325450Speter		return;
12425450Speter	}
12525450Speter
12625450Speter	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
12725450Speter	if (media_list == NULL)
12825450Speter		err(1, "malloc");
12925450Speter	ifmr.ifm_ulist = media_list;
13025450Speter
13125450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
13225450Speter		err(1, "SIOCGIFMEDIA");
13325450Speter
13425450Speter	printf("\tmedia: ");
13577385Sphk	print_media_word(ifmr.ifm_current, 1);
13625450Speter	if (ifmr.ifm_active != ifmr.ifm_current) {
13725450Speter		putchar(' ');
13825450Speter		putchar('(');
13977385Sphk		print_media_word(ifmr.ifm_active, 0);
14025450Speter		putchar(')');
14125450Speter	}
14225450Speter
14377385Sphk	putchar('\n');
14477385Sphk
14525450Speter	if (ifmr.ifm_status & IFM_AVALID) {
14677385Sphk		printf("\tstatus: ");
14725450Speter		switch (IFM_TYPE(ifmr.ifm_active)) {
14825450Speter		case IFM_ETHER:
149161536Sthomas		case IFM_ATM:
15025450Speter			if (ifmr.ifm_status & IFM_ACTIVE)
15125450Speter				printf("active");
15225450Speter			else
15325450Speter				printf("no carrier");
15425450Speter			break;
15525450Speter
15625450Speter		case IFM_FDDI:
15725450Speter		case IFM_TOKEN:
15825450Speter			if (ifmr.ifm_status & IFM_ACTIVE)
15925450Speter				printf("inserted");
16025450Speter			else
16125450Speter				printf("no ring");
16225450Speter			break;
163114232Sharti
16477217Sphk		case IFM_IEEE80211:
16577217Sphk			/* XXX: Different value for adhoc? */
16677217Sphk			if (ifmr.ifm_status & IFM_ACTIVE)
16777217Sphk				printf("associated");
16877217Sphk			else
16977217Sphk				printf("no carrier");
17077217Sphk			break;
17125450Speter		}
17285853Syar		putchar('\n');
17325450Speter	}
17425450Speter
17577385Sphk	if (ifmr.ifm_count > 0 && supmedia) {
17677385Sphk		printf("\tsupported media:\n");
17725450Speter		for (i = 0; i < ifmr.ifm_count; i++) {
17877385Sphk			printf("\t\t");
17977385Sphk			print_media_word_ifconfig(media_list[i]);
18077385Sphk			putchar('\n');
18125450Speter		}
18225450Speter	}
18325450Speter
18425450Speter	free(media_list);
18525450Speter}
18625450Speter
187140913Sambriskostatic struct ifmediareq *
188140913Sambriskogetifmediastate(int s)
18925450Speter{
190140913Sambrisko	static struct ifmediareq *ifmr = NULL;
191140913Sambrisko	int *mwords;
19225450Speter
193140913Sambrisko	if (ifmr == NULL) {
194140913Sambrisko		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
195140913Sambrisko		if (ifmr == NULL)
196140913Sambrisko			err(1, "malloc");
19725450Speter
198140913Sambrisko		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
199140913Sambrisko		(void) strncpy(ifmr->ifm_name, name,
200140913Sambrisko		    sizeof(ifmr->ifm_name));
201140913Sambrisko
202140913Sambrisko		ifmr->ifm_count = 0;
203140913Sambrisko		ifmr->ifm_ulist = NULL;
204140913Sambrisko
20525450Speter		/*
206140913Sambrisko		 * We must go through the motions of reading all
207140913Sambrisko		 * supported media because we need to know both
208140913Sambrisko		 * the current media type and the top-level type.
20925450Speter		 */
210140913Sambrisko
211140913Sambrisko		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
21225450Speter			err(1, "SIOCGIFMEDIA");
213140913Sambrisko		}
214140913Sambrisko
215140913Sambrisko		if (ifmr->ifm_count == 0)
216140913Sambrisko			errx(1, "%s: no media types?", name);
217140913Sambrisko
218140913Sambrisko		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
219140913Sambrisko		if (mwords == NULL)
220140913Sambrisko			err(1, "malloc");
221140913Sambrisko
222140913Sambrisko		ifmr->ifm_ulist = mwords;
223140913Sambrisko		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
224140913Sambrisko			err(1, "SIOCGIFMEDIA");
22525450Speter	}
22625450Speter
227140913Sambrisko	return ifmr;
228140913Sambrisko}
22925450Speter
230140913Sambriskostatic void
231140913Sambriskosetifmediacallback(int s, void *arg)
232140913Sambrisko{
233140913Sambrisko	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
234140913Sambrisko	static int did_it = 0;
235140913Sambrisko
236140913Sambrisko	if (!did_it) {
237154240Sambrisko		ifr.ifr_media = ifmr->ifm_current;
238140913Sambrisko		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
239140913Sambrisko			err(1, "SIOCSIFMEDIA (media)");
240140913Sambrisko		free(ifmr->ifm_ulist);
241140913Sambrisko		free(ifmr);
242140913Sambrisko		did_it = 1;
243140913Sambrisko	}
244140913Sambrisko}
245140913Sambrisko
246140913Sambriskostatic void
247140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp)
248140913Sambrisko{
249140913Sambrisko	struct ifmediareq *ifmr;
250140913Sambrisko	int subtype;
251140913Sambrisko
252140913Sambrisko	ifmr = getifmediastate(s);
253140913Sambrisko
25425450Speter	/*
25525450Speter	 * We are primarily concerned with the top-level type.
25625450Speter	 * However, "current" may be only IFM_NONE, so we just look
25725450Speter	 * for the top-level type in the first "supported type"
25825450Speter	 * entry.
25925450Speter	 *
26025450Speter	 * (I'm assuming that all supported media types for a given
26125450Speter	 * interface will be the same top-level type..)
26225450Speter	 */
263140913Sambrisko	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
26425450Speter
26525450Speter	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
266140913Sambrisko	ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
267140913Sambrisko	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
26825450Speter
269140913Sambrisko	if ((ifr.ifr_media & IFM_TMASK) == 0) {
270140913Sambrisko		ifr.ifr_media &= ~IFM_GMASK;
271140913Sambrisko	}
272140913Sambrisko
273140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
274140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
27525450Speter}
27625450Speter
277138593Ssamstatic void
27895005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
27925450Speter{
28025450Speter
28125450Speter	domediaopt(val, 0, s);
28225450Speter}
28325450Speter
284138593Ssamstatic void
28595005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
28625450Speter{
28725450Speter
28825450Speter	domediaopt(val, 1, s);
28925450Speter}
29025450Speter
29125450Speterstatic void
29295005Simpdomediaopt(const char *val, int clear, int s)
29325450Speter{
294140913Sambrisko	struct ifmediareq *ifmr;
295140913Sambrisko	int options;
29625450Speter
297140913Sambrisko	ifmr = getifmediastate(s);
29825450Speter
299140913Sambrisko	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
30025450Speter
30125450Speter	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
302140913Sambrisko	ifr.ifr_media = ifmr->ifm_current;
30325450Speter	if (clear)
30425450Speter		ifr.ifr_media &= ~options;
305165359Sjkim	else {
306165359Sjkim		if (options & IFM_HDX) {
307165359Sjkim			ifr.ifr_media &= ~IFM_FDX;
308165359Sjkim			options &= ~IFM_HDX;
309165359Sjkim		}
31025450Speter		ifr.ifr_media |= options;
311165359Sjkim	}
312140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
313140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
31425450Speter}
31525450Speter
316166113Smariusstatic void
317166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp)
318166113Smarius{
319166113Smarius	struct ifmediareq *ifmr;
320166113Smarius	int inst;
321114164Ssam
322166113Smarius	ifmr = getifmediastate(s);
323166113Smarius
324166113Smarius	inst = atoi(val);
325166113Smarius	if (inst < 0 || inst > IFM_INST_MAX)
326166113Smarius		errx(1, "invalid media instance: %s", val);
327166113Smarius
328166113Smarius	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
329166113Smarius	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
330166113Smarius
331166113Smarius	ifmr->ifm_current = ifr.ifr_media;
332166113Smarius	callback_register(setifmediacallback, (void *)ifmr);
333166113Smarius}
334166113Smarius
335138593Ssamstatic void
336114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp)
337114164Ssam{
338140913Sambrisko	struct ifmediareq *ifmr;
339140913Sambrisko	int mode;
340114164Ssam
341140913Sambrisko	ifmr = getifmediastate(s);
342114164Ssam
343140913Sambrisko	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
344114164Ssam
345114164Ssam	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
346140913Sambrisko	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
347114164Ssam
348140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
349140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
350114164Ssam}
351114164Ssam
35225450Speter/**********************************************************************
35325450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c
35425450Speter **********************************************************************/
35525450Speter
35625450Speterstatic struct ifmedia_description ifm_type_descriptions[] =
35725450Speter    IFM_TYPE_DESCRIPTIONS;
35825450Speter
35925450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
36025450Speter    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
36125450Speter
36225450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] =
36325450Speter    IFM_SUBTYPE_ETHERNET_ALIASES;
36425450Speter
36525450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
36625450Speter    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
36725450Speter
36825450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
36925450Speter    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
37025450Speter
37125450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] =
37225450Speter    IFM_SUBTYPE_TOKENRING_ALIASES;
37325450Speter
37425450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
37525450Speter    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
37625450Speter
37725450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] =
37825450Speter    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
37925450Speter
38025450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] =
38125450Speter    IFM_SUBTYPE_FDDI_ALIASES;
38225450Speter
38325450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
38425450Speter    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
38525450Speter
38677217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
38777217Sphk    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
38877217Sphk
38977217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
39077217Sphk    IFM_SUBTYPE_IEEE80211_ALIASES;
39177217Sphk
39277217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
39377217Sphk    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
39477217Sphk
395114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
396114164Ssam    IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
397114164Ssam
398116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
399116820Ssam    IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
400116820Ssam
401114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] =
402114232Sharti    IFM_SUBTYPE_ATM_DESCRIPTIONS;
403114232Sharti
404114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] =
405114232Sharti    IFM_SUBTYPE_ATM_ALIASES;
406114232Sharti
407114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
408114232Sharti    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
409114232Sharti
41025450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] =
41125450Speter    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
41225450Speter
41325450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] =
41425450Speter    IFM_SUBTYPE_SHARED_ALIASES;
41525450Speter
41625450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] =
41725450Speter    IFM_SHARED_OPTION_DESCRIPTIONS;
41825450Speter
41925450Speterstruct ifmedia_type_to_subtype {
42025450Speter	struct {
42125450Speter		struct ifmedia_description *desc;
42225450Speter		int alias;
42325450Speter	} subtypes[5];
42425450Speter	struct {
42525450Speter		struct ifmedia_description *desc;
42625450Speter		int alias;
42725450Speter	} options[3];
428114164Ssam	struct {
429114164Ssam		struct ifmedia_description *desc;
430114164Ssam		int alias;
431116820Ssam	} modes[3];
43225450Speter};
43325450Speter
43425450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
43525450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
43625450Speter	{
43725450Speter		{
43825450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
43925450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
44025450Speter			{ &ifm_subtype_ethernet_descriptions[0], 0 },
44125450Speter			{ &ifm_subtype_ethernet_aliases[0], 1 },
44225450Speter			{ NULL, 0 },
44325450Speter		},
44425450Speter		{
44525450Speter			{ &ifm_shared_option_descriptions[0], 0 },
44677217Sphk			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
44725450Speter			{ NULL, 0 },
44825450Speter		},
449114164Ssam		{
450114164Ssam			{ NULL, 0 },
451114164Ssam		},
45225450Speter	},
45325450Speter	{
45425450Speter		{
45525450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
45625450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
45725450Speter			{ &ifm_subtype_tokenring_descriptions[0], 0 },
45825450Speter			{ &ifm_subtype_tokenring_aliases[0], 1 },
45925450Speter			{ NULL, 0 },
46025450Speter		},
46125450Speter		{
46225450Speter			{ &ifm_shared_option_descriptions[0], 0 },
46377217Sphk			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
46425450Speter			{ NULL, 0 },
46525450Speter		},
466114164Ssam		{
467114164Ssam			{ NULL, 0 },
468114164Ssam		},
46925450Speter	},
47025450Speter	{
47125450Speter		{
47225450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
47325450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
47425450Speter			{ &ifm_subtype_fddi_descriptions[0], 0 },
47525450Speter			{ &ifm_subtype_fddi_aliases[0], 1 },
47625450Speter			{ NULL, 0 },
47725450Speter		},
47825450Speter		{
47925450Speter			{ &ifm_shared_option_descriptions[0], 0 },
48077217Sphk			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
48125450Speter			{ NULL, 0 },
48225450Speter		},
483114164Ssam		{
484114164Ssam			{ NULL, 0 },
485114164Ssam		},
48625450Speter	},
48777217Sphk	{
48877217Sphk		{
48977217Sphk			{ &ifm_subtype_shared_descriptions[0], 0 },
49077217Sphk			{ &ifm_subtype_shared_aliases[0], 1 },
49177217Sphk			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
49277217Sphk			{ &ifm_subtype_ieee80211_aliases[0], 1 },
49377217Sphk			{ NULL, 0 },
49477217Sphk		},
49577217Sphk		{
49677217Sphk			{ &ifm_shared_option_descriptions[0], 0 },
49777217Sphk			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
49877217Sphk			{ NULL, 0 },
49977217Sphk		},
500114164Ssam		{
501114164Ssam			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
502116820Ssam			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
503114164Ssam			{ NULL, 0 },
504114164Ssam		},
50577217Sphk	},
506114232Sharti	{
507114232Sharti		{
508114232Sharti			{ &ifm_subtype_shared_descriptions[0], 0 },
509114232Sharti			{ &ifm_subtype_shared_aliases[0], 1 },
510114232Sharti			{ &ifm_subtype_atm_descriptions[0], 0 },
511114232Sharti			{ &ifm_subtype_atm_aliases[0], 1 },
512114232Sharti			{ NULL, 0 },
513114232Sharti		},
514114232Sharti		{
515114232Sharti			{ &ifm_shared_option_descriptions[0], 0 },
516114232Sharti			{ &ifm_subtype_atm_option_descriptions[0], 0 },
517114232Sharti			{ NULL, 0 },
518114232Sharti		},
519114232Sharti		{
520114232Sharti			{ NULL, 0 },
521114232Sharti		},
522114232Sharti	},
52325450Speter};
52425450Speter
52525450Speterstatic int
52695005Simpget_media_subtype(int type, const char *val)
52725450Speter{
52825450Speter	struct ifmedia_description *desc;
52925450Speter	struct ifmedia_type_to_subtype *ttos;
53025450Speter	int rval, i;
53125450Speter
53225450Speter	/* Find the top-level interface type. */
53325450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
53425450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
53525450Speter		if (type == desc->ifmt_word)
53625450Speter			break;
53725450Speter	if (desc->ifmt_string == NULL)
53825450Speter		errx(1, "unknown media type 0x%x", type);
53925450Speter
54025450Speter	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
54125450Speter		rval = lookup_media_word(ttos->subtypes[i].desc, val);
54225450Speter		if (rval != -1)
54325450Speter			return (rval);
54425450Speter	}
54525450Speter	errx(1, "unknown media subtype: %s", val);
546114164Ssam	/*NOTREACHED*/
54725450Speter}
54825450Speter
54925450Speterstatic int
550114164Ssamget_media_mode(int type, const char *val)
551114164Ssam{
552114164Ssam	struct ifmedia_description *desc;
553114164Ssam	struct ifmedia_type_to_subtype *ttos;
554114164Ssam	int rval, i;
555114164Ssam
556114164Ssam	/* Find the top-level interface type. */
557114164Ssam	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
558114164Ssam	    desc->ifmt_string != NULL; desc++, ttos++)
559114164Ssam		if (type == desc->ifmt_word)
560114164Ssam			break;
561114164Ssam	if (desc->ifmt_string == NULL)
562114164Ssam		errx(1, "unknown media mode 0x%x", type);
563114164Ssam
564114164Ssam	for (i = 0; ttos->modes[i].desc != NULL; i++) {
565114164Ssam		rval = lookup_media_word(ttos->modes[i].desc, val);
566114164Ssam		if (rval != -1)
567114164Ssam			return (rval);
568114164Ssam	}
569114164Ssam	return -1;
570114164Ssam}
571114164Ssam
572114164Ssamstatic int
57395005Simpget_media_options(int type, const char *val)
57425450Speter{
57525450Speter	struct ifmedia_description *desc;
57625450Speter	struct ifmedia_type_to_subtype *ttos;
57725450Speter	char *optlist, *optptr;
57825450Speter	int option = 0, i, rval = 0;
57925450Speter
58025450Speter	/* We muck with the string, so copy it. */
58125450Speter	optlist = strdup(val);
58225450Speter	if (optlist == NULL)
58325450Speter		err(1, "strdup");
58425450Speter
58525450Speter	/* Find the top-level interface type. */
58625450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
58725450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
58825450Speter		if (type == desc->ifmt_word)
58925450Speter			break;
59025450Speter	if (desc->ifmt_string == NULL)
59125450Speter		errx(1, "unknown media type 0x%x", type);
59225450Speter
59325450Speter	/*
59425450Speter	 * Look up the options in the user-provided comma-separated
59525450Speter	 * list.
59625450Speter	 */
59725450Speter	optptr = optlist;
59825450Speter	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
59925450Speter		for (i = 0; ttos->options[i].desc != NULL; i++) {
60025450Speter			option = lookup_media_word(ttos->options[i].desc, optptr);
60125450Speter			if (option != -1)
60225450Speter				break;
60325450Speter		}
60425450Speter		if (option == 0)
60525450Speter			errx(1, "unknown option: %s", optptr);
60625450Speter		rval |= option;
60725450Speter	}
60825450Speter
60925450Speter	free(optlist);
61025450Speter	return (rval);
61125450Speter}
61225450Speter
61325450Speterstatic int
61495005Simplookup_media_word(struct ifmedia_description *desc, const char *val)
61525450Speter{
61625450Speter
61725450Speter	for (; desc->ifmt_string != NULL; desc++)
61825450Speter		if (strcasecmp(desc->ifmt_string, val) == 0)
61925450Speter			return (desc->ifmt_word);
62025450Speter
62125450Speter	return (-1);
62225450Speter}
62325450Speter
62495005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw)
62525450Speter{
62625450Speter	struct ifmedia_description *desc;
62777385Sphk
62877385Sphk	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
62977385Sphk		if (IFM_TYPE(ifmw) == desc->ifmt_word)
63077385Sphk			break;
63177385Sphk
63277385Sphk	return desc;
63377385Sphk}
63477385Sphk
63595005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
63677385Sphk{
63777385Sphk	struct ifmedia_description *desc;
63825450Speter	struct ifmedia_type_to_subtype *ttos;
63925450Speter
64025450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
64125450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
64225450Speter		if (IFM_TYPE(ifmw) == desc->ifmt_word)
64325450Speter			break;
64477385Sphk
64577385Sphk	return ttos;
64677385Sphk}
64777385Sphk
64895005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw,
64995005Simp    struct ifmedia_type_to_subtype *ttos)
65077385Sphk{
65177385Sphk	int i;
65277385Sphk	struct ifmedia_description *desc;
65377385Sphk
65477385Sphk	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
65577385Sphk		if (ttos->subtypes[i].alias)
65677385Sphk			continue;
65777385Sphk		for (desc = ttos->subtypes[i].desc;
65877385Sphk		    desc->ifmt_string != NULL; desc++) {
65977385Sphk			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
66077385Sphk				return desc;
66177385Sphk		}
66277385Sphk	}
66377385Sphk
66477385Sphk	return NULL;
66577385Sphk}
66677385Sphk
667114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw,
668114164Ssam    struct ifmedia_type_to_subtype *ttos)
669114164Ssam{
670114164Ssam	int i;
671114164Ssam	struct ifmedia_description *desc;
672114164Ssam
673114164Ssam	for (i = 0; ttos->modes[i].desc != NULL; i++) {
674114164Ssam		if (ttos->modes[i].alias)
675114164Ssam			continue;
676114164Ssam		for (desc = ttos->modes[i].desc;
677114164Ssam		    desc->ifmt_string != NULL; desc++) {
678114164Ssam			if (IFM_MODE(ifmw) == desc->ifmt_word)
679114164Ssam				return desc;
680114164Ssam		}
681114164Ssam	}
682114164Ssam
683114164Ssam	return NULL;
684114164Ssam}
685114164Ssam
68677385Sphkstatic void
68795005Simpprint_media_word(int ifmw, int print_toptype)
68877385Sphk{
68977385Sphk	struct ifmedia_description *desc;
69077385Sphk	struct ifmedia_type_to_subtype *ttos;
69177385Sphk	int seen_option = 0, i;
69277385Sphk
69377385Sphk	/* Find the top-level interface type. */
69477385Sphk	desc = get_toptype_desc(ifmw);
69577385Sphk	ttos = get_toptype_ttos(ifmw);
69625450Speter	if (desc->ifmt_string == NULL) {
69725450Speter		printf("<unknown type>");
69825450Speter		return;
69977385Sphk	} else if (print_toptype) {
70077385Sphk		printf("%s", desc->ifmt_string);
70125450Speter	}
70225450Speter
70325450Speter	/*
70425450Speter	 * Don't print the top-level type; it's not like we can
70525450Speter	 * change it, or anything.
70625450Speter	 */
70725450Speter
70825450Speter	/* Find subtype. */
70977385Sphk	desc = get_subtype_desc(ifmw, ttos);
710161536Sthomas	if (desc == NULL) {
711161536Sthomas		printf("<unknown subtype>");
712161536Sthomas		return;
713161536Sthomas	}
71425450Speter
71577385Sphk	if (print_toptype)
71677385Sphk		putchar(' ');
71777385Sphk
71825450Speter	printf("%s", desc->ifmt_string);
71925450Speter
720114164Ssam	if (print_toptype) {
721114164Ssam		desc = get_mode_desc(ifmw, ttos);
722116820Ssam		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
723114164Ssam			printf(" mode %s", desc->ifmt_string);
724114164Ssam	}
725114164Ssam
72625450Speter	/* Find options. */
72725450Speter	for (i = 0; ttos->options[i].desc != NULL; i++) {
72825450Speter		if (ttos->options[i].alias)
72925450Speter			continue;
73025450Speter		for (desc = ttos->options[i].desc;
73125450Speter		    desc->ifmt_string != NULL; desc++) {
73225450Speter			if (ifmw & desc->ifmt_word) {
73325450Speter				if (seen_option == 0)
73425450Speter					printf(" <");
73525450Speter				printf("%s%s", seen_option++ ? "," : "",
73625450Speter				    desc->ifmt_string);
73725450Speter			}
73825450Speter		}
73925450Speter	}
74025450Speter	printf("%s", seen_option ? ">" : "");
741166113Smarius
742166169Smarius	if (print_toptype && IFM_INST(ifmw) != 0)
743166113Smarius		printf(" instance %d", IFM_INST(ifmw));
74425450Speter}
74525450Speter
74677385Sphkstatic void
74795005Simpprint_media_word_ifconfig(int ifmw)
74877385Sphk{
74977385Sphk	struct ifmedia_description *desc;
75077385Sphk	struct ifmedia_type_to_subtype *ttos;
75177385Sphk	int i;
75277385Sphk
75377385Sphk	/* Find the top-level interface type. */
75477385Sphk	desc = get_toptype_desc(ifmw);
75577385Sphk	ttos = get_toptype_ttos(ifmw);
75677385Sphk	if (desc->ifmt_string == NULL) {
75777385Sphk		printf("<unknown type>");
75877385Sphk		return;
75977385Sphk	}
76077385Sphk
76177385Sphk	/*
76277385Sphk	 * Don't print the top-level type; it's not like we can
76377385Sphk	 * change it, or anything.
76477385Sphk	 */
76577385Sphk
76677385Sphk	/* Find subtype. */
76777385Sphk	desc = get_subtype_desc(ifmw, ttos);
768161536Sthomas	if (desc == NULL) {
769161536Sthomas		printf("<unknown subtype>");
770161536Sthomas		return;
771161536Sthomas	}
77277385Sphk
77377385Sphk	printf("media %s", desc->ifmt_string);
77477385Sphk
775114164Ssam	desc = get_mode_desc(ifmw, ttos);
776114164Ssam	if (desc != NULL)
777114164Ssam		printf(" mode %s", desc->ifmt_string);
778114164Ssam
77977385Sphk	/* Find options. */
78077385Sphk	for (i = 0; ttos->options[i].desc != NULL; i++) {
78177385Sphk		if (ttos->options[i].alias)
78277385Sphk			continue;
78377385Sphk		for (desc = ttos->options[i].desc;
78477385Sphk		    desc->ifmt_string != NULL; desc++) {
78577385Sphk			if (ifmw & desc->ifmt_word) {
78677385Sphk				printf(" mediaopt %s", desc->ifmt_string);
78777385Sphk			}
78877385Sphk		}
78977385Sphk	}
790166113Smarius
791166169Smarius	if (IFM_INST(ifmw) != 0)
792166169Smarius		printf(" instance %d", IFM_INST(ifmw));
79377385Sphk}
79477385Sphk
79525450Speter/**********************************************************************
79625450Speter * ...until here.
79725450Speter **********************************************************************/
798138593Ssam
799138593Ssamstatic struct cmd media_cmds[] = {
800138593Ssam	DEF_CMD_ARG("media",	setmedia),
801138593Ssam	DEF_CMD_ARG("mode",	setmediamode),
802138593Ssam	DEF_CMD_ARG("mediaopt",	setmediaopt),
803138593Ssam	DEF_CMD_ARG("-mediaopt",unsetmediaopt),
804166113Smarius	DEF_CMD_ARG("inst",	setmediainst),
805166113Smarius	DEF_CMD_ARG("instance",	setmediainst),
806138593Ssam};
807138593Ssamstatic struct afswtch af_media = {
808138593Ssam	.af_name	= "af_media",
809138593Ssam	.af_af		= AF_UNSPEC,
810139494Ssam	.af_other_status = media_status,
811138593Ssam};
812138593Ssam
813138593Ssamstatic __constructor void
814138593Ssamifmedia_ctor(void)
815138593Ssam{
816138593Ssam#define	N(a)	(sizeof(a) / sizeof(a[0]))
817138593Ssam	int i;
818138593Ssam
819138593Ssam	for (i = 0; i < N(media_cmds);  i++)
820138593Ssam		cmd_register(&media_cmds[i]);
821138593Ssam	af_register(&af_media);
822138593Ssam#undef N
823138593Ssam}
824