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