xref: /freebsd/sbin/etherswitchcfg/ifmedia.c (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
1270069b7SAdrian Chadd /*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
2270069b7SAdrian Chadd 
3*df57947fSPedro F. Giffuni /*-
4*df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
5*df57947fSPedro F. Giffuni  *
6270069b7SAdrian Chadd  * Copyright (c) 1997 Jason R. Thorpe.
7270069b7SAdrian Chadd  * All rights reserved.
8270069b7SAdrian Chadd  *
9270069b7SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
10270069b7SAdrian Chadd  * modification, are permitted provided that the following conditions
11270069b7SAdrian Chadd  * are met:
12270069b7SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
13270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
14270069b7SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
15270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
16270069b7SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
17270069b7SAdrian Chadd  * 3. All advertising materials mentioning features or use of this software
18270069b7SAdrian Chadd  *    must display the following acknowledgement:
19270069b7SAdrian Chadd  *      This product includes software developed for the NetBSD Project
20270069b7SAdrian Chadd  *	by Jason R. Thorpe.
21270069b7SAdrian Chadd  * 4. The name of the author may not be used to endorse or promote products
22270069b7SAdrian Chadd  *    derived from this software without specific prior written permission.
23270069b7SAdrian Chadd  *
24270069b7SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25270069b7SAdrian Chadd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26270069b7SAdrian Chadd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27270069b7SAdrian Chadd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28270069b7SAdrian Chadd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29270069b7SAdrian Chadd  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30270069b7SAdrian Chadd  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31270069b7SAdrian Chadd  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32270069b7SAdrian Chadd  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33270069b7SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34270069b7SAdrian Chadd  * SUCH DAMAGE.
35270069b7SAdrian Chadd  */
36270069b7SAdrian Chadd 
37270069b7SAdrian Chadd /*
38270069b7SAdrian Chadd  * Copyright (c) 1983, 1993
39270069b7SAdrian Chadd  *	The Regents of the University of California.  All rights reserved.
40270069b7SAdrian Chadd  *
41270069b7SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
42270069b7SAdrian Chadd  * modification, are permitted provided that the following conditions
43270069b7SAdrian Chadd  * are met:
44270069b7SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
45270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
46270069b7SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
47270069b7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
48270069b7SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
49270069b7SAdrian Chadd  * 4. Neither the name of the University nor the names of its contributors
50270069b7SAdrian Chadd  *    may be used to endorse or promote products derived from this software
51270069b7SAdrian Chadd  *    without specific prior written permission.
52270069b7SAdrian Chadd  *
53270069b7SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54270069b7SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55270069b7SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56270069b7SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57270069b7SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58270069b7SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59270069b7SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60270069b7SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61270069b7SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62270069b7SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63270069b7SAdrian Chadd  * SUCH DAMAGE.
64270069b7SAdrian Chadd  */
65270069b7SAdrian Chadd /*
66270069b7SAdrian Chadd  * based on sbin/ifconfig/ifmedia.c r221954
67270069b7SAdrian Chadd  */
68270069b7SAdrian Chadd 
69270069b7SAdrian Chadd #include <sys/param.h>
70270069b7SAdrian Chadd #include <sys/ioctl.h>
71270069b7SAdrian Chadd #include <sys/socket.h>
72270069b7SAdrian Chadd #include <sys/sysctl.h>
73270069b7SAdrian Chadd #include <sys/time.h>
74270069b7SAdrian Chadd 
75270069b7SAdrian Chadd #include <net/if.h>
76270069b7SAdrian Chadd #include <net/if_dl.h>
77270069b7SAdrian Chadd #include <net/if_types.h>
78270069b7SAdrian Chadd #include <net/if_media.h>
79270069b7SAdrian Chadd #include <net/route.h>
80270069b7SAdrian Chadd 
81270069b7SAdrian Chadd #include <ctype.h>
82270069b7SAdrian Chadd #include <err.h>
83270069b7SAdrian Chadd #include <errno.h>
84270069b7SAdrian Chadd #include <fcntl.h>
85270069b7SAdrian Chadd #include <stdio.h>
86270069b7SAdrian Chadd #include <stdlib.h>
87270069b7SAdrian Chadd #include <string.h>
88270069b7SAdrian Chadd #include <unistd.h>
89270069b7SAdrian Chadd 
90270069b7SAdrian Chadd void	domediaopt(const char *, int, int);
91270069b7SAdrian Chadd int	get_media_subtype(int, const char *);
92270069b7SAdrian Chadd int	get_media_mode(int, const char *);
93270069b7SAdrian Chadd int	get_media_options(int, const char *);
94270069b7SAdrian Chadd int	lookup_media_word(struct ifmedia_description *, const char *);
95270069b7SAdrian Chadd void	print_media_word(int, int);
96270069b7SAdrian Chadd void	print_media_word_ifconfig(int);
97270069b7SAdrian Chadd 
98270069b7SAdrian Chadd #if 0
99270069b7SAdrian Chadd static struct ifmedia_description *get_toptype_desc(int);
100270069b7SAdrian Chadd static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
101270069b7SAdrian Chadd static struct ifmedia_description *get_subtype_desc(int,
102270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos);
103270069b7SAdrian Chadd 
104270069b7SAdrian Chadd #define	IFM_OPMODE(x) \
105270069b7SAdrian Chadd 	((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
106270069b7SAdrian Chadd 	 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
107270069b7SAdrian Chadd 	 IFM_IEEE80211_MBSS))
108270069b7SAdrian Chadd #define	IFM_IEEE80211_STA	0
109270069b7SAdrian Chadd 
110270069b7SAdrian Chadd static void
111270069b7SAdrian Chadd media_status(int s)
112270069b7SAdrian Chadd {
113270069b7SAdrian Chadd 	struct ifmediareq ifmr;
114270069b7SAdrian Chadd 	int *media_list, i;
115270069b7SAdrian Chadd 
116270069b7SAdrian Chadd 	(void) memset(&ifmr, 0, sizeof(ifmr));
117270069b7SAdrian Chadd 	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
118270069b7SAdrian Chadd 
119270069b7SAdrian Chadd 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
120270069b7SAdrian Chadd 		/*
121270069b7SAdrian Chadd 		 * Interface doesn't support SIOC{G,S}IFMEDIA.
122270069b7SAdrian Chadd 		 */
123270069b7SAdrian Chadd 		return;
124270069b7SAdrian Chadd 	}
125270069b7SAdrian Chadd 
126270069b7SAdrian Chadd 	if (ifmr.ifm_count == 0) {
127270069b7SAdrian Chadd 		warnx("%s: no media types?", name);
128270069b7SAdrian Chadd 		return;
129270069b7SAdrian Chadd 	}
130270069b7SAdrian Chadd 
131270069b7SAdrian Chadd 	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
132270069b7SAdrian Chadd 	if (media_list == NULL)
133270069b7SAdrian Chadd 		err(1, "malloc");
134270069b7SAdrian Chadd 	ifmr.ifm_ulist = media_list;
135270069b7SAdrian Chadd 
136270069b7SAdrian Chadd 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
137270069b7SAdrian Chadd 		err(1, "SIOCGIFMEDIA");
138270069b7SAdrian Chadd 
139270069b7SAdrian Chadd 	printf("\tmedia: ");
140270069b7SAdrian Chadd 	print_media_word(ifmr.ifm_current, 1);
141270069b7SAdrian Chadd 	if (ifmr.ifm_active != ifmr.ifm_current) {
142270069b7SAdrian Chadd 		putchar(' ');
143270069b7SAdrian Chadd 		putchar('(');
144270069b7SAdrian Chadd 		print_media_word(ifmr.ifm_active, 0);
145270069b7SAdrian Chadd 		putchar(')');
146270069b7SAdrian Chadd 	}
147270069b7SAdrian Chadd 
148270069b7SAdrian Chadd 	putchar('\n');
149270069b7SAdrian Chadd 
150270069b7SAdrian Chadd 	if (ifmr.ifm_status & IFM_AVALID) {
151270069b7SAdrian Chadd 		printf("\tstatus: ");
152270069b7SAdrian Chadd 		switch (IFM_TYPE(ifmr.ifm_active)) {
153270069b7SAdrian Chadd 		case IFM_ETHER:
154270069b7SAdrian Chadd 		case IFM_ATM:
155270069b7SAdrian Chadd 			if (ifmr.ifm_status & IFM_ACTIVE)
156270069b7SAdrian Chadd 				printf("active");
157270069b7SAdrian Chadd 			else
158270069b7SAdrian Chadd 				printf("no carrier");
159270069b7SAdrian Chadd 			break;
160270069b7SAdrian Chadd 
161270069b7SAdrian Chadd 		case IFM_IEEE80211:
162270069b7SAdrian Chadd 			if (ifmr.ifm_status & IFM_ACTIVE) {
163270069b7SAdrian Chadd 				/* NB: only sta mode associates */
164270069b7SAdrian Chadd 				if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
165270069b7SAdrian Chadd 					printf("associated");
166270069b7SAdrian Chadd 				else
167270069b7SAdrian Chadd 					printf("running");
168270069b7SAdrian Chadd 			} else
169270069b7SAdrian Chadd 				printf("no carrier");
170270069b7SAdrian Chadd 			break;
171270069b7SAdrian Chadd 		}
172270069b7SAdrian Chadd 		putchar('\n');
173270069b7SAdrian Chadd 	}
174270069b7SAdrian Chadd 
175270069b7SAdrian Chadd 	if (ifmr.ifm_count > 0 && supmedia) {
176270069b7SAdrian Chadd 		printf("\tsupported media:\n");
177270069b7SAdrian Chadd 		for (i = 0; i < ifmr.ifm_count; i++) {
178270069b7SAdrian Chadd 			printf("\t\t");
179270069b7SAdrian Chadd 			print_media_word_ifconfig(media_list[i]);
180270069b7SAdrian Chadd 			putchar('\n');
181270069b7SAdrian Chadd 		}
182270069b7SAdrian Chadd 	}
183270069b7SAdrian Chadd 
184270069b7SAdrian Chadd 	free(media_list);
185270069b7SAdrian Chadd }
186270069b7SAdrian Chadd 
187270069b7SAdrian Chadd struct ifmediareq *
188270069b7SAdrian Chadd ifmedia_getstate(int s)
189270069b7SAdrian Chadd {
190270069b7SAdrian Chadd 	static struct ifmediareq *ifmr = NULL;
191270069b7SAdrian Chadd 	int *mwords;
192270069b7SAdrian Chadd 
193270069b7SAdrian Chadd 	if (ifmr == NULL) {
194270069b7SAdrian Chadd 		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
195270069b7SAdrian Chadd 		if (ifmr == NULL)
196270069b7SAdrian Chadd 			err(1, "malloc");
197270069b7SAdrian Chadd 
198270069b7SAdrian Chadd 		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
199270069b7SAdrian Chadd 		(void) strncpy(ifmr->ifm_name, name,
200270069b7SAdrian Chadd 		    sizeof(ifmr->ifm_name));
201270069b7SAdrian Chadd 
202270069b7SAdrian Chadd 		ifmr->ifm_count = 0;
203270069b7SAdrian Chadd 		ifmr->ifm_ulist = NULL;
204270069b7SAdrian Chadd 
205270069b7SAdrian Chadd 		/*
206270069b7SAdrian Chadd 		 * We must go through the motions of reading all
207270069b7SAdrian Chadd 		 * supported media because we need to know both
208270069b7SAdrian Chadd 		 * the current media type and the top-level type.
209270069b7SAdrian Chadd 		 */
210270069b7SAdrian Chadd 
211270069b7SAdrian Chadd 		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
212270069b7SAdrian Chadd 			err(1, "SIOCGIFMEDIA");
213270069b7SAdrian Chadd 		}
214270069b7SAdrian Chadd 
215270069b7SAdrian Chadd 		if (ifmr->ifm_count == 0)
216270069b7SAdrian Chadd 			errx(1, "%s: no media types?", name);
217270069b7SAdrian Chadd 
218270069b7SAdrian Chadd 		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
219270069b7SAdrian Chadd 		if (mwords == NULL)
220270069b7SAdrian Chadd 			err(1, "malloc");
221270069b7SAdrian Chadd 
222270069b7SAdrian Chadd 		ifmr->ifm_ulist = mwords;
223270069b7SAdrian Chadd 		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
224270069b7SAdrian Chadd 			err(1, "SIOCGIFMEDIA");
225270069b7SAdrian Chadd 	}
226270069b7SAdrian Chadd 
227270069b7SAdrian Chadd 	return ifmr;
228270069b7SAdrian Chadd }
229270069b7SAdrian Chadd 
230270069b7SAdrian Chadd static void
231270069b7SAdrian Chadd setifmediacallback(int s, void *arg)
232270069b7SAdrian Chadd {
233270069b7SAdrian Chadd 	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
234270069b7SAdrian Chadd 	static int did_it = 0;
235270069b7SAdrian Chadd 
236270069b7SAdrian Chadd 	if (!did_it) {
237270069b7SAdrian Chadd 		ifr.ifr_media = ifmr->ifm_current;
238270069b7SAdrian Chadd 		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
239270069b7SAdrian Chadd 			err(1, "SIOCSIFMEDIA (media)");
240270069b7SAdrian Chadd 		free(ifmr->ifm_ulist);
241270069b7SAdrian Chadd 		free(ifmr);
242270069b7SAdrian Chadd 		did_it = 1;
243270069b7SAdrian Chadd 	}
244270069b7SAdrian Chadd }
245270069b7SAdrian Chadd 
246270069b7SAdrian Chadd static void
247270069b7SAdrian Chadd setmedia(const char *val, int d, int s, const struct afswtch *afp)
248270069b7SAdrian Chadd {
249270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
250270069b7SAdrian Chadd 	int subtype;
251270069b7SAdrian Chadd 
252270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
253270069b7SAdrian Chadd 
254270069b7SAdrian Chadd 	/*
255270069b7SAdrian Chadd 	 * We are primarily concerned with the top-level type.
256270069b7SAdrian Chadd 	 * However, "current" may be only IFM_NONE, so we just look
257270069b7SAdrian Chadd 	 * for the top-level type in the first "supported type"
258270069b7SAdrian Chadd 	 * entry.
259270069b7SAdrian Chadd 	 *
260270069b7SAdrian Chadd 	 * (I'm assuming that all supported media types for a given
261270069b7SAdrian Chadd 	 * interface will be the same top-level type..)
262270069b7SAdrian Chadd 	 */
263270069b7SAdrian Chadd 	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
264270069b7SAdrian Chadd 
265270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
266270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
267270069b7SAdrian Chadd 	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
268270069b7SAdrian Chadd 
269270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
270270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
271270069b7SAdrian Chadd }
272270069b7SAdrian Chadd 
273270069b7SAdrian Chadd static void
274270069b7SAdrian Chadd setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
275270069b7SAdrian Chadd {
276270069b7SAdrian Chadd 
277270069b7SAdrian Chadd 	domediaopt(val, 0, s);
278270069b7SAdrian Chadd }
279270069b7SAdrian Chadd 
280270069b7SAdrian Chadd static void
281270069b7SAdrian Chadd unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
282270069b7SAdrian Chadd {
283270069b7SAdrian Chadd 
284270069b7SAdrian Chadd 	domediaopt(val, 1, s);
285270069b7SAdrian Chadd }
286270069b7SAdrian Chadd 
287270069b7SAdrian Chadd static void
288270069b7SAdrian Chadd domediaopt(const char *val, int clear, int s)
289270069b7SAdrian Chadd {
290270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
291270069b7SAdrian Chadd 	int options;
292270069b7SAdrian Chadd 
293270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
294270069b7SAdrian Chadd 
295270069b7SAdrian Chadd 	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
296270069b7SAdrian Chadd 
297270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
298270069b7SAdrian Chadd 	ifr.ifr_media = ifmr->ifm_current;
299270069b7SAdrian Chadd 	if (clear)
300270069b7SAdrian Chadd 		ifr.ifr_media &= ~options;
301270069b7SAdrian Chadd 	else {
302270069b7SAdrian Chadd 		if (options & IFM_HDX) {
303270069b7SAdrian Chadd 			ifr.ifr_media &= ~IFM_FDX;
304270069b7SAdrian Chadd 			options &= ~IFM_HDX;
305270069b7SAdrian Chadd 		}
306270069b7SAdrian Chadd 		ifr.ifr_media |= options;
307270069b7SAdrian Chadd 	}
308270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
309270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
310270069b7SAdrian Chadd }
311270069b7SAdrian Chadd 
312270069b7SAdrian Chadd static void
313270069b7SAdrian Chadd setmediainst(const char *val, int d, int s, const struct afswtch *afp)
314270069b7SAdrian Chadd {
315270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
316270069b7SAdrian Chadd 	int inst;
317270069b7SAdrian Chadd 
318270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
319270069b7SAdrian Chadd 
320270069b7SAdrian Chadd 	inst = atoi(val);
321270069b7SAdrian Chadd 	if (inst < 0 || inst > (int)IFM_INST_MAX)
322270069b7SAdrian Chadd 		errx(1, "invalid media instance: %s", val);
323270069b7SAdrian Chadd 
324270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
325270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
326270069b7SAdrian Chadd 
327270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
328270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
329270069b7SAdrian Chadd }
330270069b7SAdrian Chadd 
331270069b7SAdrian Chadd static void
332270069b7SAdrian Chadd setmediamode(const char *val, int d, int s, const struct afswtch *afp)
333270069b7SAdrian Chadd {
334270069b7SAdrian Chadd 	struct ifmediareq *ifmr;
335270069b7SAdrian Chadd 	int mode;
336270069b7SAdrian Chadd 
337270069b7SAdrian Chadd 	ifmr = ifmedia_getstate(s);
338270069b7SAdrian Chadd 
339270069b7SAdrian Chadd 	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
340270069b7SAdrian Chadd 
341270069b7SAdrian Chadd 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
342270069b7SAdrian Chadd 	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
343270069b7SAdrian Chadd 
344270069b7SAdrian Chadd 	ifmr->ifm_current = ifr.ifr_media;
345270069b7SAdrian Chadd 	callback_register(setifmediacallback, (void *)ifmr);
346270069b7SAdrian Chadd }
347270069b7SAdrian Chadd #endif
348270069b7SAdrian Chadd 
349270069b7SAdrian Chadd /**********************************************************************
350270069b7SAdrian Chadd  * A good chunk of this is duplicated from sys/net/ifmedia.c
351270069b7SAdrian Chadd  **********************************************************************/
352270069b7SAdrian Chadd 
353270069b7SAdrian Chadd static struct ifmedia_description ifm_type_descriptions[] =
354270069b7SAdrian Chadd     IFM_TYPE_DESCRIPTIONS;
355270069b7SAdrian Chadd 
356270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
357270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
358270069b7SAdrian Chadd 
359270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
360270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_ALIASES;
361270069b7SAdrian Chadd 
362270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
363270069b7SAdrian Chadd     IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
364270069b7SAdrian Chadd 
365270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
366270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
367270069b7SAdrian Chadd 
368270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
369270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_ALIASES;
370270069b7SAdrian Chadd 
371270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
372270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
373270069b7SAdrian Chadd 
374ae824d80SEd Schouten static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
375270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
376270069b7SAdrian Chadd 
377ae824d80SEd Schouten static struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
378270069b7SAdrian Chadd     IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
379270069b7SAdrian Chadd 
380270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_descriptions[] =
381270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_DESCRIPTIONS;
382270069b7SAdrian Chadd 
383270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_aliases[] =
384270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_ALIASES;
385270069b7SAdrian Chadd 
386270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
387270069b7SAdrian Chadd     IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
388270069b7SAdrian Chadd 
389270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_shared_descriptions[] =
390270069b7SAdrian Chadd     IFM_SUBTYPE_SHARED_DESCRIPTIONS;
391270069b7SAdrian Chadd 
392270069b7SAdrian Chadd static struct ifmedia_description ifm_subtype_shared_aliases[] =
393270069b7SAdrian Chadd     IFM_SUBTYPE_SHARED_ALIASES;
394270069b7SAdrian Chadd 
395270069b7SAdrian Chadd static struct ifmedia_description ifm_shared_option_descriptions[] =
396270069b7SAdrian Chadd     IFM_SHARED_OPTION_DESCRIPTIONS;
397270069b7SAdrian Chadd 
398270069b7SAdrian Chadd static struct ifmedia_description ifm_shared_option_aliases[] =
399270069b7SAdrian Chadd     IFM_SHARED_OPTION_ALIASES;
400270069b7SAdrian Chadd 
401270069b7SAdrian Chadd struct ifmedia_type_to_subtype {
402270069b7SAdrian Chadd 	struct {
403270069b7SAdrian Chadd 		struct ifmedia_description *desc;
404270069b7SAdrian Chadd 		int alias;
405270069b7SAdrian Chadd 	} subtypes[5];
406270069b7SAdrian Chadd 	struct {
407270069b7SAdrian Chadd 		struct ifmedia_description *desc;
408270069b7SAdrian Chadd 		int alias;
409270069b7SAdrian Chadd 	} options[4];
410270069b7SAdrian Chadd 	struct {
411270069b7SAdrian Chadd 		struct ifmedia_description *desc;
412270069b7SAdrian Chadd 		int alias;
413270069b7SAdrian Chadd 	} modes[3];
414270069b7SAdrian Chadd };
415270069b7SAdrian Chadd 
416270069b7SAdrian Chadd /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
417270069b7SAdrian Chadd static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
418270069b7SAdrian Chadd 	{
419270069b7SAdrian Chadd 		{
420270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
421270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
422270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_descriptions[0], 0 },
423270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_aliases[0], 1 },
424270069b7SAdrian Chadd 			{ NULL, 0 },
425270069b7SAdrian Chadd 		},
426270069b7SAdrian Chadd 		{
427270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
428270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
429270069b7SAdrian Chadd 			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
430270069b7SAdrian Chadd 			{ NULL, 0 },
431270069b7SAdrian Chadd 		},
432270069b7SAdrian Chadd 		{
433270069b7SAdrian Chadd 			{ NULL, 0 },
434270069b7SAdrian Chadd 		},
435270069b7SAdrian Chadd 	},
436270069b7SAdrian Chadd 	{
437270069b7SAdrian Chadd 		{
438270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
439270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
440270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
441270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_aliases[0], 1 },
442270069b7SAdrian Chadd 			{ NULL, 0 },
443270069b7SAdrian Chadd 		},
444270069b7SAdrian Chadd 		{
445270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
446270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
447270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
448270069b7SAdrian Chadd 			{ NULL, 0 },
449270069b7SAdrian Chadd 		},
450270069b7SAdrian Chadd 		{
451270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
452270069b7SAdrian Chadd 			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
453270069b7SAdrian Chadd 			{ NULL, 0 },
454270069b7SAdrian Chadd 		},
455270069b7SAdrian Chadd 	},
456270069b7SAdrian Chadd 	{
457270069b7SAdrian Chadd 		{
458270069b7SAdrian Chadd 			{ &ifm_subtype_shared_descriptions[0], 0 },
459270069b7SAdrian Chadd 			{ &ifm_subtype_shared_aliases[0], 1 },
460270069b7SAdrian Chadd 			{ &ifm_subtype_atm_descriptions[0], 0 },
461270069b7SAdrian Chadd 			{ &ifm_subtype_atm_aliases[0], 1 },
462270069b7SAdrian Chadd 			{ NULL, 0 },
463270069b7SAdrian Chadd 		},
464270069b7SAdrian Chadd 		{
465270069b7SAdrian Chadd 			{ &ifm_shared_option_descriptions[0], 0 },
466270069b7SAdrian Chadd 			{ &ifm_shared_option_aliases[0], 1 },
467270069b7SAdrian Chadd 			{ &ifm_subtype_atm_option_descriptions[0], 0 },
468270069b7SAdrian Chadd 			{ NULL, 0 },
469270069b7SAdrian Chadd 		},
470270069b7SAdrian Chadd 		{
471270069b7SAdrian Chadd 			{ NULL, 0 },
472270069b7SAdrian Chadd 		},
473270069b7SAdrian Chadd 	},
474270069b7SAdrian Chadd };
475270069b7SAdrian Chadd 
476270069b7SAdrian Chadd int
get_media_subtype(int type,const char * val)477270069b7SAdrian Chadd get_media_subtype(int type, const char *val)
478270069b7SAdrian Chadd {
479270069b7SAdrian Chadd 	struct ifmedia_description *desc;
480270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
481270069b7SAdrian Chadd 	int rval, i;
482270069b7SAdrian Chadd 
483270069b7SAdrian Chadd 	/* Find the top-level interface type. */
484270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
485270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
486270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
487270069b7SAdrian Chadd 			break;
488270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
489270069b7SAdrian Chadd 		errx(1, "unknown media type 0x%x", type);
490270069b7SAdrian Chadd 
491270069b7SAdrian Chadd 	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
492270069b7SAdrian Chadd 		rval = lookup_media_word(ttos->subtypes[i].desc, val);
493270069b7SAdrian Chadd 		if (rval != -1)
494270069b7SAdrian Chadd 			return (rval);
495270069b7SAdrian Chadd 	}
496270069b7SAdrian Chadd 	errx(1, "unknown media subtype: %s", val);
497270069b7SAdrian Chadd 	/*NOTREACHED*/
498270069b7SAdrian Chadd }
499270069b7SAdrian Chadd 
500270069b7SAdrian Chadd int
get_media_mode(int type,const char * val)501270069b7SAdrian Chadd get_media_mode(int type, const char *val)
502270069b7SAdrian Chadd {
503270069b7SAdrian Chadd 	struct ifmedia_description *desc;
504270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
505270069b7SAdrian Chadd 	int rval, i;
506270069b7SAdrian Chadd 
507270069b7SAdrian Chadd 	/* Find the top-level interface type. */
508270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
509270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
510270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
511270069b7SAdrian Chadd 			break;
512270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
513270069b7SAdrian Chadd 		errx(1, "unknown media mode 0x%x", type);
514270069b7SAdrian Chadd 
515270069b7SAdrian Chadd 	for (i = 0; ttos->modes[i].desc != NULL; i++) {
516270069b7SAdrian Chadd 		rval = lookup_media_word(ttos->modes[i].desc, val);
517270069b7SAdrian Chadd 		if (rval != -1)
518270069b7SAdrian Chadd 			return (rval);
519270069b7SAdrian Chadd 	}
520270069b7SAdrian Chadd 	return -1;
521270069b7SAdrian Chadd }
522270069b7SAdrian Chadd 
523270069b7SAdrian Chadd int
get_media_options(int type,const char * val)524270069b7SAdrian Chadd get_media_options(int type, const char *val)
525270069b7SAdrian Chadd {
526270069b7SAdrian Chadd 	struct ifmedia_description *desc;
527270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
528270069b7SAdrian Chadd 	char *optlist, *optptr;
529270069b7SAdrian Chadd 	int option = 0, i, rval = 0;
530270069b7SAdrian Chadd 
531270069b7SAdrian Chadd 	/* We muck with the string, so copy it. */
532270069b7SAdrian Chadd 	optlist = strdup(val);
533270069b7SAdrian Chadd 	if (optlist == NULL)
534270069b7SAdrian Chadd 		err(1, "strdup");
535270069b7SAdrian Chadd 
536270069b7SAdrian Chadd 	/* Find the top-level interface type. */
537270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
538270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
539270069b7SAdrian Chadd 		if (type == desc->ifmt_word)
540270069b7SAdrian Chadd 			break;
541270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL)
542270069b7SAdrian Chadd 		errx(1, "unknown media type 0x%x", type);
543270069b7SAdrian Chadd 
544270069b7SAdrian Chadd 	/*
545270069b7SAdrian Chadd 	 * Look up the options in the user-provided comma-separated
546270069b7SAdrian Chadd 	 * list.
547270069b7SAdrian Chadd 	 */
548270069b7SAdrian Chadd 	optptr = optlist;
549270069b7SAdrian Chadd 	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
550270069b7SAdrian Chadd 		for (i = 0; ttos->options[i].desc != NULL; i++) {
551270069b7SAdrian Chadd 			option = lookup_media_word(ttos->options[i].desc, optptr);
552270069b7SAdrian Chadd 			if (option != -1)
553270069b7SAdrian Chadd 				break;
554270069b7SAdrian Chadd 		}
555270069b7SAdrian Chadd 		if (option == 0)
556270069b7SAdrian Chadd 			errx(1, "unknown option: %s", optptr);
557270069b7SAdrian Chadd 		rval |= option;
558270069b7SAdrian Chadd 	}
559270069b7SAdrian Chadd 
560270069b7SAdrian Chadd 	free(optlist);
561270069b7SAdrian Chadd 	return (rval);
562270069b7SAdrian Chadd }
563270069b7SAdrian Chadd 
564270069b7SAdrian Chadd int
lookup_media_word(struct ifmedia_description * desc,const char * val)565270069b7SAdrian Chadd lookup_media_word(struct ifmedia_description *desc, const char *val)
566270069b7SAdrian Chadd {
567270069b7SAdrian Chadd 
568270069b7SAdrian Chadd 	for (; desc->ifmt_string != NULL; desc++)
569270069b7SAdrian Chadd 		if (strcasecmp(desc->ifmt_string, val) == 0)
570270069b7SAdrian Chadd 			return (desc->ifmt_word);
571270069b7SAdrian Chadd 
572270069b7SAdrian Chadd 	return (-1);
573270069b7SAdrian Chadd }
574270069b7SAdrian Chadd 
get_toptype_desc(int ifmw)575270069b7SAdrian Chadd static struct ifmedia_description *get_toptype_desc(int ifmw)
576270069b7SAdrian Chadd {
577270069b7SAdrian Chadd 	struct ifmedia_description *desc;
578270069b7SAdrian Chadd 
579270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
580270069b7SAdrian Chadd 		if (IFM_TYPE(ifmw) == desc->ifmt_word)
581270069b7SAdrian Chadd 			break;
582270069b7SAdrian Chadd 
583270069b7SAdrian Chadd 	return desc;
584270069b7SAdrian Chadd }
585270069b7SAdrian Chadd 
get_toptype_ttos(int ifmw)586270069b7SAdrian Chadd static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
587270069b7SAdrian Chadd {
588270069b7SAdrian Chadd 	struct ifmedia_description *desc;
589270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
590270069b7SAdrian Chadd 
591270069b7SAdrian Chadd 	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
592270069b7SAdrian Chadd 	    desc->ifmt_string != NULL; desc++, ttos++)
593270069b7SAdrian Chadd 		if (IFM_TYPE(ifmw) == desc->ifmt_word)
594270069b7SAdrian Chadd 			break;
595270069b7SAdrian Chadd 
596270069b7SAdrian Chadd 	return ttos;
597270069b7SAdrian Chadd }
598270069b7SAdrian Chadd 
get_subtype_desc(int ifmw,struct ifmedia_type_to_subtype * ttos)599270069b7SAdrian Chadd static struct ifmedia_description *get_subtype_desc(int ifmw,
600270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos)
601270069b7SAdrian Chadd {
602270069b7SAdrian Chadd 	int i;
603270069b7SAdrian Chadd 	struct ifmedia_description *desc;
604270069b7SAdrian Chadd 
605270069b7SAdrian Chadd 	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
606270069b7SAdrian Chadd 		if (ttos->subtypes[i].alias)
607270069b7SAdrian Chadd 			continue;
608270069b7SAdrian Chadd 		for (desc = ttos->subtypes[i].desc;
609270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
610270069b7SAdrian Chadd 			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
611270069b7SAdrian Chadd 				return desc;
612270069b7SAdrian Chadd 		}
613270069b7SAdrian Chadd 	}
614270069b7SAdrian Chadd 
615270069b7SAdrian Chadd 	return NULL;
616270069b7SAdrian Chadd }
617270069b7SAdrian Chadd 
get_mode_desc(int ifmw,struct ifmedia_type_to_subtype * ttos)618270069b7SAdrian Chadd static struct ifmedia_description *get_mode_desc(int ifmw,
619270069b7SAdrian Chadd     struct ifmedia_type_to_subtype *ttos)
620270069b7SAdrian Chadd {
621270069b7SAdrian Chadd 	int i;
622270069b7SAdrian Chadd 	struct ifmedia_description *desc;
623270069b7SAdrian Chadd 
624270069b7SAdrian Chadd 	for (i = 0; ttos->modes[i].desc != NULL; i++) {
625270069b7SAdrian Chadd 		if (ttos->modes[i].alias)
626270069b7SAdrian Chadd 			continue;
627270069b7SAdrian Chadd 		for (desc = ttos->modes[i].desc;
628270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
629270069b7SAdrian Chadd 			if (IFM_MODE(ifmw) == desc->ifmt_word)
630270069b7SAdrian Chadd 				return desc;
631270069b7SAdrian Chadd 		}
632270069b7SAdrian Chadd 	}
633270069b7SAdrian Chadd 
634270069b7SAdrian Chadd 	return NULL;
635270069b7SAdrian Chadd }
636270069b7SAdrian Chadd 
637270069b7SAdrian Chadd void
print_media_word(int ifmw,int print_toptype)638270069b7SAdrian Chadd print_media_word(int ifmw, int print_toptype)
639270069b7SAdrian Chadd {
640270069b7SAdrian Chadd 	struct ifmedia_description *desc;
641270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
642270069b7SAdrian Chadd 	int seen_option = 0, i;
643270069b7SAdrian Chadd 
644270069b7SAdrian Chadd 	/* Find the top-level interface type. */
645270069b7SAdrian Chadd 	desc = get_toptype_desc(ifmw);
646270069b7SAdrian Chadd 	ttos = get_toptype_ttos(ifmw);
647270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL) {
648270069b7SAdrian Chadd 		printf("<unknown type>");
649270069b7SAdrian Chadd 		return;
650270069b7SAdrian Chadd 	} else if (print_toptype) {
651270069b7SAdrian Chadd 		printf("%s", desc->ifmt_string);
652270069b7SAdrian Chadd 	}
653270069b7SAdrian Chadd 
654270069b7SAdrian Chadd 	/*
655270069b7SAdrian Chadd 	 * Don't print the top-level type; it's not like we can
656270069b7SAdrian Chadd 	 * change it, or anything.
657270069b7SAdrian Chadd 	 */
658270069b7SAdrian Chadd 
659270069b7SAdrian Chadd 	/* Find subtype. */
660270069b7SAdrian Chadd 	desc = get_subtype_desc(ifmw, ttos);
661270069b7SAdrian Chadd 	if (desc == NULL) {
662270069b7SAdrian Chadd 		printf("<unknown subtype>");
663270069b7SAdrian Chadd 		return;
664270069b7SAdrian Chadd 	}
665270069b7SAdrian Chadd 
666270069b7SAdrian Chadd 	if (print_toptype)
667270069b7SAdrian Chadd 		putchar(' ');
668270069b7SAdrian Chadd 
669270069b7SAdrian Chadd 	printf("%s", desc->ifmt_string);
670270069b7SAdrian Chadd 
671270069b7SAdrian Chadd 	if (print_toptype) {
672270069b7SAdrian Chadd 		desc = get_mode_desc(ifmw, ttos);
673270069b7SAdrian Chadd 		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
674270069b7SAdrian Chadd 			printf(" mode %s", desc->ifmt_string);
675270069b7SAdrian Chadd 	}
676270069b7SAdrian Chadd 
677270069b7SAdrian Chadd 	/* Find options. */
678270069b7SAdrian Chadd 	for (i = 0; ttos->options[i].desc != NULL; i++) {
679270069b7SAdrian Chadd 		if (ttos->options[i].alias)
680270069b7SAdrian Chadd 			continue;
681270069b7SAdrian Chadd 		for (desc = ttos->options[i].desc;
682270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
683270069b7SAdrian Chadd 			if (ifmw & desc->ifmt_word) {
684270069b7SAdrian Chadd 				if (seen_option == 0)
685270069b7SAdrian Chadd 					printf(" <");
686270069b7SAdrian Chadd 				printf("%s%s", seen_option++ ? "," : "",
687270069b7SAdrian Chadd 				    desc->ifmt_string);
688270069b7SAdrian Chadd 			}
689270069b7SAdrian Chadd 		}
690270069b7SAdrian Chadd 	}
691270069b7SAdrian Chadd 	printf("%s", seen_option ? ">" : "");
692270069b7SAdrian Chadd 
693270069b7SAdrian Chadd 	if (print_toptype && IFM_INST(ifmw) != 0)
694270069b7SAdrian Chadd 		printf(" instance %d", IFM_INST(ifmw));
695270069b7SAdrian Chadd }
696270069b7SAdrian Chadd 
697270069b7SAdrian Chadd void
print_media_word_ifconfig(int ifmw)698270069b7SAdrian Chadd print_media_word_ifconfig(int ifmw)
699270069b7SAdrian Chadd {
700270069b7SAdrian Chadd 	struct ifmedia_description *desc;
701270069b7SAdrian Chadd 	struct ifmedia_type_to_subtype *ttos;
702270069b7SAdrian Chadd 	int seen_option = 0, i;
703270069b7SAdrian Chadd 
704270069b7SAdrian Chadd 	/* Find the top-level interface type. */
705270069b7SAdrian Chadd 	desc = get_toptype_desc(ifmw);
706270069b7SAdrian Chadd 	ttos = get_toptype_ttos(ifmw);
707270069b7SAdrian Chadd 	if (desc->ifmt_string == NULL) {
708270069b7SAdrian Chadd 		printf("<unknown type>");
709270069b7SAdrian Chadd 		return;
710270069b7SAdrian Chadd 	}
711270069b7SAdrian Chadd 
712270069b7SAdrian Chadd 	/*
713270069b7SAdrian Chadd 	 * Don't print the top-level type; it's not like we can
714270069b7SAdrian Chadd 	 * change it, or anything.
715270069b7SAdrian Chadd 	 */
716270069b7SAdrian Chadd 
717270069b7SAdrian Chadd 	/* Find subtype. */
718270069b7SAdrian Chadd 	desc = get_subtype_desc(ifmw, ttos);
719270069b7SAdrian Chadd 	if (desc == NULL) {
720270069b7SAdrian Chadd 		printf("<unknown subtype>");
721270069b7SAdrian Chadd 		return;
722270069b7SAdrian Chadd 	}
723270069b7SAdrian Chadd 
724270069b7SAdrian Chadd 	printf("media %s", desc->ifmt_string);
725270069b7SAdrian Chadd 
726270069b7SAdrian Chadd 	desc = get_mode_desc(ifmw, ttos);
727270069b7SAdrian Chadd 	if (desc != NULL)
728270069b7SAdrian Chadd 		printf(" mode %s", desc->ifmt_string);
729270069b7SAdrian Chadd 
730270069b7SAdrian Chadd 	/* Find options. */
731270069b7SAdrian Chadd 	for (i = 0; ttos->options[i].desc != NULL; i++) {
732270069b7SAdrian Chadd 		if (ttos->options[i].alias)
733270069b7SAdrian Chadd 			continue;
734270069b7SAdrian Chadd 		for (desc = ttos->options[i].desc;
735270069b7SAdrian Chadd 		    desc->ifmt_string != NULL; desc++) {
736270069b7SAdrian Chadd 			if (ifmw & desc->ifmt_word) {
737270069b7SAdrian Chadd 				if (seen_option == 0)
738270069b7SAdrian Chadd 					printf(" mediaopt ");
739270069b7SAdrian Chadd 				printf("%s%s", seen_option++ ? "," : "",
740270069b7SAdrian Chadd 				    desc->ifmt_string);
741270069b7SAdrian Chadd 			}
742270069b7SAdrian Chadd 		}
743270069b7SAdrian Chadd 	}
744270069b7SAdrian Chadd 
745270069b7SAdrian Chadd 	if (IFM_INST(ifmw) != 0)
746270069b7SAdrian Chadd 		printf(" instance %d", IFM_INST(ifmw));
747270069b7SAdrian Chadd }
748270069b7SAdrian Chadd 
749270069b7SAdrian Chadd /**********************************************************************
750270069b7SAdrian Chadd  * ...until here.
751270069b7SAdrian Chadd  **********************************************************************/
752