1235289Sadrian/*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
2235289Sadrian/* $FreeBSD$ */
3235289Sadrian
4331722Seadler/*
5235289Sadrian * Copyright (c) 1997 Jason R. Thorpe.
6235289Sadrian * All rights reserved.
7235289Sadrian *
8235289Sadrian * Redistribution and use in source and binary forms, with or without
9235289Sadrian * modification, are permitted provided that the following conditions
10235289Sadrian * are met:
11235289Sadrian * 1. Redistributions of source code must retain the above copyright
12235289Sadrian *    notice, this list of conditions and the following disclaimer.
13235289Sadrian * 2. Redistributions in binary form must reproduce the above copyright
14235289Sadrian *    notice, this list of conditions and the following disclaimer in the
15235289Sadrian *    documentation and/or other materials provided with the distribution.
16235289Sadrian * 3. All advertising materials mentioning features or use of this software
17235289Sadrian *    must display the following acknowledgement:
18235289Sadrian *      This product includes software developed for the NetBSD Project
19235289Sadrian *	by Jason R. Thorpe.
20235289Sadrian * 4. The name of the author may not be used to endorse or promote products
21235289Sadrian *    derived from this software without specific prior written permission.
22235289Sadrian *
23235289Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24235289Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25235289Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26235289Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27235289Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28235289Sadrian * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29235289Sadrian * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30235289Sadrian * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31235289Sadrian * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32235289Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33235289Sadrian * SUCH DAMAGE.
34235289Sadrian */
35235289Sadrian
36235289Sadrian/*
37235289Sadrian * Copyright (c) 1983, 1993
38235289Sadrian *	The Regents of the University of California.  All rights reserved.
39235289Sadrian *
40235289Sadrian * Redistribution and use in source and binary forms, with or without
41235289Sadrian * modification, are permitted provided that the following conditions
42235289Sadrian * are met:
43235289Sadrian * 1. Redistributions of source code must retain the above copyright
44235289Sadrian *    notice, this list of conditions and the following disclaimer.
45235289Sadrian * 2. Redistributions in binary form must reproduce the above copyright
46235289Sadrian *    notice, this list of conditions and the following disclaimer in the
47235289Sadrian *    documentation and/or other materials provided with the distribution.
48235289Sadrian * 4. Neither the name of the University nor the names of its contributors
49235289Sadrian *    may be used to endorse or promote products derived from this software
50235289Sadrian *    without specific prior written permission.
51235289Sadrian *
52235289Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53235289Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54235289Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55235289Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56235289Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57235289Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58235289Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59235289Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60235289Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61235289Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62235289Sadrian * SUCH DAMAGE.
63235289Sadrian */
64235289Sadrian/*
65235289Sadrian * based on sbin/ifconfig/ifmedia.c r221954
66235289Sadrian */
67235289Sadrian
68235289Sadrian#include <sys/param.h>
69235289Sadrian#include <sys/ioctl.h>
70235289Sadrian#include <sys/socket.h>
71235289Sadrian#include <sys/sysctl.h>
72235289Sadrian#include <sys/time.h>
73235289Sadrian
74235289Sadrian#include <net/if.h>
75235289Sadrian#include <net/if_dl.h>
76235289Sadrian#include <net/if_types.h>
77235289Sadrian#include <net/if_media.h>
78235289Sadrian#include <net/route.h>
79235289Sadrian
80235289Sadrian#include <ctype.h>
81235289Sadrian#include <err.h>
82235289Sadrian#include <errno.h>
83235289Sadrian#include <fcntl.h>
84235289Sadrian#include <stdio.h>
85235289Sadrian#include <stdlib.h>
86235289Sadrian#include <string.h>
87235289Sadrian#include <unistd.h>
88235289Sadrian
89235289Sadrianvoid	domediaopt(const char *, int, int);
90235289Sadrianint	get_media_subtype(int, const char *);
91235289Sadrianint	get_media_mode(int, const char *);
92235289Sadrianint	get_media_options(int, const char *);
93235289Sadrianint	lookup_media_word(struct ifmedia_description *, const char *);
94235289Sadrianvoid	print_media_word(int, int);
95235289Sadrianvoid	print_media_word_ifconfig(int);
96235289Sadrian
97235289Sadrian#if 0
98235289Sadrianstatic struct ifmedia_description *get_toptype_desc(int);
99235289Sadrianstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int);
100235289Sadrianstatic struct ifmedia_description *get_subtype_desc(int,
101235289Sadrian    struct ifmedia_type_to_subtype *ttos);
102235289Sadrian
103235289Sadrian#define	IFM_OPMODE(x) \
104235289Sadrian	((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
105235289Sadrian	 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
106235289Sadrian	 IFM_IEEE80211_MBSS))
107235289Sadrian#define	IFM_IEEE80211_STA	0
108235289Sadrian
109235289Sadrianstatic void
110235289Sadrianmedia_status(int s)
111235289Sadrian{
112235289Sadrian	struct ifmediareq ifmr;
113235289Sadrian	int *media_list, i;
114235289Sadrian
115235289Sadrian	(void) memset(&ifmr, 0, sizeof(ifmr));
116235289Sadrian	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
117235289Sadrian
118235289Sadrian	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
119235289Sadrian		/*
120235289Sadrian		 * Interface doesn't support SIOC{G,S}IFMEDIA.
121235289Sadrian		 */
122235289Sadrian		return;
123235289Sadrian	}
124235289Sadrian
125235289Sadrian	if (ifmr.ifm_count == 0) {
126235289Sadrian		warnx("%s: no media types?", name);
127235289Sadrian		return;
128235289Sadrian	}
129235289Sadrian
130235289Sadrian	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
131235289Sadrian	if (media_list == NULL)
132235289Sadrian		err(1, "malloc");
133235289Sadrian	ifmr.ifm_ulist = media_list;
134235289Sadrian
135235289Sadrian	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
136235289Sadrian		err(1, "SIOCGIFMEDIA");
137235289Sadrian
138235289Sadrian	printf("\tmedia: ");
139235289Sadrian	print_media_word(ifmr.ifm_current, 1);
140235289Sadrian	if (ifmr.ifm_active != ifmr.ifm_current) {
141235289Sadrian		putchar(' ');
142235289Sadrian		putchar('(');
143235289Sadrian		print_media_word(ifmr.ifm_active, 0);
144235289Sadrian		putchar(')');
145235289Sadrian	}
146235289Sadrian
147235289Sadrian	putchar('\n');
148235289Sadrian
149235289Sadrian	if (ifmr.ifm_status & IFM_AVALID) {
150235289Sadrian		printf("\tstatus: ");
151235289Sadrian		switch (IFM_TYPE(ifmr.ifm_active)) {
152235289Sadrian		case IFM_ETHER:
153235289Sadrian		case IFM_ATM:
154235289Sadrian			if (ifmr.ifm_status & IFM_ACTIVE)
155235289Sadrian				printf("active");
156235289Sadrian			else
157235289Sadrian				printf("no carrier");
158235289Sadrian			break;
159235289Sadrian
160235289Sadrian		case IFM_FDDI:
161235289Sadrian		case IFM_TOKEN:
162235289Sadrian			if (ifmr.ifm_status & IFM_ACTIVE)
163235289Sadrian				printf("inserted");
164235289Sadrian			else
165235289Sadrian				printf("no ring");
166235289Sadrian			break;
167235289Sadrian
168235289Sadrian		case IFM_IEEE80211:
169235289Sadrian			if (ifmr.ifm_status & IFM_ACTIVE) {
170235289Sadrian				/* NB: only sta mode associates */
171235289Sadrian				if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
172235289Sadrian					printf("associated");
173235289Sadrian				else
174235289Sadrian					printf("running");
175235289Sadrian			} else
176235289Sadrian				printf("no carrier");
177235289Sadrian			break;
178235289Sadrian		}
179235289Sadrian		putchar('\n');
180235289Sadrian	}
181235289Sadrian
182235289Sadrian	if (ifmr.ifm_count > 0 && supmedia) {
183235289Sadrian		printf("\tsupported media:\n");
184235289Sadrian		for (i = 0; i < ifmr.ifm_count; i++) {
185235289Sadrian			printf("\t\t");
186235289Sadrian			print_media_word_ifconfig(media_list[i]);
187235289Sadrian			putchar('\n');
188235289Sadrian		}
189235289Sadrian	}
190235289Sadrian
191235289Sadrian	free(media_list);
192235289Sadrian}
193235289Sadrian
194235289Sadrianstruct ifmediareq *
195235289Sadrianifmedia_getstate(int s)
196235289Sadrian{
197235289Sadrian	static struct ifmediareq *ifmr = NULL;
198235289Sadrian	int *mwords;
199235289Sadrian
200235289Sadrian	if (ifmr == NULL) {
201235289Sadrian		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
202235289Sadrian		if (ifmr == NULL)
203235289Sadrian			err(1, "malloc");
204235289Sadrian
205235289Sadrian		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
206235289Sadrian		(void) strncpy(ifmr->ifm_name, name,
207235289Sadrian		    sizeof(ifmr->ifm_name));
208235289Sadrian
209235289Sadrian		ifmr->ifm_count = 0;
210235289Sadrian		ifmr->ifm_ulist = NULL;
211235289Sadrian
212235289Sadrian		/*
213235289Sadrian		 * We must go through the motions of reading all
214235289Sadrian		 * supported media because we need to know both
215235289Sadrian		 * the current media type and the top-level type.
216235289Sadrian		 */
217235289Sadrian
218235289Sadrian		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
219235289Sadrian			err(1, "SIOCGIFMEDIA");
220235289Sadrian		}
221235289Sadrian
222235289Sadrian		if (ifmr->ifm_count == 0)
223235289Sadrian			errx(1, "%s: no media types?", name);
224235289Sadrian
225235289Sadrian		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
226235289Sadrian		if (mwords == NULL)
227235289Sadrian			err(1, "malloc");
228235289Sadrian
229235289Sadrian		ifmr->ifm_ulist = mwords;
230235289Sadrian		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
231235289Sadrian			err(1, "SIOCGIFMEDIA");
232235289Sadrian	}
233235289Sadrian
234235289Sadrian	return ifmr;
235235289Sadrian}
236235289Sadrian
237235289Sadrianstatic void
238235289Sadriansetifmediacallback(int s, void *arg)
239235289Sadrian{
240235289Sadrian	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
241235289Sadrian	static int did_it = 0;
242235289Sadrian
243235289Sadrian	if (!did_it) {
244235289Sadrian		ifr.ifr_media = ifmr->ifm_current;
245235289Sadrian		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
246235289Sadrian			err(1, "SIOCSIFMEDIA (media)");
247235289Sadrian		free(ifmr->ifm_ulist);
248235289Sadrian		free(ifmr);
249235289Sadrian		did_it = 1;
250235289Sadrian	}
251235289Sadrian}
252235289Sadrian
253235289Sadrianstatic void
254235289Sadriansetmedia(const char *val, int d, int s, const struct afswtch *afp)
255235289Sadrian{
256235289Sadrian	struct ifmediareq *ifmr;
257235289Sadrian	int subtype;
258235289Sadrian
259235289Sadrian	ifmr = ifmedia_getstate(s);
260235289Sadrian
261235289Sadrian	/*
262235289Sadrian	 * We are primarily concerned with the top-level type.
263235289Sadrian	 * However, "current" may be only IFM_NONE, so we just look
264235289Sadrian	 * for the top-level type in the first "supported type"
265235289Sadrian	 * entry.
266235289Sadrian	 *
267235289Sadrian	 * (I'm assuming that all supported media types for a given
268235289Sadrian	 * interface will be the same top-level type..)
269235289Sadrian	 */
270235289Sadrian	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
271235289Sadrian
272235289Sadrian	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
273235289Sadrian	ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
274235289Sadrian	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
275235289Sadrian
276235289Sadrian	ifmr->ifm_current = ifr.ifr_media;
277235289Sadrian	callback_register(setifmediacallback, (void *)ifmr);
278235289Sadrian}
279235289Sadrian
280235289Sadrianstatic void
281235289Sadriansetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
282235289Sadrian{
283235289Sadrian
284235289Sadrian	domediaopt(val, 0, s);
285235289Sadrian}
286235289Sadrian
287235289Sadrianstatic void
288235289Sadrianunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
289235289Sadrian{
290235289Sadrian
291235289Sadrian	domediaopt(val, 1, s);
292235289Sadrian}
293235289Sadrian
294235289Sadrianstatic void
295235289Sadriandomediaopt(const char *val, int clear, int s)
296235289Sadrian{
297235289Sadrian	struct ifmediareq *ifmr;
298235289Sadrian	int options;
299235289Sadrian
300235289Sadrian	ifmr = ifmedia_getstate(s);
301235289Sadrian
302235289Sadrian	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
303235289Sadrian
304235289Sadrian	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
305235289Sadrian	ifr.ifr_media = ifmr->ifm_current;
306235289Sadrian	if (clear)
307235289Sadrian		ifr.ifr_media &= ~options;
308235289Sadrian	else {
309235289Sadrian		if (options & IFM_HDX) {
310235289Sadrian			ifr.ifr_media &= ~IFM_FDX;
311235289Sadrian			options &= ~IFM_HDX;
312235289Sadrian		}
313235289Sadrian		ifr.ifr_media |= options;
314235289Sadrian	}
315235289Sadrian	ifmr->ifm_current = ifr.ifr_media;
316235289Sadrian	callback_register(setifmediacallback, (void *)ifmr);
317235289Sadrian}
318235289Sadrian
319235289Sadrianstatic void
320235289Sadriansetmediainst(const char *val, int d, int s, const struct afswtch *afp)
321235289Sadrian{
322235289Sadrian	struct ifmediareq *ifmr;
323235289Sadrian	int inst;
324235289Sadrian
325235289Sadrian	ifmr = ifmedia_getstate(s);
326235289Sadrian
327235289Sadrian	inst = atoi(val);
328235289Sadrian	if (inst < 0 || inst > (int)IFM_INST_MAX)
329235289Sadrian		errx(1, "invalid media instance: %s", val);
330235289Sadrian
331235289Sadrian	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
332235289Sadrian	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
333235289Sadrian
334235289Sadrian	ifmr->ifm_current = ifr.ifr_media;
335235289Sadrian	callback_register(setifmediacallback, (void *)ifmr);
336235289Sadrian}
337235289Sadrian
338235289Sadrianstatic void
339235289Sadriansetmediamode(const char *val, int d, int s, const struct afswtch *afp)
340235289Sadrian{
341235289Sadrian	struct ifmediareq *ifmr;
342235289Sadrian	int mode;
343235289Sadrian
344235289Sadrian	ifmr = ifmedia_getstate(s);
345235289Sadrian
346235289Sadrian	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
347235289Sadrian
348235289Sadrian	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
349235289Sadrian	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
350235289Sadrian
351235289Sadrian	ifmr->ifm_current = ifr.ifr_media;
352235289Sadrian	callback_register(setifmediacallback, (void *)ifmr);
353235289Sadrian}
354235289Sadrian#endif
355235289Sadrian
356235289Sadrian/**********************************************************************
357235289Sadrian * A good chunk of this is duplicated from sys/net/ifmedia.c
358235289Sadrian **********************************************************************/
359235289Sadrian
360235289Sadrianstatic struct ifmedia_description ifm_type_descriptions[] =
361235289Sadrian    IFM_TYPE_DESCRIPTIONS;
362235289Sadrian
363235289Sadrianstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
364235289Sadrian    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
365235289Sadrian
366235289Sadrianstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] =
367235289Sadrian    IFM_SUBTYPE_ETHERNET_ALIASES;
368235289Sadrian
369235289Sadrianstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
370235289Sadrian    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
371235289Sadrian
372235289Sadrianstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
373235289Sadrian    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
374235289Sadrian
375235289Sadrianstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] =
376235289Sadrian    IFM_SUBTYPE_TOKENRING_ALIASES;
377235289Sadrian
378235289Sadrianstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
379235289Sadrian    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
380235289Sadrian
381235289Sadrianstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] =
382235289Sadrian    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
383235289Sadrian
384235289Sadrianstatic struct ifmedia_description ifm_subtype_fddi_aliases[] =
385235289Sadrian    IFM_SUBTYPE_FDDI_ALIASES;
386235289Sadrian
387235289Sadrianstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
388235289Sadrian    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
389235289Sadrian
390235289Sadrianstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
391235289Sadrian    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
392235289Sadrian
393235289Sadrianstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
394235289Sadrian    IFM_SUBTYPE_IEEE80211_ALIASES;
395235289Sadrian
396235289Sadrianstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
397235289Sadrian    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
398235289Sadrian
399241720Sedstatic struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
400235289Sadrian    IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
401235289Sadrian
402241720Sedstatic struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
403235289Sadrian    IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
404235289Sadrian
405235289Sadrianstatic struct ifmedia_description ifm_subtype_atm_descriptions[] =
406235289Sadrian    IFM_SUBTYPE_ATM_DESCRIPTIONS;
407235289Sadrian
408235289Sadrianstatic struct ifmedia_description ifm_subtype_atm_aliases[] =
409235289Sadrian    IFM_SUBTYPE_ATM_ALIASES;
410235289Sadrian
411235289Sadrianstatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
412235289Sadrian    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
413235289Sadrian
414235289Sadrianstatic struct ifmedia_description ifm_subtype_shared_descriptions[] =
415235289Sadrian    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
416235289Sadrian
417235289Sadrianstatic struct ifmedia_description ifm_subtype_shared_aliases[] =
418235289Sadrian    IFM_SUBTYPE_SHARED_ALIASES;
419235289Sadrian
420235289Sadrianstatic struct ifmedia_description ifm_shared_option_descriptions[] =
421235289Sadrian    IFM_SHARED_OPTION_DESCRIPTIONS;
422235289Sadrian
423235289Sadrianstatic struct ifmedia_description ifm_shared_option_aliases[] =
424235289Sadrian    IFM_SHARED_OPTION_ALIASES;
425235289Sadrian
426235289Sadrianstruct ifmedia_type_to_subtype {
427235289Sadrian	struct {
428235289Sadrian		struct ifmedia_description *desc;
429235289Sadrian		int alias;
430235289Sadrian	} subtypes[5];
431235289Sadrian	struct {
432235289Sadrian		struct ifmedia_description *desc;
433235289Sadrian		int alias;
434235289Sadrian	} options[4];
435235289Sadrian	struct {
436235289Sadrian		struct ifmedia_description *desc;
437235289Sadrian		int alias;
438235289Sadrian	} modes[3];
439235289Sadrian};
440235289Sadrian
441235289Sadrian/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
442235289Sadrianstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
443235289Sadrian	{
444235289Sadrian		{
445235289Sadrian			{ &ifm_subtype_shared_descriptions[0], 0 },
446235289Sadrian			{ &ifm_subtype_shared_aliases[0], 1 },
447235289Sadrian			{ &ifm_subtype_ethernet_descriptions[0], 0 },
448235289Sadrian			{ &ifm_subtype_ethernet_aliases[0], 1 },
449235289Sadrian			{ NULL, 0 },
450235289Sadrian		},
451235289Sadrian		{
452235289Sadrian			{ &ifm_shared_option_descriptions[0], 0 },
453235289Sadrian			{ &ifm_shared_option_aliases[0], 1 },
454235289Sadrian			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
455235289Sadrian			{ NULL, 0 },
456235289Sadrian		},
457235289Sadrian		{
458235289Sadrian			{ NULL, 0 },
459235289Sadrian		},
460235289Sadrian	},
461235289Sadrian	{
462235289Sadrian		{
463235289Sadrian			{ &ifm_subtype_shared_descriptions[0], 0 },
464235289Sadrian			{ &ifm_subtype_shared_aliases[0], 1 },
465235289Sadrian			{ &ifm_subtype_tokenring_descriptions[0], 0 },
466235289Sadrian			{ &ifm_subtype_tokenring_aliases[0], 1 },
467235289Sadrian			{ NULL, 0 },
468235289Sadrian		},
469235289Sadrian		{
470235289Sadrian			{ &ifm_shared_option_descriptions[0], 0 },
471235289Sadrian			{ &ifm_shared_option_aliases[0], 1 },
472235289Sadrian			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
473235289Sadrian			{ NULL, 0 },
474235289Sadrian		},
475235289Sadrian		{
476235289Sadrian			{ NULL, 0 },
477235289Sadrian		},
478235289Sadrian	},
479235289Sadrian	{
480235289Sadrian		{
481235289Sadrian			{ &ifm_subtype_shared_descriptions[0], 0 },
482235289Sadrian			{ &ifm_subtype_shared_aliases[0], 1 },
483235289Sadrian			{ &ifm_subtype_fddi_descriptions[0], 0 },
484235289Sadrian			{ &ifm_subtype_fddi_aliases[0], 1 },
485235289Sadrian			{ NULL, 0 },
486235289Sadrian		},
487235289Sadrian		{
488235289Sadrian			{ &ifm_shared_option_descriptions[0], 0 },
489235289Sadrian			{ &ifm_shared_option_aliases[0], 1 },
490235289Sadrian			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
491235289Sadrian			{ NULL, 0 },
492235289Sadrian		},
493235289Sadrian		{
494235289Sadrian			{ NULL, 0 },
495235289Sadrian		},
496235289Sadrian	},
497235289Sadrian	{
498235289Sadrian		{
499235289Sadrian			{ &ifm_subtype_shared_descriptions[0], 0 },
500235289Sadrian			{ &ifm_subtype_shared_aliases[0], 1 },
501235289Sadrian			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
502235289Sadrian			{ &ifm_subtype_ieee80211_aliases[0], 1 },
503235289Sadrian			{ NULL, 0 },
504235289Sadrian		},
505235289Sadrian		{
506235289Sadrian			{ &ifm_shared_option_descriptions[0], 0 },
507235289Sadrian			{ &ifm_shared_option_aliases[0], 1 },
508235289Sadrian			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
509235289Sadrian			{ NULL, 0 },
510235289Sadrian		},
511235289Sadrian		{
512235289Sadrian			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
513235289Sadrian			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
514235289Sadrian			{ NULL, 0 },
515235289Sadrian		},
516235289Sadrian	},
517235289Sadrian	{
518235289Sadrian		{
519235289Sadrian			{ &ifm_subtype_shared_descriptions[0], 0 },
520235289Sadrian			{ &ifm_subtype_shared_aliases[0], 1 },
521235289Sadrian			{ &ifm_subtype_atm_descriptions[0], 0 },
522235289Sadrian			{ &ifm_subtype_atm_aliases[0], 1 },
523235289Sadrian			{ NULL, 0 },
524235289Sadrian		},
525235289Sadrian		{
526235289Sadrian			{ &ifm_shared_option_descriptions[0], 0 },
527235289Sadrian			{ &ifm_shared_option_aliases[0], 1 },
528235289Sadrian			{ &ifm_subtype_atm_option_descriptions[0], 0 },
529235289Sadrian			{ NULL, 0 },
530235289Sadrian		},
531235289Sadrian		{
532235289Sadrian			{ NULL, 0 },
533235289Sadrian		},
534235289Sadrian	},
535235289Sadrian};
536235289Sadrian
537235289Sadrianint
538235289Sadrianget_media_subtype(int type, const char *val)
539235289Sadrian{
540235289Sadrian	struct ifmedia_description *desc;
541235289Sadrian	struct ifmedia_type_to_subtype *ttos;
542235289Sadrian	int rval, i;
543235289Sadrian
544235289Sadrian	/* Find the top-level interface type. */
545235289Sadrian	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
546235289Sadrian	    desc->ifmt_string != NULL; desc++, ttos++)
547235289Sadrian		if (type == desc->ifmt_word)
548235289Sadrian			break;
549235289Sadrian	if (desc->ifmt_string == NULL)
550235289Sadrian		errx(1, "unknown media type 0x%x", type);
551235289Sadrian
552235289Sadrian	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
553235289Sadrian		rval = lookup_media_word(ttos->subtypes[i].desc, val);
554235289Sadrian		if (rval != -1)
555235289Sadrian			return (rval);
556235289Sadrian	}
557235289Sadrian	errx(1, "unknown media subtype: %s", val);
558235289Sadrian	/*NOTREACHED*/
559235289Sadrian}
560235289Sadrian
561235289Sadrianint
562235289Sadrianget_media_mode(int type, const char *val)
563235289Sadrian{
564235289Sadrian	struct ifmedia_description *desc;
565235289Sadrian	struct ifmedia_type_to_subtype *ttos;
566235289Sadrian	int rval, i;
567235289Sadrian
568235289Sadrian	/* Find the top-level interface type. */
569235289Sadrian	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
570235289Sadrian	    desc->ifmt_string != NULL; desc++, ttos++)
571235289Sadrian		if (type == desc->ifmt_word)
572235289Sadrian			break;
573235289Sadrian	if (desc->ifmt_string == NULL)
574235289Sadrian		errx(1, "unknown media mode 0x%x", type);
575235289Sadrian
576235289Sadrian	for (i = 0; ttos->modes[i].desc != NULL; i++) {
577235289Sadrian		rval = lookup_media_word(ttos->modes[i].desc, val);
578235289Sadrian		if (rval != -1)
579235289Sadrian			return (rval);
580235289Sadrian	}
581235289Sadrian	return -1;
582235289Sadrian}
583235289Sadrian
584235289Sadrianint
585235289Sadrianget_media_options(int type, const char *val)
586235289Sadrian{
587235289Sadrian	struct ifmedia_description *desc;
588235289Sadrian	struct ifmedia_type_to_subtype *ttos;
589235289Sadrian	char *optlist, *optptr;
590235289Sadrian	int option = 0, i, rval = 0;
591235289Sadrian
592235289Sadrian	/* We muck with the string, so copy it. */
593235289Sadrian	optlist = strdup(val);
594235289Sadrian	if (optlist == NULL)
595235289Sadrian		err(1, "strdup");
596235289Sadrian
597235289Sadrian	/* Find the top-level interface type. */
598235289Sadrian	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
599235289Sadrian	    desc->ifmt_string != NULL; desc++, ttos++)
600235289Sadrian		if (type == desc->ifmt_word)
601235289Sadrian			break;
602235289Sadrian	if (desc->ifmt_string == NULL)
603235289Sadrian		errx(1, "unknown media type 0x%x", type);
604235289Sadrian
605235289Sadrian	/*
606235289Sadrian	 * Look up the options in the user-provided comma-separated
607235289Sadrian	 * list.
608235289Sadrian	 */
609235289Sadrian	optptr = optlist;
610235289Sadrian	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
611235289Sadrian		for (i = 0; ttos->options[i].desc != NULL; i++) {
612235289Sadrian			option = lookup_media_word(ttos->options[i].desc, optptr);
613235289Sadrian			if (option != -1)
614235289Sadrian				break;
615235289Sadrian		}
616235289Sadrian		if (option == 0)
617235289Sadrian			errx(1, "unknown option: %s", optptr);
618235289Sadrian		rval |= option;
619235289Sadrian	}
620235289Sadrian
621235289Sadrian	free(optlist);
622235289Sadrian	return (rval);
623235289Sadrian}
624235289Sadrian
625235289Sadrianint
626235289Sadrianlookup_media_word(struct ifmedia_description *desc, const char *val)
627235289Sadrian{
628235289Sadrian
629235289Sadrian	for (; desc->ifmt_string != NULL; desc++)
630235289Sadrian		if (strcasecmp(desc->ifmt_string, val) == 0)
631235289Sadrian			return (desc->ifmt_word);
632235289Sadrian
633235289Sadrian	return (-1);
634235289Sadrian}
635235289Sadrian
636235289Sadrianstatic struct ifmedia_description *get_toptype_desc(int ifmw)
637235289Sadrian{
638235289Sadrian	struct ifmedia_description *desc;
639235289Sadrian
640235289Sadrian	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
641235289Sadrian		if (IFM_TYPE(ifmw) == desc->ifmt_word)
642235289Sadrian			break;
643235289Sadrian
644235289Sadrian	return desc;
645235289Sadrian}
646235289Sadrian
647235289Sadrianstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
648235289Sadrian{
649235289Sadrian	struct ifmedia_description *desc;
650235289Sadrian	struct ifmedia_type_to_subtype *ttos;
651235289Sadrian
652235289Sadrian	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
653235289Sadrian	    desc->ifmt_string != NULL; desc++, ttos++)
654235289Sadrian		if (IFM_TYPE(ifmw) == desc->ifmt_word)
655235289Sadrian			break;
656235289Sadrian
657235289Sadrian	return ttos;
658235289Sadrian}
659235289Sadrian
660235289Sadrianstatic struct ifmedia_description *get_subtype_desc(int ifmw,
661235289Sadrian    struct ifmedia_type_to_subtype *ttos)
662235289Sadrian{
663235289Sadrian	int i;
664235289Sadrian	struct ifmedia_description *desc;
665235289Sadrian
666235289Sadrian	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
667235289Sadrian		if (ttos->subtypes[i].alias)
668235289Sadrian			continue;
669235289Sadrian		for (desc = ttos->subtypes[i].desc;
670235289Sadrian		    desc->ifmt_string != NULL; desc++) {
671235289Sadrian			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
672235289Sadrian				return desc;
673235289Sadrian		}
674235289Sadrian	}
675235289Sadrian
676235289Sadrian	return NULL;
677235289Sadrian}
678235289Sadrian
679235289Sadrianstatic struct ifmedia_description *get_mode_desc(int ifmw,
680235289Sadrian    struct ifmedia_type_to_subtype *ttos)
681235289Sadrian{
682235289Sadrian	int i;
683235289Sadrian	struct ifmedia_description *desc;
684235289Sadrian
685235289Sadrian	for (i = 0; ttos->modes[i].desc != NULL; i++) {
686235289Sadrian		if (ttos->modes[i].alias)
687235289Sadrian			continue;
688235289Sadrian		for (desc = ttos->modes[i].desc;
689235289Sadrian		    desc->ifmt_string != NULL; desc++) {
690235289Sadrian			if (IFM_MODE(ifmw) == desc->ifmt_word)
691235289Sadrian				return desc;
692235289Sadrian		}
693235289Sadrian	}
694235289Sadrian
695235289Sadrian	return NULL;
696235289Sadrian}
697235289Sadrian
698235289Sadrianvoid
699235289Sadrianprint_media_word(int ifmw, int print_toptype)
700235289Sadrian{
701235289Sadrian	struct ifmedia_description *desc;
702235289Sadrian	struct ifmedia_type_to_subtype *ttos;
703235289Sadrian	int seen_option = 0, i;
704235289Sadrian
705235289Sadrian	/* Find the top-level interface type. */
706235289Sadrian	desc = get_toptype_desc(ifmw);
707235289Sadrian	ttos = get_toptype_ttos(ifmw);
708235289Sadrian	if (desc->ifmt_string == NULL) {
709235289Sadrian		printf("<unknown type>");
710235289Sadrian		return;
711235289Sadrian	} else if (print_toptype) {
712235289Sadrian		printf("%s", desc->ifmt_string);
713235289Sadrian	}
714235289Sadrian
715235289Sadrian	/*
716235289Sadrian	 * Don't print the top-level type; it's not like we can
717235289Sadrian	 * change it, or anything.
718235289Sadrian	 */
719235289Sadrian
720235289Sadrian	/* Find subtype. */
721235289Sadrian	desc = get_subtype_desc(ifmw, ttos);
722235289Sadrian	if (desc == NULL) {
723235289Sadrian		printf("<unknown subtype>");
724235289Sadrian		return;
725235289Sadrian	}
726235289Sadrian
727235289Sadrian	if (print_toptype)
728235289Sadrian		putchar(' ');
729235289Sadrian
730235289Sadrian	printf("%s", desc->ifmt_string);
731235289Sadrian
732235289Sadrian	if (print_toptype) {
733235289Sadrian		desc = get_mode_desc(ifmw, ttos);
734235289Sadrian		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
735235289Sadrian			printf(" mode %s", desc->ifmt_string);
736235289Sadrian	}
737235289Sadrian
738235289Sadrian	/* Find options. */
739235289Sadrian	for (i = 0; ttos->options[i].desc != NULL; i++) {
740235289Sadrian		if (ttos->options[i].alias)
741235289Sadrian			continue;
742235289Sadrian		for (desc = ttos->options[i].desc;
743235289Sadrian		    desc->ifmt_string != NULL; desc++) {
744235289Sadrian			if (ifmw & desc->ifmt_word) {
745235289Sadrian				if (seen_option == 0)
746235289Sadrian					printf(" <");
747235289Sadrian				printf("%s%s", seen_option++ ? "," : "",
748235289Sadrian				    desc->ifmt_string);
749235289Sadrian			}
750235289Sadrian		}
751235289Sadrian	}
752235289Sadrian	printf("%s", seen_option ? ">" : "");
753235289Sadrian
754235289Sadrian	if (print_toptype && IFM_INST(ifmw) != 0)
755235289Sadrian		printf(" instance %d", IFM_INST(ifmw));
756235289Sadrian}
757235289Sadrian
758235289Sadrianvoid
759235289Sadrianprint_media_word_ifconfig(int ifmw)
760235289Sadrian{
761235289Sadrian	struct ifmedia_description *desc;
762235289Sadrian	struct ifmedia_type_to_subtype *ttos;
763235289Sadrian	int seen_option = 0, i;
764235289Sadrian
765235289Sadrian	/* Find the top-level interface type. */
766235289Sadrian	desc = get_toptype_desc(ifmw);
767235289Sadrian	ttos = get_toptype_ttos(ifmw);
768235289Sadrian	if (desc->ifmt_string == NULL) {
769235289Sadrian		printf("<unknown type>");
770235289Sadrian		return;
771235289Sadrian	}
772235289Sadrian
773235289Sadrian	/*
774235289Sadrian	 * Don't print the top-level type; it's not like we can
775235289Sadrian	 * change it, or anything.
776235289Sadrian	 */
777235289Sadrian
778235289Sadrian	/* Find subtype. */
779235289Sadrian	desc = get_subtype_desc(ifmw, ttos);
780235289Sadrian	if (desc == NULL) {
781235289Sadrian		printf("<unknown subtype>");
782235289Sadrian		return;
783235289Sadrian	}
784235289Sadrian
785235289Sadrian	printf("media %s", desc->ifmt_string);
786235289Sadrian
787235289Sadrian	desc = get_mode_desc(ifmw, ttos);
788235289Sadrian	if (desc != NULL)
789235289Sadrian		printf(" mode %s", desc->ifmt_string);
790235289Sadrian
791235289Sadrian	/* Find options. */
792235289Sadrian	for (i = 0; ttos->options[i].desc != NULL; i++) {
793235289Sadrian		if (ttos->options[i].alias)
794235289Sadrian			continue;
795235289Sadrian		for (desc = ttos->options[i].desc;
796235289Sadrian		    desc->ifmt_string != NULL; desc++) {
797235289Sadrian			if (ifmw & desc->ifmt_word) {
798235289Sadrian				if (seen_option == 0)
799235289Sadrian					printf(" mediaopt ");
800235289Sadrian				printf("%s%s", seen_option++ ? "," : "",
801235289Sadrian				    desc->ifmt_string);
802235289Sadrian			}
803235289Sadrian		}
804235289Sadrian	}
805235289Sadrian
806235289Sadrian	if (IFM_INST(ifmw) != 0)
807235289Sadrian		printf(" instance %d", IFM_INST(ifmw));
808235289Sadrian}
809235289Sadrian
810235289Sadrian/**********************************************************************
811235289Sadrian * ...until here.
812235289Sadrian **********************************************************************/
813