125450Speter/*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
250476Speter/* $FreeBSD: stable/11/sbin/ifconfig/ifmedia.c 352650 2019-09-24 06:37:01Z kib $ */
325450Speter
4331722Seadler/*
525450Speter * Copyright (c) 1997 Jason R. Thorpe.
625450Speter * All rights reserved.
725450Speter *
825450Speter * Redistribution and use in source and binary forms, with or without
925450Speter * modification, are permitted provided that the following conditions
1025450Speter * are met:
1125450Speter * 1. Redistributions of source code must retain the above copyright
1225450Speter *    notice, this list of conditions and the following disclaimer.
1325450Speter * 2. Redistributions in binary form must reproduce the above copyright
1425450Speter *    notice, this list of conditions and the following disclaimer in the
1525450Speter *    documentation and/or other materials provided with the distribution.
1625450Speter * 3. All advertising materials mentioning features or use of this software
1725450Speter *    must display the following acknowledgement:
1825450Speter *      This product includes software developed for the NetBSD Project
1925450Speter *	by Jason R. Thorpe.
2025450Speter * 4. The name of the author may not be used to endorse or promote products
2125450Speter *    derived from this software without specific prior written permission.
2225450Speter *
2325450Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2425450Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2525450Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2625450Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2725450Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2825450Speter * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2925450Speter * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
3025450Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3125450Speter * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3225450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3325450Speter * SUCH DAMAGE.
3425450Speter */
3525450Speter
3625450Speter/*
3725450Speter * Copyright (c) 1983, 1993
3825450Speter *	The Regents of the University of California.  All rights reserved.
3925450Speter *
4025450Speter * Redistribution and use in source and binary forms, with or without
4125450Speter * modification, are permitted provided that the following conditions
4225450Speter * are met:
4325450Speter * 1. Redistributions of source code must retain the above copyright
4425450Speter *    notice, this list of conditions and the following disclaimer.
4525450Speter * 2. Redistributions in binary form must reproduce the above copyright
4625450Speter *    notice, this list of conditions and the following disclaimer in the
4725450Speter *    documentation and/or other materials provided with the distribution.
4825450Speter * 4. Neither the name of the University nor the names of its contributors
4925450Speter *    may be used to endorse or promote products derived from this software
5025450Speter *    without specific prior written permission.
5125450Speter *
5225450Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5325450Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5425450Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5525450Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5625450Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5725450Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5825450Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5925450Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6025450Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6125450Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6225450Speter * SUCH DAMAGE.
6325450Speter */
6425450Speter
6525450Speter#include <sys/param.h>
6625450Speter#include <sys/ioctl.h>
6725450Speter#include <sys/socket.h>
6825450Speter#include <sys/sysctl.h>
6925450Speter#include <sys/time.h>
7025450Speter
7125450Speter#include <net/if.h>
7225450Speter#include <net/if_dl.h>
7325450Speter#include <net/if_types.h>
7425450Speter#include <net/if_media.h>
7525450Speter#include <net/route.h>
7625450Speter
7725450Speter#include <ctype.h>
7825450Speter#include <err.h>
7925450Speter#include <errno.h>
8025450Speter#include <fcntl.h>
81352650Skib#include <stdbool.h>
8225450Speter#include <stdio.h>
8325450Speter#include <stdlib.h>
8425450Speter#include <string.h>
8525450Speter#include <unistd.h>
8625450Speter
8725450Speter#include "ifconfig.h"
8825450Speter
8995005Simpstatic void	domediaopt(const char *, int, int);
9095005Simpstatic int	get_media_subtype(int, const char *);
91114164Ssamstatic int	get_media_mode(int, const char *);
9295005Simpstatic int	get_media_options(int, const char *);
9395005Simpstatic int	lookup_media_word(struct ifmedia_description *, const char *);
9495005Simpstatic void	print_media_word(int, int);
9595005Simpstatic void	print_media_word_ifconfig(int);
9625450Speter
9795005Simpstatic struct ifmedia_description *get_toptype_desc(int);
9895005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int);
9995005Simpstatic struct ifmedia_description *get_subtype_desc(int,
10095005Simp    struct ifmedia_type_to_subtype *ttos);
10177385Sphk
102178354Ssam#define	IFM_OPMODE(x) \
103178354Ssam	((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
104195618Srpaulo	 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
105195618Srpaulo	 IFM_IEEE80211_MBSS))
106178354Ssam#define	IFM_IEEE80211_STA	0
107178354Ssam
108138593Ssamstatic void
109139494Ssammedia_status(int s)
11025450Speter{
11125450Speter	struct ifmediareq ifmr;
112352650Skib	struct ifdownreason ifdr;
11325450Speter	int *media_list, i;
114352650Skib	bool no_carrier, xmedia;
11525450Speter
11625450Speter	(void) memset(&ifmr, 0, sizeof(ifmr));
117299873Struckman	(void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
118352650Skib	xmedia = true;
11925450Speter
120281236Serj	/*
121281236Serj	 * Check if interface supports extended media types.
122281236Serj	 */
123281236Serj	if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0)
124352650Skib		xmedia = false;
125352650Skib	if (!xmedia && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
12625450Speter		/*
12725450Speter		 * Interface doesn't support SIOC{G,S}IFMEDIA.
12825450Speter		 */
12925450Speter		return;
13025450Speter	}
13125450Speter
13225450Speter	if (ifmr.ifm_count == 0) {
13325450Speter		warnx("%s: no media types?", name);
13425450Speter		return;
13525450Speter	}
13625450Speter
13725450Speter	media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
13825450Speter	if (media_list == NULL)
13925450Speter		err(1, "malloc");
14025450Speter	ifmr.ifm_ulist = media_list;
14125450Speter
142281236Serj	if (xmedia) {
143281236Serj		if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0)
144281236Serj			err(1, "SIOCGIFXMEDIA");
145281236Serj	} else {
146281236Serj		if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
147281236Serj			err(1, "SIOCGIFMEDIA");
148281236Serj	}
14925450Speter
15025450Speter	printf("\tmedia: ");
15177385Sphk	print_media_word(ifmr.ifm_current, 1);
15225450Speter	if (ifmr.ifm_active != ifmr.ifm_current) {
15325450Speter		putchar(' ');
15425450Speter		putchar('(');
15577385Sphk		print_media_word(ifmr.ifm_active, 0);
15625450Speter		putchar(')');
15725450Speter	}
15825450Speter
15977385Sphk	putchar('\n');
16077385Sphk
16125450Speter	if (ifmr.ifm_status & IFM_AVALID) {
162352650Skib		no_carrier = false;
16377385Sphk		printf("\tstatus: ");
16425450Speter		switch (IFM_TYPE(ifmr.ifm_active)) {
16525450Speter		case IFM_ETHER:
166161536Sthomas		case IFM_ATM:
16725450Speter			if (ifmr.ifm_status & IFM_ACTIVE)
16825450Speter				printf("active");
16925450Speter			else
170352650Skib				no_carrier = true;
17125450Speter			break;
17225450Speter
17325450Speter		case IFM_FDDI:
17425450Speter		case IFM_TOKEN:
17525450Speter			if (ifmr.ifm_status & IFM_ACTIVE)
17625450Speter				printf("inserted");
17725450Speter			else
17825450Speter				printf("no ring");
17925450Speter			break;
180114232Sharti
18177217Sphk		case IFM_IEEE80211:
182178354Ssam			if (ifmr.ifm_status & IFM_ACTIVE) {
183178354Ssam				/* NB: only sta mode associates */
184178354Ssam				if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
185178354Ssam					printf("associated");
186178354Ssam				else
187178354Ssam					printf("running");
188178354Ssam			} else
189352650Skib				no_carrier = true;
19077217Sphk			break;
19125450Speter		}
192352650Skib		if (no_carrier) {
193352650Skib			printf("no carrier");
194352650Skib			memset(&ifdr, 0, sizeof(ifdr));
195352650Skib			strlcpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name));
196352650Skib			if (ioctl(s, SIOCGIFDOWNREASON, (caddr_t)&ifdr) == 0) {
197352650Skib				switch (ifdr.ifdr_reason) {
198352650Skib				case IFDR_REASON_MSG:
199352650Skib					printf(" (%s)", ifdr.ifdr_msg);
200352650Skib					break;
201352650Skib				case IFDR_REASON_VENDOR:
202352650Skib					printf(" (vendor code %d)",
203352650Skib					    ifdr.ifdr_vendor);
204352650Skib					break;
205352650Skib				default:
206352650Skib					break;
207352650Skib				}
208352650Skib			}
209352650Skib		}
21085853Syar		putchar('\n');
21125450Speter	}
21225450Speter
21377385Sphk	if (ifmr.ifm_count > 0 && supmedia) {
21477385Sphk		printf("\tsupported media:\n");
21525450Speter		for (i = 0; i < ifmr.ifm_count; i++) {
21677385Sphk			printf("\t\t");
21777385Sphk			print_media_word_ifconfig(media_list[i]);
21877385Sphk			putchar('\n');
21925450Speter		}
22025450Speter	}
22125450Speter
22225450Speter	free(media_list);
22325450Speter}
22425450Speter
225170531Ssamstruct ifmediareq *
226170531Ssamifmedia_getstate(int s)
22725450Speter{
228140913Sambrisko	static struct ifmediareq *ifmr = NULL;
229140913Sambrisko	int *mwords;
230281236Serj	int xmedia = 1;
23125450Speter
232140913Sambrisko	if (ifmr == NULL) {
233140913Sambrisko		ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
234140913Sambrisko		if (ifmr == NULL)
235140913Sambrisko			err(1, "malloc");
23625450Speter
237140913Sambrisko		(void) memset(ifmr, 0, sizeof(struct ifmediareq));
238299873Struckman		(void) strlcpy(ifmr->ifm_name, name,
239140913Sambrisko		    sizeof(ifmr->ifm_name));
240140913Sambrisko
241140913Sambrisko		ifmr->ifm_count = 0;
242140913Sambrisko		ifmr->ifm_ulist = NULL;
243140913Sambrisko
24425450Speter		/*
245140913Sambrisko		 * We must go through the motions of reading all
246140913Sambrisko		 * supported media because we need to know both
247140913Sambrisko		 * the current media type and the top-level type.
24825450Speter		 */
249140913Sambrisko
250281236Serj		if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) {
251281236Serj			xmedia = 0;
252281236Serj		}
253281236Serj		if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
25425450Speter			err(1, "SIOCGIFMEDIA");
255140913Sambrisko		}
256140913Sambrisko
257140913Sambrisko		if (ifmr->ifm_count == 0)
258140913Sambrisko			errx(1, "%s: no media types?", name);
259140913Sambrisko
260140913Sambrisko		mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
261140913Sambrisko		if (mwords == NULL)
262140913Sambrisko			err(1, "malloc");
263140913Sambrisko
264140913Sambrisko		ifmr->ifm_ulist = mwords;
265281236Serj		if (xmedia) {
266281236Serj			if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0)
267281236Serj				err(1, "SIOCGIFXMEDIA");
268281236Serj		} else {
269281236Serj			if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
270281236Serj				err(1, "SIOCGIFMEDIA");
271281236Serj		}
27225450Speter	}
27325450Speter
274140913Sambrisko	return ifmr;
275140913Sambrisko}
27625450Speter
277140913Sambriskostatic void
278140913Sambriskosetifmediacallback(int s, void *arg)
279140913Sambrisko{
280140913Sambrisko	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
281140913Sambrisko	static int did_it = 0;
282140913Sambrisko
283140913Sambrisko	if (!did_it) {
284154240Sambrisko		ifr.ifr_media = ifmr->ifm_current;
285140913Sambrisko		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
286140913Sambrisko			err(1, "SIOCSIFMEDIA (media)");
287140913Sambrisko		free(ifmr->ifm_ulist);
288140913Sambrisko		free(ifmr);
289140913Sambrisko		did_it = 1;
290140913Sambrisko	}
291140913Sambrisko}
292140913Sambrisko
293140913Sambriskostatic void
294140913Sambriskosetmedia(const char *val, int d, int s, const struct afswtch *afp)
295140913Sambrisko{
296140913Sambrisko	struct ifmediareq *ifmr;
297140913Sambrisko	int subtype;
298140913Sambrisko
299170531Ssam	ifmr = ifmedia_getstate(s);
300140913Sambrisko
30125450Speter	/*
30225450Speter	 * We are primarily concerned with the top-level type.
30325450Speter	 * However, "current" may be only IFM_NONE, so we just look
30425450Speter	 * for the top-level type in the first "supported type"
30525450Speter	 * entry.
30625450Speter	 *
30725450Speter	 * (I'm assuming that all supported media types for a given
30825450Speter	 * interface will be the same top-level type..)
30925450Speter	 */
310140913Sambrisko	subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
31125450Speter
312299873Struckman	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
313221954Smarius	ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
314140913Sambrisko	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
31525450Speter
316140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
317140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
31825450Speter}
31925450Speter
320138593Ssamstatic void
32195005Simpsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
32225450Speter{
32325450Speter
32425450Speter	domediaopt(val, 0, s);
32525450Speter}
32625450Speter
327138593Ssamstatic void
32895005Simpunsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
32925450Speter{
33025450Speter
33125450Speter	domediaopt(val, 1, s);
33225450Speter}
33325450Speter
33425450Speterstatic void
33595005Simpdomediaopt(const char *val, int clear, int s)
33625450Speter{
337140913Sambrisko	struct ifmediareq *ifmr;
338140913Sambrisko	int options;
33925450Speter
340170531Ssam	ifmr = ifmedia_getstate(s);
34125450Speter
342140913Sambrisko	options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
34325450Speter
344299873Struckman	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
345140913Sambrisko	ifr.ifr_media = ifmr->ifm_current;
34625450Speter	if (clear)
34725450Speter		ifr.ifr_media &= ~options;
348165359Sjkim	else {
349165359Sjkim		if (options & IFM_HDX) {
350165359Sjkim			ifr.ifr_media &= ~IFM_FDX;
351165359Sjkim			options &= ~IFM_HDX;
352165359Sjkim		}
35325450Speter		ifr.ifr_media |= options;
354165359Sjkim	}
355140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
356140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
35725450Speter}
35825450Speter
359166113Smariusstatic void
360166113Smariussetmediainst(const char *val, int d, int s, const struct afswtch *afp)
361166113Smarius{
362166113Smarius	struct ifmediareq *ifmr;
363166113Smarius	int inst;
364114164Ssam
365170531Ssam	ifmr = ifmedia_getstate(s);
366166113Smarius
367166113Smarius	inst = atoi(val);
368194799Sdelphij	if (inst < 0 || inst > (int)IFM_INST_MAX)
369166113Smarius		errx(1, "invalid media instance: %s", val);
370166113Smarius
371299873Struckman	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
372166113Smarius	ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
373166113Smarius
374166113Smarius	ifmr->ifm_current = ifr.ifr_media;
375166113Smarius	callback_register(setifmediacallback, (void *)ifmr);
376166113Smarius}
377166113Smarius
378138593Ssamstatic void
379114164Ssamsetmediamode(const char *val, int d, int s, const struct afswtch *afp)
380114164Ssam{
381140913Sambrisko	struct ifmediareq *ifmr;
382140913Sambrisko	int mode;
383114164Ssam
384170531Ssam	ifmr = ifmedia_getstate(s);
385114164Ssam
386140913Sambrisko	mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
387114164Ssam
388299873Struckman	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
389140913Sambrisko	ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
390114164Ssam
391140913Sambrisko	ifmr->ifm_current = ifr.ifr_media;
392140913Sambrisko	callback_register(setifmediacallback, (void *)ifmr);
393114164Ssam}
394114164Ssam
39525450Speter/**********************************************************************
39625450Speter * A good chunk of this is duplicated from sys/net/ifmedia.c
39725450Speter **********************************************************************/
39825450Speter
39925450Speterstatic struct ifmedia_description ifm_type_descriptions[] =
40025450Speter    IFM_TYPE_DESCRIPTIONS;
40125450Speter
40225450Speterstatic struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
40325450Speter    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
40425450Speter
40525450Speterstatic struct ifmedia_description ifm_subtype_ethernet_aliases[] =
40625450Speter    IFM_SUBTYPE_ETHERNET_ALIASES;
40725450Speter
40825450Speterstatic struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
40925450Speter    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
41025450Speter
41125450Speterstatic struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
41225450Speter    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
41325450Speter
41425450Speterstatic struct ifmedia_description ifm_subtype_tokenring_aliases[] =
41525450Speter    IFM_SUBTYPE_TOKENRING_ALIASES;
41625450Speter
41725450Speterstatic struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
41825450Speter    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
41925450Speter
42025450Speterstatic struct ifmedia_description ifm_subtype_fddi_descriptions[] =
42125450Speter    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
42225450Speter
42325450Speterstatic struct ifmedia_description ifm_subtype_fddi_aliases[] =
42425450Speter    IFM_SUBTYPE_FDDI_ALIASES;
42525450Speter
42625450Speterstatic struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
42725450Speter    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
42825450Speter
42977217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
43077217Sphk    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
43177217Sphk
43277217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
43377217Sphk    IFM_SUBTYPE_IEEE80211_ALIASES;
43477217Sphk
43577217Sphkstatic struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
43677217Sphk    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
43777217Sphk
438114164Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
439114164Ssam    IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
440114164Ssam
441116820Ssamstruct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
442116820Ssam    IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
443116820Ssam
444114232Shartistatic struct ifmedia_description ifm_subtype_atm_descriptions[] =
445114232Sharti    IFM_SUBTYPE_ATM_DESCRIPTIONS;
446114232Sharti
447114232Shartistatic struct ifmedia_description ifm_subtype_atm_aliases[] =
448114232Sharti    IFM_SUBTYPE_ATM_ALIASES;
449114232Sharti
450114232Shartistatic struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
451114232Sharti    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
452114232Sharti
45325450Speterstatic struct ifmedia_description ifm_subtype_shared_descriptions[] =
45425450Speter    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
45525450Speter
45625450Speterstatic struct ifmedia_description ifm_subtype_shared_aliases[] =
45725450Speter    IFM_SUBTYPE_SHARED_ALIASES;
45825450Speter
45925450Speterstatic struct ifmedia_description ifm_shared_option_descriptions[] =
46025450Speter    IFM_SHARED_OPTION_DESCRIPTIONS;
46125450Speter
462217013Smariusstatic struct ifmedia_description ifm_shared_option_aliases[] =
463217013Smarius    IFM_SHARED_OPTION_ALIASES;
464217013Smarius
46525450Speterstruct ifmedia_type_to_subtype {
46625450Speter	struct {
46725450Speter		struct ifmedia_description *desc;
46825450Speter		int alias;
46925450Speter	} subtypes[5];
47025450Speter	struct {
47125450Speter		struct ifmedia_description *desc;
47225450Speter		int alias;
473217013Smarius	} options[4];
474114164Ssam	struct {
475114164Ssam		struct ifmedia_description *desc;
476114164Ssam		int alias;
477116820Ssam	} modes[3];
47825450Speter};
47925450Speter
48025450Speter/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
48125450Speterstatic struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
48225450Speter	{
48325450Speter		{
48425450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
48525450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
48625450Speter			{ &ifm_subtype_ethernet_descriptions[0], 0 },
48725450Speter			{ &ifm_subtype_ethernet_aliases[0], 1 },
48825450Speter			{ NULL, 0 },
48925450Speter		},
49025450Speter		{
49125450Speter			{ &ifm_shared_option_descriptions[0], 0 },
492217013Smarius			{ &ifm_shared_option_aliases[0], 1 },
49377217Sphk			{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
49425450Speter			{ NULL, 0 },
49525450Speter		},
496114164Ssam		{
497114164Ssam			{ NULL, 0 },
498114164Ssam		},
49925450Speter	},
50025450Speter	{
50125450Speter		{
50225450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
50325450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
50425450Speter			{ &ifm_subtype_tokenring_descriptions[0], 0 },
50525450Speter			{ &ifm_subtype_tokenring_aliases[0], 1 },
50625450Speter			{ NULL, 0 },
50725450Speter		},
50825450Speter		{
50925450Speter			{ &ifm_shared_option_descriptions[0], 0 },
510217013Smarius			{ &ifm_shared_option_aliases[0], 1 },
51177217Sphk			{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
51225450Speter			{ NULL, 0 },
51325450Speter		},
514114164Ssam		{
515114164Ssam			{ NULL, 0 },
516114164Ssam		},
51725450Speter	},
51825450Speter	{
51925450Speter		{
52025450Speter			{ &ifm_subtype_shared_descriptions[0], 0 },
52125450Speter			{ &ifm_subtype_shared_aliases[0], 1 },
52225450Speter			{ &ifm_subtype_fddi_descriptions[0], 0 },
52325450Speter			{ &ifm_subtype_fddi_aliases[0], 1 },
52425450Speter			{ NULL, 0 },
52525450Speter		},
52625450Speter		{
52725450Speter			{ &ifm_shared_option_descriptions[0], 0 },
528217013Smarius			{ &ifm_shared_option_aliases[0], 1 },
52977217Sphk			{ &ifm_subtype_fddi_option_descriptions[0], 0 },
53025450Speter			{ NULL, 0 },
53125450Speter		},
532114164Ssam		{
533114164Ssam			{ NULL, 0 },
534114164Ssam		},
53525450Speter	},
53677217Sphk	{
53777217Sphk		{
53877217Sphk			{ &ifm_subtype_shared_descriptions[0], 0 },
53977217Sphk			{ &ifm_subtype_shared_aliases[0], 1 },
54077217Sphk			{ &ifm_subtype_ieee80211_descriptions[0], 0 },
54177217Sphk			{ &ifm_subtype_ieee80211_aliases[0], 1 },
54277217Sphk			{ NULL, 0 },
54377217Sphk		},
54477217Sphk		{
54577217Sphk			{ &ifm_shared_option_descriptions[0], 0 },
546217013Smarius			{ &ifm_shared_option_aliases[0], 1 },
54777217Sphk			{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
54877217Sphk			{ NULL, 0 },
54977217Sphk		},
550114164Ssam		{
551114164Ssam			{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
552116820Ssam			{ &ifm_subtype_ieee80211_mode_aliases[0], 0 },
553114164Ssam			{ NULL, 0 },
554114164Ssam		},
55577217Sphk	},
556114232Sharti	{
557114232Sharti		{
558114232Sharti			{ &ifm_subtype_shared_descriptions[0], 0 },
559114232Sharti			{ &ifm_subtype_shared_aliases[0], 1 },
560114232Sharti			{ &ifm_subtype_atm_descriptions[0], 0 },
561114232Sharti			{ &ifm_subtype_atm_aliases[0], 1 },
562114232Sharti			{ NULL, 0 },
563114232Sharti		},
564114232Sharti		{
565114232Sharti			{ &ifm_shared_option_descriptions[0], 0 },
566217013Smarius			{ &ifm_shared_option_aliases[0], 1 },
567114232Sharti			{ &ifm_subtype_atm_option_descriptions[0], 0 },
568114232Sharti			{ NULL, 0 },
569114232Sharti		},
570114232Sharti		{
571114232Sharti			{ NULL, 0 },
572114232Sharti		},
573114232Sharti	},
57425450Speter};
57525450Speter
57625450Speterstatic int
57795005Simpget_media_subtype(int type, const char *val)
57825450Speter{
57925450Speter	struct ifmedia_description *desc;
58025450Speter	struct ifmedia_type_to_subtype *ttos;
58125450Speter	int rval, i;
58225450Speter
58325450Speter	/* Find the top-level interface type. */
58425450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
58525450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
58625450Speter		if (type == desc->ifmt_word)
58725450Speter			break;
58825450Speter	if (desc->ifmt_string == NULL)
58925450Speter		errx(1, "unknown media type 0x%x", type);
59025450Speter
59125450Speter	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
59225450Speter		rval = lookup_media_word(ttos->subtypes[i].desc, val);
59325450Speter		if (rval != -1)
59425450Speter			return (rval);
59525450Speter	}
59625450Speter	errx(1, "unknown media subtype: %s", val);
597114164Ssam	/*NOTREACHED*/
59825450Speter}
59925450Speter
60025450Speterstatic int
601114164Ssamget_media_mode(int type, const char *val)
602114164Ssam{
603114164Ssam	struct ifmedia_description *desc;
604114164Ssam	struct ifmedia_type_to_subtype *ttos;
605114164Ssam	int rval, i;
606114164Ssam
607114164Ssam	/* Find the top-level interface type. */
608114164Ssam	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
609114164Ssam	    desc->ifmt_string != NULL; desc++, ttos++)
610114164Ssam		if (type == desc->ifmt_word)
611114164Ssam			break;
612114164Ssam	if (desc->ifmt_string == NULL)
613114164Ssam		errx(1, "unknown media mode 0x%x", type);
614114164Ssam
615114164Ssam	for (i = 0; ttos->modes[i].desc != NULL; i++) {
616114164Ssam		rval = lookup_media_word(ttos->modes[i].desc, val);
617114164Ssam		if (rval != -1)
618114164Ssam			return (rval);
619114164Ssam	}
620114164Ssam	return -1;
621114164Ssam}
622114164Ssam
623114164Ssamstatic int
62495005Simpget_media_options(int type, const char *val)
62525450Speter{
62625450Speter	struct ifmedia_description *desc;
62725450Speter	struct ifmedia_type_to_subtype *ttos;
62825450Speter	char *optlist, *optptr;
62925450Speter	int option = 0, i, rval = 0;
63025450Speter
63125450Speter	/* We muck with the string, so copy it. */
63225450Speter	optlist = strdup(val);
63325450Speter	if (optlist == NULL)
63425450Speter		err(1, "strdup");
63525450Speter
63625450Speter	/* Find the top-level interface type. */
63725450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
63825450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
63925450Speter		if (type == desc->ifmt_word)
64025450Speter			break;
64125450Speter	if (desc->ifmt_string == NULL)
64225450Speter		errx(1, "unknown media type 0x%x", type);
64325450Speter
64425450Speter	/*
64525450Speter	 * Look up the options in the user-provided comma-separated
64625450Speter	 * list.
64725450Speter	 */
64825450Speter	optptr = optlist;
64925450Speter	for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
65025450Speter		for (i = 0; ttos->options[i].desc != NULL; i++) {
65125450Speter			option = lookup_media_word(ttos->options[i].desc, optptr);
65225450Speter			if (option != -1)
65325450Speter				break;
65425450Speter		}
65525450Speter		if (option == 0)
65625450Speter			errx(1, "unknown option: %s", optptr);
65725450Speter		rval |= option;
65825450Speter	}
65925450Speter
66025450Speter	free(optlist);
66125450Speter	return (rval);
66225450Speter}
66325450Speter
66425450Speterstatic int
66595005Simplookup_media_word(struct ifmedia_description *desc, const char *val)
66625450Speter{
66725450Speter
66825450Speter	for (; desc->ifmt_string != NULL; desc++)
66925450Speter		if (strcasecmp(desc->ifmt_string, val) == 0)
67025450Speter			return (desc->ifmt_word);
67125450Speter
67225450Speter	return (-1);
67325450Speter}
67425450Speter
67595005Simpstatic struct ifmedia_description *get_toptype_desc(int ifmw)
67625450Speter{
67725450Speter	struct ifmedia_description *desc;
67877385Sphk
67977385Sphk	for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
68077385Sphk		if (IFM_TYPE(ifmw) == desc->ifmt_word)
68177385Sphk			break;
68277385Sphk
68377385Sphk	return desc;
68477385Sphk}
68577385Sphk
68695005Simpstatic struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
68777385Sphk{
68877385Sphk	struct ifmedia_description *desc;
68925450Speter	struct ifmedia_type_to_subtype *ttos;
69025450Speter
69125450Speter	for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
69225450Speter	    desc->ifmt_string != NULL; desc++, ttos++)
69325450Speter		if (IFM_TYPE(ifmw) == desc->ifmt_word)
69425450Speter			break;
69577385Sphk
69677385Sphk	return ttos;
69777385Sphk}
69877385Sphk
69995005Simpstatic struct ifmedia_description *get_subtype_desc(int ifmw,
70095005Simp    struct ifmedia_type_to_subtype *ttos)
70177385Sphk{
70277385Sphk	int i;
70377385Sphk	struct ifmedia_description *desc;
70477385Sphk
70577385Sphk	for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
70677385Sphk		if (ttos->subtypes[i].alias)
70777385Sphk			continue;
70877385Sphk		for (desc = ttos->subtypes[i].desc;
70977385Sphk		    desc->ifmt_string != NULL; desc++) {
71077385Sphk			if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
71177385Sphk				return desc;
71277385Sphk		}
71377385Sphk	}
71477385Sphk
71577385Sphk	return NULL;
71677385Sphk}
71777385Sphk
718114164Ssamstatic struct ifmedia_description *get_mode_desc(int ifmw,
719114164Ssam    struct ifmedia_type_to_subtype *ttos)
720114164Ssam{
721114164Ssam	int i;
722114164Ssam	struct ifmedia_description *desc;
723114164Ssam
724114164Ssam	for (i = 0; ttos->modes[i].desc != NULL; i++) {
725114164Ssam		if (ttos->modes[i].alias)
726114164Ssam			continue;
727114164Ssam		for (desc = ttos->modes[i].desc;
728114164Ssam		    desc->ifmt_string != NULL; desc++) {
729114164Ssam			if (IFM_MODE(ifmw) == desc->ifmt_word)
730114164Ssam				return desc;
731114164Ssam		}
732114164Ssam	}
733114164Ssam
734114164Ssam	return NULL;
735114164Ssam}
736114164Ssam
73777385Sphkstatic void
73895005Simpprint_media_word(int ifmw, int print_toptype)
73977385Sphk{
74077385Sphk	struct ifmedia_description *desc;
74177385Sphk	struct ifmedia_type_to_subtype *ttos;
74277385Sphk	int seen_option = 0, i;
74377385Sphk
74477385Sphk	/* Find the top-level interface type. */
74577385Sphk	desc = get_toptype_desc(ifmw);
74677385Sphk	ttos = get_toptype_ttos(ifmw);
74725450Speter	if (desc->ifmt_string == NULL) {
74825450Speter		printf("<unknown type>");
74925450Speter		return;
75077385Sphk	} else if (print_toptype) {
75177385Sphk		printf("%s", desc->ifmt_string);
75225450Speter	}
75325450Speter
75425450Speter	/*
75525450Speter	 * Don't print the top-level type; it's not like we can
75625450Speter	 * change it, or anything.
75725450Speter	 */
75825450Speter
75925450Speter	/* Find subtype. */
76077385Sphk	desc = get_subtype_desc(ifmw, ttos);
761161536Sthomas	if (desc == NULL) {
762161536Sthomas		printf("<unknown subtype>");
763161536Sthomas		return;
764161536Sthomas	}
76525450Speter
76677385Sphk	if (print_toptype)
76777385Sphk		putchar(' ');
76877385Sphk
76925450Speter	printf("%s", desc->ifmt_string);
77025450Speter
771114164Ssam	if (print_toptype) {
772114164Ssam		desc = get_mode_desc(ifmw, ttos);
773116820Ssam		if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
774114164Ssam			printf(" mode %s", desc->ifmt_string);
775114164Ssam	}
776114164Ssam
77725450Speter	/* Find options. */
77825450Speter	for (i = 0; ttos->options[i].desc != NULL; i++) {
77925450Speter		if (ttos->options[i].alias)
78025450Speter			continue;
78125450Speter		for (desc = ttos->options[i].desc;
78225450Speter		    desc->ifmt_string != NULL; desc++) {
78325450Speter			if (ifmw & desc->ifmt_word) {
78425450Speter				if (seen_option == 0)
78525450Speter					printf(" <");
78625450Speter				printf("%s%s", seen_option++ ? "," : "",
78725450Speter				    desc->ifmt_string);
78825450Speter			}
78925450Speter		}
79025450Speter	}
79125450Speter	printf("%s", seen_option ? ">" : "");
792166113Smarius
793166169Smarius	if (print_toptype && IFM_INST(ifmw) != 0)
794166113Smarius		printf(" instance %d", IFM_INST(ifmw));
79525450Speter}
79625450Speter
79777385Sphkstatic void
79895005Simpprint_media_word_ifconfig(int ifmw)
79977385Sphk{
80077385Sphk	struct ifmedia_description *desc;
80177385Sphk	struct ifmedia_type_to_subtype *ttos;
802215259Smarius	int seen_option = 0, i;
80377385Sphk
80477385Sphk	/* Find the top-level interface type. */
80577385Sphk	desc = get_toptype_desc(ifmw);
80677385Sphk	ttos = get_toptype_ttos(ifmw);
80777385Sphk	if (desc->ifmt_string == NULL) {
80877385Sphk		printf("<unknown type>");
80977385Sphk		return;
81077385Sphk	}
81177385Sphk
81277385Sphk	/*
81377385Sphk	 * Don't print the top-level type; it's not like we can
81477385Sphk	 * change it, or anything.
81577385Sphk	 */
81677385Sphk
81777385Sphk	/* Find subtype. */
81877385Sphk	desc = get_subtype_desc(ifmw, ttos);
819161536Sthomas	if (desc == NULL) {
820161536Sthomas		printf("<unknown subtype>");
821161536Sthomas		return;
822161536Sthomas	}
82377385Sphk
82477385Sphk	printf("media %s", desc->ifmt_string);
82577385Sphk
826114164Ssam	desc = get_mode_desc(ifmw, ttos);
827114164Ssam	if (desc != NULL)
828114164Ssam		printf(" mode %s", desc->ifmt_string);
829114164Ssam
83077385Sphk	/* Find options. */
83177385Sphk	for (i = 0; ttos->options[i].desc != NULL; i++) {
83277385Sphk		if (ttos->options[i].alias)
83377385Sphk			continue;
83477385Sphk		for (desc = ttos->options[i].desc;
83577385Sphk		    desc->ifmt_string != NULL; desc++) {
83677385Sphk			if (ifmw & desc->ifmt_word) {
837215259Smarius				if (seen_option == 0)
838215259Smarius					printf(" mediaopt ");
839215259Smarius				printf("%s%s", seen_option++ ? "," : "",
840215259Smarius				    desc->ifmt_string);
84177385Sphk			}
84277385Sphk		}
84377385Sphk	}
844166113Smarius
845166169Smarius	if (IFM_INST(ifmw) != 0)
846166169Smarius		printf(" instance %d", IFM_INST(ifmw));
84777385Sphk}
84877385Sphk
84925450Speter/**********************************************************************
85025450Speter * ...until here.
85125450Speter **********************************************************************/
852138593Ssam
853138593Ssamstatic struct cmd media_cmds[] = {
854138593Ssam	DEF_CMD_ARG("media",	setmedia),
855138593Ssam	DEF_CMD_ARG("mode",	setmediamode),
856138593Ssam	DEF_CMD_ARG("mediaopt",	setmediaopt),
857138593Ssam	DEF_CMD_ARG("-mediaopt",unsetmediaopt),
858166113Smarius	DEF_CMD_ARG("inst",	setmediainst),
859166113Smarius	DEF_CMD_ARG("instance",	setmediainst),
860138593Ssam};
861138593Ssamstatic struct afswtch af_media = {
862138593Ssam	.af_name	= "af_media",
863138593Ssam	.af_af		= AF_UNSPEC,
864139494Ssam	.af_other_status = media_status,
865138593Ssam};
866138593Ssam
867138593Ssamstatic __constructor void
868138593Ssamifmedia_ctor(void)
869138593Ssam{
870194799Sdelphij	size_t i;
871138593Ssam
872288305Sngie	for (i = 0; i < nitems(media_cmds);  i++)
873138593Ssam		cmd_register(&media_cmds[i]);
874138593Ssam	af_register(&af_media);
875138593Ssam}
876