2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <sys/sysctl.h>
38 #include <net/if_dl.h>
39 #include <net/if_types.h>
40 #include <net/if_media.h>
41 #include <net/route.h>
54 #include "libifconfig.h"
55 #include "libifconfig_internal.h"
57 static const struct ifmedia_description *lookup_media_desc(
58 const struct ifmedia_description *, const char *);
59 static const struct ifmedia_type_to_subtype *get_toptype_ttos(ifmedia_t);
61 #define IFM_OPMODE(x) \
62 ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
63 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
65 #define IFM_IEEE80211_STA 0
67 static const struct ifmedia_description
68 ifm_type_descriptions[] =
69 IFM_TYPE_DESCRIPTIONS;
71 static const struct ifmedia_description
72 ifm_subtype_ethernet_descriptions[] =
73 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
75 static const struct ifmedia_description
76 ifm_subtype_ethernet_aliases[] =
77 IFM_SUBTYPE_ETHERNET_ALIASES;
79 static const struct ifmedia_description
80 ifm_subtype_ethernet_option_descriptions[] =
81 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
83 static const struct ifmedia_description
84 ifm_subtype_ieee80211_descriptions[] =
85 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
87 static const struct ifmedia_description
88 ifm_subtype_ieee80211_aliases[] =
89 IFM_SUBTYPE_IEEE80211_ALIASES;
91 static const struct ifmedia_description
92 ifm_subtype_ieee80211_option_descriptions[] =
93 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
95 static const struct ifmedia_description
96 ifm_subtype_ieee80211_mode_descriptions[] =
97 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
99 static const struct ifmedia_description
100 ifm_subtype_ieee80211_mode_aliases[] =
101 IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
103 static const struct ifmedia_description
104 ifm_subtype_atm_descriptions[] =
105 IFM_SUBTYPE_ATM_DESCRIPTIONS;
107 static const struct ifmedia_description
108 ifm_subtype_atm_aliases[] =
109 IFM_SUBTYPE_ATM_ALIASES;
111 static const struct ifmedia_description
112 ifm_subtype_atm_option_descriptions[] =
113 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
115 static const struct ifmedia_description
116 ifm_subtype_shared_descriptions[] =
117 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
119 static const struct ifmedia_description
120 ifm_subtype_shared_aliases[] =
121 IFM_SUBTYPE_SHARED_ALIASES;
123 static const struct ifmedia_description
124 ifm_shared_option_descriptions[] =
125 IFM_SHARED_OPTION_DESCRIPTIONS;
127 static const struct ifmedia_description
128 ifm_shared_option_aliases[] =
129 IFM_SHARED_OPTION_ALIASES;
131 static const struct ifmedia_description *
132 lookup_media_desc(const struct ifmedia_description *desc, const char *name)
135 for (; desc->ifmt_string != NULL; ++desc)
136 if (strcasecmp(desc->ifmt_string, name) == 0)
141 struct ifmedia_type_to_subtype {
143 const struct ifmedia_description *desc;
148 const struct ifmedia_description *desc;
153 const struct ifmedia_description *desc;
159 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
160 static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] =
164 { &ifm_subtype_shared_descriptions[0], 0 },
165 { &ifm_subtype_shared_aliases[0], 1 },
166 { &ifm_subtype_ethernet_descriptions[0], 0 },
167 { &ifm_subtype_ethernet_aliases[0], 1 },
171 { &ifm_shared_option_descriptions[0], 0 },
172 { &ifm_shared_option_aliases[0], 1 },
173 { &ifm_subtype_ethernet_option_descriptions[0], 0 },
182 { &ifm_subtype_shared_descriptions[0], 0 },
183 { &ifm_subtype_shared_aliases[0], 1 },
184 { &ifm_subtype_ieee80211_descriptions[0], 0 },
185 { &ifm_subtype_ieee80211_aliases[0], 1 },
189 { &ifm_shared_option_descriptions[0], 0 },
190 { &ifm_shared_option_aliases[0], 1 },
191 { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
195 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
196 { &ifm_subtype_ieee80211_mode_aliases[0], 0 },
202 { &ifm_subtype_shared_descriptions[0], 0 },
203 { &ifm_subtype_shared_aliases[0], 1 },
204 { &ifm_subtype_atm_descriptions[0], 0 },
205 { &ifm_subtype_atm_aliases[0], 1 },
209 { &ifm_shared_option_descriptions[0], 0 },
210 { &ifm_shared_option_aliases[0], 1 },
211 { &ifm_subtype_atm_option_descriptions[0], 0 },
220 static const struct ifmedia_type_to_subtype *
221 get_toptype_ttos(ifmedia_t media)
223 const struct ifmedia_description *desc;
224 const struct ifmedia_type_to_subtype *ttos;
226 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
227 desc->ifmt_string != NULL; desc++, ttos++) {
228 if (IFM_TYPE(media) == desc->ifmt_word)
236 ifconfig_media_get_type(ifmedia_t media)
238 const struct ifmedia_description *desc;
240 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; ++desc) {
241 if (IFM_TYPE(media) == desc->ifmt_word)
242 return (desc->ifmt_string);
249 ifconfig_media_lookup_type(const char *name)
251 const struct ifmedia_description *desc;
253 desc = lookup_media_desc(ifm_type_descriptions, name);
254 return (desc == NULL ? INVALID_IFMEDIA : desc->ifmt_word);
258 ifconfig_media_get_subtype(ifmedia_t media)
260 const struct ifmedia_description *desc;
261 const struct ifmedia_type_to_subtype *ttos;
263 ttos = get_toptype_ttos(media);
269 for (size_t i = 0; ttos->subtypes[i].desc != NULL; ++i) {
270 if (ttos->subtypes[i].alias)
272 for (desc = ttos->subtypes[i].desc;
273 desc->ifmt_string != NULL; ++desc) {
274 if (IFM_SUBTYPE(media) == desc->ifmt_word)
275 return (desc->ifmt_string);
283 ifconfig_media_lookup_subtype(ifmedia_t media, const char *name)
285 const struct ifmedia_description *desc;
286 const struct ifmedia_type_to_subtype *ttos;
288 ttos = get_toptype_ttos(media);
291 return (INVALID_IFMEDIA);
294 for (size_t i = 0; ttos->subtypes[i].desc != NULL; ++i) {
295 desc = lookup_media_desc(ttos->subtypes[i].desc, name);
297 return (desc->ifmt_word);
300 return (INVALID_IFMEDIA);
304 ifconfig_media_get_mode(ifmedia_t media)
306 const struct ifmedia_description *desc;
307 const struct ifmedia_type_to_subtype *ttos;
309 ttos = get_toptype_ttos(media);
315 for (size_t i = 0; ttos->modes[i].desc != NULL; ++i) {
316 if (ttos->modes[i].alias)
318 for (desc = ttos->modes[i].desc;
319 desc->ifmt_string != NULL; ++desc) {
320 if (IFM_MODE(media) == desc->ifmt_word)
321 return (desc->ifmt_string);
329 ifconfig_media_lookup_mode(ifmedia_t media, const char *name)
331 const struct ifmedia_description *desc;
332 const struct ifmedia_type_to_subtype *ttos;
334 ttos = get_toptype_ttos(media);
337 return (INVALID_IFMEDIA);
340 for (size_t i = 0; ttos->modes[i].desc != NULL; ++i) {
341 desc = lookup_media_desc(ttos->modes[i].desc, name);
343 return (desc->ifmt_word);
346 return (INVALID_IFMEDIA);
350 ifconfig_media_get_options(ifmedia_t media)
352 const char **options;
353 const struct ifmedia_description *desc;
354 const struct ifmedia_type_to_subtype *ttos;
357 ttos = get_toptype_ttos(media);
364 for (size_t i = 0; ttos->options[i].desc != NULL; ++i) {
365 if (ttos->options[i].alias)
367 for (desc = ttos->options[i].desc;
368 desc->ifmt_string != NULL; ++desc) {
369 if ((media & desc->ifmt_word) != 0)
378 options = calloc(n + 1, sizeof(*options));
384 for (size_t i = 0; ttos->options[i].desc != NULL; ++i) {
385 if (ttos->options[i].alias)
387 for (desc = ttos->options[i].desc;
388 desc->ifmt_string != NULL; ++desc) {
389 if ((media & desc->ifmt_word) != 0) {
390 options[n] = desc->ifmt_string;
399 ifconfig_media_lookup_options(ifmedia_t media, const char **opts, size_t nopts)
402 const struct ifmedia_description *desc, *opt;
403 const struct ifmedia_type_to_subtype *ttos;
405 assert(opts != NULL);
408 ttos = get_toptype_ttos(media);
414 options = calloc(nopts, sizeof(*options));
417 (void)memset(options, INVALID_IFMEDIA, nopts * sizeof(ifmedia_t));
419 for (size_t i = 0; ttos->options[i].desc != NULL; ++i) {
420 desc = ttos->options[i].desc;
421 for (size_t j = 0; j < nopts; ++j) {
422 opt = lookup_media_desc(desc, opts[j]);
424 options[j] = opt->ifmt_word;
430 /***************************************************************************
431 * Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c
432 ***************************************************************************/
434 /* Internal structure used for allocations and frees */
435 struct _ifconfig_media_status {
436 struct ifmediareq ifmr;
441 ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name,
442 struct ifmediareq **ifmr)
444 struct _ifconfig_media_status *ms, *ms2;
445 unsigned long cmd = SIOCGIFXMEDIA;
448 ms = calloc(1, sizeof(*ms));
450 h->error.errtype = OTHER;
451 h->error.errcode = ENOMEM;
454 (void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name));
457 * Check if interface supports extended media types.
459 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) {
461 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) {
462 /* Interface doesn't support SIOC{G,S}IFMEDIA. */
463 h->error.errtype = OK;
468 if (ms->ifmr.ifm_count == 0) {
470 return (0); /* Interface has no media types ?*/
473 ms2 = realloc(ms, sizeof(*ms) + sizeof(int) * ms->ifmr.ifm_count);
475 h->error.errtype = OTHER;
476 h->error.errcode = ENOMEM;
480 ms2->ifmr.ifm_ulist = &ms2->medialist[0];
482 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms2->ifmr) < 0) {
492 ifconfig_media_get_status(const struct ifmediareq *ifmr)
494 switch (IFM_TYPE(ifmr->ifm_active)) {
497 if (ifmr->ifm_status & IFM_ACTIVE) {
500 return ("no carrier");
505 if (ifmr->ifm_status & IFM_ACTIVE) {
506 /* NB: only sta mode associates */
507 if (IFM_OPMODE(ifmr->ifm_active) == IFM_IEEE80211_STA) {
508 return ("associated");
513 return ("no carrier");
522 ifconfig_media_get_downreason(ifconfig_handle_t *h, const char *name,
523 struct ifdownreason *ifdr)
526 (void)memset(ifdr, 0, sizeof(*ifdr));
527 (void)strlcpy(ifdr->ifdr_name, name, sizeof(ifdr->ifdr_name));
528 return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDOWNREASON, ifdr));