]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_media.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / net / if_media.c
index 59778216b5220aadd65b950b05648026e66780c1..dec89f265d2627a6bff1a98d69f29c79dd3c6c00 100644 (file)
@@ -1,25 +1,34 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * This file contains Original Code and/or Modifications of Original Code 
+ * as defined in and that are subject to the Apple Public Source License 
+ * Version 2.0 (the 'License'). You may not use this file except in 
+ * compliance with the License.  The rights granted to you under the 
+ * License may not be used to create, or enable the creation or 
+ * redistribution of, unlawful or unlicensed copies of an Apple operating 
+ * system, or to circumvent, violate, or enable the circumvention or 
+ * violation of, any terms of an Apple operating system software license 
+ * agreement.
+ *
+ * Please obtain a copy of the License at 
+ * http://www.opensource.apple.com/apsl/ and read it before using this 
+ * file.
+ *
+ * The Original Code and all software distributed under the License are 
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
+ * Please see the License for the specific language governing rights and 
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
  */
 /*     $NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $     */
+/* $FreeBSD: src/sys/net/if_media.c,v 1.9.2.4 2001/07/04 00:12:38 brooks Exp $ */
 
 /*
  * Copyright (c) 1997
  *     Useful for debugging newly-ported  drivers.
  */
 
-static struct ifmedia_entry *ifmedia_match __P((struct ifmedia *ifm,
-    int flags, int mask));
+static struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm,
+    int flags, int mask);
 
 #ifdef IFMEDIA_DEBUG
 int    ifmedia_debug = 0;
-static void ifmedia_printword __P((int));
+static void ifmedia_printword(int);
 #endif
 
 /*
@@ -109,6 +118,19 @@ ifmedia_init(ifm, dontcare_mask, change_callback, status_callback)
        ifm->ifm_status = status_callback;
 }
 
+void
+ifmedia_removeall(ifm)
+       struct ifmedia *ifm;
+{
+       struct ifmedia_entry *entry;
+
+       for (entry = LIST_FIRST(&ifm->ifm_list); entry;
+            entry = LIST_FIRST(&ifm->ifm_list)) {
+               LIST_REMOVE(entry, ifm_list);
+               FREE(entry, M_IFADDR);
+       }
+}
+
 /*
  * Add a media configuration to the list of supported media
  * for a specific interface instance.
@@ -133,7 +155,7 @@ ifmedia_add(ifm, mword, data, aux)
        }
 #endif
 
-       entry = _MALLOC(sizeof(*entry), M_IFADDR, M_WAITOK);
+       entry = _MALLOC(sizeof(*entry), M_IFADDR, M_NOWAIT);
        if (entry == NULL)
                panic("ifmedia_add: can't malloc entry");
 
@@ -199,11 +221,11 @@ ifmedia_set(ifm, target)
  * Device-independent media ioctl support function.
  */
 int
-ifmedia_ioctl(ifp, ifr, ifm, cmd)
-       struct ifnet *ifp;
-       struct ifreq *ifr;
-       struct ifmedia *ifm;
-       u_long cmd;
+ifmedia_ioctl(
+       struct ifnet *ifp,
+       struct ifreq *ifr,
+       struct ifmedia *ifm,
+       u_long cmd)
 {
        struct ifmedia_entry *match;
        struct ifmediareq *ifmr = (struct ifmediareq *) ifr;
@@ -277,6 +299,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
        {
                struct ifmedia_entry *ep;
                int *kptr, count;
+               int usermax;    /* user requested max */
 
                kptr = NULL;            /* XXX gcc */
 
@@ -287,7 +310,25 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
                (*ifm->ifm_status)(ifp, ifmr);
 
                count = 0;
-               ep = ifm->ifm_list.lh_first;
+               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.
+                */
+               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),
@@ -296,23 +337,17 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
                        /*
                         * Get the media words from the interface's list.
                         */
+                       ep = LIST_FIRST(&ifm->ifm_list);
                        for (; ep != NULL && count < ifmr->ifm_count;
-                           ep = ep->ifm_list.le_next, count++)
+                           ep = LIST_NEXT(ep, ifm_list), count++)
                                kptr[count] = ep->ifm_media;
 
                        if (ep != NULL)
                                error = E2BIG;  /* oops! */
+               } else {
+                       count = usermax;
                }
 
-               /*
-                * 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
-                * callocate.
-                */
-               for (; ep != NULL; ep = ep->ifm_list.le_next)
-                       count++;
-
                /*
                 * We do the copyout on E2BIG, because that's
                 * just our way of telling userland that there
@@ -322,7 +357,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
                sticky = error;
                if ((error == 0 || error == E2BIG) && ifmr->ifm_count != 0) {
                        error = copyout((caddr_t)kptr,
-                           (caddr_t)ifmr->ifm_ulist,
+                           CAST_USER_ADDR_T(ifmr->ifm_ulist),
                            ifmr->ifm_count * sizeof(int));
                }
 
@@ -358,8 +393,7 @@ ifmedia_match(ifm, target, mask)
        match = NULL;
        mask = ~mask;
 
-       for (next = ifm->ifm_list.lh_first; next != NULL;
-           next = next->ifm_list.le_next) {
+       LIST_FOREACH(next, &ifm->ifm_list, ifm_list) {
                if ((next->ifm_media & mask) == (target & mask)) {
 #if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
                        if (match) {