ifmedia.c revision 77385
125450Speter/*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
250476Speter/* $FreeBSD: head/sbin/ifconfig/ifmedia.c 77385 2001-05-29 09:13:44Z phk $ */
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
9225450Speterstatic void	domediaopt __P((const char *, int, int));
9325450Speterstatic int	get_media_subtype __P((int, const char *));
9425450Speterstatic int	get_media_options __P((int, const char *));
9525450Speterstatic int	lookup_media_word __P((struct ifmedia_description *, const char *));
9677385Sphkstatic void	print_media_word __P((int, int));
9777385Sphkstatic void	print_media_word_ifconfig __P((int));
9825450Speter
9977385Sphkstatic struct ifmedia_description *get_toptype_desc __P((int));
10077385Sphkstatic struct ifmedia_type_to_subtype *get_toptype_ttos __P((int));
10177385Sphkstatic struct ifmedia_description *get_subtype_desc __P((int,
10277385Sphk    struct ifmedia_type_to_subtype *ttos));
10377385Sphk
10425450Spetervoid
10525667Spetermedia_status(s, info)
10625450Speter	int s;
10725667Speter	struct rt_addrinfo *info __unused;
10825450Speter{
10925450Speter	struct ifmediareq ifmr;
11025450Speter	int *media_list, i;
11125450Speter
11225450Speter	(void) memset(&ifmr, 0, sizeof(ifmr));
11325450Speter	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
11425450Speter
11525450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
11625450Speter		/*
11725450Speter		 * Interface doesn't support SIOC{G,S}IFMEDIA.
11825450Speter		 */
11925450Speter		return;
12025450Speter	}
12125450Speter
12225450Speter	if (ifmr.ifm_count == 0) {
12325450Speter		warnx("%s: no media types?", name);
12425450Speter		return;
12525450Speter	}
12625450Speter
12725450Speter	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
12825450Speter	if (media_list == NULL)
12925450Speter		err(1, "malloc");
13025450Speter	ifmr.ifm_ulist = media_list;
13125450Speter
13225450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
13325450Speter		err(1, "SIOCGIFMEDIA");
13425450Speter
13525450Speter	printf("\tmedia: ");
13677385Sphk	print_media_word(ifmr.ifm_current, 1);
13725450Speter	if (ifmr.ifm_active != ifmr.ifm_current) {
13825450Speter		putchar(' ');
13925450Speter		putchar('(');
14077385Sphk		print_media_word(ifmr.ifm_active, 0);
14125450Speter		putchar(')');
14225450Speter	}
14325450Speter
14477385Sphk	putchar('\n');
14577385Sphk
14625450Speter	if (ifmr.ifm_status & IFM_AVALID) {
14777385Sphk		printf("\tstatus: ");
14825450Speter		switch (IFM_TYPE(ifmr.ifm_active)) {
14925450Speter		case IFM_ETHER:
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;
16377217Sphk		case IFM_IEEE80211:
16477217Sphk			/* XXX: Different value for adhoc? */
16577217Sphk			if (ifmr.ifm_status & IFM_ACTIVE)
16677217Sphk				printf("associated");
16777217Sphk			else
16877217Sphk				printf("no carrier");
16977217Sphk			break;
17025450Speter		}
17125450Speter	}
17225450Speter
17325450Speter	putchar('\n');
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
18725450Spetervoid
18825660Spetersetmedia(val, d, s, afp)
18925450Speter	const char *val;
19025450Speter	int d;
19125450Speter	int s;
19225660Speter	const struct afswtch *afp;
19325450Speter{
19425450Speter	struct ifmediareq ifmr;
19525450Speter	int first_type, subtype;
19625450Speter
19725450Speter	(void) memset(&ifmr, 0, sizeof(ifmr));
19825450Speter	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
19925450Speter
20025450Speter	ifmr.ifm_count = 1;
20125450Speter	ifmr.ifm_ulist = &first_type;
20225450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
20325450Speter		/*
20425450Speter		 * If we get E2BIG, the kernel is telling us
20525450Speter		 * that there are more, so we can ignore it.
20625450Speter		 */
20725450Speter		if (errno != E2BIG)
20825450Speter			err(1, "SIOCGIFMEDIA");
20925450Speter	}
21025450Speter
21125450Speter	if (ifmr.ifm_count == 0)
21225450Speter		errx(1, "%s: no media types?", name);
21325450Speter
21425450Speter	/*
21525450Speter	 * We are primarily concerned with the top-level type.
21625450Speter	 * However, "current" may be only IFM_NONE, so we just look
21725450Speter	 * for the top-level type in the first "supported type"
21825450Speter	 * entry.
21925450Speter	 *
22025450Speter	 * (I'm assuming that all supported media types for a given
22125450Speter	 * interface will be the same top-level type..)
22225450Speter	 */
22325450Speter	subtype = get_media_subtype(IFM_TYPE(first_type), val);
22425450Speter
22525450Speter	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
22625450Speter	ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
22725450Speter	    IFM_TYPE(first_type) | subtype;
22825450Speter
22925450Speter	if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
23025450Speter		err(1, "SIOCSIFMEDIA");
23125450Speter}
23225450Speter
23325450Spetervoid
23425660Spetersetmediaopt(val, d, s, afp)
23525450Speter	const char *val;
23625450Speter	int d;
23725450Speter	int s;
23825660Speter	const struct afswtch *afp;
23925450Speter{
24025450Speter
24125450Speter	domediaopt(val, 0, s);
24225450Speter}
24325450Speter
24425450Spetervoid
24525660Speterunsetmediaopt(val, d, s, afp)
24625450Speter	const char *val;
24725450Speter	int d;
24825450Speter	int s;
24925660Speter	const struct afswtch *afp;
25025450Speter{
25125450Speter
25225450Speter	domediaopt(val, 1, s);
25325450Speter}
25425450Speter
25525450Speterstatic void
25625450Speterdomediaopt(val, clear, s)
25725450Speter	const char *val;
25825450Speter	int clear;
25925450Speter	int s;
26025450Speter{
26125450Speter	struct ifmediareq ifmr;
26225450Speter	int *mwords, options;
26325450Speter
26425450Speter	(void) memset(&ifmr, 0, sizeof(ifmr));
26525450Speter	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
26625450Speter
26725450Speter	/*
26825450Speter	 * We must go through the motions of reading all
26925450Speter	 * supported media because we need to know both
27025450Speter	 * the current media type and the top-level type.
27125450Speter	 */
27225450Speter
27325450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
27425450Speter		err(1, "SIOCGIFMEDIA");
27525450Speter
27625450Speter	if (ifmr.ifm_count == 0)
27725450Speter		errx(1, "%s: no media types?", name);
27825450Speter
27925450Speter	mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
28025450Speter	if (mwords == NULL)
28125450Speter		err(1, "malloc");
28225450Speter
28325450Speter	ifmr.ifm_ulist = mwords;
28425450Speter	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
28525450Speter		err(1, "SIOCGIFMEDIA");
28625450Speter
28725450Speter	options = get_media_options(IFM_TYPE(mwords[0]), val);
28825450Speter
28925450Speter	free(mwords);
29025450Speter
29125450Speter	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
29225450Speter	ifr.ifr_media = ifmr.ifm_current;
29325450Speter	if (clear)
29425450Speter		ifr.ifr_media &= ~options;
29525450Speter	else
29625450Speter		ifr.ifr_media |= options;
29725450Speter
29825450Speter	if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
29925450Speter		err(1, "SIOCSIFMEDIA");
30025450Speter}
30125450Speter
30225450Speter/**********************************************************************
30325450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c
30425450Speter **********************************************************************/
30525450Speter
30625450Speterstatic struct ifmedia_description ifm_type_descriptions[] =
30725450Speter    IFM_TYPE_DESCRIPTIONS;
30825450Speter
30925450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
31025450Speter    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
31125450Speter
31225450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] =
31325450Speter    IFM_SUBTYPE_ETHERNET_ALIASES;
31425450Speter
31525450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
31625450Speter    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
31725450Speter
31825450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
31925450Speter    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
32025450Speter
32125450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] =
32225450Speter    IFM_SUBTYPE_TOKENRING_ALIASES;
32325450Speter
32425450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
32525450Speter    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
32625450Speter
32725450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] =
32825450Speter    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
32925450Speter
33025450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] =
33125450Speter    IFM_SUBTYPE_FDDI_ALIASES;
33225450Speter
33325450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
33425450Speter    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
33525450Speter
33677217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
33777217Sphk    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
33877217Sphk
33977217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
34077217Sphk    IFM_SUBTYPE_IEEE80211_ALIASES;
34177217Sphk
34277217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
34377217Sphk    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
34477217Sphk
34525450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] =
34625450Speter    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
34725450Speter
34825450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] =
34925450Speter    IFM_SUBTYPE_SHARED_ALIASES;
35025450Speter
35125450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] =
35225450Speter    IFM_SHARED_OPTION_DESCRIPTIONS;
35325450Speter
35425450Speterstruct ifmedia_type_to_subtype {
35525450Speter	struct {
35625450Speter		struct ifmedia_description *desc;
35725450Speter		int alias;
35825450Speter	} subtypes[5];
35925450Speter	struct {
36025450Speter		struct ifmedia_description *desc;
36125450Speter		int alias;
36225450Speter	} options[3];
36325450Speter};
36425450Speter
36525450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
36625450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
36725450Speter	{
36825450Speter		{
36925450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
37025450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
37125450Speter			{ &ifm_subtype_ethernet_descriptions[0], 0 },
37225450Speter			{ &ifm_subtype_ethernet_aliases[0], 1 },
37325450Speter			{ NULL, 0 },
37425450Speter		},
37525450Speter		{
37625450Speter			{ &ifm_shared_option_descriptions[0], 0 },
37777217Sphk			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
37825450Speter			{ NULL, 0 },
37925450Speter		},
38025450Speter	},
38125450Speter	{
38225450Speter		{
38325450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
38425450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
38525450Speter			{ &ifm_subtype_tokenring_descriptions[0], 0 },
38625450Speter			{ &ifm_subtype_tokenring_aliases[0], 1 },
38725450Speter			{ NULL, 0 },
38825450Speter		},
38925450Speter		{
39025450Speter			{ &ifm_shared_option_descriptions[0], 0 },
39177217Sphk			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
39225450Speter			{ NULL, 0 },
39325450Speter		},
39425450Speter	},
39525450Speter	{
39625450Speter		{
39725450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
39825450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
39925450Speter			{ &ifm_subtype_fddi_descriptions[0], 0 },
40025450Speter			{ &ifm_subtype_fddi_aliases[0], 1 },
40125450Speter			{ NULL, 0 },
40225450Speter		},
40325450Speter		{
40425450Speter			{ &ifm_shared_option_descriptions[0], 0 },
40577217Sphk			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
40625450Speter			{ NULL, 0 },
40725450Speter		},
40825450Speter	},
40977217Sphk	{
41077217Sphk		{
41177217Sphk			{ &ifm_subtype_shared_descriptions[0], 0 },
41277217Sphk			{ &ifm_subtype_shared_aliases[0], 1 },
41377217Sphk			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
41477217Sphk			{ &ifm_subtype_ieee80211_aliases[0], 1 },
41577217Sphk			{ NULL, 0 },
41677217Sphk		},
41777217Sphk		{
41877217Sphk			{ &ifm_shared_option_descriptions[0], 0 },
41977217Sphk			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
42077217Sphk			{ NULL, 0 },
42177217Sphk		},
42277217Sphk	},
42325450Speter};
42425450Speter
42525450Speterstatic int
42625450Speterget_media_subtype(type, val)
42725450Speter	int type;
42825450Speter	const char *val;
42925450Speter{
43025450Speter	struct ifmedia_description *desc;
43125450Speter	struct ifmedia_type_to_subtype *ttos;
43225450Speter	int rval, i;
43325450Speter
43425450Speter	/* Find the top-level interface type. */
43525450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
43625450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
43725450Speter		if (type == desc->ifmt_word)
43825450Speter			break;
43925450Speter	if (desc->ifmt_string == NULL)
44025450Speter		errx(1, "unknown media type 0x%x", type);
44125450Speter
44225450Speter	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
44325450Speter		rval = lookup_media_word(ttos->subtypes[i].desc, val);
44425450Speter		if (rval != -1)
44525450Speter			return (rval);
44625450Speter	}
44725450Speter	errx(1, "unknown media subtype: %s", val);
44825450Speter	/* NOTREACHED */
44925450Speter}
45025450Speter
45125450Speterstatic int
45225450Speterget_media_options(type, val)
45325450Speter	int type;
45425450Speter	const char *val;
45525450Speter{
45625450Speter	struct ifmedia_description *desc;
45725450Speter	struct ifmedia_type_to_subtype *ttos;
45825450Speter	char *optlist, *optptr;
45925450Speter	int option = 0, i, rval = 0;
46025450Speter
46125450Speter	/* We muck with the string, so copy it. */
46225450Speter	optlist = strdup(val);
46325450Speter	if (optlist == NULL)
46425450Speter		err(1, "strdup");
46525450Speter
46625450Speter	/* Find the top-level interface type. */
46725450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
46825450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
46925450Speter		if (type == desc->ifmt_word)
47025450Speter			break;
47125450Speter	if (desc->ifmt_string == NULL)
47225450Speter		errx(1, "unknown media type 0x%x", type);
47325450Speter
47425450Speter	/*
47525450Speter	 * Look up the options in the user-provided comma-separated
47625450Speter	 * list.
47725450Speter	 */
47825450Speter	optptr = optlist;
47925450Speter	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
48025450Speter		for (i = 0; ttos->options[i].desc != NULL; i++) {
48125450Speter			option = lookup_media_word(ttos->options[i].desc, optptr);
48225450Speter			if (option != -1)
48325450Speter				break;
48425450Speter		}
48525450Speter		if (option == 0)
48625450Speter			errx(1, "unknown option: %s", optptr);
48725450Speter		rval |= option;
48825450Speter	}
48925450Speter
49025450Speter	free(optlist);
49125450Speter	return (rval);
49225450Speter}
49325450Speter
49425450Speterstatic int
49525450Speterlookup_media_word(desc, val)
49625450Speter	struct ifmedia_description *desc;
49725450Speter	const char *val;
49825450Speter{
49925450Speter
50025450Speter	for (; desc->ifmt_string != NULL; desc++)
50125450Speter		if (strcasecmp(desc->ifmt_string, val) == 0)
50225450Speter			return (desc->ifmt_word);
50325450Speter
50425450Speter	return (-1);
50525450Speter}
50625450Speter
50777385Sphkstatic struct ifmedia_description *get_toptype_desc(ifmw)
50825450Speter	int ifmw;
50925450Speter{
51025450Speter	struct ifmedia_description *desc;
51177385Sphk
51277385Sphk	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
51377385Sphk		if (IFM_TYPE(ifmw) == desc->ifmt_word)
51477385Sphk			break;
51577385Sphk
51677385Sphk	return desc;
51777385Sphk}
51877385Sphk
51977385Sphkstatic struct ifmedia_type_to_subtype *get_toptype_ttos(ifmw)
52077385Sphk	int ifmw;
52177385Sphk{
52277385Sphk	struct ifmedia_description *desc;
52325450Speter	struct ifmedia_type_to_subtype *ttos;
52425450Speter
52525450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
52625450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
52725450Speter		if (IFM_TYPE(ifmw) == desc->ifmt_word)
52825450Speter			break;
52977385Sphk
53077385Sphk	return ttos;
53177385Sphk}
53277385Sphk
53377385Sphkstatic struct ifmedia_description *get_subtype_desc(ifmw, ttos)
53477385Sphk	int ifmw;
53577385Sphk	struct ifmedia_type_to_subtype *ttos;
53677385Sphk{
53777385Sphk	int i;
53877385Sphk	struct ifmedia_description *desc;
53977385Sphk
54077385Sphk	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
54177385Sphk		if (ttos->subtypes[i].alias)
54277385Sphk			continue;
54377385Sphk		for (desc = ttos->subtypes[i].desc;
54477385Sphk		    desc->ifmt_string != NULL; desc++) {
54577385Sphk			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
54677385Sphk				return desc;
54777385Sphk		}
54877385Sphk	}
54977385Sphk
55077385Sphk	return NULL;
55177385Sphk}
55277385Sphk
55377385Sphkstatic void
55477385Sphkprint_media_word(ifmw, print_toptype)
55577385Sphk	int ifmw;
55677385Sphk	int print_toptype;
55777385Sphk{
55877385Sphk	struct ifmedia_description *desc;
55977385Sphk	struct ifmedia_type_to_subtype *ttos;
56077385Sphk	int seen_option = 0, i;
56177385Sphk
56277385Sphk	/* Find the top-level interface type. */
56377385Sphk	desc = get_toptype_desc(ifmw);
56477385Sphk	ttos = get_toptype_ttos(ifmw);
56525450Speter	if (desc->ifmt_string == NULL) {
56625450Speter		printf("<unknown type>");
56725450Speter		return;
56877385Sphk	} else if (print_toptype) {
56977385Sphk		printf("%s", desc->ifmt_string);
57025450Speter	}
57125450Speter
57225450Speter	/*
57325450Speter	 * Don't print the top-level type; it's not like we can
57425450Speter	 * change it, or anything.
57525450Speter	 */
57625450Speter
57725450Speter	/* Find subtype. */
57877385Sphk	desc = get_subtype_desc(ifmw, ttos);
57977385Sphk	if (desc != NULL)
58077385Sphk		goto got_subtype;
58125450Speter
58225450Speter	/* Falling to here means unknown subtype. */
58325450Speter	printf("<unknown subtype>");
58425450Speter	return;
58525450Speter
58625450Speter got_subtype:
58777385Sphk	if (print_toptype)
58877385Sphk		putchar(' ');
58977385Sphk
59025450Speter	printf("%s", desc->ifmt_string);
59125450Speter
59225450Speter	/* Find options. */
59325450Speter	for (i = 0; ttos->options[i].desc != NULL; i++) {
59425450Speter		if (ttos->options[i].alias)
59525450Speter			continue;
59625450Speter		for (desc = ttos->options[i].desc;
59725450Speter		    desc->ifmt_string != NULL; desc++) {
59825450Speter			if (ifmw & desc->ifmt_word) {
59925450Speter				if (seen_option == 0)
60025450Speter					printf(" <");
60125450Speter				printf("%s%s", seen_option++ ? "," : "",
60225450Speter				    desc->ifmt_string);
60325450Speter			}
60425450Speter		}
60525450Speter	}
60625450Speter	printf("%s", seen_option ? ">" : "");
60725450Speter}
60825450Speter
60977385Sphkstatic void
61077385Sphkprint_media_word_ifconfig(ifmw)
61177385Sphk	int ifmw;
61277385Sphk{
61377385Sphk	struct ifmedia_description *desc;
61477385Sphk	struct ifmedia_type_to_subtype *ttos;
61577385Sphk	int i;
61677385Sphk
61777385Sphk	/* Find the top-level interface type. */
61877385Sphk	desc = get_toptype_desc(ifmw);
61977385Sphk	ttos = get_toptype_ttos(ifmw);
62077385Sphk	if (desc->ifmt_string == NULL) {
62177385Sphk		printf("<unknown type>");
62277385Sphk		return;
62377385Sphk	}
62477385Sphk
62577385Sphk	/*
62677385Sphk	 * Don't print the top-level type; it's not like we can
62777385Sphk	 * change it, or anything.
62877385Sphk	 */
62977385Sphk
63077385Sphk	/* Find subtype. */
63177385Sphk	desc = get_subtype_desc(ifmw, ttos);
63277385Sphk	if (desc != NULL)
63377385Sphk		goto got_subtype;
63477385Sphk
63577385Sphk	/* Falling to here means unknown subtype. */
63677385Sphk	printf("<unknown subtype>");
63777385Sphk	return;
63877385Sphk
63977385Sphk got_subtype:
64077385Sphk	printf("media %s", desc->ifmt_string);
64177385Sphk
64277385Sphk	/* Find options. */
64377385Sphk	for (i = 0; ttos->options[i].desc != NULL; i++) {
64477385Sphk		if (ttos->options[i].alias)
64577385Sphk			continue;
64677385Sphk		for (desc = ttos->options[i].desc;
64777385Sphk		    desc->ifmt_string != NULL; desc++) {
64877385Sphk			if (ifmw & desc->ifmt_word) {
64977385Sphk				printf(" mediaopt %s", desc->ifmt_string);
65077385Sphk			}
65177385Sphk		}
65277385Sphk	}
65377385Sphk}
65477385Sphk
65525450Speter/**********************************************************************
65625450Speter * ...until here.
65725450Speter **********************************************************************/
658