]> git.saurik.com Git - apple/network_cmds.git/blame - ifconfig.tproj/ifmedia.c
network_cmds-176.2.1.tar.gz
[apple/network_cmds.git] / ifconfig.tproj / ifmedia.c
CommitLineData
b7080c8e
A
1/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
2/* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.6 1999/08/28 00:13:08 peter Exp $ */
3
4/*
5 * Copyright (c) 1997 Jason R. Thorpe.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the NetBSD Project
19 * by Jason R. Thorpe.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36/*
37 * Copyright (c) 1983, 1993
38 * The Regents of the University of California. All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 */
68
69#include <sys/param.h>
70#include <sys/ioctl.h>
71#include <sys/socket.h>
72#include <sys/sysctl.h>
73#include <sys/time.h>
74
75#include <net/if.h>
76#include <net/if_dl.h>
77#include <net/if_types.h>
78#include <net/if_media.h>
79#include <net/route.h>
80
81#include <ctype.h>
82#include <err.h>
83#include <errno.h>
84#include <fcntl.h>
85#include <stdio.h>
86#include <stdlib.h>
87#include <string.h>
88#include <unistd.h>
89
90#include "ifconfig.h"
91
92static void domediaopt __P((const char *, int, int));
93static int get_media_subtype __P((int, const char *));
94static int get_media_options __P((int, const char *));
95static int lookup_media_word __P((struct ifmedia_description *, const char *));
96static void print_media_word __P((int));
97
98void
99media_status(s, info)
100 int s;
101 struct rt_addrinfo *info;
102{
103 struct ifmediareq ifmr;
104 int *media_list, i;
105
106 (void) memset(&ifmr, 0, sizeof(ifmr));
107 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
108
109 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
110 /*
111 * Interface doesn't support SIOC{G,S}IFMEDIA.
112 */
113 return;
114 }
115
116 if (ifmr.ifm_count == 0) {
117 //warnx("%s: no media types?", name);
118 return;
119 }
120
121 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
122 if (media_list == NULL)
123 err(1, "malloc");
124 ifmr.ifm_ulist = media_list;
125
126 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
127 err(1, "SIOCGIFMEDIA");
128
129 printf("\tmedia: ");
130 print_media_word(ifmr.ifm_current);
131 if (ifmr.ifm_active != ifmr.ifm_current) {
132 putchar(' ');
133 putchar('(');
134 print_media_word(ifmr.ifm_active);
135 putchar(')');
136 }
137
138 if (ifmr.ifm_status & IFM_AVALID) {
139 printf(" status: ");
140#if 0
141 switch (IFM_TYPE(ifmr.ifm_active)) {
142 case IFM_ETHER:
143 if (ifmr.ifm_status & IFM_ACTIVE)
144 printf("active");
145 else
146 printf("no carrier");
147 break;
148
149 case IFM_FDDI:
150 case IFM_TOKEN:
151 if (ifmr.ifm_status & IFM_ACTIVE)
152 printf("inserted");
153 else
154 printf("no ring");
155 break;
156 }
157#endif 0
158 if (ifmr.ifm_status & IFM_ACTIVE)
159 printf("active");
160 else
161 printf("inactive");
162 }
163
164 putchar('\n');
165
166 if (ifmr.ifm_count > 0) {
167 printf("\tsupported media:");
168 for (i = 0; i < ifmr.ifm_count; i++) {
169 putchar(' ');
170 print_media_word(media_list[i]);
171 }
172 putchar('\n');
173 }
174
175 free(media_list);
176}
177
178void
179setmedia(val, d, s, afp)
180 const char *val;
181 int d;
182 int s;
183 const struct afswtch *afp;
184{
185 struct ifmediareq ifmr;
186 int first_type, subtype;
187
188 (void) memset(&ifmr, 0, sizeof(ifmr));
189 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
190
191 ifmr.ifm_count = 1;
192 ifmr.ifm_ulist = &first_type;
193 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
194 /*
195 * If we get E2BIG, the kernel is telling us
196 * that there are more, so we can ignore it.
197 */
198 if (errno != E2BIG)
199 err(1, "SIOCGIFMEDIA");
200 }
201
202 if (ifmr.ifm_count == 0)
203 errx(1, "%s: no media types?", name);
204
205 /*
206 * We are primarily concerned with the top-level type.
207 * However, "current" may be only IFM_NONE, so we just look
208 * for the top-level type in the first "supported type"
209 * entry.
210 *
211 * (I'm assuming that all supported media types for a given
212 * interface will be the same top-level type..)
213 */
214 subtype = get_media_subtype(IFM_TYPE(first_type), val);
215
216 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
217 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
218 IFM_TYPE(first_type) | subtype;
219
220 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
221 err(1, "SIOCSIFMEDIA");
222}
223
224void
225setmediaopt(val, d, s, afp)
226 const char *val;
227 int d;
228 int s;
229 const struct afswtch *afp;
230{
231
232 domediaopt(val, 0, s);
233}
234
235void
236unsetmediaopt(val, d, s, afp)
237 const char *val;
238 int d;
239 int s;
240 const struct afswtch *afp;
241{
242
243 domediaopt(val, 1, s);
244}
245
246static void
247domediaopt(val, clear, s)
248 const char *val;
249 int clear;
250 int s;
251{
252 struct ifmediareq ifmr;
253 int *mwords, options;
254
255 (void) memset(&ifmr, 0, sizeof(ifmr));
256 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
257
258 /*
259 * We must go through the motions of reading all
260 * supported media because we need to know both
261 * the current media type and the top-level type.
262 */
263
264 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
265 err(1, "SIOCGIFMEDIA");
266
267 if (ifmr.ifm_count == 0)
268 errx(1, "%s: no media types?", name);
269
270 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
271 if (mwords == NULL)
272 err(1, "malloc");
273
274 ifmr.ifm_ulist = mwords;
275 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
276 err(1, "SIOCGIFMEDIA");
277
278 options = get_media_options(IFM_TYPE(mwords[0]), val);
279
280 free(mwords);
281
282 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
283 ifr.ifr_media = ifmr.ifm_current;
284 if (clear)
285 ifr.ifr_media &= ~options;
286 else
287 ifr.ifr_media |= options;
288
289 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
290 err(1, "SIOCSIFMEDIA");
291}
292
293/**********************************************************************
294 * A good chunk of this is duplicated from sys/net/ifmedia.c
295 **********************************************************************/
296
297static struct ifmedia_description ifm_type_descriptions[] =
298 IFM_TYPE_DESCRIPTIONS;
299
300static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
301 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
302
303static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
304 IFM_SUBTYPE_ETHERNET_ALIASES;
305
306static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
307 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
308
309static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
310 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
311
312static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
313 IFM_SUBTYPE_TOKENRING_ALIASES;
314
315static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
316 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
317
318static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
319 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
320
321static struct ifmedia_description ifm_subtype_fddi_aliases[] =
322 IFM_SUBTYPE_FDDI_ALIASES;
323
324static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
325 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
326
327static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
328 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
329
330static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
331 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
332
333static struct ifmedia_description ifm_subtype_shared_descriptions[] =
334 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
335
336static struct ifmedia_description ifm_subtype_shared_aliases[] =
337 IFM_SUBTYPE_SHARED_ALIASES;
338
339static struct ifmedia_description ifm_shared_option_descriptions[] =
340 IFM_SHARED_OPTION_DESCRIPTIONS;
341
342struct ifmedia_type_to_subtype {
343 struct {
344 struct ifmedia_description *desc;
345 int alias;
346 } subtypes[5];
347 struct {
348 struct ifmedia_description *desc;
349 int alias;
350 } options[3];
351};
352
353/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
354static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
355 {
356 {
357 { &ifm_subtype_shared_descriptions[0], 0 },
358 { &ifm_subtype_shared_aliases[0], 1 },
359 { &ifm_subtype_ethernet_descriptions[0], 0 },
360 { &ifm_subtype_ethernet_aliases[0], 1 },
361 { NULL, 0 },
362 },
363 {
364 { &ifm_shared_option_descriptions[0], 0 },
365 { &ifm_subtype_ethernet_option_descriptions[0], 1 },
366 { NULL, 0 },
367 },
368 },
369 {
370 {
371 { &ifm_subtype_shared_descriptions[0], 0 },
372 { &ifm_subtype_shared_aliases[0], 1 },
373 { &ifm_subtype_tokenring_descriptions[0], 0 },
374 { &ifm_subtype_tokenring_aliases[0], 1 },
375 { NULL, 0 },
376 },
377 {
378 { &ifm_shared_option_descriptions[0], 0 },
379 { &ifm_subtype_tokenring_option_descriptions[0], 1 },
380 { NULL, 0 },
381 },
382 },
383 {
384 {
385 { &ifm_subtype_shared_descriptions[0], 0 },
386 { &ifm_subtype_shared_aliases[0], 1 },
387 { &ifm_subtype_fddi_descriptions[0], 0 },
388 { &ifm_subtype_fddi_aliases[0], 1 },
389 { NULL, 0 },
390 },
391 {
392 { &ifm_shared_option_descriptions[0], 0 },
393 { &ifm_subtype_fddi_option_descriptions[0], 1 },
394 { NULL, 0 },
395 },
396 },
397 {
398 {
399 { &ifm_subtype_shared_descriptions[0], 0 },
400 { &ifm_subtype_shared_aliases[0], 1 },
401 { &ifm_subtype_ieee80211_descriptions[0], 0 },
402 { NULL, 0 },
403 },
404 {
405 { &ifm_shared_option_descriptions[0], 0 },
406 { &ifm_subtype_ieee80211_option_descriptions[0], 1 },
407 { NULL, 0 },
408 },
409 },
410};
411
412static int
413get_media_subtype(type, val)
414 int type;
415 const char *val;
416{
417 struct ifmedia_description *desc;
418 struct ifmedia_type_to_subtype *ttos;
419 int rval, i;
420
421 /* Find the top-level interface type. */
422 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
423 desc->ifmt_string != NULL; desc++, ttos++)
424 if (type == desc->ifmt_word)
425 break;
426 if (desc->ifmt_string == NULL)
427 errx(1, "unknown media type 0x%x", type);
428
429 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
430 rval = lookup_media_word(ttos->subtypes[i].desc, val);
431 if (rval != -1)
432 return (rval);
433 }
434 errx(1, "unknown media subtype: %s", val);
435 /* NOTREACHED */
436}
437
438static int
439get_media_options(type, val)
440 int type;
441 const char *val;
442{
443 struct ifmedia_description *desc;
444 struct ifmedia_type_to_subtype *ttos;
445 char *optlist, *optptr;
446 int option = 0, i, rval = 0;
447
448 /* We muck with the string, so copy it. */
449 optlist = strdup(val);
450 if (optlist == NULL)
451 err(1, "strdup");
452
453 /* Find the top-level interface type. */
454 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
455 desc->ifmt_string != NULL; desc++, ttos++)
456 if (type == desc->ifmt_word)
457 break;
458 if (desc->ifmt_string == NULL)
459 errx(1, "unknown media type 0x%x", type);
460
461 /*
462 * Look up the options in the user-provided comma-separated
463 * list.
464 */
465 optptr = optlist;
466 for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
467 for (i = 0; ttos->options[i].desc != NULL; i++) {
468 option = lookup_media_word(ttos->options[i].desc, optptr);
469 if (option != -1)
470 break;
471 }
472 if (option == 0)
473 errx(1, "unknown option: %s", optptr);
474 rval |= option;
475 }
476
477 free(optlist);
478 return (rval);
479}
480
481static int
482lookup_media_word(desc, val)
483 struct ifmedia_description *desc;
484 const char *val;
485{
486
487 for (; desc->ifmt_string != NULL; desc++)
488 if (strcasecmp(desc->ifmt_string, val) == 0)
489 return (desc->ifmt_word);
490
491 return (-1);
492}
493
494static void
495print_media_word(ifmw)
496 int ifmw;
497{
498 struct ifmedia_description *desc;
499 struct ifmedia_type_to_subtype *ttos;
500 int seen_option = 0, i;
501
502 /* Find the top-level interface type. */
503 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
504 desc->ifmt_string != NULL; desc++, ttos++)
505 if (IFM_TYPE(ifmw) == desc->ifmt_word)
506 break;
507 if (desc->ifmt_string == NULL) {
508 printf("<unknown type>");
509 return;
510 }
511
512 /*
513 * Don't print the top-level type; it's not like we can
514 * change it, or anything.
515 */
516
517 /* Find subtype. */
518 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
519 if (ttos->subtypes[i].alias)
520 continue;
521 for (desc = ttos->subtypes[i].desc;
522 desc->ifmt_string != NULL; desc++) {
523 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
524 goto got_subtype;
525 }
526 }
527
528 /* Falling to here means unknown subtype. */
529 printf("<unknown subtype>");
530 return;
531
532 got_subtype:
533 printf("%s", desc->ifmt_string);
534
535 /* Find options. */
536 for (i = 0; ttos->options[i].desc != NULL; i++) {
537 if (ttos->options[i].alias)
538 continue;
539 for (desc = ttos->options[i].desc;
540 desc->ifmt_string != NULL; desc++) {
541 if (ifmw & desc->ifmt_word) {
542 if (seen_option == 0)
543 printf(" <");
544 printf("%s%s", seen_option++ ? "," : "",
545 desc->ifmt_string);
546 }
547 }
548 }
549 printf("%s", seen_option ? ">" : "");
550}
551
552/**********************************************************************
553 * ...until here.
554 **********************************************************************/