1139804Simp/*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
2139013Sdavidxu/* $FreeBSD$ */
3112904Sjeff
4112904Sjeff/*
5112904Sjeff * Copyright (c) 1997 Jason R. Thorpe.
6112904Sjeff * All rights reserved.
7112904Sjeff *
8112904Sjeff * Redistribution and use in source and binary forms, with or without
9112904Sjeff * modification, are permitted provided that the following conditions
10112904Sjeff * are met:
11112904Sjeff * 1. Redistributions of source code must retain the above copyright
12112904Sjeff *    notice, this list of conditions and the following disclaimer.
13112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright
14112904Sjeff *    notice, this list of conditions and the following disclaimer in the
15112904Sjeff *    documentation and/or other materials provided with the distribution.
16112904Sjeff * 3. All advertising materials mentioning features or use of this software
17112904Sjeff *    must display the following acknowledgement:
18112904Sjeff *      This product includes software developed for the NetBSD Project
19112904Sjeff *	by Jason R. Thorpe.
20112904Sjeff * 4. The name of the author may not be used to endorse or promote products
21112904Sjeff *    derived from this software without specific prior written permission.
22112904Sjeff *
23112904Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24112904Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25112904Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26112904Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27112904Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28116182Sobrien * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29116182Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30116182Sobrien * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31162536Sdavidxu * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32112904Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33112904Sjeff * SUCH DAMAGE.
34131431Smarcel */
35112904Sjeff
36115765Sjeff/*
37112904Sjeff * Copyright (c) 1983, 1993
38164033Srwatson *	The Regents of the University of California.  All rights reserved.
39112904Sjeff *
40161678Sdavidxu * Redistribution and use in source and binary forms, with or without
41165369Sdavidxu * modification, are permitted provided that the following conditions
42161678Sdavidxu * are met:
43112904Sjeff * 1. Redistributions of source code must retain the above copyright
44112904Sjeff *    notice, this list of conditions and the following disclaimer.
45112904Sjeff * 2. Redistributions in binary form must reproduce the above copyright
46216641Sdavidxu *    notice, this list of conditions and the following disclaimer in the
47139013Sdavidxu *    documentation and/or other materials provided with the distribution.
48112904Sjeff * 4. Neither the name of the University nor the names of its contributors
49112904Sjeff *    may be used to endorse or promote products derived from this software
50139013Sdavidxu *    without specific prior written permission.
51139013Sdavidxu *
52139013Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53139013Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54139013Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55139013Sdavidxu * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56165369Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57165369Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58205014Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59162536Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60162536Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61162536Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62179970Sdavidxu * SUCH DAMAGE.
63179970Sdavidxu */
64179970Sdavidxu/*
65161678Sdavidxu * based on sbin/ifconfig/ifmedia.c r221954
66161678Sdavidxu */
67161678Sdavidxu
68161678Sdavidxu#include <sys/param.h>
69161678Sdavidxu#include <sys/ioctl.h>
70161678Sdavidxu#include <sys/socket.h>
71161678Sdavidxu#include <sys/sysctl.h>
72161678Sdavidxu#include <sys/time.h>
73161678Sdavidxu
74161678Sdavidxu#include <net/if.h>
75161678Sdavidxu#include <net/if_dl.h>
76161678Sdavidxu#include <net/if_types.h>
77161678Sdavidxu#include <net/if_media.h>
78161678Sdavidxu#include <net/route.h>
79161678Sdavidxu
80161678Sdavidxu#include <ctype.h>
81161678Sdavidxu#include <err.h>
82161678Sdavidxu#include <errno.h>
83161678Sdavidxu#include <fcntl.h>
84161678Sdavidxu#include <stdio.h>
85161678Sdavidxu#include <stdlib.h>
86161678Sdavidxu#include <string.h>
87115765Sjeff#include <unistd.h>
88161678Sdavidxu
89161678Sdavidxuvoid	domediaopt(const char *, int, int);
90161678Sdavidxuint	get_media_subtype(int, const char *);
91161678Sdavidxuint	get_media_mode(int, const char *);
92161678Sdavidxuint	get_media_options(int, const char *);
93161678Sdavidxuint	lookup_media_word(struct ifmedia_description *, const char *);
94161678Sdavidxuvoid	print_media_word(int, int);
95161678Sdavidxuvoid	print_media_word_ifconfig(int);
96161678Sdavidxu
97161678Sdavidxu#if 0
98161678Sdavidxustatic struct ifmedia_description *get_toptype_desc(int);
99161678Sdavidxustatic struct ifmedia_type_to_subtype *get_toptype_ttos(int);
100161678Sdavidxustatic struct ifmedia_description *get_subtype_desc(int,
101161678Sdavidxu    struct ifmedia_type_to_subtype *ttos);
102161678Sdavidxu
103170300Sjeff#define	IFM_OPMODE(x) \
104170300Sjeff	((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
105161678Sdavidxu	 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
106161678Sdavidxu	 IFM_IEEE80211_MBSS))
107161678Sdavidxu#define	IFM_IEEE80211_STA	0
108161678Sdavidxu
109161678Sdavidxustatic void
110161678Sdavidxumedia_status(int s)
111161678Sdavidxu{
112161678Sdavidxu	struct ifmediareq ifmr;
113161678Sdavidxu	int *media_list, i;
114161742Sdavidxu
115161678Sdavidxu	(void) memset(&ifmr, 0, sizeof(ifmr));
116201991Sdavidxu	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
117201991Sdavidxu
118201991Sdavidxu	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
119201991Sdavidxu		/*
120201991Sdavidxu		 * Interface doesn't support SIOC{G,S}IFMEDIA.
121201991Sdavidxu		 */
122115765Sjeff		return;
123115765Sjeff	}
124161678Sdavidxu
125161678Sdavidxu	if (ifmr.ifm_count == 0) {
126201991Sdavidxu		warnx("%s: no media types?", name);
127201991Sdavidxu		return;
128201991Sdavidxu	}
129201991Sdavidxu
130201991Sdavidxu	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
131201991Sdavidxu	if (media_list == NULL)
132201991Sdavidxu		err(1, "malloc");
133201991Sdavidxu	ifmr.ifm_ulist = media_list;
134201991Sdavidxu
135201991Sdavidxu	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
136161678Sdavidxu		err(1, "SIOCGIFMEDIA");
137138224Sdavidxu
138161678Sdavidxu	printf("\tmedia: ");
139161678Sdavidxu	print_media_word(ifmr.ifm_current, 1);
140161678Sdavidxu	if (ifmr.ifm_active != ifmr.ifm_current) {
141161678Sdavidxu		putchar(' ');
142201991Sdavidxu		putchar('(');
143177848Sdavidxu		print_media_word(ifmr.ifm_active, 0);
144177848Sdavidxu		putchar(')');
145161678Sdavidxu	}
146201991Sdavidxu
147201991Sdavidxu	putchar('\n');
148161678Sdavidxu
149161678Sdavidxu	if (ifmr.ifm_status & IFM_AVALID) {
150161678Sdavidxu		printf("\tstatus: ");
151161678Sdavidxu		switch (IFM_TYPE(ifmr.ifm_active)) {
152158377Sdavidxu		case IFM_ETHER:
153161678Sdavidxu		case IFM_ATM:
154161678Sdavidxu			if (ifmr.ifm_status & IFM_ACTIVE)
155161678Sdavidxu				printf("active");
156201991Sdavidxu			else
157138224Sdavidxu				printf("no carrier");
158115765Sjeff			break;
159161678Sdavidxu
160189756Sdavidxu		case IFM_FDDI:
161161678Sdavidxu		case IFM_TOKEN:
162161678Sdavidxu			if (ifmr.ifm_status & IFM_ACTIVE)
163161678Sdavidxu				printf("inserted");
164161678Sdavidxu			else
165161678Sdavidxu				printf("no ring");
166161678Sdavidxu			break;
167161678Sdavidxu
168161678Sdavidxu		case IFM_IEEE80211:
169161678Sdavidxu			if (ifmr.ifm_status & IFM_ACTIVE) {
170161678Sdavidxu				/* NB: only sta mode associates */
171163709Sjb				if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
172163709Sjb					printf("associated");
173163709Sjb				else
174161678Sdavidxu					printf("running");
175138224Sdavidxu			} else
176216678Sdavidxu				printf("no carrier");
177216678Sdavidxu			break;
178115765Sjeff		}
179161678Sdavidxu		putchar('\n');
180161678Sdavidxu	}
181161678Sdavidxu
182177848Sdavidxu	if (ifmr.ifm_count > 0 && supmedia) {
183177848Sdavidxu		printf("\tsupported media:\n");
184161678Sdavidxu		for (i = 0; i < ifmr.ifm_count; i++) {
185179421Sdavidxu			printf("\t\t");
186138224Sdavidxu			print_media_word_ifconfig(media_list[i]);
187161678Sdavidxu			putchar('\n');
188115310Sjeff		}
189161678Sdavidxu	}
190161678Sdavidxu
191161678Sdavidxu	free(media_list);
192161678Sdavidxu}
193161678Sdavidxu
194161678Sdavidxustruct ifmediareq *
195161678Sdavidxuifmedia_getstate(int s)
196139013Sdavidxu{
197139013Sdavidxu	static struct ifmediareq *ifmr = NULL;
198139257Sdavidxu	int *mwords;
199139257Sdavidxu
200177848Sdavidxu	if (ifmr == NULL) {
201177848Sdavidxu		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
202161678Sdavidxu		if (ifmr == NULL)
203139257Sdavidxu			err(1, "malloc");
204163697Sdavidxu
205161678Sdavidxu		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
206161678Sdavidxu		(void) strncpy(ifmr->ifm_name, name,
207161678Sdavidxu		    sizeof(ifmr->ifm_name));
208161678Sdavidxu
209161678Sdavidxu		ifmr->ifm_count = 0;
210161678Sdavidxu		ifmr->ifm_ulist = NULL;
211115310Sjeff
212177848Sdavidxu		/*
213177848Sdavidxu		 * We must go through the motions of reading all
214177848Sdavidxu		 * supported media because we need to know both
215177848Sdavidxu		 * the current media type and the top-level type.
216170300Sjeff		 */
217170300Sjeff
218161678Sdavidxu		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
219161678Sdavidxu			err(1, "SIOCGIFMEDIA");
220161678Sdavidxu		}
221179421Sdavidxu
222138224Sdavidxu		if (ifmr->ifm_count == 0)
223161678Sdavidxu			errx(1, "%s: no media types?", name);
224161678Sdavidxu
225179421Sdavidxu		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
226179421Sdavidxu		if (mwords == NULL)
227179421Sdavidxu			err(1, "malloc");
228179421Sdavidxu
229201991Sdavidxu		ifmr->ifm_ulist = mwords;
230201991Sdavidxu		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
231201991Sdavidxu			err(1, "SIOCGIFMEDIA");
232179421Sdavidxu	}
233179421Sdavidxu
234179421Sdavidxu	return ifmr;
235179421Sdavidxu}
236161678Sdavidxu
237170300Sjeffstatic void
238161678Sdavidxusetifmediacallback(int s, void *arg)
239161678Sdavidxu{
240161678Sdavidxu	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
241161678Sdavidxu	static int did_it = 0;
242143149Sdavidxu
243143149Sdavidxu	if (!did_it) {
244143149Sdavidxu		ifr.ifr_media = ifmr->ifm_current;
245161678Sdavidxu		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
246161678Sdavidxu			err(1, "SIOCSIFMEDIA (media)");
247161678Sdavidxu		free(ifmr->ifm_ulist);
248201991Sdavidxu		free(ifmr);
249201991Sdavidxu		did_it = 1;
250161678Sdavidxu	}
251161678Sdavidxu}
252161678Sdavidxu
253143149Sdavidxustatic void
254143149Sdavidxusetmedia(const char *val, int d, int s, const struct afswtch *afp)
255143149Sdavidxu{
256143149Sdavidxu	struct ifmediareq *ifmr;
257143149Sdavidxu	int subtype;
258201991Sdavidxu
259201991Sdavidxu	ifmr = ifmedia_getstate(s);
260143149Sdavidxu
261143149Sdavidxu	/*
262143149Sdavidxu	 * We are primarily concerned with the top-level type.
263161678Sdavidxu	 * However, "current" may be only IFM_NONE, so we just look
264139013Sdavidxu	 * for the top-level type in the first "supported type"
265138224Sdavidxu	 * entry.
266161678Sdavidxu	 *
267161678Sdavidxu	 * (I'm assuming that all supported media types for a given
268138224Sdavidxu	 * interface will be the same top-level type..)
269138224Sdavidxu	 */
270161678Sdavidxu	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
271161678Sdavidxu
272139013Sdavidxu	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
273201886Sdavidxu	ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
274179421Sdavidxu	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
275179421Sdavidxu
276139013Sdavidxu	ifmr->ifm_current = ifr.ifr_media;
277139013Sdavidxu	callback_register(setifmediacallback, (void *)ifmr);
278161678Sdavidxu}
279177848Sdavidxu
280161678Sdavidxustatic void
281138224Sdavidxusetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
282177848Sdavidxu{
283139257Sdavidxu
284161678Sdavidxu	domediaopt(val, 0, s);
285139257Sdavidxu}
286161678Sdavidxu
287177848Sdavidxustatic void
288139257Sdavidxuunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
289139257Sdavidxu{
290161678Sdavidxu
291177848Sdavidxu	domediaopt(val, 1, s);
292161678Sdavidxu}
293139257Sdavidxu
294177848Sdavidxustatic void
295139257Sdavidxudomediaopt(const char *val, int clear, int s)
296161678Sdavidxu{
297139257Sdavidxu	struct ifmediareq *ifmr;
298161678Sdavidxu	int options;
299177848Sdavidxu
300139257Sdavidxu	ifmr = ifmedia_getstate(s);
301139257Sdavidxu
302161678Sdavidxu	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
303177848Sdavidxu
304177848Sdavidxu	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
305161678Sdavidxu	ifr.ifr_media = ifmr->ifm_current;
306139257Sdavidxu	if (clear)
307177848Sdavidxu		ifr.ifr_media &= ~options;
308138224Sdavidxu	else {
309161678Sdavidxu		if (options & IFM_HDX) {
310161678Sdavidxu			ifr.ifr_media &= ~IFM_FDX;
311161678Sdavidxu			options &= ~IFM_HDX;
312177848Sdavidxu		}
313177848Sdavidxu		ifr.ifr_media |= options;
314177880Sdavidxu	}
315177880Sdavidxu	ifmr->ifm_current = ifr.ifr_media;
316177880Sdavidxu	callback_register(setifmediacallback, (void *)ifmr);
317177880Sdavidxu}
318177880Sdavidxu
319177880Sdavidxustatic void
320177880Sdavidxusetmediainst(const char *val, int d, int s, const struct afswtch *afp)
321177880Sdavidxu{
322177880Sdavidxu	struct ifmediareq *ifmr;
323177848Sdavidxu	int inst;
324177880Sdavidxu
325177880Sdavidxu	ifmr = ifmedia_getstate(s);
326177848Sdavidxu
327177848Sdavidxu	inst = atoi(val);
328177848Sdavidxu	if (inst < 0 || inst > (int)IFM_INST_MAX)
329177848Sdavidxu		errx(1, "invalid media instance: %s", val);
330177848Sdavidxu
331177848Sdavidxu	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
332138224Sdavidxu	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
333138224Sdavidxu
334161678Sdavidxu	ifmr->ifm_current = ifr.ifr_media;
335177848Sdavidxu	callback_register(setifmediacallback, (void *)ifmr);
336161678Sdavidxu}
337138225Sdavidxu
338177848Sdavidxustatic void
339138224Sdavidxusetmediamode(const char *val, int d, int s, const struct afswtch *afp)
340161678Sdavidxu{
341161678Sdavidxu	struct ifmediareq *ifmr;
342161678Sdavidxu	int mode;
343177848Sdavidxu
344177848Sdavidxu	ifmr = ifmedia_getstate(s);
345177848Sdavidxu
346177848Sdavidxu	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
347177848Sdavidxu
348138224Sdavidxu	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
349138224Sdavidxu	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
350201991Sdavidxu
351201991Sdavidxu	ifmr->ifm_current = ifr.ifr_media;
352201991Sdavidxu	callback_register(setifmediacallback, (void *)ifmr);
353201991Sdavidxu}
354201991Sdavidxu#endif
355201991Sdavidxu
356201991Sdavidxu/**********************************************************************
357201991Sdavidxu * A good chunk of this is duplicated from sys/net/ifmedia.c
358201991Sdavidxu **********************************************************************/
359201991Sdavidxu
360201991Sdavidxustatic struct ifmedia_description ifm_type_descriptions[] =
361201991Sdavidxu    IFM_TYPE_DESCRIPTIONS;
362201991Sdavidxu
363201991Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
364201991Sdavidxu    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
365201991Sdavidxu
366139013Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_aliases[] =
367177848Sdavidxu    IFM_SUBTYPE_ETHERNET_ALIASES;
368115765Sjeff
369201991Sdavidxustatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
370161678Sdavidxu    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
371139013Sdavidxu
372161678Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
373161678Sdavidxu    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
374201991Sdavidxu
375203744Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_aliases[] =
376201991Sdavidxu    IFM_SUBTYPE_TOKENRING_ALIASES;
377201991Sdavidxu
378201991Sdavidxustatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
379201991Sdavidxu    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
380201991Sdavidxu
381201991Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_descriptions[] =
382201991Sdavidxu    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
383201991Sdavidxu
384201991Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_aliases[] =
385201991Sdavidxu    IFM_SUBTYPE_FDDI_ALIASES;
386201991Sdavidxu
387158718Sdavidxustatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
388201991Sdavidxu    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
389201991Sdavidxu
390139013Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
391139013Sdavidxu    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
392139013Sdavidxu
393177848Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
394139013Sdavidxu    IFM_SUBTYPE_IEEE80211_ALIASES;
395161678Sdavidxu
396201991Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
397161678Sdavidxu    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
398161678Sdavidxu
399161678Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
400158718Sdavidxu    IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
401201991Sdavidxu
402201991Sdavidxustatic struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
403201991Sdavidxu    IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
404158718Sdavidxu
405201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_descriptions[] =
406201991Sdavidxu    IFM_SUBTYPE_ATM_DESCRIPTIONS;
407201991Sdavidxu
408201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_aliases[] =
409201991Sdavidxu    IFM_SUBTYPE_ATM_ALIASES;
410201991Sdavidxu
411201991Sdavidxustatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
412201991Sdavidxu    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
413201991Sdavidxu
414201991Sdavidxustatic struct ifmedia_description ifm_subtype_shared_descriptions[] =
415201991Sdavidxu    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
416139013Sdavidxu
417139013Sdavidxustatic struct ifmedia_description ifm_subtype_shared_aliases[] =
418139013Sdavidxu    IFM_SUBTYPE_SHARED_ALIASES;
419161678Sdavidxu
420161678Sdavidxustatic struct ifmedia_description ifm_shared_option_descriptions[] =
421161678Sdavidxu    IFM_SHARED_OPTION_DESCRIPTIONS;
422139013Sdavidxu
423139013Sdavidxustatic struct ifmedia_description ifm_shared_option_aliases[] =
424139013Sdavidxu    IFM_SHARED_OPTION_ALIASES;
425161678Sdavidxu
426201991Sdavidxustruct ifmedia_type_to_subtype {
427115765Sjeff	struct {
428161678Sdavidxu		struct ifmedia_description *desc;
429161678Sdavidxu		int alias;
430201991Sdavidxu	} subtypes[5];
431201991Sdavidxu	struct {
432201991Sdavidxu		struct ifmedia_description *desc;
433201991Sdavidxu		int alias;
434115765Sjeff	} options[4];
435115765Sjeff	struct {
436161678Sdavidxu		struct ifmedia_description *desc;
437161678Sdavidxu		int alias;
438161678Sdavidxu	} modes[3];
439161678Sdavidxu};
440139257Sdavidxu
441161678Sdavidxu/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
442161678Sdavidxustatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
443161678Sdavidxu	{
444201991Sdavidxu		{
445161678Sdavidxu			{ &ifm_subtype_shared_descriptions[0], 0 },
446161678Sdavidxu			{ &ifm_subtype_shared_aliases[0], 1 },
447161678Sdavidxu			{ &ifm_subtype_ethernet_descriptions[0], 0 },
448161678Sdavidxu			{ &ifm_subtype_ethernet_aliases[0], 1 },
449201991Sdavidxu			{ NULL, 0 },
450201991Sdavidxu		},
451201991Sdavidxu		{
452201991Sdavidxu			{ &ifm_shared_option_descriptions[0], 0 },
453161678Sdavidxu			{ &ifm_shared_option_aliases[0], 1 },
454201991Sdavidxu			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
455161678Sdavidxu			{ NULL, 0 },
456161678Sdavidxu		},
457161678Sdavidxu		{
458161678Sdavidxu			{ NULL, 0 },
459161678Sdavidxu		},
460177848Sdavidxu	},
461161678Sdavidxu	{
462177848Sdavidxu		{
463115765Sjeff			{ &ifm_subtype_shared_descriptions[0], 0 },
464161678Sdavidxu			{ &ifm_subtype_shared_aliases[0], 1 },
465201991Sdavidxu			{ &ifm_subtype_tokenring_descriptions[0], 0 },
466201991Sdavidxu			{ &ifm_subtype_tokenring_aliases[0], 1 },
467161678Sdavidxu			{ NULL, 0 },
468115765Sjeff		},
469139257Sdavidxu		{
470161678Sdavidxu			{ &ifm_shared_option_descriptions[0], 0 },
471161678Sdavidxu			{ &ifm_shared_option_aliases[0], 1 },
472201991Sdavidxu			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
473201991Sdavidxu			{ NULL, 0 },
474201991Sdavidxu		},
475177848Sdavidxu		{
476161678Sdavidxu			{ NULL, 0 },
477139257Sdavidxu		},
478201991Sdavidxu	},
479139013Sdavidxu	{
480139013Sdavidxu		{
481139257Sdavidxu			{ &ifm_subtype_shared_descriptions[0], 0 },
482138224Sdavidxu			{ &ifm_subtype_shared_aliases[0], 1 },
483138224Sdavidxu			{ &ifm_subtype_fddi_descriptions[0], 0 },
484177848Sdavidxu			{ &ifm_subtype_fddi_aliases[0], 1 },
485161678Sdavidxu			{ NULL, 0 },
486161678Sdavidxu		},
487161678Sdavidxu		{
488161678Sdavidxu			{ &ifm_shared_option_descriptions[0], 0 },
489161678Sdavidxu			{ &ifm_shared_option_aliases[0], 1 },
490161678Sdavidxu			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
491161678Sdavidxu			{ NULL, 0 },
492161678Sdavidxu		},
493161678Sdavidxu		{
494161678Sdavidxu			{ NULL, 0 },
495161678Sdavidxu		},
496161678Sdavidxu	},
497161678Sdavidxu	{
498161678Sdavidxu		{
499161678Sdavidxu			{ &ifm_subtype_shared_descriptions[0], 0 },
500161678Sdavidxu			{ &ifm_subtype_shared_aliases[0], 1 },
501161678Sdavidxu			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
502161678Sdavidxu			{ &ifm_subtype_ieee80211_aliases[0], 1 },
503138224Sdavidxu			{ NULL, 0 },
504161678Sdavidxu		},
505138224Sdavidxu		{
506161678Sdavidxu			{ &ifm_shared_option_descriptions[0], 0 },
507161678Sdavidxu			{ &ifm_shared_option_aliases[0], 1 },
508161678Sdavidxu			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
509161678Sdavidxu			{ NULL, 0 },
510161678Sdavidxu		},
511161678Sdavidxu		{
512161678Sdavidxu			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
513161678Sdavidxu			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
514139751Sdavidxu			{ NULL, 0 },
515139751Sdavidxu		},
516139751Sdavidxu	},
517138224Sdavidxu	{
518138224Sdavidxu		{
519161678Sdavidxu			{ &ifm_subtype_shared_descriptions[0], 0 },
520161678Sdavidxu			{ &ifm_subtype_shared_aliases[0], 1 },
521161678Sdavidxu			{ &ifm_subtype_atm_descriptions[0], 0 },
522218969Sjhb			{ &ifm_subtype_atm_aliases[0], 1 },
523161678Sdavidxu			{ NULL, 0 },
524139013Sdavidxu		},
525161678Sdavidxu		{
526139013Sdavidxu			{ &ifm_shared_option_descriptions[0], 0 },
527139013Sdavidxu			{ &ifm_shared_option_aliases[0], 1 },
528139013Sdavidxu			{ &ifm_subtype_atm_option_descriptions[0], 0 },
529139013Sdavidxu			{ NULL, 0 },
530139013Sdavidxu		},
531139013Sdavidxu		{
532161678Sdavidxu			{ NULL, 0 },
533161678Sdavidxu		},
534161678Sdavidxu	},
535161678Sdavidxu};
536161678Sdavidxu
537163677Sdavidxuint
538163677Sdavidxuget_media_subtype(int type, const char *val)
539161678Sdavidxu{
540161678Sdavidxu	struct ifmedia_description *desc;
541161678Sdavidxu	struct ifmedia_type_to_subtype *ttos;
542161678Sdavidxu	int rval, i;
543161678Sdavidxu
544161678Sdavidxu	/* Find the top-level interface type. */
545161678Sdavidxu	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
546161678Sdavidxu	    desc->ifmt_string != NULL; desc++, ttos++)
547161678Sdavidxu		if (type == desc->ifmt_word)
548161678Sdavidxu			break;
549161678Sdavidxu	if (desc->ifmt_string == NULL)
550161678Sdavidxu		errx(1, "unknown media type 0x%x", type);
551161678Sdavidxu
552161678Sdavidxu	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
553161678Sdavidxu		rval = lookup_media_word(ttos->subtypes[i].desc, val);
554161678Sdavidxu		if (rval != -1)
555161678Sdavidxu			return (rval);
556161678Sdavidxu	}
557161678Sdavidxu	errx(1, "unknown media subtype: %s", val);
558161678Sdavidxu	/*NOTREACHED*/
559139013Sdavidxu}
560139013Sdavidxu
561161678Sdavidxuint
562139013Sdavidxuget_media_mode(int type, const char *val)
563139013Sdavidxu{
564139013Sdavidxu	struct ifmedia_description *desc;
565161678Sdavidxu	struct ifmedia_type_to_subtype *ttos;
566161678Sdavidxu	int rval, i;
567161678Sdavidxu
568218969Sjhb	/* Find the top-level interface type. */
569139013Sdavidxu	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
570139013Sdavidxu	    desc->ifmt_string != NULL; desc++, ttos++)
571161678Sdavidxu		if (type == desc->ifmt_word)
572139013Sdavidxu			break;
573139013Sdavidxu	if (desc->ifmt_string == NULL)
574139013Sdavidxu		errx(1, "unknown media mode 0x%x", type);
575161678Sdavidxu
576161678Sdavidxu	for (i = 0; ttos->modes[i].desc != NULL; i++) {
577161678Sdavidxu		rval = lookup_media_word(ttos->modes[i].desc, val);
578139013Sdavidxu		if (rval != -1)
579163449Sdavidxu			return (rval);
580112904Sjeff	}
581143149Sdavidxu	return -1;
582163449Sdavidxu}
583163449Sdavidxu
584138224Sdavidxuint
585112904Sjeffget_media_options(int type, const char *val)
586143149Sdavidxu{
587161678Sdavidxu	struct ifmedia_description *desc;
588112904Sjeff	struct ifmedia_type_to_subtype *ttos;
589161678Sdavidxu	char *optlist, *optptr;
590112904Sjeff	int option = 0, i, rval = 0;
591112904Sjeff
592112904Sjeff	/* We muck with the string, so copy it. */
593112904Sjeff	optlist = strdup(val);
594112904Sjeff	if (optlist == NULL)
595112904Sjeff		err(1, "strdup");
596163449Sdavidxu
597112904Sjeff	/* Find the top-level interface type. */
598138224Sdavidxu	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
599138224Sdavidxu	    desc->ifmt_string != NULL; desc++, ttos++)
600138224Sdavidxu		if (type == desc->ifmt_word)
601138224Sdavidxu			break;
602115765Sjeff	if (desc->ifmt_string == NULL)
603115765Sjeff		errx(1, "unknown media type 0x%x", type);
604115765Sjeff
605115765Sjeff	/*
606115765Sjeff	 * Look up the options in the user-provided comma-separated
607115765Sjeff	 * list.
608163449Sdavidxu	 */
609139013Sdavidxu	optptr = optlist;
610115765Sjeff	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
611138224Sdavidxu		for (i = 0; ttos->options[i].desc != NULL; i++) {
612138224Sdavidxu			option = lookup_media_word(ttos->options[i].desc, optptr);
613138224Sdavidxu			if (option != -1)
614115765Sjeff				break;
615115765Sjeff		}
616115765Sjeff		if (option == 0)
617115765Sjeff			errx(1, "unknown option: %s", optptr);
618115765Sjeff		rval |= option;
619115765Sjeff	}
620112904Sjeff
621112904Sjeff	free(optlist);
622138224Sdavidxu	return (rval);
623138224Sdavidxu}
624138224Sdavidxu
625138224Sdavidxuint
626161678Sdavidxulookup_media_word(struct ifmedia_description *desc, const char *val)
627138224Sdavidxu{
628112904Sjeff
629161678Sdavidxu	for (; desc->ifmt_string != NULL; desc++)
630161678Sdavidxu		if (strcasecmp(desc->ifmt_string, val) == 0)
631161678Sdavidxu			return (desc->ifmt_word);
632161678Sdavidxu
633161678Sdavidxu	return (-1);
634161678Sdavidxu}
635161678Sdavidxu
636161678Sdavidxustatic struct ifmedia_description *get_toptype_desc(int ifmw)
637161678Sdavidxu{
638161678Sdavidxu	struct ifmedia_description *desc;
639112904Sjeff
640112904Sjeff	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
641112904Sjeff		if (IFM_TYPE(ifmw) == desc->ifmt_word)
642112904Sjeff			break;
643112904Sjeff
644112904Sjeff	return desc;
645163449Sdavidxu}
646112904Sjeff
647112904Sjeffstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
648112967Sjake{
649143149Sdavidxu	struct ifmedia_description *desc;
650143149Sdavidxu	struct ifmedia_type_to_subtype *ttos;
651143149Sdavidxu
652143149Sdavidxu	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
653115765Sjeff	    desc->ifmt_string != NULL; desc++, ttos++)
654112904Sjeff		if (IFM_TYPE(ifmw) == desc->ifmt_word)
655112904Sjeff			break;
656112904Sjeff
657115765Sjeff	return ttos;
658117685Smtm}
659117685Smtm
660112904Sjeffstatic struct ifmedia_description *get_subtype_desc(int ifmw,
661143149Sdavidxu    struct ifmedia_type_to_subtype *ttos)
662161678Sdavidxu{
663161678Sdavidxu	int i;
664143149Sdavidxu	struct ifmedia_description *desc;
665143149Sdavidxu
666143149Sdavidxu	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
667112904Sjeff		if (ttos->subtypes[i].alias)
668117743Smtm			continue;
669117743Smtm		for (desc = ttos->subtypes[i].desc;
670112904Sjeff		    desc->ifmt_string != NULL; desc++) {
671112904Sjeff			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
672161678Sdavidxu				return desc;
673161678Sdavidxu		}
674161678Sdavidxu	}
675139013Sdavidxu
676163449Sdavidxu	return NULL;
677140245Sdavidxu}
678112904Sjeff
679140245Sdavidxustatic struct ifmedia_description *get_mode_desc(int ifmw,
680139013Sdavidxu    struct ifmedia_type_to_subtype *ttos)
681140245Sdavidxu{
682139013Sdavidxu	int i;
683140245Sdavidxu	struct ifmedia_description *desc;
684162536Sdavidxu
685162030Sdavidxu	for (i = 0; ttos->modes[i].desc != NULL; i++) {
686162030Sdavidxu		if (ttos->modes[i].alias)
687162030Sdavidxu			continue;
688139013Sdavidxu		for (desc = ttos->modes[i].desc;
689140245Sdavidxu		    desc->ifmt_string != NULL; desc++) {
690140245Sdavidxu			if (IFM_MODE(ifmw) == desc->ifmt_word)
691140245Sdavidxu				return desc;
692139013Sdavidxu		}
693162536Sdavidxu	}
694140245Sdavidxu
695140245Sdavidxu	return NULL;
696140245Sdavidxu}
697140245Sdavidxu
698139751Sdavidxuvoid
699139013Sdavidxuprint_media_word(int ifmw, int print_toptype)
700139013Sdavidxu{
701140245Sdavidxu	struct ifmedia_description *desc;
702140245Sdavidxu	struct ifmedia_type_to_subtype *ttos;
703140245Sdavidxu	int seen_option = 0, i;
704139013Sdavidxu
705162030Sdavidxu	/* Find the top-level interface type. */
706162030Sdavidxu	desc = get_toptype_desc(ifmw);
707162030Sdavidxu	ttos = get_toptype_ttos(ifmw);
708139013Sdavidxu	if (desc->ifmt_string == NULL) {
709139013Sdavidxu		printf("<unknown type>");
710139013Sdavidxu		return;
711139013Sdavidxu	} else if (print_toptype) {
712161678Sdavidxu		printf("%s", desc->ifmt_string);
713161678Sdavidxu	}
714161678Sdavidxu
715139013Sdavidxu	/*
716163449Sdavidxu	 * Don't print the top-level type; it's not like we can
717139013Sdavidxu	 * change it, or anything.
718139013Sdavidxu	 */
719163449Sdavidxu
720163449Sdavidxu	/* Find subtype. */
721139257Sdavidxu	desc = get_subtype_desc(ifmw, ttos);
722139257Sdavidxu	if (desc == NULL) {
723112904Sjeff		printf("<unknown subtype>");
724112904Sjeff		return;
725112904Sjeff	}
726112904Sjeff
727163449Sdavidxu	if (print_toptype)
728161678Sdavidxu		putchar(' ');
729115765Sjeff
730115765Sjeff	printf("%s", desc->ifmt_string);
731139013Sdavidxu
732115765Sjeff	if (print_toptype) {
733112904Sjeff		desc = get_mode_desc(ifmw, ttos);
734161678Sdavidxu		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
735161678Sdavidxu			printf(" mode %s", desc->ifmt_string);
736163449Sdavidxu	}
737161678Sdavidxu
738161678Sdavidxu	/* Find options. */
739161678Sdavidxu	for (i = 0; ttos->options[i].desc != NULL; i++) {
740161678Sdavidxu		if (ttos->options[i].alias)
741161855Sdavidxu			continue;
742161678Sdavidxu		for (desc = ttos->options[i].desc;
743161678Sdavidxu		    desc->ifmt_string != NULL; desc++) {
744117685Smtm			if (ifmw & desc->ifmt_word) {
745161678Sdavidxu				if (seen_option == 0)
746161678Sdavidxu					printf(" <");
747139257Sdavidxu				printf("%s%s", seen_option++ ? "," : "",
748139257Sdavidxu				    desc->ifmt_string);
749139257Sdavidxu			}
750139257Sdavidxu		}
751139257Sdavidxu	}
752139257Sdavidxu	printf("%s", seen_option ? ">" : "");
753139257Sdavidxu
754117743Smtm	if (print_toptype && IFM_INST(ifmw) != 0)
755117743Smtm		printf(" instance %d", IFM_INST(ifmw));
756117743Smtm}
757117743Smtm
758117743Smtmvoid
759163449Sdavidxuprint_media_word_ifconfig(int ifmw)
760163449Sdavidxu{
761139257Sdavidxu	struct ifmedia_description *desc;
762161678Sdavidxu	struct ifmedia_type_to_subtype *ttos;
763139257Sdavidxu	int seen_option = 0, i;
764139257Sdavidxu
765139257Sdavidxu	/* Find the top-level interface type. */
766115765Sjeff	desc = get_toptype_desc(ifmw);
767115765Sjeff	ttos = get_toptype_ttos(ifmw);
768138224Sdavidxu	if (desc->ifmt_string == NULL) {
769138224Sdavidxu		printf("<unknown type>");
770115765Sjeff		return;
771112904Sjeff	}
772139013Sdavidxu
773205014Snwhitehorn	/*
774162536Sdavidxu	 * Don't print the top-level type; it's not like we can
775161678Sdavidxu	 * change it, or anything.
776162536Sdavidxu	 */
777162536Sdavidxu
778162536Sdavidxu	/* Find subtype. */
779162536Sdavidxu	desc = get_subtype_desc(ifmw, ttos);
780162536Sdavidxu	if (desc == NULL) {
781162536Sdavidxu		printf("<unknown subtype>");
782162536Sdavidxu		return;
783162536Sdavidxu	}
784162536Sdavidxu
785162536Sdavidxu	printf("media %s", desc->ifmt_string);
786162536Sdavidxu
787162536Sdavidxu	desc = get_mode_desc(ifmw, ttos);
788162536Sdavidxu	if (desc != NULL)
789162536Sdavidxu		printf(" mode %s", desc->ifmt_string);
790162536Sdavidxu
791162536Sdavidxu	/* Find options. */
792162536Sdavidxu	for (i = 0; ttos->options[i].desc != NULL; i++) {
793162536Sdavidxu		if (ttos->options[i].alias)
794162536Sdavidxu			continue;
795162536Sdavidxu		for (desc = ttos->options[i].desc;
796162536Sdavidxu		    desc->ifmt_string != NULL; desc++) {
797162536Sdavidxu			if (ifmw & desc->ifmt_word) {
798162536Sdavidxu				if (seen_option == 0)
799162536Sdavidxu					printf(" mediaopt ");
800162536Sdavidxu				printf("%s%s", seen_option++ ? "," : "",
801162536Sdavidxu				    desc->ifmt_string);
802162536Sdavidxu			}
803162536Sdavidxu		}
804162536Sdavidxu	}
805162536Sdavidxu
806162536Sdavidxu	if (IFM_INST(ifmw) != 0)
807162536Sdavidxu		printf(" instance %d", IFM_INST(ifmw));
808162536Sdavidxu}
809162536Sdavidxu
810162536Sdavidxu/**********************************************************************
811162536Sdavidxu * ...until here.
812162536Sdavidxu **********************************************************************/
813162536Sdavidxu