[Midnightbsd-cvs] src [11208] trunk/sbin/ipfw: sync with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun Jul 1 16:44:37 EDT 2018
Revision: 11208
http://svnweb.midnightbsd.org/src/?rev=11208
Author: laffer1
Date: 2018-07-01 16:44:37 -0400 (Sun, 01 Jul 2018)
Log Message:
-----------
sync with freebsd
Modified Paths:
--------------
trunk/sbin/ipfw/Makefile
trunk/sbin/ipfw/altq.c
trunk/sbin/ipfw/dummynet.c
trunk/sbin/ipfw/ipfw.8
trunk/sbin/ipfw/ipfw2.c
trunk/sbin/ipfw/ipfw2.h
trunk/sbin/ipfw/ipv6.c
trunk/sbin/ipfw/main.c
trunk/sbin/ipfw/nat.c
Property Changed:
----------------
trunk/sbin/ipfw/ipfw.8
Modified: trunk/sbin/ipfw/Makefile
===================================================================
--- trunk/sbin/ipfw/Makefile 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/Makefile 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,8 +1,17 @@
# $MidnightBSD$
+# $FreeBSD: stable/10/sbin/ipfw/Makefile 263086 2014-03-12 10:45:58Z glebius $
+.include <bsd.own.mk>
+
PROG= ipfw
-SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c altq.c
+SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c
WARNS?= 2
+
+.if ${MK_PF} != "no"
+SRCS+= altq.c
+CFLAGS+=-DPF
+.endif
+
DPADD= ${LIBUTIL}
LDADD= -lutil
MAN= ipfw.8
Modified: trunk/sbin/ipfw/altq.c
===================================================================
--- trunk/sbin/ipfw/altq.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/altq.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/altq.c 220802 2011-04-18 21:18:22Z glebius $
*
* altq interface
*/
Modified: trunk/sbin/ipfw/dummynet.c
===================================================================
--- trunk/sbin/ipfw/dummynet.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/dummynet.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,4 +1,12 @@
+/* $MidnightBSD$ */
/*
+ * Codel/FQ_Codel and PIE/FQ_PIE Code:
+ * Copyright (C) 2016 Centre for Advanced Internet Architectures,
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Portions of this code were made possible in part by a gift from
+ * The Comcast Innovation Fund.
+ * Implemented by Rasool Al-Saadi <ralsaadi at swin.edu.au>
+ *
* Copyright (c) 2002-2003,2010 Luigi Rizzo
*
* Redistribution and use in source forms, with and without modification,
@@ -10,11 +18,12 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/dummynet.c 320782 2017-07-07 15:35:42Z asomers $
*
* dummynet support
*/
+#define NEW_AQM
#include <sys/types.h>
#include <sys/socket.h>
/* XXX there are several sysctl leftover here */
@@ -22,6 +31,10 @@
#include "ipfw2.h"
+#ifdef NEW_AQM
+#include <stdint.h>
+#endif
+
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -56,8 +69,15 @@
{ "sched_mask", TOK_SCHED_MASK },
{ "flow_mask", TOK_FLOW_MASK },
{ "droptail", TOK_DROPTAIL },
+ { "ecn", TOK_ECN },
{ "red", TOK_RED },
{ "gred", TOK_GRED },
+#ifdef NEW_AQM
+ { "codel", TOK_CODEL}, /* Codel AQM */
+ { "fq_codel", TOK_FQ_CODEL}, /* FQ-Codel */
+ { "pie", TOK_PIE}, /* PIE AQM */
+ { "fq_pie", TOK_FQ_PIE}, /* FQ-PIE */
+#endif
{ "bw", TOK_BW },
{ "bandwidth", TOK_BW },
{ "delay", TOK_DELAY },
@@ -80,6 +100,32 @@
{ NULL, 0 } /* terminator */
};
+#ifdef NEW_AQM
+/* AQM/extra sched parameters tokens*/
+static struct _s_x aqm_params[] = {
+ { "target", TOK_TARGET},
+ { "interval", TOK_INTERVAL},
+ { "limit", TOK_LIMIT},
+ { "flows", TOK_FLOWS},
+ { "quantum", TOK_QUANTUM},
+ { "ecn", TOK_ECN},
+ { "noecn", TOK_NO_ECN},
+ { "tupdate", TOK_TUPDATE},
+ { "max_burst", TOK_MAX_BURST},
+ { "max_ecnth", TOK_MAX_ECNTH},
+ { "alpha", TOK_ALPHA},
+ { "beta", TOK_BETA},
+ { "capdrop", TOK_CAPDROP},
+ { "nocapdrop", TOK_NO_CAPDROP},
+ { "onoff", TOK_ONOFF},
+ { "dre", TOK_DRE},
+ { "ts", TOK_TS},
+ { "derand", TOK_DERAND},
+ { "noderand", TOK_NO_DERAND},
+ { NULL, 0 } /* terminator */
+};
+#endif
+
#define O_NEXT(p, len) ((void *)((char *)p + len))
static void
@@ -101,6 +147,214 @@
return ret;
}
+#ifdef NEW_AQM
+
+/* Codel flags */
+enum {
+ CODEL_ECN_ENABLED = 1
+};
+
+/* PIE flags, from PIE kernel module */
+enum {
+ PIE_ECN_ENABLED = 1,
+ PIE_CAPDROP_ENABLED = 2,
+ PIE_ON_OFF_MODE_ENABLED = 4,
+ PIE_DEPRATEEST_ENABLED = 8,
+ PIE_DERAND_ENABLED = 16
+};
+
+#define PIE_FIX_POINT_BITS 13
+#define PIE_SCALE (1L<<PIE_FIX_POINT_BITS)
+
+/* integer to time */
+void
+us_to_time(int t,char *strt)
+{
+ if (t < 0)
+ strt[0]='\0';
+ else if ( t==0 )
+ sprintf(strt,"%d", t);
+ else if (t< 1000)
+ sprintf(strt,"%dus", t);
+ else if (t < 1000000)
+ sprintf(strt,"%gms", (float) t / 1000);
+ else
+ sprintf(strt,"%gfs", (float) t / 1000000);
+}
+
+/*
+ * returns -1 if s is not a valid time, otherwise, return time in us
+ */
+static long
+time_to_us(const char *s)
+{
+ int i, dots = 0;
+ int len = strlen(s);
+ char strt[16]="", stru[16]="";
+
+ if (len>15)
+ return -1;
+ for (i = 0; i<len && (isdigit(s[i]) || s[i]=='.') ; i++)
+ if (s[i]=='.') {
+ if (dots)
+ return -1;
+ else
+ dots++;
+ }
+
+ if (!i)
+ return -1;
+ strncpy(strt, s, i);
+ if (i<len)
+ strcpy(stru, s+i);
+ else
+ strcpy(stru, "ms");
+
+ if (!strcasecmp(stru, "us"))
+ return atol(strt);
+ if (!strcasecmp(stru, "ms"))
+ return (strtod(strt, NULL) * 1000);
+ if (!strcasecmp(stru, "s"))
+ return (strtod(strt, NULL)*1000000);
+
+ return -1;
+}
+
+
+/* Get AQM or scheduler extra parameters */
+void
+get_extra_parms(uint32_t nr, char *out, int subtype)
+{
+ struct dn_extra_parms *ep;
+ int ret;
+ char strt1[15], strt2[15], strt3[15];
+ u_int l;
+
+ /* prepare the request */
+ l = sizeof(struct dn_extra_parms);
+ ep = safe_calloc(1, l);
+ memset(ep, 0, sizeof(*ep));
+ *out = '\0';
+
+ oid_fill(&ep->oid, l, DN_CMD_GET, DN_API_VERSION);
+ ep->oid.len = l;
+ ep->oid.subtype = subtype;
+ ep->nr = nr;
+
+ ret = do_cmd(-IP_DUMMYNET3, ep, (uintptr_t)&l);
+ if (ret) {
+ free(ep);
+ errx(EX_DATAERR, "Error getting extra parameters\n");
+ }
+
+ switch (subtype) {
+ case DN_AQM_PARAMS:
+ if( !strcasecmp(ep->name, "codel")) {
+ us_to_time(ep->par[0], strt1);
+ us_to_time(ep->par[1], strt2);
+ l = sprintf(out, " AQM CoDel target %s interval %s",
+ strt1, strt2);
+ if (ep->par[2] & CODEL_ECN_ENABLED)
+ l = sprintf(out + l, " ECN");
+ else
+ l += sprintf(out + l, " NoECN");
+ } else if( !strcasecmp(ep->name, "pie")) {
+ us_to_time(ep->par[0], strt1);
+ us_to_time(ep->par[1], strt2);
+ us_to_time(ep->par[2], strt3);
+ l = sprintf(out, " AQM type PIE target %s tupdate %s alpha "
+ "%g beta %g max_burst %s max_ecnth %.3g",
+ strt1,
+ strt2,
+ ep->par[4] / (float) PIE_SCALE,
+ ep->par[5] / (float) PIE_SCALE,
+ strt3,
+ ep->par[3] / (float) PIE_SCALE
+ );
+
+ if (ep->par[6] & PIE_ECN_ENABLED)
+ l += sprintf(out + l, " ECN");
+ else
+ l += sprintf(out + l, " NoECN");
+ if (ep->par[6] & PIE_CAPDROP_ENABLED)
+ l += sprintf(out + l, " CapDrop");
+ else
+ l += sprintf(out + l, " NoCapDrop");
+ if (ep->par[6] & PIE_ON_OFF_MODE_ENABLED)
+ l += sprintf(out + l, " OnOff");
+ if (ep->par[6] & PIE_DEPRATEEST_ENABLED)
+ l += sprintf(out + l, " DRE");
+ else
+ l += sprintf(out + l, " TS");
+ if (ep->par[6] & PIE_DERAND_ENABLED)
+ l += sprintf(out + l, " Derand");
+ else
+ l += sprintf(out + l, " NoDerand");
+ }
+ break;
+
+ case DN_SCH_PARAMS:
+ if (!strcasecmp(ep->name,"FQ_CODEL")) {
+ us_to_time(ep->par[0], strt1);
+ us_to_time(ep->par[1], strt2);
+ l = sprintf(out," FQ_CODEL target %s interval %s"
+ " quantum %jd limit %jd flows %jd",
+ strt1, strt2,
+ (intmax_t) ep->par[3],
+ (intmax_t) ep->par[4],
+ (intmax_t) ep->par[5]
+ );
+ if (ep->par[2] & CODEL_ECN_ENABLED)
+ l += sprintf(out + l, " ECN");
+ else
+ l += sprintf(out + l, " NoECN");
+ l += sprintf(out + l, "\n");
+ } else if (!strcasecmp(ep->name,"FQ_PIE")) {
+ us_to_time(ep->par[0], strt1);
+ us_to_time(ep->par[1], strt2);
+ us_to_time(ep->par[2], strt3);
+ l = sprintf(out, " FQ_PIE target %s tupdate %s alpha "
+ "%g beta %g max_burst %s max_ecnth %.3g"
+ " quantum %jd limit %jd flows %jd",
+ strt1,
+ strt2,
+ ep->par[4] / (float) PIE_SCALE,
+ ep->par[5] / (float) PIE_SCALE,
+ strt3,
+ ep->par[3] / (float) PIE_SCALE,
+ (intmax_t) ep->par[7],
+ (intmax_t) ep->par[8],
+ (intmax_t) ep->par[9]
+ );
+
+ if (ep->par[6] & PIE_ECN_ENABLED)
+ l += sprintf(out + l, " ECN");
+ else
+ l += sprintf(out + l, " NoECN");
+ if (ep->par[6] & PIE_CAPDROP_ENABLED)
+ l += sprintf(out + l, " CapDrop");
+ else
+ l += sprintf(out + l, " NoCapDrop");
+ if (ep->par[6] & PIE_ON_OFF_MODE_ENABLED)
+ l += sprintf(out + l, " OnOff");
+ if (ep->par[6] & PIE_DEPRATEEST_ENABLED)
+ l += sprintf(out + l, " DRE");
+ else
+ l += sprintf(out + l, " TS");
+ if (ep->par[6] & PIE_DERAND_ENABLED)
+ l += sprintf(out + l, " Derand");
+ else
+ l += sprintf(out + l, " NoDerand");
+ l += sprintf(out + l, "\n");
+ }
+ break;
+ }
+
+ free(ep);
+}
+#endif
+
+
#if 0
static int
sort_q(void *arg, const void *pa, const void *pb)
@@ -224,7 +478,7 @@
int l;
char qs[30];
char plr[30];
- char red[90]; /* Display RED parameters */
+ char red[200]; /* Display RED parameters */
l = fs->qsize;
if (fs->flags & DN_QSIZE_BYTES) {
@@ -239,7 +493,7 @@
else
plr[0] = '\0';
- if (fs->flags & DN_IS_RED) /* RED parameters */
+ if (fs->flags & DN_IS_RED) { /* RED parameters */
sprintf(red,
"\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
(fs->flags & DN_IS_GENTLE_RED) ? 'G' : ' ',
@@ -247,7 +501,14 @@
fs->min_th,
fs->max_th,
1.0 * fs->max_p / (double)(1 << SCALE_RED));
- else
+ if (fs->flags & DN_IS_ECN)
+ strncat(red, " (ecn)", 6);
+#ifdef NEW_AQM
+ /* get AQM parameters */
+ } else if (fs->flags & DN_IS_AQM) {
+ get_extra_parms(fs->fs_nr, red, DN_AQM_PARAMS);
+#endif
+ } else
sprintf(red, "droptail");
if (prefix[0]) {
@@ -337,6 +598,11 @@
printf(" sched %d type %s flags 0x%x %d buckets %d active\n",
s->sched_nr,
s->name, s->flags, s->buckets, s->oid.id);
+#ifdef NEW_AQM
+ char parms[200];
+ get_extra_parms(s->sched_nr, parms, DN_SCH_PARAMS);
+ printf("%s",parms);
+#endif
if (s->flags & DN_HAVE_MASK)
print_mask(&s->sched_mask);
}
@@ -534,8 +800,7 @@
warn("interface name truncated");
namelen--;
/* interface name */
- strncpy(if_name, arg, namelen);
- if_name[namelen] = '\0';
+ strlcpy(if_name, arg, namelen);
*bandwidth = 0;
} else { /* read bandwidth value */
int bw;
@@ -662,8 +927,7 @@
} else if (!strcasecmp(name, ED_TOK_NAME)) {
if (profile_name[0] != '\0')
errx(ED_EFMT("duplicated token: %s"), name);
- strncpy(profile_name, arg, sizeof(profile_name) - 1);
- profile_name[sizeof(profile_name)-1] = '\0';
+ strlcpy(profile_name, arg, sizeof(profile_name));
do_points = 0;
} else if (!strcasecmp(name, ED_TOK_DELAY)) {
if (do_points)
@@ -734,9 +998,245 @@
}
p->samples_no = samples;
p->loss_level = loss * samples;
- strncpy(p->name, profile_name, sizeof(p->name));
+ strlcpy(p->name, profile_name, sizeof(p->name));
}
+#ifdef NEW_AQM
+
+/* Parse AQM/extra scheduler parameters */
+static int
+process_extra_parms(int *ac, char **av, struct dn_extra_parms *ep,
+ uint16_t type)
+{
+ int i;
+
+ /* use kernel defaults */
+ for (i=0; i<DN_MAX_EXTRA_PARM; i++)
+ ep->par[i] = -1;
+
+ switch(type) {
+ case TOK_CODEL:
+ case TOK_FQ_CODEL:
+ /* Codel
+ * 0- target, 1- interval, 2- flags,
+ * FQ_CODEL
+ * 3- quantum, 4- limit, 5- flows
+ */
+ if (type==TOK_CODEL)
+ ep->par[2] = 0;
+ else
+ ep->par[2] = CODEL_ECN_ENABLED;
+
+ while (*ac > 0) {
+ int tok = match_token(aqm_params, *av);
+ (*ac)--; av++;
+ switch(tok) {
+ case TOK_TARGET:
+ if (*ac <= 0 || time_to_us(av[0]) < 0)
+ errx(EX_DATAERR, "target needs time\n");
+
+ ep->par[0] = time_to_us(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_INTERVAL:
+ if (*ac <= 0 || time_to_us(av[0]) < 0)
+ errx(EX_DATAERR, "interval needs time\n");
+
+ ep->par[1] = time_to_us(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_ECN:
+ ep->par[2] = CODEL_ECN_ENABLED;
+ break;
+ case TOK_NO_ECN:
+ ep->par[2] &= ~CODEL_ECN_ENABLED;
+ break;
+ /* Config fq_codel parameters */
+ case TOK_QUANTUM:
+ if (type != TOK_FQ_CODEL)
+ errx(EX_DATAERR, "quantum is not for codel\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "quantum needs number\n");
+
+ ep->par[3]= atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_LIMIT:
+ if (type != TOK_FQ_CODEL)
+ errx(EX_DATAERR, "limit is not for codel, use queue instead\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "limit needs number\n");
+
+ ep->par[4] = atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_FLOWS:
+ if (type != TOK_FQ_CODEL)
+ errx(EX_DATAERR, "flows is not for codel\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "flows needs number\n");
+
+ ep->par[5] = atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+ default:
+ printf("%s is Invalid parameter\n", av[-1]);
+ }
+ }
+ break;
+ case TOK_PIE:
+ case TOK_FQ_PIE:
+ /* PIE
+ * 0- target , 1- tupdate, 2- max_burst,
+ * 3- max_ecnth, 4- alpha,
+ * 5- beta, 6- flags
+ * FQ_CODEL
+ * 7- quantum, 8- limit, 9- flows
+ */
+
+ if ( type == TOK_PIE)
+ ep->par[6] = PIE_CAPDROP_ENABLED | PIE_DEPRATEEST_ENABLED
+ | PIE_DERAND_ENABLED;
+ else
+ /* for FQ-PIE, use TS mode */
+ ep->par[6] = PIE_CAPDROP_ENABLED | PIE_DERAND_ENABLED
+ | PIE_ECN_ENABLED;
+
+ while (*ac > 0) {
+ int tok = match_token(aqm_params, *av);
+ (*ac)--; av++;
+ switch(tok) {
+ case TOK_TARGET:
+ if (*ac <= 0 || time_to_us(av[0]) < 0)
+ errx(EX_DATAERR, "target needs time\n");
+
+ ep->par[0] = time_to_us(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_TUPDATE:
+ if (*ac <= 0 || time_to_us(av[0]) < 0)
+ errx(EX_DATAERR, "tupdate needs time\n");
+
+ ep->par[1] = time_to_us(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_MAX_BURST:
+ if (*ac <= 0 || time_to_us(av[0]) < 0)
+ errx(EX_DATAERR, "max_burst needs time\n");
+
+ ep->par[2] = time_to_us(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_MAX_ECNTH:
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "max_ecnth needs number\n");
+
+ ep->par[3] = atof(av[0]) * PIE_SCALE;
+ (*ac)--; av++;
+ break;
+
+ case TOK_ALPHA:
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "alpha needs number\n");
+
+ ep->par[4] = atof(av[0]) * PIE_SCALE;
+ (*ac)--; av++;
+ break;
+
+ case TOK_BETA:
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "beta needs number\n");
+
+ ep->par[5] = atof(av[0]) * PIE_SCALE;
+ (*ac)--; av++;
+ break;
+
+ case TOK_ECN:
+ ep->par[6] |= PIE_ECN_ENABLED;
+ break;
+ case TOK_NO_ECN:
+ ep->par[6] &= ~PIE_ECN_ENABLED;
+ break;
+
+ case TOK_CAPDROP:
+ ep->par[6] |= PIE_CAPDROP_ENABLED;
+ break;
+ case TOK_NO_CAPDROP:
+ ep->par[6] &= ~PIE_CAPDROP_ENABLED;
+ break;
+
+ case TOK_ONOFF:
+ ep->par[6] |= PIE_ON_OFF_MODE_ENABLED;
+ break;
+
+ case TOK_DRE:
+ ep->par[6] |= PIE_DEPRATEEST_ENABLED;
+ break;
+
+ case TOK_TS:
+ ep->par[6] &= ~PIE_DEPRATEEST_ENABLED;
+ break;
+
+ case TOK_DERAND:
+ ep->par[6] |= PIE_DERAND_ENABLED;
+ break;
+ case TOK_NO_DERAND:
+ ep->par[6] &= ~PIE_DERAND_ENABLED;
+ break;
+
+ /* Config fq_pie parameters */
+ case TOK_QUANTUM:
+ if (type != TOK_FQ_PIE)
+ errx(EX_DATAERR, "quantum is not for pie\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "quantum needs number\n");
+
+ ep->par[7]= atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_LIMIT:
+ if (type != TOK_FQ_PIE)
+ errx(EX_DATAERR, "limit is not for pie, use queue instead\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "limit needs number\n");
+
+ ep->par[8] = atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+ case TOK_FLOWS:
+ if (type != TOK_FQ_PIE)
+ errx(EX_DATAERR, "flows is not for pie\n");
+ if (*ac <= 0 || !is_valid_number(av[0]))
+ errx(EX_DATAERR, "flows needs number\n");
+
+ ep->par[9] = atoi(av[0]);
+ (*ac)--; av++;
+ break;
+
+
+ default:
+ printf("%s is invalid parameter\n", av[-1]);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#endif
+
+
/*
* configuration of pipes, schedulers, flowsets.
* When we configure a new scheduler, an empty pipe is created, so:
@@ -759,9 +1259,9 @@
void
ipfw_config_pipe(int ac, char **av)
{
- int i, j;
+ int i;
+ u_int j;
char *end;
- void *par = NULL;
struct dn_id *buf, *base;
struct dn_sch *sch = NULL;
struct dn_link *p = NULL;
@@ -768,6 +1268,12 @@
struct dn_fs *fs = NULL;
struct dn_profile *pf = NULL;
struct ipfw_flow_id *mask = NULL;
+#ifdef NEW_AQM
+ struct dn_extra_parms *aqm_extra;
+ struct dn_extra_parms *sch_extra;
+ int lmax_extra;
+#endif
+
int lmax;
uint32_t _foo = 0, *flags = &_foo , *buckets = &_foo;
@@ -779,6 +1285,15 @@
lmax += sizeof(struct dn_sch) + sizeof(struct dn_link) +
sizeof(struct dn_fs) + sizeof(struct dn_profile);
+#ifdef NEW_AQM
+ /* Extra Params */
+ lmax_extra = sizeof(struct dn_extra_parms);
+ /* two lmax_extra because one for AQM params and another
+ * sch params
+ */
+ lmax += lmax_extra*2;
+#endif
+
av++; ac--;
/* Pipe number */
if (ac && isdigit(**av)) {
@@ -804,8 +1319,16 @@
* The FIFO scheduler and link are derived from the
* WF2Q+ one in the kernel.
*/
+#ifdef NEW_AQM
+ sch_extra = o_next(&buf, lmax_extra, DN_TEXT);
+ sch_extra ->oid.subtype = 0; /* don't configure scheduler */
+#endif
sch = o_next(&buf, sizeof(*sch), DN_SCH);
p = o_next(&buf, sizeof(*p), DN_LINK);
+#ifdef NEW_AQM
+ aqm_extra = o_next(&buf, lmax_extra, DN_TEXT);
+ aqm_extra ->oid.subtype = 0; /* don't configure AQM */
+#endif
fs = o_next(&buf, sizeof(*fs), DN_FS);
sch->sched_nr = i;
@@ -823,6 +1346,10 @@
break;
case 2: /* "queue N config ... " */
+#ifdef NEW_AQM
+ aqm_extra = o_next(&buf, lmax_extra, DN_TEXT);
+ aqm_extra ->oid.subtype = 0;
+#endif
fs = o_next(&buf, sizeof(*fs), DN_FS);
fs->fs_nr = i;
mask = &fs->flow_mask;
@@ -831,7 +1358,15 @@
break;
case 3: /* "sched N config ..." */
+#ifdef NEW_AQM
+ sch_extra = o_next(&buf, lmax_extra, DN_TEXT);
+ sch_extra ->oid.subtype = 0;
+#endif
sch = o_next(&buf, sizeof(*sch), DN_SCH);
+#ifdef NEW_AQM
+ aqm_extra = o_next(&buf, lmax_extra, DN_TEXT);
+ aqm_extra ->oid.subtype = 0;
+#endif
fs = o_next(&buf, sizeof(*fs), DN_FS);
sch->sched_nr = i;
mask = &sch->sched_mask;
@@ -905,7 +1440,6 @@
* per-flow queue, mask is dst_ip, dst_port,
* src_ip, src_port, proto measured in bits
*/
- par = NULL;
bzero(mask, sizeof(*mask));
end = NULL;
@@ -1019,7 +1553,33 @@
} /* end while, config masks */
end_mask:
break;
+#ifdef NEW_AQM
+ case TOK_CODEL:
+ case TOK_PIE:
+ NEED(fs, "codel/pie is only for flowsets");
+ fs->flags &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
+ fs->flags |= DN_IS_AQM;
+
+ strlcpy(aqm_extra->name, av[-1],
+ sizeof(aqm_extra->name));
+ aqm_extra->oid.subtype = DN_AQM_PARAMS;
+
+ process_extra_parms(&ac, av, aqm_extra, tok);
+ break;
+
+ case TOK_FQ_CODEL:
+ case TOK_FQ_PIE:
+ if (!strcmp(av[-1],"type"))
+ errx(EX_DATAERR, "use type before fq_codel/fq_pie");
+
+ NEED(sch, "fq_codel/fq_pie is only for schd");
+ strlcpy(sch_extra->name, av[-1],
+ sizeof(sch_extra->name));
+ sch_extra->oid.subtype = DN_SCH_PARAMS;
+ process_extra_parms(&ac, av, sch_extra, tok);
+ break;
+#endif
case TOK_RED:
case TOK_GRED:
NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
@@ -1047,13 +1607,17 @@
}
if ((end = strsep(&av[0], "/"))) {
double max_p = strtod(end, NULL);
- if (max_p > 1 || max_p <= 0)
- errx(EX_DATAERR, "0 < max_p <= 1");
+ if (max_p > 1 || max_p < 0)
+ errx(EX_DATAERR, "0 <= max_p <= 1");
fs->max_p = (int)(max_p * (1 << SCALE_RED));
}
ac--; av++;
break;
+ case TOK_ECN:
+ fs->flags |= DN_IS_ECN;
+ break;
+
case TOK_DROPTAIL:
NEED(fs, "droptail is only for flowsets");
fs->flags &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
@@ -1080,9 +1644,23 @@
l = strlen(av[0]);
if (l == 0 || l > 15)
errx(1, "type %s too long\n", av[0]);
- strcpy(sch->name, av[0]);
+ strlcpy(sch->name, av[0], sizeof(sch->name));
sch->oid.subtype = 0; /* use string */
- ac--; av++;
+#ifdef NEW_AQM
+ /* if fq_codel is selected, consider all tokens after it
+ * as parameters
+ */
+ if (!strcasecmp(av[0],"fq_codel") || !strcasecmp(av[0],"fq_pie")){
+ strlcpy(sch_extra->name, av[0],
+ sizeof(sch_extra->name));
+ sch_extra->oid.subtype = DN_SCH_PARAMS;
+ process_extra_parms(&ac, av, sch_extra, tok);
+ } else {
+ ac--;av++;
+ }
+#else
+ ac--;av++;
+#endif
break;
}
@@ -1176,14 +1754,28 @@
errx(EX_DATAERR, "2 <= queue size <= %ld", limit);
}
+#ifdef NEW_AQM
+ if ((fs->flags & DN_IS_ECN) && !((fs->flags & DN_IS_RED)||
+ (fs->flags & DN_IS_AQM)))
+ errx(EX_USAGE, "ECN can be used with red/gred/"
+ "codel/fq_codel only!");
+#else
+ if ((fs->flags & DN_IS_ECN) && !(fs->flags & DN_IS_RED))
+ errx(EX_USAGE, "enable red/gred for ECN");
+
+#endif
+
if (fs->flags & DN_IS_RED) {
size_t len;
int lookup_depth, avg_pkt_size;
- double w_q;
- if (fs->min_th >= fs->max_th)
+ if (!(fs->flags & DN_IS_ECN) && (fs->min_th >= fs->max_th))
errx(EX_DATAERR, "min_th %d must be < than max_th %d",
fs->min_th, fs->max_th);
+ else if ((fs->flags & DN_IS_ECN) && (fs->min_th > fs->max_th))
+ errx(EX_DATAERR, "min_th %d must be =< than max_th %d",
+ fs->min_th, fs->max_th);
+
if (fs->max_th == 0)
errx(EX_DATAERR, "max_th must be > 0");
@@ -1205,6 +1797,7 @@
"net.inet.ip.dummynet.red_avg_pkt_size must"
" be greater than zero");
+#if 0 /* the following computation is now done in the kernel */
/*
* Ticks needed for sending a medium-sized packet.
* Unfortunately, when we are configuring a WF2Q+ queue, we
@@ -1214,12 +1807,10 @@
* correct. But on the other hand, why do we want RED with
* WF2Q+ ?
*/
-#if 0
if (p.bandwidth==0) /* this is a WF2Q+ queue */
s = 0;
else
s = (double)ck.hz * avg_pkt_size * 8 / p.bandwidth;
-#endif
/*
* max idle time (in ticks) before avg queue size becomes 0.
* NOTA: (3/w_q) is approx the value x so that
@@ -1226,7 +1817,6 @@
* (1-w_q)^x < 10^-3.
*/
w_q = ((double)fs->w_q) / (1 << SCALE_RED);
-#if 0 // go in kernel
idle = s * 3. / w_q;
fs->lookup_step = (int)idle / lookup_depth;
if (!fs->lookup_step)
@@ -1235,7 +1825,7 @@
for (t = fs->lookup_step; t > 1; --t)
weight *= 1 - w_q;
fs->lookup_weight = (int)(weight * (1 << SCALE_RED));
-#endif
+#endif /* code moved in the kernel */
}
}
@@ -1287,8 +1877,8 @@
av--;
}
if (v[1] < v[0] ||
- v[1] < 0 || v[1] >= DN_MAX_ID-1 ||
- v[0] < 0 || v[1] >= DN_MAX_ID-1) {
+ v[1] >= DN_MAX_ID-1 ||
+ v[1] >= DN_MAX_ID-1) {
continue; /* invalid entry */
}
n++;
@@ -1315,11 +1905,12 @@
dummynet_list(int ac, char *av[], int show_counters)
{
struct dn_id *oid, *x = NULL;
- int ret, i, l;
+ int ret, i;
int n; /* # of ranges */
- int buflen;
- int max_size; /* largest obj passed up */
+ u_int buflen, l;
+ u_int max_size; /* largest obj passed up */
+ (void)show_counters; // XXX unused, but we should use it.
ac--;
av++; /* skip 'list' | 'show' word */
Modified: trunk/sbin/ipfw/ipfw.8
===================================================================
--- trunk/sbin/ipfw/ipfw.8 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/ipfw.8 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,7 +1,8 @@
-.\"
.\" $MidnightBSD$
.\"
-.Dd October 25, 2012
+.\" $FreeBSD: stable/10/sbin/ipfw/ipfw.8 331202 2018-03-19 09:54:16Z ae $
+.\"
+.Dd March 12, 2018
.Dt IPFW 8
.Os
.Sh NAME
@@ -40,7 +41,6 @@
.Nm
.Cm set show
.Ss SYSCTL SHORTCUTS
-.Pp
.Nm
.Cm enable
.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
@@ -47,7 +47,6 @@
.Nm
.Cm disable
.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
-.Pp
.Ss LOOKUP TABLES
.Nm
.Cm table Ar number Cm add Ar addr Ns Oo / Ns Ar masklen Oc Op Ar value
@@ -61,7 +60,6 @@
.Cm table
.Brq Ar number | all
.Cm list
-.Pp
.Ss DUMMYNET CONFIGURATION (TRAFFIC SHAPER AND PACKET SCHEDULER)
.Nm
.Brq Cm pipe | queue | sched
@@ -73,7 +71,6 @@
.Brq Cm pipe | queue | sched
.Brq Cm delete | list | show
.Op Ar number ...
-.Pp
.Ss IN-KERNEL NAT
.Nm
.Op Fl q
@@ -145,7 +142,7 @@
.Em stateful
behaviour, i.e., upon a match it will create
.Em dynamic rules ,
-i.e. rules that match packets with the same 5-tuple
+i.e., rules that match packets with the same 5-tuple
(protocol, source and destination addresses and ports)
as the packet which caused their creation.
Dynamic rules, which have a limited lifetime, are checked
@@ -227,14 +224,15 @@
is specified, also show expired dynamic rules.
.It Fl f
Do not ask for confirmation for commands that can cause problems
-if misused,
-.No i.e. Cm flush .
+if misused, i.e.,
+.Cm flush .
If there is no tty associated with the process, this is implied.
.It Fl i
When listing a table (see the
.Sx LOOKUP TABLES
section below for more information on lookup tables), format values
-as IP addresses. By default, values are shown as integers.
+as IP addresses.
+By default, values are shown as integers.
.It Fl n
Only check syntax of the command strings, without actually passing
them to the kernel.
@@ -285,7 +283,6 @@
When listing, show last match timestamp as seconds from the epoch.
This form can be more convenient for postprocessing by scripts.
.El
-.Pp
.Ss LIST OF RULES AND PREPROCESSING
To ease configuration, rules can be put into a file which is
processed using
@@ -325,7 +322,6 @@
This allows for flexible configuration files (like conditionalizing
them on the local hostname) and the use of macros to centralize
frequently required arguments like IP addresses.
-.Pp
.Ss TRAFFIC SHAPER CONFIGURATION
The
.Nm
@@ -427,7 +423,7 @@
or may not be case-sensitive depending on their nature
(e.g.\& uid's are, hostnames are not).
.Pp
-Some arguments (e.g. port or address lists) are comma-separated
+Some arguments (e.g., port or address lists) are comma-separated
lists of values.
In this case, spaces after commas ',' are allowed to make
the line more readable.
@@ -566,7 +562,22 @@
.Xr bpf 4
attached to the
.Li ipfw0
-pseudo interface. There is no overhead if no
+pseudo interface.
+This pseudo interface can be created after a boot
+manually by using the following command:
+.Bd -literal -offset indent
+# ifconfig ipfw0 create
+.Ed
+.Pp
+Or, automatically at boot time by adding the following
+line to the
+.Xr rc.conf 5
+file:
+.Bd -literal -offset indent
+firewall_logif="YES"
+.Ed
+.Pp
+There is no overhead if no
.Xr bpf 4
is attached to the pseudo interface.
.Pp
@@ -844,7 +855,7 @@
and
.Cm return
actions don't do any jumps and simply go to the next rule if memory
-can't be allocated or stack overflowed/undeflowed.
+cannot be allocated or stack overflowed/underflowed.
.Pp
Internally stack for rule numbers is implemented using
.Xr mbuf_tags 9
@@ -859,7 +870,8 @@
action and returns ruleset processing to the first rule
with number greater than number of corresponding
.Cm call
-rule. See description of the
+rule.
+See description of the
.Cm call
action for more details.
.Pp
@@ -879,7 +891,6 @@
A workaround for this is to use new syntax and
.Fl c
switch:
-.Pp
.Bd -literal -offset indent
# Add a rule without actual body
ipfw add 2999 return via any
@@ -942,12 +953,14 @@
The packet is tagged so as to use the FIB (routing table)
.Ar fibnum
in any subsequent forwarding decisions.
-Initially this is limited to the values 0 through 15, see
-.Xr setfib 1 .
+In the current implementation, this is limited to the values 0 through 15, see
+.Xr setfib 2 .
Processing continues at the next rule.
It is possible to use the
.Cm tablearg
-keyword with a setfib. If tablearg value is not within compiled FIB range packet fib is set to 0.
+keyword with setfib.
+If the tablearg value is not within the compiled range of fibs,
+the packet's fib is set to 0.
.It Cm setdscp Ar DSCP | number | tablearg
Set specified DiffServ codepoint for an IPv4/IPv6 packet.
Processing continues at the next rule.
@@ -1004,21 +1017,27 @@
If the tablearg value is not within the 0..64 range, lower 6 bits of supplied
value are used.
.It Cm reass
-Queue and reassemble ip fragments.
-If the packet is not fragmented, counters are updated and processing continues with the next rule.
+Queue and reassemble IPv4 fragments.
+If the packet is not fragmented, counters are updated and
+processing continues with the next rule.
If the packet is the last logical fragment, the packet is reassembled and, if
.Va net.inet.ip.fw.one_pass
-is set to 0, processing continues with the next rule, else packet is allowed to pass and search terminates.
-If the packet is a fragment in the middle, it is consumed and processing stops immediately.
+is set to 0, processing continues with the next rule.
+Otherwise, the packet is allowed to pass and the search terminates.
+If the packet is a fragment in the middle of a logical group of fragments,
+it is consumed and
+processing stops immediately.
.Pp
-Fragments handling can be tuned via
+Fragment handling can be tuned via
.Va net.inet.ip.maxfragpackets
and
.Va net.inet.ip.maxfragsperpacket
-which limit, respectively, the maximum number of processable fragments (default: 800) and
+which limit, respectively, the maximum number of processable
+fragments (default: 800) and
the maximum number of fragments per packet (default: 16).
.Pp
-NOTA BENE: since fragments do not contain port numbers, they should be avoided with the
+NOTA BENE: since fragments do not contain port numbers,
+they should be avoided with the
.Nm reass
rule.
Alternatively, direction-based (like
@@ -1497,7 +1516,7 @@
field value is contained in
.Ar spec
mask.
-Multiple values can be specified via
+Multiple values can be specified via
the comma separated list.
Value can be one of keywords used in
.Cm setdscp
@@ -1579,7 +1598,6 @@
.Pp
Note that the ampersand character has a special meaning in many shells
and should generally be escaped.
-.Pp
.El
Note that the order of MAC addresses (destination first,
source second) is
@@ -1603,9 +1621,9 @@
.It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar table Ns Pq Ar number Ns Op , Ns Ar value | Ar ipno | Ar any
Matches packets received, transmitted or going through,
respectively, the interface specified by exact name
-.Ns No ( Ar ifX Ns No ),
+.Po Ar ifX Pc ,
by device name
-.Ns No ( Ar if Ns Ar * Ns No ),
+.Po Ar if* Pc ,
by IP address, or through some interface.
.Pp
The
@@ -1649,7 +1667,8 @@
.It Cm sockarg
Matches packets that are associated to a local socket and
for which the SO_USER_COOKIE socket option has been set
-to a non-zero value. As a side effect, the value of the
+to a non-zero value.
+As a side effect, the value of the
option is made available as
.Cm tablearg
value, which in turn can be used as
@@ -1799,9 +1818,9 @@
.El
.Sh LOOKUP TABLES
Lookup tables are useful to handle large sparse sets of
-addresses or other search keys (e.g. ports, jail IDs, interface names).
+addresses or other search keys (e.g., ports, jail IDs, interface names).
In the rest of this section we will use the term ``address''.
-There may be up to 4096 different lookup tables, numbered 0 to 4095.
+There may be up to 65535 different lookup tables, numbered 0 to 65534.
.Pp
Each entry is represented by an
.Ar addr Ns Op / Ns Ar masklen
@@ -1837,7 +1856,8 @@
.Xr route 4 ) .
.Pp
Lookup tables currently support only ports, jail IDs, IPv4/IPv6 addresses
-and interface names. Wildcards is not supported for interface names.
+and interface names.
+Wildcards is not supported for interface names.
.Pp
The
.Cm tablearg
@@ -1866,7 +1886,8 @@
When used with the
.Cm skipto
action, the user should be aware that the code will walk the ruleset
-up to a rule equal to, or past, the given number, and should therefore try keep the
+up to a rule equal to, or past, the given number,
+and should therefore try keep the
ruleset compact between the skipto and the target rules.
.Sh SETS OF RULES
Each rule belongs to one of 32 different
@@ -2074,10 +2095,12 @@
for each /24 destination subnet.
.Pp
The FLOW_MASK, together with the SCHED_MASK, is used to split
-packets into flows. As an example, using
+packets into flows.
+As an example, using
``src-ip 0x000000ff''
together with the previous SCHED_MASK makes a flow for
-each individual source address. In turn, flows for each /24
+each individual source address.
+In turn, flows for each /24
subnet will be sent to the same scheduler instance.
.Pp
The above diagram holds even for the
@@ -2196,12 +2219,13 @@
of a packet on the link.
.Pp
Some link types introduce extra delays in the transmission
-of a packet, e.g. because of MAC level framing, contention on
+of a packet, e.g., because of MAC level framing, contention on
the use of the channel, MAC level retransmissions and so on.
From our point of view, the channel is effectively unavailable
for this extra time, which is constant or variable depending
-on the link type. Additionally, packets may be dropped after this
-time (e.g. on a wireless link after too many retransmissions).
+on the link type.
+Additionally, packets may be dropped after this
+time (e.g., on a wireless link after too many retransmissions).
We can model the additional delay with an empirical curve
that represents its distribution.
.Bd -literal -offset indent
@@ -2237,7 +2261,7 @@
explicitly as a configuration parameter for the pipe;
.It Cm loss-level Ar L
the probability above which packets are lost.
-(0.0 <= L <= 1.0, default 1.0 i.e. no loss);
+(0.0 <= L <= 1.0, default 1.0 i.e., no loss);
.It Cm samples Ar N
the number of samples used in the internal
representation of the curve (2..1024; default 100);
@@ -2302,7 +2326,8 @@
.It Cm wf2q+
implements the WF2Q+ algorithm, which is a Weighted Fair Queueing
algorithm which permits flows to share bandwidth according to
-their weights. Note that weights are not priorities; even a flow
+their weights.
+Note that weights are not priorities; even a flow
with a minuscule weight will never starve.
WF2Q+ has O(log N) per-packet processing cost, where N is the number
of flows, and is the default algorithm used by previous versions
@@ -2417,12 +2442,13 @@
control the maximum lengths that can be specified.
.Pp
.It Cm red | gred Ar w_q Ns / Ns Ar min_th Ns / Ns Ar max_th Ns / Ns Ar max_p
+[ecn]
Make use of the RED (Random Early Detection) queue management algorithm.
.Ar w_q
and
.Ar max_p
are floating
-point numbers between 0 and 1 (0 not included), while
+point numbers between 0 and 1 (inclusive), while
.Ar min_th
and
.Ar max_th
@@ -2429,10 +2455,10 @@
are integer numbers specifying thresholds for queue management
(thresholds are computed in bytes if the queue has been defined
in bytes, in slots otherwise).
-The
+The two parameters can also be of the same value if needed. The
.Nm dummynet
-also supports the gentle RED variant (gred).
-Three
+also supports the gentle RED variant (gred) and ECN (Explicit Congestion
+Notification) as optional. Three
.Xr sysctl 8
variables can be used to control the RED behaviour:
.Bl -tag -width indent
@@ -2533,7 +2559,6 @@
not loaded, or if the kernel was not compiled with divert socket support,
the packets are dropped.
.Sh NETWORK ADDRESS TRANSLATION (NAT)
-.Pp
.Nm
support in-kernel NAT using the kernel version of
.Xr libalias 3 .
@@ -2589,7 +2614,8 @@
.Xr natd 8
for more information.
.It Cm tablearg
-Uses argument supplied in lookup table. See
+Uses argument supplied in lookup table.
+See
.Sx LOOKUP TABLES
section below for more information on lookup tables.
.El
@@ -2651,11 +2677,13 @@
before ipfw module gets loaded.
.Bl -tag -width indent
.It Va net.inet.ip.fw.default_to_accept: No 0
-Defines ipfw last rule behavior. This value overrides
+Defines ipfw last rule behavior.
+This value overrides
.Cd "options IPFW_DEFAULT_TO_(ACCEPT|DENY)"
from kernel configuration file.
.It Va net.inet.ip.fw.tables_max: No 128
-Defines number of tables available in ipfw. Number cannot exceed 65534.
+Defines number of tables available in ipfw.
+Number cannot exceed 65534.
.El
.Sh SYSCTL VARIABLES
A set of
@@ -2685,12 +2713,14 @@
An attacker can
establish multiple fake associations by sending AddIP messages.
.It Va net.inet.ip.alias.sctp.chunk_proc_limit: No 5
-Defines the maximum number of chunks in an SCTP packet that will be parsed for a
+Defines the maximum number of chunks in an SCTP packet that will be
+parsed for a
packet that matches an existing association.
This value is enforced to be greater or equal than
.Cm net.inet.ip.alias.sctp.initialising_chunk_proc_limit .
A high value is
-a DoS risk yet setting too low a value may result in important control chunks in
+a DoS risk yet setting too low a value may result in
+important control chunks in
the packet not being located and parsed.
.It Va net.inet.ip.alias.sctp.error_on_ootb: No 1
Defines when the
@@ -2712,7 +2742,8 @@
.Nm nat
is tracking global IP addresses.
.It Cm 3
-ErrorM is sent in response to all OOTB packets on both the local and global side
+ErrorM is sent in response to all OOTB packets on both
+the local and global side
(DoS risk).
.El
.Pp
@@ -2763,12 +2794,14 @@
A higher value may become a DoS
risk as malformed packets can consume processing resources.
.It Va net.inet.ip.alias.sctp.param_proc_limit: No 25
-Defines the maximum number of parameters within a chunk that will be parsed in a
+Defines the maximum number of parameters within a chunk that will be
+parsed in a
packet.
As for other similar sysctl variables, larger values pose a DoS risk.
.It Va net.inet.ip.alias.sctp.log_level: No 0
Level of detail in the system log messages (0 \- minimal, 1 \- event,
-2 \- info, 3 \- detail, 4 \- debug, 5 \- max debug). May be a good
+2 \- info, 3 \- detail, 4 \- debug, 5 \- max debug).
+May be a good
option in high loss environments.
.It Va net.inet.ip.alias.sctp.shutdown_time: No 15
Timeout value while waiting for SHUTDOWN-COMPLETE.
@@ -2787,7 +2820,8 @@
.El
.Pp
This variable is fully dynamic, the new value will be adopted for all newly
-arriving associations, existing associations are treated as they were previously.
+arriving associations, existing associations are treated
+as they were previously.
Global tracking will decrease the number of collisions within the
.Nm nat
at a cost
@@ -2931,7 +2965,6 @@
.Nm .
Default is no.
.El
-.Pp
.Sh EXAMPLES
There are far too many possible uses of
.Nm
@@ -3017,16 +3050,6 @@
by adding the following to the appropriate place in ruleset:
.Pp
.Dl "ipfw add setdscp be ip from any to any dscp af11,af21"
-.Pp
-This rule drops all incoming packets that appear to be coming from another
-directly connected system but on the wrong interface.
-For example, a packet with a source address of
-.Li 192.168.0.0/24 ,
-configured on
-.Li fxp0 ,
-but coming in on
-.Li fxp1
-would be dropped.
.Ss DYNAMIC RULES
In order to protect a site from flood attacks involving fake
TCP packets, it is safer to use dynamic rules:
@@ -3039,9 +3062,11 @@
those connection which start with a regular SYN packet coming
from the inside of our network.
Dynamic rules are checked when encountering the first
-.Cm check-state
+occurrence of a
+.Cm check-state ,
+.Cm keep-state
or
-.Cm keep-state
+.Cm limit
rule.
A
.Cm check-state
@@ -3086,7 +3111,6 @@
to divert port 5000:
.Pp
.Dl ipfw divert 5000 ip from 192.168.2.0/24 to any in
-.Pp
.Ss TRAFFIC SHAPING
The following rules show some of the applications of
.Nm
@@ -3303,7 +3327,6 @@
.Dl " 10.0.0.100"
.Dl "ipfw nat 5 config redirect_port tcp"
.Dl " 192.168.0.1:80,192.168.0.10:22,192.168.0.20:25 500"
-.Pp
.Sh SEE ALSO
.Xr cpp 1 ,
.Xr m4 1 ,
@@ -3352,13 +3375,14 @@
traffic shaper supported by Akamba Corp.
.Pp
The ipfw core (ipfw2) has been completely redesigned and
-reimplemented by Luigi Rizzo in summer 2002. Further
+reimplemented by Luigi Rizzo in summer 2002.
+Further
actions and
options have been added by various developer over the years.
.Pp
.An -nosplit
In-kernel NAT support written by
-.An Paolo Pisati Aq piso at FreeBSD.org
+.An Paolo Pisati Aq Mt piso at FreeBSD.org
as part of a Summer of Code 2005 project.
.Pp
SCTP
Property changes on: trunk/sbin/ipfw/ipfw.8
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sbin/ipfw/ipfw2.c
===================================================================
--- trunk/sbin/ipfw/ipfw2.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/ipfw2.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/ipfw2.c 296311 2016-03-02 13:38:21Z ae $
*/
#include <sys/types.h>
@@ -60,6 +61,8 @@
int ipfw_socket = -1;
+uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
+
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
@@ -455,7 +458,7 @@
* and calls setsockopt().
* Function returns 0 on success or -1 otherwise.
*/
-int
+static int
do_setcmd3(int optname, void *optval, socklen_t optlen)
{
socklen_t len;
@@ -536,8 +539,8 @@
* of the first. A warning is printed to stderr in the case that the
* first string does not match the third.
*
- * This function exists to warn about the bizzare construction
- * strncmp(str, "by", 2) which is used to allow people to use a shotcut
+ * This function exists to warn about the bizarre construction
+ * strncmp(str, "by", 2) which is used to allow people to use a shortcut
* for "bytes". The problem is that in addition to accepting "by",
* "byt", "byte", and "bytes", it also excepts "by_rabid_dogs" and any
* other string beginning with "by".
@@ -777,7 +780,7 @@
errx(EX_DATAERR, "Invalid DSCP value");
}
- if (code > 32)
+ if (code >= 32)
*high |= 1 << (code - 32);
else
*low |= 1 << code;
@@ -1092,8 +1095,9 @@
#define HAVE_OPTIONS 0x8000
static void
-show_prerequisites(int *flags, int want, int cmd __unused)
+show_prerequisites(int *flags, int want, int cmd)
{
+ (void)cmd; /* UNUSED */
if (co.comment_only)
return;
if ( (*flags & HAVE_IP) == HAVE_IP)
@@ -2202,6 +2206,7 @@
{
int len = 0;
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+ uint32_t tables_max;
cmd->o.len &= ~F_LEN_MASK; /* zero len */
@@ -2220,6 +2225,10 @@
*p++ = '\0';
cmd->o.opcode = O_IP_DST_LOOKUP;
cmd->o.arg1 = strtoul(av + 6, NULL, 0);
+ tables_max = ipfw_get_tables_max();
+ if (cmd->o.arg1 > tables_max)
+ errx(EX_USAGE, "The table number exceeds the maximum "
+ "allowed value (%u)", tables_max - 1);
if (p) {
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
d[0] = strtoul(p, NULL, 0);
@@ -2260,14 +2269,14 @@
case '/':
masklen = atoi(p);
if (masklen == 0)
- d[1] = htonl(0); /* mask */
+ d[1] = htonl(0U); /* mask */
else if (masklen > 32)
errx(EX_DATAERR, "bad width ``%s''", p);
else
- d[1] = htonl(~0 << (32 - masklen));
+ d[1] = htonl(~0U << (32 - masklen));
break;
case '{': /* no mask, assume /24 and put back the '{' */
- d[1] = htonl(~0 << (32 - 24));
+ d[1] = htonl(~0U << (32 - 24));
*(--p) = md;
break;
@@ -2276,7 +2285,7 @@
/* FALLTHROUGH */
case 0: /* initialization value */
default:
- d[1] = htonl(~0); /* force /32 */
+ d[1] = htonl(~0U); /* force /32 */
break;
}
d[0] &= d[1]; /* mask base address with mask */
@@ -2778,13 +2787,19 @@
add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen)
{
struct in6_addr a;
- char *host, *ch;
+ char *host, *ch, buf[INET6_ADDRSTRLEN];
ipfw_insn *ret = NULL;
+ int len;
- if ((host = strdup(av)) == NULL)
- return NULL;
- if ((ch = strrchr(host, '/')) != NULL)
- *ch = '\0';
+ /* Copy first address in set if needed */
+ if ((ch = strpbrk(av, "/,")) != NULL) {
+ len = ch - av;
+ strlcpy(buf, av, sizeof(buf));
+ if (len < sizeof(buf))
+ buf[len] = '\0';
+ host = buf;
+ } else
+ host = av;
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, host, &a) == 1)
@@ -2796,7 +2811,6 @@
if (ret == NULL && strcmp(av, "any") != 0)
ret = cmd;
- free(host);
return ret;
}
@@ -2804,13 +2818,19 @@
add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen)
{
struct in6_addr a;
- char *host, *ch;
+ char *host, *ch, buf[INET6_ADDRSTRLEN];
ipfw_insn *ret = NULL;
+ int len;
- if ((host = strdup(av)) == NULL)
- return NULL;
- if ((ch = strrchr(host, '/')) != NULL)
- *ch = '\0';
+ /* Copy first address in set if needed */
+ if ((ch = strpbrk(av, "/,")) != NULL) {
+ len = ch - av;
+ strlcpy(buf, av, sizeof(buf));
+ if (len < sizeof(buf))
+ buf[len] = '\0';
+ host = buf;
+ } else
+ host = av;
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, host, &a) == 1)
@@ -2822,7 +2842,6 @@
if (ret == NULL && strcmp(av, "any") != 0)
ret = cmd;
- free(host);
return ret;
}
@@ -2972,7 +2991,7 @@
action->opcode = O_NAT;
action->len = F_INSN_SIZE(ipfw_insn_nat);
CHECK_ACTLEN;
- if (_substrcmp(*av, "global") == 0) {
+ if (*av != NULL && _substrcmp(*av, "global") == 0) {
action->arg1 = 0;
av++;
break;
@@ -3071,9 +3090,9 @@
((struct sockaddr_in*)&result)->sin_addr.s_addr =
INADDR_ANY;
} else {
- /*
+ /*
* Resolve the host name or address to a family and a
- * network representation of the addres.
+ * network representation of the address.
*/
if (getaddrinfo(*av, NULL, NULL, &res))
errx(EX_DATAERR, NULL);
@@ -4108,6 +4127,33 @@
static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
/*
+ * Retrieve maximum number of tables supported by ipfw(4) module.
+ */
+uint32_t
+ipfw_get_tables_max()
+{
+ size_t len;
+ uint32_t tables_max;
+
+ if (ipfw_tables_max != 0)
+ return (ipfw_tables_max);
+
+ len = sizeof(tables_max);
+ if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
+ NULL, 0) == -1) {
+ if (co.test_only)
+ tables_max = 128; /* Old conservative default */
+ else
+ errx(1, "Can't determine maximum number of ipfw tables."
+ " Perhaps you forgot to load ipfw module?");
+ }
+
+ ipfw_tables_max = tables_max;
+
+ return (ipfw_tables_max);
+}
+
+/*
* This one handles all table-related commands
* ipfw table N add addr[/masklen] [value]
* ipfw table N delete addr[/masklen]
@@ -4120,19 +4166,10 @@
ipfw_table_xentry xent;
int do_add;
int is_all;
- size_t len;
uint32_t a;
uint32_t tables_max;
- len = sizeof(tables_max);
- if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
- NULL, 0) == -1) {
- if (co.test_only)
- tables_max = 128; /* Old conservative default */
- else
- errx(1, "Can't determine maximum number of ipfw tables."
- " Perhaps you forgot to load ipfw module?");
- }
+ tables_max = ipfw_get_tables_max();
memset(&xent, 0, sizeof(xent));
@@ -4263,13 +4300,24 @@
addrlen = sizeof(struct in6_addr);
} else {
/* Port or any other key */
+ /* Skip non-base 10 entries like 'fa1' */
key = strtol(arg, &p, 10);
- /* Skip non-base 10 entries like 'fa1' */
- if (p != arg) {
+ if (*p == '\0') {
pkey = (uint32_t *)paddr;
*pkey = htonl(key);
type = IPFW_TABLE_CIDR;
+ masklen = 32;
addrlen = sizeof(uint32_t);
+ } else if ((p != arg) && (*p == '.')) {
+ /*
+ * Warn on IPv4 address strings
+ * which are "valid" for inet_aton() but not
+ * in inet_pton().
+ *
+ * Typical examples: '10.5' or '10.0.0.05'
+ */
+ errx(EX_DATAERR,
+ "Invalid IPv4 address: %s", arg);
}
}
}
@@ -4342,7 +4390,7 @@
addr6 = &xent->k.addr6;
- if (IN6_IS_ADDR_V4COMPAT(addr6)) {
+ if ((xent->flags & IPFW_TCF_INET) != 0) {
/* IPv4 address */
inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
} else {
@@ -4371,7 +4419,7 @@
if (sz < xent->len)
break;
sz -= xent->len;
- xent = (void *)xent + xent->len;
+ xent = (ipfw_table_xentry *)((char *)xent + xent->len);
}
free(tbl);
Modified: trunk/sbin/ipfw/ipfw2.h
===================================================================
--- trunk/sbin/ipfw/ipfw2.h 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/ipfw2.h 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/ipfw2.h 301772 2016-06-10 00:00:25Z truckman $
*/
/*
@@ -165,8 +166,34 @@
TOK_BURST,
TOK_RED,
TOK_GRED,
+ TOK_ECN,
TOK_DROPTAIL,
TOK_PROTO,
+#ifdef NEW_AQM
+ /* AQM tokens*/
+ TOK_NO_ECN,
+ TOK_CODEL,
+ TOK_FQ_CODEL,
+ TOK_TARGET,
+ TOK_INTERVAL,
+ TOK_FLOWS,
+ TOK_QUANTUM,
+
+ TOK_PIE,
+ TOK_FQ_PIE,
+ TOK_TUPDATE,
+ TOK_MAX_BURST,
+ TOK_MAX_ECNTH,
+ TOK_ALPHA,
+ TOK_BETA,
+ TOK_CAPDROP,
+ TOK_NO_CAPDROP,
+ TOK_ONOFF,
+ TOK_DRE,
+ TOK_TS,
+ TOK_DERAND,
+ TOK_NO_DERAND,
+#endif
/* dummynet tokens */
TOK_WEIGHT,
TOK_LMAX,
@@ -228,6 +255,8 @@
int do_cmd(int optname, void *optval, uintptr_t optlen);
+uint32_t ipfw_get_tables_max(void);
+
struct in6_addr;
void n2mask(struct in6_addr *mask, int n);
int contigmask(uint8_t *p, int len);
@@ -266,11 +295,14 @@
void ipfw_zero(int ac, char *av[], int optname);
void ipfw_list(int ac, char *av[], int show_counters);
+#ifdef PF
/* altq.c */
void altq_set_enabled(int enabled);
u_int32_t altq_name_to_qid(const char *name);
-
void print_altq_cmd(struct _ipfw_insn_altq *altqptr);
+#else
+#define NO_ALTQ
+#endif
/* dummynet.c */
void dummynet_list(int ac, char *av[], int show_counters);
Modified: trunk/sbin/ipfw/ipv6.c
===================================================================
--- trunk/sbin/ipfw/ipv6.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/ipv6.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/ipv6.c 318271 2017-05-14 13:59:40Z marius $
*
* ipv6 support
*/
@@ -338,6 +339,7 @@
{
int len = 0;
struct in6_addr *d = &(cmd->addr6);
+ char *oav;
/*
* Needed for multiple address.
* Note d[1] points to struct in6_add r mask6 of cmd
@@ -375,7 +377,7 @@
return (1);
}
- av = strdup(av);
+ oav = av = strdup(av);
while (av) {
/*
* After the address we can have '/' indicating a mask,
@@ -451,7 +453,7 @@
if (len + 1 > F_LEN_MASK)
errx(EX_DATAERR, "address list too long");
cmd->o.len |= len+1;
- free(av);
+ free(oav);
return (1);
}
Modified: trunk/sbin/ipfw/main.c
===================================================================
--- trunk/sbin/ipfw/main.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/main.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003,2010 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* Command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/main.c 229778 2012-01-07 16:09:33Z uqs $
*/
#include <sys/wait.h>
@@ -122,9 +123,9 @@
break;
if (copy) {
arg[j++] = arg[i];
- copy = !index("," WHITESP, arg[i]);
+ copy = !strchr("," WHITESP, arg[i]);
} else {
- copy = !index(WHITESP, arg[i]);
+ copy = !strchr(WHITESP, arg[i]);
if (copy)
arg[j++] = arg[i];
}
@@ -141,7 +142,7 @@
* processing, this is just the number of blanks plus 1.
*/
for (i = 0, ac = 1; i < l; i++)
- if (index(WHITESP, arg[i]) != NULL)
+ if (strchr(WHITESP, arg[i]) != NULL)
ac++;
/*
@@ -162,12 +163,12 @@
*/
av_p = (char *)&av[ac+1];
for (ac = 1, i = j = 0; i < l; i++) {
- if (index(WHITESP, arg[i]) != NULL || i == l-1) {
+ if (strchr(WHITESP, arg[i]) != NULL || i == l-1) {
if (i == l-1)
i++;
bcopy(arg+j, av_p, i-j);
av[ac] = av_p;
- av_p += i-j; /* the lenght of the string */
+ av_p += i-j; /* the length of the string */
*av_p++ = '\0';
ac++;
j = i + 1;
@@ -240,7 +241,7 @@
" ipfw sysctl -a\n");
return 0;
}
- s = index(av[2], '=');
+ s = strchr(av[2], '=');
if (s == NULL) {
s = !strcmp(av[2], "-a") ? NULL : av[2];
sysctlbyname(s, NULL, NULL, NULL, 0);
@@ -309,6 +310,7 @@
case 'p':
errx(EX_USAGE, "An absolute pathname must be used "
"with -p option.");
+ /* NOTREACHED */
case 'q':
co.do_quiet = 1;
Modified: trunk/sbin/ipfw/nat.c
===================================================================
--- trunk/sbin/ipfw/nat.c 2018-07-01 20:42:37 UTC (rev 11207)
+++ trunk/sbin/ipfw/nat.c 2018-07-01 20:44:37 UTC (rev 11208)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
@@ -17,7 +18,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sbin/ipfw/nat.c 278324 2015-02-06 18:13:29Z jhb $
*
* In-kernel nat support
*/
@@ -156,9 +157,9 @@
}
}
if (sin == NULL)
- errx(1, "%s: cannot get interface address", ifn);
-
- n->ip = sin->sin_addr;
+ n->ip.s_addr = htonl(INADDR_ANY);
+ else
+ n->ip = sin->sin_addr;
strncpy(n->if_name, ifn, IF_NAMESIZE);
free(buf);
@@ -318,6 +319,7 @@
char *sep = **av;
u_int c = 0;
+ (void)ac; /* UNUSED */
while ((sep = strchr(sep, ',')) != NULL) {
c++;
sep++;
@@ -379,6 +381,7 @@
char *sep = **av;
u_int c = 0;
+ (void)ac; /* UNUSED */
while ((sep = strchr(sep, ',')) != NULL) {
c++;
sep++;
@@ -419,7 +422,7 @@
/*
* Extract local address.
*/
- if ((sep = strchr(**av, ',')) != NULL) {
+ if (strchr(**av, ',') != NULL) {
r->laddr.s_addr = INADDR_NONE;
r->lport = ~0;
numLocalPorts = 1;
@@ -452,7 +455,7 @@
/*
* Extract public port and optionally address.
*/
- if ((sep = strchr(**av, ':')) != NULL) {
+ if (strchr(**av, ':') != NULL) {
if (StrToAddrAndPortRange(**av, &r->paddr, protoName,
&portRange) != 0)
errx(EX_DATAERR, "redirect_port: "
@@ -480,7 +483,7 @@
* option for this redirect entry, else stop here processing arg[cv].
*/
if (*ac != 0 && isdigit(***av)) {
- if ((sep = strchr(**av, ':')) != NULL) {
+ if (strchr(**av, ':') != NULL) {
if (StrToAddrAndPortRange(**av, &r->raddr, protoName,
&portRange) != 0)
errx(EX_DATAERR, "redirect_port: "
More information about the Midnightbsd-cvs
mailing list