xref: /freebsd/sbin/etherswitchcfg/ifmedia.c (revision 270069b756f1f69d8991fc6b591258e794f95f1b)
1*270069b7SAdrian Chadd /*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
2*270069b7SAdrian Chadd /* $FreeBSD$ */
3*270069b7SAdrian Chadd 
4*270069b7SAdrian Chadd /*
5*270069b7SAdrian Chadd  * Copyright (c) 1997 Jason R. Thorpe.
6*270069b7SAdrian Chadd  * All rights reserved.
7*270069b7SAdrian Chadd  *
8*270069b7SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
9*270069b7SAdrian Chadd  * modification, are permitted provided that the following conditions
10*270069b7SAdrian Chadd  * are met:
11*270069b7SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
12*270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
13*270069b7SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
14*270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
15*270069b7SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
16*270069b7SAdrian Chadd  * 3. All advertising materials mentioning features or use of this software
17*270069b7SAdrian Chadd  *    must display the following acknowledgement:
18*270069b7SAdrian Chadd  *      This product includes software developed for the NetBSD Project
19*270069b7SAdrian Chadd  *	by Jason R. Thorpe.
20*270069b7SAdrian Chadd  * 4. The name of the author may not be used to endorse or promote products
21*270069b7SAdrian Chadd  *    derived from this software without specific prior written permission.
22*270069b7SAdrian Chadd  *
23*270069b7SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24*270069b7SAdrian Chadd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25*270069b7SAdrian Chadd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*270069b7SAdrian Chadd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27*270069b7SAdrian Chadd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28*270069b7SAdrian Chadd  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29*270069b7SAdrian Chadd  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30*270069b7SAdrian Chadd  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31*270069b7SAdrian Chadd  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*270069b7SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*270069b7SAdrian Chadd  * SUCH DAMAGE.
34*270069b7SAdrian Chadd  */
35*270069b7SAdrian Chadd 
36*270069b7SAdrian Chadd /*
37*270069b7SAdrian Chadd  * Copyright (c) 1983, 1993
38*270069b7SAdrian Chadd  *	The Regents of the University of California.  All rights reserved.
39*270069b7SAdrian Chadd  *
40*270069b7SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
41*270069b7SAdrian Chadd  * modification, are permitted provided that the following conditions
42*270069b7SAdrian Chadd  * are met:
43*270069b7SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
44*270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
45*270069b7SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
46*270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
47*270069b7SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
48*270069b7SAdrian Chadd  * 4. Neither the name of the University nor the names of its contributors
49*270069b7SAdrian Chadd  *    may be used to endorse or promote products derived from this software
50*270069b7SAdrian Chadd  *    without specific prior written permission.
51*270069b7SAdrian Chadd  *
52*270069b7SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53*270069b7SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54*270069b7SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55*270069b7SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56*270069b7SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57*270069b7SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58*270069b7SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59*270069b7SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60*270069b7SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61*270069b7SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62*270069b7SAdrian Chadd  * SUCH DAMAGE.
63*270069b7SAdrian Chadd  */
64*270069b7SAdrian Chadd /*
65*270069b7SAdrian Chadd  * based on sbin/ifconfig/ifmedia.c r221954
66*270069b7SAdrian Chadd  */
67*270069b7SAdrian Chadd 
68*270069b7SAdrian Chadd #include <sys/param.h>
69*270069b7SAdrian Chadd #include <sys/ioctl.h>
70*270069b7SAdrian Chadd #include <sys/socket.h>
71*270069b7SAdrian Chadd #include <sys/sysctl.h>
72*270069b7SAdrian Chadd #include <sys/time.h>
73*270069b7SAdrian Chadd 
74*270069b7SAdrian Chadd #include <net/if.h>
75*270069b7SAdrian Chadd #include <net/if_dl.h>
76*270069b7SAdrian Chadd #include <net/if_types.h>
77*270069b7SAdrian Chadd #include <net/if_media.h>
78*270069b7SAdrian Chadd #include <net/route.h>
79*270069b7SAdrian Chadd 
80*270069b7SAdrian Chadd #include <ctype.h>
81*270069b7SAdrian Chadd #include <err.h>
82*270069b7SAdrian Chadd #include <errno.h>
83*270069b7SAdrian Chadd #include <fcntl.h>
84*270069b7SAdrian Chadd #include <stdio.h>
85*270069b7SAdrian Chadd #include <stdlib.h>
86*270069b7SAdrian Chadd #include <string.h>
87*270069b7SAdrian Chadd #include <unistd.h>
88*270069b7SAdrian Chadd 
89*270069b7SAdrian Chadd void	domediaopt(const char *, int, int);
90*270069b7SAdrian Chadd int	get_media_subtype(int, const char *);
91*270069b7SAdrian Chadd int	get_media_mode(int, const char *);
92*270069b7SAdrian Chadd int	get_media_options(int, const char *);
93*270069b7SAdrian Chadd int	lookup_media_word(struct ifmedia_description *, const char *);
94*270069b7SAdrian Chadd void	print_media_word(int, int);
95*270069b7SAdrian Chadd void	print_media_word_ifconfig(int);
96*270069b7SAdrian Chadd 
97*270069b7SAdrian Chadd #if 0
98*270069b7SAdrian Chadd static struct ifmedia_description *get_toptype_desc(int);
99*270069b7SAdrian Chadd static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
100*270069b7SAdrian Chadd static struct ifmedia_description *get_subtype_desc(int,
101*270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos);
102*270069b7SAdrian Chadd 
103*270069b7SAdrian Chadd #define	IFM_OPMODE(x) \
104*270069b7SAdrian Chadd 	((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
105*270069b7SAdrian Chadd 	 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
106*270069b7SAdrian Chadd 	 IFM_IEEE80211_MBSS))
107*270069b7SAdrian Chadd #define	IFM_IEEE80211_STA	0
108*270069b7SAdrian Chadd 
109*270069b7SAdrian Chadd static void
110*270069b7SAdrian Chadd media_status(int s)
111*270069b7SAdrian Chadd {
112*270069b7SAdrian Chadd 	struct ifmediareq ifmr;
113*270069b7SAdrian Chadd 	int *media_list, i;
114*270069b7SAdrian Chadd 
115*270069b7SAdrian Chadd 	(void) memset(&ifmr, 0, sizeof(ifmr));
116*270069b7SAdrian Chadd 	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
117*270069b7SAdrian Chadd 
118*270069b7SAdrian Chadd 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
119*270069b7SAdrian Chadd 		/*
120*270069b7SAdrian Chadd 		 * Interface doesn't support SIOC{G,S}IFMEDIA.
121*270069b7SAdrian Chadd 		 */
122*270069b7SAdrian Chadd 		return;
123*270069b7SAdrian Chadd 	}
124*270069b7SAdrian Chadd 
125*270069b7SAdrian Chadd 	if (ifmr.ifm_count == 0) {
126*270069b7SAdrian Chadd 		warnx("%s: no media types?", name);
127*270069b7SAdrian Chadd 		return;
128*270069b7SAdrian Chadd 	}
129*270069b7SAdrian Chadd 
130*270069b7SAdrian Chadd 	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
131*270069b7SAdrian Chadd 	if (media_list == NULL)
132*270069b7SAdrian Chadd 		err(1, "malloc");
133*270069b7SAdrian Chadd 	ifmr.ifm_ulist = media_list;
134*270069b7SAdrian Chadd 
135*270069b7SAdrian Chadd 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
136*270069b7SAdrian Chadd 		err(1, "SIOCGIFMEDIA");
137*270069b7SAdrian Chadd 
138*270069b7SAdrian Chadd 	printf("\tmedia: ");
139*270069b7SAdrian Chadd 	print_media_word(ifmr.ifm_current, 1);
140*270069b7SAdrian Chadd 	if (ifmr.ifm_active != ifmr.ifm_current) {
141*270069b7SAdrian Chadd 		putchar(' ');
142*270069b7SAdrian Chadd 		putchar('(');
143*270069b7SAdrian Chadd 		print_media_word(ifmr.ifm_active, 0);
144*270069b7SAdrian Chadd 		putchar(')');
145*270069b7SAdrian Chadd 	}
146*270069b7SAdrian Chadd 
147*270069b7SAdrian Chadd 	putchar('\n');
148*270069b7SAdrian Chadd 
149*270069b7SAdrian Chadd 	if (ifmr.ifm_status & IFM_AVALID) {
150*270069b7SAdrian Chadd 		printf("\tstatus: ");
151*270069b7SAdrian Chadd 		switch (IFM_TYPE(ifmr.ifm_active)) {
152*270069b7SAdrian Chadd 		case IFM_ETHER:
153*270069b7SAdrian Chadd 		case IFM_ATM:
154*270069b7SAdrian Chadd 			if (ifmr.ifm_status & IFM_ACTIVE)
155*270069b7SAdrian Chadd 				printf("active");
156*270069b7SAdrian Chadd 			else
157*270069b7SAdrian Chadd 				printf("no carrier");
158*270069b7SAdrian Chadd 			break;
159*270069b7SAdrian Chadd 
160*270069b7SAdrian Chadd 		case IFM_FDDI:
161*270069b7SAdrian Chadd 		case IFM_TOKEN:
162*270069b7SAdrian Chadd 			if (ifmr.ifm_status & IFM_ACTIVE)
163*270069b7SAdrian Chadd 				printf("inserted");
164*270069b7SAdrian Chadd 			else
165*270069b7SAdrian Chadd 				printf("no ring");
166*270069b7SAdrian Chadd 			break;
167*270069b7SAdrian Chadd 
168*270069b7SAdrian Chadd 		case IFM_IEEE80211:
169*270069b7SAdrian Chadd 			if (ifmr.ifm_status & IFM_ACTIVE) {
170*270069b7SAdrian Chadd 				/* NB: only sta mode associates */
171*270069b7SAdrian Chadd 				if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
172*270069b7SAdrian Chadd 					printf("associated");
173*270069b7SAdrian Chadd 				else
174*270069b7SAdrian Chadd 					printf("running");
175*270069b7SAdrian Chadd 			} else
176*270069b7SAdrian Chadd 				printf("no carrier");
177*270069b7SAdrian Chadd 			break;
178*270069b7SAdrian Chadd 		}
179*270069b7SAdrian Chadd 		putchar('\n');
180*270069b7SAdrian Chadd 	}
181*270069b7SAdrian Chadd 
182*270069b7SAdrian Chadd 	if (ifmr.ifm_count > 0 && supmedia) {
183*270069b7SAdrian Chadd 		printf("\tsupported media:\n");
184*270069b7SAdrian Chadd 		for (i = 0; i < ifmr.ifm_count; i++) {
185*270069b7SAdrian Chadd 			printf("\t\t");
186*270069b7SAdrian Chadd 			print_media_word_ifconfig(media_list[i]);
187*270069b7SAdrian Chadd 			putchar('\n');
188*270069b7SAdrian Chadd 		}
189*270069b7SAdrian Chadd 	}
190*270069b7SAdrian Chadd 
191*270069b7SAdrian Chadd 	free(media_list);
192*270069b7SAdrian Chadd }
193*270069b7SAdrian Chadd 
194*270069b7SAdrian Chadd struct ifmediareq *
195*270069b7SAdrian Chadd ifmedia_getstate(int s)
196*270069b7SAdrian Chadd {
197*270069b7SAdrian Chadd 	static struct ifmediareq *ifmr = NULL;
198*270069b7SAdrian Chadd 	int *mwords;
199*270069b7SAdrian Chadd 
200*270069b7SAdrian Chadd 	if (ifmr == NULL) {
201*270069b7SAdrian Chadd 		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
202*270069b7SAdrian Chadd 		if (ifmr == NULL)
203*270069b7SAdrian Chadd 			err(1, "malloc");
204*270069b7SAdrian Chadd 
205*270069b7SAdrian Chadd 		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
206*270069b7SAdrian Chadd 		(void) strncpy(ifmr->ifm_name, name,
207*270069b7SAdrian Chadd 		    sizeof(ifmr->ifm_name));
208*270069b7SAdrian Chadd 
209*270069b7SAdrian Chadd 		ifmr->ifm_count = 0;
210*270069b7SAdrian Chadd 		ifmr->ifm_ulist = NULL;
211*270069b7SAdrian Chadd 
212*270069b7SAdrian Chadd 		/*
213*270069b7SAdrian Chadd 		 * We must go through the motions of reading all
214*270069b7SAdrian Chadd 		 * supported media because we need to know both
215*270069b7SAdrian Chadd 		 * the current media type and the top-level type.
216*270069b7SAdrian Chadd 		 */
217*270069b7SAdrian Chadd 
218*270069b7SAdrian Chadd 		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
219*270069b7SAdrian Chadd 			err(1, "SIOCGIFMEDIA");
220*270069b7SAdrian Chadd 		}
221*270069b7SAdrian Chadd 
222*270069b7SAdrian Chadd 		if (ifmr->ifm_count == 0)
223*270069b7SAdrian Chadd 			errx(1, "%s: no media types?", name);
224*270069b7SAdrian Chadd 
225*270069b7SAdrian Chadd 		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
226*270069b7SAdrian Chadd 		if (mwords == NULL)
227*270069b7SAdrian Chadd 			err(1, "malloc");
228*270069b7SAdrian Chadd 
229*270069b7SAdrian Chadd 		ifmr->ifm_ulist = mwords;
230*270069b7SAdrian Chadd 		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
231*270069b7SAdrian Chadd 			err(1, "SIOCGIFMEDIA");
232*270069b7SAdrian Chadd 	}
233*270069b7SAdrian Chadd 
234*270069b7SAdrian Chadd 	return ifmr;
235*270069b7SAdrian Chadd }
236*270069b7SAdrian Chadd 
237*270069b7SAdrian Chadd static void
238*270069b7SAdrian Chadd setifmediacallback(int s, void *arg)
239*270069b7SAdrian Chadd {
240*270069b7SAdrian Chadd 	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
241*270069b7SAdrian Chadd 	static int did_it = 0;
242*270069b7SAdrian Chadd 
243*270069b7SAdrian Chadd 	if (!did_it) {
244*270069b7SAdrian Chadd 		ifr.ifr_media = ifmr->ifm_current;
245*270069b7SAdrian Chadd 		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
246*270069b7SAdrian Chadd 			err(1, "SIOCSIFMEDIA (media)");
247*270069b7SAdrian Chadd 		free(ifmr->ifm_ulist);
248*270069b7SAdrian Chadd 		free(ifmr);
249*270069b7SAdrian Chadd 		did_it = 1;
250*270069b7SAdrian Chadd 	}
251*270069b7SAdrian Chadd }
252*270069b7SAdrian Chadd 
253*270069b7SAdrian Chadd static void
254*270069b7SAdrian Chadd setmedia(const char *val, int d, int s, const struct afswtch *afp)
255*270069b7SAdrian Chadd {
256*270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
257*270069b7SAdrian Chadd 	int subtype;
258*270069b7SAdrian Chadd 
259*270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
260*270069b7SAdrian Chadd 
261*270069b7SAdrian Chadd 	/*
262*270069b7SAdrian Chadd 	 * We are primarily concerned with the top-level type.
263*270069b7SAdrian Chadd 	 * However, "current" may be only IFM_NONE, so we just look
264*270069b7SAdrian Chadd 	 * for the top-level type in the first "supported type"
265*270069b7SAdrian Chadd 	 * entry.
266*270069b7SAdrian Chadd 	 *
267*270069b7SAdrian Chadd 	 * (I'm assuming that all supported media types for a given
268*270069b7SAdrian Chadd 	 * interface will be the same top-level type..)
269*270069b7SAdrian Chadd 	 */
270*270069b7SAdrian Chadd 	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
271*270069b7SAdrian Chadd 
272*270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
273*270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
274*270069b7SAdrian Chadd 	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
275*270069b7SAdrian Chadd 
276*270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
277*270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
278*270069b7SAdrian Chadd }
279*270069b7SAdrian Chadd 
280*270069b7SAdrian Chadd static void
281*270069b7SAdrian Chadd setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
282*270069b7SAdrian Chadd {
283*270069b7SAdrian Chadd 
284*270069b7SAdrian Chadd 	domediaopt(val, 0, s);
285*270069b7SAdrian Chadd }
286*270069b7SAdrian Chadd 
287*270069b7SAdrian Chadd static void
288*270069b7SAdrian Chadd unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
289*270069b7SAdrian Chadd {
290*270069b7SAdrian Chadd 
291*270069b7SAdrian Chadd 	domediaopt(val, 1, s);
292*270069b7SAdrian Chadd }
293*270069b7SAdrian Chadd 
294*270069b7SAdrian Chadd static void
295*270069b7SAdrian Chadd domediaopt(const char *val, int clear, int s)
296*270069b7SAdrian Chadd {
297*270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
298*270069b7SAdrian Chadd 	int options;
299*270069b7SAdrian Chadd 
300*270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
301*270069b7SAdrian Chadd 
302*270069b7SAdrian Chadd 	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
303*270069b7SAdrian Chadd 
304*270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
305*270069b7SAdrian Chadd 	ifr.ifr_media = ifmr->ifm_current;
306*270069b7SAdrian Chadd 	if (clear)
307*270069b7SAdrian Chadd 		ifr.ifr_media &= ~options;
308*270069b7SAdrian Chadd 	else {
309*270069b7SAdrian Chadd 		if (options & IFM_HDX) {
310*270069b7SAdrian Chadd 			ifr.ifr_media &= ~IFM_FDX;
311*270069b7SAdrian Chadd 			options &= ~IFM_HDX;
312*270069b7SAdrian Chadd 		}
313*270069b7SAdrian Chadd 		ifr.ifr_media |= options;
314*270069b7SAdrian Chadd 	}
315*270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
316*270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
317*270069b7SAdrian Chadd }
318*270069b7SAdrian Chadd 
319*270069b7SAdrian Chadd static void
320*270069b7SAdrian Chadd setmediainst(const char *val, int d, int s, const struct afswtch *afp)
321*270069b7SAdrian Chadd {
322*270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
323*270069b7SAdrian Chadd 	int inst;
324*270069b7SAdrian Chadd 
325*270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
326*270069b7SAdrian Chadd 
327*270069b7SAdrian Chadd 	inst = atoi(val);
328*270069b7SAdrian Chadd 	if (inst < 0 || inst > (int)IFM_INST_MAX)
329*270069b7SAdrian Chadd 		errx(1, "invalid media instance: %s", val);
330*270069b7SAdrian Chadd 
331*270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
332*270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
333*270069b7SAdrian Chadd 
334*270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
335*270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
336*270069b7SAdrian Chadd }
337*270069b7SAdrian Chadd 
338*270069b7SAdrian Chadd static void
339*270069b7SAdrian Chadd setmediamode(const char *val, int d, int s, const struct afswtch *afp)
340*270069b7SAdrian Chadd {
341*270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
342*270069b7SAdrian Chadd 	int mode;
343*270069b7SAdrian Chadd 
344*270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
345*270069b7SAdrian Chadd 
346*270069b7SAdrian Chadd 	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
347*270069b7SAdrian Chadd 
348*270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
349*270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
350*270069b7SAdrian Chadd 
351*270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
352*270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
353*270069b7SAdrian Chadd }
354*270069b7SAdrian Chadd #endif
355*270069b7SAdrian Chadd 
356*270069b7SAdrian Chadd /**********************************************************************
357*270069b7SAdrian Chadd  * A good chunk of this is duplicated from sys/net/ifmedia.c
358*270069b7SAdrian Chadd  **********************************************************************/
359*270069b7SAdrian Chadd 
360*270069b7SAdrian Chadd static struct ifmedia_description ifm_type_descriptions[] =
361*270069b7SAdrian Chadd     IFM_TYPE_DESCRIPTIONS;
362*270069b7SAdrian Chadd 
363*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
364*270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
365*270069b7SAdrian Chadd 
366*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
367*270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_ALIASES;
368*270069b7SAdrian Chadd 
369*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
370*270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
371*270069b7SAdrian Chadd 
372*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
373*270069b7SAdrian Chadd     IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
374*270069b7SAdrian Chadd 
375*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
376*270069b7SAdrian Chadd     IFM_SUBTYPE_TOKENRING_ALIASES;
377*270069b7SAdrian Chadd 
378*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
379*270069b7SAdrian Chadd     IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
380*270069b7SAdrian Chadd 
381*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
382*270069b7SAdrian Chadd     IFM_SUBTYPE_FDDI_DESCRIPTIONS;
383*270069b7SAdrian Chadd 
384*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_fddi_aliases[] =
385*270069b7SAdrian Chadd     IFM_SUBTYPE_FDDI_ALIASES;
386*270069b7SAdrian Chadd 
387*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
388*270069b7SAdrian Chadd     IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
389*270069b7SAdrian Chadd 
390*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
391*270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
392*270069b7SAdrian Chadd 
393*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
394*270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_ALIASES;
395*270069b7SAdrian Chadd 
396*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
397*270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
398*270069b7SAdrian Chadd 
399*270069b7SAdrian Chadd struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
400*270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
401*270069b7SAdrian Chadd 
402*270069b7SAdrian Chadd struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
403*270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
404*270069b7SAdrian Chadd 
405*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_descriptions[] =
406*270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_DESCRIPTIONS;
407*270069b7SAdrian Chadd 
408*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_aliases[] =
409*270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_ALIASES;
410*270069b7SAdrian Chadd 
411*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
412*270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
413*270069b7SAdrian Chadd 
414*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_shared_descriptions[] =
415*270069b7SAdrian Chadd     IFM_SUBTYPE_SHARED_DESCRIPTIONS;
416*270069b7SAdrian Chadd 
417*270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_shared_aliases[] =
418*270069b7SAdrian Chadd     IFM_SUBTYPE_SHARED_ALIASES;
419*270069b7SAdrian Chadd 
420*270069b7SAdrian Chadd static struct ifmedia_description ifm_shared_option_descriptions[] =
421*270069b7SAdrian Chadd     IFM_SHARED_OPTION_DESCRIPTIONS;
422*270069b7SAdrian Chadd 
423*270069b7SAdrian Chadd static struct ifmedia_description ifm_shared_option_aliases[] =
424*270069b7SAdrian Chadd     IFM_SHARED_OPTION_ALIASES;
425*270069b7SAdrian Chadd 
426*270069b7SAdrian Chadd struct ifmedia_type_to_subtype {
427*270069b7SAdrian Chadd 	struct {
428*270069b7SAdrian Chadd 		struct ifmedia_description *desc;
429*270069b7SAdrian Chadd 		int alias;
430*270069b7SAdrian Chadd 	} subtypes[5];
431*270069b7SAdrian Chadd 	struct {
432*270069b7SAdrian Chadd 		struct ifmedia_description *desc;
433*270069b7SAdrian Chadd 		int alias;
434*270069b7SAdrian Chadd 	} options[4];
435*270069b7SAdrian Chadd 	struct {
436*270069b7SAdrian Chadd 		struct ifmedia_description *desc;
437*270069b7SAdrian Chadd 		int alias;
438*270069b7SAdrian Chadd 	} modes[3];
439*270069b7SAdrian Chadd };
440*270069b7SAdrian Chadd 
441*270069b7SAdrian Chadd /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
442*270069b7SAdrian Chadd static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
443*270069b7SAdrian Chadd 	{
444*270069b7SAdrian Chadd 		{
445*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
446*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
447*270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_descriptions[0], 0 },
448*270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_aliases[0], 1 },
449*270069b7SAdrian Chadd 			{ NULL, 0 },
450*270069b7SAdrian Chadd 		},
451*270069b7SAdrian Chadd 		{
452*270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
453*270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
454*270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
455*270069b7SAdrian Chadd 			{ NULL, 0 },
456*270069b7SAdrian Chadd 		},
457*270069b7SAdrian Chadd 		{
458*270069b7SAdrian Chadd 			{ NULL, 0 },
459*270069b7SAdrian Chadd 		},
460*270069b7SAdrian Chadd 	},
461*270069b7SAdrian Chadd 	{
462*270069b7SAdrian Chadd 		{
463*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
464*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
465*270069b7SAdrian Chadd 			{ &ifm_subtype_tokenring_descriptions[0], 0 },
466*270069b7SAdrian Chadd 			{ &ifm_subtype_tokenring_aliases[0], 1 },
467*270069b7SAdrian Chadd 			{ NULL, 0 },
468*270069b7SAdrian Chadd 		},
469*270069b7SAdrian Chadd 		{
470*270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
471*270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
472*270069b7SAdrian Chadd 			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
473*270069b7SAdrian Chadd 			{ NULL, 0 },
474*270069b7SAdrian Chadd 		},
475*270069b7SAdrian Chadd 		{
476*270069b7SAdrian Chadd 			{ NULL, 0 },
477*270069b7SAdrian Chadd 		},
478*270069b7SAdrian Chadd 	},
479*270069b7SAdrian Chadd 	{
480*270069b7SAdrian Chadd 		{
481*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
482*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
483*270069b7SAdrian Chadd 			{ &ifm_subtype_fddi_descriptions[0], 0 },
484*270069b7SAdrian Chadd 			{ &ifm_subtype_fddi_aliases[0], 1 },
485*270069b7SAdrian Chadd 			{ NULL, 0 },
486*270069b7SAdrian Chadd 		},
487*270069b7SAdrian Chadd 		{
488*270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
489*270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
490*270069b7SAdrian Chadd 			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
491*270069b7SAdrian Chadd 			{ NULL, 0 },
492*270069b7SAdrian Chadd 		},
493*270069b7SAdrian Chadd 		{
494*270069b7SAdrian Chadd 			{ NULL, 0 },
495*270069b7SAdrian Chadd 		},
496*270069b7SAdrian Chadd 	},
497*270069b7SAdrian Chadd 	{
498*270069b7SAdrian Chadd 		{
499*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
500*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
501*270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
502*270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_aliases[0], 1 },
503*270069b7SAdrian Chadd 			{ NULL, 0 },
504*270069b7SAdrian Chadd 		},
505*270069b7SAdrian Chadd 		{
506*270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
507*270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
508*270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
509*270069b7SAdrian Chadd 			{ NULL, 0 },
510*270069b7SAdrian Chadd 		},
511*270069b7SAdrian Chadd 		{
512*270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
513*270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
514*270069b7SAdrian Chadd 			{ NULL, 0 },
515*270069b7SAdrian Chadd 		},
516*270069b7SAdrian Chadd 	},
517*270069b7SAdrian Chadd 	{
518*270069b7SAdrian Chadd 		{
519*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
520*270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
521*270069b7SAdrian Chadd 			{ &ifm_subtype_atm_descriptions[0], 0 },
522*270069b7SAdrian Chadd 			{ &ifm_subtype_atm_aliases[0], 1 },
523*270069b7SAdrian Chadd 			{ NULL, 0 },
524*270069b7SAdrian Chadd 		},
525*270069b7SAdrian Chadd 		{
526*270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
527*270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
528*270069b7SAdrian Chadd 			{ &ifm_subtype_atm_option_descriptions[0], 0 },
529*270069b7SAdrian Chadd 			{ NULL, 0 },
530*270069b7SAdrian Chadd 		},
531*270069b7SAdrian Chadd 		{
532*270069b7SAdrian Chadd 			{ NULL, 0 },
533*270069b7SAdrian Chadd 		},
534*270069b7SAdrian Chadd 	},
535*270069b7SAdrian Chadd };
536*270069b7SAdrian Chadd 
537*270069b7SAdrian Chadd int
538*270069b7SAdrian Chadd get_media_subtype(int type, const char *val)
539*270069b7SAdrian Chadd {
540*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
541*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
542*270069b7SAdrian Chadd 	int rval, i;
543*270069b7SAdrian Chadd 
544*270069b7SAdrian Chadd 	/* Find the top-level interface type. */
545*270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
546*270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
547*270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
548*270069b7SAdrian Chadd 			break;
549*270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
550*270069b7SAdrian Chadd 		errx(1, "unknown media type 0x%x", type);
551*270069b7SAdrian Chadd 
552*270069b7SAdrian Chadd 	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
553*270069b7SAdrian Chadd 		rval = lookup_media_word(ttos->subtypes[i].desc, val);
554*270069b7SAdrian Chadd 		if (rval != -1)
555*270069b7SAdrian Chadd 			return (rval);
556*270069b7SAdrian Chadd 	}
557*270069b7SAdrian Chadd 	errx(1, "unknown media subtype: %s", val);
558*270069b7SAdrian Chadd 	/*NOTREACHED*/
559*270069b7SAdrian Chadd }
560*270069b7SAdrian Chadd 
561*270069b7SAdrian Chadd int
562*270069b7SAdrian Chadd get_media_mode(int type, const char *val)
563*270069b7SAdrian Chadd {
564*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
565*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
566*270069b7SAdrian Chadd 	int rval, i;
567*270069b7SAdrian Chadd 
568*270069b7SAdrian Chadd 	/* Find the top-level interface type. */
569*270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
570*270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
571*270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
572*270069b7SAdrian Chadd 			break;
573*270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
574*270069b7SAdrian Chadd 		errx(1, "unknown media mode 0x%x", type);
575*270069b7SAdrian Chadd 
576*270069b7SAdrian Chadd 	for (i = 0; ttos->modes[i].desc != NULL; i++) {
577*270069b7SAdrian Chadd 		rval = lookup_media_word(ttos->modes[i].desc, val);
578*270069b7SAdrian Chadd 		if (rval != -1)
579*270069b7SAdrian Chadd 			return (rval);
580*270069b7SAdrian Chadd 	}
581*270069b7SAdrian Chadd 	return -1;
582*270069b7SAdrian Chadd }
583*270069b7SAdrian Chadd 
584*270069b7SAdrian Chadd int
585*270069b7SAdrian Chadd get_media_options(int type, const char *val)
586*270069b7SAdrian Chadd {
587*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
588*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
589*270069b7SAdrian Chadd 	char *optlist, *optptr;
590*270069b7SAdrian Chadd 	int option = 0, i, rval = 0;
591*270069b7SAdrian Chadd 
592*270069b7SAdrian Chadd 	/* We muck with the string, so copy it. */
593*270069b7SAdrian Chadd 	optlist = strdup(val);
594*270069b7SAdrian Chadd 	if (optlist == NULL)
595*270069b7SAdrian Chadd 		err(1, "strdup");
596*270069b7SAdrian Chadd 
597*270069b7SAdrian Chadd 	/* Find the top-level interface type. */
598*270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
599*270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
600*270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
601*270069b7SAdrian Chadd 			break;
602*270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
603*270069b7SAdrian Chadd 		errx(1, "unknown media type 0x%x", type);
604*270069b7SAdrian Chadd 
605*270069b7SAdrian Chadd 	/*
606*270069b7SAdrian Chadd 	 * Look up the options in the user-provided comma-separated
607*270069b7SAdrian Chadd 	 * list.
608*270069b7SAdrian Chadd 	 */
609*270069b7SAdrian Chadd 	optptr = optlist;
610*270069b7SAdrian Chadd 	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
611*270069b7SAdrian Chadd 		for (i = 0; ttos->options[i].desc != NULL; i++) {
612*270069b7SAdrian Chadd 			option = lookup_media_word(ttos->options[i].desc, optptr);
613*270069b7SAdrian Chadd 			if (option != -1)
614*270069b7SAdrian Chadd 				break;
615*270069b7SAdrian Chadd 		}
616*270069b7SAdrian Chadd 		if (option == 0)
617*270069b7SAdrian Chadd 			errx(1, "unknown option: %s", optptr);
618*270069b7SAdrian Chadd 		rval |= option;
619*270069b7SAdrian Chadd 	}
620*270069b7SAdrian Chadd 
621*270069b7SAdrian Chadd 	free(optlist);
622*270069b7SAdrian Chadd 	return (rval);
623*270069b7SAdrian Chadd }
624*270069b7SAdrian Chadd 
625*270069b7SAdrian Chadd int
626*270069b7SAdrian Chadd lookup_media_word(struct ifmedia_description *desc, const char *val)
627*270069b7SAdrian Chadd {
628*270069b7SAdrian Chadd 
629*270069b7SAdrian Chadd 	for (; desc->ifmt_string != NULL; desc++)
630*270069b7SAdrian Chadd 		if (strcasecmp(desc->ifmt_string, val) == 0)
631*270069b7SAdrian Chadd 			return (desc->ifmt_word);
632*270069b7SAdrian Chadd 
633*270069b7SAdrian Chadd 	return (-1);
634*270069b7SAdrian Chadd }
635*270069b7SAdrian Chadd 
636*270069b7SAdrian Chadd static struct ifmedia_description *get_toptype_desc(int ifmw)
637*270069b7SAdrian Chadd {
638*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
639*270069b7SAdrian Chadd 
640*270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
641*270069b7SAdrian Chadd 		if (IFM_TYPE(ifmw) == desc->ifmt_word)
642*270069b7SAdrian Chadd 			break;
643*270069b7SAdrian Chadd 
644*270069b7SAdrian Chadd 	return desc;
645*270069b7SAdrian Chadd }
646*270069b7SAdrian Chadd 
647*270069b7SAdrian Chadd static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
648*270069b7SAdrian Chadd {
649*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
650*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
651*270069b7SAdrian Chadd 
652*270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
653*270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
654*270069b7SAdrian Chadd 		if (IFM_TYPE(ifmw) == desc->ifmt_word)
655*270069b7SAdrian Chadd 			break;
656*270069b7SAdrian Chadd 
657*270069b7SAdrian Chadd 	return ttos;
658*270069b7SAdrian Chadd }
659*270069b7SAdrian Chadd 
660*270069b7SAdrian Chadd static struct ifmedia_description *get_subtype_desc(int ifmw,
661*270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos)
662*270069b7SAdrian Chadd {
663*270069b7SAdrian Chadd 	int i;
664*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
665*270069b7SAdrian Chadd 
666*270069b7SAdrian Chadd 	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
667*270069b7SAdrian Chadd 		if (ttos->subtypes[i].alias)
668*270069b7SAdrian Chadd 			continue;
669*270069b7SAdrian Chadd 		for (desc = ttos->subtypes[i].desc;
670*270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
671*270069b7SAdrian Chadd 			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
672*270069b7SAdrian Chadd 				return desc;
673*270069b7SAdrian Chadd 		}
674*270069b7SAdrian Chadd 	}
675*270069b7SAdrian Chadd 
676*270069b7SAdrian Chadd 	return NULL;
677*270069b7SAdrian Chadd }
678*270069b7SAdrian Chadd 
679*270069b7SAdrian Chadd static struct ifmedia_description *get_mode_desc(int ifmw,
680*270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos)
681*270069b7SAdrian Chadd {
682*270069b7SAdrian Chadd 	int i;
683*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
684*270069b7SAdrian Chadd 
685*270069b7SAdrian Chadd 	for (i = 0; ttos->modes[i].desc != NULL; i++) {
686*270069b7SAdrian Chadd 		if (ttos->modes[i].alias)
687*270069b7SAdrian Chadd 			continue;
688*270069b7SAdrian Chadd 		for (desc = ttos->modes[i].desc;
689*270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
690*270069b7SAdrian Chadd 			if (IFM_MODE(ifmw) == desc->ifmt_word)
691*270069b7SAdrian Chadd 				return desc;
692*270069b7SAdrian Chadd 		}
693*270069b7SAdrian Chadd 	}
694*270069b7SAdrian Chadd 
695*270069b7SAdrian Chadd 	return NULL;
696*270069b7SAdrian Chadd }
697*270069b7SAdrian Chadd 
698*270069b7SAdrian Chadd void
699*270069b7SAdrian Chadd print_media_word(int ifmw, int print_toptype)
700*270069b7SAdrian Chadd {
701*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
702*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
703*270069b7SAdrian Chadd 	int seen_option = 0, i;
704*270069b7SAdrian Chadd 
705*270069b7SAdrian Chadd 	/* Find the top-level interface type. */
706*270069b7SAdrian Chadd 	desc = get_toptype_desc(ifmw);
707*270069b7SAdrian Chadd 	ttos = get_toptype_ttos(ifmw);
708*270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL) {
709*270069b7SAdrian Chadd 		printf("<unknown type>");
710*270069b7SAdrian Chadd 		return;
711*270069b7SAdrian Chadd 	} else if (print_toptype) {
712*270069b7SAdrian Chadd 		printf("%s", desc->ifmt_string);
713*270069b7SAdrian Chadd 	}
714*270069b7SAdrian Chadd 
715*270069b7SAdrian Chadd 	/*
716*270069b7SAdrian Chadd 	 * Don't print the top-level type; it's not like we can
717*270069b7SAdrian Chadd 	 * change it, or anything.
718*270069b7SAdrian Chadd 	 */
719*270069b7SAdrian Chadd 
720*270069b7SAdrian Chadd 	/* Find subtype. */
721*270069b7SAdrian Chadd 	desc = get_subtype_desc(ifmw, ttos);
722*270069b7SAdrian Chadd 	if (desc == NULL) {
723*270069b7SAdrian Chadd 		printf("<unknown subtype>");
724*270069b7SAdrian Chadd 		return;
725*270069b7SAdrian Chadd 	}
726*270069b7SAdrian Chadd 
727*270069b7SAdrian Chadd 	if (print_toptype)
728*270069b7SAdrian Chadd 		putchar(' ');
729*270069b7SAdrian Chadd 
730*270069b7SAdrian Chadd 	printf("%s", desc->ifmt_string);
731*270069b7SAdrian Chadd 
732*270069b7SAdrian Chadd 	if (print_toptype) {
733*270069b7SAdrian Chadd 		desc = get_mode_desc(ifmw, ttos);
734*270069b7SAdrian Chadd 		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
735*270069b7SAdrian Chadd 			printf(" mode %s", desc->ifmt_string);
736*270069b7SAdrian Chadd 	}
737*270069b7SAdrian Chadd 
738*270069b7SAdrian Chadd 	/* Find options. */
739*270069b7SAdrian Chadd 	for (i = 0; ttos->options[i].desc != NULL; i++) {
740*270069b7SAdrian Chadd 		if (ttos->options[i].alias)
741*270069b7SAdrian Chadd 			continue;
742*270069b7SAdrian Chadd 		for (desc = ttos->options[i].desc;
743*270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
744*270069b7SAdrian Chadd 			if (ifmw & desc->ifmt_word) {
745*270069b7SAdrian Chadd 				if (seen_option == 0)
746*270069b7SAdrian Chadd 					printf(" <");
747*270069b7SAdrian Chadd 				printf("%s%s", seen_option++ ? "," : "",
748*270069b7SAdrian Chadd 				    desc->ifmt_string);
749*270069b7SAdrian Chadd 			}
750*270069b7SAdrian Chadd 		}
751*270069b7SAdrian Chadd 	}
752*270069b7SAdrian Chadd 	printf("%s", seen_option ? ">" : "");
753*270069b7SAdrian Chadd 
754*270069b7SAdrian Chadd 	if (print_toptype && IFM_INST(ifmw) != 0)
755*270069b7SAdrian Chadd 		printf(" instance %d", IFM_INST(ifmw));
756*270069b7SAdrian Chadd }
757*270069b7SAdrian Chadd 
758*270069b7SAdrian Chadd void
759*270069b7SAdrian Chadd print_media_word_ifconfig(int ifmw)
760*270069b7SAdrian Chadd {
761*270069b7SAdrian Chadd 	struct ifmedia_description *desc;
762*270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
763*270069b7SAdrian Chadd 	int seen_option = 0, i;
764*270069b7SAdrian Chadd 
765*270069b7SAdrian Chadd 	/* Find the top-level interface type. */
766*270069b7SAdrian Chadd 	desc = get_toptype_desc(ifmw);
767*270069b7SAdrian Chadd 	ttos = get_toptype_ttos(ifmw);
768*270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL) {
769*270069b7SAdrian Chadd 		printf("<unknown type>");
770*270069b7SAdrian Chadd 		return;
771*270069b7SAdrian Chadd 	}
772*270069b7SAdrian Chadd 
773*270069b7SAdrian Chadd 	/*
774*270069b7SAdrian Chadd 	 * Don't print the top-level type; it's not like we can
775*270069b7SAdrian Chadd 	 * change it, or anything.
776*270069b7SAdrian Chadd 	 */
777*270069b7SAdrian Chadd 
778*270069b7SAdrian Chadd 	/* Find subtype. */
779*270069b7SAdrian Chadd 	desc = get_subtype_desc(ifmw, ttos);
780*270069b7SAdrian Chadd 	if (desc == NULL) {
781*270069b7SAdrian Chadd 		printf("<unknown subtype>");
782*270069b7SAdrian Chadd 		return;
783*270069b7SAdrian Chadd 	}
784*270069b7SAdrian Chadd 
785*270069b7SAdrian Chadd 	printf("media %s", desc->ifmt_string);
786*270069b7SAdrian Chadd 
787*270069b7SAdrian Chadd 	desc = get_mode_desc(ifmw, ttos);
788*270069b7SAdrian Chadd 	if (desc != NULL)
789*270069b7SAdrian Chadd 		printf(" mode %s", desc->ifmt_string);
790*270069b7SAdrian Chadd 
791*270069b7SAdrian Chadd 	/* Find options. */
792*270069b7SAdrian Chadd 	for (i = 0; ttos->options[i].desc != NULL; i++) {
793*270069b7SAdrian Chadd 		if (ttos->options[i].alias)
794*270069b7SAdrian Chadd 			continue;
795*270069b7SAdrian Chadd 		for (desc = ttos->options[i].desc;
796*270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
797*270069b7SAdrian Chadd 			if (ifmw & desc->ifmt_word) {
798*270069b7SAdrian Chadd 				if (seen_option == 0)
799*270069b7SAdrian Chadd 					printf(" mediaopt ");
800*270069b7SAdrian Chadd 				printf("%s%s", seen_option++ ? "," : "",
801*270069b7SAdrian Chadd 				    desc->ifmt_string);
802*270069b7SAdrian Chadd 			}
803*270069b7SAdrian Chadd 		}
804*270069b7SAdrian Chadd 	}
805*270069b7SAdrian Chadd 
806*270069b7SAdrian Chadd 	if (IFM_INST(ifmw) != 0)
807*270069b7SAdrian Chadd 		printf(" instance %d", IFM_INST(ifmw));
808*270069b7SAdrian Chadd }
809*270069b7SAdrian Chadd 
810*270069b7SAdrian Chadd /**********************************************************************
811*270069b7SAdrian Chadd  * ...until here.
812*270069b7SAdrian Chadd  **********************************************************************/
813