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