]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/rtsock.c
xnu-1228.9.59.tar.gz
[apple/xnu.git] / bsd / net / rtsock.c
index ed72eaf27e50371d3437837b7e56c7e59d02a7c2..b4aee361bb67a881f0b671205f89d8019c706407 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * 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. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * 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
@@ -20,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * Copyright (c) 1988, 1991, 1993
 #include <sys/domain.h>
 #include <sys/protosw.h>
 #include <sys/syslog.h>
+#include <kern/lock.h>
 
 #include <net/if.h>
 #include <net/route.h>
 #include <net/raw_cb.h>
 #include <netinet/in.h>
 
+#include <machine/spl.h>
+
+extern struct rtstat rtstat;
+extern int rttrash;
+extern u_long route_generation;
+extern int use_routegenid;
+extern int check_routeselfref;
+
 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
 
-static struct  sockaddr route_dst = { 2, PF_ROUTE, };
-static struct  sockaddr route_src = { 2, PF_ROUTE, };
-static struct  sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
-static struct  sockproto route_proto = { PF_ROUTE, };
+extern lck_mtx_t *rt_mtx;
+static struct  sockaddr route_dst = { 2, PF_ROUTE, { 0, } };
+static struct  sockaddr route_src = { 2, PF_ROUTE, { 0, } };
+static struct  sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, { 0, } };
+static struct  sockproto route_proto = { PF_ROUTE,  0 };
 
 struct walkarg {
        int     w_tmemsize;
@@ -91,16 +104,16 @@ struct walkarg {
 };
 
 static struct mbuf *
-               rt_msg1 __P((int, struct rt_addrinfo *));
-static int     rt_msg2 __P((int,
-                   struct rt_addrinfo *, caddr_t, struct walkarg *));
-static int     rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
-static int     sysctl_dumpentry __P((struct radix_node *rn, void *vw));
-static int     sysctl_iflist __P((int af, struct walkarg *w));
-static int      route_output __P((struct mbuf *, struct socket *));
-static void     rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
-static void    rt_setif __P((struct rtentry *, struct sockaddr *, struct sockaddr *,
-                             struct sockaddr *));
+               rt_msg1(int, struct rt_addrinfo *);
+static int     rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *);
+static int     rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
+static int     sysctl_dumpentry(struct radix_node *rn, void *vw);
+static int     sysctl_iflist(int af, struct walkarg *w);
+static int     sysctl_iflist2(int af, struct walkarg *w);
+static int      route_output(struct mbuf *, struct socket *);
+static void     rt_setmetrics(u_long, struct rt_metrics *, struct rt_metrics *);
+static void    rt_setif(struct rtentry *, struct sockaddr *, struct sockaddr *,
+                             struct sockaddr *);
 
 /* Sleazy use of local variables throughout file, warning!!!! */
 #define dst    info.rti_info[RTAX_DST]
@@ -118,20 +131,19 @@ static void       rt_setif __P((struct rtentry *, struct sockaddr *, struct sockaddr *
 static int
 rts_abort(struct socket *so)
 {
-       int s, error;
-       s = splnet();
+       int error;
+       
        error = raw_usrreqs.pru_abort(so);
-       splx(s);
        return error;
 }
 
 /* pru_accept is EOPNOTSUPP */
 
 static int
-rts_attach(struct socket *so, int proto, struct proc *p)
+rts_attach(struct socket *so, int proto, __unused struct proc *p)
 {
        struct rawcb *rp;
-       int s, error;
+       int error;
 
        if (sotorawcb(so) != 0)
                return EISCONN; /* XXX panic? */
@@ -147,17 +159,18 @@ rts_attach(struct socket *so, int proto, struct proc *p)
         * Probably we should try to do more of this work beforehand and
         * eliminate the spl.
         */
-       s = splnet();
        so->so_pcb = (caddr_t)rp;
        error = raw_attach(so, proto);  /* don't use raw_usrreqs.pru_attach, it checks for SS_PRIV */
        rp = sotorawcb(so);
        if (error) {
-               splx(s);
                FREE(rp, M_PCB);
-               so->so_pcb = 0;
+               so->so_pcb = NULL;
+               so->so_flags |= SOF_PCBCLEARING;
                return error;
        }
+
        switch(rp->rcb_proto.sp_protocol) {
+//####LD route_cb needs looking
        case AF_INET:
                route_cb.ip_count++;
                break;
@@ -173,29 +186,25 @@ rts_attach(struct socket *so, int proto, struct proc *p)
        }
        rp->rcb_faddr = &route_src;
        route_cb.any_count++;
+       /* the socket is already locked when we enter rts_attach */ 
        soisconnected(so);
        so->so_options |= SO_USELOOPBACK;
-       splx(s);
        return 0;
 }
 
 static int
 rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
-       splx(s);
        return error;
 }
 
 static int
 rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
-       splx(s);
        return error;
 }
 
@@ -206,9 +215,8 @@ static int
 rts_detach(struct socket *so)
 {
        struct rawcb *rp = sotorawcb(so);
-       int s, error;
+       int error;
 
-       s = splnet();
        if (rp != 0) {
                switch(rp->rcb_proto.sp_protocol) {
                case AF_INET:
@@ -227,17 +235,14 @@ rts_detach(struct socket *so)
                route_cb.any_count--;
        }
        error = raw_usrreqs.pru_detach(so);
-       splx(s);
        return error;
 }
 
 static int
 rts_disconnect(struct socket *so)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_disconnect(so);
-       splx(s);
        return error;
 }
 
@@ -246,10 +251,8 @@ rts_disconnect(struct socket *so)
 static int
 rts_peeraddr(struct socket *so, struct sockaddr **nam)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_peeraddr(so, nam);
-       splx(s);
        return error;
 }
 
@@ -260,10 +263,8 @@ static int
 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
         struct mbuf *control, struct proc *p)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
-       splx(s);
        return error;
 }
 
@@ -272,54 +273,53 @@ rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
 static int
 rts_shutdown(struct socket *so)
 {
-       int s, error;
-       s = splnet();
+       int  error;
        error = raw_usrreqs.pru_shutdown(so);
-       splx(s);
        return error;
 }
 
 static int
 rts_sockaddr(struct socket *so, struct sockaddr **nam)
 {
-       int s, error;
-       s = splnet();
+       int error;
        error = raw_usrreqs.pru_sockaddr(so, nam);
-       splx(s);
        return error;
 }
 
 static struct pr_usrreqs route_usrreqs = {
-       rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
-       pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
-       pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
-       rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
-       sosend, soreceive, sopoll
+       rts_abort, pru_accept_notsupp, rts_attach, rts_bind,
+       rts_connect, pru_connect2_notsupp, pru_control_notsupp,
+       rts_detach, rts_disconnect, pru_listen_notsupp, rts_peeraddr,
+       pru_rcvd_notsupp, pru_rcvoob_notsupp, rts_send, pru_sense_null,
+       rts_shutdown, rts_sockaddr, sosend, soreceive, pru_sopoll_notsupp
 };
 
 /*ARGSUSED*/
 static int
-route_output(m, so)
-       register struct mbuf *m;
-       struct socket *so;
+route_output(struct mbuf *m, struct socket *so)
 {
-       register struct rt_msghdr *rtm = 0;
-       register struct rtentry *rt = 0;
-       struct rtentry *saved_nrt = 0;
+       struct rt_msghdr *rtm = NULL;
+       struct rtentry *rt = NULL;
+       struct rtentry *saved_nrt = NULL;
        struct radix_node_head *rnh;
        struct rt_addrinfo info;
        int len, error = 0;
-       struct ifnet *ifp = 0;
-       struct ifaddr *ifa = 0;
+       struct ifnet *ifp = NULL;
+#ifndef __APPLE__
        struct proc  *curproc = current_proc();
+#endif
        int sendonlytoself = 0;
 
 #define senderr(e) { error = e; goto flush;}
-       if (m == 0 || ((m->m_len < sizeof(long)) &&
-                      (m = m_pullup(m, sizeof(long))) == 0))
+       if (m == 0 || ((m->m_len < sizeof(long)) && (m = m_pullup(m, sizeof(long))) == 0))
                return (ENOBUFS);
        if ((m->m_flags & M_PKTHDR) == 0)
                panic("route_output");
+
+       /* unlock the socket (but keep a reference) it won't be accessed until raw_input appends to it. */
+       socket_unlock(so, 0);
+       lck_mtx_lock(rt_mtx);
+
        len = m->m_pkthdr.len;
        if (len < sizeof(*rtm) ||
            len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
@@ -356,15 +356,17 @@ route_output(m, so)
                dst = 0;
                senderr(EPERM);
        }
-       rtm->rtm_pid = curproc->p_pid;
+
+       rtm->rtm_pid = proc_selfpid();
        info.rti_addrs = rtm->rtm_addrs;
        if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
                dst = 0;
                senderr(EINVAL);
        }
        if (dst == 0 || (dst->sa_family >= AF_MAX)
-           || (gate != 0 && (gate->sa_family >= AF_MAX)))
+           || (gate != 0 && (gate->sa_family >= AF_MAX))) {
                senderr(EINVAL);
+       }
        if (genmask) {
                struct radix_node *t;
                t = rn_addmask((caddr_t)genmask, 0, 1);
@@ -374,10 +376,10 @@ route_output(m, so)
                        senderr(ENOBUFS);
        }
        switch (rtm->rtm_type) {
-
-       case RTM_ADD:
-               if (gate == 0)
-                       senderr(EINVAL);
+       
+               case RTM_ADD:
+                       if (gate == 0)
+                               senderr(EINVAL);
 
 #ifdef __APPLE__
 /* XXX LD11JUL02 Special case for AOL 5.1.2 connectivity issue to AirPort BS (Radar 2969954)
@@ -392,169 +394,172 @@ route_output(m, so)
  * confusing the routing table with a wrong route to the previous default gateway
  */
 {
-               extern int check_routeselfref;
 #define satosinaddr(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr)
-
-               if (check_routeselfref && (dst && dst->sa_family == AF_INET) && 
-                       (netmask && satosinaddr(netmask) == INADDR_BROADCAST) &&
-                       (gate && satosinaddr(dst) == satosinaddr(gate))) {
-                               log(LOG_WARNING, "route_output: circular route %ld.%ld.%ld.%ld/32 ignored\n",
-                                       (ntohl(satosinaddr(gate)>>24))&0xff,
-                                       (ntohl(satosinaddr(gate)>>16))&0xff,
-                                       (ntohl(satosinaddr(gate)>>8))&0xff,
-                                       (ntohl(satosinaddr(gate)))&0xff);
-                                       
-                               senderr(EINVAL);
-               }
+       
+                       if (check_routeselfref && (dst && dst->sa_family == AF_INET) && 
+                               (netmask && satosinaddr(netmask) == INADDR_BROADCAST) &&
+                               (gate && satosinaddr(dst) == satosinaddr(gate))) {
+                                       log(LOG_WARNING, "route_output: circular route %ld.%ld.%ld.%ld/32 ignored\n",
+                                               (ntohl(satosinaddr(gate)>>24))&0xff,
+                                               (ntohl(satosinaddr(gate)>>16))&0xff,
+                                               (ntohl(satosinaddr(gate)>>8))&0xff,
+                                               (ntohl(satosinaddr(gate)))&0xff);
+                                               
+                                       senderr(EINVAL);
+                       }
 }
 #endif 
-               error = rtrequest(RTM_ADD, dst, gate, netmask,
-                                       rtm->rtm_flags, &saved_nrt);
-               if (error == 0 && saved_nrt) {
+                       error = rtrequest_locked(RTM_ADD, dst, gate, netmask,
+                                               rtm->rtm_flags, &saved_nrt);
+                       if (error == 0 && saved_nrt) {
 #ifdef __APPLE__
-                   /* 
-                    * If the route request specified an interface with
-                    * IFA and/or IFP, we set the requested interface on
-                    * the route with rt_setif.  It would be much better
-                    * to do this inside rtrequest, but that would
-                    * require passing the desired interface, in some
-                    * form, to rtrequest.  Since rtrequest is called in
-                    * so many places (roughly 40 in our source), adding
-                    * a parameter is to much for us to swallow; this is
-                    * something for the FreeBSD developers to tackle.
-                    * Instead, we let rtrequest compute whatever
-                    * interface it wants, then come in behind it and
-                    * stick in the interface that we really want.  This
-                    * works reasonably well except when rtrequest can't
-                    * figure out what interface to use (with
-                    * ifa_withroute) and returns ENETUNREACH.  Ideally
-                    * it shouldn't matter if rtrequest can't figure out
-                    * the interface if we're going to explicitly set it
-                    * ourselves anyway.  But practically we can't
-                    * recover here because rtrequest will not do any of
-                    * the work necessary to add the route if it can't
-                    * find an interface.  As long as there is a default
-                    * route that leads to some interface, rtrequest will
-                    * find an interface, so this problem should be
-                    * rarely encountered.
-                    * dwiggins@bbn.com
-                    */
-
-                       rt_setif(saved_nrt, ifpaddr, ifaaddr, gate);
+                               /* 
+                                * If the route request specified an interface with
+                                * IFA and/or IFP, we set the requested interface on
+                                * the route with rt_setif.  It would be much better
+                                * to do this inside rtrequest, but that would
+                                * require passing the desired interface, in some
+                                * form, to rtrequest.  Since rtrequest is called in
+                                * so many places (roughly 40 in our source), adding
+                                * a parameter is to much for us to swallow; this is
+                                * something for the FreeBSD developers to tackle.
+                                * Instead, we let rtrequest compute whatever
+                                * interface it wants, then come in behind it and
+                                * stick in the interface that we really want.  This
+                                * works reasonably well except when rtrequest can't
+                                * figure out what interface to use (with
+                                * ifa_withroute) and returns ENETUNREACH.  Ideally
+                                * it shouldn't matter if rtrequest can't figure out
+                                * the interface if we're going to explicitly set it
+                                * ourselves anyway.  But practically we can't
+                                * recover here because rtrequest will not do any of
+                                * the work necessary to add the route if it can't
+                                * find an interface.  As long as there is a default
+                                * route that leads to some interface, rtrequest will
+                                * find an interface, so this problem should be
+                                * rarely encountered.
+                                * dwiggins@bbn.com
+                                */
+       
+                               rt_setif(saved_nrt, ifpaddr, ifaaddr, gate);
 #endif
-                       rt_setmetrics(rtm->rtm_inits,
-                               &rtm->rtm_rmx, &saved_nrt->rt_rmx);
-                       saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
-                       saved_nrt->rt_rmx.rmx_locks |=
-                               (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
-                       rtunref(saved_nrt);
-                       saved_nrt->rt_genmask = genmask;
-               }
-               break;
-
-       case RTM_DELETE:
-               error = rtrequest(RTM_DELETE, dst, gate, netmask,
-                               rtm->rtm_flags, &saved_nrt);
-               if (error == 0) {
-                       if ((rt = saved_nrt))
-                               rtref(rt);
-                       goto report;
-               }
-               break;
-
-       case RTM_GET:
-       case RTM_CHANGE:
-       case RTM_LOCK:
-               if ((rnh = rt_tables[dst->sa_family]) == 0) {
-                       senderr(EAFNOSUPPORT);
-               } else if ((rt = (struct rtentry *)
-                               rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
-                       rtref(rt);
-               else
-                       senderr(ESRCH);
-               switch(rtm->rtm_type) {
-
-               case RTM_GET:
-               report:
-                       dst = rt_key(rt);
-                       gate = rt->rt_gateway;
-                       netmask = rt_mask(rt);
-                       genmask = rt->rt_genmask;
-                       if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
-                               ifp = rt->rt_ifp;
-                               if (ifp) {
-                                       ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
-                                       ifaaddr = rt->rt_ifa->ifa_addr;
-                                       rtm->rtm_index = ifp->if_index;
-                               } else {
-                                       ifpaddr = 0;
-                                       ifaaddr = 0;
-                           }
+                               rt_setmetrics(rtm->rtm_inits,
+                                       &rtm->rtm_rmx, &saved_nrt->rt_rmx);
+                               saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+                               saved_nrt->rt_rmx.rmx_locks |=
+                                       (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+                               rtunref(saved_nrt);
+                               saved_nrt->rt_genmask = genmask;
                        }
-                       len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
-                               (struct walkarg *)0);
-                       if (len > rtm->rtm_msglen) {
-                               struct rt_msghdr *new_rtm;
-                               R_Malloc(new_rtm, struct rt_msghdr *, len);
-                               if (new_rtm == 0)
-                                       senderr(ENOBUFS);
-                               Bcopy(rtm, new_rtm, rtm->rtm_msglen);
-                               Free(rtm); rtm = new_rtm;
+                       break;
+
+               case RTM_DELETE:
+                       error = rtrequest_locked(RTM_DELETE, dst, gate, netmask,
+                                       rtm->rtm_flags, &saved_nrt);
+                       if (error == 0) {
+                               rt = saved_nrt;
+                               goto report;
                        }
-                       (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
-                               (struct walkarg *)0);
-                       rtm->rtm_flags = rt->rt_flags;
-                       rtm->rtm_rmx = rt->rt_rmx;
-                       rtm->rtm_addrs = info.rti_addrs;
                        break;
 
+               case RTM_GET:
                case RTM_CHANGE:
-                       if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
-                               senderr(error);
-
-                       /*
-                        * If they tried to change things but didn't specify
-                        * the required gateway, then just use the old one.
-                        * This can happen if the user tries to change the
-                        * flags on the default route without changing the
-                        * default gateway.  Changing flags still doesn't work.
-                        */
-                       if ((rt->rt_flags & RTF_GATEWAY) && !gate)
-                               gate = rt->rt_gateway;
-
+               case RTM_LOCK:
+                       if ((rnh = rt_tables[dst->sa_family]) == 0) {
+                               senderr(EAFNOSUPPORT);
+                       } else if ((rt = (struct rtentry *)
+                                       rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
+                               rtref(rt);
+                       else
+                               senderr(ESRCH);
+                       switch(rtm->rtm_type) {
+
+                               case RTM_GET: {
+                                       struct ifaddr *ifa2;
+                               report:
+                                       dst = rt_key(rt);
+                                       gate = rt->rt_gateway;
+                                       netmask = rt_mask(rt);
+                                       genmask = rt->rt_genmask;
+                                       if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
+                                               ifp = rt->rt_ifp;
+                                               if (ifp) {
+                                                       ifnet_lock_shared(ifp);
+                                                       ifa2 = ifp->if_addrhead.tqh_first;
+                                                       ifpaddr = ifa2->ifa_addr;
+                                                       ifnet_lock_done(ifp);
+                                                       ifaaddr = rt->rt_ifa->ifa_addr;
+                                                       rtm->rtm_index = ifp->if_index;
+                                               } else {
+                                                       ifpaddr = 0;
+                                                       ifaaddr = 0;
+                                               }
+                                       }
+                                       len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
+                                               (struct walkarg *)0);
+                                       if (len > rtm->rtm_msglen) {
+                                               struct rt_msghdr *new_rtm;
+                                               R_Malloc(new_rtm, struct rt_msghdr *, len);
+                                               if (new_rtm == 0) {
+                                                       senderr(ENOBUFS);
+                                               }
+                                               Bcopy(rtm, new_rtm, rtm->rtm_msglen);
+                                               R_Free(rtm); rtm = new_rtm;
+                                       }
+                                       (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
+                                               (struct walkarg *)0);
+                                       rtm->rtm_flags = rt->rt_flags;
+                                       rtm->rtm_rmx = rt->rt_rmx;
+                                       rtm->rtm_addrs = info.rti_addrs;
+                                       }
+                                       break;
+
+                               case RTM_CHANGE:
+                                       if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
+                                               senderr(error);
+               
+                                       /*
+                                        * If they tried to change things but didn't specify
+                                        * the required gateway, then just use the old one.
+                                        * This can happen if the user tries to change the
+                                        * flags on the default route without changing the
+                                        * default gateway.  Changing flags still doesn't work.
+                                        */
+                                       if ((rt->rt_flags & RTF_GATEWAY) && !gate)
+                                               gate = rt->rt_gateway;
+               
 #ifdef __APPLE__
-                       /*
-                        * On Darwin, we call rt_setif which contains the
-                        * equivalent to the code found at this very spot
-                        * in BSD.
-                        */
-                       rt_setif(rt, ifpaddr, ifaaddr, gate);
+                                       /*
+                                        * On Darwin, we call rt_setif which contains the
+                                        * equivalent to the code found at this very spot
+                                        * in BSD.
+                                        */
+                                       rt_setif(rt, ifpaddr, ifaaddr, gate);
 #endif
-
-                       rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
-                                       &rt->rt_rmx);
+               
+                                       rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
+                                                       &rt->rt_rmx);
 #ifndef __APPLE__
-                       /* rt_setif, called above does this for us on darwin */
-                       if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
-                              rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
+                                       /* rt_setif, called above does this for us on darwin */
+                                       if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+                                                  rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
 #endif
-                       if (genmask)
-                               rt->rt_genmask = genmask;
-                       /*
-                        * Fall into
-                        */
-               case RTM_LOCK:
-                       rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
-                       rt->rt_rmx.rmx_locks |=
-                               (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+                                       if (genmask)
+                                               rt->rt_genmask = genmask;
+                                       /*
+                                        * Fall into
+                                        */
+                               case RTM_LOCK:
+                                       rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+                                       rt->rt_rmx.rmx_locks |=
+                                               (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+                                       break;
+                               }
                        break;
-               }
-               break;
-
-       default:
-               senderr(EOPNOTSUPP);
+       
+               default:
+                       senderr(EOPNOTSUPP);
        }
-
 flush:
        if (rtm) {
                if (error)
@@ -563,16 +568,18 @@ flush:
                        rtm->rtm_flags |= RTF_DONE;
        }
        if (rt)
-               rtfree(rt);
+               rtfree_locked(rt);
+       lck_mtx_unlock(rt_mtx);
+       socket_lock(so, 0);     /* relock the socket now */
     {
-       register struct rawcb *rp = 0;
+       struct rawcb *rp = 0;
        /*
         * Check to see if we don't want our own messages.
         */
        if ((so->so_options & SO_USELOOPBACK) == 0) {
                if (route_cb.any_count <= 1) {
                        if (rtm)
-                               Free(rtm);
+                               R_Free(rtm);
                        m_freem(m);
                        return (error);
                }
@@ -586,22 +593,25 @@ flush:
                        m = NULL;
                } else if (m->m_pkthdr.len > rtm->rtm_msglen)
                        m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
-               Free(rtm);
+               R_Free(rtm);
        }
        if (sendonlytoself && m) {
-               if (sbappendaddr(&so->so_rcv, &route_src, m, (struct mbuf*)0) == 0) {
-                       m_freem(m);
-                       error = ENOBUFS;
-               } else {
+               error = 0;
+               if (sbappendaddr(&so->so_rcv, &route_src, m, (struct mbuf*)0, &error) != 0) {
                        sorwakeup(so);
                }
+               if (error)
+                       return error;
        } else {
                if (rp)
                        rp->rcb_proto.sp_family = 0; /* Avoid us */
                if (dst)
                        route_proto.sp_protocol = dst->sa_family;
-               if (m)
+               if (m) {
+                       socket_unlock(so, 0);
                        raw_input(m, &route_proto, &route_src, &route_dst);
+                       socket_lock(so, 0);
+               }
                if (rp)
                        rp->rcb_proto.sp_family = PF_ROUTE;
                }
@@ -610,9 +620,7 @@ flush:
 }
 
 static void
-rt_setmetrics(which, in, out)
-       u_long which;
-       register struct rt_metrics *in, *out;
+rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
 {
 #define metric(f, e) if (which & (f)) out->e = in->e;
        metric(RTV_RPIPE, rmx_recvpipe);
@@ -630,30 +638,57 @@ rt_setmetrics(which, in, out)
  * Set route's interface given ifpaddr, ifaaddr, and gateway.
  */
 static void
-rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
-       struct rtentry *rt;
-       struct sockaddr *Ifpaddr, *Ifaaddr, *Gate;
+rt_setif(
+       struct rtentry *rt,
+       struct sockaddr *Ifpaddr,
+       struct sockaddr *Ifaaddr,
+       struct sockaddr *Gate)
 {
        struct ifaddr *ifa = 0;
        struct ifnet  *ifp = 0;
 
+       lck_mtx_assert(rt_mtx, LCK_MTX_ASSERT_OWNED);
+
+       /* trigger route cache reevaluation */
+       if (use_routegenid)
+               route_generation++;
+
        /* new gateway could require new ifaddr, ifp;
           flags may also be different; ifp may be specified
           by ll sockaddr when protocol address is ambiguous */
        if (Ifpaddr && (ifa = ifa_ifwithnet(Ifpaddr)) &&
-           (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate))
+           (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate)) {
+           ifafree(ifa);
                ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate,
                                        ifp);
-       else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
-               ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) :
-                               TAILQ_FIRST(&ifp->if_addrhead);
        }
-       else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
-                (Gate && (ifa = ifa_ifwithroute(rt->rt_flags,
-                                       rt_key(rt), Gate))))
-               ifp = ifa->ifa_ifp;
+       else
+       {
+               if (ifa) {
+                       ifafree(ifa);
+                       ifa = 0;
+               }
+               if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
+                       if (Gate) {
+                               ifa = ifaof_ifpforaddr(Gate, ifp);
+                       }
+                       else {
+                               ifnet_lock_shared(ifp);
+                               ifa = TAILQ_FIRST(&ifp->if_addrhead);
+                               ifaref(ifa);
+                               ifnet_lock_done(ifp);
+                       }
+               }
+               else if (Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) {
+                       ifp = ifa->ifa_ifp;
+               }
+               else if (Gate && (ifa = ifa_ifwithroute_locked(rt->rt_flags,
+                                               rt_key(rt), Gate))) {
+                       ifp = ifa->ifa_ifp;
+               }
+       }
        if (ifa) {
-               register struct ifaddr *oifa = rt->rt_ifa;
+               struct ifaddr *oifa = rt->rt_ifa;
                if (oifa != ifa) {
                    if (oifa && oifa->ifa_rtrequest)
                        oifa->ifa_rtrequest(RTM_DELETE,
@@ -663,8 +698,11 @@ rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
                    rt->rt_rmx.rmx_mtu = ifp->if_mtu;
                    if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
-               } else
+               } else {
+                       ifafree(ifa);
                        goto call_ifareq;
+               }
+               ifafree(ifa);
                return;
        }
       call_ifareq:
@@ -685,12 +723,10 @@ rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
  * This data is derived straight from userland.
  */
 static int
-rt_xaddrs(cp, cplim, rtinfo)
-       register caddr_t cp, cplim;
-       register struct rt_addrinfo *rtinfo;
+rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
 {
-       register struct sockaddr *sa;
-       register int i;
+       struct sockaddr *sa;
+       int i;
 
        bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
@@ -724,14 +760,14 @@ rt_xaddrs(cp, cplim, rtinfo)
 }
 
 static struct mbuf *
-rt_msg1(type, rtinfo)
-       int type;
-       register struct rt_addrinfo *rtinfo;
+rt_msg1(
+       int type,
+       struct rt_addrinfo *rtinfo)
 {
-       register struct rt_msghdr *rtm;
-       register struct mbuf *m;
-       register int i;
-       register struct sockaddr *sa;
+       struct rt_msghdr *rtm;
+       struct mbuf *m;
+       int i;
+       struct sockaddr *sa;
        int len, dlen;
 
        switch (type) {
@@ -788,13 +824,9 @@ rt_msg1(type, rtinfo)
 }
 
 static int
-rt_msg2(type, rtinfo, cp, w)
-       int type;
-       register struct rt_addrinfo *rtinfo;
-       caddr_t cp;
-       struct walkarg *w;
+rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
 {
-       register int i;
+       int i;
        int len, dlen, second_time = 0;
        caddr_t cp0;
 
@@ -807,10 +839,27 @@ again:
                len = sizeof(struct ifa_msghdr);
                break;
 
+       case RTM_DELMADDR:
+       case RTM_NEWMADDR:
+               len = sizeof(struct ifma_msghdr);
+               break;
+
        case RTM_IFINFO:
                len = sizeof(struct if_msghdr);
                break;
 
+       case RTM_IFINFO2:
+               len = sizeof(struct if_msghdr2);
+               break;
+
+       case RTM_NEWMADDR2:
+               len = sizeof(struct ifma_msghdr2);
+               break;
+
+       case RTM_GET2:
+               len = sizeof(struct rt_msghdr2);
+               break;
+
        default:
                len = sizeof(struct rt_msghdr);
        }
@@ -818,7 +867,7 @@ again:
        if (cp0)
                cp += len;
        for (i = 0; i < RTAX_MAX; i++) {
-               register struct sockaddr *sa;
+               struct sockaddr *sa;
 
                if ((sa = rtinfo->rti_info[i]) == 0)
                        continue;
@@ -831,7 +880,7 @@ again:
                len += dlen;
        }
        if (cp == 0 && w != NULL && !second_time) {
-               register struct walkarg *rw = w;
+               struct walkarg *rw = w;
 
                if (rw->w_req) {
                        if (rw->w_tmemsize < len) {
@@ -850,7 +899,7 @@ again:
                }
        }
        if (cp) {
-               register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
+               struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
 
                rtm->rtm_version = RTM_VERSION;
                rtm->rtm_type = type;
@@ -861,19 +910,19 @@ again:
 
 /*
  * This routine is called to generate a message from the routing
- * socket indicating that a redirect has occured, a routing lookup
+ * socket indicating that a redirect has occurred, a routing lookup
  * has failed, or that a protocol has detected timeouts to a particular
  * destination.
  */
 void
-rt_missmsg(type, rtinfo, flags, error)
-       int type, flags, error;
-       register struct rt_addrinfo *rtinfo;
+rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
 {
-       register struct rt_msghdr *rtm;
-       register struct mbuf *m;
+       struct rt_msghdr *rtm;
+       struct mbuf *m;
        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
 
+       lck_mtx_assert(rt_mtx, LCK_MTX_ASSERT_OWNED);
+
        if (route_cb.any_count == 0)
                return;
        m = rt_msg1(type, rtinfo);
@@ -892,10 +941,10 @@ rt_missmsg(type, rtinfo, flags, error)
  * socket indicating that the status of a network interface has changed.
  */
 void
-rt_ifmsg(ifp)
-       register struct ifnet *ifp;
+rt_ifmsg(
+       struct ifnet *ifp)
 {
-       register struct if_msghdr *ifm;
+       struct if_msghdr *ifm;
        struct mbuf *m;
        struct rt_addrinfo info;
 
@@ -908,7 +957,7 @@ rt_ifmsg(ifp)
        ifm = mtod(m, struct if_msghdr *);
        ifm->ifm_index = ifp->if_index;
        ifm->ifm_flags = (u_short)ifp->if_flags;
-       ifm->ifm_data = ifp->if_data;
+       if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
        ifm->ifm_addrs = 0;
        route_proto.sp_protocol = 0;
        raw_input(m, &route_proto, &route_src, &route_dst);
@@ -921,12 +970,12 @@ rt_ifmsg(ifp)
  * socket indicate a request to configure interfaces, then it will
  * be unnecessary as the routing socket will automatically generate
  * copies of it.
+ *
+ * Since this is coming from the interface, it is expected that the
+ * interface will be locked.
  */
 void
-rt_newaddrmsg(cmd, ifa, error, rt)
-       int cmd, error;
-       register struct ifaddr *ifa;
-       register struct rtentry *rt;
+rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
 {
        struct rt_addrinfo info;
        struct sockaddr *sa = 0;
@@ -940,7 +989,7 @@ rt_newaddrmsg(cmd, ifa, error, rt)
                bzero((caddr_t)&info, sizeof(info));
                if ((cmd == RTM_ADD && pass == 1) ||
                    (cmd == RTM_DELETE && pass == 2)) {
-                       register struct ifa_msghdr *ifam;
+                       struct ifa_msghdr *ifam;
                        int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
 
                        ifaaddr = sa = ifa->ifa_addr;
@@ -957,7 +1006,7 @@ rt_newaddrmsg(cmd, ifa, error, rt)
                }
                if ((cmd == RTM_ADD && pass == 2) ||
                    (cmd == RTM_DELETE && pass == 1)) {
-                       register struct rt_msghdr *rtm;
+                       struct rt_msghdr *rtm;
 
                        if (rt == 0)
                                continue;
@@ -983,9 +1032,7 @@ rt_newaddrmsg(cmd, ifa, error, rt)
  * there is no route state to worry about.
  */
 void
-rt_newmaddrmsg(cmd, ifma)
-       int cmd;
-       struct ifmultiaddr *ifma;
+rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
 {
        struct rt_addrinfo info;
        struct mbuf *m = 0;
@@ -1005,11 +1052,11 @@ rt_newmaddrmsg(cmd, ifma)
         * If a link-layer address is present, present it as a ``gateway''
         * (similarly to how ARP entries, e.g., are presented).
         */
-       gate = ifma->ifma_lladdr;
+       gate = ifma->ifma_ll->ifma_addr;
        if ((m = rt_msg1(cmd, &info)) == NULL)
                return;
        ifmam = mtod(m, struct ifma_msghdr *);
-       ifmam->ifmam_index = ifp->if_index;
+       ifmam->ifmam_index = ifp ? ifp->if_index : 0;
        ifmam->ifmam_addrs = info.rti_addrs;
        route_proto.sp_protocol = ifma->ifma_addr->sa_family;
        raw_input(m, &route_proto, &route_src, &route_dst);
@@ -1019,12 +1066,10 @@ rt_newmaddrmsg(cmd, ifma)
  * This is used in dumping the kernel table via sysctl().
  */
 int
-sysctl_dumpentry(rn, vw)
-       struct radix_node *rn;
-       void *vw;
+sysctl_dumpentry(struct radix_node *rn, void *vw)
 {
-       register struct walkarg *w = vw;
-       register struct rtentry *rt = (struct rtentry *)rn;
+       struct walkarg *w = vw;
+       struct rtentry *rt = (struct rtentry *)rn;
        int error = 0, size;
        struct rt_addrinfo info;
 
@@ -1035,65 +1080,158 @@ sysctl_dumpentry(rn, vw)
        gate = rt->rt_gateway;
        netmask = rt_mask(rt);
        genmask = rt->rt_genmask;
-       size = rt_msg2(RTM_GET, &info, 0, w);
-       if (w->w_req && w->w_tmem) {
-               register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
-
-               rtm->rtm_flags = rt->rt_flags;
-               rtm->rtm_use = rt->rt_use;
-               rtm->rtm_rmx = rt->rt_rmx;
-               rtm->rtm_index = rt->rt_ifp->if_index;
-               rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
-               rtm->rtm_addrs = info.rti_addrs;
-               error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
-               return (error);
+       if (w->w_op != NET_RT_DUMP2) {
+               size = rt_msg2(RTM_GET, &info, 0, w);
+               if (w->w_req && w->w_tmem) {
+                       struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
+
+                       rtm->rtm_flags = rt->rt_flags;
+                       rtm->rtm_use = rt->rt_use;
+                       rtm->rtm_rmx = rt->rt_rmx;
+                       rtm->rtm_index = rt->rt_ifp->if_index;
+                       rtm->rtm_pid = 0;
+                        rtm->rtm_seq = 0;
+                        rtm->rtm_errno = 0;
+                       rtm->rtm_addrs = info.rti_addrs;
+                       error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
+                       return (error);
+               }
+       } else {
+                size = rt_msg2(RTM_GET2, &info, 0, w);
+                if (w->w_req && w->w_tmem) {
+                        struct rt_msghdr2 *rtm = (struct rt_msghdr2 *)w->w_tmem;
+
+                        rtm->rtm_flags = rt->rt_flags;
+                        rtm->rtm_use = rt->rt_use;
+                        rtm->rtm_rmx = rt->rt_rmx;
+                        rtm->rtm_index = rt->rt_ifp->if_index;
+                        rtm->rtm_refcnt = rt->rt_refcnt;
+                       if (rt->rt_parent)
+                               rtm->rtm_parentflags = rt->rt_parent->rt_flags;
+                       else
+                               rtm->rtm_parentflags = 0;
+                        rtm->rtm_reserved = 0;
+                        rtm->rtm_addrs = info.rti_addrs;
+                        error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
+                        return (error);
+
+               }
        }
        return (error);
 }
 
 int
-sysctl_iflist(af, w)
-       int     af;
-       register struct walkarg *w;
+sysctl_iflist(
+       int     af,
+       struct  walkarg *w)
 {
-       register struct ifnet *ifp;
-       register struct ifaddr *ifa;
+       struct ifnet *ifp;
+       struct ifaddr *ifa;
        struct  rt_addrinfo info;
        int     len, error = 0;
 
        bzero((caddr_t)&info, sizeof(info));
-       for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
+       ifnet_head_lock_shared();
+       TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
+               if (error)
+                       break;
                if (w->w_arg && w->w_arg != ifp->if_index)
                        continue;
+               ifnet_lock_shared(ifp);
                ifa = ifp->if_addrhead.tqh_first;
                ifpaddr = ifa->ifa_addr;
                len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
                ifpaddr = 0;
                if (w->w_req && w->w_tmem) {
-                       register struct if_msghdr *ifm;
+                       struct if_msghdr *ifm;
 
                        ifm = (struct if_msghdr *)w->w_tmem;
                        ifm->ifm_index = ifp->if_index;
                        ifm->ifm_flags = (u_short)ifp->if_flags;
-                       ifm->ifm_data = ifp->if_data;
+                       if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
                        ifm->ifm_addrs = info.rti_addrs;
                        error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
-                       if (error)
-                               return (error);
+                       if (error) {
+                               ifnet_lock_done(ifp);
+                               break;
+                       }
                }
                while ((ifa = ifa->ifa_link.tqe_next) != 0) {
                        if (af && af != ifa->ifa_addr->sa_family)
                                continue;
-#ifndef __APPLE__
-                       if (curproc->p_prison && prison_if(curproc, ifa->ifa_addr))
+                       ifaaddr = ifa->ifa_addr;
+                       netmask = ifa->ifa_netmask;
+                       brdaddr = ifa->ifa_dstaddr;
+                       len = rt_msg2(RTM_NEWADDR, &info, 0, w);
+                       if (w->w_req && w->w_tmem) {
+                               struct ifa_msghdr *ifam;
+
+                               ifam = (struct ifa_msghdr *)w->w_tmem;
+                               ifam->ifam_index = ifa->ifa_ifp->if_index;
+                               ifam->ifam_flags = ifa->ifa_flags;
+                               ifam->ifam_metric = ifa->ifa_metric;
+                               ifam->ifam_addrs = info.rti_addrs;
+                               error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+                               if (error)
+                                       break;
+                       }
+               }
+               ifnet_lock_done(ifp);
+               ifaaddr = netmask = brdaddr = 0;
+       }
+       ifnet_head_done();
+       return error;
+}
+
+int
+sysctl_iflist2(
+       int     af,
+       struct  walkarg *w)
+{
+       struct ifnet *ifp;
+       struct ifaddr *ifa;
+       struct  rt_addrinfo info;
+       int     len, error = 0;
+       
+       bzero((caddr_t)&info, sizeof(info));
+       ifnet_head_lock_shared();
+       TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
+               if (error)
+                       break;
+               if (w->w_arg && w->w_arg != ifp->if_index)
+                       continue;
+               ifnet_lock_shared(ifp);
+               ifa = ifp->if_addrhead.tqh_first;
+               ifpaddr = ifa->ifa_addr;
+               len = rt_msg2(RTM_IFINFO2, &info, (caddr_t)0, w);
+               ifpaddr = 0;
+               if (w->w_req && w->w_tmem) {
+                       struct if_msghdr2 *ifm;
+
+                       ifm = (struct if_msghdr2 *)w->w_tmem;
+                       ifm->ifm_addrs = info.rti_addrs;
+                       ifm->ifm_flags = (u_short)ifp->if_flags;
+                       ifm->ifm_index = ifp->if_index;
+                       ifm->ifm_snd_len = ifp->if_snd.ifq_len;
+                       ifm->ifm_snd_maxlen = ifp->if_snd.ifq_maxlen;
+                       ifm->ifm_snd_drops = ifp->if_snd.ifq_drops;
+                       ifm->ifm_timer = ifp->if_timer;
+                       if_data_internal_to_if_data64(ifp, &ifp->if_data, &ifm->ifm_data);
+                       error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+                       if (error) {
+                               ifnet_lock_done(ifp);
+                               break;
+                       }
+               }
+               while ((ifa = ifa->ifa_link.tqe_next) != 0) {
+                       if (af && af != ifa->ifa_addr->sa_family)
                                continue;
-#endif
                        ifaaddr = ifa->ifa_addr;
                        netmask = ifa->ifa_netmask;
                        brdaddr = ifa->ifa_dstaddr;
                        len = rt_msg2(RTM_NEWADDR, &info, 0, w);
                        if (w->w_req && w->w_tmem) {
-                               register struct ifa_msghdr *ifam;
+                               struct ifa_msghdr *ifam;
 
                                ifam = (struct ifa_msghdr *)w->w_tmem;
                                ifam->ifam_index = ifa->ifa_ifp->if_index;
@@ -1102,21 +1240,81 @@ sysctl_iflist(af, w)
                                ifam->ifam_addrs = info.rti_addrs;
                                error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
                                if (error)
-                                       return (error);
+                                       break;
                        }
                }
+               if (error) {
+                       ifnet_lock_done(ifp);
+                       break;
+               }
+               {
+                       struct ifmultiaddr *ifma;
+                       
+                       for (ifma = ifp->if_multiaddrs.lh_first; ifma;
+                               ifma = ifma->ifma_link.le_next) {
+                               if (af && af != ifma->ifma_addr->sa_family)
+                                       continue;
+                               bzero((caddr_t)&info, sizeof(info));
+                               ifaaddr = ifma->ifma_addr;
+                               if (ifp->if_addrhead.tqh_first)
+                                       ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
+                               if (ifma->ifma_ll)
+                                       gate = ifma->ifma_ll->ifma_addr;
+                               len = rt_msg2(RTM_NEWMADDR2, &info, 0, w);
+                               if (w->w_req && w->w_tmem) {
+                                       struct ifma_msghdr2 *ifmam;
+
+                                       ifmam = (struct ifma_msghdr2 *)w->w_tmem;
+                                       ifmam->ifmam_addrs = info.rti_addrs;
+                                       ifmam->ifmam_flags = 0;
+                                       ifmam->ifmam_index = ifma->ifma_ifp->if_index;
+                                       ifmam->ifmam_refcount = ifma->ifma_refcount;
+                                       error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+                                       if (error)
+                                               break;
+                               }
+                       }
+               }
+               ifnet_lock_done(ifp);
                ifaaddr = netmask = brdaddr = 0;
        }
-       return (0);
+       ifnet_head_done();
+       return error;
 }
 
+
+static int
+sysctl_rtstat(struct sysctl_req *req)
+{
+       int error;
+
+       error = SYSCTL_OUT(req, &rtstat, sizeof(struct rtstat));
+       if (error)
+               return (error);
+
+       return 0;
+}
+
+static int
+sysctl_rttrash(struct sysctl_req *req)
+{
+        int error;
+
+        error = SYSCTL_OUT(req, &rttrash, sizeof(rttrash));
+        if (error)
+                return (error);
+
+        return 0;
+}
+
+
 static int
 sysctl_rtsock SYSCTL_HANDLER_ARGS
 {
        int     *name = (int *)arg1;
        u_int   namelen = arg2;
-       register struct radix_node_head *rnh;
-       int     i, s, error = EINVAL;
+       struct radix_node_head *rnh;
+       int     i, error = EINVAL;
        u_char  af;
        struct  walkarg w;
 
@@ -1132,22 +1330,32 @@ sysctl_rtsock SYSCTL_HANDLER_ARGS
        w.w_arg = name[2];
        w.w_req = req;
 
-       s = splnet();
        switch (w.w_op) {
 
        case NET_RT_DUMP:
+       case NET_RT_DUMP2:
        case NET_RT_FLAGS:
+               lck_mtx_lock(rt_mtx);
                for (i = 1; i <= AF_MAX; i++)
                        if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
                            (error = rnh->rnh_walktree(rnh,
                                                        sysctl_dumpentry, &w)))
                                break;
+               lck_mtx_unlock(rt_mtx);
                break;
-
        case NET_RT_IFLIST:
                error = sysctl_iflist(af, &w);
+               break;
+       case NET_RT_IFLIST2:
+               error = sysctl_iflist2(af, &w);
+               break;
+       case NET_RT_STAT:
+               error = sysctl_rtstat(req);
+               break;
+       case NET_RT_TRASH:
+               error = sysctl_rttrash(req);
+               break;
        }
-       splx(s);
        if (w.w_tmem)
                FREE(w.w_tmem, M_RTABLE);
        return (error);
@@ -1166,13 +1374,18 @@ static struct protosw routesw[] = {
   0,           route_output,   raw_ctlinput,   0,
   0,
   raw_init,    0,              0,              0,
-  0, &route_usrreqs, 0, 0
+  0, 
+  &route_usrreqs,
+  0,                   0,              0,
+  { 0, 0 },    0,      { 0 }
 }
 };
 
 struct domain routedomain =
     { PF_ROUTE, "route", route_init, 0, 0,
-      routesw};
+      routesw, 
+      NULL, NULL, 0, 0, 0, 0, NULL, 0, 
+      { 0, 0 } };
 
 DOMAIN_SET(route);