source: rtems-libbsd/freebsd/sys/net/if_media.c @ 6d9d7b1

55-freebsd-126-freebsd-12
Last change on this file since 6d9d7b1 was 0237319, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/17 at 11:18:31

Update due to Newlib 2017-06-07 changes

The following files are now provided by Newlib:

  • arpa/inet.h
  • net/if.h
  • netinet/in.h
  • netinet/tcp.h
  • sys/socket.h
  • sys/uio.h
  • sys/un.h

The <sys/param.h> and <sys/cpuset.h> are now compatible enough to be
used directly.

Update #2833.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*      $NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $     */
4/* $FreeBSD$ */
5
6/*-
7 * Copyright (c) 1997
8 *      Jonathan Stone and Jason R. Thorpe.  All rights reserved.
9 *
10 * This software is derived from information provided by Matt Thomas.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *      This product includes software developed by Jonathan Stone
23 *      and Jason R. Thorpe for the NetBSD Project.
24 * 4. The names of the authors may not be used to endorse or promote products
25 *    derived from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
35 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40/*
41 * BSD/OS-compatible network interface media selection.
42 *
43 * Where it is safe to do so, this code strays slightly from the BSD/OS
44 * design.  Software which uses the API (device drivers, basically)
45 * shouldn't notice any difference.
46 *
47 * Many thanks to Matt Thomas for providing the information necessary
48 * to implement this interface.
49 */
50
51#include <rtems/bsd/local/opt_ifmedia.h>
52
53#include <sys/param.h>
54#include <sys/systm.h>
55#include <sys/socket.h>
56#include <sys/sockio.h>
57#include <sys/malloc.h>
58#include <sys/module.h>
59#include <sys/sysctl.h>
60
61#include <net/if.h>
62#include <net/if_media.h>
63
64/*
65 * Compile-time options:
66 * IFMEDIA_DEBUG:
67 *      turn on implementation-level debug printfs.
68 *      Useful for debugging newly-ported  drivers.
69 */
70
71static struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm,
72    int flags, int mask);
73
74#ifdef IFMEDIA_DEBUG
75#include <net/if_var.h>
76int     ifmedia_debug = 0;
77SYSCTL_INT(_debug, OID_AUTO, ifmedia, CTLFLAG_RW, &ifmedia_debug,
78            0, "if_media debugging msgs");
79static  void ifmedia_printword(int);
80#endif
81
82/*
83 * Initialize if_media struct for a specific interface instance.
84 */
85void
86ifmedia_init(ifm, dontcare_mask, change_callback, status_callback)
87        struct ifmedia *ifm;
88        int dontcare_mask;
89        ifm_change_cb_t change_callback;
90        ifm_stat_cb_t status_callback;
91{
92
93        LIST_INIT(&ifm->ifm_list);
94        ifm->ifm_cur = NULL;
95        ifm->ifm_media = 0;
96        ifm->ifm_mask = dontcare_mask;          /* IF don't-care bits */
97        ifm->ifm_change = change_callback;
98        ifm->ifm_status = status_callback;
99}
100
101void
102ifmedia_removeall(ifm)
103        struct ifmedia *ifm;
104{
105        struct ifmedia_entry *entry;
106
107        for (entry = LIST_FIRST(&ifm->ifm_list); entry;
108             entry = LIST_FIRST(&ifm->ifm_list)) {
109                LIST_REMOVE(entry, ifm_list);
110                free(entry, M_IFADDR);
111        }
112        ifm->ifm_cur = NULL;
113}
114
115/*
116 * Add a media configuration to the list of supported media
117 * for a specific interface instance.
118 */
119void
120ifmedia_add(ifm, mword, data, aux)
121        struct ifmedia *ifm;
122        int mword;
123        int data;
124        void *aux;
125{
126        register struct ifmedia_entry *entry;
127
128#ifdef IFMEDIA_DEBUG
129        if (ifmedia_debug) {
130                if (ifm == NULL) {
131                        printf("ifmedia_add: null ifm\n");
132                        return;
133                }
134                printf("Adding entry for ");
135                ifmedia_printword(mword);
136        }
137#endif
138
139        entry = malloc(sizeof(*entry), M_IFADDR, M_NOWAIT);
140        if (entry == NULL)
141                panic("ifmedia_add: can't malloc entry");
142
143        entry->ifm_media = mword;
144        entry->ifm_data = data;
145        entry->ifm_aux = aux;
146
147        LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list);
148}
149
150/*
151 * Add an array of media configurations to the list of
152 * supported media for a specific interface instance.
153 */
154void
155ifmedia_list_add(ifm, lp, count)
156        struct ifmedia *ifm;
157        struct ifmedia_entry *lp;
158        int count;
159{
160        int i;
161
162        for (i = 0; i < count; i++)
163                ifmedia_add(ifm, lp[i].ifm_media, lp[i].ifm_data,
164                    lp[i].ifm_aux);
165}
166
167/*
168 * Set the default active media.
169 *
170 * Called by device-specific code which is assumed to have already
171 * selected the default media in hardware.  We do _not_ call the
172 * media-change callback.
173 */
174void
175ifmedia_set(ifm, target)
176        struct ifmedia *ifm;
177        int target;
178
179{
180        struct ifmedia_entry *match;
181
182        match = ifmedia_match(ifm, target, ifm->ifm_mask);
183
184        if (match == NULL) {
185                printf("ifmedia_set: no match for 0x%x/0x%x\n",
186                    target, ~ifm->ifm_mask);
187                panic("ifmedia_set");
188        }
189        ifm->ifm_cur = match;
190
191#ifdef IFMEDIA_DEBUG
192        if (ifmedia_debug) {
193                printf("ifmedia_set: target ");
194                ifmedia_printword(target);
195                printf("ifmedia_set: setting to ");
196                ifmedia_printword(ifm->ifm_cur->ifm_media);
197        }
198#endif
199}
200
201/*
202 * Given a media word, return one suitable for an application
203 * using the original encoding.
204 */
205static int
206compat_media(int media)
207{
208
209        if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) {
210                media &= ~(IFM_ETH_XTYPE|IFM_TMASK);
211                media |= IFM_OTHER;
212        }
213        return (media);
214}
215
216/*
217 * Device-independent media ioctl support function.
218 */
219int
220ifmedia_ioctl(ifp, ifr, ifm, cmd)
221        struct ifnet *ifp;
222        struct ifreq *ifr;
223        struct ifmedia *ifm;
224        u_long cmd;
225{
226        struct ifmedia_entry *match;
227        struct ifmediareq *ifmr = (struct ifmediareq *) ifr;
228        int error = 0;
229
230        if (ifp == NULL || ifr == NULL || ifm == NULL)
231                return(EINVAL);
232
233        switch (cmd) {
234
235        /*
236         * Set the current media.
237         */
238        case  SIOCSIFMEDIA:
239        {
240                struct ifmedia_entry *oldentry;
241                int oldmedia;
242                int newmedia = ifr->ifr_media;
243
244                match = ifmedia_match(ifm, newmedia, ifm->ifm_mask);
245                if (match == NULL) {
246#ifdef IFMEDIA_DEBUG
247                        if (ifmedia_debug) {
248                                printf(
249                                    "ifmedia_ioctl: no media found for 0x%x\n",
250                                    newmedia);
251                        }
252#endif
253                        return (ENXIO);
254                }
255
256                /*
257                 * If no change, we're done.
258                 * XXX Automedia may invole software intervention.
259                 *     Keep going in case the connected media changed.
260                 *     Similarly, if best match changed (kernel debugger?).
261                 */
262                if ((IFM_SUBTYPE(newmedia) != IFM_AUTO) &&
263                    (newmedia == ifm->ifm_media) &&
264                    (match == ifm->ifm_cur))
265                        return 0;
266
267                /*
268                 * We found a match, now make the driver switch to it.
269                 * Make sure to preserve our old media type in case the
270                 * driver can't switch.
271                 */
272#ifdef IFMEDIA_DEBUG
273                if (ifmedia_debug) {
274                        printf("ifmedia_ioctl: switching %s to ",
275                            ifp->if_xname);
276                        ifmedia_printword(match->ifm_media);
277                }
278#endif
279                oldentry = ifm->ifm_cur;
280                oldmedia = ifm->ifm_media;
281                ifm->ifm_cur = match;
282                ifm->ifm_media = newmedia;
283                error = (*ifm->ifm_change)(ifp);
284                if (error) {
285                        ifm->ifm_cur = oldentry;
286                        ifm->ifm_media = oldmedia;
287                }
288                break;
289        }
290
291        /*
292         * Get list of available media and current media on interface.
293         */
294        case  SIOCGIFMEDIA:
295        case  SIOCGIFXMEDIA:
296        {
297                struct ifmedia_entry *ep;
298                int i;
299
300                if (ifmr->ifm_count < 0)
301                        return (EINVAL);
302
303                if (cmd == SIOCGIFMEDIA) {
304                        ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
305                            compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE;
306                } else {
307                        ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
308                            ifm->ifm_cur->ifm_media : IFM_NONE;
309                }
310                ifmr->ifm_mask = ifm->ifm_mask;
311                ifmr->ifm_status = 0;
312                (*ifm->ifm_status)(ifp, ifmr);
313
314                /*
315                 * If there are more interfaces on the list, count
316                 * them.  This allows the caller to set ifmr->ifm_count
317                 * to 0 on the first call to know how much space to
318                 * allocate.
319                 */
320                i = 0;
321                LIST_FOREACH(ep, &ifm->ifm_list, ifm_list)
322                        if (i++ < ifmr->ifm_count) {
323                                error = copyout(&ep->ifm_media,
324                                    ifmr->ifm_ulist + i - 1, sizeof(int));
325                                if (error)
326                                        break;
327                        }
328                if (error == 0 && i > ifmr->ifm_count)
329                        error = ifmr->ifm_count ? E2BIG : 0;
330                ifmr->ifm_count = i;
331                break;
332        }
333
334        default:
335                return (EINVAL);
336        }
337
338        return (error);
339}
340
341/*
342 * Find media entry matching a given ifm word.
343 *
344 */
345static struct ifmedia_entry *
346ifmedia_match(ifm, target, mask)
347        struct ifmedia *ifm;
348        int target;
349        int mask;
350{
351        struct ifmedia_entry *match, *next;
352
353        match = NULL;
354        mask = ~mask;
355
356        LIST_FOREACH(next, &ifm->ifm_list, ifm_list) {
357                if ((next->ifm_media & mask) == (target & mask)) {
358#if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
359                        if (match) {
360                                printf("ifmedia_match: multiple match for "
361                                    "0x%x/0x%x\n", target, mask);
362                        }
363#endif
364                        match = next;
365                }
366        }
367
368        return match;
369}
370
371/*
372 * Compute the interface `baudrate' from the media, for the interface
373 * metrics (used by routing daemons).
374 */
375static const struct ifmedia_baudrate ifmedia_baudrate_descriptions[] =   
376    IFM_BAUDRATE_DESCRIPTIONS;
377
378uint64_t
379ifmedia_baudrate(int mword)
380{
381        int i;
382
383        for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) {
384                if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_descriptions[i].ifmb_word))
385                        return (ifmedia_baudrate_descriptions[i].ifmb_baudrate);
386        }
387
388        /* Not known. */
389        return (0);
390}
391 
392#ifdef IFMEDIA_DEBUG
393struct ifmedia_description ifm_type_descriptions[] =
394    IFM_TYPE_DESCRIPTIONS;
395
396struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
397    IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
398
399struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
400    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
401
402struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
403    IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
404
405struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
406    IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
407
408struct ifmedia_description ifm_subtype_fddi_descriptions[] =
409    IFM_SUBTYPE_FDDI_DESCRIPTIONS;
410
411struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
412    IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
413
414struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
415    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
416
417struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
418    IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
419
420struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
421    IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
422
423struct ifmedia_description ifm_subtype_atm_descriptions[] =
424    IFM_SUBTYPE_ATM_DESCRIPTIONS;
425
426struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
427    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
428
429struct ifmedia_description ifm_subtype_shared_descriptions[] =
430    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
431
432struct ifmedia_description ifm_shared_option_descriptions[] =
433    IFM_SHARED_OPTION_DESCRIPTIONS;
434
435struct ifmedia_type_to_subtype {
436        struct ifmedia_description *subtypes;
437        struct ifmedia_description *options;
438        struct ifmedia_description *modes;
439};
440
441/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
442struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
443        {
444          &ifm_subtype_ethernet_descriptions[0],
445          &ifm_subtype_ethernet_option_descriptions[0],
446          NULL,
447        },
448        {
449          &ifm_subtype_tokenring_descriptions[0],
450          &ifm_subtype_tokenring_option_descriptions[0],
451          NULL,
452        },
453        {
454          &ifm_subtype_fddi_descriptions[0],
455          &ifm_subtype_fddi_option_descriptions[0],
456          NULL,
457        },
458        {
459          &ifm_subtype_ieee80211_descriptions[0],
460          &ifm_subtype_ieee80211_option_descriptions[0],
461          &ifm_subtype_ieee80211_mode_descriptions[0]
462        },
463        {
464          &ifm_subtype_atm_descriptions[0],
465          &ifm_subtype_atm_option_descriptions[0],
466          NULL,
467        },
468};
469
470/*
471 * print a media word.
472 */
473static void
474ifmedia_printword(ifmw)
475        int ifmw;
476{
477        struct ifmedia_description *desc;
478        struct ifmedia_type_to_subtype *ttos;
479        int seen_option = 0;
480
481        /* Find the top-level interface type. */
482        for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
483            desc->ifmt_string != NULL; desc++, ttos++)
484                if (IFM_TYPE(ifmw) == desc->ifmt_word)
485                        break;
486        if (desc->ifmt_string == NULL) {
487                printf("<unknown type>\n");
488                return;
489        }
490        printf("%s", desc->ifmt_string);
491
492        /* Any mode. */
493        for (desc = ttos->modes; desc && desc->ifmt_string != NULL; desc++)
494                if (IFM_MODE(ifmw) == desc->ifmt_word) {
495                        if (desc->ifmt_string != NULL)
496                                printf(" mode %s", desc->ifmt_string);
497                        break;
498                }
499
500        /*
501         * Check for the shared subtype descriptions first, then the
502         * type-specific ones.
503         */
504        for (desc = ifm_subtype_shared_descriptions;
505            desc->ifmt_string != NULL; desc++)
506                if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
507                        goto got_subtype;
508
509        for (desc = ttos->subtypes; desc->ifmt_string != NULL; desc++)
510                if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
511                        break;
512        if (desc->ifmt_string == NULL) {
513                printf(" <unknown subtype>\n");
514                return;
515        }
516
517 got_subtype:
518        printf(" %s", desc->ifmt_string);
519
520        /*
521         * Look for shared options.
522         */
523        for (desc = ifm_shared_option_descriptions;
524            desc->ifmt_string != NULL; desc++) {
525                if (ifmw & desc->ifmt_word) {
526                        if (seen_option == 0)
527                                printf(" <");
528                        printf("%s%s", seen_option++ ? "," : "",
529                            desc->ifmt_string);
530                }
531        }
532
533        /*
534         * Look for subtype-specific options.
535         */
536        for (desc = ttos->options; desc->ifmt_string != NULL; desc++) {
537                if (ifmw & desc->ifmt_word) {
538                        if (seen_option == 0)
539                                printf(" <");
540                        printf("%s%s", seen_option++ ? "," : "",
541                            desc->ifmt_string);
542                }
543        }
544        printf("%s\n", seen_option ? ">" : "");
545}
546#endif /* IFMEDIA_DEBUG */
Note: See TracBrowser for help on using the repository browser.