/*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/appleapiopts.h>
#ifdef PRIVATE
+#include <netinet/ip_flowid.h>
+
+/* Apply ipv6 mask on ipv6 addr */
+#define APPLY_MASK(addr,mask) \
+ (addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \
+ (addr)->__u6_addr.__u6_addr32[1] &= (mask)->__u6_addr.__u6_addr32[1]; \
+ (addr)->__u6_addr.__u6_addr32[2] &= (mask)->__u6_addr.__u6_addr32[2]; \
+ (addr)->__u6_addr.__u6_addr32[3] &= (mask)->__u6_addr.__u6_addr32[3];
+
/*
* Definition of dummynet data structures. In the structures, I decided
* not to use the macros in <sys/queue.h> in the hope of making the code
* processing requirements.
*/
#ifdef KERNEL
+#include <net/if_var.h>
+#include <net/route.h>
#include <netinet/ip_var.h> /* for ip_out_args */
+#include <netinet/ip6.h> /* for ip6_out_args */
+#include <netinet/in.h>
+#include <netinet6/ip6_var.h> /* for ip6_out_args */
struct dn_pkt_tag {
- struct ip_fw *rule; /* matching rule */
- int dn_dir; /* action when packet comes out. */
+ struct ip_fw *dn_ipfw_rule; /* matching IPFW rule */
+ void *dn_pf_rule; /* matching PF rule */
+ int dn_dir; /* action when packet comes out. */
#define DN_TO_IP_OUT 1
#define DN_TO_IP_IN 2
#define DN_TO_BDG_FWD 3
-
- dn_key output_time; /* when the pkt is due for delivery */
- struct ifnet *ifp; /* interface, for ip_output */
- struct sockaddr_in *dn_dst ;
- struct route ro; /* route, for ip_output. MUST COPY */
- int flags ; /* flags, for ip_output (IPv6 ?) */
- struct ip_out_args ipoa; /* output args, for ip_output. MUST COPY */
+#define DN_TO_IP6_IN 4
+#define DN_TO_IP6_OUT 5
+ dn_key dn_output_time; /* when the pkt is due for delivery */
+ struct ifnet *dn_ifp; /* interface, for ip[6]_output */
+ union {
+ struct sockaddr_in _dn_dst;
+ struct sockaddr_in6 _dn_dst6 ;
+ } dn_dst_;
+#define dn_dst dn_dst_._dn_dst
+#define dn_dst6 dn_dst_._dn_dst6
+ union {
+ struct route _dn_ro; /* route, for ip_output. MUST COPY */
+ struct route_in6 _dn_ro6; /* route, for ip6_output. MUST COPY */
+ } dn_ro_;
+#define dn_ro dn_ro_._dn_ro
+#define dn_ro6 dn_ro_._dn_ro6
+ struct route_in6 dn_ro6_pmtu; /* for ip6_output */
+ struct ifnet *dn_origifp; /* for ip6_output */
+ u_int32_t dn_mtu; /* for ip6_output */
+ int dn_alwaysfrag; /* for ip6_output */
+ u_int32_t dn_unfragpartlen; /* for ip6_output */
+ struct ip6_exthdrs dn_exthdrs; /* for ip6_output */
+ int dn_flags ; /* flags, for ip[6]_output */
+ int dn_client;
+#define DN_CLIENT_IPFW 1
+#define DN_CLIENT_PF 2
+ union {
+ struct ip_out_args _dn_ipoa; /* output args, for ip_output. MUST COPY */
+ struct ip6_out_args _dn_ip6oa; /* output args, for ip_output. MUST COPY */
+ } dn_ipoa_;
+#define dn_ipoa dn_ipoa_._dn_ipoa
+#define dn_ip6oa dn_ipoa_._dn_ip6oa
};
#else
struct dn_pkt;
*/
struct dn_flow_queue {
struct dn_flow_queue *next ;
- struct ipfw_flow_id id ;
+ struct ip_flow_id id ;
struct mbuf *head, *tail ; /* queue of packets */
u_int len ;
int qsize ; /* queue size in slots or bytes */
int plr ; /* pkt loss rate (2^31-1 means 100%) */
- struct ipfw_flow_id flow_mask ;
+ struct ip_flow_id flow_mask ;
/* hash table of queues onto this flow_set */
int rq_size ; /* number of slots */
SLIST_HEAD(dn_pipe_head, dn_pipe);
-#ifdef KERNEL
-
+#ifdef BSD_KERNEL_PRIVATE
+extern uint32_t my_random(void);
void ip_dn_init(void); /* called from raw_ip.c:load_ipfw() */
typedef int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */
-typedef void ip_dn_ruledel_t(void *); /* ip_fw.c */
typedef int ip_dn_io_t(struct mbuf *m, int pipe_nr, int dir,
- struct ip_fw_args *fwa);
+ struct ip_fw_args *fwa, int );
extern ip_dn_ctl_t *ip_dn_ctl_ptr;
-extern ip_dn_ruledel_t *ip_dn_ruledel_ptr;
extern ip_dn_io_t *ip_dn_io_ptr;
+void dn_ipfw_rule_delete(void *);
#define DUMMYNET_LOADED (ip_dn_io_ptr != NULL)
#pragma pack(4)
struct dn_flow_queue_32 {
user32_addr_t next ;
- struct ipfw_flow_id id ;
+ struct ip_flow_id id ;
user32_addr_t head, tail ; /* queue of packets */
u_int len ;
int qsize ; /* queue size in slots or bytes */
int plr ; /* pkt loss rate (2^31-1 means 100%) */
- struct ipfw_flow_id flow_mask ;
+ struct ip_flow_id flow_mask ;
/* hash table of queues onto this flow_set */
int rq_size ; /* number of slots */
struct dn_flow_queue_64 {
user64_addr_t next ;
- struct ipfw_flow_id id ;
+ struct ip_flow_id id ;
user64_addr_t head, tail ; /* queue of packets */
u_int len ;
int qsize ; /* queue size in slots or bytes */
int plr ; /* pkt loss rate (2^31-1 means 100%) */
- struct ipfw_flow_id flow_mask ;
+ struct ip_flow_id flow_mask ;
/* hash table of queues onto this flow_set */
int rq_size ; /* number of slots */
struct dn_flow_set_64 fs ; /* used with fixed-rate flows */
};
-
-
/*
* Return the IPFW rule associated with the dummynet tag; if any.
* Make sure that the dummynet tag is not reused by lower layers.
KERNEL_TAG_TYPE_DUMMYNET, NULL);
if (mtag != NULL) {
mtag->m_tag_type = KERNEL_TAG_TYPE_NONE;
- return (((struct dn_pkt_tag *)(mtag+1))->rule);
+ return (((struct dn_pkt_tag *)(mtag+1))->dn_ipfw_rule);
} else
return (NULL);
}
-#endif /* KERNEL */
+#include <sys/eventhandler.h>
+/* Dummynet event handling declarations */
+extern struct eventhandler_lists_ctxt dummynet_evhdlr_ctxt;
+extern void dummynet_init(void);
+
+struct dn_pipe_mini_config {
+ uint32_t bandwidth;
+ uint32_t delay;
+ uint32_t plr;
+};
+
+struct dn_rule_mini_config {
+ uint32_t dir;
+ uint32_t af;
+ uint32_t proto;
+ /*
+ * XXX PF rules actually define ranges of ports and
+ * along with range goes an opcode ((not) equal to, less than
+ * greater than, etc.
+ * For now the following works assuming there's no port range
+ * and the rule is for specific port.
+ * Also the operation is assumed as equal to.
+ */
+ uint32_t src_port;
+ uint32_t dst_port;
+ char ifname[IFXNAMSIZ];
+};
+
+struct dummynet_event {
+ uint32_t dn_event_code;
+ union {
+ struct dn_pipe_mini_config _dnev_pipe_config;
+ struct dn_rule_mini_config _dnev_rule_config;
+ } dn_event;
+};
+
+#define dn_event_pipe_config dn_event._dnev_pipe_config
+#define dn_event_rule_config dn_event._dnev_rule_config
+
+extern void dummynet_event_enqueue_nwk_wq_entry(struct dummynet_event *);
+
+enum {
+ DUMMYNET_RULE_CONFIG,
+ DUMMYNET_RULE_DELETE,
+ DUMMYNET_PIPE_CONFIG,
+ DUMMYNET_PIPE_DELETE,
+ DUMMYNET_NLC_DISABLED,
+};
+
+enum { DN_INOUT, DN_IN, DN_OUT };
+/*
+ * The signature for the callback is:
+ * eventhandler_entry_arg __unused
+ * dummynet_event pointer to dummynet event object
+ */
+typedef void (*dummynet_event_fn) (struct eventhandler_entry_arg, struct dummynet_event *);
+EVENTHANDLER_DECLARE(dummynet_event, dummynet_event_fn);
+#endif /* BSD_KERNEL_PRIVATE */
#endif /* PRIVATE */
#endif /* _IP_DUMMYNET_H */