Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/ifconfig/ifmedia.c
39475 views
1
/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-4-Clause
5
*
6
* Copyright (c) 1997 Jason R. Thorpe.
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
* 3. All advertising materials mentioning features or use of this software
18
* must display the following acknowledgement:
19
* This product includes software developed for the NetBSD Project
20
* by Jason R. Thorpe.
21
* 4. The name of the author may not be used to endorse or promote products
22
* derived from this software without specific prior written permission.
23
*
24
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
* SUCH DAMAGE.
35
*/
36
37
/*
38
* Copyright (c) 1983, 1993
39
* The Regents of the University of California. All rights reserved.
40
*
41
* Redistribution and use in source and binary forms, with or without
42
* modification, are permitted provided that the following conditions
43
* are met:
44
* 1. Redistributions of source code must retain the above copyright
45
* notice, this list of conditions and the following disclaimer.
46
* 2. Redistributions in binary form must reproduce the above copyright
47
* notice, this list of conditions and the following disclaimer in the
48
* documentation and/or other materials provided with the distribution.
49
* 4. Neither the name of the University nor the names of its contributors
50
* may be used to endorse or promote products derived from this software
51
* without specific prior written permission.
52
*
53
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63
* SUCH DAMAGE.
64
*/
65
66
#include <sys/param.h>
67
#include <sys/ioctl.h>
68
#include <sys/socket.h>
69
#include <sys/sysctl.h>
70
#include <sys/time.h>
71
72
#include <net/if.h>
73
#include <net/if_dl.h>
74
#include <net/if_types.h>
75
#include <net/if_media.h>
76
#include <net/route.h>
77
78
#include <ctype.h>
79
#include <err.h>
80
#include <errno.h>
81
#include <fcntl.h>
82
#include <stdbool.h>
83
#include <stdio.h>
84
#include <stdlib.h>
85
#include <string.h>
86
#include <unistd.h>
87
88
#include <libifconfig.h>
89
90
#include "ifconfig.h"
91
92
static void domediaopt(if_ctx *, const char *, bool);
93
static ifmedia_t get_media_subtype(ifmedia_t, const char *);
94
static ifmedia_t get_media_mode(ifmedia_t, const char *);
95
static ifmedia_t get_media_options(ifmedia_t, const char *);
96
static void print_media(ifmedia_t, bool);
97
static void print_media_ifconfig(ifmedia_t);
98
99
static void
100
media_status(if_ctx *ctx)
101
{
102
struct ifmediareq *ifmr;
103
104
if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
105
return;
106
107
if (ifmr->ifm_count == 0) {
108
warnx("%s: no media types?", ctx->ifname);
109
goto free;
110
}
111
112
printf("\tmedia: ");
113
print_media(ifmr->ifm_current, true);
114
if (ifmr->ifm_active != ifmr->ifm_current) {
115
putchar(' ');
116
putchar('(');
117
print_media(ifmr->ifm_active, false);
118
putchar(')');
119
}
120
121
putchar('\n');
122
123
if (ifmr->ifm_status & IFM_AVALID) {
124
struct ifdownreason ifdr;
125
const char *status;
126
127
status = ifconfig_media_get_status(ifmr);
128
printf("\tstatus: %s", status);
129
if (strcmp(status, "no carrier") == 0 &&
130
ifconfig_media_get_downreason(lifh, ctx->ifname, &ifdr) == 0) {
131
switch (ifdr.ifdr_reason) {
132
case IFDR_REASON_MSG:
133
printf(" (%s)", ifdr.ifdr_msg);
134
break;
135
case IFDR_REASON_VENDOR:
136
printf(" (vendor code %d)",
137
ifdr.ifdr_vendor);
138
break;
139
default:
140
break;
141
}
142
}
143
putchar('\n');
144
}
145
146
if (ctx->args->supmedia) {
147
printf("\tsupported media:\n");
148
for (int i = 0; i < ifmr->ifm_count; ++i) {
149
printf("\t\t");
150
print_media_ifconfig(ifmr->ifm_ulist[i]);
151
putchar('\n');
152
}
153
}
154
free:
155
free(ifmr);
156
}
157
158
struct ifmediareq *
159
ifmedia_getstate(if_ctx *ctx)
160
{
161
static struct ifmediareq *ifmr = NULL;
162
163
if (ifmr != NULL)
164
return (ifmr);
165
166
if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
167
errc(1, ifconfig_err_errno(lifh),
168
"%s: ifconfig_media_get_mediareq", ctx->ifname);
169
170
if (ifmr->ifm_count == 0)
171
errx(1, "%s: no media types?", ctx->ifname);
172
173
return (ifmr);
174
}
175
176
static void
177
setifmediacallback(if_ctx *ctx, void *arg)
178
{
179
struct ifmediareq *ifmr = (struct ifmediareq *)arg;
180
static bool did_it = false;
181
struct ifreq ifr = {};
182
183
if (!did_it) {
184
ifr.ifr_media = ifmr->ifm_current;
185
if (ioctl_ctx_ifr(ctx, SIOCSIFMEDIA, &ifr) < 0)
186
err(1, "SIOCSIFMEDIA (media)");
187
free(ifmr);
188
did_it = true;
189
}
190
}
191
192
static void
193
setmedia(if_ctx *ctx, const char *val, int d __unused)
194
{
195
struct ifmediareq *ifmr;
196
int subtype;
197
198
ifmr = ifmedia_getstate(ctx);
199
200
/*
201
* We are primarily concerned with the top-level type.
202
* However, "current" may be only IFM_NONE, so we just look
203
* for the top-level type in the first "supported type"
204
* entry.
205
*
206
* (I'm assuming that all supported media types for a given
207
* interface will be the same top-level type..)
208
*/
209
subtype = get_media_subtype(ifmr->ifm_ulist[0], val);
210
211
ifmr->ifm_current = (ifmr->ifm_current & IFM_IMASK) |
212
IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
213
214
callback_register(setifmediacallback, (void *)ifmr);
215
}
216
217
static void
218
setmediaopt(if_ctx *ctx, const char *val, int d __unused)
219
{
220
221
domediaopt(ctx, val, false);
222
}
223
224
static void
225
unsetmediaopt(if_ctx *ctx, const char *val, int d __unused)
226
{
227
228
domediaopt(ctx, val, true);
229
}
230
231
static void
232
domediaopt(if_ctx *ctx, const char *val, bool clear)
233
{
234
struct ifmediareq *ifmr;
235
ifmedia_t options;
236
237
ifmr = ifmedia_getstate(ctx);
238
239
options = get_media_options(ifmr->ifm_ulist[0], val);
240
241
if (clear)
242
ifmr->ifm_current &= ~options;
243
else {
244
if (options & IFM_HDX) {
245
ifmr->ifm_current &= ~IFM_FDX;
246
options &= ~IFM_HDX;
247
}
248
ifmr->ifm_current |= options;
249
}
250
callback_register(setifmediacallback, (void *)ifmr);
251
}
252
253
static void
254
setmediainst(if_ctx *ctx, const char *val, int d __unused)
255
{
256
struct ifmediareq *ifmr;
257
int inst;
258
259
ifmr = ifmedia_getstate(ctx);
260
261
inst = atoi(val);
262
if (inst < 0 || inst > (int)IFM_INST_MAX)
263
errx(1, "invalid media instance: %s", val);
264
265
ifmr->ifm_current = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
266
267
callback_register(setifmediacallback, (void *)ifmr);
268
}
269
270
static void
271
setmediamode(if_ctx *ctx, const char *val, int d __unused)
272
{
273
struct ifmediareq *ifmr;
274
int mode;
275
276
ifmr = ifmedia_getstate(ctx);
277
278
mode = get_media_mode(ifmr->ifm_ulist[0], val);
279
280
ifmr->ifm_current = (ifmr->ifm_current & ~IFM_MMASK) | mode;
281
282
callback_register(setifmediacallback, (void *)ifmr);
283
}
284
285
static ifmedia_t
286
get_media_subtype(ifmedia_t media, const char *val)
287
{
288
ifmedia_t subtype;
289
290
subtype = ifconfig_media_lookup_subtype(media, val);
291
if (subtype != INVALID_IFMEDIA)
292
return (subtype);
293
switch (errno) {
294
case EINVAL:
295
errx(EXIT_FAILURE, "unknown media type 0x%x", media);
296
case ENOENT:
297
errx(EXIT_FAILURE, "unknown media subtype: %s", val);
298
default:
299
err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
300
}
301
/*NOTREACHED*/
302
}
303
304
static ifmedia_t
305
get_media_mode(ifmedia_t media, const char *val)
306
{
307
ifmedia_t mode;
308
309
mode = ifconfig_media_lookup_mode(media, val);
310
if (mode != INVALID_IFMEDIA)
311
return (mode);
312
switch (errno) {
313
case EINVAL:
314
errx(EXIT_FAILURE, "unknown media type 0x%x", media);
315
case ENOENT:
316
return (INVALID_IFMEDIA);
317
default:
318
err(EXIT_FAILURE, "ifconfig_media_lookup_subtype");
319
}
320
/*NOTREACHED*/
321
}
322
323
static ifmedia_t
324
get_media_options(ifmedia_t media, const char *val)
325
{
326
ifmedia_t *options;
327
const char **optnames;
328
char *opts, *opt;
329
size_t nopts;
330
int rval;
331
332
/*
333
* We muck with the string, so copy it.
334
*/
335
opts = strdup(val);
336
if (opts == NULL)
337
err(EXIT_FAILURE, "strdup");
338
339
/*
340
* Split the comma-delimited list into separate strings.
341
*/
342
nopts = 0;
343
for (opt = opts; (opt = strtok(opt, ",")) != NULL; opt = NULL)
344
++nopts;
345
if (nopts == 0) {
346
free(opts);
347
return (0);
348
}
349
optnames = calloc(nopts, sizeof(*optnames));
350
if (optnames == NULL)
351
err(EXIT_FAILURE, "calloc");
352
opt = opts;
353
for (size_t i = 0; i < nopts; ++i) {
354
optnames[i] = opt;
355
opt = strchr(opt, '\0') + 1;
356
}
357
358
/*
359
* Look up the options in the user-provided list.
360
*/
361
options = ifconfig_media_lookup_options(media, optnames, nopts);
362
if (options == NULL)
363
err(EXIT_FAILURE, "ifconfig_media_lookup_options");
364
rval = 0;
365
for (size_t i = 0; i < nopts; ++i) {
366
if (options[i] == INVALID_IFMEDIA)
367
errx(EXIT_FAILURE, "unknown option: %s", optnames[i]);
368
rval |= options[i];
369
}
370
free(options);
371
free(optnames);
372
free(opts);
373
return (rval);
374
}
375
376
static void
377
print_media(ifmedia_t media, bool print_toptype)
378
{
379
const char *val, **options;
380
381
val = ifconfig_media_get_type(media);
382
if (val == NULL) {
383
printf("<unknown type>");
384
return;
385
} else if (print_toptype) {
386
printf("%s", val);
387
}
388
389
val = ifconfig_media_get_subtype(media);
390
if (val == NULL) {
391
printf("<unknown subtype>");
392
return;
393
}
394
395
if (print_toptype)
396
putchar(' ');
397
398
printf("%s", val);
399
400
if (print_toptype) {
401
val = ifconfig_media_get_mode(media);
402
if (val != NULL && strcasecmp("autoselect", val) != 0)
403
printf(" mode %s", val);
404
}
405
406
options = ifconfig_media_get_options(media);
407
if (options != NULL && options[0] != NULL) {
408
printf(" <%s", options[0]);
409
for (size_t i = 1; options[i] != NULL; ++i)
410
printf(",%s", options[i]);
411
printf(">");
412
}
413
free(options);
414
415
if (print_toptype && IFM_INST(media) != 0)
416
printf(" instance %d", IFM_INST(media));
417
}
418
419
static void
420
print_media_ifconfig(ifmedia_t media)
421
{
422
const char *val, **options;
423
424
val = ifconfig_media_get_type(media);
425
if (val == NULL) {
426
printf("<unknown type>");
427
return;
428
}
429
430
/*
431
* Don't print the top-level type; it's not like we can
432
* change it, or anything.
433
*/
434
435
val = ifconfig_media_get_subtype(media);
436
if (val == NULL) {
437
printf("<unknown subtype>");
438
return;
439
}
440
441
printf("media %s", val);
442
443
val = ifconfig_media_get_mode(media);
444
if (val != NULL)
445
printf(" mode %s", val);
446
447
options = ifconfig_media_get_options(media);
448
if (options != NULL && options[0] != NULL) {
449
printf(" mediaopt %s", options[0]);
450
for (size_t i = 1; options[i] != NULL; ++i)
451
printf(",%s", options[i]);
452
}
453
free(options);
454
455
if (IFM_INST(media) != 0)
456
printf(" instance %d", IFM_INST(media));
457
}
458
459
/**********************************************************************
460
* ...until here.
461
**********************************************************************/
462
463
static struct cmd media_cmds[] = {
464
DEF_CMD_ARG("media", setmedia),
465
DEF_CMD_ARG("mode", setmediamode),
466
DEF_CMD_ARG("mediaopt", setmediaopt),
467
DEF_CMD_ARG("-mediaopt",unsetmediaopt),
468
DEF_CMD_ARG("inst", setmediainst),
469
DEF_CMD_ARG("instance", setmediainst),
470
};
471
static struct afswtch af_media = {
472
.af_name = "af_media",
473
.af_af = AF_UNSPEC,
474
.af_other_status = media_status,
475
};
476
477
static __constructor void
478
ifmedia_ctor(void)
479
{
480
for (size_t i = 0; i < nitems(media_cmds); i++)
481
cmd_register(&media_cmds[i]);
482
af_register(&af_media);
483
}
484
485