]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/route.h
xnu-1504.3.12.tar.gz
[apple/xnu.git] / bsd / net / route.h
index e4644cbbb79f91281a1e45077999ff0b061a58e7..b2bcea3b888797908b6f717aa9a1f7d39c998063 100644 (file)
@@ -1,31 +1,29 @@
 /*
- * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * @APPLE_LICENSE_OSREFERENCE_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. 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.
  * 
- * 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 
+ * 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@
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -66,6 +64,7 @@
 #ifndef _NET_ROUTE_H_
 #define _NET_ROUTE_H_
 #include <sys/appleapiopts.h>
+#include <stdint.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
 #ifdef PRIVATE
 struct  rtentry;
 struct route {
-       struct  rtentry *ro_rt;
-       struct  sockaddr ro_dst;
-       u_long  reserved[2];    /* for future use if needed */
+       /*
+        * N.B: struct route must begin with ro_rt and ro_flags
+        * because the code does some casts of a 'struct route_in6 *'
+        * to a 'struct route *'.
+        */
+       struct rtentry  *ro_rt;
+       uint32_t        ro_flags;       /* route flags (see below) */
+       struct sockaddr ro_dst;
 };
+
+#define        ROF_SRCIF_SELECTED      0x1 /* source interface was selected */
+
 #else
 struct route;
 #endif /* PRIVATE */
@@ -97,30 +104,23 @@ struct route;
  * retransmission behavior and are included in the routing structure.
  */
 struct rt_metrics {
-       u_long  rmx_locks;      /* Kernel must leave these values alone */
-       u_long  rmx_mtu;        /* MTU for this path */
-       u_long  rmx_hopcount;   /* max hops expected */
-       int32_t rmx_expire;     /* lifetime for route, e.g. redirect */
-       u_long  rmx_recvpipe;   /* inbound delay-bandwidth product */
-       u_long  rmx_sendpipe;   /* outbound delay-bandwidth product */
-       u_long  rmx_ssthresh;   /* outbound gateway buffer limit */
-       u_long  rmx_rtt;        /* estimated round trip time */
-       u_long  rmx_rttvar;     /* estimated rtt variance */
-       u_long  rmx_pksent;     /* packets sent using this route */
-       u_long  rmx_filler[4];  /* will be used for T/TCP later */
+       u_int32_t       rmx_locks;      /* Kernel must leave these values alone */
+       u_int32_t       rmx_mtu;        /* MTU for this path */
+       u_int32_t       rmx_hopcount;   /* max hops expected */
+       int32_t         rmx_expire;     /* lifetime for route, e.g. redirect */
+       u_int32_t       rmx_recvpipe;   /* inbound delay-bandwidth product */
+       u_int32_t       rmx_sendpipe;   /* outbound delay-bandwidth product */
+       u_int32_t       rmx_ssthresh;   /* outbound gateway buffer limit */
+       u_int32_t       rmx_rtt;        /* estimated round trip time */
+       u_int32_t       rmx_rttvar;     /* estimated rtt variance */
+       u_int32_t       rmx_pksent;     /* packets sent using this route */
+       u_int32_t       rmx_filler[4];  /* will be used for T/TCP later */
 };
 
 /*
  * rmx_rtt and rmx_rttvar are stored as microseconds;
- * RTTTOPRHZ(rtt) converts to a value suitable for use
- * by a protocol slowtimo counter.
  */
 #define        RTM_RTTUNIT     1000000 /* units for rtt, rttvar, as units per sec */
-#define        RTTTOPRHZ(r)    ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
-
-/*
- * XXX kernel function pointer `rt_output' is visible to applications.
- */
 
 /*
  * We distinguish between routes to hosts and routes to networks,
@@ -130,51 +130,40 @@ struct rt_metrics {
  * gateways are marked so that the output routines know to address the
  * gateway rather than the ultimate destination.
  */
-#ifdef PRIVATE
+#ifdef KERNEL_PRIVATE
+#include <kern/locks.h>
 #ifndef RNF_NORMAL
 #include <net/radix.h>
 #endif
+/*
+ * Kernel routing entry structure (private).
+ */
 struct rtentry {
        struct  radix_node rt_nodes[2]; /* tree glue, and other values */
 #define        rt_key(r)       ((struct sockaddr *)((r)->rt_nodes->rn_key))
 #define        rt_mask(r)      ((struct sockaddr *)((r)->rt_nodes->rn_mask))
        struct  sockaddr *rt_gateway;   /* value */
        int32_t rt_refcnt;              /* # held references */
-       u_long  rt_flags;               /* up/down?, host/net */
+       uint32_t rt_flags;              /* up/down?, host/net */
        struct  ifnet *rt_ifp;          /* the answer: interface to use */
-        u_long  rt_dlt;                        /* DLIL dl_tag */
-       struct  ifaddr *rt_ifa;         /* the answer: interface to use */
+       struct  ifaddr *rt_ifa;         /* the answer: interface addr to use */
        struct  sockaddr *rt_genmask;   /* for generation of cloned routes */
-       caddr_t rt_llinfo;              /* pointer to link level info cache */
+       void    *rt_llinfo;             /* pointer to link level info cache */
+       void    (*rt_llinfo_free)(void *); /* link level info free function */
        struct  rt_metrics rt_rmx;      /* metrics used by rx'ing protocols */
        struct  rtentry *rt_gwroute;    /* implied entry for gatewayed routes */
-       int     (*rt_output)(struct ifnet *, struct mbuf *,
-                                 struct sockaddr *, struct rtentry *);
-                                       /* output routine for this (rt,if) */
-       struct  rtentry *rt_parent;     /* cloning parent of this route */
-       u_long  generation_id;          /* route generation id */
-};
-#endif /* PRIVATE */
-
-#ifdef __APPLE_API_OBSOLETE
-/*
- * Following structure necessary for 4.3 compatibility;
- * We should eventually move it to a compat file.
- */
-struct ortentry {
-       u_long  rt_hash;                /* to speed lookups */
-       struct  sockaddr rt_dst;        /* key */
-       struct  sockaddr rt_gateway;    /* value */
-       short   rt_flags;               /* up/down?, host/net */
-       short   rt_refcnt;              /* # held references */
-       u_long  rt_use;                 /* raw # packets forwarded */
-       struct  ifnet *rt_ifp;          /* the answer: interface to use */
+       struct  rtentry *rt_parent;     /* cloning parent of this route */
+       uint32_t generation_id;         /* route generation id */
+       /*
+        * See bsd/net/route.c for synchronization notes.
+        */
+       decl_lck_mtx_data(, rt_lock);   /* lock for routing entry */
 };
-#endif /* __APPLE_API_OBSOLETE */
+#endif /* KERNEL_PRIVATE */
 
-#ifdef PRIVATE
+#ifdef KERNEL_PRIVATE
 #define rt_use rt_rmx.rmx_pksent
-#endif /* PRIVATE */
+#endif /* KERNEL_PRIVATE */
 
 #define        RTF_UP          0x1             /* route usable */
 #define        RTF_GATEWAY     0x2             /* destination is a gateway */
@@ -197,10 +186,12 @@ struct ortentry {
 #define RTF_PROTO3     0x40000         /* protocol specific routing flag */
                                        /* 0x80000 unused */
 #define RTF_PINNED     0x100000        /* future use */
-#define        RTF_LOCAL       0x200000        /* route represents a local address */
+#define        RTF_LOCAL       0x200000        /* route represents a local address */
 #define        RTF_BROADCAST   0x400000        /* route represents a bcast address */
 #define        RTF_MULTICAST   0x800000        /* route represents a mcast address */
-                                       /* 0x1000000 and up unassigned */
+#define RTF_IFSCOPE    0x1000000       /* has valid interface scope */
+#define RTF_CONDEMNED  0x2000000       /* defunct; no longer modifiable */
+                                       /* 0x4000000 and up unassigned */
 
 /*
  * Routing statistics.
@@ -217,33 +208,33 @@ struct    rtstat {
  * Structures for routing messages.
  */
 struct rt_msghdr {
-       u_short rtm_msglen;     /* to skip over non-understood messages */
-       u_char  rtm_version;    /* future binary compatibility */
-       u_char  rtm_type;       /* message type */
-       u_short rtm_index;      /* index for associated ifp */
-       int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */
-       int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */
-       pid_t   rtm_pid;        /* identify sender */
-       int     rtm_seq;        /* for sender to identify action */
-       int     rtm_errno;      /* why failed */
-       int     rtm_use;        /* from rtentry */
-       u_long  rtm_inits;      /* which metrics we are initializing */
-       struct  rt_metrics rtm_rmx; /* metrics themselves */
+       u_short rtm_msglen;             /* to skip over non-understood messages */
+       u_char  rtm_version;            /* future binary compatibility */
+       u_char  rtm_type;               /* message type */
+       u_short rtm_index;              /* index for associated ifp */
+       int     rtm_flags;              /* flags, incl. kern & message, e.g. DONE */
+       int     rtm_addrs;              /* bitmask identifying sockaddrs in msg */
+       pid_t   rtm_pid;                /* identify sender */
+       int     rtm_seq;                /* for sender to identify action */
+       int     rtm_errno;              /* why failed */
+       int     rtm_use;                /* from rtentry */
+       u_int32_t rtm_inits;            /* which metrics we are initializing */
+       struct rt_metrics rtm_rmx;      /* metrics themselves */
 };
 
 struct rt_msghdr2 {
-        u_short rtm_msglen;     /* to skip over non-understood messages */
-        u_char  rtm_version;    /* future binary compatibility */
-        u_char  rtm_type;       /* message type */
-        u_short rtm_index;      /* index for associated ifp */
-        int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */
-        int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */
-       int32_t rtm_refcnt;         /* reference count */
-       int     rtm_parentflags;      /* flags of the parent route */
-        int     rtm_reserved;      /* reserved field set to 0 */
-        int     rtm_use;        /* from rtentry */
-        u_long  rtm_inits;      /* which metrics we are initializing */
-        struct  rt_metrics rtm_rmx; /* metrics themselves */
+       u_short rtm_msglen;             /* to skip over non-understood messages */
+       u_char  rtm_version;            /* future binary compatibility */
+       u_char  rtm_type;               /* message type */
+       u_short rtm_index;              /* index for associated ifp */
+       int     rtm_flags;              /* flags, incl. kern & message, e.g. DONE */
+       int     rtm_addrs;              /* bitmask identifying sockaddrs in msg */
+       int32_t rtm_refcnt;             /* reference count */
+       int     rtm_parentflags;        /* flags of the parent route */
+       int     rtm_reserved;           /* reserved field set to 0 */
+       int     rtm_use;                /* from rtentry */
+       u_int32_t rtm_inits;            /* which metrics we are initializing */
+       struct rt_metrics rtm_rmx;      /* metrics themselves */
 };
 
 
@@ -270,7 +261,7 @@ struct rt_msghdr2 {
 #define        RTM_DELMADDR    0x10    /* mcast group membership being deleted */
 #ifdef PRIVATE
 #define RTM_GET_SILENT 0x11
-#endif PRIVATE
+#endif /* PRIVATE */
 #define RTM_IFINFO2    0x12    /* */
 #define RTM_NEWMADDR2  0x13    /* */
 #define RTM_GET2       0x14    /* */
@@ -326,45 +317,162 @@ struct route_cb {
        int     any_count;
 };
 
+#ifdef PRIVATE
+/*
+ * For scoped routing; a zero interface scope value means nil/no scope.
+ */
+#define        IFSCOPE_NONE    0
+#endif /* PRIVATE */
+
 #ifdef KERNEL_PRIVATE
-#define RTFREE(rt)     rtfree(rt)
+/*
+ * Generic call trace used by some subsystems (e.g. route, ifaddr)
+ */
+#define        CTRACE_STACK_SIZE       8               /* depth of stack trace */
+#define        CTRACE_HIST_SIZE        4               /* refcnt history size */
+typedef struct ctrace {
+       void    *th;                            /* thread ptr */
+       void    *pc[CTRACE_STACK_SIZE];         /* PC stack trace */
+} ctrace_t;
+
+extern void ctrace_record(ctrace_t *);
+
+#define        RT_LOCK_ASSERT_HELD(_rt)                                        \
+       lck_mtx_assert(&(_rt)->rt_lock, LCK_MTX_ASSERT_OWNED)
+
+#define        RT_LOCK_ASSERT_NOTHELD(_rt)                                     \
+       lck_mtx_assert(&(_rt)->rt_lock, LCK_MTX_ASSERT_NOTOWNED)
+
+#define        RT_LOCK(_rt) do {                                               \
+       if (!rte_debug)                                                 \
+               lck_mtx_lock(&(_rt)->rt_lock);                          \
+       else                                                            \
+               rt_lock(_rt, FALSE);                                    \
+} while (0)
+
+#define        RT_LOCK_SPIN(_rt) do {                                          \
+       if (!rte_debug)                                                 \
+               lck_mtx_lock_spin(&(_rt)->rt_lock);                     \
+       else                                                            \
+               rt_lock(_rt, TRUE);                                     \
+} while (0)
+
+#define        RT_CONVERT_LOCK(_rt) do {                                       \
+       RT_LOCK_ASSERT_HELD(_rt);                                       \
+       lck_mtx_convert_spin(&(_rt)->rt_lock);                          \
+} while (0)
+
+#define        RT_UNLOCK(_rt) do {                                             \
+       if (!rte_debug)                                                 \
+               lck_mtx_unlock(&(_rt)->rt_lock);                        \
+       else                                                            \
+               rt_unlock(_rt);                                         \
+} while (0)
+
+#define        RT_ADDREF_LOCKED(_rt) do {                                      \
+       if (!rte_debug) {                                               \
+               RT_LOCK_ASSERT_HELD(_rt);                               \
+               if (++(_rt)->rt_refcnt == 0)                            \
+                       panic("RT_ADDREF(%p) bad refcnt\n", _rt);       \
+       } else {                                                        \
+               rtref(_rt);                                             \
+       }                                                               \
+} while (0)
+
+/*
+ * Spin variant mutex is used here; caller is responsible for
+ * converting any previously-held similar lock to full mutex.
+ */
+#define        RT_ADDREF(_rt) do {                                             \
+       RT_LOCK_SPIN(_rt);                                              \
+       RT_ADDREF_LOCKED(_rt);                                          \
+       RT_UNLOCK(_rt);                                                 \
+} while (0)
+
+#define        RT_REMREF_LOCKED(_rt) do {                                      \
+       if (!rte_debug) {                                               \
+               RT_LOCK_ASSERT_HELD(_rt);                               \
+               if ((_rt)->rt_refcnt == 0)                              \
+                       panic("RT_REMREF(%p) bad refcnt\n", _rt);       \
+               --(_rt)->rt_refcnt;                                     \
+       } else {                                                        \
+               (void) rtunref(_rt);                                    \
+       }                                                               \
+} while (0)
+
+/*
+ * Spin variant mutex is used here; caller is responsible for
+ * converting any previously-held similar lock to full mutex.
+ */
+#define        RT_REMREF(_rt) do {                                             \
+       RT_LOCK_SPIN(_rt);                                              \
+       RT_REMREF_LOCKED(_rt);                                          \
+       RT_UNLOCK(_rt);                                                 \
+} while (0)
+
+#define RTFREE(_rt)            rtfree(_rt)
+#define RTFREE_LOCKED(_rt)     rtfree_locked(_rt)
+
 extern struct route_cb route_cb;
 extern struct radix_node_head *rt_tables[AF_MAX+1];
+__private_extern__ lck_mtx_t *rnh_lock;
+__private_extern__ int use_routegenid;
+__private_extern__ uint32_t route_generation;
+__private_extern__ int rttrash;
+__private_extern__ unsigned int rte_debug;
 
 struct ifmultiaddr;
 struct proc;
 
-void    route_init(void);
-void    rt_ifmsg(struct ifnet *);
-void    rt_missmsg(int, struct rt_addrinfo *, int, int);
-void    rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
-void    rt_newmaddrmsg(int, struct ifmultiaddr *);
-int     rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
-void    rtalloc(struct route *);
-void    rtalloc_ign(struct route *, u_long);
-struct rtentry *
-        rtalloc1(struct sockaddr *, int, u_long);
-struct rtentry *
-        rtalloc1_locked(const struct sockaddr *, int, u_long);
-void   rtfree(struct rtentry *);
-void   rtfree_locked(struct rtentry *);
-void   rtref(struct rtentry *);
+extern void route_init(void) __attribute__((section("__TEXT, initcode")));
+extern void routegenid_update(void);
+extern void rt_ifmsg(struct ifnet *);
+extern void rt_missmsg(int, struct rt_addrinfo *, int, int);
+extern void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
+extern void rt_newmaddrmsg(int, struct ifmultiaddr *);
+extern int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
+extern void set_primary_ifscope(unsigned int);
+extern unsigned int get_primary_ifscope(void);
+extern boolean_t rt_inet_default(struct rtentry *, struct sockaddr *);
+extern struct rtentry *rt_lookup(boolean_t, struct sockaddr *,
+    struct sockaddr *, struct radix_node_head *, unsigned int);
+extern void rtalloc(struct route *);
+extern void rtalloc_ign(struct route *, uint32_t);
+extern void rtalloc_ign_locked(struct route *, uint32_t);
+extern void rtalloc_scoped_ign(struct route *, uint32_t, unsigned int);
+extern void rtalloc_scoped_ign_locked(struct route *, uint32_t, unsigned int);
+extern struct rtentry *rtalloc1(struct sockaddr *, int, uint32_t);
+extern struct rtentry *rtalloc1_locked(struct sockaddr *, int, uint32_t);
+extern struct rtentry *rtalloc1_scoped(struct sockaddr *, int, uint32_t,
+    unsigned int);
+extern struct rtentry *rtalloc1_scoped_locked(struct sockaddr *, int,
+    uint32_t, unsigned int);
+extern void rtfree(struct rtentry *);
+extern void rtfree_locked(struct rtentry *);
+extern void rtref(struct rtentry *);
 /*
  * rtunref will decrement the refcount, rtfree will decrement and free if
  * the refcount has reached zero and the route is not up.
  * Unless you have good reason to do otherwise, use rtfree.
  */
-void   rtunref(struct rtentry *);
-void   rtsetifa(struct rtentry *, struct ifaddr *);
-int     rtinit(struct ifaddr *, int, int);
-int     rtinit_locked(struct ifaddr *, int, int);
-int     rtioctl(int, caddr_t, struct proc *);
-void    rtredirect(struct sockaddr *, struct sockaddr *,
-           struct sockaddr *, int, struct sockaddr *, struct rtentry **);
-int     rtrequest(int, struct sockaddr *,
-           struct sockaddr *, struct sockaddr *, int, struct rtentry **);
-int     rtrequest_locked(int, struct sockaddr *,
-           struct sockaddr *, struct sockaddr *, int, struct rtentry **);
-#endif KERNEL_PRIVATE
+extern int rtunref(struct rtentry *);
+extern void rtsetifa(struct rtentry *, struct ifaddr *);
+extern int rtinit(struct ifaddr *, int, int);
+extern int rtinit_locked(struct ifaddr *, int, int);
+extern int rtioctl(unsigned long, caddr_t, struct proc *);
+extern void rtredirect(struct ifnet *, struct sockaddr *, struct sockaddr *,
+    struct sockaddr *, int, struct sockaddr *, struct rtentry **);
+extern int rtrequest(int, struct sockaddr *,
+    struct sockaddr *, struct sockaddr *, int, struct rtentry **);
+extern int rtrequest_locked(int, struct sockaddr *,
+    struct sockaddr *, struct sockaddr *, int, struct rtentry **);
+extern int rtrequest_scoped_locked(int, struct sockaddr *, struct sockaddr *,
+    struct sockaddr *, int, struct rtentry **, unsigned int);
+extern unsigned int sa_get_ifscope(struct sockaddr *);
+extern void rt_lock(struct rtentry *, boolean_t);
+extern void rt_unlock(struct rtentry *);
+extern struct sockaddr *rtm_scrub_ifscope(int, struct sockaddr *,
+    struct sockaddr *, struct sockaddr_storage *);
+#endif /* KERNEL_PRIVATE */
 
 #endif