diff --git a/lib/libifconfig/Symbol.map b/lib/libifconfig/Symbol.map index ec1ccec7f95c..782f78ec5e34 100644 --- a/lib/libifconfig/Symbol.map +++ b/lib/libifconfig/Symbol.map @@ -1,74 +1,75 @@ FBSD_1.6 { ifconfig_bridge_get_bridge_status; ifconfig_bridge_free_bridge_status; ifconfig_carp_get_info; ifconfig_close; ifconfig_create_interface; ifconfig_create_interface_vlan; ifconfig_destroy_interface; ifconfig_err_errno; ifconfig_err_errtype; ifconfig_err_ioctlreq; ifconfig_foreach_ifaddr; ifconfig_foreach_iface; ifconfig_get_capability; ifconfig_get_description; ifconfig_get_fib; ifconfig_get_groups; ifconfig_get_ifstatus; ifconfig_get_metric; ifconfig_get_mtu; ifconfig_get_nd6; ifconfig_get_orig_name; ifconfig_inet_get_addrinfo; ifconfig_inet6_get_addrinfo; ifconfig_lagg_free_lagg_status; ifconfig_lagg_get_lagg_status; ifconfig_lagg_get_laggport_status; ifconfig_list_cloners; ifconfig_media_get_mediareq; ifconfig_media_get_options_string; ifconfig_media_get_status; ifconfig_media_get_subtype; ifconfig_media_get_type; + ifconfig_media_get_downreason; ifconfig_open; ifconfig_set_capability; ifconfig_set_description; ifconfig_set_fib; ifconfig_set_metric; ifconfig_set_mtu; ifconfig_set_name; ifconfig_set_vlantag; ifconfig_sfp_channel_count; ifconfig_sfp_dump_region_count; ifconfig_sfp_free_sfp_status; ifconfig_sfp_get_sfp_dump; ifconfig_sfp_get_sfp_info; ifconfig_sfp_get_sfp_info_strings; ifconfig_sfp_get_sfp_status; ifconfig_sfp_get_sfp_vendor_info; ifconfig_sfp_physical_spec; ifconfig_unset_description; bias_mA; power_dBm; power_mW; /* Auto-generated. */ ifconfig_sfp_cab_tech_description; ifconfig_sfp_cab_tech_symbol; ifconfig_sfp_conn_description; ifconfig_sfp_conn_symbol; ifconfig_sfp_eth_10g_description; ifconfig_sfp_eth_10g_symbol; ifconfig_sfp_eth_1040g_description; ifconfig_sfp_eth_1040g_symbol; ifconfig_sfp_eth_description; ifconfig_sfp_eth_symbol; ifconfig_sfp_eth_ext_description; ifconfig_sfp_eth_ext_symbol; ifconfig_sfp_fc_speed_description; ifconfig_sfp_fc_speed_symbol; ifconfig_sfp_rev_description; ifconfig_sfp_rev_symbol; }; diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h index 46a13ae27d69..d8245ea13b23 100644 --- a/lib/libifconfig/libifconfig.h +++ b/lib/libifconfig/libifconfig.h @@ -1,291 +1,300 @@ /* * Copyright (c) 2016-2017, Marie Helene Kvello-Aune * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * thislist of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #pragma once #include #include #include #include #define ND6_IFF_DEFAULTIF 0x8000 typedef enum { OK = 0, OTHER, IOCTL, SOCKET } ifconfig_errtype; /* * Opaque definition so calling application can just pass a * pointer to it for library use. */ struct ifconfig_handle; typedef struct ifconfig_handle ifconfig_handle_t; struct carpreq; struct ifaddrs; struct ifbropreq; struct ifbreq; struct in6_ndireq; struct lagg_reqall; struct lagg_reqflags; struct lagg_reqopts; struct lagg_reqport; /** Stores extra info associated with a bridge(4) interface */ struct ifconfig_bridge_status { struct ifbropreq *params; /**< current operational parameters */ struct ifbreq *members; /**< list of bridge members */ size_t members_count; /**< how many member interfaces */ uint32_t cache_size; /**< size of address cache */ uint32_t cache_lifetime; /**< address cache entry lifetime */ }; struct ifconfig_capabilities { /** Current capabilities (ifconfig prints this as 'options')*/ int curcap; /** Requested capabilities (ifconfig prints this as 'capabilities')*/ int reqcap; }; /** Stores extra info associated with an inet address */ struct ifconfig_inet_addr { const struct sockaddr_in *sin; const struct sockaddr_in *netmask; const struct sockaddr_in *dst; const struct sockaddr_in *broadcast; int prefixlen; uint8_t vhid; }; /** Stores extra info associated with an inet6 address */ struct ifconfig_inet6_addr { struct sockaddr_in6 *sin6; struct sockaddr_in6 *dstin6; struct in6_addrlifetime lifetime; int prefixlen; uint32_t flags; uint8_t vhid; }; /** Stores extra info associated with a lagg(4) interface */ struct ifconfig_lagg_status { struct lagg_reqall *ra; struct lagg_reqopts *ro; struct lagg_reqflags *rf; }; /** Retrieves a new state object for use in other API calls. * Example usage: *{@code * // Create state object * ifconfig_handle_t *lifh; * lifh = ifconfig_open(); * if (lifh == NULL) { * // Handle error * } * * // Do stuff with the handle * * // Dispose of the state object * ifconfig_close(lifh); * lifh = NULL; *} */ ifconfig_handle_t *ifconfig_open(void); /** Frees resources held in the provided state object. * @param h The state object to close. * @see #ifconfig_open(void) */ void ifconfig_close(ifconfig_handle_t *h); /** Identifies what kind of error occured. */ ifconfig_errtype ifconfig_err_errtype(ifconfig_handle_t *h); /** Retrieves the errno associated with the error, if any. */ int ifconfig_err_errno(ifconfig_handle_t *h); typedef void (*ifconfig_foreach_func_t)(ifconfig_handle_t *h, struct ifaddrs *ifa, void *udata); /** Iterate over every network interface * @param h An open ifconfig state object * @param cb A callback function to call with a pointer to each interface * @param udata An opaque value that will be passed to the callback. * @return 0 on success, nonzero if the list could not be iterated */ int ifconfig_foreach_iface(ifconfig_handle_t *h, ifconfig_foreach_func_t cb, void *udata); /** Iterate over every address on a single network interface * @param h An open ifconfig state object * @param ifa A pointer that was supplied by a previous call to * ifconfig_foreach_iface * @param udata An opaque value that will be passed to the callback. * @param cb A callback function to call with a pointer to each ifaddr */ void ifconfig_foreach_ifaddr(ifconfig_handle_t *h, struct ifaddrs *ifa, ifconfig_foreach_func_t cb, void *udata); /** If error type was IOCTL, this identifies which request failed. */ unsigned long ifconfig_err_ioctlreq(ifconfig_handle_t *h); int ifconfig_get_description(ifconfig_handle_t *h, const char *name, char **description); int ifconfig_set_description(ifconfig_handle_t *h, const char *name, const char *newdescription); int ifconfig_unset_description(ifconfig_handle_t *h, const char *name); int ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname); int ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname, char **orig_name); int ifconfig_set_fib(ifconfig_handle_t *h, const char *name, int fib); int ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib); int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu); int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu); int ifconfig_get_nd6(ifconfig_handle_t *h, const char *name, struct in6_ndireq *nd); int ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int metric); int ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric); int ifconfig_set_capability(ifconfig_handle_t *h, const char *name, const int capability); int ifconfig_get_capability(ifconfig_handle_t *h, const char *name, struct ifconfig_capabilities *capability); /** Retrieve the list of groups to which this interface belongs * @param h An open ifconfig state object * @param name The interface name * @param ifgr return argument. The caller is responsible for freeing * ifgr->ifgr_groups * @return 0 on success, nonzero on failure */ int ifconfig_get_groups(ifconfig_handle_t *h, const char *name, struct ifgroupreq *ifgr); int ifconfig_get_ifstatus(ifconfig_handle_t *h, const char *name, struct ifstat *stat); /** Retrieve the interface media information * @param h An open ifconfig state object * @param name The interface name * @param ifmr Return argument. The caller is responsible for freeing it * @return 0 on success, nonzero on failure */ int ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, struct ifmediareq **ifmr); const char *ifconfig_media_get_type(int ifmw); const char *ifconfig_media_get_subtype(int ifmw); const char *ifconfig_media_get_status(const struct ifmediareq *ifmr); void ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen); +/** Retrieve the reason the interface is down + * @param h An open ifconfig state object + * @param name The interface name + * @param ifdr Return argument. + * @return 0 on success, nonzero on failure + */ +int ifconfig_media_get_downreason(ifconfig_handle_t *h, const char *name, + struct ifdownreason *ifdr); + int ifconfig_carp_get_info(ifconfig_handle_t *h, const char *name, struct carpreq *carpr, int ncarpr); /** Retrieve additional information about an inet address * @param h An open ifconfig state object * @param name The interface name * @param ifa Pointer to the the address structure of interest * @param addr Return argument. It will be filled with additional information * about the address. * @return 0 on success, nonzero on failure. */ int ifconfig_inet_get_addrinfo(ifconfig_handle_t *h, const char *name, struct ifaddrs *ifa, struct ifconfig_inet_addr *addr); /** Retrieve additional information about an inet6 address * @param h An open ifconfig state object * @param name The interface name * @param ifa Pointer to the the address structure of interest * @param addr Return argument. It will be filled with additional information * about the address. * @return 0 on success, nonzero on failure. */ int ifconfig_inet6_get_addrinfo(ifconfig_handle_t *h, const char *name, struct ifaddrs *ifa, struct ifconfig_inet6_addr *addr); /** Retrieve additional information about a bridge(4) interface */ int ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, const char *name, struct ifconfig_bridge_status **bridge); /** Frees the structure returned by ifconfig_bridge_get_bridge_status. Does * nothing if the argument is NULL * @param bridge Pointer to the structure to free */ void ifconfig_bridge_free_bridge_status(struct ifconfig_bridge_status *bridge); /** Retrieve additional information about a lagg(4) interface */ int ifconfig_lagg_get_lagg_status(ifconfig_handle_t *h, const char *name, struct ifconfig_lagg_status **lagg_status); /** Retrieve additional information about a member of a lagg(4) interface */ int ifconfig_lagg_get_laggport_status(ifconfig_handle_t *h, const char *name, struct lagg_reqport *rp); /** Frees the structure returned by ifconfig_lagg_get_lagg_status. Does * nothing if the argument is NULL * @param laggstat Pointer to the structure to free */ void ifconfig_lagg_free_lagg_status(struct ifconfig_lagg_status *laggstat); /** Destroy a virtual interface * @param name Interface to destroy */ int ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name); /** Creates a (virtual) interface * @param name Name of interface to create. Example: bridge or bridge42 * @param name ifname Is set to actual name of created interface */ int ifconfig_create_interface(ifconfig_handle_t *h, const char *name, char **ifname); /** Creates a (virtual) interface * @param name Name of interface to create. Example: vlan0 or ix0.50 * @param name ifname Is set to actual name of created interface * @param vlandev Name of interface to attach to * @param vlanid VLAN ID/Tag. Must not be 0. */ int ifconfig_create_interface_vlan(ifconfig_handle_t *h, const char *name, char **ifname, const char *vlandev, const unsigned short vlantag); int ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name, const char *vlandev, const unsigned short vlantag); /** Gets the names of all interface cloners available on the system * @param bufp Set to the address of the names buffer on success or NULL * if an error occurs. This buffer must be freed when done. * @param lenp Set to the number of names in the returned buffer or 0 * if an error occurs. Each name is contained within an * IFNAMSIZ length slice of the buffer, for a total buffer * length of *lenp * IFNAMSIZ bytes. */ int ifconfig_list_cloners(ifconfig_handle_t *h, char **bufp, size_t *lenp); diff --git a/lib/libifconfig/libifconfig_media.c b/lib/libifconfig/libifconfig_media.c index f7302d8a9b24..d7ef507604be 100644 --- a/lib/libifconfig/libifconfig_media.c +++ b/lib/libifconfig/libifconfig_media.c @@ -1,394 +1,404 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libifconfig.h" #include "libifconfig_internal.h" 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 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; static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; static 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[] = { { { { &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 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); } const char * ifconfig_media_get_type(int ifmw) { struct ifmedia_description *desc; /*int seen_option = 0, i;*/ /* Find the top-level interface type. */ desc = get_toptype_desc(ifmw); if (desc->ifmt_string == NULL) { return (""); } else { return (desc->ifmt_string); } } const char * ifconfig_media_get_subtype(int ifmw) { struct ifmedia_description *desc; struct ifmedia_type_to_subtype *ttos; ttos = get_toptype_ttos(ifmw); desc = get_subtype_desc(ifmw, ttos); return (desc->ifmt_string); } /*************************************************************************** * Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c ***************************************************************************/ /* Internal structure used for allocations and frees */ struct _ifconfig_media_status { struct ifmediareq ifmr; int medialist[0]; }; int ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, struct ifmediareq **ifmr) { struct _ifconfig_media_status *ms, *ms2; unsigned long cmd = SIOCGIFXMEDIA; *ifmr = NULL; ms = calloc(1, sizeof(*ms)); if (ms == NULL) { h->error.errtype = OTHER; h->error.errcode = ENOMEM; return (-1); } (void)memset(ms, 0, sizeof(*ms)); (void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name)); /* * Check if interface supports extended media types. */ if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { cmd = SIOCGIFMEDIA; if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { /* Interface doesn't support SIOC{G,S}IFMEDIA. */ h->error.errtype = OK; free(ms); return (-1); } } if (ms->ifmr.ifm_count == 0) { *ifmr = &ms->ifmr; return (0); /* Interface has no media types ?*/ } ms2 = realloc(ms, sizeof(*ms) + sizeof(int) * ms->ifmr.ifm_count); if (ms2 == NULL) { h->error.errtype = OTHER; h->error.errcode = ENOMEM; free(ms); return (-1); } ms2->ifmr.ifm_ulist = &ms2->medialist[0]; if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms2->ifmr) < 0) { free(ms2); return (-1); } *ifmr = &ms2->ifmr; return (0); } const char * ifconfig_media_get_status(const struct ifmediareq *ifmr) { switch (IFM_TYPE(ifmr->ifm_active)) { case IFM_ETHER: case IFM_ATM: if (ifmr->ifm_status & IFM_ACTIVE) { return ("active"); } else { return ("no carrier"); } break; case IFM_IEEE80211: if (ifmr->ifm_status & IFM_ACTIVE) { /* NB: only sta mode associates */ if (IFM_OPMODE(ifmr->ifm_active) == IFM_IEEE80211_STA) { return ("associated"); } else { return ("running"); } } else { return ("no carrier"); } break; default: 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 +ifconfig_media_get_downreason(ifconfig_handle_t *h, const char *name, + struct ifdownreason *ifdr) +{ + + (void)memset(ifdr, 0, sizeof(*ifdr)); + (void)strlcpy(ifdr->ifdr_name, name, sizeof(ifdr->ifdr_name)); + return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDOWNREASON, ifdr)); +}