xref: /freebsd/sbin/ifconfig/ifmedia.c (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
14edfe6b9SPeter Wemm /*	$NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $	*/
24edfe6b9SPeter Wemm 
3df57947fSPedro F. Giffuni /*-
4df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
5df57947fSPedro F. Giffuni  *
64edfe6b9SPeter Wemm  * Copyright (c) 1997 Jason R. Thorpe.
74edfe6b9SPeter Wemm  * All rights reserved.
84edfe6b9SPeter Wemm  *
94edfe6b9SPeter Wemm  * Redistribution and use in source and binary forms, with or without
104edfe6b9SPeter Wemm  * modification, are permitted provided that the following conditions
114edfe6b9SPeter Wemm  * are met:
124edfe6b9SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
134edfe6b9SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
144edfe6b9SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
154edfe6b9SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
164edfe6b9SPeter Wemm  *    documentation and/or other materials provided with the distribution.
174edfe6b9SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
184edfe6b9SPeter Wemm  *    must display the following acknowledgement:
194edfe6b9SPeter Wemm  *      This product includes software developed for the NetBSD Project
204edfe6b9SPeter Wemm  *	by Jason R. Thorpe.
214edfe6b9SPeter Wemm  * 4. The name of the author may not be used to endorse or promote products
224edfe6b9SPeter Wemm  *    derived from this software without specific prior written permission.
234edfe6b9SPeter Wemm  *
244edfe6b9SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
254edfe6b9SPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
264edfe6b9SPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
274edfe6b9SPeter Wemm  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
284edfe6b9SPeter Wemm  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
294edfe6b9SPeter Wemm  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
304edfe6b9SPeter Wemm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
314edfe6b9SPeter Wemm  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
324edfe6b9SPeter Wemm  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334edfe6b9SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344edfe6b9SPeter Wemm  * SUCH DAMAGE.
354edfe6b9SPeter Wemm  */
364edfe6b9SPeter Wemm 
374edfe6b9SPeter Wemm /*
384edfe6b9SPeter Wemm  * Copyright (c) 1983, 1993
394edfe6b9SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
404edfe6b9SPeter Wemm  *
414edfe6b9SPeter Wemm  * Redistribution and use in source and binary forms, with or without
424edfe6b9SPeter Wemm  * modification, are permitted provided that the following conditions
434edfe6b9SPeter Wemm  * are met:
444edfe6b9SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
454edfe6b9SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
464edfe6b9SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
474edfe6b9SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
484edfe6b9SPeter Wemm  *    documentation and/or other materials provided with the distribution.
494edfe6b9SPeter Wemm  * 4. Neither the name of the University nor the names of its contributors
504edfe6b9SPeter Wemm  *    may be used to endorse or promote products derived from this software
514edfe6b9SPeter Wemm  *    without specific prior written permission.
524edfe6b9SPeter Wemm  *
534edfe6b9SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
544edfe6b9SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
554edfe6b9SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
564edfe6b9SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
574edfe6b9SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
584edfe6b9SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
594edfe6b9SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
604edfe6b9SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
614edfe6b9SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
624edfe6b9SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
634edfe6b9SPeter Wemm  * SUCH DAMAGE.
644edfe6b9SPeter Wemm  */
654edfe6b9SPeter Wemm 
664edfe6b9SPeter Wemm #include <sys/param.h>
674edfe6b9SPeter Wemm #include <sys/ioctl.h>
684edfe6b9SPeter Wemm #include <sys/socket.h>
694edfe6b9SPeter Wemm #include <sys/sysctl.h>
704edfe6b9SPeter Wemm #include <sys/time.h>
714edfe6b9SPeter Wemm 
724edfe6b9SPeter Wemm #include <net/if.h>
734edfe6b9SPeter Wemm #include <net/if_dl.h>
744edfe6b9SPeter Wemm #include <net/if_types.h>
754edfe6b9SPeter Wemm #include <net/if_media.h>
764edfe6b9SPeter Wemm #include <net/route.h>
774edfe6b9SPeter Wemm 
784edfe6b9SPeter Wemm #include <ctype.h>
794edfe6b9SPeter Wemm #include <err.h>
804edfe6b9SPeter Wemm #include <errno.h>
814edfe6b9SPeter Wemm #include <fcntl.h>
82093aa3e3SKonstantin Belousov #include <stdbool.h>
834edfe6b9SPeter Wemm #include <stdio.h>
844edfe6b9SPeter Wemm #include <stdlib.h>
854edfe6b9SPeter Wemm #include <string.h>
864edfe6b9SPeter Wemm #include <unistd.h>
874edfe6b9SPeter Wemm 
882803fa47SRyan Moeller #include <libifconfig.h>
892803fa47SRyan Moeller 
904edfe6b9SPeter Wemm #include "ifconfig.h"
914edfe6b9SPeter Wemm 
9274b42611SAlexander V. Chernikov static void domediaopt(if_ctx *, const char *, bool);
932803fa47SRyan Moeller static ifmedia_t get_media_subtype(ifmedia_t, const char *);
942803fa47SRyan Moeller static ifmedia_t get_media_mode(ifmedia_t, const char *);
952803fa47SRyan Moeller static ifmedia_t get_media_options(ifmedia_t, const char *);
962803fa47SRyan Moeller static void print_media(ifmedia_t, bool);
972803fa47SRyan Moeller static void print_media_ifconfig(ifmedia_t);
98b032f27cSSam Leffler 
995faf8dcbSSam Leffler static void
media_status(if_ctx * ctx)10085e0016aSAlexander V. Chernikov media_status(if_ctx *ctx)
1014edfe6b9SPeter Wemm {
1022803fa47SRyan Moeller 	struct ifmediareq *ifmr;
1034edfe6b9SPeter Wemm 
10485e0016aSAlexander V. Chernikov 	if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
1054edfe6b9SPeter Wemm 		return;
1064edfe6b9SPeter Wemm 
1072803fa47SRyan Moeller 	if (ifmr->ifm_count == 0) {
10885e0016aSAlexander V. Chernikov 		warnx("%s: no media types?", ctx->ifname);
1092803fa47SRyan Moeller 		goto free;
110eb7e25b2SEric Joyner 	}
1114edfe6b9SPeter Wemm 
1124edfe6b9SPeter Wemm 	printf("\tmedia: ");
1132803fa47SRyan Moeller 	print_media(ifmr->ifm_current, true);
1142803fa47SRyan Moeller 	if (ifmr->ifm_active != ifmr->ifm_current) {
1154edfe6b9SPeter Wemm 		putchar(' ');
1164edfe6b9SPeter Wemm 		putchar('(');
1172803fa47SRyan Moeller 		print_media(ifmr->ifm_active, false);
1184edfe6b9SPeter Wemm 		putchar(')');
1194edfe6b9SPeter Wemm 	}
1204edfe6b9SPeter Wemm 
121ca299b1fSPoul-Henning Kamp 	putchar('\n');
122ca299b1fSPoul-Henning Kamp 
1232803fa47SRyan Moeller 	if (ifmr->ifm_status & IFM_AVALID) {
1242803fa47SRyan Moeller 		struct ifdownreason ifdr;
1252803fa47SRyan Moeller 		const char *status;
1264edfe6b9SPeter Wemm 
1272803fa47SRyan Moeller 		status = ifconfig_media_get_status(ifmr);
1282803fa47SRyan Moeller 		printf("\tstatus: %s", status);
1292803fa47SRyan Moeller 		if (strcmp(status, "no carrier") == 0 &&
13085e0016aSAlexander V. Chernikov 		    ifconfig_media_get_downreason(lifh, ctx->ifname, &ifdr) == 0) {
131093aa3e3SKonstantin Belousov 			switch (ifdr.ifdr_reason) {
132093aa3e3SKonstantin Belousov 			case IFDR_REASON_MSG:
133093aa3e3SKonstantin Belousov 				printf(" (%s)", ifdr.ifdr_msg);
134093aa3e3SKonstantin Belousov 				break;
135093aa3e3SKonstantin Belousov 			case IFDR_REASON_VENDOR:
136093aa3e3SKonstantin Belousov 				printf(" (vendor code %d)",
137093aa3e3SKonstantin Belousov 				    ifdr.ifdr_vendor);
138093aa3e3SKonstantin Belousov 				break;
139093aa3e3SKonstantin Belousov 			default:
140093aa3e3SKonstantin Belousov 				break;
141093aa3e3SKonstantin Belousov 			}
142093aa3e3SKonstantin Belousov 		}
1434edfe6b9SPeter Wemm 		putchar('\n');
144f23badd9SYaroslav Tykhiy 	}
1454edfe6b9SPeter Wemm 
146ea73ff97SAlexander V. Chernikov 	if (ctx->args->supmedia) {
147ca299b1fSPoul-Henning Kamp 		printf("\tsupported media:\n");
14844cd85d4SAlexander V. Chernikov 		for (int i = 0; i < ifmr->ifm_count; ++i) {
149ca299b1fSPoul-Henning Kamp 			printf("\t\t");
1502803fa47SRyan Moeller 			print_media_ifconfig(ifmr->ifm_ulist[i]);
1514edfe6b9SPeter Wemm 			putchar('\n');
1524edfe6b9SPeter Wemm 		}
153ca299b1fSPoul-Henning Kamp 	}
1542803fa47SRyan Moeller free:
1552803fa47SRyan Moeller 	free(ifmr);
1564edfe6b9SPeter Wemm }
1574edfe6b9SPeter Wemm 
1588f3591a5SSam Leffler struct ifmediareq *
ifmedia_getstate(if_ctx * ctx)15985e0016aSAlexander V. Chernikov ifmedia_getstate(if_ctx *ctx)
1604edfe6b9SPeter Wemm {
161407fb44cSRyan Moeller 	static struct ifmediareq *ifmr = NULL;
162407fb44cSRyan Moeller 
163407fb44cSRyan Moeller 	if (ifmr != NULL)
164407fb44cSRyan Moeller 		return (ifmr);
1654edfe6b9SPeter Wemm 
16685e0016aSAlexander V. Chernikov 	if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
1672803fa47SRyan Moeller 		errc(1, ifconfig_err_errno(lifh),
16885e0016aSAlexander V. Chernikov 		    "%s: ifconfig_media_get_mediareq", ctx->ifname);
1694edfe6b9SPeter Wemm 
170499e862cSDoug Ambrisko 	if (ifmr->ifm_count == 0)
17185e0016aSAlexander V. Chernikov 		errx(1, "%s: no media types?", ctx->ifname);
1724edfe6b9SPeter Wemm 
1732803fa47SRyan Moeller 	return (ifmr);
174499e862cSDoug Ambrisko }
175499e862cSDoug Ambrisko 
176499e862cSDoug Ambrisko static void
setifmediacallback(if_ctx * ctx,void * arg)17774b42611SAlexander V. Chernikov setifmediacallback(if_ctx *ctx, void *arg)
178499e862cSDoug Ambrisko {
179499e862cSDoug Ambrisko 	struct ifmediareq *ifmr = (struct ifmediareq *)arg;
1802803fa47SRyan Moeller 	static bool did_it = false;
181*f414f37eSAlexander V. Chernikov 	struct ifreq ifr = {};
182499e862cSDoug Ambrisko 
183499e862cSDoug Ambrisko 	if (!did_it) {
1841cc59a99SDoug Ambrisko 		ifr.ifr_media = ifmr->ifm_current;
185*f414f37eSAlexander V. Chernikov 		if (ioctl_ctx_ifr(ctx, SIOCSIFMEDIA, &ifr) < 0)
186499e862cSDoug Ambrisko 			err(1, "SIOCSIFMEDIA (media)");
187499e862cSDoug Ambrisko 		free(ifmr);
1882803fa47SRyan Moeller 		did_it = true;
189499e862cSDoug Ambrisko 	}
190499e862cSDoug Ambrisko }
191499e862cSDoug Ambrisko 
192499e862cSDoug Ambrisko static void
setmedia(if_ctx * ctx,const char * val,int d __unused)19374b42611SAlexander V. Chernikov setmedia(if_ctx *ctx, const char *val, int d __unused)
194499e862cSDoug Ambrisko {
195499e862cSDoug Ambrisko 	struct ifmediareq *ifmr;
196499e862cSDoug Ambrisko 	int subtype;
197499e862cSDoug Ambrisko 
19885e0016aSAlexander V. Chernikov 	ifmr = ifmedia_getstate(ctx);
199499e862cSDoug Ambrisko 
2004edfe6b9SPeter Wemm 	/*
2014edfe6b9SPeter Wemm 	 * We are primarily concerned with the top-level type.
2024edfe6b9SPeter Wemm 	 * However, "current" may be only IFM_NONE, so we just look
2034edfe6b9SPeter Wemm 	 * for the top-level type in the first "supported type"
2044edfe6b9SPeter Wemm 	 * entry.
2054edfe6b9SPeter Wemm 	 *
2064edfe6b9SPeter Wemm 	 * (I'm assuming that all supported media types for a given
2074edfe6b9SPeter Wemm 	 * interface will be the same top-level type..)
2084edfe6b9SPeter Wemm 	 */
2092803fa47SRyan Moeller 	subtype = get_media_subtype(ifmr->ifm_ulist[0], val);
2104edfe6b9SPeter Wemm 
211*f414f37eSAlexander V. Chernikov 	ifmr->ifm_current = (ifmr->ifm_current & IFM_IMASK) |
212499e862cSDoug Ambrisko 	    IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
2134edfe6b9SPeter Wemm 
214499e862cSDoug Ambrisko 	callback_register(setifmediacallback, (void *)ifmr);
2154edfe6b9SPeter Wemm }
2164edfe6b9SPeter Wemm 
2175faf8dcbSSam Leffler static void
setmediaopt(if_ctx * ctx,const char * val,int d __unused)21874b42611SAlexander V. Chernikov setmediaopt(if_ctx *ctx, const char *val, int d __unused)
2194edfe6b9SPeter Wemm {
2204edfe6b9SPeter Wemm 
22174b42611SAlexander V. Chernikov 	domediaopt(ctx, val, false);
2224edfe6b9SPeter Wemm }
2234edfe6b9SPeter Wemm 
2245faf8dcbSSam Leffler static void
unsetmediaopt(if_ctx * ctx,const char * val,int d __unused)22574b42611SAlexander V. Chernikov unsetmediaopt(if_ctx *ctx, const char *val, int d __unused)
2264edfe6b9SPeter Wemm {
2274edfe6b9SPeter Wemm 
22874b42611SAlexander V. Chernikov 	domediaopt(ctx, val, true);
2294edfe6b9SPeter Wemm }
2304edfe6b9SPeter Wemm 
2314edfe6b9SPeter Wemm static void
domediaopt(if_ctx * ctx,const char * val,bool clear)23274b42611SAlexander V. Chernikov domediaopt(if_ctx *ctx, const char *val, bool clear)
2334edfe6b9SPeter Wemm {
234499e862cSDoug Ambrisko 	struct ifmediareq *ifmr;
2352803fa47SRyan Moeller 	ifmedia_t options;
2364edfe6b9SPeter Wemm 
23785e0016aSAlexander V. Chernikov 	ifmr = ifmedia_getstate(ctx);
2384edfe6b9SPeter Wemm 
2392803fa47SRyan Moeller 	options = get_media_options(ifmr->ifm_ulist[0], val);
2404edfe6b9SPeter Wemm 
2414edfe6b9SPeter Wemm 	if (clear)
242*f414f37eSAlexander V. Chernikov 		ifmr->ifm_current &= ~options;
243f7c6b0a8SJung-uk Kim 	else {
244f7c6b0a8SJung-uk Kim 		if (options & IFM_HDX) {
245*f414f37eSAlexander V. Chernikov 			ifmr->ifm_current &= ~IFM_FDX;
246f7c6b0a8SJung-uk Kim 			options &= ~IFM_HDX;
247f7c6b0a8SJung-uk Kim 		}
248*f414f37eSAlexander V. Chernikov 		ifmr->ifm_current |= options;
249f7c6b0a8SJung-uk Kim 	}
250499e862cSDoug Ambrisko 	callback_register(setifmediacallback, (void *)ifmr);
2514e61f6f1SSam Leffler }
2524e61f6f1SSam Leffler 
25311139493SMarius Strobl static void
setmediainst(if_ctx * ctx,const char * val,int d __unused)25474b42611SAlexander V. Chernikov setmediainst(if_ctx *ctx, const char *val, int d __unused)
25511139493SMarius Strobl {
25611139493SMarius Strobl 	struct ifmediareq *ifmr;
25711139493SMarius Strobl 	int inst;
25811139493SMarius Strobl 
25985e0016aSAlexander V. Chernikov 	ifmr = ifmedia_getstate(ctx);
26011139493SMarius Strobl 
26111139493SMarius Strobl 	inst = atoi(val);
262b59dcaeeSXin LI 	if (inst < 0 || inst > (int)IFM_INST_MAX)
26311139493SMarius Strobl 		errx(1, "invalid media instance: %s", val);
26411139493SMarius Strobl 
265*f414f37eSAlexander V. Chernikov 	ifmr->ifm_current = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
26611139493SMarius Strobl 
26711139493SMarius Strobl 	callback_register(setifmediacallback, (void *)ifmr);
26811139493SMarius Strobl }
2694e61f6f1SSam Leffler 
2705faf8dcbSSam Leffler static void
setmediamode(if_ctx * ctx,const char * val,int d __unused)27174b42611SAlexander V. Chernikov setmediamode(if_ctx *ctx, const char *val, int d __unused)
2724e61f6f1SSam Leffler {
273499e862cSDoug Ambrisko 	struct ifmediareq *ifmr;
274499e862cSDoug Ambrisko 	int mode;
2754e61f6f1SSam Leffler 
27685e0016aSAlexander V. Chernikov 	ifmr = ifmedia_getstate(ctx);
2774e61f6f1SSam Leffler 
2782803fa47SRyan Moeller 	mode = get_media_mode(ifmr->ifm_ulist[0], val);
2794e61f6f1SSam Leffler 
280*f414f37eSAlexander V. Chernikov 	ifmr->ifm_current = (ifmr->ifm_current & ~IFM_MMASK) | mode;
2814e61f6f1SSam Leffler 
282499e862cSDoug Ambrisko 	callback_register(setifmediacallback, (void *)ifmr);
2834edfe6b9SPeter Wemm }
2844edfe6b9SPeter Wemm 
2852803fa47SRyan Moeller static ifmedia_t
get_media_subtype(ifmedia_t media,const char * val)2862803fa47SRyan Moeller get_media_subtype(ifmedia_t media, const char *val)
2874edfe6b9SPeter Wemm {
2882803fa47SRyan Moeller 	ifmedia_t subtype;
2894edfe6b9SPeter Wemm 
2902803fa47SRyan Moeller 	subtype = ifconfig_media_lookup_subtype(media, val);
2912803fa47SRyan Moeller 	if (subtype != INVALID_IFMEDIA)
2922803fa47SRyan Moeller 		return (subtype);
2932803fa47SRyan Moeller 	switch (errno) {
2942803fa47SRyan Moeller 	case EINVAL:
2952803fa47SRyan Moeller 		errx(EXIT_FAILURE, "unknown media type 0x%x", media);
2962803fa47SRyan Moeller 	case ENOENT:
2972803fa47SRyan Moeller 		errx(EXIT_FAILURE, "unknown media subtype: %s", val);
2982803fa47SRyan Moeller 	default:
2992803fa47SRyan Moeller 		err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
3004edfe6b9SPeter Wemm 	}
3014edfe6b9SPeter Wemm 	/*NOTREACHED*/
3024edfe6b9SPeter Wemm }
3034edfe6b9SPeter Wemm 
3042803fa47SRyan Moeller static ifmedia_t
get_media_mode(ifmedia_t media,const char * val)3052803fa47SRyan Moeller get_media_mode(ifmedia_t media, const char *val)
3064e61f6f1SSam Leffler {
3072803fa47SRyan Moeller 	ifmedia_t mode;
3084e61f6f1SSam Leffler 
3092803fa47SRyan Moeller 	mode = ifconfig_media_lookup_mode(media, val);
3102803fa47SRyan Moeller 	if (mode != INVALID_IFMEDIA)
3112803fa47SRyan Moeller 		return (mode);
3122803fa47SRyan Moeller 	switch (errno) {
3132803fa47SRyan Moeller 	case EINVAL:
3142803fa47SRyan Moeller 		errx(EXIT_FAILURE, "unknown media type 0x%x", media);
3152803fa47SRyan Moeller 	case ENOENT:
3162803fa47SRyan Moeller 		return (INVALID_IFMEDIA);
3172803fa47SRyan Moeller 	default:
3182803fa47SRyan Moeller 		err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
3194e61f6f1SSam Leffler 	}
3202803fa47SRyan Moeller 	/*NOTREACHED*/
3214e61f6f1SSam Leffler }
3224e61f6f1SSam Leffler 
3232803fa47SRyan Moeller static ifmedia_t
get_media_options(ifmedia_t media,const char * val)3242803fa47SRyan Moeller get_media_options(ifmedia_t media, const char *val)
3254edfe6b9SPeter Wemm {
3262803fa47SRyan Moeller 	ifmedia_t *options;
3272803fa47SRyan Moeller 	const char **optnames;
3282803fa47SRyan Moeller 	char *opts, *opt;
3292803fa47SRyan Moeller 	size_t nopts;
3302803fa47SRyan Moeller 	int rval;
3314edfe6b9SPeter Wemm 
3324edfe6b9SPeter Wemm 	/*
3332803fa47SRyan Moeller 	 * We muck with the string, so copy it.
3344edfe6b9SPeter Wemm 	 */
3352803fa47SRyan Moeller 	opts = strdup(val);
3362803fa47SRyan Moeller 	if (opts == NULL)
3372803fa47SRyan Moeller 		err(EXIT_FAILURE, "strdup");
3382803fa47SRyan Moeller 
3392803fa47SRyan Moeller 	/*
3402803fa47SRyan Moeller 	 * Split the comma-delimited list into separate strings.
3412803fa47SRyan Moeller 	 */
3422803fa47SRyan Moeller 	nopts = 0;
3432803fa47SRyan Moeller 	for (opt = opts; (opt = strtok(opt, ",")) != NULL; opt = NULL)
3442803fa47SRyan Moeller 		++nopts;
3452803fa47SRyan Moeller 	if (nopts == 0) {
3462803fa47SRyan Moeller 		free(opts);
3472803fa47SRyan Moeller 		return (0);
3484edfe6b9SPeter Wemm 	}
3492803fa47SRyan Moeller 	optnames = calloc(nopts, sizeof(*optnames));
3502803fa47SRyan Moeller 	if (optnames == NULL)
3512803fa47SRyan Moeller 		err(EXIT_FAILURE, "calloc");
3522803fa47SRyan Moeller 	opt = opts;
3532803fa47SRyan Moeller 	for (size_t i = 0; i < nopts; ++i) {
3542803fa47SRyan Moeller 		optnames[i] = opt;
3552803fa47SRyan Moeller 		opt = strchr(opt, '\0') + 1;
3564edfe6b9SPeter Wemm 	}
3574edfe6b9SPeter Wemm 
3582803fa47SRyan Moeller 	/*
3592803fa47SRyan Moeller 	 * Look up the options in the user-provided list.
3602803fa47SRyan Moeller 	 */
3612803fa47SRyan Moeller 	options = ifconfig_media_lookup_options(media, optnames, nopts);
3622803fa47SRyan Moeller 	if (options == NULL)
3632803fa47SRyan Moeller 		err(EXIT_FAILURE, "ifconfig_media_lookup_options");
3642803fa47SRyan Moeller 	rval = 0;
3652803fa47SRyan Moeller 	for (size_t i = 0; i < nopts; ++i) {
3662803fa47SRyan Moeller 		if (options[i] == INVALID_IFMEDIA)
3672803fa47SRyan Moeller 			errx(EXIT_FAILURE, "unknown option: %s", optnames[i]);
3682803fa47SRyan Moeller 		rval |= options[i];
3692803fa47SRyan Moeller 	}
3702803fa47SRyan Moeller 	free(options);
3712803fa47SRyan Moeller 	free(optnames);
3722803fa47SRyan Moeller 	free(opts);
3734edfe6b9SPeter Wemm 	return (rval);
3744edfe6b9SPeter Wemm }
3754edfe6b9SPeter Wemm 
376ca299b1fSPoul-Henning Kamp static void
print_media(ifmedia_t media,bool print_toptype)3772803fa47SRyan Moeller print_media(ifmedia_t media, bool print_toptype)
378ca299b1fSPoul-Henning Kamp {
3792803fa47SRyan Moeller 	const char *val, **options;
3804edfe6b9SPeter Wemm 
3812803fa47SRyan Moeller 	val = ifconfig_media_get_type(media);
3822803fa47SRyan Moeller 	if (val == NULL) {
3834edfe6b9SPeter Wemm 		printf("<unknown type>");
3844edfe6b9SPeter Wemm 		return;
385ca299b1fSPoul-Henning Kamp 	} else if (print_toptype) {
3862803fa47SRyan Moeller 		printf("%s", val);
3874edfe6b9SPeter Wemm 	}
3884edfe6b9SPeter Wemm 
3892803fa47SRyan Moeller 	val = ifconfig_media_get_subtype(media);
3902803fa47SRyan Moeller 	if (val == NULL) {
3914edfe6b9SPeter Wemm 		printf("<unknown subtype>");
3924edfe6b9SPeter Wemm 		return;
39368e16088SThomas Quinot 	}
3944edfe6b9SPeter Wemm 
395ca299b1fSPoul-Henning Kamp 	if (print_toptype)
396ca299b1fSPoul-Henning Kamp 		putchar(' ');
397ca299b1fSPoul-Henning Kamp 
3982803fa47SRyan Moeller 	printf("%s", val);
3994edfe6b9SPeter Wemm 
4004e61f6f1SSam Leffler 	if (print_toptype) {
4012803fa47SRyan Moeller 		val = ifconfig_media_get_mode(media);
4022803fa47SRyan Moeller 		if (val != NULL && strcasecmp("autoselect", val) != 0)
4032803fa47SRyan Moeller 			printf(" mode %s", val);
4044e61f6f1SSam Leffler 	}
4054e61f6f1SSam Leffler 
4062803fa47SRyan Moeller 	options = ifconfig_media_get_options(media);
4072803fa47SRyan Moeller 	if (options != NULL && options[0] != NULL) {
4082803fa47SRyan Moeller 		printf(" <%s", options[0]);
4092803fa47SRyan Moeller 		for (size_t i = 1; options[i] != NULL; ++i)
4102803fa47SRyan Moeller 			printf(",%s", options[i]);
4112803fa47SRyan Moeller 		printf(">");
4124edfe6b9SPeter Wemm 	}
4132803fa47SRyan Moeller 	free(options);
41411139493SMarius Strobl 
4152803fa47SRyan Moeller 	if (print_toptype && IFM_INST(media) != 0)
4162803fa47SRyan Moeller 		printf(" instance %d", IFM_INST(media));
4174edfe6b9SPeter Wemm }
4184edfe6b9SPeter Wemm 
419ca299b1fSPoul-Henning Kamp static void
print_media_ifconfig(ifmedia_t media)4202803fa47SRyan Moeller print_media_ifconfig(ifmedia_t media)
421ca299b1fSPoul-Henning Kamp {
4222803fa47SRyan Moeller 	const char *val, **options;
423ca299b1fSPoul-Henning Kamp 
4242803fa47SRyan Moeller 	val = ifconfig_media_get_type(media);
4252803fa47SRyan Moeller 	if (val == NULL) {
426ca299b1fSPoul-Henning Kamp 		printf("<unknown type>");
427ca299b1fSPoul-Henning Kamp 		return;
428ca299b1fSPoul-Henning Kamp 	}
429ca299b1fSPoul-Henning Kamp 
430ca299b1fSPoul-Henning Kamp 	/*
431ca299b1fSPoul-Henning Kamp 	 * Don't print the top-level type; it's not like we can
432ca299b1fSPoul-Henning Kamp 	 * change it, or anything.
433ca299b1fSPoul-Henning Kamp 	 */
434ca299b1fSPoul-Henning Kamp 
4352803fa47SRyan Moeller 	val = ifconfig_media_get_subtype(media);
4362803fa47SRyan Moeller 	if (val == NULL) {
437ca299b1fSPoul-Henning Kamp 		printf("<unknown subtype>");
438ca299b1fSPoul-Henning Kamp 		return;
43968e16088SThomas Quinot 	}
440ca299b1fSPoul-Henning Kamp 
4412803fa47SRyan Moeller 	printf("media %s", val);
442ca299b1fSPoul-Henning Kamp 
4432803fa47SRyan Moeller 	val = ifconfig_media_get_mode(media);
4442803fa47SRyan Moeller 	if (val != NULL)
4452803fa47SRyan Moeller 		printf(" mode %s", val);
4464e61f6f1SSam Leffler 
4472803fa47SRyan Moeller 	options = ifconfig_media_get_options(media);
4482803fa47SRyan Moeller 	if (options != NULL && options[0] != NULL) {
4492803fa47SRyan Moeller 		printf(" mediaopt %s", options[0]);
4502803fa47SRyan Moeller 		for (size_t i = 1; options[i] != NULL; ++i)
4512803fa47SRyan Moeller 			printf(",%s", options[i]);
452ca299b1fSPoul-Henning Kamp 	}
4532803fa47SRyan Moeller 	free(options);
45411139493SMarius Strobl 
4552803fa47SRyan Moeller 	if (IFM_INST(media) != 0)
4562803fa47SRyan Moeller 		printf(" instance %d", IFM_INST(media));
457ca299b1fSPoul-Henning Kamp }
458ca299b1fSPoul-Henning Kamp 
4594edfe6b9SPeter Wemm /**********************************************************************
4604edfe6b9SPeter Wemm  * ...until here.
4614edfe6b9SPeter Wemm  **********************************************************************/
4625faf8dcbSSam Leffler 
4635faf8dcbSSam Leffler static struct cmd media_cmds[] = {
4645faf8dcbSSam Leffler 	DEF_CMD_ARG("media",	setmedia),
4655faf8dcbSSam Leffler 	DEF_CMD_ARG("mode",	setmediamode),
4665faf8dcbSSam Leffler 	DEF_CMD_ARG("mediaopt",	setmediaopt),
4675faf8dcbSSam Leffler 	DEF_CMD_ARG("-mediaopt",unsetmediaopt),
46811139493SMarius Strobl 	DEF_CMD_ARG("inst",	setmediainst),
46911139493SMarius Strobl 	DEF_CMD_ARG("instance",	setmediainst),
4705faf8dcbSSam Leffler };
4715faf8dcbSSam Leffler static struct afswtch af_media = {
4725faf8dcbSSam Leffler 	.af_name	= "af_media",
4735faf8dcbSSam Leffler 	.af_af		= AF_UNSPEC,
47490c4b74cSSam Leffler 	.af_other_status = media_status,
4755faf8dcbSSam Leffler };
4765faf8dcbSSam Leffler 
4775faf8dcbSSam Leffler static __constructor void
ifmedia_ctor(void)4785faf8dcbSSam Leffler ifmedia_ctor(void)
4795faf8dcbSSam Leffler {
48044cd85d4SAlexander V. Chernikov 	for (size_t i = 0; i < nitems(media_cmds);  i++)
4815faf8dcbSSam Leffler 		cmd_register(&media_cmds[i]);
4825faf8dcbSSam Leffler 	af_register(&af_media);
4835faf8dcbSSam Leffler }
484