Changeset View
Changeset View
Standalone View
Standalone View
sbin/ifconfig/ifmedia.c
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdbool.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 "ifconfig.h" | #include "ifconfig.h" | ||||
static void domediaopt(const char *, int, int); | static void domediaopt(const char *, bool, int); | ||||
static int get_media_subtype(int, const char *); | static ifmedia_t get_media_subtype(ifmedia_t, const char *); | ||||
static int get_media_mode(int, const char *); | static ifmedia_t get_media_mode(ifmedia_t, const char *); | ||||
static int get_media_options(int, const char *); | static ifmedia_t get_media_options(ifmedia_t, const char *); | ||||
static int lookup_media_word(struct ifmedia_description *, const char *); | static void print_media(ifmedia_t, bool); | ||||
static void print_media_word(int, int); | static void print_media_ifconfig(ifmedia_t); | ||||
static void print_media_word_ifconfig(int); | |||||
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) \ | |||||
((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ | |||||
IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ | |||||
IFM_IEEE80211_MBSS)) | |||||
#define IFM_IEEE80211_STA 0 | |||||
static void | static void | ||||
media_status(int s) | media_status(int s) | ||||
{ | { | ||||
struct ifmediareq ifmr; | struct ifmediareq *ifmr; | ||||
struct ifdownreason ifdr; | |||||
int *media_list, i; | |||||
bool no_carrier, xmedia; | |||||
(void) memset(&ifmr, 0, sizeof(ifmr)); | if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1) | ||||
(void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); | |||||
xmedia = true; | |||||
/* | |||||
* Check if interface supports extended media types. | |||||
*/ | |||||
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) | |||||
xmedia = false; | |||||
if (!xmedia && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { | |||||
/* | |||||
* Interface doesn't support SIOC{G,S}IFMEDIA. | |||||
*/ | |||||
return; | return; | ||||
} | |||||
if (ifmr.ifm_count == 0) { | if (ifmr->ifm_count == 0) { | ||||
warnx("%s: no media types?", name); | warnx("%s: no media types?", name); | ||||
return; | goto free; | ||||
} | } | ||||
media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); | |||||
if (media_list == NULL) | |||||
err(1, "malloc"); | |||||
ifmr.ifm_ulist = media_list; | |||||
if (xmedia) { | |||||
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) | |||||
err(1, "SIOCGIFXMEDIA"); | |||||
} else { | |||||
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) | |||||
err(1, "SIOCGIFMEDIA"); | |||||
} | |||||
printf("\tmedia: "); | printf("\tmedia: "); | ||||
print_media_word(ifmr.ifm_current, 1); | print_media(ifmr->ifm_current, true); | ||||
if (ifmr.ifm_active != ifmr.ifm_current) { | if (ifmr->ifm_active != ifmr->ifm_current) { | ||||
putchar(' '); | putchar(' '); | ||||
putchar('('); | putchar('('); | ||||
print_media_word(ifmr.ifm_active, 0); | print_media(ifmr->ifm_active, false); | ||||
putchar(')'); | putchar(')'); | ||||
} | } | ||||
putchar('\n'); | putchar('\n'); | ||||
if (ifmr.ifm_status & IFM_AVALID) { | if (ifmr->ifm_status & IFM_AVALID) { | ||||
no_carrier = false; | struct ifdownreason ifdr; | ||||
printf("\tstatus: "); | const char *status; | ||||
switch (IFM_TYPE(ifmr.ifm_active)) { | |||||
case IFM_ETHER: | |||||
case IFM_ATM: | |||||
if (ifmr.ifm_status & IFM_ACTIVE) | |||||
printf("active"); | |||||
else | |||||
no_carrier = true; | |||||
break; | |||||
case IFM_IEEE80211: | status = ifconfig_media_get_status(ifmr); | ||||
if (ifmr.ifm_status & IFM_ACTIVE) { | printf("\tstatus: %s", status); | ||||
/* NB: only sta mode associates */ | if (strcmp(status, "no carrier") == 0 && | ||||
if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) | ifconfig_media_get_downreason(lifh, name, &ifdr) == 0) { | ||||
printf("associated"); | |||||
else | |||||
printf("running"); | |||||
} else | |||||
no_carrier = true; | |||||
break; | |||||
} | |||||
if (no_carrier) { | |||||
printf("no carrier"); | |||||
memset(&ifdr, 0, sizeof(ifdr)); | |||||
strlcpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); | |||||
if (ioctl(s, SIOCGIFDOWNREASON, (caddr_t)&ifdr) == 0) { | |||||
switch (ifdr.ifdr_reason) { | switch (ifdr.ifdr_reason) { | ||||
case IFDR_REASON_MSG: | case IFDR_REASON_MSG: | ||||
printf(" (%s)", ifdr.ifdr_msg); | printf(" (%s)", ifdr.ifdr_msg); | ||||
break; | break; | ||||
case IFDR_REASON_VENDOR: | case IFDR_REASON_VENDOR: | ||||
printf(" (vendor code %d)", | printf(" (vendor code %d)", | ||||
ifdr.ifdr_vendor); | ifdr.ifdr_vendor); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | |||||
putchar('\n'); | putchar('\n'); | ||||
} | } | ||||
if (ifmr.ifm_count > 0 && supmedia) { | if (supmedia) { | ||||
printf("\tsupported media:\n"); | printf("\tsupported media:\n"); | ||||
for (i = 0; i < ifmr.ifm_count; i++) { | for (size_t i = 0; i < ifmr->ifm_count; ++i) { | ||||
printf("\t\t"); | printf("\t\t"); | ||||
print_media_word_ifconfig(media_list[i]); | print_media_ifconfig(ifmr->ifm_ulist[i]); | ||||
putchar('\n'); | putchar('\n'); | ||||
} | } | ||||
} | } | ||||
free: | |||||
free(media_list); | free(ifmr); | ||||
} | } | ||||
struct ifmediareq * | struct ifmediareq * | ||||
ifmedia_getstate(int s) | ifmedia_getstate(void) | ||||
{ | { | ||||
static struct ifmediareq *ifmr = NULL; | static struct ifmediareq *ifmr; | ||||
int *mwords; | |||||
int xmedia = 1; | |||||
if (ifmr == NULL) { | if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1) | ||||
ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq)); | errc(1, ifconfig_err_errno(lifh), | ||||
if (ifmr == NULL) | "%s: ifconfig_media_get_mediareq", name); | ||||
err(1, "malloc"); | |||||
(void) memset(ifmr, 0, sizeof(struct ifmediareq)); | |||||
(void) strlcpy(ifmr->ifm_name, name, | |||||
sizeof(ifmr->ifm_name)); | |||||
ifmr->ifm_count = 0; | |||||
ifmr->ifm_ulist = NULL; | |||||
/* | |||||
* We must go through the motions of reading all | |||||
* supported media because we need to know both | |||||
* the current media type and the top-level type. | |||||
*/ | |||||
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) { | |||||
xmedia = 0; | |||||
} | |||||
if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) { | |||||
err(1, "SIOCGIFMEDIA"); | |||||
} | |||||
if (ifmr->ifm_count == 0) | if (ifmr->ifm_count == 0) | ||||
errx(1, "%s: no media types?", name); | errx(1, "%s: no media types?", name); | ||||
mwords = (int *)malloc(ifmr->ifm_count * sizeof(int)); | return (ifmr); | ||||
if (mwords == NULL) | |||||
err(1, "malloc"); | |||||
ifmr->ifm_ulist = mwords; | |||||
if (xmedia) { | |||||
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) | |||||
err(1, "SIOCGIFXMEDIA"); | |||||
} else { | |||||
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) | |||||
err(1, "SIOCGIFMEDIA"); | |||||
} | } | ||||
} | |||||
return ifmr; | |||||
} | |||||
static void | static void | ||||
setifmediacallback(int s, void *arg) | setifmediacallback(int s, void *arg) | ||||
{ | { | ||||
struct ifmediareq *ifmr = (struct ifmediareq *)arg; | struct ifmediareq *ifmr = (struct ifmediareq *)arg; | ||||
static int did_it = 0; | static bool did_it = false; | ||||
if (!did_it) { | if (!did_it) { | ||||
ifr.ifr_media = ifmr->ifm_current; | ifr.ifr_media = ifmr->ifm_current; | ||||
if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) | if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) | ||||
err(1, "SIOCSIFMEDIA (media)"); | err(1, "SIOCSIFMEDIA (media)"); | ||||
free(ifmr->ifm_ulist); | |||||
free(ifmr); | free(ifmr); | ||||
did_it = 1; | did_it = true; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
setmedia(const char *val, int d, int s, const struct afswtch *afp) | setmedia(const char *val, int d, int s, const struct afswtch *afp) | ||||
{ | { | ||||
struct ifmediareq *ifmr; | struct ifmediareq *ifmr; | ||||
int subtype; | int subtype; | ||||
ifmr = ifmedia_getstate(s); | ifmr = ifmedia_getstate(); | ||||
/* | /* | ||||
* We are primarily concerned with the top-level type. | * We are primarily concerned with the top-level type. | ||||
* However, "current" may be only IFM_NONE, so we just look | * However, "current" may be only IFM_NONE, so we just look | ||||
* for the top-level type in the first "supported type" | * for the top-level type in the first "supported type" | ||||
* entry. | * entry. | ||||
* | * | ||||
* (I'm assuming that all supported media types for a given | * (I'm assuming that all supported media types for a given | ||||
* interface will be the same top-level type..) | * interface will be the same top-level type..) | ||||
*/ | */ | ||||
subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val); | subtype = get_media_subtype(ifmr->ifm_ulist[0], val); | ||||
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | ||||
ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | | ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | | ||||
IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; | IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; | ||||
ifmr->ifm_current = ifr.ifr_media; | ifmr->ifm_current = ifr.ifr_media; | ||||
callback_register(setifmediacallback, (void *)ifmr); | callback_register(setifmediacallback, (void *)ifmr); | ||||
} | } | ||||
static void | static void | ||||
setmediaopt(const char *val, int d, int s, const struct afswtch *afp) | setmediaopt(const char *val, int d, int s, const struct afswtch *afp) | ||||
{ | { | ||||
domediaopt(val, 0, s); | domediaopt(val, false, s); | ||||
} | } | ||||
static void | static void | ||||
unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) | unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) | ||||
{ | { | ||||
domediaopt(val, 1, s); | domediaopt(val, true, s); | ||||
} | } | ||||
static void | static void | ||||
domediaopt(const char *val, int clear, int s) | domediaopt(const char *val, bool clear, int s) | ||||
{ | { | ||||
struct ifmediareq *ifmr; | struct ifmediareq *ifmr; | ||||
int options; | ifmedia_t options; | ||||
ifmr = ifmedia_getstate(s); | ifmr = ifmedia_getstate(); | ||||
options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val); | options = get_media_options(ifmr->ifm_ulist[0], val); | ||||
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | ||||
ifr.ifr_media = ifmr->ifm_current; | ifr.ifr_media = ifmr->ifm_current; | ||||
if (clear) | if (clear) | ||||
ifr.ifr_media &= ~options; | ifr.ifr_media &= ~options; | ||||
else { | else { | ||||
if (options & IFM_HDX) { | if (options & IFM_HDX) { | ||||
ifr.ifr_media &= ~IFM_FDX; | ifr.ifr_media &= ~IFM_FDX; | ||||
options &= ~IFM_HDX; | options &= ~IFM_HDX; | ||||
} | } | ||||
ifr.ifr_media |= options; | ifr.ifr_media |= options; | ||||
} | } | ||||
ifmr->ifm_current = ifr.ifr_media; | ifmr->ifm_current = ifr.ifr_media; | ||||
callback_register(setifmediacallback, (void *)ifmr); | callback_register(setifmediacallback, (void *)ifmr); | ||||
} | } | ||||
static void | static void | ||||
setmediainst(const char *val, int d, int s, const struct afswtch *afp) | setmediainst(const char *val, int d, int s, const struct afswtch *afp) | ||||
{ | { | ||||
struct ifmediareq *ifmr; | struct ifmediareq *ifmr; | ||||
int inst; | int inst; | ||||
ifmr = ifmedia_getstate(s); | ifmr = ifmedia_getstate(); | ||||
inst = atoi(val); | inst = atoi(val); | ||||
if (inst < 0 || inst > (int)IFM_INST_MAX) | if (inst < 0 || inst > (int)IFM_INST_MAX) | ||||
errx(1, "invalid media instance: %s", val); | errx(1, "invalid media instance: %s", val); | ||||
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | ||||
ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; | ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; | ||||
ifmr->ifm_current = ifr.ifr_media; | ifmr->ifm_current = ifr.ifr_media; | ||||
callback_register(setifmediacallback, (void *)ifmr); | callback_register(setifmediacallback, (void *)ifmr); | ||||
} | } | ||||
static void | static void | ||||
setmediamode(const char *val, int d, int s, const struct afswtch *afp) | setmediamode(const char *val, int d, int s, const struct afswtch *afp) | ||||
{ | { | ||||
struct ifmediareq *ifmr; | struct ifmediareq *ifmr; | ||||
int mode; | int mode; | ||||
ifmr = ifmedia_getstate(s); | ifmr = ifmedia_getstate(); | ||||
mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val); | mode = get_media_mode(ifmr->ifm_ulist[0], val); | ||||
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); | ||||
ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; | ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; | ||||
ifmr->ifm_current = ifr.ifr_media; | ifmr->ifm_current = ifr.ifr_media; | ||||
callback_register(setifmediacallback, (void *)ifmr); | callback_register(setifmediacallback, (void *)ifmr); | ||||
} | } | ||||
/********************************************************************** | static ifmedia_t | ||||
* A good chunk of this is duplicated from sys/net/if_media.c | get_media_subtype(ifmedia_t media, const char *val) | ||||
**********************************************************************/ | |||||
static struct ifmedia_description ifm_type_descriptions[] = | |||||
IFM_TYPE_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = | |||||
IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_ethernet_aliases[] = | |||||
IFM_SUBTYPE_ETHERNET_ALIASES; | |||||
static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = | |||||
IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = | |||||
IFM_SUBTYPE_IEEE80211_ALIASES; | |||||
static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; | |||||
struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = | |||||
IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; | |||||
struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = | |||||
IFM_SUBTYPE_IEEE80211_MODE_ALIASES; | |||||
static struct ifmedia_description ifm_subtype_atm_descriptions[] = | |||||
IFM_SUBTYPE_ATM_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_atm_aliases[] = | |||||
IFM_SUBTYPE_ATM_ALIASES; | |||||
static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = | |||||
IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_shared_descriptions[] = | |||||
IFM_SUBTYPE_SHARED_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_subtype_shared_aliases[] = | |||||
IFM_SUBTYPE_SHARED_ALIASES; | |||||
static struct ifmedia_description ifm_shared_option_descriptions[] = | |||||
IFM_SHARED_OPTION_DESCRIPTIONS; | |||||
static struct ifmedia_description ifm_shared_option_aliases[] = | |||||
IFM_SHARED_OPTION_ALIASES; | |||||
struct ifmedia_type_to_subtype { | |||||
struct { | |||||
struct ifmedia_description *desc; | |||||
int alias; | |||||
} subtypes[5]; | |||||
struct { | |||||
struct ifmedia_description *desc; | |||||
int alias; | |||||
} options[4]; | |||||
struct { | |||||
struct ifmedia_description *desc; | |||||
int alias; | |||||
} modes[3]; | |||||
}; | |||||
/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ | |||||
static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { | |||||
{ | { | ||||
{ | ifmedia_t subtype; | ||||
{ &ifm_subtype_shared_descriptions[0], 0 }, | |||||
{ &ifm_subtype_shared_aliases[0], 1 }, | |||||
{ &ifm_subtype_ethernet_descriptions[0], 0 }, | |||||
{ &ifm_subtype_ethernet_aliases[0], 1 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ &ifm_shared_option_descriptions[0], 0 }, | |||||
{ &ifm_shared_option_aliases[0], 1 }, | |||||
{ &ifm_subtype_ethernet_option_descriptions[0], 0 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ NULL, 0 }, | |||||
}, | |||||
}, | |||||
{ | |||||
{ | |||||
{ &ifm_subtype_shared_descriptions[0], 0 }, | |||||
{ &ifm_subtype_shared_aliases[0], 1 }, | |||||
{ &ifm_subtype_ieee80211_descriptions[0], 0 }, | |||||
{ &ifm_subtype_ieee80211_aliases[0], 1 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ &ifm_shared_option_descriptions[0], 0 }, | |||||
{ &ifm_shared_option_aliases[0], 1 }, | |||||
{ &ifm_subtype_ieee80211_option_descriptions[0], 0 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, | |||||
{ &ifm_subtype_ieee80211_mode_aliases[0], 0 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
}, | |||||
{ | |||||
{ | |||||
{ &ifm_subtype_shared_descriptions[0], 0 }, | |||||
{ &ifm_subtype_shared_aliases[0], 1 }, | |||||
{ &ifm_subtype_atm_descriptions[0], 0 }, | |||||
{ &ifm_subtype_atm_aliases[0], 1 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ &ifm_shared_option_descriptions[0], 0 }, | |||||
{ &ifm_shared_option_aliases[0], 1 }, | |||||
{ &ifm_subtype_atm_option_descriptions[0], 0 }, | |||||
{ NULL, 0 }, | |||||
}, | |||||
{ | |||||
{ NULL, 0 }, | |||||
}, | |||||
}, | |||||
}; | |||||
static int | subtype = ifconfig_media_lookup_subtype(media, val); | ||||
get_media_subtype(int type, const char *val) | if (subtype != INVALID_IFMEDIA) | ||||
{ | return (subtype); | ||||
struct ifmedia_description *desc; | switch (errno) { | ||||
struct ifmedia_type_to_subtype *ttos; | case EINVAL: | ||||
int rval, i; | errx(EXIT_FAILURE, "unknown media type 0x%x", media); | ||||
case ENOENT: | |||||
/* Find the top-level interface type. */ | errx(EXIT_FAILURE, "unknown media subtype: %s", val); | ||||
for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | default: | ||||
desc->ifmt_string != NULL; desc++, ttos++) | err(EXIT_FAILURE, "ifconfig_media_lookup_subtype"); | ||||
if (type == desc->ifmt_word) | |||||
break; | |||||
if (desc->ifmt_string == NULL) | |||||
errx(1, "unknown media type 0x%x", type); | |||||
for (i = 0; ttos->subtypes[i].desc != NULL; i++) { | |||||
rval = lookup_media_word(ttos->subtypes[i].desc, val); | |||||
if (rval != -1) | |||||
return (rval); | |||||
} | } | ||||
errx(1, "unknown media subtype: %s", val); | |||||
/*NOTREACHED*/ | /*NOTREACHED*/ | ||||
} | } | ||||
static int | static ifmedia_t | ||||
get_media_mode(int type, const char *val) | get_media_mode(ifmedia_t media, const char *val) | ||||
{ | { | ||||
struct ifmedia_description *desc; | ifmedia_t mode; | ||||
struct ifmedia_type_to_subtype *ttos; | |||||
int rval, i; | |||||
/* Find the top-level interface type. */ | mode = ifconfig_media_lookup_mode(media, val); | ||||
for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | if (mode != INVALID_IFMEDIA) | ||||
desc->ifmt_string != NULL; desc++, ttos++) | return (mode); | ||||
if (type == desc->ifmt_word) | switch (errno) { | ||||
break; | case EINVAL: | ||||
if (desc->ifmt_string == NULL) | errx(EXIT_FAILURE, "unknown media type 0x%x", media); | ||||
errx(1, "unknown media mode 0x%x", type); | case ENOENT: | ||||
return (INVALID_IFMEDIA); | |||||
for (i = 0; ttos->modes[i].desc != NULL; i++) { | default: | ||||
rval = lookup_media_word(ttos->modes[i].desc, val); | err(EXIT_FAILURE, "ifconfig_media_lookup_subtype"); | ||||
if (rval != -1) | |||||
return (rval); | |||||
} | } | ||||
return -1; | /*NOTREACHED*/ | ||||
} | } | ||||
static int | static ifmedia_t | ||||
get_media_options(int type, const char *val) | get_media_options(ifmedia_t media, const char *val) | ||||
{ | { | ||||
struct ifmedia_description *desc; | ifmedia_t *options; | ||||
struct ifmedia_type_to_subtype *ttos; | const char **optnames; | ||||
char *optlist, *optptr; | char *opts, *opt; | ||||
int option, i, rval = 0; | size_t nopts; | ||||
freqlabs: Whoops need to free this too. | |||||
int rval; | |||||
/* We muck with the string, so copy it. */ | /* | ||||
optlist = strdup(val); | * We muck with the string, so copy it. | ||||
if (optlist == NULL) | */ | ||||
err(1, "strdup"); | opts = strdup(val); | ||||
if (opts == NULL) | |||||
err(EXIT_FAILURE, "strdup"); | |||||
/* Find the top-level interface type. */ | |||||
for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | |||||
desc->ifmt_string != NULL; desc++, ttos++) | |||||
if (type == desc->ifmt_word) | |||||
break; | |||||
if (desc->ifmt_string == NULL) | |||||
errx(1, "unknown media type 0x%x", type); | |||||
/* | /* | ||||
* Look up the options in the user-provided comma-separated | * Split the comma-delimited list into separate strings. | ||||
* list. | |||||
*/ | */ | ||||
optptr = optlist; | nopts = 0; | ||||
for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { | for (opt = opts; (opt = strtok(opt, ",")) != NULL; opt = NULL) | ||||
option = -1; | ++nopts; | ||||
for (i = 0; ttos->options[i].desc != NULL; i++) { | if (nopts == 0) { | ||||
option = lookup_media_word(ttos->options[i].desc, optptr); | free(opts); | ||||
if (option != -1) | return (0); | ||||
break; | |||||
} | } | ||||
if (option == -1) | optnames = calloc(nopts, sizeof(*optnames)); | ||||
errx(1, "unknown option: %s", optptr); | if (optnames == NULL) | ||||
rval |= option; | err(EXIT_FAILURE, "calloc"); | ||||
opt = opts; | |||||
for (size_t i = 0; i < nopts; ++i) { | |||||
optnames[i] = opt; | |||||
opt = strchr(opt, '\0') + 1; | |||||
} | } | ||||
free(optlist); | /* | ||||
* Look up the options in the user-provided list. | |||||
*/ | |||||
options = ifconfig_media_lookup_options(media, optnames, nopts); | |||||
if (options == NULL) | |||||
err(EXIT_FAILURE, "ifconfig_media_lookup_options"); | |||||
rval = 0; | |||||
for (size_t i = 0; i < nopts; ++i) { | |||||
if (options[i] == INVALID_IFMEDIA) | |||||
errx(EXIT_FAILURE, "unknown option: %s", optnames[i]); | |||||
rval |= options[i]; | |||||
} | |||||
free(options); | |||||
free(optnames); | |||||
free(opts); | |||||
return (rval); | return (rval); | ||||
} | } | ||||
static int | |||||
lookup_media_word(struct ifmedia_description *desc, const char *val) | |||||
{ | |||||
for (; desc->ifmt_string != NULL; desc++) | |||||
if (strcasecmp(desc->ifmt_string, val) == 0) | |||||
return (desc->ifmt_word); | |||||
return (-1); | |||||
} | |||||
static struct ifmedia_description *get_toptype_desc(int ifmw) | |||||
{ | |||||
struct ifmedia_description *desc; | |||||
for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) | |||||
if (IFM_TYPE(ifmw) == desc->ifmt_word) | |||||
break; | |||||
return desc; | |||||
} | |||||
static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) | |||||
{ | |||||
struct ifmedia_description *desc; | |||||
struct ifmedia_type_to_subtype *ttos; | |||||
for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; | |||||
desc->ifmt_string != NULL; desc++, ttos++) | |||||
if (IFM_TYPE(ifmw) == desc->ifmt_word) | |||||
break; | |||||
return ttos; | |||||
} | |||||
static struct ifmedia_description *get_subtype_desc(int ifmw, | |||||
struct ifmedia_type_to_subtype *ttos) | |||||
{ | |||||
int i; | |||||
struct ifmedia_description *desc; | |||||
for (i = 0; ttos->subtypes[i].desc != NULL; i++) { | |||||
if (ttos->subtypes[i].alias) | |||||
continue; | |||||
for (desc = ttos->subtypes[i].desc; | |||||
desc->ifmt_string != NULL; desc++) { | |||||
if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) | |||||
return desc; | |||||
} | |||||
} | |||||
return NULL; | |||||
} | |||||
static struct ifmedia_description *get_mode_desc(int ifmw, | |||||
struct ifmedia_type_to_subtype *ttos) | |||||
{ | |||||
int i; | |||||
struct ifmedia_description *desc; | |||||
for (i = 0; ttos->modes[i].desc != NULL; i++) { | |||||
if (ttos->modes[i].alias) | |||||
continue; | |||||
for (desc = ttos->modes[i].desc; | |||||
desc->ifmt_string != NULL; desc++) { | |||||
if (IFM_MODE(ifmw) == desc->ifmt_word) | |||||
return desc; | |||||
} | |||||
} | |||||
return NULL; | |||||
} | |||||
static void | static void | ||||
print_media_word(int ifmw, int print_toptype) | print_media(ifmedia_t media, bool print_toptype) | ||||
{ | { | ||||
struct ifmedia_description *desc; | const char *val, **options; | ||||
struct ifmedia_type_to_subtype *ttos; | |||||
int seen_option = 0, i; | |||||
/* Find the top-level interface type. */ | val = ifconfig_media_get_type(media); | ||||
desc = get_toptype_desc(ifmw); | if (val == NULL) { | ||||
ttos = get_toptype_ttos(ifmw); | |||||
if (desc->ifmt_string == NULL) { | |||||
printf("<unknown type>"); | printf("<unknown type>"); | ||||
return; | return; | ||||
} else if (print_toptype) { | } else if (print_toptype) { | ||||
printf("%s", desc->ifmt_string); | printf("%s", val); | ||||
} | } | ||||
/* | val = ifconfig_media_get_subtype(media); | ||||
* Don't print the top-level type; it's not like we can | if (val == NULL) { | ||||
* change it, or anything. | |||||
*/ | |||||
/* Find subtype. */ | |||||
desc = get_subtype_desc(ifmw, ttos); | |||||
if (desc == NULL) { | |||||
printf("<unknown subtype>"); | printf("<unknown subtype>"); | ||||
return; | return; | ||||
} | } | ||||
if (print_toptype) | if (print_toptype) | ||||
putchar(' '); | putchar(' '); | ||||
printf("%s", desc->ifmt_string); | printf("%s", val); | ||||
if (print_toptype) { | if (print_toptype) { | ||||
desc = get_mode_desc(ifmw, ttos); | val = ifconfig_media_get_mode(media); | ||||
if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) | if (val != NULL && strcasecmp("autoselect", val) != 0) | ||||
printf(" mode %s", desc->ifmt_string); | printf(" mode %s", val); | ||||
} | } | ||||
/* Find options. */ | options = ifconfig_media_get_options(media); | ||||
for (i = 0; ttos->options[i].desc != NULL; i++) { | if (options != NULL && options[0] != NULL) { | ||||
if (ttos->options[i].alias) | printf(" <%s", options[0]); | ||||
continue; | for (size_t i = 1; options[i] != NULL; ++i) | ||||
for (desc = ttos->options[i].desc; | printf(",%s", options[i]); | ||||
desc->ifmt_string != NULL; desc++) { | printf(">"); | ||||
if (ifmw & desc->ifmt_word) { | |||||
if (seen_option == 0) | |||||
printf(" <"); | |||||
printf("%s%s", seen_option++ ? "," : "", | |||||
desc->ifmt_string); | |||||
} | } | ||||
} | free(options); | ||||
} | |||||
printf("%s", seen_option ? ">" : ""); | |||||
if (print_toptype && IFM_INST(ifmw) != 0) | if (print_toptype && IFM_INST(media) != 0) | ||||
printf(" instance %d", IFM_INST(ifmw)); | printf(" instance %d", IFM_INST(media)); | ||||
} | } | ||||
static void | static void | ||||
print_media_word_ifconfig(int ifmw) | print_media_ifconfig(ifmedia_t media) | ||||
{ | { | ||||
struct ifmedia_description *desc; | const char *val, **options; | ||||
struct ifmedia_type_to_subtype *ttos; | |||||
int seen_option = 0, i; | |||||
/* Find the top-level interface type. */ | val = ifconfig_media_get_type(media); | ||||
desc = get_toptype_desc(ifmw); | if (val == NULL) { | ||||
ttos = get_toptype_ttos(ifmw); | |||||
if (desc->ifmt_string == NULL) { | |||||
printf("<unknown type>"); | printf("<unknown type>"); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Don't print the top-level type; it's not like we can | * Don't print the top-level type; it's not like we can | ||||
* change it, or anything. | * change it, or anything. | ||||
*/ | */ | ||||
/* Find subtype. */ | val = ifconfig_media_get_subtype(media); | ||||
desc = get_subtype_desc(ifmw, ttos); | if (val == NULL) { | ||||
if (desc == NULL) { | |||||
printf("<unknown subtype>"); | printf("<unknown subtype>"); | ||||
return; | return; | ||||
} | } | ||||
printf("media %s", desc->ifmt_string); | printf("media %s", val); | ||||
desc = get_mode_desc(ifmw, ttos); | val = ifconfig_media_get_mode(media); | ||||
if (desc != NULL) | if (val != NULL) | ||||
printf(" mode %s", desc->ifmt_string); | printf(" mode %s", val); | ||||
/* Find options. */ | options = ifconfig_media_get_options(media); | ||||
for (i = 0; ttos->options[i].desc != NULL; i++) { | if (options != NULL && options[0] != NULL) { | ||||
if (ttos->options[i].alias) | printf(" mediaopt %s", options[0]); | ||||
continue; | for (size_t i = 1; options[i] != NULL; ++i) | ||||
for (desc = ttos->options[i].desc; | printf(",%s", options[i]); | ||||
desc->ifmt_string != NULL; desc++) { | |||||
if (ifmw & desc->ifmt_word) { | |||||
if (seen_option == 0) | |||||
printf(" mediaopt "); | |||||
printf("%s%s", seen_option++ ? "," : "", | |||||
desc->ifmt_string); | |||||
} | } | ||||
} | free(options); | ||||
} | |||||
if (IFM_INST(ifmw) != 0) | if (IFM_INST(media) != 0) | ||||
printf(" instance %d", IFM_INST(ifmw)); | printf(" instance %d", IFM_INST(media)); | ||||
} | } | ||||
/********************************************************************** | /********************************************************************** | ||||
* ...until here. | * ...until here. | ||||
**********************************************************************/ | **********************************************************************/ | ||||
static struct cmd media_cmds[] = { | static struct cmd media_cmds[] = { | ||||
DEF_CMD_ARG("media", setmedia), | DEF_CMD_ARG("media", setmedia), | ||||
Show All 21 Lines |
Whoops need to free this too.