diff options
Diffstat (limited to 'sys/net/if_media.c')
-rw-r--r-- | sys/net/if_media.c | 72 |
1 files changed, 14 insertions, 58 deletions
diff --git a/sys/net/if_media.c b/sys/net/if_media.c index 22bdc82af18f..810db3f4e012 100644 --- a/sys/net/if_media.c +++ b/sys/net/if_media.c @@ -204,7 +204,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd) { struct ifmedia_entry *match; struct ifmediareq *ifmr = (struct ifmediareq *) ifr; - int error = 0, sticky; + int error = 0; if (ifp == NULL || ifr == NULL || ifm == NULL) return(EINVAL); @@ -273,10 +273,10 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd) case SIOCGIFMEDIA: { struct ifmedia_entry *ep; - int *kptr, count; - int usermax; /* user requested max */ + int i; - kptr = NULL; /* XXX gcc */ + if (ifmr->ifm_count < 0) + return (EINVAL); ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? ifm->ifm_cur->ifm_media : IFM_NONE; @@ -284,67 +284,23 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd) ifmr->ifm_status = 0; (*ifm->ifm_status)(ifp, ifmr); - count = 0; - usermax = 0; - /* * 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) - usermax++; - - /* - * Don't allow the user to ask for too many - * or a negative number. - */ - if (ifmr->ifm_count > usermax) - ifmr->ifm_count = usermax; - else if (ifmr->ifm_count < 0) - return (EINVAL); - - if (ifmr->ifm_count != 0) { - kptr = (int *)malloc(ifmr->ifm_count * sizeof(int), - M_TEMP, M_NOWAIT); - - if (kptr == NULL) - return (ENOMEM); - /* - * Get the media words from the interface's list. - */ - ep = LIST_FIRST(&ifm->ifm_list); - for (; ep != NULL && count < ifmr->ifm_count; - ep = LIST_NEXT(ep, ifm_list), count++) - kptr[count] = ep->ifm_media; - - if (ep != NULL) - error = E2BIG; /* oops! */ - } else { - count = usermax; - } - - /* - * We do the copyout on E2BIG, because that's - * just our way of telling userland that there - * are more. This is the behavior I've observed - * under BSD/OS 3.0 - */ - sticky = error; - if ((error == 0 || error == E2BIG) && ifmr->ifm_count != 0) { - error = copyout((caddr_t)kptr, - (caddr_t)ifmr->ifm_ulist, - ifmr->ifm_count * sizeof(int)); - } - - if (error == 0) - error = sticky; - - if (ifmr->ifm_count != 0) - free(kptr, M_TEMP); - - ifmr->ifm_count = count; + if (i++ < ifmr->ifm_count) { + error = copyout(&ep->ifm_media, + ifmr->ifm_ulist + i - 1, sizeof(int)); + if (error) + break; + } + if (error == 0 && i > ifmr->ifm_count) + error = ifmr->ifm_count ? E2BIG : 0; + ifmr->ifm_count = i; break; } |