--- b/sys/net/if_media.c +++ b/sys/net/if_media.c @@ -182,199 +182,199 @@ ifmedia_set(struct ifmedia *ifm, int target) ifmedia_printword(ifm->ifm_cur->ifm_media); } #endif } /* * Given a media word, return one suitable for an application * using the original encoding. */ static int compat_media(int media) { if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) { media &= ~(IFM_ETH_XTYPE|IFM_TMASK); media |= IFM_OTHER; } return (media); } /* * Device-independent media ioctl support function. */ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm, u_long cmd) { struct ifmedia_entry *match; struct ifmediareq *ifmr = (struct ifmediareq *) ifr; int error = 0; if (ifp == NULL || ifr == NULL || ifm == NULL) return (EINVAL); switch (cmd) { /* * Set the current media. */ case SIOCSIFMEDIA: { struct ifmedia_entry *oldentry; int oldmedia; int newmedia = ifr->ifr_media; match = ifmedia_match(ifm, newmedia, ifm->ifm_mask); if (match == NULL) { #ifdef IFMEDIA_DEBUG if (ifmedia_debug) { printf( "ifmedia_ioctl: no media found for %#010x mask %#010x\n", newmedia, ifm->ifm_mask); } #endif return (ENXIO); } /* * If no change, we're done. * XXX Automedia may invole software intervention. * Keep going in case the connected media changed. * Similarly, if best match changed (kernel debugger?). */ if (IFM_SUBTYPE(newmedia) != IFM_AUTO && newmedia == ifm->ifm_media && match == ifm->ifm_cur) return (0); /* * We found a match, now make the driver switch to it. * Make sure to preserve our old media type in case the * driver can't switch. */ #ifdef IFMEDIA_DEBUG if (ifmedia_debug) { printf("ifmedia_ioctl: switching %s to ", ifp->if_xname); ifmedia_printword(match->ifm_media); } #endif oldentry = ifm->ifm_cur; oldmedia = ifm->ifm_media; ifm->ifm_cur = match; ifm->ifm_media = newmedia; error = (*ifm->ifm_change)(ifp); if (error) { ifm->ifm_cur = oldentry; ifm->ifm_media = oldmedia; } break; } /* * Get list of available media and current media on interface. */ case SIOCGIFMEDIA: case SIOCGIFXMEDIA: { struct ifmedia_entry *ep; int i; - if (ifmr->ifm_count < 0) + if (ifmr->ifm_count < 0 || ifm->ifm_status == NULL) return (EINVAL); if (cmd == SIOCGIFMEDIA) { ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE; } else { ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? ifm->ifm_cur->ifm_media : IFM_NONE; } ifmr->ifm_mask = ifm->ifm_mask; ifmr->ifm_status = 0; (*ifm->ifm_status)(ifp, ifmr); /* * If there are more interfaces on the list, count * them. This allows the caller to set ifmr->ifm_count * to 0 on the first call to know how much space to * allocate. */ i = 0; LIST_FOREACH(ep, &ifm->ifm_list, ifm_list) { if (i < ifmr->ifm_count) { error = copyout(&ep->ifm_media, ifmr->ifm_ulist + i, sizeof(int)); if (error != 0) break; } i++; } if (error == 0 && i > ifmr->ifm_count) error = ifmr->ifm_count != 0 ? E2BIG : 0; ifmr->ifm_count = i; break; } default: return (EINVAL); } return (error); } /* * Find media entry matching a given ifm word. * */ static struct ifmedia_entry * ifmedia_match(struct ifmedia *ifm, int target, int mask) { struct ifmedia_entry *match, *next; match = NULL; mask = ~mask; LIST_FOREACH(next, &ifm->ifm_list, ifm_list) { if ((next->ifm_media & mask) == (target & mask)) { #if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC) if (match) { printf("ifmedia_match: multiple match for " "%#010x/%#010x\n", target, mask); } #endif match = next; } } return (match); } /* * Compute the interface `baudrate' from the media, for the interface * metrics (used by routing daemons). */ static const struct ifmedia_baudrate ifmedia_baudrate_descriptions[] = IFM_BAUDRATE_DESCRIPTIONS; uint64_t ifmedia_baudrate(int mword) { int i; for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) { if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_descriptions[i]. ifmb_word)) return (ifmedia_baudrate_descriptions[i].ifmb_baudrate); } /* Not known. */ return (0); } #ifdef IFMEDIA_DEBUG static const struct ifmedia_description ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; static const struct ifmedia_description ifm_subtype_ethernet_descriptions[] = IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; static const struct ifmedia_description