summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>1998-12-14 18:09:13 +0000
committerluigi <luigi@FreeBSD.org>1998-12-14 18:09:13 +0000
commit4b628fa86de9e1f3e478283a0118b2209ccc5885 (patch)
tree1e45fc838f0be7bd575a8f9d8373624ff7318a2a /sys/netinet
parent78f32fa7e071a1e01b906f438ffe7454438b1730 (diff)
downloadFreeBSD-src-4b628fa86de9e1f3e478283a0118b2209ccc5885.zip
FreeBSD-src-4b628fa86de9e1f3e478283a0118b2209ccc5885.tar.gz
Last bits (i think) of dummynet for -current.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/if_ether.c12
-rw-r--r--sys/netinet/in.h7
-rw-r--r--sys/netinet/ip_dummynet.c115
-rw-r--r--sys/netinet/ip_dummynet.h10
-rw-r--r--sys/netinet/ip_fw.c270
-rw-r--r--sys/netinet/ip_fw.h11
-rw-r--r--sys/netinet/ip_input.c129
-rw-r--r--sys/netinet/ip_output.c107
-rw-r--r--sys/netinet/raw_ip.c24
9 files changed, 503 insertions, 182 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index ac8d86d..2dbc38c 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if_ether.c 8.1 (Berkeley) 6/10/93
- * $Id: if_ether.c,v 1.47 1998/06/12 03:48:14 julian Exp $
+ * $Id: if_ether.c,v 1.48 1998/09/17 00:04:21 fenner Exp $
*/
/*
@@ -41,6 +41,7 @@
*/
#include "opt_inet.h"
+#include "opt_bdg.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -461,7 +462,16 @@ in_arpinput(m)
(void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));
(void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));
for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next)
+#ifdef BRIDGE
+ /*
+ * For a bridge, we want to check the address irrespective
+ * of the receive interface. (This will change slightly
+ * when we have clusters of interfaces).
+ */
+ {
+#else
if (ia->ia_ifp == &ac->ac_if) {
+#endif
maybe_ia = ia;
if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
(isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 67e5851..1188bde 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
- * $Id: in.h,v 1.36 1998/07/06 03:20:12 julian Exp $
+ * $Id: in.h,v 1.37 1998/08/23 03:07:14 wollman Exp $
*/
#ifndef _NETINET_IN_H_
@@ -323,6 +323,11 @@ struct ip_opts {
#define IP_FW_GET 54 /* get entire firewall rule chain */
#define IP_NAT 55 /* set/get NAT opts */
+#define IP_DUMMYNET_CONFIGURE 60 /* add/configure a dummynet pipe */
+#define IP_DUMMYNET_DEL 61 /* delete a dummynet pipe from chain */
+#define IP_DUMMYNET_FLUSH 62 /* flush dummynet */
+#define IP_DUMMYNET_GET 64 /* get entire dummynet pipes */
+
/*
* Defaults and limits for options
*/
diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c
index 31b4249..9743a0a 100644
--- a/sys/netinet/ip_dummynet.c
+++ b/sys/netinet/ip_dummynet.c
@@ -10,7 +10,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_dummynet.c 1.2 1998/08/21 15:01:13 luigi Exp $
+ * $Id: ip_dummynet.c,v 1.1 1998/09/12 22:03:20 luigi Exp $
*/
/*
@@ -40,6 +40,7 @@
#include <sys/queue.h> /* XXX */
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/time.h>
#include <sys/sysctl.h>
#include <net/if.h>
@@ -68,7 +69,7 @@ SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, calls, CTLFLAG_RD, &dn_calls, 0, "")
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, idle, CTLFLAG_RD, &dn_idle, 0, "");
#endif
-static int ip_dn_ctl(int optname, struct mbuf **mm);
+static int ip_dn_ctl(struct sockopt *sopt);
static void dummynet(void);
static void dn_restart(void);
@@ -116,7 +117,7 @@ dn_move(struct dn_pipe *pipe, int immediate)
*/
if ( pipe->p.head == NULL &&
pipe->ticks_from_last_insert != pipe->delay) {
- printf("Warning, empty pipe and delay %d (should be %a)d\n",
+ printf("Warning, empty pipe and delay %d (should be %d)\n",
pipe->ticks_from_last_insert, pipe->delay);
pipe->ticks_from_last_insert = pipe->delay;
}
@@ -402,68 +403,77 @@ dn_rule_delete(void *r)
{
struct dn_pipe *q, *p = all_pipes ;
-
+ int matches = 0 ;
for ( p= all_pipes ; p ; p = p->next ) {
struct dn_pkt *x ;
for (x = p->r.head ; x ; x = (struct dn_pkt *)x->dn_next )
- if (x->hdr.mh_data == r)
+ if (x->hdr.mh_data == r) {
+ matches++ ;
x->hdr.mh_data = (void *)ip_fw_default_rule ;
+ }
for (x = p->p.head ; x ; x = (struct dn_pkt *)x->dn_next )
- if (x->hdr.mh_data == r)
+ if (x->hdr.mh_data == r) {
+ matches++ ;
x->hdr.mh_data = (void *)ip_fw_default_rule ;
}
}
+ printf("dn_rule_delete, r 0x%x, default 0x%x%s, %d matches\n",
+ r, ip_fw_default_rule,
+ r == ip_fw_default_rule ? " AARGH!":"", matches);
+}
/*
* handler for the various dummynet socket options
* (get, flush, config, del)
*/
static int
-ip_dn_ctl(int optname, struct mbuf **mm)
+ip_dn_ctl(struct sockopt *sopt)
{
- struct mbuf *m ;
- if (optname == IP_DUMMYNET_GET) {
- struct dn_pipe *p = all_pipes ;
- *mm = m = m_get(M_WAIT, MT_SOOPTS);
- m->m_len = 0 ;
- m->m_next = NULL ;
- for (; p ; p = p->next ) {
- struct dn_pipe *q = mtod(m,struct dn_pipe *) ;
- memcpy( m->m_data, p, sizeof(*p) );
+ int error = 0 ;
+ size_t size ;
+ char *buf, *bp ;
+ struct dn_pipe *p, *q, tmp_pipe ;
+
+ struct dn_pipe *x, *a, *b ;
+
+ /* Disallow sets in really-really secure mode. */
+ if (sopt->sopt_dir == SOPT_SET && securelevel >= 3)
+ return (EPERM);
+
+ switch (sopt->sopt_name) {
+ default :
+ panic("ip_dn_ctl -- unknown option");
+
+ case IP_DUMMYNET_GET :
+ for (p = all_pipes, size = 0 ; p ; p = p->next )
+ size += sizeof( *p ) ;
+ buf = malloc(size, M_TEMP, M_WAITOK);
+ if (buf == 0) {
+ error = ENOBUFS ;
+ break ;
+ }
+ for (p = all_pipes, bp = buf ; p ; p = p->next ) {
+ struct dn_pipe *q = (struct dn_pipe *)bp ;
+
+ bcopy(p, bp, sizeof( *p ) );
/*
* return bw and delay in bits/s and ms, respectively
*/
q->bandwidth *= (8*hz) ;
q->delay = (q->delay * 1000) / hz ;
-
- m->m_len = sizeof(*p) ;
- m->m_next = m_get(M_WAIT, MT_SOOPTS);
- m = m->m_next ;
- m->m_len = 0 ;
- }
- return 0 ;
+ bp += sizeof( *p ) ;
}
- if (securelevel > 2) { /* like in the firewall code... */
- if (m) (void)m_free(m);
- return (EPERM) ;
- }
- m = *mm ;
- if (optname == IP_DUMMYNET_FLUSH) {
+ error = sooptcopyout(sopt, buf, size);
+ FREE(buf, M_TEMP);
+ break ;
+ case IP_DUMMYNET_FLUSH :
dummynet_flush() ;
- if (m) (void)m_free(m);
- return 0 ;
- }
- if (!m) /* need an argument for the following */
- return (EINVAL);
- if (optname == IP_DUMMYNET_CONFIGURE) {
- struct dn_pipe *p = mtod(m,struct dn_pipe *) ;
- struct dn_pipe *x, *a, *b ;
- if (m->m_len != sizeof (*p) ) {
- printf("dn_pipe Invalid length, %d instead of %d\n",
- m->m_len, sizeof(*p) );
- (void)m_free(m);
- return (EINVAL);
- }
+ break ;
+ case IP_DUMMYNET_CONFIGURE :
+ p = &tmp_pipe ;
+ error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
+ if (error)
+ break ;
/*
* The config program passes parameters as follows:
* bandwidth = bits/second (0 = no limits);
@@ -509,7 +519,8 @@ ip_dn_ctl(int optname, struct mbuf **mm)
x = malloc(sizeof(struct dn_pipe), M_IPFW, M_DONTWAIT) ;
if (x == NULL) {
printf("ip_dummynet.c: sorry no memory\n");
- return (ENOSPC) ;
+ error = ENOSPC ;
+ break ;
}
bzero(x, sizeof(*x) );
x->bandwidth = p->bandwidth ;
@@ -528,12 +539,13 @@ ip_dn_ctl(int optname, struct mbuf **mm)
a->next = x ;
splx(s);
}
- (void)m_free(m);
- return 0 ;
- }
- if (optname == IP_DUMMYNET_DEL) {
- struct dn_pipe *p = mtod(m,struct dn_pipe *) ;
- struct dn_pipe *x, *a, *b ;
+ break ;
+
+ case IP_DUMMYNET_DEL :
+ p = &tmp_pipe ;
+ error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
+ if (error)
+ break ;
for (a = NULL , b = all_pipes ; b && b->pipe_nr < p->pipe_nr ;
a = b , b = b->next) ;
@@ -557,8 +569,9 @@ ip_dn_ctl(int optname, struct mbuf **mm)
purge_pipe(b); /* remove pkts from here */
free(b, M_IPFW);
}
+ break ;
}
- return 0 ;
+ return error ;
}
void
diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h
index 33833fc..f01406f 100644
--- a/sys/netinet/ip_dummynet.h
+++ b/sys/netinet/ip_dummynet.h
@@ -16,6 +16,8 @@
#ifndef _IP_DUMMYNET_H
#define _IP_DUMMYNET_H
+typedef int ip_dn_ctl_t __P((struct sockopt *)) ;
+extern ip_dn_ctl_t *ip_dn_ctl_ptr;
/*
* Definition of dummynet data structures.
* Dummynet handles a list of pipes, each one identified by a unique
@@ -85,12 +87,20 @@ struct dn_pipe { /* a pipe */
};
/*
+ * The following is used to define a new mbuf type that is
+ * prepended to the packet when it comes out of a pipe. The definition
+ * ought to go in /sys/sys/mbuf.h but here it is less intrusive.
+ */
+
+#define MT_DUMMYNET MT_CONTROL
+/*
* what to do of a packet when it comes out of a pipe
*/
#define DN_TO_IP_OUT 1
#define DN_TO_IP_IN 2
#define DN_TO_BDG_FWD 3
#ifdef KERNEL
+MALLOC_DECLARE(M_IPFW);
void ip_dn_init(void); /* called in ip_input.c */
void dn_rule_delete(void *r); /* used in ip_fw.c */
int dummynet_io(int pipe, int dir,
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index 8e818dc..d9069dc 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -12,15 +12,16 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.c,v 1.98 1998/11/15 15:33:52 bde Exp $
+ * $Id: ip_fw.c,v 1.96 1998/08/23 03:07:14 wollman Exp $
*/
/*
* Implement IP packet firewall
*/
-#if !defined(KLD_MODULE) && !defined(IPFIREWALL_MODULE)
+#ifndef IPFIREWALL_MODULE
#include "opt_ipfw.h"
+#include "opt_ipdn.h"
#include "opt_ipdivert.h"
#include "opt_inet.h"
#ifndef INET
@@ -43,18 +44,25 @@
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_fw.h>
+#ifdef DUMMYNET
+#include <net/route.h>
+#include <netinet/ip_dummynet.h>
+#endif
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>
#include <netinet/udp.h>
+#include <netinet/if_ether.h> /* XXX ethertype_ip */
+
static int fw_debug = 1;
#ifdef IPFIREWALL_VERBOSE
static int fw_verbose = 1;
#else
static int fw_verbose = 0;
#endif
+static int fw_one_pass = 0; /* XXX */
#ifdef IPFIREWALL_VERBOSE_LIMIT
static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
#else
@@ -63,13 +71,14 @@ static int fw_verbose_limit = 0;
#define IPFW_DEFAULT_RULE ((u_int)(u_short)~0)
-static LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
+LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
-static MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
+MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
#ifdef SYSCTL_NODE
SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, "");
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO,one_pass,CTLFLAG_RW, &fw_one_pass, 0, "");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, "");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_limit, 0, "");
#endif
@@ -100,8 +109,16 @@ static int icmptype_match __P((struct icmp * icmp, struct ip_fw * f));
static void ipfw_report __P((struct ip_fw *f, struct ip *ip,
struct ifnet *rif, struct ifnet *oif));
+static void flush_rule_ptrs(void);
+
+#ifdef IPFIREWALL_MODULE
+static ip_fw_chk_t *old_chk_ptr;
+static ip_fw_ctl_t *old_ctl_ptr;
+#endif
+
static int ip_fw_chk __P((struct ip **pip, int hlen,
struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
+ struct ip_fw_chain **flow_id,
struct sockaddr_in **next_hop));
static int ip_fw_ctl __P((struct sockopt *sopt));
@@ -279,6 +296,7 @@ static void
ipfw_report(struct ip_fw *f, struct ip *ip,
struct ifnet *rif, struct ifnet *oif)
{
+ if (ip) {
static u_int64_t counter;
struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl);
@@ -319,6 +337,11 @@ ipfw_report(struct ip_fw *f, struct ip *ip,
case IP_FW_F_SKIPTO:
printf("SkipTo %d", f->fw_skipto_rule);
break;
+#ifdef DUMMYNET
+ case IP_FW_F_PIPE:
+ printf("Pipe %d", f->fw_skipto_rule);
+ break;
+#endif
#ifdef IPFIREWALL_FORWARD
case IP_FW_F_FWD:
printf("Forward to ");
@@ -383,15 +406,45 @@ ipfw_report(struct ip_fw *f, struct ip *ip,
printf("ipfw: limit reached on rule #%d\n",
f ? f->fw_number : -1);
}
+}
+
+/*
+ * given an ip_fw_chain *, lookup_next_rule will return a pointer
+ * of the same type to the next one. This can be either the jump
+ * target (for skipto instructions) or the next one in the chain (in
+ * all other cases including a missing jump target).
+ * Backward jumps are not allowed, so start looking from the next
+ * rule...
+ */
+static struct ip_fw_chain * lookup_next_rule(struct ip_fw_chain *me);
+
+static struct ip_fw_chain *
+lookup_next_rule(struct ip_fw_chain *me)
+{
+ struct ip_fw_chain *chain ;
+ int rule = me->rule->fw_skipto_rule ; /* guess... */
+
+ if ( (me->rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_SKIPTO )
+ for (chain = me->chain.le_next; chain ; chain = chain->chain.le_next )
+ if (chain->rule->fw_number >= rule)
+ return chain ;
+ return me->chain.le_next ; /* failure or not a skipto */
+}
/*
* Parameters:
*
- * ip Pointer to packet header (struct ip *)
+ * pip Pointer to packet header (struct ip **)
+ * XXX future extension: pip = NULL means a complete ethernet packet
+ * including ethernet header in the mbuf. Other fields
+ * are ignored/invalid.
+ *
* hlen Packet header length
* oif Outgoing interface, or NULL if packet is incoming
* *cookie Skip up to the first rule past this rule number;
* *m The packet; we set to NULL when/if we nuke it.
+ * *flow_id pointer to the last matching rule (in/out)
+ * *next_hop socket we are forwarding to (in/out).
*
* Return value:
*
@@ -404,17 +457,58 @@ ipfw_report(struct ip_fw *f, struct ip *ip,
static int
ip_fw_chk(struct ip **pip, int hlen,
struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
+ struct ip_fw_chain **flow_id,
struct sockaddr_in **next_hop)
{
struct ip_fw_chain *chain;
struct ip_fw *rule = NULL;
- struct ip *ip = *pip;
+ struct ip *ip = NULL ;
struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
- u_short offset = (ip->ip_off & IP_OFFMASK);
+ u_short offset ;
u_short src_port, dst_port;
u_int16_t skipto = *cookie;
- *cookie = 0;
+ if (pip) { /* normal ip packet */
+ ip = *pip;
+ offset = (ip->ip_off & IP_OFFMASK);
+ } else { /* bridged or non-ip packet */
+ struct ether_header *eh = mtod(*m, struct ether_header *);
+ switch (ntohs(eh->ether_type)) {
+ case ETHERTYPE_IP :
+ if ((*m)->m_len<sizeof(struct ether_header) + sizeof(struct ip))
+ goto non_ip ;
+ ip = (struct ip *)(eh + 1 );
+ if (ip->ip_v != IPVERSION)
+ goto non_ip ;
+ hlen = ip->ip_hl << 2;
+ if (hlen < sizeof(struct ip)) /* minimum header length */
+ goto non_ip ;
+ if ((*m)->m_len < 14 + hlen + 14) {
+ printf("-- m_len %d, need more...\n", (*m)->m_len);
+ goto non_ip ;
+ }
+ offset = (ip->ip_off & IP_OFFMASK);
+ break ;
+ default :
+non_ip: ip = NULL ;
+ break ;
+ }
+ }
+
+ if (*flow_id) {
+ if (fw_one_pass)
+ return 0 ; /* accept if passed first test */
+ /*
+ * pkt has already been tagged. Look for the next rule
+ * to restart processing
+ */
+ chain = LIST_NEXT( *flow_id, chain);
+
+ if ( (chain = (*flow_id)->rule->next_rule_ptr) == NULL )
+ chain = (*flow_id)->rule->next_rule_ptr =
+ lookup_next_rule(*flow_id) ;
+ if (! chain) goto dropit;
+ } else {
/*
* Go down the chain, looking for enlightment
* If we've been asked to start at a given rule immediatly, do so.
@@ -428,8 +522,12 @@ ip_fw_chk(struct ip **pip, int hlen,
}
if (! chain) goto dropit;
}
+ }
+ *cookie = 0;
for (; chain; chain = LIST_NEXT(chain, chain)) {
- register struct ip_fw *const f = chain->rule;
+ register struct ip_fw * f ;
+again:
+ f = chain->rule;
if (oif) {
/* Check direction outbound */
@@ -440,6 +538,40 @@ ip_fw_chk(struct ip **pip, int hlen,
if (!(f->fw_flg & IP_FW_F_IN))
continue;
}
+ if (ip == NULL ) {
+ /*
+ * do relevant checks for non-ip packets:
+ * after this, only goto got_match or continue
+ */
+ struct ether_header *eh = mtod(*m, struct ether_header *);
+
+ /*
+ * make default rule always match or we have a panic
+ */
+ if (f->fw_number == IPFW_DEFAULT_RULE)
+ goto got_match ;
+ /*
+ * temporary hack:
+ * udp from 0.0.0.0 means this rule applies.
+ * 1 src port is match ether type
+ * 2 src ports (interval) is match ether type
+ * 3 src ports is match ether address
+ */
+ if ( f->fw_src.s_addr != 0 || f->fw_prot != IPPROTO_UDP)
+ continue;
+ switch (IP_FW_GETNSRCP(f)) {
+ case 1: /* match one type */
+ if ( /* ( (f->fw_flg & IP_FW_F_INVSRC) != 0) ^ */
+ ( f->fw_uar.fw_pts[0] == ntohs(eh->ether_type) ) ) {
+ printf("match!\n");
+ goto got_match ;
+ }
+ break ;
+ default:
+ break ;
+ }
+ continue ;
+ }
/* Fragments */
if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK))
@@ -489,12 +621,12 @@ ip_fw_chk(struct ip **pip, int hlen,
continue;
#define PULLUP_TO(len) do { \
- if ((*m)->m_len < (len) \
- && (*m = m_pullup(*m, (len))) == 0) { \
+ if ((*m)->m_len < (len) ) { \
+ if ( (*m = m_pullup(*m, (len))) == 0) \
goto bogusfrag; \
- } \
*pip = ip = mtod(*m, struct ip *); \
offset = (ip->ip_off & IP_OFFMASK); \
+ } \
} while (0)
/* Protocol specific checks */
@@ -578,9 +710,19 @@ bogusfrag:
}
got_match:
+ *flow_id = chain ; /* XXX set flow id */
/* Update statistics */
f->fw_pcnt += 1;
+ /*
+ * note -- bridged-ip packets still have some fields
+ * in network order, including ip_len
+ */
+ if (ip) {
+ if (pip)
f->fw_bcnt += ip->ip_len;
+ else
+ f->fw_bcnt += ntohs(ip->ip_len);
+ }
f->timestamp = time_second;
/* Log to console if desired */
@@ -593,9 +735,11 @@ got_match:
return(0);
case IP_FW_F_COUNT:
continue;
+#ifdef IPDIVERT
case IP_FW_F_DIVERT:
*cookie = f->fw_number;
return(f->fw_divert_port);
+#endif
case IP_FW_F_TEE:
/*
* XXX someday tee packet here, but beware that you
@@ -606,17 +750,17 @@ got_match:
* to write custom routine.
*/
continue;
- case IP_FW_F_SKIPTO:
-#ifdef DIAGNOSTIC
- while (LIST_NEXT(chain, chain)
- && LIST_NEXT(chain, chain)->rule->fw_number
- < f->fw_skipto_rule)
-#else
- while (LIST_NEXT(chain, chain)->rule->fw_number
- < f->fw_skipto_rule)
+ case IP_FW_F_SKIPTO: /* XXX check */
+ if ( f->next_rule_ptr )
+ chain = f->next_rule_ptr ;
+ else
+ chain = lookup_next_rule(chain) ;
+ if (! chain) goto dropit;
+ goto again ;
+#ifdef DUMMYNET
+ case IP_FW_F_PIPE:
+ return(f->fw_pipe_nr | 0x10000 );
#endif
- chain = LIST_NEXT(chain, chain);
- continue;
#ifdef IPFIREWALL_FORWARD
case IP_FW_F_FWD:
/* Change the next-hop address for this packet.
@@ -656,6 +800,7 @@ got_match:
* - The packet is not a multicast or broadcast packet
*/
if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
+ && ip
&& (ip->ip_p != IPPROTO_ICMP || is_icmp_query(ip))
&& !((*m)->m_flags & (M_BCAST|M_MCAST))
&& !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
@@ -698,7 +843,7 @@ dropit:
/*
* Finally, drop the packet.
*/
- *cookie = 0;
+ /* *cookie = 0; */ /* XXX is this necessary ? */
if (*m) {
m_freem(*m);
*m = NULL;
@@ -706,6 +851,22 @@ dropit:
return(0);
}
+/*
+ * when a rule is added/deleted, zero the direct pointers within
+ * all firewall rules. These will be reconstructed on the fly
+ * as packets are matched.
+ * Must be called at splnet().
+ */
+static void
+flush_rule_ptrs()
+{
+ struct ip_fw_chain *fcp ;
+
+ for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) {
+ fcp->rule->next_rule_ptr = NULL ;
+ }
+}
+
static int
add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
{
@@ -727,6 +888,8 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';
ftmp->fw_pcnt = 0L;
ftmp->fw_bcnt = 0L;
+ ftmp->next_rule_ptr = NULL ;
+ ftmp->pipe_ptr = NULL ;
fwc->rule = ftmp;
s = splnet();
@@ -763,6 +926,7 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
fcpl = fcp;
}
}
+ flush_rule_ptrs();
splx(s);
return (0);
@@ -786,6 +950,10 @@ del_entry(struct ip_fw_head *chainptr, u_short number)
next = LIST_NEXT(fcp, chain);
LIST_REMOVE(fcp, chain);
+#ifdef DUMMYNET
+ dn_rule_delete(fcp) ;
+#endif
+ flush_rule_ptrs();
free(fcp->rule, M_IPFW);
free(fcp, M_IPFW);
fcp = next;
@@ -941,6 +1109,7 @@ check_ipfw_struct(struct ip_fw *frwl)
}
break;
case IP_FW_F_DIVERT: /* Diverting to port zero is invalid */
+ case IP_FW_F_PIPE: /* piping through 0 is invalid */
case IP_FW_F_TEE:
if (frwl->fw_divert_port == 0) {
dprintf(("%s can't divert to port 0\n", err_prefix));
@@ -1049,12 +1218,15 @@ ip_fw_ctl(struct sockopt *sopt)
break;
default:
- panic("ip_fw_ctl");
+ printf("ip_fw_ctl invalid option %d\n", sopt->sopt_name);
+ error = EINVAL ;
}
return (error);
}
+struct ip_fw_chain *ip_fw_default_rule ;
+
void
ip_fw_init(void)
{
@@ -1077,6 +1249,7 @@ ip_fw_init(void)
add_entry(&ip_fw_chain, &default_rule))
panic("ip_fw_init");
+ ip_fw_default_rule = ip_fw_chain.lh_first ;
printf("IP packet filtering initialized, "
#ifdef IPDIVERT
"divert enabled, ");
@@ -1102,10 +1275,7 @@ ip_fw_init(void)
#endif
}
-static ip_fw_chk_t *old_chk_ptr;
-static ip_fw_ctl_t *old_ctl_ptr;
-
-#if defined(IPFIREWALL_MODULE) && !defined(KLD_MODULE)
+#ifdef IPFIREWALL_MODULE
#include <sys/exec.h>
#include <sys/sysent.h>
@@ -1152,48 +1322,4 @@ ipfw_mod(struct lkm_table *lkmtp, int cmd, int ver)
MOD_DISPATCH(ipfw, lkmtp, cmd, ver,
ipfw_load, ipfw_unload, lkm_nullcmd);
}
-#else
-static int
-ipfw_modevent(module_t mod, int type, void *unused)
-{
- int s;
-
- switch (type) {
- case MOD_LOAD:
- s = splnet();
-
- old_chk_ptr = ip_fw_chk_ptr;
- old_ctl_ptr = ip_fw_ctl_ptr;
-
- ip_fw_init();
- splx(s);
- return 0;
- case MOD_UNLOAD:
- s = splnet();
-
- ip_fw_chk_ptr = old_chk_ptr;
- ip_fw_ctl_ptr = old_ctl_ptr;
-
- while (LIST_FIRST(&ip_fw_chain) != NULL) {
- struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);
- LIST_REMOVE(LIST_FIRST(&ip_fw_chain), chain);
- free(fcp->rule, M_IPFW);
- free(fcp, M_IPFW);
- }
-
- splx(s);
- printf("IP firewall unloaded\n");
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-static moduledata_t ipfwmod = {
- "ipfw",
- ipfw_modevent,
- 0
-};
-DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
#endif
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 31e8366..a4cee76 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -11,7 +11,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.h,v 1.34 1998/08/23 03:07:14 wollman Exp $
+ * $Id: ip_fw.h,v 1.35 1998/09/02 19:14:01 phk Exp $
*/
#ifndef _IP_FW_H
@@ -35,7 +35,7 @@
union ip_fw_if {
struct in_addr fu_via_ip; /* Specified by IP address */
struct { /* Specified by interface name */
-#define FW_IFNLEN IFNAMSIZ
+#define FW_IFNLEN 10 /* need room ! was IFNAMSIZ */
char name[FW_IFNLEN];
short unit; /* -1 means match any unit */
} fu_via_if;
@@ -69,6 +69,7 @@ struct ip_fw {
union ip_fw_if fw_in_if, fw_out_if; /* Incoming and outgoing interfaces */
union {
u_short fu_divert_port; /* Divert/tee port (options IPDIVERT) */
+ u_short fu_pipe_nr; /* pipe number (option DUMMYNET) */
u_short fu_skipto_rule; /* SKIPTO command rule number */
u_short fu_reject_code; /* REJECT response code */
struct sockaddr_in fu_fwd_ip;
@@ -78,6 +79,8 @@ struct ip_fw {
/* in ports array (dst ports follow */
/* src ports; max of 10 ports in all; */
/* count of 0 means match all ports) */
+ void *pipe_ptr; /* Pipe ptr in case of dummynet pipe */
+ void *next_rule_ptr ; /* next rule in case of match */
};
#define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f)
@@ -94,6 +97,7 @@ struct ip_fw {
#define fw_divert_port fw_un.fu_divert_port
#define fw_skipto_rule fw_un.fu_skipto_rule
#define fw_reject_code fw_un.fu_reject_code
+#define fw_pipe_nr fw_un.fu_pipe_nr
#define fw_fwd_ip fw_un.fu_fwd_ip
struct ip_fw_chain {
@@ -113,6 +117,7 @@ struct ip_fw_chain {
#define IP_FW_F_TEE 0x00000005 /* This is a tee rule */
#define IP_FW_F_SKIPTO 0x00000006 /* This is a skipto rule */
#define IP_FW_F_FWD 0x00000007 /* This is a "change forwarding address" rule */
+#define IP_FW_F_PIPE 0x00000008 /* This is a dummynet rule */
#define IP_FW_F_IN 0x00000100 /* Check inbound packets */
#define IP_FW_F_OUT 0x00000200 /* Check outbound packets */
@@ -188,7 +193,7 @@ void ip_fw_init __P((void));
struct ip;
struct sockopt;
typedef int ip_fw_chk_t __P((struct ip **, int, struct ifnet *, u_int16_t *,
- struct mbuf **, struct sockaddr_in **));
+ struct mbuf **, struct ip_fw_chain **, struct sockaddr_in **));
typedef int ip_fw_ctl_t __P((struct sockopt *));
extern ip_fw_chk_t *ip_fw_chk_ptr;
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 8661bf8..839c5b7 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
- * $Id: ip_input.c,v 1.107 1998/11/16 08:27:36 dfr Exp $
+ * $Id: ip_input.c,v 1.101 1998/09/10 08:56:40 dfr Exp $
* $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $
*/
@@ -39,6 +39,7 @@
#include "opt_bootp.h"
#include "opt_ipfw.h"
+#include "opt_ipdn.h"
#include "opt_ipdivert.h"
#include "opt_ipfilter.h"
@@ -47,6 +48,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
+#include <sys/malloc.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
@@ -76,6 +78,10 @@
#include <netinet/ip_fw.h>
#endif
+#ifdef DUMMYNET
+#include <netinet/ip_dummynet.h>
+#endif
+
int rsvp_on = 0;
static int ip_rsvp_on;
struct socket *ip_rsvpd;
@@ -149,6 +155,10 @@ SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW,
ip_fw_chk_t *ip_fw_chk_ptr;
ip_fw_ctl_t *ip_fw_ctl_ptr;
+#ifdef DUMMYNET
+ip_dn_ctl_t *ip_dn_ctl_ptr;
+#endif
+
/* IP Network Address Translation (NAT) hooks */
ip_nat_t *ip_nat_ptr;
ip_nat_ctl_t *ip_nat_ctl_ptr;
@@ -224,6 +234,12 @@ ip_init()
ip_id = time_second & 0xffff;
ipintrq.ifq_maxlen = ipqmaxlen;
+#ifdef IPFIREWALL
+ ip_fw_init();
+#endif
+#ifdef DUMMYNET
+ ip_dn_init();
+#endif
#ifdef IPNAT
ip_nat_init();
#endif
@@ -245,9 +261,34 @@ ip_input(struct mbuf *m)
{
struct ip *ip;
struct ipq *fp;
+ struct ipqent *ipqe;
struct in_ifaddr *ia;
int i, hlen, mff;
u_short sum;
+#ifndef IPDIVERT /* dummy variable for the firewall code to play with */
+ u_short ip_divert_cookie = 0 ;
+#endif
+#ifdef COMPAT_IPFW
+ struct ip_fw_chain *rule = NULL ;
+#endif
+
+#if defined(IPFIREWALL) && defined(DUMMYNET)
+ /*
+ * dummynet packet are prepended a vestigial mbuf with
+ * m_type = MT_DUMMYNET and m_data pointing to the matching
+ * rule.
+ */
+ if (m->m_type == MT_DUMMYNET) {
+ struct mbuf *m0 = m ;
+ rule = (struct ip_fw_chain *)(m->m_data) ;
+ m = m->m_next ;
+ free(m0, M_IPFW);
+ ip = mtod(m, struct ip *);
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+ goto iphack ;
+ } else
+ rule = NULL ;
+#endif
#ifdef DIAGNOSTIC
if (m == NULL || (m->m_flags & M_PKTHDR) == 0)
@@ -336,9 +377,12 @@ tooshort:
* deals with it.
* - Firewall: deny/allow/divert
* - Xlate: translate packet's addr/port (NAT).
+ * - Pipe: pass pkt through dummynet.
* - Wrap: fake packet's addr/port <unimpl.>
* - Encapsulate: put it in another IP and send out. <unimp.>
*/
+
+iphack:
#if defined(IPFILTER) || defined(IPFILTER_LKM)
/*
* Check if we want to allow this packet to be processed.
@@ -354,8 +398,6 @@ tooshort:
#endif
#ifdef COMPAT_IPFW
if (ip_fw_chk_ptr) {
- u_int16_t port;
-
#ifdef IPFIREWALL_FORWARD
/*
* If we've been forwarded from the output side, then
@@ -364,29 +406,41 @@ tooshort:
if (ip_fw_fwd_addr)
goto ours;
#endif /* IPFIREWALL_FORWARD */
+ i = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie,
+ &m, &rule, &ip_fw_fwd_addr);
+ /*
+ * see the comment in ip_output for the return values
+ * produced by the firewall.
+ */
+ if (!m) /* packet discarded by firewall */
+ return ;
+ if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */
+ goto pass ;
+#ifdef DUMMYNET
+ if (i & 0x10000) {
+ /* send packet to the appropriate pipe */
+ dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule);
+ return ;
+ }
+#endif
#ifdef IPDIVERT
- port = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie,
- &m, &ip_fw_fwd_addr);
- if (port) {
+ if (i > 0 && i < 0x10000) {
/* Divert packet */
- frag_divert_port = port;
+ frag_divert_port = i & 0xffff ;
goto ours;
}
-#else /* !DIVERT */
+#endif
+#ifdef IPFIREWALL_FORWARD
+ if (i == 0 && ip_fw_fwd_addr != NULL)
+ goto pass ;
+#endif
/*
- * If ipfw says divert, we have to just drop packet
- * Use port as a dummy argument.
+ * if we get here, the packet must be dropped
*/
- port = 0;
- if ((*ip_fw_chk_ptr)(&ip, hlen, NULL, &port,
- &m, &ip_fw_fwd_addr)) {
m_freem(m);
- m = NULL;
- }
-#endif /* !DIVERT */
- if (!m)
return;
}
+pass:
if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN))
return;
@@ -512,7 +566,7 @@ ours:
*/
if (ip->ip_off & (IP_MF | IP_OFFMASK | IP_RF)) {
if (m->m_flags & M_EXT) { /* XXX */
- if ((m = m_pullup(m, hlen)) == 0) {
+ if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
ipstat.ips_toosmall++;
#ifdef IPDIVERT
frag_divert_port = 0;
@@ -710,13 +764,13 @@ ip_reass(m, fp, where)
fp->ipq_id = ip->ip_id;
fp->ipq_src = ip->ip_src;
fp->ipq_dst = ip->ip_dst;
- fp->ipq_frags = m;
- m->m_nextpkt = NULL;
+ fp->ipq_frags = 0;
#ifdef IPDIVERT
fp->ipq_divert = 0;
fp->ipq_div_cookie = 0;
#endif
- goto inserted;
+ q = 0;
+ goto insert;
}
#define GETIP(m) ((struct ip*)((m)->m_pkthdr.header))
@@ -731,8 +785,7 @@ ip_reass(m, fp, where)
/*
* If there is a preceding segment, it may provide some of
* our data already. If so, drop the data from the incoming
- * segment. If it provides all of our data, drop us, otherwise
- * stick new segment in the proper place.
+ * segment. If it provides all of our data, drop us.
*/
if (p) {
i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off;
@@ -743,11 +796,6 @@ ip_reass(m, fp, where)
ip->ip_off += i;
ip->ip_len -= i;
}
- m->m_nextpkt = p->m_nextpkt;
- p->m_nextpkt = m;
- } else {
- m->m_nextpkt = fp->ipq_frags;
- fp->ipq_frags = m;
}
/*
@@ -755,7 +803,7 @@ ip_reass(m, fp, where)
* if they are completely covered, dequeue them.
*/
for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off;
- q = nq) {
+ p = q, q = nq) {
i = (ip->ip_off + ip->ip_len) -
GETIP(q)->ip_off;
if (i < GETIP(q)->ip_len) {
@@ -765,11 +813,14 @@ ip_reass(m, fp, where)
break;
}
nq = q->m_nextpkt;
- m->m_nextpkt = nq;
+ if (p)
+ p->m_nextpkt = nq;
+ else
+ fp->ipq_frags = nq;
m_freem(q);
}
-inserted:
+insert:
#ifdef IPDIVERT
/*
@@ -784,8 +835,16 @@ inserted:
#endif
/*
- * Check for complete reassembly.
+ * Stick new segment in its place;
+ * check for complete reassembly.
*/
+ if (p == NULL) {
+ m->m_nextpkt = fp->ipq_frags;
+ fp->ipq_frags = m;
+ } else {
+ m->m_nextpkt = p->m_nextpkt;
+ p->m_nextpkt = m;
+ }
next = 0;
for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) {
if (GETIP(q)->ip_off != next)
@@ -1241,7 +1300,7 @@ ip_srcroute()
*(mtod(m, struct in_addr *)) = *p--;
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf(" hops %lx", (u_long)ntohl(mtod(m, struct in_addr *)->s_addr));
+ printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr));
#endif
/*
@@ -1261,7 +1320,7 @@ ip_srcroute()
while (p >= ip_srcrt.route) {
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf(" %lx", (u_long)ntohl(q->s_addr));
+ printf(" %lx", ntohl(q->s_addr));
#endif
*q++ = *p--;
}
@@ -1271,7 +1330,7 @@ ip_srcroute()
*q = ip_srcrt.dst;
#ifdef DIAGNOSTIC
if (ipprintfs)
- printf(" %lx\n", (u_long)ntohl(q->s_addr));
+ printf(" %lx\n", ntohl(q->s_addr));
#endif
return (m);
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index c9acdf3..32e3545 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -37,12 +37,12 @@
#define _IP_VHL
#include "opt_ipfw.h"
+#include "opt_ipdn.h"
#include "opt_ipdivert.h"
#include "opt_ipfilter.h"
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
@@ -77,6 +77,10 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#include <netinet/ip_fw.h>
#endif
+#ifdef DUMMYNET
+#include <netinet/ip_dummynet.h>
+#endif
+
#ifdef IPFIREWALL_FORWARD_DEBUG
#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
(ntohl(a.s_addr)>>16)&0xFF,\
@@ -131,6 +135,41 @@ ip_output(m0, opt, ro, flags, imo)
int fwd_rewrite_src = 0;
#endif
+#ifndef IPDIVERT /* dummy variable for the firewall code to play with */
+ u_short ip_divert_cookie = 0 ;
+#endif
+#ifdef COMPAT_IPFW
+ struct ip_fw_chain *rule = NULL ;
+#endif
+
+#if defined(IPFIREWALL) && defined(DUMMYNET)
+ /*
+ * dummynet packet are prepended a vestigial mbuf with
+ * m_type = MT_DUMMYNET and m_data pointing to the matching
+ * rule.
+ */
+ if (m->m_type == MT_DUMMYNET) {
+ struct mbuf *tmp_m = m ;
+ /*
+ * the packet was already tagged, so part of the
+ * processing was already done, and we need to go down.
+ * opt, flags and imo have already been used, and now
+ * they are used to hold ifp and hlen and NULL, respectively.
+ */
+ rule = (struct ip_fw_chain *)(m->m_data) ;
+ m = m->m_next ;
+ free(tmp_m, M_IPFW);
+ ip = mtod(m, struct ip *);
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ ifp = (struct ifnet *)opt;
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
+ opt = NULL ;
+ flags = 0 ; /* XXX is this correct ? */
+ goto sendit;
+ } else
+ rule = NULL ;
+#endif
+
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
panic("ip_output no HDR");
@@ -394,28 +433,52 @@ sendit:
* Check with the firewall...
*/
if (ip_fw_chk_ptr) {
-#ifdef IPFIREWALL_FORWARD
struct sockaddr_in *old = dst;
-#endif
-#ifdef IPDIVERT
- ip_divert_port = (*ip_fw_chk_ptr)(&ip,
- hlen, ifp, &ip_divert_cookie, &m, &dst);
- if (ip_divert_port) { /* Divert packet */
- (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
+
+ off = (*ip_fw_chk_ptr)(&ip,
+ hlen, ifp, &ip_divert_cookie, &m, &rule, &dst);
+ /*
+ * On return we must do the following:
+ * m == NULL -> drop the pkt
+ * 1<=off<= 0xffff -> DIVERT
+ * (off & 0x10000) -> send to a DUMMYNET pipe
+ * dst != old -> IPFIREWALL_FORWARD
+ * off==0, dst==old -> accept
+ * If some of the above modules is not compiled in, then
+ * we should't have to check the corresponding condition
+ * (because the ipfw control socket should not accept
+ * unsupported rules), but better play safe and drop
+ * packets in case of doubt.
+ */
+ if (!m) { /* firewall said to reject */
+ error = EACCES;
goto done;
}
-#else /* !IPDIVERT */
- u_int16_t dummy = 0;
- /* If ipfw says divert, we have to just drop packet */
- if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, &dummy, &m, &dst)) {
- m_freem(m);
+ if (off == 0 && dst == old) /* common case */
+ goto pass ;
+#ifdef DUMMYNET
+ if (off & 0x10000) {
+ /*
+ * pass the pkt to dummynet. Need to include
+ * pipe number, m, ifp, ro, hlen because these are
+ * not recomputed in the next pass.
+ * All other parameters have been already used and
+ * so they are not needed anymore.
+ * XXX note: if the ifp or ro entry are deleted
+ * while a pkt is in dummynet, we are in trouble!
+ */
+ dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,hlen,rule);
goto done;
}
-#endif /* !IPDIVERT */
- if (!m) {
- error = EACCES;
+#endif
+#ifdef IPDIVERT
+ if (off > 0 && off < 0x10000) { /* Divert packet */
+ ip_divert_port = off & 0xffff ;
+ (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
goto done;
}
+#endif
+
#ifdef IPFIREWALL_FORWARD
/* Here we check dst to make sure it's directly reachable on the
* interface we previously thought it was.
@@ -426,7 +489,7 @@ sendit:
* such control is nigh impossible. So we do it here.
* And I'm babbling.
*/
- if (old != dst) {
+ if (off == 0 && old != dst) {
struct in_ifaddr *ia;
/* It's changed... */
@@ -515,12 +578,20 @@ sendit:
*/
if (fwd_rewrite_src)
ip->ip_src = IA_SIN(ia)->sin_addr;
+ goto pass ;
}
#endif /* IPFIREWALL_FORWARD */
+ /*
+ * if we get here, none of the above matches, and
+ * we have to drop the pkt
+ */
+ m_freem(m);
+ error = EACCES; /* not sure this is the right error msg */
+ goto done;
}
#endif /* COMPAT_IPFW */
-
+pass:
/*
* If small enough for interface, can just send directly.
*/
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index ee05690..1dd3618 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
- * $Id: raw_ip.c,v 1.54 1998/05/15 20:11:34 wollman Exp $
+ * $Id: raw_ip.c,v 1.55 1998/08/23 03:07:14 wollman Exp $
*/
#include <sys/param.h>
@@ -61,6 +61,10 @@
#include <netinet/ip_fw.h>
+#include "opt_ipdn.h"
+#ifdef DUMMYNET
+#include <netinet/ip_dummynet.h>
+#endif
#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
#undef COMPAT_IPFW
#define COMPAT_IPFW 1
@@ -259,6 +263,14 @@ rip_ctloutput(so, sopt)
else
error = ip_nat_ctl_ptr(sopt);
break;
+#ifdef DUMMYNET
+ case IP_DUMMYNET_GET:
+ if (ip_dn_ctl_ptr == NULL)
+ error = ENOPROTOOPT ;
+ else
+ error = ip_dn_ctl_ptr(sopt);
+ break ;
+#endif /* DUMMYNET */
#endif /* COMPAT_IPFW */
case MRT_INIT:
@@ -308,6 +320,16 @@ rip_ctloutput(so, sopt)
else
error = ip_nat_ctl_ptr(sopt);
break;
+#ifdef DUMMYNET
+ case IP_DUMMYNET_CONFIGURE:
+ case IP_DUMMYNET_DEL:
+ case IP_DUMMYNET_FLUSH:
+ if (ip_dn_ctl_ptr == NULL)
+ error = ENOPROTOOPT ;
+ else
+ error = ip_dn_ctl_ptr(sopt);
+ break ;
+#endif
#endif /* COMPAT_IPFW */
case IP_RSVP_ON:
OpenPOWER on IntegriCloud