diff options
Diffstat (limited to 'sys/netpfil')
| -rw-r--r-- | sys/netpfil/ipfw/ip_dn_glue.c | 858 | ||||
| -rw-r--r-- | sys/netpfil/ipfw/ip_dn_private.h | 10 | ||||
| -rw-r--r-- | sys/netpfil/ipfw/ip_dummynet.c | 96 | ||||
| -rw-r--r-- | sys/netpfil/pf/if_pfsync.c | 3 | ||||
| -rw-r--r-- | sys/netpfil/pf/pf.c | 2 | ||||
| -rw-r--r-- | sys/netpfil/pf/pf_ioctl.c | 11 | ||||
| -rw-r--r-- | sys/netpfil/pf/pf_lb.c | 117 | ||||
| -rw-r--r-- | sys/netpfil/pf/pf_table.c | 2 | 
8 files changed, 157 insertions, 942 deletions
| diff --git a/sys/netpfil/ipfw/ip_dn_glue.c b/sys/netpfil/ipfw/ip_dn_glue.c deleted file mode 100644 index 0412b730e4df..000000000000 --- a/sys/netpfil/ipfw/ip_dn_glue.c +++ /dev/null @@ -1,858 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * - * Binary compatibility support for /sbin/ipfw RELENG_7 and RELENG_8 - */ - -#include "opt_inet6.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/priv.h> -#include <sys/proc.h> -#include <sys/rwlock.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/time.h> -#include <sys/taskqueue.h> -#include <net/if.h>	/* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */ -#include <netinet/in.h> -#include <netinet/ip_var.h>	/* ip_output(), IP_FORWARDING */ -#include <netinet/ip_fw.h> -#include <netinet/ip_dummynet.h> - -#include <netpfil/ipfw/ip_fw_private.h> -#include <netpfil/ipfw/dn_heap.h> -#include <netpfil/ipfw/ip_dn_private.h> -#ifdef NEW_AQM -#include <netpfil/ipfw/dn_aqm.h> -#endif -#include <netpfil/ipfw/dn_sched.h> - -/* FREEBSD7.2 ip_dummynet.h r191715*/ - -struct dn_heap_entry7 { -	int64_t key;        /* sorting key. Topmost element is smallest one */ -	void *object;      /* object pointer */ -}; - -struct dn_heap7 { -	int size; -	int elements; -	int offset; /* XXX if > 0 this is the offset of direct ptr to obj */ -	struct dn_heap_entry7 *p;   /* really an array of "size" entries */ -}; - -/* Common to 7.2 and 8 */ -struct dn_flow_set { -	SLIST_ENTRY(dn_flow_set) next;	/* linked list in a hash slot */ - -	u_short fs_nr ;			/* flow_set number       */ -	u_short flags_fs; -#define DNOLD_HAVE_FLOW_MASK   0x0001 -#define DNOLD_IS_RED           0x0002 -#define DNOLD_IS_GENTLE_RED    0x0004 -#define DNOLD_QSIZE_IS_BYTES   0x0008	/* queue size is measured in bytes */ -#define DNOLD_NOERROR          0x0010	/* do not report ENOBUFS on drops  */ -#define DNOLD_HAS_PROFILE      0x0020	/* the pipe has a delay profile. */ -#define DNOLD_IS_PIPE          0x4000 -#define DNOLD_IS_QUEUE         0x8000 - -	struct dn_pipe7 *pipe ;		/* pointer to parent pipe */ -	u_short parent_nr ;		/* parent pipe#, 0 if local to a pipe */ - -	int weight ;			/* WFQ queue weight */ -	int qsize ;			/* queue size in slots or bytes */ -	int plr[4] ;			/* pkt loss rate (2^31-1 means 100%) */ - -	struct ipfw_flow_id flow_mask ; - -	/* hash table of queues onto this flow_set */ -	int rq_size ;			/* number of slots */ -	int rq_elements ;		/* active elements */ -	struct dn_flow_queue7 **rq ;	/* array of rq_size entries */ - -	u_int32_t last_expired ;	/* do not expire too frequently */ -	int backlogged ;		/* #active queues for this flowset */ - -        /* RED parameters */ -#define SCALE_RED               16 -#define SCALE(x)                ( (x) << SCALE_RED ) -#define SCALE_VAL(x)            ( (x) >> SCALE_RED ) -#define SCALE_MUL(x,y)          ( ( (x) * (y) ) >> SCALE_RED ) -	int w_q ;           /* queue weight (scaled) */ -	int max_th ;        /* maximum threshold for queue (scaled) */ -	int min_th ;        /* minimum threshold for queue (scaled) */ -	int max_p ;         /* maximum value for p_b (scaled) */ -	u_int c_1 ;         /* max_p/(max_th-min_th) (scaled) */ -	u_int c_2 ;         /* max_p*min_th/(max_th-min_th) (scaled) */ -	u_int c_3 ;         /* for GRED, (1-max_p)/max_th (scaled) */ -	u_int c_4 ;         /* for GRED, 1 - 2*max_p (scaled) */ -	u_int * w_q_lookup ;    /* lookup table for computing (1-w_q)^t */ -	u_int lookup_depth ;    /* depth of lookup table */ -	int lookup_step ;       /* granularity inside the lookup table */ -	int lookup_weight ;     /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ -	int avg_pkt_size ;      /* medium packet size */ -	int max_pkt_size ;      /* max packet size */ -}; -SLIST_HEAD(dn_flow_set_head, dn_flow_set); - -#define DN_IS_PIPE		0x4000 -#define DN_IS_QUEUE		0x8000 -struct dn_flow_queue7 { -	struct dn_flow_queue7 *next ; -	struct ipfw_flow_id id ; - -	struct mbuf *head, *tail ;  /* queue of packets */ -	u_int len ; -	u_int len_bytes ; - -	u_long numbytes; - -	u_int64_t tot_pkts ;    /* statistics counters  */ -	u_int64_t tot_bytes ; -	u_int32_t drops ; - -	int hash_slot ;     /* debugging/diagnostic */ - -	/* RED parameters */ -	int avg ;                   /* average queue length est. (scaled) */ -	int count ;                 /* arrivals since last RED drop */ -	int random ;                /* random value (scaled) */ -	u_int32_t q_time;      /* start of queue idle time */ - -	/* WF2Q+ support */ -	struct dn_flow_set *fs ;    /* parent flow set */ -	int heap_pos ;      /* position (index) of struct in heap */ -	int64_t sched_time ;     /* current time when queue enters ready_heap */ - -	int64_t S,F ;        /* start time, finish time */ -}; - -struct dn_pipe7 {        /* a pipe */ -	SLIST_ENTRY(dn_pipe7)    next;   /* linked list in a hash slot */ - -	int pipe_nr ;       /* number   */ -	uint32_t bandwidth;      /* really, bytes/tick.  */ -	int delay ;         /* really, ticks    */ - -	struct  mbuf *head, *tail ; /* packets in delay line */ - -	/* WF2Q+ */ -	struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/ -	struct dn_heap7 not_eligible_heap; /* top extract- key Start time */ -	struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */ - -	int64_t V ;          /* virtual time */ -	int sum;            /* sum of weights of all active sessions */ - -	int numbytes; - -	int64_t sched_time ;     /* time pipe was scheduled in ready_heap */ - -	/* -	* When the tx clock come from an interface (if_name[0] != '\0'), its name -	* is stored below, whereas the ifp is filled when the rule is configured. -	*/ -	char if_name[IFNAMSIZ]; -	struct ifnet *ifp ; -	int ready ; /* set if ifp != NULL and we got a signal from it */ - -	struct dn_flow_set fs ; /* used with fixed-rate flows */ -}; -SLIST_HEAD(dn_pipe_head7, dn_pipe7); - -/* FREEBSD8 ip_dummynet.h r196045 */ -struct dn_flow_queue8 { -	struct dn_flow_queue8 *next ; -	struct ipfw_flow_id id ; - -	struct mbuf *head, *tail ;  /* queue of packets */ -	u_int len ; -	u_int len_bytes ; - -	uint64_t numbytes ;     /* credit for transmission (dynamic queues) */ -	int64_t extra_bits;     /* extra bits simulating unavailable channel */ - -	u_int64_t tot_pkts ;    /* statistics counters  */ -	u_int64_t tot_bytes ; -	u_int32_t drops ; - -	int hash_slot ;     /* debugging/diagnostic */ - -	/* RED parameters */ -	int avg ;                   /* average queue length est. (scaled) */ -	int count ;                 /* arrivals since last RED drop */ -	int random ;                /* random value (scaled) */ -	int64_t idle_time;       /* start of queue idle time */ - -	/* WF2Q+ support */ -	struct dn_flow_set *fs ;    /* parent flow set */ -	int heap_pos ;      /* position (index) of struct in heap */ -	int64_t sched_time ;     /* current time when queue enters ready_heap */ - -	int64_t S,F ;        /* start time, finish time */ -}; - -struct dn_pipe8 {        /* a pipe */ -	SLIST_ENTRY(dn_pipe8)    next;   /* linked list in a hash slot */ - -	int pipe_nr ;       /* number   */ -	uint32_t bandwidth;      /* really, bytes/tick.  */ -	int delay ;         /* really, ticks    */ - -	struct  mbuf *head, *tail ; /* packets in delay line */ - -	/* WF2Q+ */ -	struct dn_heap7 scheduler_heap ; /* top extract - key Finish time*/ -	struct dn_heap7 not_eligible_heap; /* top extract- key Start time */ -	struct dn_heap7 idle_heap ; /* random extract - key Start=Finish time */ - -	int64_t V ;          /* virtual time */ -	int sum;            /* sum of weights of all active sessions */ - -	/* Same as in dn_flow_queue, numbytes can become large */ -	int64_t numbytes;       /* bits I can transmit (more or less). */ -	uint64_t burst;     /* burst size, scaled: bits * hz */ - -	int64_t sched_time ;     /* time pipe was scheduled in ready_heap */ -	int64_t idle_time;       /* start of pipe idle time */ - -	char if_name[IFNAMSIZ]; -	struct ifnet *ifp ; -	int ready ; /* set if ifp != NULL and we got a signal from it */ - -	struct dn_flow_set fs ; /* used with fixed-rate flows */ - -    /* fields to simulate a delay profile */ -#define ED_MAX_NAME_LEN     32 -	char name[ED_MAX_NAME_LEN]; -	int loss_level; -	int samples_no; -	int *samples; -}; - -#define ED_MAX_SAMPLES_NO   1024 -struct dn_pipe_max8 { -	struct dn_pipe8 pipe; -	int samples[ED_MAX_SAMPLES_NO]; -}; -SLIST_HEAD(dn_pipe_head8, dn_pipe8); - -/* - * Changes from 7.2 to 8: - * dn_pipe: - *      numbytes from int to int64_t - *      add burst (int64_t) - *      add idle_time (int64_t) - *      add profile - *      add struct dn_pipe_max - *      add flag DN_HAS_PROFILE - * - * dn_flow_queue - *      numbytes from u_long to int64_t - *      add extra_bits (int64_t) - *      q_time from u_int32_t to int64_t and name idle_time - * - * dn_flow_set unchanged - * - */ - -/* NOTE:XXX copied from dummynet.c */ -#define O_NEXT(p, len) ((void *)((char *)p + len)) -static void -oid_fill(struct dn_id *oid, int len, int type, uintptr_t id) -{ -	oid->len = len; -	oid->type = type; -	oid->subtype = 0; -	oid->id = id; -} -/* make room in the buffer and move the pointer forward */ -static void * -o_next(struct dn_id **o, int len, int type) -{ -	struct dn_id *ret = *o; -	oid_fill(ret, len, type, 0); -	*o = O_NEXT(*o, len); -	return ret; -} - -static size_t pipesize7 = sizeof(struct dn_pipe7); -static size_t pipesize8 = sizeof(struct dn_pipe8); -static size_t pipesizemax8 = sizeof(struct dn_pipe_max8); - -/* Indicate 'ipfw' version - * 1: from FreeBSD 7.2 - * 0: from FreeBSD 8 - * -1: unknown (for now is unused) - * - * It is update when a IP_DUMMYNET_DEL or IP_DUMMYNET_CONFIGURE request arrives - * NOTE: if a IP_DUMMYNET_GET arrives and the 'ipfw' version is unknown, - *       it is suppose to be the FreeBSD 8 version. - */ -static int is7 = 0; - -static int -convertflags2new(int src) -{ -	int dst = 0; - -	if (src & DNOLD_HAVE_FLOW_MASK) -		dst |= DN_HAVE_MASK; -	if (src & DNOLD_QSIZE_IS_BYTES) -		dst |= DN_QSIZE_BYTES; -	if (src & DNOLD_NOERROR) -		dst |= DN_NOERROR; -	if (src & DNOLD_IS_RED) -		dst |= DN_IS_RED; -	if (src & DNOLD_IS_GENTLE_RED) -		dst |= DN_IS_GENTLE_RED; -	if (src & DNOLD_HAS_PROFILE) -		dst |= DN_HAS_PROFILE; - -	return dst; -} - -static int -convertflags2old(int src) -{ -	int dst = 0; - -	if (src & DN_HAVE_MASK) -		dst |= DNOLD_HAVE_FLOW_MASK; -	if (src & DN_IS_RED) -		dst |= DNOLD_IS_RED; -	if (src & DN_IS_GENTLE_RED) -		dst |= DNOLD_IS_GENTLE_RED; -	if (src & DN_NOERROR) -		dst |= DNOLD_NOERROR; -	if (src & DN_HAS_PROFILE) -		dst |= DNOLD_HAS_PROFILE; -	if (src & DN_QSIZE_BYTES) -		dst |= DNOLD_QSIZE_IS_BYTES; - -	return dst; -} - -static int -dn_compat_del(void *v) -{ -	struct dn_pipe7 *p = (struct dn_pipe7 *) v; -	struct dn_pipe8 *p8 = (struct dn_pipe8 *) v; -	struct { -		struct dn_id oid; -		uintptr_t a[1];	/* add more if we want a list */ -	} cmd; - -	/* XXX DN_API_VERSION ??? */ -	oid_fill((void *)&cmd, sizeof(cmd), DN_CMD_DELETE, DN_API_VERSION); - -	if (is7) { -		if (p->pipe_nr == 0 && p->fs.fs_nr == 0) -			return EINVAL; -		if (p->pipe_nr != 0 && p->fs.fs_nr != 0) -			return EINVAL; -	} else { -		if (p8->pipe_nr == 0 && p8->fs.fs_nr == 0) -			return EINVAL; -		if (p8->pipe_nr != 0 && p8->fs.fs_nr != 0) -			return EINVAL; -	} - -	if (p->pipe_nr != 0) { /* pipe x delete */ -		cmd.a[0] = p->pipe_nr; -		cmd.oid.subtype = DN_LINK; -	} else { /* queue x delete */ -		cmd.oid.subtype = DN_FS; -		cmd.a[0] = (is7) ? p->fs.fs_nr : p8->fs.fs_nr; -	} - -	return do_config(&cmd, cmd.oid.len); -} - -static int -dn_compat_config_queue(struct dn_fs *fs, void* v) -{ -	struct dn_pipe7 *p7 = (struct dn_pipe7 *)v; -	struct dn_pipe8 *p8 = (struct dn_pipe8 *)v; -	struct dn_flow_set *f; - -	if (is7) -		f = &p7->fs; -	else -		f = &p8->fs; - -	fs->fs_nr = f->fs_nr; -	fs->sched_nr = f->parent_nr; -	fs->flow_mask = f->flow_mask; -	fs->buckets = f->rq_size; -	fs->qsize = f->qsize; -	fs->plr[0] = f->plr[0]; -	fs->plr[1] = f->plr[1]; -	fs->plr[2] = f->plr[2]; -	fs->plr[3] = f->plr[3]; -	fs->par[0] = f->weight; -	fs->flags = convertflags2new(f->flags_fs); -	if (fs->flags & DN_IS_GENTLE_RED || fs->flags & DN_IS_RED) { -		fs->w_q = f->w_q; -		fs->max_th = f->max_th; -		fs->min_th = f->min_th; -		fs->max_p = f->max_p; -	} - -	return 0; -} - -static int -dn_compat_config_pipe(struct dn_sch *sch, struct dn_link *p,  -		      struct dn_fs *fs, void* v) -{ -	struct dn_pipe7 *p7 = (struct dn_pipe7 *)v; -	struct dn_pipe8 *p8 = (struct dn_pipe8 *)v; -	int i = p7->pipe_nr; - -	sch->sched_nr = i; -	sch->oid.subtype = 0; -	p->link_nr = i; -	fs->fs_nr = i + 2*DN_MAX_ID; -	fs->sched_nr = i + DN_MAX_ID; - -	/* Common to 7 and 8 */ -	p->bandwidth = p7->bandwidth; -	p->delay = p7->delay; -	if (!is7) { -		/* FreeBSD 8 has burst  */ -		p->burst = p8->burst; -	} - -	/* fill the fifo flowset */ -	dn_compat_config_queue(fs, v); -	fs->fs_nr = i + 2*DN_MAX_ID; -	fs->sched_nr = i + DN_MAX_ID; - -	/* Move scheduler related parameter from fs to sch */ -	sch->buckets = fs->buckets; /*XXX*/ -	fs->buckets = 0; -	if (fs->flags & DN_HAVE_MASK) { -		sch->flags |= DN_HAVE_MASK; -		fs->flags &= ~DN_HAVE_MASK; -		sch->sched_mask = fs->flow_mask; -		bzero(&fs->flow_mask, sizeof(struct ipfw_flow_id)); -	} - -	return 0; -} - -static int -dn_compat_config_profile(struct dn_profile *pf, struct dn_link *p, -			 void *v) -{ -	struct dn_pipe8 *p8 = (struct dn_pipe8 *)v; - -	p8->samples = &(((struct dn_pipe_max8 *)p8)->samples[0]); - -	pf->link_nr = p->link_nr; -	pf->loss_level = p8->loss_level; -// 	pf->bandwidth = p->bandwidth; //XXX bandwidth redundant? -	pf->samples_no = p8->samples_no; -	strncpy(pf->name, p8->name,sizeof(pf->name)); -	bcopy(p8->samples, pf->samples, sizeof(pf->samples)); - -	return 0; -} - -/* - * If p->pipe_nr != 0 the command is 'pipe x config', so need to create - * the three main struct, else only a flowset is created - */ -static int -dn_compat_configure(void *v) -{ -	struct dn_id *buf = NULL, *base; -	struct dn_sch *sch = NULL; -	struct dn_link *p = NULL; -	struct dn_fs *fs = NULL; -	struct dn_profile *pf = NULL; -	int lmax; -	int error; - -	struct dn_pipe7 *p7 = (struct dn_pipe7 *)v; -	struct dn_pipe8 *p8 = (struct dn_pipe8 *)v; - -	int i; /* number of object to configure */ - -	lmax = sizeof(struct dn_id);	/* command header */ -	lmax += sizeof(struct dn_sch) + sizeof(struct dn_link) + -		sizeof(struct dn_fs) + sizeof(struct dn_profile); - -	base = buf = malloc(lmax, M_DUMMYNET, M_WAITOK|M_ZERO); -	o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG); -	base->id = DN_API_VERSION; - -	/* pipe_nr is the same in p7 and p8 */ -	i = p7->pipe_nr; -	if (i != 0) { /* pipe config */ -		sch = o_next(&buf, sizeof(*sch), DN_SCH); -		p = o_next(&buf, sizeof(*p), DN_LINK); -		fs = o_next(&buf, sizeof(*fs), DN_FS); - -		error = dn_compat_config_pipe(sch, p, fs, v); -		if (error) { -			free(buf, M_DUMMYNET); -			return error; -		} -		if (!is7 && p8->samples_no > 0) { -			/* Add profiles*/ -			pf = o_next(&buf, sizeof(*pf), DN_PROFILE); -			error = dn_compat_config_profile(pf, p, v); -			if (error) { -				free(buf, M_DUMMYNET); -				return error; -			} -		} -	} else { /* queue config */ -		fs = o_next(&buf, sizeof(*fs), DN_FS); -		error = dn_compat_config_queue(fs, v); -		if (error) { -			free(buf, M_DUMMYNET); -			return error; -		} -	} -	error = do_config(base, (char *)buf - (char *)base); - -	if (buf) -		free(buf, M_DUMMYNET); -	return error; -} - -int -dn_compat_calc_size(void) -{ -	int need = 0; -	/* XXX use FreeBSD 8 struct size */ -	/* NOTE: -	 * - half scheduler: 		schk_count/2 -	 * - all flowset:		fsk_count -	 * - all flowset queues:	queue_count -	 * - all pipe queue:		si_count -	 */ -	need += V_dn_cfg.schk_count * sizeof(struct dn_pipe8) / 2; -	need += V_dn_cfg.fsk_count * sizeof(struct dn_flow_set); -	need += V_dn_cfg.si_count * sizeof(struct dn_flow_queue8); -	need += V_dn_cfg.queue_count * sizeof(struct dn_flow_queue8); - -	return need; -} - -int -dn_c_copy_q (void *_ni, void *arg) -{ -	struct copy_args *a = arg; -	struct dn_flow_queue7 *fq7 = (struct dn_flow_queue7 *)*a->start; -	struct dn_flow_queue8 *fq8 = (struct dn_flow_queue8 *)*a->start; -	struct dn_flow *ni = (struct dn_flow *)_ni; -	int size = 0; - -	/* XXX hash slot not set */ -	/* No difference between 7.2/8 */ -	fq7->len = ni->length; -	fq7->len_bytes = ni->len_bytes; -	fq7->id = ni->fid; - -	if (is7) { -		size = sizeof(struct dn_flow_queue7); -		fq7->tot_pkts = ni->tot_pkts; -		fq7->tot_bytes = ni->tot_bytes; -		fq7->drops = ni->drops; -	} else { -		size = sizeof(struct dn_flow_queue8); -		fq8->tot_pkts = ni->tot_pkts; -		fq8->tot_bytes = ni->tot_bytes; -		fq8->drops = ni->drops; -	} - -	*a->start += size; -	return 0; -} - -int -dn_c_copy_pipe(struct dn_schk *s, struct copy_args *a, int nq) -{ -	struct dn_link *l = &s->link; -	struct dn_fsk *f = s->fs; - -	struct dn_pipe7 *pipe7 = (struct dn_pipe7 *)*a->start; -	struct dn_pipe8 *pipe8 = (struct dn_pipe8 *)*a->start; -	struct dn_flow_set *fs; -	int size = 0; - -	if (is7) { -		fs = &pipe7->fs; -		size = sizeof(struct dn_pipe7); -	} else { -		fs = &pipe8->fs; -		size = sizeof(struct dn_pipe8); -	} - -	/* These 4 field are the same in pipe7 and pipe8 */ -	pipe7->next.sle_next = (struct dn_pipe7 *)DN_IS_PIPE; -	pipe7->bandwidth = l->bandwidth; -	pipe7->delay = l->delay * 1000 / hz; -	pipe7->pipe_nr = l->link_nr - DN_MAX_ID; - -	if (!is7) { -		if (s->profile) { -			struct dn_profile *pf = s->profile; -			strncpy(pipe8->name, pf->name, sizeof(pf->name)); -			pipe8->loss_level = pf->loss_level; -			pipe8->samples_no = pf->samples_no; -		} -		pipe8->burst = div64(l->burst , 8 * hz); -	} - -	fs->flow_mask = s->sch.sched_mask; -	fs->rq_size = s->sch.buckets ? s->sch.buckets : 1; - -	fs->parent_nr = l->link_nr - DN_MAX_ID; -	fs->qsize = f->fs.qsize; -	fs->plr[0] = f->fs.plr[0]; -	fs->plr[1] = f->fs.plr[1]; -	fs->plr[2] = f->fs.plr[2]; -	fs->plr[3] = f->fs.plr[3]; -	fs->w_q = f->fs.w_q; -	fs->max_th = f->max_th; -	fs->min_th = f->min_th; -	fs->max_p = f->fs.max_p; -	fs->rq_elements = nq; - -	fs->flags_fs = convertflags2old(f->fs.flags); - -	*a->start += size; -	return 0; -} - -int -dn_compat_copy_pipe(struct copy_args *a, void *_o) -{ -	int have = a->end - *a->start; -	int need = 0; -	int pipe_size = sizeof(struct dn_pipe8); -	int queue_size = sizeof(struct dn_flow_queue8); -	int n_queue = 0; /* number of queues */ - -	struct dn_schk *s = (struct dn_schk *)_o; -	/* calculate needed space: -	 * - struct dn_pipe -	 * - if there are instances, dn_queue * n_instances -	 */ -	n_queue = (s->sch.flags & DN_HAVE_MASK ? dn_ht_entries(s->siht) : -						(s->siht ? 1 : 0)); -	need = pipe_size + queue_size * n_queue; -	if (have < need) { -		D("have %d < need %d", have, need); -		return 1; -	} -	/* copy pipe */ -	dn_c_copy_pipe(s, a, n_queue); - -	/* copy queues */ -	if (s->sch.flags & DN_HAVE_MASK) -		dn_ht_scan(s->siht, dn_c_copy_q, a); -	else if (s->siht) -		dn_c_copy_q(s->siht, a); -	return 0; -} - -int -dn_c_copy_fs(struct dn_fsk *f, struct copy_args *a, int nq) -{ -	struct dn_flow_set *fs = (struct dn_flow_set *)*a->start; - -	fs->next.sle_next = (struct dn_flow_set *)DN_IS_QUEUE; -	fs->fs_nr = f->fs.fs_nr; -	fs->qsize = f->fs.qsize; -	fs->plr[0] = f->fs.plr[0]; -	fs->plr[1] = f->fs.plr[1]; -	fs->plr[2] = f->fs.plr[2]; -	fs->plr[3] = f->fs.plr[3]; -	fs->w_q = f->fs.w_q; -	fs->max_th = f->max_th; -	fs->min_th = f->min_th; -	fs->max_p = f->fs.max_p; -	fs->flow_mask = f->fs.flow_mask; -	fs->rq_elements = nq; -	fs->rq_size = (f->fs.buckets ? f->fs.buckets : 1); -	fs->parent_nr = f->fs.sched_nr; -	fs->weight = f->fs.par[0]; - -	fs->flags_fs = convertflags2old(f->fs.flags); -	*a->start += sizeof(struct dn_flow_set); -	return 0; -} - -int -dn_compat_copy_queue(struct copy_args *a, void *_o) -{ -	int have = a->end - *a->start; -	int need = 0; -	int fs_size = sizeof(struct dn_flow_set); -	int queue_size = sizeof(struct dn_flow_queue8); - -	struct dn_fsk *fs = (struct dn_fsk *)_o; -	int n_queue = 0; /* number of queues */ - -	n_queue = (fs->fs.flags & DN_HAVE_MASK ? dn_ht_entries(fs->qht) : -						(fs->qht ? 1 : 0)); - -	need = fs_size + queue_size * n_queue; -	if (have < need) { -		D("have < need"); -		return 1; -	} - -	/* copy flowset */ -	dn_c_copy_fs(fs, a, n_queue); - -	/* copy queues */ -	if (fs->fs.flags & DN_HAVE_MASK) -		dn_ht_scan(fs->qht, dn_c_copy_q, a); -	else if (fs->qht) -		dn_c_copy_q(fs->qht, a); - -	return 0; -} - -int -copy_data_helper_compat(void *_o, void *_arg) -{ -	struct copy_args *a = _arg; - -	if (a->type == DN_COMPAT_PIPE) { -		struct dn_schk *s = _o; -		if (s->sch.oid.subtype != 1 || s->sch.sched_nr <= DN_MAX_ID) { -			return 0;	/* not old type */ -		} -		/* copy pipe parameters, and if instance exists, copy -		 * other parameters and eventually queues. -		 */ -		if(dn_compat_copy_pipe(a, _o)) -			return DNHT_SCAN_END; -	} else if (a->type == DN_COMPAT_QUEUE) { -		struct dn_fsk *fs = _o; -		if (fs->fs.fs_nr >= DN_MAX_ID) -			return 0; -		if (dn_compat_copy_queue(a, _o)) -			return DNHT_SCAN_END; -	} -	return 0; -} - -/* Main function to manage old requests */ -int -ip_dummynet_compat(struct sockopt *sopt) -{ -	int error=0; -	void *v = NULL; -	struct dn_id oid; - -	/* Length of data, used to found ipfw version... */ -	int len = sopt->sopt_valsize; - -	/* len can be 0 if command was dummynet_flush */ -	if (len == pipesize7) { -		D("setting compatibility with FreeBSD 7.2"); -		is7 = 1; -	} -	else if (len == pipesize8 || len == pipesizemax8) { -		D("setting compatibility with FreeBSD 8"); -		is7 = 0; -	} - -	switch (sopt->sopt_name) { -	default: -		printf("dummynet: -- unknown option %d", sopt->sopt_name); -		error = EINVAL; -		break; - -	case IP_DUMMYNET_FLUSH: -		oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH, DN_API_VERSION); -		do_config(&oid, oid.len); -		break; - -	case IP_DUMMYNET_DEL: -		v = malloc(len, M_TEMP, M_WAITOK); -		error = sooptcopyin(sopt, v, len, len); -		if (error) -			break; -		error = dn_compat_del(v); -		free(v, M_TEMP); -		break; - -	case IP_DUMMYNET_CONFIGURE: -		v = malloc(len, M_TEMP, M_NOWAIT); -		if (v == NULL) { -			error = ENOMEM; -			break; -		} -		error = sooptcopyin(sopt, v, len, len); -		if (error) -			break; -		error = dn_compat_configure(v); -		free(v, M_TEMP); -		break; - -	case IP_DUMMYNET_GET: { -		void *buf; -		int ret; -		int original_size = sopt->sopt_valsize; -		int size; - -		ret = dummynet_get(sopt, &buf); -		if (ret) -			return 0;//XXX ? -		size = sopt->sopt_valsize; -		sopt->sopt_valsize = original_size; -		D("size=%d, buf=%p", size, buf); -		ret = sooptcopyout(sopt, buf, size); -		if (ret) -			printf("  %s ERROR sooptcopyout\n", __FUNCTION__); -		if (buf) -			free(buf, M_DUMMYNET); -	    } -	} - -	return error; -} diff --git a/sys/netpfil/ipfw/ip_dn_private.h b/sys/netpfil/ipfw/ip_dn_private.h index 756a997b6ec3..9a43b86791e0 100644 --- a/sys/netpfil/ipfw/ip_dn_private.h +++ b/sys/netpfil/ipfw/ip_dn_private.h @@ -437,15 +437,7 @@ struct copy_args {  };  struct sockopt; -int ip_dummynet_compat(struct sockopt *sopt); -int dummynet_get(struct sockopt *sopt, void **compat); -int dn_c_copy_q (void *_ni, void *arg); -int dn_c_copy_pipe(struct dn_schk *s, struct copy_args *a, int nq); -int dn_c_copy_fs(struct dn_fsk *f, struct copy_args *a, int nq); -int dn_compat_copy_queue(struct copy_args *a, void *_o); -int dn_compat_copy_pipe(struct copy_args *a, void *_o); -int copy_data_helper_compat(void *_o, void *_arg); -int dn_compat_calc_size(void); +int dummynet_get(struct sockopt *sopt);  int do_config(void *p, size_t l);  /* function to drain idle object */ diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c index d522f9da0fbe..61442c617753 100644 --- a/sys/netpfil/ipfw/ip_dummynet.c +++ b/sys/netpfil/ipfw/ip_dummynet.c @@ -2198,9 +2198,6 @@ compute_space(struct dn_id *cmd, struct copy_args *a)  	case DN_FS:	/* queue show */  		x = DN_C_FS | DN_C_QUEUE;  		break; -	case DN_GET_COMPAT:	/* compatibility mode */ -		need =  dn_compat_calc_size();  -		break;  	}  	a->flags = x;  	if (x & DN_C_SCH) { @@ -2226,11 +2223,9 @@ compute_space(struct dn_id *cmd, struct copy_args *a)  }  /* - * If compat != NULL dummynet_get is called in compatibility mode. - * *compat will be the pointer to the buffer to pass to ipfw   */  int -dummynet_get(struct sockopt *sopt, void **compat) +dummynet_get(struct sockopt *sopt)  {  	int have, i, need, error;  	char *start = NULL, *buf; @@ -2248,37 +2243,28 @@ dummynet_get(struct sockopt *sopt, void **compat)  	cmd = &r.o; -	if (!compat) { -		/* copy at least an oid, and possibly a full object */ -		error = sooptcopyin(sopt, cmd, sizeof(r), sizeof(*cmd)); -		sopt->sopt_valsize = sopt_valsize; -		if (error) -			goto done; -		l = cmd->len; +	/* copy at least an oid, and possibly a full object */ +	error = sooptcopyin(sopt, cmd, sizeof(r), sizeof(*cmd)); +	sopt->sopt_valsize = sopt_valsize; +	if (error) +		goto done; +	l = cmd->len;  #ifdef EMULATE_SYSCTL -		/* sysctl emulation. */ -		if (cmd->type == DN_SYSCTL_GET) -			return kesysctl_emu_get(sopt); +	/* sysctl emulation. */ +	if (cmd->type == DN_SYSCTL_GET) +		return kesysctl_emu_get(sopt);  #endif -		if (l > sizeof(r)) { -			/* request larger than default, allocate buffer */ -			cmd = malloc(l,  M_DUMMYNET, M_NOWAIT); -			if (cmd == NULL) { -				error = ENOMEM; -				goto done; -			} -			error = sooptcopyin(sopt, cmd, l, l); -			sopt->sopt_valsize = sopt_valsize; -			if (error) -				goto done; +	if (l > sizeof(r)) { +		/* request larger than default, allocate buffer */ +		cmd = malloc(l,  M_DUMMYNET, M_NOWAIT); +		if (cmd == NULL) { +			error = ENOMEM; +			goto done;  		} -	} else { /* compatibility */ -		error = 0; -		cmd->type = DN_CMD_GET; -		cmd->len = sizeof(struct dn_id); -		cmd->subtype = DN_GET_COMPAT; -		// cmd->id = sopt_valsize; -		D("compatibility mode"); +		error = sooptcopyin(sopt, cmd, l, l); +		sopt->sopt_valsize = sopt_valsize; +		if (error) +			goto done;  	}  #ifdef NEW_AQM @@ -2337,12 +2323,7 @@ dummynet_get(struct sockopt *sopt, void **compat)  	}  	if (start == NULL) { -		if (compat) { -			*compat = NULL; -			error =  1; // XXX -		} else { -			error = sooptcopyout(sopt, cmd, sizeof(*cmd)); -		} +		error = sooptcopyout(sopt, cmd, sizeof(*cmd));  		goto done;  	}  	ND("have %d:%d sched %d, %d:%d links %d, %d:%d flowsets %d, " @@ -2355,35 +2336,20 @@ dummynet_get(struct sockopt *sopt, void **compat)  	sopt->sopt_valsize = sopt_valsize;  	a.type = cmd->subtype; -	if (compat == NULL) { -		memcpy(start, cmd, sizeof(*cmd)); -		((struct dn_id*)(start))->len = sizeof(struct dn_id); -		buf = start + sizeof(*cmd); -	} else -		buf = start; +	memcpy(start, cmd, sizeof(*cmd)); +	((struct dn_id*)(start))->len = sizeof(struct dn_id); +	buf = start + sizeof(*cmd);  	a.start = &buf;  	a.end = start + have;  	/* start copying other objects */ -	if (compat) { -		a.type = DN_COMPAT_PIPE; -		dn_ht_scan(V_dn_cfg.schedhash, copy_data_helper_compat, &a); -		a.type = DN_COMPAT_QUEUE; -		dn_ht_scan(V_dn_cfg.fshash, copy_data_helper_compat, &a); -	} else if (a.type == DN_FS) { +	if (a.type == DN_FS) {  		dn_ht_scan(V_dn_cfg.fshash, copy_data_helper, &a);  	} else {  		dn_ht_scan(V_dn_cfg.schedhash, copy_data_helper, &a);  	}  	DN_BH_WUNLOCK(); -	if (compat) { -		*compat = start; -		sopt->sopt_valsize = buf - start; -		/* free() is done by ip_dummynet_compat() */ -		start = NULL; //XXX hack -	} else { -		error = sooptcopyout(sopt, start, buf - start); -	} +	error = sooptcopyout(sopt, start, buf - start);  done:  	if (cmd != &r.o)  		free(cmd, M_DUMMYNET); @@ -2519,17 +2485,9 @@ ip_dn_ctl(struct sockopt *sopt)  		error = EINVAL;  		break; -	case IP_DUMMYNET_FLUSH: -	case IP_DUMMYNET_CONFIGURE: -	case IP_DUMMYNET_DEL:	/* remove a pipe or queue */ -	case IP_DUMMYNET_GET: -		D("dummynet: compat option %d", sopt->sopt_name); -		error = ip_dummynet_compat(sopt); -		break; -  	case IP_DUMMYNET3:  		if (sopt->sopt_dir == SOPT_GET) { -			error = dummynet_get(sopt, NULL); +			error = dummynet_get(sopt);  			break;  		}  		l = sopt->sopt_valsize; diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c index 66bc99df2afa..de69ecbb0985 100644 --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -546,6 +546,9 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)  	PF_RULES_RASSERT(); +	if (strnlen(sp->pfs_1301.ifname, IFNAMSIZ) == IFNAMSIZ) +		return (EINVAL); +  	if (sp->pfs_1301.creatorid == 0) {  		if (V_pf_status.debug >= PF_DEBUG_MISC)  			printf("%s: invalid creator id: %08x\n", __func__, diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index fd70fb1c8a36..a39f5fe58cd6 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -1007,7 +1007,7 @@ pf_src_node_exists(struct pf_ksrc_node **sn, struct pf_srchash *sh)  	return (false);  } -static void +void  pf_free_src_node(struct pf_ksrc_node *sn)  { diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index a4557f139ae5..703ecf446fad 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -4792,6 +4792,17 @@ DIOCCHANGEADDR_error:  			error = ENODEV;  			goto fail;  		} +		if (strnlen(io->pfrio_table.pfrt_anchor, MAXPATHLEN) +		    == MAXPATHLEN) { +			error = EINVAL; +			goto fail; +		} +		if (strnlen(io->pfrio_table.pfrt_name, PF_TABLE_NAME_SIZE) +		    == PF_TABLE_NAME_SIZE) { +			error = EINVAL; +			goto fail; +		} +  		PF_RULES_WLOCK();  		error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,  		    io->pfrio_flags | PFR_FLAG_USERIOCTL); diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c index 5d85e16f18e3..7aeb8266ca8c 100644 --- a/sys/netpfil/pf/pf_lb.c +++ b/sys/netpfil/pf/pf_lb.c @@ -535,6 +535,63 @@ pf_get_mape_sport(struct pf_pdesc *pd, struct pf_krule *r,  	return (1);  } +static __inline  u_short +pf_check_src_node_valid(struct pf_ksrc_node *sn, struct pf_kpool *rpool) +{ +	struct pf_addr		*raddr, *rmask; +	struct pf_addr		*caddr; /* cached redirection address */ +	struct pf_kpooladdr	*pa; +	sa_family_t		 raf; +	sa_family_t		 caf; /* cached redirection AF */ +	u_short			 valid = 0; + +	KASSERT(sn != NULL, ("sn is NULL")); +	KASSERT(rpool != NULL, ("rpool is NULL")); + +	/* check if the cached entry is still valid */ + +	if (sn->type ==  PF_SN_LIMIT) { +		/* Always valid as it does not store redirection address */ +		return (1); +	} + +	mtx_lock(&rpool->mtx); +	caddr = &(sn->raddr); +	caf = sn->raf; + +	TAILQ_FOREACH(pa, &rpool->list, entries) { +		if (PF_AZERO(caddr, caf)) { +			valid = 1; +			goto done; +		} else if (pa->addr.type == PF_ADDR_DYNIFTL) { +			if (pfr_kentry_byaddr(pa->addr.p.dyn->pfid_kt, caddr, caf, 0)) { +				valid = 1; +				goto done; +			} +		} else if (pa->addr.type == PF_ADDR_TABLE) { +			if (pfr_kentry_byaddr(pa->addr.p.tbl, caddr, caf, 0)) { +				valid = 1; +				goto done; +			} +		} else if (pa->addr.type != PF_ADDR_NOROUTE) { +			/* PF_ADDR_URPFFAILED, PF_ADDR_RANGE, PF_ADDR_ADDRMASK */ +			raddr = &(pa->addr.v.a.addr); +			rmask = &(pa->addr.v.a.mask); +			raf = pa->af; +			if (raf == caf && pf_match_addr(0, raddr, rmask, caddr, caf)) { +				valid = 1; +				goto done; +			} +		} +		/* else PF_ADDR_NOROUTE */ +	} + +done: +	mtx_unlock(&rpool->mtx); + +	return (valid); +} +  u_short  pf_map_addr(sa_family_t saf, struct pf_krule *r, struct pf_addr *saddr,      struct pf_addr *naddr, struct pfi_kkif **nkif, sa_family_t *naf, @@ -874,6 +931,45 @@ pf_map_addr_sn(sa_family_t saf, struct pf_krule *r, struct pf_addr *saddr,  	if (sn != NULL) {  		PF_SRC_NODE_LOCK_ASSERT(sn); +		/* +		 * Check if source node's redirection address still exists +		 * in pool from which the SN was created. If not, delete it. +		 * Similar to pf_kill_srcnodes(). Unlink the source node +		 * from tree, unlink it from states, then free it. Do not +		 * overlap source node and state locks to avoid LOR. +		 */ +		if (!pf_check_src_node_valid(sn, rpool)) { +			pf_unlink_src_node(sn); +			PF_SRC_NODE_UNLOCK(sn); +			if (V_pf_status.debug >= PF_DEBUG_NOISY) { +				printf("%s: stale src tracking (%d) ", +				    __func__, sn_type); +				pf_print_host(saddr, 0, saf); +				printf(" to "); +				pf_print_host(&(sn->raddr), 0, sn->raf); +				if (nkif) +					printf("@%s", sn->rkif->pfik_name); +				printf("\n"); +			} + +			for (int i = 0; i <= V_pf_hashmask; i++) { +				struct pf_idhash *ih = &V_pf_idhash[i]; +				struct pf_kstate *st; + +				PF_HASHROW_LOCK(ih); +				LIST_FOREACH(st, &ih->states, entry) { +					if (st->sns[sn->type] == sn) { +						st->sns[sn->type] = NULL; +					} +				} +				PF_HASHROW_UNLOCK(ih); +			} +			pf_free_src_node(sn); +			counter_u64_add(V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS], 1); +			sn = NULL; +			goto map_addr; +		} +  		(*naf) = sn->raf;  		/* If the supplied address is the same as the current one we've @@ -902,9 +998,10 @@ pf_map_addr_sn(sa_family_t saf, struct pf_krule *r, struct pf_addr *saddr,  		goto done;  	} +map_addr:  	/* -	 * Source node has not been found. Find a new address and store it -	 * in variables given by the caller. +	 * Source node has not been found or is invalid. Find a new address +	 * and store it in variables given by the caller.  	 */  	if ((reason = pf_map_addr(saf, r, saddr, naddr, nkif, naf, init_addr,  	    rpool)) != 0) { @@ -974,6 +1071,7 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,  {  	struct pf_pdesc	*pd = ctx->pd;  	struct pf_addr	*naddr; +	int		 idx;  	uint16_t	*nportp;  	uint16_t	 low, high;  	u_short		 reason; @@ -988,8 +1086,19 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,  			return (PFRES_MEMORY);  	} -	naddr = &ctx->nk->addr[1]; -	nportp = &ctx->nk->port[1]; +	switch (nat_action) { +	case PF_NAT: +		idx = pd->sidx; +		break; +	case PF_BINAT: +		idx = 1; +		break; +	case PF_RDR: +		idx = pd->didx; +		break; +	} +	naddr = &ctx->nk->addr[idx]; +	nportp = &ctx->nk->port[idx];  	switch (nat_action) {  	case PF_NAT: diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index 73ec18fa7646..cf752ce0de18 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -2071,7 +2071,7 @@ pfr_lookup_table(struct pfr_table *tbl)  	    (struct pfr_ktable *)tbl));  } -static struct pfr_kentry * +struct pfr_kentry *  pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,      int exact)  { | 
