Home | History | Annotate | Line # | Download | only in ifconfig
      1   1.1   dyoung #include <sys/cdefs.h>
      2   1.1   dyoung #ifndef lint
      3  1.14   andvar __RCSID("$NetBSD: media.c,v 1.14 2022/04/04 19:33:44 andvar Exp $");
      4   1.1   dyoung #endif /* not lint */
      5   1.1   dyoung 
      6   1.1   dyoung #include <assert.h>
      7   1.1   dyoung #include <err.h>
      8   1.1   dyoung #include <errno.h>
      9   1.1   dyoung #include <stdio.h>
     10   1.1   dyoung #include <stdlib.h>
     11   1.1   dyoung #include <string.h>
     12   1.1   dyoung #include <util.h>
     13   1.1   dyoung 
     14   1.1   dyoung #include <sys/ioctl.h>
     15   1.1   dyoung 
     16   1.1   dyoung #include <net/if.h>
     17   1.1   dyoung #include <net/if_dl.h>
     18   1.1   dyoung #include <net/if_media.h>
     19  1.10      roy #include <net/if_types.h>
     20   1.1   dyoung 
     21   1.1   dyoung #include <prop/proplib.h>
     22   1.1   dyoung 
     23   1.1   dyoung #include "env.h"
     24   1.1   dyoung #include "extern.h"
     25   1.1   dyoung #include "media.h"
     26   1.1   dyoung #include "parse.h"
     27   1.1   dyoung #include "util.h"
     28   1.5    pooka #include "prog_ops.h"
     29   1.1   dyoung 
     30   1.1   dyoung static void init_current_media(prop_dictionary_t, prop_dictionary_t);
     31   1.1   dyoung static void media_constructor(void) __attribute__((constructor));
     32   1.1   dyoung static int setmedia(prop_dictionary_t, prop_dictionary_t);
     33   1.1   dyoung static int setmediainst(prop_dictionary_t, prop_dictionary_t);
     34   1.1   dyoung static int setmediamode(prop_dictionary_t, prop_dictionary_t);
     35   1.1   dyoung static int setmediaopt(prop_dictionary_t, prop_dictionary_t);
     36   1.1   dyoung static int unsetmediaopt(prop_dictionary_t, prop_dictionary_t);
     37   1.1   dyoung 
     38   1.1   dyoung /*
     39   1.1   dyoung  * Media stuff.  Whenever a media command is first performed, the
     40   1.1   dyoung  * currently select media is grabbed for this interface.  If `media'
     41  1.14   andvar  * is given, the current media word is modified.  `mediaopt' commands
     42   1.1   dyoung  * only modify the set and clear words.  They then operate on the
     43   1.1   dyoung  * current media word later.
     44   1.1   dyoung  */
     45   1.1   dyoung static int	media_current;
     46   1.1   dyoung static int	mediaopt_set;
     47   1.1   dyoung static int	mediaopt_clear;
     48   1.1   dyoung 
     49   1.2   dyoung static struct usage_func usage;
     50   1.2   dyoung 
     51   1.1   dyoung static const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
     52   1.1   dyoung 
     53   1.1   dyoung static const struct ifmedia_status_description ifm_status_descriptions[] =
     54   1.1   dyoung     IFM_STATUS_DESCRIPTIONS;
     55   1.1   dyoung 
     56  1.10      roy const struct if_status_description if_status_descriptions[] =
     57  1.10      roy 	LINK_STATE_DESCRIPTIONS;
     58  1.10      roy 
     59   1.4   dyoung static struct pstr mediamode = PSTR_INITIALIZER1(&mediamode, "mediamode",
     60   1.4   dyoung     setmediamode, "mediamode", false, &command_root.pb_parser);
     61   1.1   dyoung 
     62   1.1   dyoung static struct pinteger mediainst = PINTEGER_INITIALIZER1(&mediainst,
     63   1.1   dyoung     "mediainst", 0, IFM_INST_MAX, 10, setmediainst, "mediainst",
     64   1.1   dyoung     &command_root.pb_parser);
     65   1.1   dyoung 
     66   1.4   dyoung static struct pstr unmediaopt = PSTR_INITIALIZER1(&unmediaopt, "-mediaopt",
     67   1.4   dyoung     unsetmediaopt, "unmediaopt", false, &command_root.pb_parser);
     68   1.1   dyoung 
     69   1.4   dyoung static struct pstr mediaopt = PSTR_INITIALIZER1(&mediaopt, "mediaopt",
     70   1.4   dyoung     setmediaopt, "mediaopt", false, &command_root.pb_parser);
     71   1.1   dyoung 
     72   1.4   dyoung static struct pstr media = PSTR_INITIALIZER1(&media, "media", setmedia, "media",
     73   1.4   dyoung     false, &command_root.pb_parser);
     74   1.1   dyoung 
     75   1.1   dyoung static const struct kwinst mediakw[] = {
     76   1.1   dyoung 	  {.k_word = "instance", .k_key = "anymedia", .k_type = KW_T_BOOL,
     77   1.1   dyoung 	   .k_bool = true, .k_act = "media", .k_deact = "mediainst",
     78   1.1   dyoung 	   .k_nextparser = &mediainst.pi_parser}
     79   1.1   dyoung 	, {.k_word = "inst", .k_key = "anymedia", .k_type = KW_T_BOOL,
     80   1.1   dyoung 	   .k_bool = true, .k_act = "media", .k_deact = "mediainst",
     81   1.1   dyoung 	   .k_nextparser = &mediainst.pi_parser}
     82   1.1   dyoung 	, {.k_word = "media", .k_key = "anymedia", .k_type = KW_T_BOOL,
     83   1.1   dyoung 	   .k_bool = true, .k_deact = "media", .k_altdeact = "anymedia",
     84   1.1   dyoung 	   .k_nextparser = &media.ps_parser}
     85   1.1   dyoung 	, {.k_word = "mediaopt", .k_key = "anymedia", .k_type = KW_T_BOOL,
     86   1.1   dyoung 	   .k_bool = true, .k_deact = "mediaopt", .k_altdeact = "instance",
     87   1.1   dyoung 	   .k_nextparser = &mediaopt.ps_parser}
     88   1.1   dyoung 	, {.k_word = "-mediaopt", .k_key = "anymedia", .k_type = KW_T_BOOL,
     89   1.1   dyoung 	   .k_bool = true, .k_deact = "unmediaopt", .k_altdeact = "media",
     90   1.1   dyoung 	   .k_nextparser = &unmediaopt.ps_parser}
     91   1.1   dyoung 	, {.k_word = "mode", .k_key = "anymedia", .k_type = KW_T_BOOL,
     92   1.1   dyoung 	   .k_bool = true, .k_deact = "mode",
     93   1.1   dyoung 	   .k_nextparser = &mediamode.ps_parser}
     94   1.1   dyoung };
     95   1.1   dyoung 
     96   1.1   dyoung struct pkw kwmedia = PKW_INITIALIZER(&kwmedia, "media keywords", NULL, NULL,
     97   1.1   dyoung     mediakw, __arraycount(mediakw), NULL);
     98   1.1   dyoung 
     99   1.6    joerg __dead static void
    100   1.1   dyoung media_error(int type, const char *val, const char *opt)
    101   1.1   dyoung {
    102   1.1   dyoung 	errx(EXIT_FAILURE, "unknown %s media %s: %s",
    103   1.1   dyoung 		get_media_type_string(type), opt, val);
    104   1.1   dyoung }
    105   1.1   dyoung 
    106   1.1   dyoung void
    107   1.1   dyoung init_current_media(prop_dictionary_t env, prop_dictionary_t oenv)
    108   1.1   dyoung {
    109   1.1   dyoung 	const char *ifname;
    110   1.1   dyoung 	struct ifmediareq ifmr;
    111   1.1   dyoung 
    112   1.1   dyoung 	if ((ifname = getifname(env)) == NULL)
    113   1.1   dyoung 		err(EXIT_FAILURE, "getifname");
    114   1.1   dyoung 
    115   1.1   dyoung 	/*
    116   1.1   dyoung 	 * If we have not yet done so, grab the currently-selected
    117   1.1   dyoung 	 * media.
    118   1.1   dyoung 	 */
    119   1.1   dyoung 
    120   1.1   dyoung 	if (prop_dictionary_get(env, "initmedia") == NULL) {
    121   1.1   dyoung 		memset(&ifmr, 0, sizeof(ifmr));
    122   1.1   dyoung 
    123   1.1   dyoung 		if (direct_ioctl(env, SIOCGIFMEDIA, &ifmr) == -1) {
    124   1.1   dyoung 			/*
    125   1.1   dyoung 			 * If we get E2BIG, the kernel is telling us
    126   1.1   dyoung 			 * that there are more, so we can ignore it.
    127   1.1   dyoung 			 */
    128   1.1   dyoung 			if (errno != E2BIG)
    129   1.1   dyoung 				err(EXIT_FAILURE, "SIOCGIFMEDIA");
    130   1.1   dyoung 		}
    131   1.1   dyoung 
    132   1.1   dyoung 		if (!prop_dictionary_set_bool(oenv, "initmedia", true)) {
    133   1.1   dyoung 			err(EXIT_FAILURE, "%s: prop_dictionary_set_bool",
    134   1.1   dyoung 			    __func__);
    135   1.1   dyoung 		}
    136   1.1   dyoung 		media_current = ifmr.ifm_current;
    137   1.1   dyoung 	}
    138   1.1   dyoung 
    139   1.1   dyoung 	/* Sanity. */
    140   1.1   dyoung 	if (IFM_TYPE(media_current) == 0)
    141   1.1   dyoung 		errx(EXIT_FAILURE, "%s: no link type?", ifname);
    142   1.1   dyoung }
    143   1.1   dyoung 
    144   1.1   dyoung void
    145   1.1   dyoung process_media_commands(prop_dictionary_t env)
    146   1.1   dyoung {
    147   1.1   dyoung 	struct ifreq ifr;
    148   1.1   dyoung 
    149   1.1   dyoung 	if (prop_dictionary_get(env, "media") == NULL &&
    150   1.1   dyoung 	    prop_dictionary_get(env, "mediaopt") == NULL &&
    151   1.1   dyoung 	    prop_dictionary_get(env, "unmediaopt") == NULL &&
    152   1.1   dyoung 	    prop_dictionary_get(env, "mediamode") == NULL) {
    153   1.1   dyoung 		/* Nothing to do. */
    154   1.1   dyoung 		return;
    155   1.1   dyoung 	}
    156   1.1   dyoung 
    157   1.1   dyoung 	/*
    158   1.1   dyoung 	 * Media already set up, and commands sanity-checked.  Set/clear
    159   1.1   dyoung 	 * any options, and we're ready to go.
    160   1.1   dyoung 	 */
    161   1.1   dyoung 	media_current |= mediaopt_set;
    162   1.1   dyoung 	media_current &= ~mediaopt_clear;
    163   1.1   dyoung 
    164   1.1   dyoung 	memset(&ifr, 0, sizeof(ifr));
    165   1.1   dyoung 	ifr.ifr_media = media_current;
    166   1.1   dyoung 
    167   1.1   dyoung 	if (direct_ioctl(env, SIOCSIFMEDIA, &ifr) == -1)
    168   1.1   dyoung 		err(EXIT_FAILURE, "SIOCSIFMEDIA");
    169   1.1   dyoung }
    170   1.1   dyoung 
    171   1.1   dyoung static int
    172   1.3   dyoung setmedia(prop_dictionary_t env, prop_dictionary_t oenv)
    173   1.1   dyoung {
    174   1.1   dyoung 	int type, subtype, inst;
    175   1.1   dyoung 	prop_data_t data;
    176   1.1   dyoung 	char *val;
    177   1.1   dyoung 
    178   1.3   dyoung 	init_current_media(env, oenv);
    179   1.1   dyoung 
    180   1.1   dyoung 	data = (prop_data_t)prop_dictionary_get(env, "media");
    181   1.1   dyoung 	assert(data != NULL);
    182   1.1   dyoung 
    183   1.1   dyoung 	/* Only one media command may be given. */
    184   1.1   dyoung 	/* Must not come after mode commands */
    185   1.1   dyoung 	/* Must not come after mediaopt commands */
    186   1.1   dyoung 
    187   1.1   dyoung 	/*
    188   1.1   dyoung 	 * No need to check if `instance' has been issued; setmediainst()
    189   1.1   dyoung 	 * craps out if `media' has not been specified.
    190   1.1   dyoung 	 */
    191   1.1   dyoung 
    192   1.1   dyoung 	type = IFM_TYPE(media_current);
    193   1.1   dyoung 	inst = IFM_INST(media_current);
    194   1.1   dyoung 
    195   1.9  thorpej 	val = strndup(prop_data_value(data), prop_data_size(data));
    196   1.1   dyoung 	if (val == NULL)
    197   1.1   dyoung 		return -1;
    198   1.1   dyoung 
    199   1.1   dyoung 	/* Look up the subtype. */
    200   1.1   dyoung 	subtype = get_media_subtype(type, val);
    201   1.1   dyoung 	if (subtype == -1)
    202   1.1   dyoung 		media_error(type, val, "subtype");
    203   1.1   dyoung 
    204   1.1   dyoung 	/* Build the new current media word. */
    205   1.1   dyoung 	media_current = IFM_MAKEWORD(type, subtype, 0, inst);
    206   1.1   dyoung 
    207   1.1   dyoung 	/* Media will be set after other processing is complete. */
    208   1.1   dyoung 	return 0;
    209   1.1   dyoung }
    210   1.1   dyoung 
    211   1.1   dyoung static int
    212   1.3   dyoung setmediaopt(prop_dictionary_t env, prop_dictionary_t oenv)
    213   1.1   dyoung {
    214   1.1   dyoung 	char *invalid;
    215   1.1   dyoung 	prop_data_t data;
    216   1.1   dyoung 	char *val;
    217   1.1   dyoung 
    218   1.3   dyoung 	init_current_media(env, oenv);
    219   1.1   dyoung 
    220   1.1   dyoung 	data = (prop_data_t)prop_dictionary_get(env, "mediaopt");
    221   1.1   dyoung 	assert(data != NULL);
    222   1.1   dyoung 
    223   1.1   dyoung 	/* Can only issue `mediaopt' once. */
    224   1.1   dyoung 	/* Can't issue `mediaopt' if `instance' has already been issued. */
    225   1.1   dyoung 
    226   1.9  thorpej 	val = strndup(prop_data_value(data), prop_data_size(data));
    227   1.1   dyoung 	if (val == NULL)
    228   1.1   dyoung 		return -1;
    229   1.1   dyoung 
    230   1.1   dyoung 	mediaopt_set = get_media_options(media_current, val, &invalid);
    231   1.1   dyoung 	free(val);
    232   1.1   dyoung 	if (mediaopt_set == -1)
    233   1.1   dyoung 		media_error(media_current, invalid, "option");
    234   1.1   dyoung 
    235   1.1   dyoung 	/* Media will be set after other processing is complete. */
    236   1.1   dyoung 	return 0;
    237   1.1   dyoung }
    238   1.1   dyoung 
    239   1.1   dyoung static int
    240   1.3   dyoung unsetmediaopt(prop_dictionary_t env, prop_dictionary_t oenv)
    241   1.1   dyoung {
    242   1.1   dyoung 	char *invalid, *val;
    243   1.1   dyoung 	prop_data_t data;
    244   1.1   dyoung 
    245   1.3   dyoung 	init_current_media(env, oenv);
    246   1.1   dyoung 
    247   1.1   dyoung 	data = (prop_data_t)prop_dictionary_get(env, "unmediaopt");
    248   1.1   dyoung 	if (data == NULL) {
    249   1.1   dyoung 		errno = ENOENT;
    250   1.1   dyoung 		return -1;
    251   1.1   dyoung 	}
    252   1.1   dyoung 
    253   1.9  thorpej 	val = strndup(prop_data_value(data), prop_data_size(data));
    254   1.1   dyoung 	if (val == NULL)
    255   1.1   dyoung 		return -1;
    256   1.1   dyoung 
    257   1.1   dyoung 	/*
    258   1.1   dyoung 	 * No need to check for A_MEDIAINST, since the test for A_MEDIA
    259   1.1   dyoung 	 * implicitly checks for A_MEDIAINST.
    260   1.1   dyoung 	 */
    261   1.1   dyoung 
    262   1.1   dyoung 	mediaopt_clear = get_media_options(media_current, val, &invalid);
    263   1.1   dyoung 	free(val);
    264   1.1   dyoung 	if (mediaopt_clear == -1)
    265   1.1   dyoung 		media_error(media_current, invalid, "option");
    266   1.1   dyoung 
    267   1.1   dyoung 	/* Media will be set after other processing is complete. */
    268   1.1   dyoung 	return 0;
    269   1.1   dyoung }
    270   1.1   dyoung 
    271   1.1   dyoung static int
    272   1.3   dyoung setmediainst(prop_dictionary_t env, prop_dictionary_t oenv)
    273   1.1   dyoung {
    274   1.1   dyoung 	int type, subtype, options;
    275   1.1   dyoung 	int64_t inst;
    276   1.1   dyoung 	bool rc;
    277   1.1   dyoung 
    278   1.3   dyoung 	init_current_media(env, oenv);
    279   1.1   dyoung 
    280   1.1   dyoung 	rc = prop_dictionary_get_int64(env, "mediainst", &inst);
    281   1.1   dyoung 	assert(rc);
    282   1.1   dyoung 
    283   1.1   dyoung 	/* Can only issue `instance' once. */
    284   1.1   dyoung 	/* Must have already specified `media' */
    285   1.1   dyoung 
    286   1.1   dyoung 	type = IFM_TYPE(media_current);
    287   1.1   dyoung 	subtype = IFM_SUBTYPE(media_current);
    288   1.1   dyoung 	options = IFM_OPTIONS(media_current);
    289   1.1   dyoung 
    290   1.1   dyoung 	media_current = IFM_MAKEWORD(type, subtype, options, inst);
    291   1.1   dyoung 
    292   1.1   dyoung 	/* Media will be set after other processing is complete. */
    293   1.1   dyoung 	return 0;
    294   1.1   dyoung }
    295   1.1   dyoung 
    296   1.1   dyoung static int
    297   1.3   dyoung setmediamode(prop_dictionary_t env, prop_dictionary_t oenv)
    298   1.1   dyoung {
    299   1.1   dyoung 	int type, subtype, options, inst, mode;
    300   1.1   dyoung 	prop_data_t data;
    301   1.1   dyoung 	char *val;
    302   1.1   dyoung 
    303   1.3   dyoung 	init_current_media(env, oenv);
    304   1.1   dyoung 
    305   1.1   dyoung 	data = (prop_data_t)prop_dictionary_get(env, "mediamode");
    306   1.1   dyoung 	assert(data != NULL);
    307   1.1   dyoung 
    308   1.1   dyoung 	type = IFM_TYPE(media_current);
    309   1.1   dyoung 	subtype = IFM_SUBTYPE(media_current);
    310   1.1   dyoung 	options = IFM_OPTIONS(media_current);
    311   1.1   dyoung 	inst = IFM_INST(media_current);
    312   1.1   dyoung 
    313   1.9  thorpej 	val = strndup(prop_data_value(data), prop_data_size(data));
    314   1.1   dyoung 	if (val == NULL)
    315   1.1   dyoung 		return -1;
    316   1.1   dyoung 
    317   1.1   dyoung 	mode = get_media_mode(type, val);
    318   1.1   dyoung 	if (mode == -1)
    319   1.1   dyoung 		media_error(type, val, "mode");
    320   1.1   dyoung 
    321   1.1   dyoung 	free(val);
    322   1.1   dyoung 
    323   1.1   dyoung 	media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode;
    324   1.1   dyoung 
    325   1.1   dyoung 	/* Media will be set after other processing is complete. */
    326   1.1   dyoung 	return 0;
    327   1.1   dyoung }
    328   1.1   dyoung 
    329   1.1   dyoung void
    330   1.1   dyoung print_media_word(int ifmw, const char *opt_sep)
    331   1.1   dyoung {
    332   1.1   dyoung 	const char *str;
    333   1.1   dyoung 
    334   1.1   dyoung 	printf("%s", get_media_subtype_string(ifmw));
    335   1.1   dyoung 
    336   1.1   dyoung 	/* Find mode. */
    337   1.1   dyoung 	if (IFM_MODE(ifmw) != 0) {
    338   1.1   dyoung 		str = get_media_mode_string(ifmw);
    339   1.1   dyoung 		if (str != NULL)
    340   1.1   dyoung 			printf(" mode %s", str);
    341   1.1   dyoung 	}
    342   1.1   dyoung 
    343   1.1   dyoung 	/* Find options. */
    344   1.1   dyoung 	for (; (str = get_media_option_string(&ifmw)) != NULL; opt_sep = ",")
    345   1.1   dyoung 		printf("%s%s", opt_sep, str);
    346   1.1   dyoung 
    347   1.1   dyoung 	if (IFM_INST(ifmw) != 0)
    348   1.1   dyoung 		printf(" instance %d", IFM_INST(ifmw));
    349   1.1   dyoung }
    350   1.1   dyoung 
    351  1.10      roy static void
    352  1.10      roy print_link_status(int media_type, int link_state)
    353  1.10      roy {
    354  1.10      roy 	const struct if_status_description *p;
    355  1.10      roy 
    356  1.10      roy 	printf("\tstatus: ");
    357  1.10      roy 	for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
    358  1.10      roy 		if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) {
    359  1.10      roy 			printf("%s\n", p->ifs_string);
    360  1.10      roy 			return;
    361  1.10      roy 		}
    362  1.10      roy 	}
    363  1.10      roy 	printf("[#%d]\n", link_state);
    364  1.10      roy }
    365  1.10      roy 
    366  1.10      roy static void
    367  1.10      roy print_media_status(int media_type, int media_status)
    368  1.10      roy {
    369  1.10      roy 	const struct ifmedia_status_description *ifms;
    370  1.10      roy 	int bitno, found = 0;
    371  1.10      roy 
    372  1.10      roy 	printf("\tstatus: ");
    373  1.10      roy 	for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
    374  1.10      roy 		for (ifms = ifm_status_descriptions;
    375  1.10      roy 		     ifms->ifms_valid != 0; ifms++) {
    376  1.10      roy 			if (ifms->ifms_type != media_type ||
    377  1.10      roy 			    ifms->ifms_valid != ifm_status_valid_list[bitno])
    378  1.10      roy 				continue;
    379  1.10      roy 			printf("%s%s", found ? ", " : "",
    380  1.10      roy 			    IFM_STATUS_DESC(ifms, media_status));
    381  1.10      roy 			found = 1;
    382  1.10      roy 
    383  1.10      roy 			/*
    384  1.10      roy 			 * For each valid indicator bit, there's
    385  1.10      roy 			 * only one entry for each media type, so
    386  1.10      roy 			 * terminate the inner loop now.
    387  1.10      roy 			 */
    388  1.10      roy 			break;
    389  1.10      roy 		}
    390  1.10      roy 	}
    391  1.10      roy 
    392  1.10      roy 	if (found == 0)
    393  1.10      roy 		printf("unknown");
    394  1.10      roy 	printf("\n");
    395  1.10      roy }
    396  1.10      roy 
    397   1.1   dyoung void
    398  1.13      roy media_status(prop_dictionary_t env, prop_dictionary_t oenv)
    399   1.1   dyoung {
    400   1.1   dyoung 	struct ifmediareq ifmr;
    401   1.1   dyoung 	int af, i, s;
    402   1.1   dyoung 	int *media_list;
    403   1.1   dyoung 	const char *ifname;
    404   1.1   dyoung 
    405   1.1   dyoung 	if ((ifname = getifname(env)) == NULL)
    406   1.1   dyoung 		err(EXIT_FAILURE, "getifname");
    407   1.1   dyoung 	if ((af = getaf(env)) == -1)
    408   1.1   dyoung 		af = AF_UNSPEC;
    409   1.1   dyoung 
    410   1.1   dyoung 	/* get out early if the family is unsupported by the kernel */
    411   1.1   dyoung 	if ((s = getsock(af)) == -1)
    412   1.1   dyoung 		err(EXIT_FAILURE, "%s: getsock", __func__);
    413   1.1   dyoung 
    414   1.1   dyoung 	memset(&ifmr, 0, sizeof(ifmr));
    415   1.1   dyoung 	estrlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
    416   1.1   dyoung 
    417   1.5    pooka 	if (prog_ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
    418  1.13      roy 		struct ifdatareq ifdr = { .ifdr_data.ifi_link_state = 0 };
    419  1.13      roy 		struct if_data *ifi = &ifdr.ifdr_data;
    420  1.13      roy 
    421   1.1   dyoung 		/*
    422   1.1   dyoung 		 * Interface doesn't support SIOC{G,S}IFMEDIA.
    423   1.1   dyoung 		 */
    424  1.13      roy 		if (direct_ioctl(env, SIOCGIFDATA, &ifdr) == -1)
    425  1.13      roy 			err(EXIT_FAILURE, "%s: SIOCGIFDATA", __func__);
    426  1.13      roy 
    427  1.13      roy 		if (ifi->ifi_link_state != LINK_STATE_UNKNOWN)
    428  1.13      roy 			print_link_status(ifi->ifi_type, ifi->ifi_link_state);
    429   1.1   dyoung 		return;
    430   1.1   dyoung 	}
    431   1.1   dyoung 
    432  1.12      roy 	if (ifmr.ifm_count == 0) {
    433  1.11      roy 		warnx("%s: no media types?", ifname);
    434  1.12      roy 		return;
    435  1.12      roy 	}
    436  1.11      roy 
    437  1.11      roy 	media_list = calloc(ifmr.ifm_count, sizeof(int));
    438  1.11      roy 	if (media_list == NULL)
    439  1.11      roy 		err(EXIT_FAILURE, "malloc");
    440  1.11      roy 	ifmr.ifm_ulist = media_list;
    441  1.11      roy 
    442  1.11      roy 	if (prog_ioctl(s, SIOCGIFMEDIA, &ifmr) == -1)
    443  1.11      roy 		err(EXIT_FAILURE, "SIOCGIFMEDIA");
    444  1.11      roy 
    445  1.11      roy 	printf("\tmedia: %s ", get_media_type_string(ifmr.ifm_current));
    446  1.11      roy 	print_media_word(ifmr.ifm_current, " ");
    447  1.11      roy 	if (ifmr.ifm_active != ifmr.ifm_current) {
    448  1.11      roy 		printf(" (");
    449  1.11      roy 		print_media_word(ifmr.ifm_active, " ");
    450  1.11      roy 		printf(")");
    451  1.11      roy 	}
    452  1.11      roy 	printf("\n");
    453   1.1   dyoung 
    454  1.10      roy 	if (ifmr.ifm_status & IFM_STATUS_VALID)
    455  1.10      roy 		print_media_status(IFM_TYPE(ifmr.ifm_current), ifmr.ifm_status);
    456   1.1   dyoung 
    457   1.1   dyoung 	if (get_flag('m')) {
    458   1.1   dyoung 		int type, printed_type;
    459   1.1   dyoung 
    460   1.1   dyoung 		for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) {
    461   1.1   dyoung 			for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) {
    462   1.1   dyoung 				if (IFM_TYPE(media_list[i]) != type)
    463   1.1   dyoung 					continue;
    464   1.1   dyoung 				if (printed_type == 0) {
    465   1.1   dyoung 					printf("\tsupported %s media:\n",
    466   1.1   dyoung 					    get_media_type_string(type));
    467   1.1   dyoung 					printed_type = 1;
    468   1.1   dyoung 				}
    469   1.1   dyoung 				printf("\t\tmedia ");
    470   1.1   dyoung 				print_media_word(media_list[i], " mediaopt ");
    471   1.1   dyoung 				printf("\n");
    472   1.1   dyoung 			}
    473   1.1   dyoung 		}
    474   1.1   dyoung 	}
    475   1.1   dyoung 
    476   1.1   dyoung 	free(media_list);
    477   1.1   dyoung }
    478   1.1   dyoung 
    479   1.1   dyoung static void
    480   1.2   dyoung media_usage(prop_dictionary_t env)
    481   1.2   dyoung {
    482   1.2   dyoung 	fprintf(stderr,
    483   1.2   dyoung 	    "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] "
    484   1.2   dyoung 	    "[ instance minst ]\n");
    485   1.2   dyoung }
    486   1.2   dyoung 
    487   1.2   dyoung static void
    488   1.1   dyoung media_constructor(void)
    489   1.1   dyoung {
    490   1.1   dyoung 	if (register_flag('m') != 0)
    491   1.1   dyoung 		err(EXIT_FAILURE, __func__);
    492   1.2   dyoung 	usage_func_init(&usage, media_usage);
    493   1.2   dyoung 	register_usage(&usage);
    494   1.1   dyoung }
    495