Last bits (i think) of dummynet for -current.
This commit is contained in:
parent
fb5fbe465a
commit
b715f178c6
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -84,6 +86,13 @@ struct dn_pipe { /* a pipe */
|
|||
long numbytes; /* which can send or receive */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
@ -91,6 +100,7 @@ struct dn_pipe { /* a pipe */
|
|||
#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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
goto done;
|
||||
}
|
||||
#endif /* !IPDIVERT */
|
||||
if (!m) {
|
||||
|
||||
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;
|
||||
}
|
||||
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
|
||||
#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.
|
||||
*/
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue