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