Changeset View
Changeset View
Standalone View
Standalone View
lib/libifconfig/libifconfig_media.c
Show All 39 Lines | |||||
#include <net/if_media.h> | #include <net/if_media.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdbool.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "libifconfig.h" | #include "libifconfig.h" | ||||
#include "libifconfig_internal.h" | #include "libifconfig_internal.h" | ||||
static const struct ifmedia_description *lookup_media_desc( | |||||
const struct ifmedia_description *, const char *); | |||||
static const struct ifmedia_type_to_subtype *get_toptype_ttos(ifmedia_t); | |||||
static struct ifmedia_description *get_toptype_desc(int); | |||||
static struct ifmedia_type_to_subtype *get_toptype_ttos(int); | |||||
static struct ifmedia_description *get_subtype_desc(int, | |||||
struct ifmedia_type_to_subtype *ttos); | |||||
#define IFM_OPMODE(x) \ | #define IFM_OPMODE(x) \ | ||||
((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ | ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ | ||||
IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ | IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ | ||||
IFM_IEEE80211_MBSS)) | IFM_IEEE80211_MBSS)) | ||||
#define IFM_IEEE80211_STA 0 | #define IFM_IEEE80211_STA 0 | ||||
static struct ifmedia_description ifm_type_descriptions[] = | static const struct ifmedia_description | ||||
ifm_type_descriptions[] = | |||||
IFM_TYPE_DESCRIPTIONS; | IFM_TYPE_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_ethernet_descriptions[] = | |||||
IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; | IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ethernet_aliases[] = | static const struct ifmedia_description | ||||
ifm_subtype_ethernet_aliases[] = | |||||
IFM_SUBTYPE_ETHERNET_ALIASES; | IFM_SUBTYPE_ETHERNET_ALIASES; | ||||
static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_ethernet_option_descriptions[] = | |||||
IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; | IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_ieee80211_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; | IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = | static const struct ifmedia_description | ||||
ifm_subtype_ieee80211_aliases[] = | |||||
IFM_SUBTYPE_IEEE80211_ALIASES; | IFM_SUBTYPE_IEEE80211_ALIASES; | ||||
static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_ieee80211_option_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; | IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_ieee80211_mode_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; | IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = | static const struct ifmedia_description | ||||
ifm_subtype_ieee80211_mode_aliases[] = | |||||
IFM_SUBTYPE_IEEE80211_MODE_ALIASES; | IFM_SUBTYPE_IEEE80211_MODE_ALIASES; | ||||
static struct ifmedia_description ifm_subtype_atm_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_atm_descriptions[] = | |||||
IFM_SUBTYPE_ATM_DESCRIPTIONS; | IFM_SUBTYPE_ATM_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_atm_aliases[] = | static const struct ifmedia_description | ||||
ifm_subtype_atm_aliases[] = | |||||
IFM_SUBTYPE_ATM_ALIASES; | IFM_SUBTYPE_ATM_ALIASES; | ||||
static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_atm_option_descriptions[] = | |||||
IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; | IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_shared_descriptions[] = | static const struct ifmedia_description | ||||
ifm_subtype_shared_descriptions[] = | |||||
IFM_SUBTYPE_SHARED_DESCRIPTIONS; | IFM_SUBTYPE_SHARED_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_subtype_shared_aliases[] = | static const struct ifmedia_description | ||||
ifm_subtype_shared_aliases[] = | |||||
IFM_SUBTYPE_SHARED_ALIASES; | IFM_SUBTYPE_SHARED_ALIASES; | ||||
static struct ifmedia_description ifm_shared_option_descriptions[] = | static const struct ifmedia_description | ||||
ifm_shared_option_descriptions[] = | |||||
IFM_SHARED_OPTION_DESCRIPTIONS; | IFM_SHARED_OPTION_DESCRIPTIONS; | ||||
static struct ifmedia_description ifm_shared_option_aliases[] = | static const struct ifmedia_description | ||||
ifm_shared_option_aliases[] = | |||||
IFM_SHARED_OPTION_ALIASES; | IFM_SHARED_OPTION_ALIASES; | ||||
static const struct ifmedia_description * | |||||
lookup_media_desc(const struct ifmedia_description *desc, const char *name) | |||||
{ | |||||
for (; desc->ifmt_string != NULL; ++desc) | |||||
if (strcasecmp(desc->ifmt_string, name) == 0) | |||||
return (desc); | |||||
return (NULL); | |||||
} | |||||
struct ifmedia_type_to_subtype { | struct ifmedia_type_to_subtype { | ||||
struct { | struct { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
int alias; | bool alias; | ||||
} | } | ||||
subtypes[5]; | subtypes[5]; | ||||
struct { | struct { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
int alias; | bool alias; | ||||
} | } | ||||
options[4]; | options[4]; | ||||
struct { | struct { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
int alias; | bool alias; | ||||
} | } | ||||
modes[3]; | modes[3]; | ||||
}; | }; | ||||
/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ | /* must be in the same order as IFM_TYPE_DESCRIPTIONS */ | ||||
static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = | static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = | ||||
{ | { | ||||
{ | { | ||||
{ | { | ||||
{ &ifm_subtype_shared_descriptions[0], 0 }, | { &ifm_subtype_shared_descriptions[0], 0 }, | ||||
{ &ifm_subtype_shared_aliases[0], 1 }, | { &ifm_subtype_shared_aliases[0], 1 }, | ||||
{ &ifm_subtype_ethernet_descriptions[0], 0 }, | { &ifm_subtype_ethernet_descriptions[0], 0 }, | ||||
{ &ifm_subtype_ethernet_aliases[0], 1 }, | { &ifm_subtype_ethernet_aliases[0], 1 }, | ||||
{ NULL, 0 }, | { NULL, 0 }, | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = | ||||
{ NULL, 0 }, | { NULL, 0 }, | ||||
}, | }, | ||||
{ | { | ||||
{ NULL, 0 }, | { NULL, 0 }, | ||||
}, | }, | ||||
}, | }, | ||||
}; | }; | ||||
static struct ifmedia_description * | static const struct ifmedia_type_to_subtype * | ||||
get_toptype_desc(int ifmw) | get_toptype_ttos(ifmedia_t media) | ||||
{ | { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
const struct ifmedia_type_to_subtype *ttos; | |||||
for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) { | for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | ||||
if (IFM_TYPE(ifmw) == desc->ifmt_word) { | desc->ifmt_string != NULL; desc++, ttos++) { | ||||
break; | if (IFM_TYPE(media) == desc->ifmt_word) | ||||
return (ttos); | |||||
} | } | ||||
errno = ENOENT; | |||||
return (NULL); | |||||
} | } | ||||
return (desc); | const char * | ||||
} | ifconfig_media_get_type(ifmedia_t media) | ||||
static struct ifmedia_type_to_subtype * | |||||
get_toptype_ttos(int ifmw) | |||||
{ | { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
struct ifmedia_type_to_subtype *ttos; | |||||
for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; ++desc) { | ||||
desc->ifmt_string != NULL; desc++, ttos++) { | if (IFM_TYPE(media) == desc->ifmt_word) | ||||
if (IFM_TYPE(ifmw) == desc->ifmt_word) { | return (desc->ifmt_string); | ||||
break; | |||||
} | } | ||||
errno = ENOENT; | |||||
return (NULL); | |||||
} | } | ||||
return (ttos); | ifmedia_t | ||||
ifconfig_media_lookup_type(const char *name) | |||||
{ | |||||
const struct ifmedia_description *desc; | |||||
desc = lookup_media_desc(ifm_type_descriptions, name); | |||||
return (desc == NULL ? INVALID_IFMEDIA : desc->ifmt_word); | |||||
} | } | ||||
static struct ifmedia_description * | const char * | ||||
get_subtype_desc(int ifmw, | ifconfig_media_get_subtype(ifmedia_t media) | ||||
struct ifmedia_type_to_subtype *ttos) | |||||
{ | { | ||||
int i; | const struct ifmedia_description *desc; | ||||
struct ifmedia_description *desc; | const struct ifmedia_type_to_subtype *ttos; | ||||
for (i = 0; ttos->subtypes[i].desc != NULL; i++) { | ttos = get_toptype_ttos(media); | ||||
if (ttos->subtypes[i].alias) { | if (ttos == NULL) { | ||||
continue; | errno = EINVAL; | ||||
return (NULL); | |||||
} | } | ||||
for (size_t i = 0; ttos->subtypes[i].desc != NULL; ++i) { | |||||
if (ttos->subtypes[i].alias) | |||||
continue; | |||||
for (desc = ttos->subtypes[i].desc; | for (desc = ttos->subtypes[i].desc; | ||||
desc->ifmt_string != NULL; desc++) { | desc->ifmt_string != NULL; ++desc) { | ||||
if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) { | if (IFM_SUBTYPE(media) == desc->ifmt_word) | ||||
return (desc); | return (desc->ifmt_string); | ||||
} | } | ||||
} | } | ||||
errno = ENOENT; | |||||
return (NULL); | |||||
} | } | ||||
return (NULL); | ifmedia_t | ||||
ifconfig_media_lookup_subtype(ifmedia_t media, const char *name) | |||||
{ | |||||
const struct ifmedia_description *desc; | |||||
const struct ifmedia_type_to_subtype *ttos; | |||||
ttos = get_toptype_ttos(media); | |||||
if (ttos == NULL) { | |||||
errno = EINVAL; | |||||
return (INVALID_IFMEDIA); | |||||
} | } | ||||
for (size_t i = 0; ttos->subtypes[i].desc != NULL; ++i) { | |||||
desc = lookup_media_desc(ttos->subtypes[i].desc, name); | |||||
if (desc != NULL) | |||||
return (desc->ifmt_word); | |||||
} | |||||
errno = ENOENT; | |||||
return (INVALID_IFMEDIA); | |||||
} | |||||
const char * | const char * | ||||
ifconfig_media_get_type(int ifmw) | ifconfig_media_get_mode(ifmedia_t media) | ||||
{ | { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
const struct ifmedia_type_to_subtype *ttos; | |||||
/*int seen_option = 0, i;*/ | ttos = get_toptype_ttos(media); | ||||
if (ttos == NULL) { | |||||
errno = EINVAL; | |||||
return (NULL); | |||||
} | |||||
/* Find the top-level interface type. */ | for (size_t i = 0; ttos->modes[i].desc != NULL; ++i) { | ||||
desc = get_toptype_desc(ifmw); | if (ttos->modes[i].alias) | ||||
if (desc->ifmt_string == NULL) { | continue; | ||||
return ("<unknown type>"); | for (desc = ttos->modes[i].desc; | ||||
} else { | desc->ifmt_string != NULL; ++desc) { | ||||
if (IFM_MODE(media) == desc->ifmt_word) | |||||
return (desc->ifmt_string); | return (desc->ifmt_string); | ||||
} | } | ||||
} | } | ||||
errno = ENOENT; | |||||
return (NULL); | |||||
} | |||||
const char * | ifmedia_t | ||||
ifconfig_media_get_subtype(int ifmw) | ifconfig_media_lookup_mode(ifmedia_t media, const char *name) | ||||
{ | { | ||||
struct ifmedia_description *desc; | const struct ifmedia_description *desc; | ||||
struct ifmedia_type_to_subtype *ttos; | const struct ifmedia_type_to_subtype *ttos; | ||||
ttos = get_toptype_ttos(ifmw); | ttos = get_toptype_ttos(media); | ||||
desc = get_subtype_desc(ifmw, ttos); | if (ttos == NULL) { | ||||
return (desc->ifmt_string); | errno = EINVAL; | ||||
return (INVALID_IFMEDIA); | |||||
} | } | ||||
for (size_t i = 0; ttos->modes[i].desc != NULL; ++i) { | |||||
desc = lookup_media_desc(ttos->modes[i].desc, name); | |||||
if (desc != NULL) | |||||
return (desc->ifmt_word); | |||||
} | |||||
errno = ENOENT; | |||||
return (INVALID_IFMEDIA); | |||||
} | |||||
const char ** | |||||
ifconfig_media_get_options(ifmedia_t media) | |||||
{ | |||||
const char **options; | |||||
const struct ifmedia_description *desc; | |||||
const struct ifmedia_type_to_subtype *ttos; | |||||
size_t n; | |||||
ttos = get_toptype_ttos(media); | |||||
if (ttos == NULL) { | |||||
errno = EINVAL; | |||||
return (NULL); | |||||
} | |||||
n = 0; | |||||
for (size_t i = 0; ttos->options[i].desc != NULL; ++i) { | |||||
if (ttos->options[i].alias) | |||||
continue; | |||||
for (desc = ttos->options[i].desc; | |||||
desc->ifmt_string != NULL; ++desc) { | |||||
if ((media & desc->ifmt_word) != 0) | |||||
++n; | |||||
} | |||||
} | |||||
if (n == 0) { | |||||
errno = ENOENT; | |||||
return (NULL); | |||||
} | |||||
options = calloc(n + 1, sizeof(*options)); | |||||
if (options == NULL) | |||||
return (NULL); | |||||
options[n] = NULL; | |||||
n = 0; | |||||
for (size_t i = 0; ttos->options[i].desc != NULL; ++i) { | |||||
if (ttos->options[i].alias) | |||||
continue; | |||||
for (desc = ttos->options[i].desc; | |||||
desc->ifmt_string != NULL; ++desc) { | |||||
if ((media & desc->ifmt_word) != 0) { | |||||
options[n] = desc->ifmt_string; | |||||
++n; | |||||
} | |||||
} | |||||
} | |||||
return (options); | |||||
} | |||||
ifmedia_t * | |||||
ifconfig_media_lookup_options(ifmedia_t media, const char **opts, size_t nopts) | |||||
{ | |||||
ifmedia_t *options; | |||||
const struct ifmedia_description *desc, *opt; | |||||
const struct ifmedia_type_to_subtype *ttos; | |||||
assert(opts != NULL); | |||||
assert(nopts > 0); | |||||
ttos = get_toptype_ttos(media); | |||||
if (ttos == NULL) { | |||||
errno = EINVAL; | |||||
return (NULL); | |||||
} | |||||
options = calloc(nopts, sizeof(*options)); | |||||
if (options == NULL) | |||||
return (NULL); | |||||
(void)memset(options, INVALID_IFMEDIA, nopts * sizeof(ifmedia_t)); | |||||
for (size_t i = 0; ttos->options[i].desc != NULL; ++i) { | |||||
desc = ttos->options[i].desc; | |||||
for (size_t j = 0; j < nopts; ++j) { | |||||
opt = lookup_media_desc(desc, opts[j]); | |||||
if (opt != NULL) | |||||
options[j] = opt->ifmt_word; | |||||
} | |||||
} | |||||
return (options); | |||||
} | |||||
/*************************************************************************** | /*************************************************************************** | ||||
* Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c | * Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c | ||||
***************************************************************************/ | ***************************************************************************/ | ||||
/* Internal structure used for allocations and frees */ | /* Internal structure used for allocations and frees */ | ||||
struct _ifconfig_media_status { | struct _ifconfig_media_status { | ||||
struct ifmediareq ifmr; | struct ifmediareq ifmr; | ||||
int medialist[0]; | int medialist[0]; | ||||
}; | }; | ||||
int | int | ||||
ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, | ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, | ||||
struct ifmediareq **ifmr) | struct ifmediareq **ifmr) | ||||
{ | { | ||||
struct _ifconfig_media_status *ms, *ms2; | struct _ifconfig_media_status *ms, *ms2; | ||||
unsigned long cmd = SIOCGIFXMEDIA; | unsigned long cmd = SIOCGIFXMEDIA; | ||||
*ifmr = NULL; | *ifmr = NULL; | ||||
ms = calloc(1, sizeof(*ms)); | ms = calloc(1, sizeof(*ms)); | ||||
if (ms == NULL) { | if (ms == NULL) { | ||||
h->error.errtype = OTHER; | h->error.errtype = OTHER; | ||||
h->error.errcode = ENOMEM; | h->error.errcode = ENOMEM; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
(void)memset(ms, 0, sizeof(*ms)); | |||||
(void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name)); | (void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name)); | ||||
/* | /* | ||||
* Check if interface supports extended media types. | * Check if interface supports extended media types. | ||||
*/ | */ | ||||
if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { | if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { | ||||
cmd = SIOCGIFMEDIA; | cmd = SIOCGIFMEDIA; | ||||
if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { | if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (ifmr->ifm_status & IFM_ACTIVE) { | ||||
return ("running"); | return ("running"); | ||||
} | } | ||||
} else { | } else { | ||||
return ("no carrier"); | return ("no carrier"); | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
return (""); | return (""); | ||||
} | |||||
} | |||||
void | |||||
ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen) | |||||
{ | |||||
struct ifmedia_type_to_subtype *ttos; | |||||
struct ifmedia_description *desc; | |||||
int i, seen_option = 0; | |||||
size_t len; | |||||
assert(buflen > 0); | |||||
buf[0] = '\0'; | |||||
ttos = get_toptype_ttos(ifmw); | |||||
for (i = 0; ttos->options[i].desc != NULL; i++) { | |||||
if (ttos->options[i].alias) { | |||||
continue; | |||||
} | |||||
for (desc = ttos->options[i].desc; | |||||
desc->ifmt_string != NULL; desc++) { | |||||
if (ifmw & desc->ifmt_word) { | |||||
if (seen_option++) { | |||||
strlcat(buf, ",", buflen); | |||||
} | |||||
len = strlcat(buf, desc->ifmt_string, buflen); | |||||
assert(len < buflen); | |||||
buf += len; | |||||
buflen -= len; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
int | int | ||||
ifconfig_media_get_downreason(ifconfig_handle_t *h, const char *name, | ifconfig_media_get_downreason(ifconfig_handle_t *h, const char *name, | ||||
struct ifdownreason *ifdr) | struct ifdownreason *ifdr) | ||||
{ | { | ||||
(void)memset(ifdr, 0, sizeof(*ifdr)); | (void)memset(ifdr, 0, sizeof(*ifdr)); | ||||
(void)strlcpy(ifdr->ifdr_name, name, sizeof(ifdr->ifdr_name)); | (void)strlcpy(ifdr->ifdr_name, name, sizeof(ifdr->ifdr_name)); | ||||
return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDOWNREASON, ifdr)); | return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDOWNREASON, ifdr)); | ||||
} | } |