diff options
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ifconfig/Makefile | 1 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 18 | ||||
-rw-r--r-- | sbin/ifconfig/ifpfsync.c | 3 | ||||
-rw-r--r-- | sbin/ifconfig/ifstf.c | 157 | ||||
-rw-r--r-- | sbin/ifconfig/ifvlan.c | 37 | ||||
-rw-r--r-- | sbin/ipfw/Makefile | 2 | ||||
-rw-r--r-- | sbin/ipfw/context.c | 148 | ||||
-rw-r--r-- | sbin/ipfw/dummynet.c | 6 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.c | 185 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.h | 4 | ||||
-rw-r--r-- | sbin/ipfw/main.c | 23 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 373 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 39 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_altq.c | 20 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 80 | ||||
-rw-r--r-- | sbin/route/route.c | 5 | ||||
-rw-r--r-- | sbin/setkey/parse.y | 23 | ||||
-rw-r--r-- | sbin/setkey/setkey.8 | 3 | ||||
-rw-r--r-- | sbin/setkey/token.l | 5 |
19 files changed, 1028 insertions, 104 deletions
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index 84509d7..0718081 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -34,6 +34,7 @@ SRCS+= ifvlan.c # SIOC[GS]ETVLAN support SRCS+= ifvxlan.c # VXLAN support SRCS+= ifgre.c # GRE keys etc SRCS+= ifgif.c # GIF reversed header workaround +SRCS+= ifstf.c # STF configuration options SRCS+= sfp.c # SFP/SFP+ information DPADD+= ${LIBM} diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index a374f09..40b485d 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -651,6 +651,23 @@ top: return(0); } +static void +setaddrfirst(const char *addr, int dummy __unused, int s, + const struct afswtch *afp) +{ + + if (afp == NULL) + err(2, "No address family"); + if (afp->af_getaddr == NULL) + err(2, "No appropriate functions from address family"); + afp->af_getaddr(addr, ADDR); + + strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); + printf("Interface name: %s, socket %d, addr %s\n", name, s, addr); + if (ioctl(s, SIOCORDERIFADDR, afp->af_addreq) < 0) + err(1, "SIOCORDERIFADDR"); +} + /*ARGSUSED*/ static void setifaddr(const char *addr, int param, int s, const struct afswtch *afp) @@ -1248,6 +1265,7 @@ static struct cmd basic_cmds[] = { DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), DEF_CMD_ARG("name", setifname), + DEF_CMD_ARG("setfirst", setaddrfirst), }; static __constructor void diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c index 9dbe1d6..4094610 100644 --- a/sbin/ifconfig/ifpfsync.c +++ b/sbin/ifconfig/ifpfsync.c @@ -203,7 +203,8 @@ pfsync_status(int s) if (preq.pfsyncr_syncdev[0] != '\0' || preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP) { printf("maxupd: %d ", preq.pfsyncr_maxupdates); - printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); + printf("defer: %s\n", (preq.pfsyncr_defer & PFSYNCF_DEFER) ? "on" : "off"); + printf("\tsyncok: %d\n", (preq.pfsyncr_defer & PFSYNCF_OK) ? 1 : 0); } } diff --git a/sbin/ifconfig/ifstf.c b/sbin/ifconfig/ifstf.c new file mode 100644 index 0000000..7d58909 --- /dev/null +++ b/sbin/ifconfig/ifstf.c @@ -0,0 +1,157 @@ +/*- + * Copyright 2013 Ermal Luci + * 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 WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sockio.h> + +#include <stdlib.h> +#include <unistd.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <sys/mbuf.h> +#include <net/if_stf.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <err.h> +#include <errno.h> + +#include "ifconfig.h" + +static int +do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) +{ + struct ifdrv ifd; + + memset(&ifd, 0, sizeof(ifd)); + + strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); + ifd.ifd_cmd = op; + ifd.ifd_len = argsize; + ifd.ifd_data = arg; + + return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); +} + +static void +stf_status(int s) +{ + struct stfv4args param; + + if (do_cmd(s, STF_GV4NET, ¶m, sizeof(param), 0) < 0) + return; + + printf("\tv4net %s/%d -> ", inet_ntoa(param.inaddr), param.prefix ? param.prefix : 32); + printf("tv4br %s\n", inet_ntoa(param.dstv4_addr)); + + return; +} + +static void +setstf_br(const char *val, int d, int s, const struct afswtch *afp) +{ + struct stfv4args req; + struct sockaddr_in sin; + + memset(&req, 0, sizeof(req)); + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + if (!inet_aton(val, &sin.sin_addr)) + errx(1, "%s: bad value", val); + + req.dstv4_addr = sin.sin_addr; + if (do_cmd(s, STF_SDSTV4, &req, sizeof(req), 1) < 0) + err(1, "STF_SV4DST %s", val); +} + +static void +setstf_set(const char *val, int d, int s, const struct afswtch *afp) +{ + struct stfv4args req; + struct sockaddr_in sin; + const char *errstr; + char *p = NULL; + + memset(&req, 0, sizeof(req)); + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + p = strrchr(val, '/'); + if (p == NULL) + errx(2, "Wrong argument given"); + + *p = '\0'; + if (!isdigit(*(p + 1))) + errstr = "invalid"; + else + req.prefix = (int)strtonum(p + 1, 0, 32, &errstr); + if (errstr != NULL) { + *p = '/'; + errx(1, "%s: bad value (width %s)", val, errstr); + } + + if (!inet_aton(val, &sin.sin_addr)) + errx(1, "%s: bad value", val); + + req.inaddr = sin.sin_addr; + if (do_cmd(s, STF_SV4NET, &req, sizeof(req), 1) < 0) + err(1, "STF_SV4NET %s", val); +} + +static struct cmd stf_cmds[] = { + DEF_CMD_ARG("stfv4net", setstf_set), + DEF_CMD_ARG("stfv4br", setstf_br), +}; +static struct afswtch af_stf = { + .af_name = "af_stf", + .af_af = AF_UNSPEC, + .af_other_status = stf_status, +}; + +static __constructor void +stf_ctor(void) +{ +#define N(a) (sizeof(a) / sizeof(a[0])) + int i; + + for (i = 0; i < N(stf_cmds); i++) + cmd_register(&stf_cmds[i]); + af_register(&af_stf); +#undef N +} diff --git a/sbin/ifconfig/ifvlan.c b/sbin/ifconfig/ifvlan.c index 944ae17..714e4e0 100644 --- a/sbin/ifconfig/ifvlan.c +++ b/sbin/ifconfig/ifvlan.c @@ -1,6 +1,10 @@ /* - * Copyright (c) 1999 - * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. + * Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu> + * Copyright (c) 2012 ADARA Networks, Inc. + * All rights reserved. + * + * Portions of this software were developed by Robert N. M. Watson under + * contract to ADARA Networks, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,10 +83,14 @@ vlan_status(int s) { struct vlanreq vreq; - if (getvlan(s, &ifr, &vreq) != -1) - printf("\tvlan: %d parent interface: %s\n", - vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? - "<none>" : vreq.vlr_parent); + if (getvlan(s, &ifr, &vreq) == -1) + return; + printf("\tvlan: %d", vreq.vlr_tag); + if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) + printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); + printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? + "<none>" : vreq.vlr_parent); + printf("\n"); } static void @@ -150,6 +158,22 @@ DECL_CMD_FUNC(setvlandev, val, d) } static +DECL_CMD_FUNC(setvlanpcp, val, d) +{ + u_long ul; + char *endp; + + ul = strtoul(val, &endp, 0); + if (*endp != '\0') + errx(1, "invalid value for vlanpcp"); + if (ul > 7) + errx(1, "value for vlanpcp out of range"); + ifr.ifr_vlan_pcp = ul; + if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1) + err(1, "SIOCSVLANPCP"); +} + +static DECL_CMD_FUNC(unsetvlandev, val, d) { struct vlanreq vreq; @@ -170,6 +194,7 @@ DECL_CMD_FUNC(unsetvlandev, val, d) static struct cmd vlan_cmds[] = { DEF_CLONE_CMD_ARG("vlan", setvlantag), DEF_CLONE_CMD_ARG("vlandev", setvlandev), + DEF_CMD_ARG("vlanpcp", setvlanpcp), /* NB: non-clone cmds */ DEF_CMD_ARG("vlan", setvlantag), DEF_CMD_ARG("vlandev", setvlandev), diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile index 6aea26b..e137e08 100644 --- a/sbin/ipfw/Makefile +++ b/sbin/ipfw/Makefile @@ -3,7 +3,7 @@ .include <bsd.own.mk> PROG= ipfw -SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c +SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c context.c WARNS?= 2 .if ${MK_PF} != "no" diff --git a/sbin/ipfw/context.c b/sbin/ipfw/context.c new file mode 100644 index 0000000..bce576e --- /dev/null +++ b/sbin/ipfw/context.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013 Ermal Lu�i + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_var.h> + +#include <netinet/in.h> +#include <netinet/ip_fw.h> + +#include "ipfw2.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sysexits.h> +#include <string.h> +#include <errno.h> +#include <err.h> + +extern int ipfw_socket; + +int +ipfw_context_handler(int ac, char **av) +{ + ip_fw3_opheader *op3; + int error = 0; + uint32_t action = 0; + socklen_t len, nlen; + char *ifname; + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "list", strlen(*av))) { + action = IP_FW_CTX_GET; + av++; + ac--; + if (ac > 0) + errx(EX_DATAERR, "list: does not take any extra arguments."); + + } else { + co.ctx = atoi(*av); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "create", strlen(*av))) + action = IP_FW_CTX_ADD; + else if (!strncmp(*av, "destroy", strlen(*av))) + action = IP_FW_CTX_DEL; + else { + if (!strncmp(*av, "madd", strlen(*av))) + action = IP_FW_CTX_ADDMEMBER; + else if (!strncmp(*av, "mdel", strlen(*av))) + action = IP_FW_CTX_DELMEMBER; + else + errx(EX_DATAERR, "Wrong parameters passed"); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + ifname = *av; + } + + ac--; + if (ac > 0) + errx(EX_DATAERR, "context handling: Too many arguments passed"); + + } + + if (co.test_only) + return (0); + + if (ipfw_socket < 0) + ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (ipfw_socket < 0) + err(EX_UNAVAILABLE, "socket"); + + switch (action) { + case IP_FW_CTX_ADD: + case IP_FW_CTX_DEL: + case IP_FW_CTX_SET: + len = sizeof(ip_fw3_opheader); + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_ADDMEMBER: + case IP_FW_CTX_DELMEMBER: + len = sizeof(ip_fw3_opheader) + strlen(ifname) + 1; + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader) + strlen(ifname) + 1); + memcpy((op3 + 1), ifname, strlen(ifname)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_GET: + len = sizeof(ip_fw3_opheader) + 1000; + nlen = len; + do { + if (nlen > len) { + len = nlen; + } + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, len); + op3->opcode = action; + op3->ctxid = co.ctx; + nlen = len; + error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, &nlen); + } while (nlen > len && !error); + + if (!error) { + if (nlen == 0) + printf("There are no contexts defined\n"); + else + printf("Currently defined contexts and their members:\n%s\n", (char *)op3); + } else + err(EX_UNAVAILABLE, "Error returned: %s\n", strerror(error)); + + break; + } + + return (error); +} diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c index e1fcef9..5c3ee39 100644 --- a/sbin/ipfw/dummynet.c +++ b/sbin/ipfw/dummynet.c @@ -803,10 +803,10 @@ read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) if_name[namelen] = '\0'; *bandwidth = 0; } else { /* read bandwidth value */ - int bw; + double bw; char *end = NULL; - bw = strtoul(arg, &end, 0); + bw = strtod(arg, &end); if (*end == 'K' || *end == 'k') { end++; bw *= 1000; @@ -822,7 +822,7 @@ read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) if (bw < 0) errx(EX_DATAERR, "bandwidth too large"); - *bandwidth = bw; + *bandwidth = (int)bw; if (if_name) if_name[0] = '\0'; } diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index f585ded..6d7d3d7 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -54,7 +54,7 @@ #include <netinet/tcp.h> #include <arpa/inet.h> -struct cmdline_opts co; /* global options */ +struct cmdline_opts co = { 0 }; /* global options */ int resvd_set_number = RESVD_SET; @@ -422,6 +422,7 @@ safe_realloc(void *ptr, size_t size) int do_cmd(int optname, void *optval, uintptr_t optlen) { + ip_fw3_opheader op3; int i; if (co.test_only) @@ -432,6 +433,15 @@ do_cmd(int optname, void *optval, uintptr_t optlen) if (ipfw_socket < 0) err(EX_UNAVAILABLE, "socket"); + if (optname != IP_FW3 && optname != IP_DUMMYNET3 && optname != -IP_DUMMYNET3) { + memset(&op3, 0, sizeof op3); + op3.ctxid = co.ctx; + op3.opcode = IP_FW_CTX_SET; + i = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, &op3, sizeof(op3)); + if (i) + errx(EX_OSERR, "setsockopt: choosing context"); + } + if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET || optname == IP_FW_ADD || optname == IP_FW3 || optname == IP_FW_NAT_GET_CONFIG || @@ -477,6 +487,7 @@ do_setcmd3(int optname, void *optval, socklen_t optlen) memset(op3, 0, sizeof(ip_fw3_opheader)); memcpy(op3 + 1, optval, optlen); op3->opcode = optname; + op3->ctxid = co.ctx; return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); } @@ -4122,8 +4133,9 @@ ipfw_flush(int force) } +static void table_list_entry(ipfw_table_xentry *); static void table_list(uint16_t num, int need_header); -static void table_fill_xentry(char *arg, ipfw_table_xentry *xent); +static void table_fill_xentry(int ac, char *av[], ipfw_table_xentry *xent); /* * Retrieve maximum number of tables supported by ipfw(4) module. @@ -4194,29 +4206,9 @@ ipfw_table_handler(int ac, char *av[]) if (_substrcmp(*av, "add") == 0 || _substrcmp(*av, "delete") == 0) { do_add = **av == 'a'; - ac--; av++; - if (!ac) - errx(EX_USAGE, "address required"); - table_fill_xentry(*av, &xent); + table_fill_xentry(ac, av, &xent); - ac--; av++; - if (do_add && ac) { - unsigned int tval; - /* isdigit is a bit of a hack here.. */ - if (strchr(*av, (int)'.') == NULL && isdigit(**av)) { - xent.value = strtoul(*av, NULL, 0); - } else { - if (lookup_host(*av, (struct in_addr *)&tval) == 0) { - /* The value must be stored in host order * - * so that the values < 65k can be distinguished */ - xent.value = ntohl(tval); - } else { - errx(EX_NOHOST, "hostname ``%s'' unknown", *av); - } - } - } else - xent.value = 0; if (do_setcmd3(do_add ? IP_FW_TABLE_XADD : IP_FW_TABLE_XDEL, &xent, xent.len) < 0) { /* If running silent, don't bomb out on these errors. */ @@ -4243,19 +4235,41 @@ ipfw_table_handler(int ac, char *av[]) do { table_list(xent.tbl, is_all); } while (++xent.tbl < a); + } else if (_substrcmp(*av, "entrystats") == 0) { + table_fill_xentry(ac, av, &xent); + + if (do_setcmd3(IP_FW_TABLE_XLISTENTRY, &xent, xent.len) < 0) { + /* If running silent, don't bomb out on these errors. */ + if (!(co.do_quiet)) + err(EX_OSERR, "setsockopt(IP_FW_TABLE_XLISTENTRY)"); + } else + table_list_entry(&xent); + } else if (_substrcmp(*av, "entryzerostats") == 0) { + table_fill_xentry(ac, av, &xent); + + if (do_setcmd3(IP_FW_TABLE_XZEROENTRY, &xent, xent.len) < 0) { + /* If running silent, don't bomb out on these errors. */ + if (!(co.do_quiet)) + err(EX_OSERR, "setsockopt(IP_FW_TABLE_XZEROENTRY)"); + } } else errx(EX_USAGE, "invalid table command %s", *av); } static void -table_fill_xentry(char *arg, ipfw_table_xentry *xent) +table_fill_xentry(int ac, char *av[], ipfw_table_xentry *xent) { - int addrlen, mask, masklen, type; + int addrlen, mask, masklen, type, do_add; struct in6_addr *paddr; uint32_t *pkey; - char *p; + char *p, *arg; uint32_t key; + do_add = **av == 'a'; + ac--; av++; + if (!ac) + errx(EX_USAGE, "address required"); + mask = 0; type = 0; addrlen = 0; @@ -4270,7 +4284,20 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent) * 4) port, uid/gid or other u32 key (base 10 format) * 5) hostname */ - paddr = &xent->k.addr6; + if (ac > 1 && av && _substrcmp(*av, "mac") == 0) { + uint8_t _mask[8]; + + type = IPFW_TABLE_MIX; + get_mac_addr_mask(av[1], (uint8_t *)xent->mac_addr, _mask); + ac-=2; av+=2; + if (ac <= 0) + errx(EX_DATAERR, "wrong argument passed."); + + paddr = (struct in6_addr *)&xent->k.addr6; + } else + paddr = &xent->k.addr6; + + arg = *av; if (ishexnumber(*arg) != 0 || *arg == ':') { /* Remove / if exists */ if ((p = strchr(arg, '/')) != NULL) { @@ -4283,9 +4310,11 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent) errx(EX_DATAERR, "bad IPv4 mask width: %s", p + 1); - type = IPFW_TABLE_CIDR; + if (type == 0) + type = IPFW_TABLE_CIDR; masklen = p ? mask : 32; addrlen = sizeof(struct in_addr); + xent->flags = IPFW_TCF_INET; } else if (inet_pton(AF_INET6, arg, paddr) == 1) { if (IN6_IS_ADDR_V4COMPAT(paddr)) errx(EX_DATAERR, @@ -4294,10 +4323,14 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent) errx(EX_DATAERR, "bad IPv6 mask width: %s", p + 1); - type = IPFW_TABLE_CIDR; + if (type == 0) + type = IPFW_TABLE_CIDR; masklen = p ? mask : 128; addrlen = sizeof(struct in6_addr); } else { + if (type != 0 && type != IPFW_TABLE_MIX) + errx(EX_DATAERR, "Wrong value passed as address"); + /* Port or any other key */ /* Skip non-base 10 entries like 'fa1' */ key = strtol(arg, &p, 10); @@ -4338,11 +4371,88 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent) masklen = 32; type = IPFW_TABLE_CIDR; addrlen = sizeof(struct in_addr); + xent->flags = IPFW_TCF_INET; + } + + ac--; av++; + if (ac > 1 && av) { + if (_substrcmp(*av, "mac") == 0) { + uint8_t _mask[8]; + + if (type == 0) + type = IPFW_TABLE_CIDR; + get_mac_addr_mask(av[1], (uint8_t *)&xent->mac_addr, _mask); + ac-=2; av+=2; + } } + if (do_add && ac > 0) { + unsigned int tval; + /* isdigit is a bit of a hack here.. */ + if (strchr(*av, (int)'.') == NULL && isdigit(**av)) { + xent->value = strtoul(*av, NULL, 0); + } else { + if (lookup_host(*av, (struct in_addr *)&tval) == 0) { + /* The value must be stored in host order * + * so that the values < 65k can be distinguished */ + xent->value = ntohl(tval); + } else { + errx(EX_NOHOST, "hostname ``%s'' unknown", *av); + } + } + } else + xent->value = 0; + xent->type = type; xent->masklen = masklen; - xent->len = offsetof(ipfw_table_xentry, k) + addrlen; + if (type == IPFW_TABLE_MIX) + xent->len = offsetof(ipfw_table_xentry, k) + addrlen + ETHER_ADDR_LEN; + else + xent->len = offsetof(ipfw_table_xentry, k) + addrlen; +} + +static void +table_list_entry(ipfw_table_xentry *xent) +{ + struct in6_addr *addr6; + uint32_t tval; + char tbuf[128]; + + switch (xent->type) { + case IPFW_TABLE_CIDR: + /* IPv4 or IPv6 prefixes */ + tval = xent->value; + addr6 = &xent->k.addr6; + + if ((xent->flags & IPFW_TCF_INET) != 0) { + /* IPv4 address */ + inet_ntop(AF_INET, (in_addr_t *)&addr6->s6_addr32[0], tbuf, sizeof(tbuf)); + } else { + /* IPv6 address */ + inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf)); + } + + if (co.do_value_as_ip) { + tval = htonl(tval); + printf("%s/%u %s %d %d %u\n", tbuf, xent->masklen, + inet_ntoa(*(struct in_addr *)&tval), pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp); + } else + printf("%s/%u %u %d %d %u\n", tbuf, xent->masklen, tval, + pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp); + break; + case IPFW_TABLE_INTERFACE: + /* Interface names */ + tval = xent->value; + if (co.do_value_as_ip) { + tval = htonl(tval); + printf("%s %u %s %d %d %u\n", xent->k.iface, xent->masklen, + inet_ntoa(*(struct in_addr *)&tval), pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp); + } else + printf("%s %u %u %d %d %u\n", xent->k.iface, xent->masklen, tval, + pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp); + + break; + } } static void @@ -4364,6 +4474,7 @@ table_list(uint16_t num, int need_header) a = (uint32_t *)(op3 + 1); *a = num; op3->opcode = IP_FW_TABLE_XGETSIZE; + op3->ctxid = co.ctx; if (do_cmd(IP_FW3, op3, (uintptr_t)&l) < 0) err(EX_OSERR, "getsockopt(IP_FW_TABLE_XGETSIZE)"); @@ -4374,6 +4485,7 @@ table_list(uint16_t num, int need_header) l = *a; tbl = safe_calloc(1, l); tbl->opheader.opcode = IP_FW_TABLE_XLIST; + tbl->opheader.ctxid = co.ctx; tbl->tbl = num; if (do_cmd(IP_FW3, tbl, (uintptr_t)&l) < 0) err(EX_OSERR, "getsockopt(IP_FW_TABLE_XLIST)"); @@ -4388,21 +4500,24 @@ table_list(uint16_t num, int need_header) tval = xent->value; addr6 = &xent->k.addr6; - if ((xent->flags & IPFW_TCF_INET) != 0) { /* IPv4 address */ - inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf)); + inet_ntop(AF_INET, &addr6->s6_addr32[0], tbuf, sizeof(tbuf)); } else { /* IPv6 address */ inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf)); } + printf("%s/%u", tbuf, xent->masklen); + if (xent->mac_addr) + printf(" mac %s", ether_ntoa((struct ether_addr *)&xent->mac_addr)); + if (co.do_value_as_ip) { tval = htonl(tval); - printf("%s/%u %s\n", tbuf, xent->masklen, + printf(" %s\n", inet_ntoa(*(struct in_addr *)&tval)); } else - printf("%s/%u %u\n", tbuf, xent->masklen, tval); + printf(" %u\n", tval); break; case IPFW_TABLE_INTERFACE: /* Interface names */ @@ -4413,6 +4528,8 @@ table_list(uint16_t num, int need_header) inet_ntoa(*(struct in_addr *)&tval)); } else printf("%s %u\n", xent->k.iface, tval); + + break; } if (sz < xent->len) diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 4f3e0c9..98646f5 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -54,6 +54,7 @@ struct cmdline_opts { int use_set; /* work with specified set number */ /* 0 means all sets, otherwise apply to set use_set - 1 */ + u_int ctx; }; extern struct cmdline_opts co; @@ -308,6 +309,9 @@ void dummynet_list(int ac, char *av[], int show_counters); void dummynet_flush(void); int ipfw_delete_pipe(int pipe_or_queue, int n); +/* Contextes */ +int ipfw_context_handler(int, char **); + /* ipv6.c */ void print_unreach6_code(uint16_t code); void print_ip6(struct _ipfw_insn_ip6 *cmd, char const *s); diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c index 82a299b..ab75a1b 100644 --- a/sbin/ipfw/main.c +++ b/sbin/ipfw/main.c @@ -262,7 +262,7 @@ ipfw_main(int oldac, char **oldav) save_av = av; optind = optreset = 1; /* restart getopt() */ - while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtv")) != -1) + while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtvx:")) != -1) switch (ch) { case 'a': do_acct = 1; @@ -335,6 +335,12 @@ ipfw_main(int oldac, char **oldav) co.verbose = 1; break; + case 'x': + co.ctx = atoi(optarg); + if (co.ctx == 0) + errx(EX_USAGE, "Context 0 is invalid"); + break; + default: free(save_av); return 1; @@ -362,7 +368,9 @@ ipfw_main(int oldac, char **oldav) co.do_nat = 0; co.do_pipe = 0; co.use_set = 0; - if (!strncmp(*av, "nat", strlen(*av))) + if (!strncmp(*av, "zone", strlen(*av))) + return (ipfw_context_handler(ac, av)); + else if (!strncmp(*av, "nat", strlen(*av))) co.do_nat = 1; else if (!strncmp(*av, "pipe", strlen(*av))) co.do_pipe = 1; @@ -389,6 +397,9 @@ ipfw_main(int oldac, char **oldav) } NEED1("missing command"); + if (!co.ctx && !co.do_pipe) + err(11, "Context is mandatory"); + /* * For pipes, queues and nats we normally say 'nat|pipe NN config' * but the code is easier to parse as 'nat|pipe config NN' @@ -458,7 +469,7 @@ ipfw_readfile(int ac, char *av[]) FILE *f = NULL; pid_t preproc = 0; - while ((c = getopt(ac, av, "cfNnp:qS")) != -1) { + while ((c = getopt(ac, av, "cfNnp:qSx:")) != -1) { switch(c) { case 'c': co.do_compact = 1; @@ -509,6 +520,12 @@ ipfw_readfile(int ac, char *av[]) co.show_sets = 1; break; + case 'x': + co.ctx = atoi(optarg); + if (co.ctx == 0) + errx(EX_USAGE, "Context 0 is invalid"); + break; + default: errx(EX_USAGE, "bad arguments, for usage" " summary ``ipfw''"); diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index e468a38..5c0becd 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #endif #include <net/if.h> +#include <net/ethernet.h> +#include <net/if_vlan_var.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -160,6 +162,7 @@ struct node_icmp { enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, + PF_STATE_OPT_MAX_PACKETS, PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, }; @@ -171,6 +174,7 @@ struct node_state_opt { u_int32_t max_states; u_int32_t max_src_states; u_int32_t max_src_conn; + u_int32_t max_packets; struct { u_int32_t limit; u_int32_t seconds; @@ -217,6 +221,7 @@ struct filter_opts { #define FOM_TOS 0x04 #define FOM_KEEP 0x08 #define FOM_SRCTRACK 0x10 +#define FOM_DSCP 0x20 struct node_uid *uid; struct node_gid *gid; struct { @@ -227,7 +232,9 @@ struct filter_opts { } flags; struct node_icmp *icmpspec; u_int32_t tos; + u_int32_t dscp; u_int32_t prob; + u_int32_t tracker; struct { int action; struct node_state_opt *options; @@ -235,10 +242,19 @@ struct filter_opts { int fragment; int allowopts; char *label; + char *schedule; struct node_qassign queues; char *tag; char *match_tag; u_int8_t match_tag_not; + struct { + uint8_t pcp[2]; + uint8_t op; + uint8_t setpcp; + } ieee8021q_pcp; + u_int32_t dnpipe; + u_int32_t pdnpipe; + u_int32_t free_flags; u_int rtableid; struct { struct node_host *addr; @@ -248,6 +264,7 @@ struct filter_opts { struct antispoof_opts { char *label; + u_int32_t tracker; u_int rtableid; } antispoof_opts; @@ -340,6 +357,7 @@ int expand_skip_interface(struct node_if *); int check_rulestate(int); int getservice(char *); int rule_label(struct pf_rule *, char *); +int rule_schedule(struct pf_rule *, char *); int rt_tableid_max(void); void mv_rules(struct pf_ruleset *, struct pf_ruleset *); @@ -441,11 +459,11 @@ int parseport(char *, struct range *r, int); %} -%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS +%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF -%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL -%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE +%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL SCHEDULE +%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DSCP DROP TABLE TRACKER %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID @@ -453,17 +471,19 @@ int parseport(char *, struct range *r, int); %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL +%token DNPIPE DNQUEUE %token LOAD RULESET_OPTIMIZATION %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY -%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS +%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS MAXPCKT +%token IEEE8021QPCP IEEE8021QSETPCP %token DIVERTTO DIVERTREPLY %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTBINARY %type <v.interface> interface if_list if_item_not if_item %type <v.number> number icmptype icmp6type uid gid -%type <v.number> tos not yesno +%type <v.number> tos dscp not yesno %type <v.probability> probability %type <v.i> no dir af fragcache optimizer %type <v.i> sourcetrack flush unaryop statelock @@ -478,8 +498,8 @@ int parseport(char *, struct range *r, int); %type <v.icmp> icmp6_list icmp6_item %type <v.number> reticmpspec reticmp6spec %type <v.fromto> fromto -%type <v.peer> ipportspec from to -%type <v.host> ipspec toipspec xhost host dynaddr host_list +%type <v.peer> ipportspec from to toipportspec +%type <v.host> ipspec xhost host dynaddr host_list %type <v.host> redir_host_list redirspec %type <v.host> route_host route_host_list routespec %type <v.os> os xos os_list @@ -488,7 +508,7 @@ int parseport(char *, struct range *r, int); %type <v.gid> gids gid_list gid_item %type <v.route> route %type <v.redirection> redirection redirpool -%type <v.string> label stringall tag anchorname +%type <v.string> label schedule stringall tag anchorname %type <v.string> string varstring numberstring %type <v.keep_state> keep %type <v.state_opt> state_opt_spec state_opt_list state_opt_item @@ -881,6 +901,11 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto YYERROR; } + r.ieee8021q_pcp.pcp[0] = $9.ieee8021q_pcp.pcp[0]; + r.ieee8021q_pcp.pcp[1] = $9.ieee8021q_pcp.pcp[1]; + r.ieee8021q_pcp.op = $9.ieee8021q_pcp.op; + r.ieee8021q_pcp.setpcp = $9.ieee8021q_pcp.setpcp; + if ($9.match_tag) if (strlcpy(r.match_tagname, $9.match_tag, PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { @@ -1221,6 +1246,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; + r.cuid = $5.tracker; j = calloc(1, sizeof(struct node_if)); if (j == NULL) err(1, "antispoof: calloc"); @@ -1270,6 +1296,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { r.logif = $2.logif; r.quick = $2.quick; r.af = $4; + r.cuid = $5.tracker; if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; @@ -1331,6 +1358,9 @@ antispoof_opt : label { } antispoof_opts.label = $1; } + | TRACKER number { + antispoof_opts.tracker = $2; + } | RTABLE NUMBER { if ($2 < 0 || $2 > rt_tableid_max()) { yyerror("invalid rtable id"); @@ -2014,6 +2044,11 @@ pfrule : action dir logquick interface route af proto fromto r.prob = $9.prob; r.rtableid = $9.rtableid; + r.ieee8021q_pcp.pcp[0] = $9.ieee8021q_pcp.pcp[0]; + r.ieee8021q_pcp.pcp[1] = $9.ieee8021q_pcp.pcp[1]; + r.ieee8021q_pcp.op = $9.ieee8021q_pcp.op; + r.ieee8021q_pcp.setpcp = $9.ieee8021q_pcp.setpcp; + r.af = $6; if ($9.tag) if (strlcpy(r.tagname, $9.tag, @@ -2033,6 +2068,11 @@ pfrule : action dir logquick interface route af proto fromto if (rule_label(&r, $9.label)) YYERROR; free($9.label); + if (rule_schedule(&r, $9.schedule)) + YYERROR; + free($9.schedule); + if ($9.tracker) + r.cuid = $9.tracker; r.flags = $9.flags.b1; r.flagset = $9.flags.b2; if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { @@ -2064,7 +2104,14 @@ pfrule : action dir logquick interface route af proto fromto #endif } - r.tos = $9.tos; + if ($9.tos) { + r.tos = $9.tos; + r.rule_flag |= PFRULE_TOS; + } + if ($9.dscp) { + r.tos = $9.dscp; + r.rule_flag |= PFRULE_DSCP; + } r.keep_state = $9.keep.action; o = $9.keep.options; @@ -2096,6 +2143,14 @@ pfrule : action dir logquick interface route af proto fromto } r.rule_flag |= PFRULE_NOSYNC; break; + case PF_STATE_OPT_MAX_PACKETS: + if (o->data.max_packets == 0) { + yyerror("max_packets must be" + "greater than 0"); + YYERROR; + } + r.spare2 = o->data.max_packets; + break; case PF_STATE_OPT_SRCTRACK: if (srctrack) { yyerror("state option " @@ -2382,6 +2437,15 @@ pfrule : action dir logquick interface route af proto fromto } #endif + if ($9.dnpipe) { + r.dnpipe = $9.dnpipe; + if ($9.free_flags & PFRULE_DN_IS_PIPE) + r.free_flags |= PFRULE_DN_IS_PIPE; + else + r.free_flags |= PFRULE_DN_IS_QUEUE; + r.pdnpipe = $9.pdnpipe; + } + expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9.uid, $9.gid, $9.icmpspec, ""); @@ -2442,6 +2506,14 @@ filter_opt : USER uids { filter_opts.marker |= FOM_TOS; filter_opts.tos = $2; } + | dscp { + if (filter_opts.marker & FOM_DSCP) { + yyerror("dscp cannot be redefined"); + YYERROR; + } + filter_opts.marker |= FOM_DSCP; + filter_opts.dscp = $1; + } | keep { if (filter_opts.marker & FOM_KEEP) { yyerror("modulate or keep cannot be redefined"); @@ -2451,6 +2523,9 @@ filter_opt : USER uids { filter_opts.keep.action = $1.action; filter_opts.keep.options = $1.options; } + | TRACKER number { + filter_opts.tracker = $2; + } | FRAGMENT { filter_opts.fragment = 1; } @@ -2464,6 +2539,13 @@ filter_opt : USER uids { } filter_opts.label = $1; } + | schedule { + if (filter_opts.schedule) { + yyerror("schedule label cannot be redefined"); + YYERROR; + } + filter_opts.schedule = $1; + } | qname { if (filter_opts.queues.qname) { yyerror("queue cannot be redefined"); @@ -2471,6 +2553,32 @@ filter_opt : USER uids { } filter_opts.queues = $1; } + | DNPIPE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNQUEUE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } | TAG string { filter_opts.tag = $2; } @@ -2490,6 +2598,98 @@ filter_opt : USER uids { if (filter_opts.prob == 0) filter_opts.prob = 1; } + | IEEE8021QPCP STRING { + u_int pcp; + + /* + * XXXRW: More complete set of operations, similar to + * ports. + */ + if (!strcmp($2, "be")) + pcp = IEEE8021Q_PCP_BE; + else if (!strcmp($2, "bk")) + pcp = IEEE8021Q_PCP_BK; + else if (!strcmp($2, "ee")) + pcp = IEEE8021Q_PCP_EE; + else if (!strcmp($2, "ca")) + pcp = IEEE8021Q_PCP_CA; + else if (!strcmp($2, "vi")) + pcp = IEEE8021Q_PCP_VI; + else if (!strcmp($2, "vo")) + pcp = IEEE8021Q_PCP_VO; + else if (!strcmp($2, "ic")) + pcp = IEEE8021Q_PCP_IC; + else if (!strcmp($2, "nc")) + pcp = IEEE8021Q_PCP_NC; + else + pcp = 8; /* flag bad argument */ + if (pcp > 7) { + yyerror("invalid ieee8021q_pcp value %s", $2); + free($2); + YYERROR; + } + free($2); + filter_opts.ieee8021q_pcp.pcp[0] = pcp; + filter_opts.ieee8021q_pcp.pcp[1] = 0; + filter_opts.ieee8021q_pcp.op = PF_OP_EQ; + } + | IEEE8021QPCP number { + u_int pcp; + + pcp = $2; + if (pcp > 7) { + yyerror("invalid ieee8021q_pcp value %u", pcp); + YYERROR; + } + filter_opts.ieee8021q_pcp.pcp[0] = pcp; + filter_opts.ieee8021q_pcp.pcp[1] = 0; + filter_opts.ieee8021q_pcp.op = PF_OP_EQ; + } + | IEEE8021QSETPCP STRING { + u_int pcp; + + /* + * XXXRW: More complete set of operations, similar to + * ports. + */ + if (!strcmp($2, "be")) + pcp = IEEE8021Q_PCP_BE; + else if (!strcmp($2, "bk")) + pcp = IEEE8021Q_PCP_BK; + else if (!strcmp($2, "ee")) + pcp = IEEE8021Q_PCP_EE; + else if (!strcmp($2, "ca")) + pcp = IEEE8021Q_PCP_CA; + else if (!strcmp($2, "vi")) + pcp = IEEE8021Q_PCP_VI; + else if (!strcmp($2, "vo")) + pcp = IEEE8021Q_PCP_VO; + else if (!strcmp($2, "ic")) + pcp = IEEE8021Q_PCP_IC; + else if (!strcmp($2, "nc")) + pcp = IEEE8021Q_PCP_NC; + else + pcp = 8; /* flag bad argument */ + if (pcp > 7) { + yyerror("invalid ieee8021q_setpcp value %s", + $2); + free($2); + YYERROR; + } + free($2); + filter_opts.ieee8021q_pcp.setpcp = pcp | SETPCP_VALID; + } + | IEEE8021QSETPCP number { + u_int pcp; + + pcp = $2; + if (pcp > 7) { + yyerror("invalid ieee8021q_setpcp value %u", + pcp); + YYERROR; + } + filter_opts.ieee8021q_pcp.setpcp = pcp | SETPCP_VALID; + } | RTABLE NUMBER { if ($2 < 0 || $2 > rt_tableid_max()) { yyerror("invalid rtable id"); @@ -2557,6 +2757,7 @@ probability : STRING { action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } + | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } ; @@ -2885,8 +3086,8 @@ ipspec : ANY { $$ = NULL; } | '{' optnl host_list '}' { $$ = $3; } ; -toipspec : TO ipspec { $$ = $2; } - | /* empty */ { $$ = NULL; } +toipportspec : TO ipportspec { $$ = $2; } + | /* empty */ { $$.host = NULL; $$.port = NULL; } ; host_list : ipspec optnl { $$ = $1; } @@ -3534,6 +3735,48 @@ tos : STRING { } ; +dscp : DSCP STRING { + if (!strcmp($2, "EF")) + $$ = DSCP_EF; + else if (!strcmp($2, "VA")) + $$ = DSCP_VA; + else if (!strcmp($2, "af11")) + $$ = DSCP_AF11; + else if (!strcmp($2, "af12")) + $$ = DSCP_AF12; + else if (!strcmp($2, "af13")) + $$ = DSCP_AF13; + else if (!strcmp($2, "af21")) + $$ = DSCP_AF21; + else if (!strcmp($2, "af22")) + $$ = DSCP_AF22; + else if (!strcmp($2, "af23")) + $$ = DSCP_AF23; + else if (!strcmp($2, "af31")) + $$ = DSCP_AF31; + else if (!strcmp($2, "af32")) + $$ = DSCP_AF32; + else if (!strcmp($2, "af33")) + $$ = DSCP_AF33; + else if (!strcmp($2, "af41")) + $$ = DSCP_AF41; + else if (!strcmp($2, "af42")) + $$ = DSCP_AF42; + else if (!strcmp($2, "af43")) + $$ = DSCP_AF43; + else if ($2[0] == '0' && $2[1] == 'x') + $$ = strtoul($2, NULL, 16) * 4; + else + $$ = strtoul($2, NULL, 10) * 4; + if (!$$ || $$ > 255) { + yyerror("illegal dscp value %s", $2); + free($2); + YYERROR; + } + free($2); + } + ; + sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; } | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; } @@ -3618,6 +3861,15 @@ state_opt_item : MAXIMUM NUMBER { $$->next = NULL; $$->tail = $$; } + | MAXPCKT NUMBER { + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + $$->type = PF_STATE_OPT_MAX_PACKETS; + $$->data.max_packets = $2; + $$->next = NULL; + $$->tail = $$; + } | MAXSRCCONN NUMBER { if ($2 < 0 || $2 > UINT_MAX) { yyerror("only positive values permitted"); @@ -3740,6 +3992,11 @@ label : LABEL STRING { } ; +schedule : SCHEDULE STRING { + $$ = $2; + } + ; + qname : QUEUE STRING { $$.qname = $2; $$.pqname = NULL; @@ -4115,7 +4372,7 @@ natrule : nataction interface af proto fromto tag tagged rtable } ; -binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag +binatrule : no BINAT natpasslog interface af proto FROM ipportspec toipportspec tag tagged rtable redirection { struct pf_rule binat; @@ -4123,7 +4380,7 @@ binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag if (check_rulestate(PFCTL_STATE_NAT)) YYERROR; - if (disallow_urpf_failed($9, "\"urpf-failed\" is not " + if (disallow_urpf_failed($9.host, "\"urpf-failed\" is not " "permitted as a binat destination")) YYERROR; @@ -4141,10 +4398,10 @@ binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag binat.log = $3.b2; binat.logif = $3.w2; binat.af = $5; - if (!binat.af && $8 != NULL && $8->af) - binat.af = $8->af; - if (!binat.af && $9 != NULL && $9->af) - binat.af = $9->af; + if (!binat.af && $8.host != NULL && $8.host->af) + binat.af = $8.host->af; + if (!binat.af && $9.host != NULL && $9.host->af) + binat.af = $9.host->af; if (!binat.af && $13 != NULL && $13->host) binat.af = $13->host->af; @@ -4183,10 +4440,10 @@ binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag free($6); } - if ($8 != NULL && disallow_table($8, "invalid use of " + if ($8.host != NULL && disallow_table($8.host, "invalid use of " "table <%s> as the source address of a binat rule")) YYERROR; - if ($8 != NULL && disallow_alias($8, "invalid use of " + if ($8.host != NULL && disallow_alias($8.host, "invalid use of " "interface (%s) as the source address of a binat " "rule")) YYERROR; @@ -4199,38 +4456,46 @@ binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag "redirect address of a binat rule")) YYERROR; - if ($8 != NULL) { - if ($8->next) { + if ($8.host != NULL) { + if ($8.host->next) { yyerror("multiple binat ip addresses"); YYERROR; } - if ($8->addr.type == PF_ADDR_DYNIFTL) - $8->af = binat.af; - if ($8->af != binat.af) { + if ($8.host->addr.type == PF_ADDR_DYNIFTL) + $8.host->af = binat.af; + if ($8.host->af != binat.af) { yyerror("binat ip versions must match"); YYERROR; } - if (check_netmask($8, binat.af)) + if (check_netmask($8.host, binat.af)) YYERROR; - memcpy(&binat.src.addr, &$8->addr, + memcpy(&binat.src.addr, &$8.host->addr, sizeof(binat.src.addr)); - free($8); + binat.src.neg = $8.host->not; + free($8.host); } - if ($9 != NULL) { - if ($9->next) { + if ($9.host != NULL) { + if ($9.host->next) { yyerror("multiple binat ip addresses"); YYERROR; } - if ($9->af != binat.af && $9->af) { + if ($9.host->af != binat.af && $9.host->af) { yyerror("binat ip versions must match"); YYERROR; } - if (check_netmask($9, binat.af)) + if (check_netmask($9.host, binat.af)) YYERROR; - memcpy(&binat.dst.addr, &$9->addr, + memcpy(&binat.dst.addr, &$9.host->addr, sizeof(binat.dst.addr)); - binat.dst.neg = $9->not; - free($9); + binat.dst.neg = $9.host->not; + free($9.host); + } + + if ($9.port != NULL) { + binat.dst.port[0] = $9.port->port[0]; + binat.dst.port[1] = $9.port->port[1]; + binat.dst.port_op = $9.port->op; + free($9.port); } if (binat.action == PF_NOBINAT) { @@ -4586,6 +4851,15 @@ filter_consistent(struct pf_rule *r, int anchor_call) "synproxy state or modulate state"); problems++; } + if ((r->rule_flag & PFRULE_TOS) && (r->rule_flag & PFRULE_DSCP)) { + yyerror("tos and dscp cannot be used together"); + problems++; + } + if (r->dnpipe && r->pdnpipe && !r->direction) { + yyerror("dummynet cannot be specified without direction"); + problems++; + } + return (-problems); } @@ -5131,6 +5405,7 @@ expand_rule(struct pf_rule *r, int added = 0, error = 0; char ifname[IF_NAMESIZE]; char label[PF_RULE_LABEL_SIZE]; + char schedule[PF_RULE_LABEL_SIZE]; char tagname[PF_TAG_NAME_SIZE]; char match_tagname[PF_TAG_NAME_SIZE]; struct pf_pooladdr *pa; @@ -5139,6 +5414,8 @@ expand_rule(struct pf_rule *r, if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) errx(1, "expand_rule: strlcpy"); + if (strlcpy(schedule, r->schedule, sizeof(schedule)) > sizeof(schedule)) + errx(1, "expand_rule: strlcpy"); if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) errx(1, "expand_rule: strlcpy"); if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= @@ -5190,6 +5467,9 @@ expand_rule(struct pf_rule *r, if (strlcpy(r->label, label, sizeof(r->label)) >= sizeof(r->label)) errx(1, "expand_rule: strlcpy"); + if (strlcpy(r->schedule, schedule, sizeof(r->schedule)) >= + sizeof(r->schedule)) + errx(1, "expand_rule: strlcpy"); if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= sizeof(r->tagname)) errx(1, "expand_rule: strlcpy"); @@ -5198,6 +5478,8 @@ expand_rule(struct pf_rule *r, errx(1, "expand_rule: strlcpy"); expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, src_host, src_port, dst_host, dst_port, proto->proto); + expand_label(r->schedule, PF_RULE_LABEL_SIZE, r->ifname, r->af, + src_host, src_port, dst_host, dst_port, proto->proto); expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, src_host, src_port, dst_host, dst_port, proto->proto); expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, @@ -5382,8 +5664,11 @@ lookup(char *s) { "debug", DEBUG}, { "divert-reply", DIVERTREPLY}, { "divert-to", DIVERTTO}, + { "dnpipe", DNPIPE}, + { "dnqueue", DNQUEUE}, { "drop", DROP}, { "drop-ovl", FRAGDROP}, + { "dscp", DSCP}, { "dup-to", DUPTO}, { "fairq", FAIRQ}, { "fastroute", FASTROUTE}, @@ -5402,6 +5687,8 @@ lookup(char *s) { "hostid", HOSTID}, { "icmp-type", ICMPTYPE}, { "icmp6-type", ICMP6TYPE}, + { "ieee8021q-pcp", IEEE8021QPCP}, + { "ieee8021q-setpcp", IEEE8021QSETPCP}, { "if-bound", IFBOUND}, { "in", IN}, { "include", INCLUDE}, @@ -5415,8 +5702,10 @@ lookup(char *s) { "load", LOAD}, { "log", LOG}, { "loginterface", LOGINTERFACE}, + { "match", MATCH}, { "max", MAXIMUM}, { "max-mss", MAXMSS}, + { "max-packets", MAXPCKT}, { "max-src-conn", MAXSRCCONN}, { "max-src-conn-rate", MAXSRCCONNRATE}, { "max-src-nodes", MAXSRCNODES}, @@ -5461,6 +5750,7 @@ lookup(char *s) { "rtable", RTABLE}, { "rule", RULE}, { "ruleset-optimization", RULESET_OPTIMIZATION}, + { "schedule", SCHEDULE}, { "scrub", SCRUB}, { "set", SET}, { "set-tos", SETTOS}, @@ -5482,6 +5772,7 @@ lookup(char *s) { "timeout", TIMEOUT}, { "to", TO}, { "tos", TOS}, + { "tracker", TRACKER}, { "ttl", TTL}, { "upperlimit", UPPERLIMIT}, { "urpf-failed", URPFFAILED}, @@ -6093,6 +6384,20 @@ rule_label(struct pf_rule *r, char *s) return (0); } +int +rule_schedule(struct pf_rule *r, char *s) +{ + if (s) { + if (strlcpy(r->schedule, s, sizeof(r->label)) >= + sizeof(r->label)) { + yyerror("rule schedule label too long (max %d chars)", + sizeof(r->label)-1); + return (-1); + } + } + return (0); +} + u_int16_t parseicmpspec(char *w, sa_family_t af) { diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index ea95320..20669c1 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -78,6 +78,7 @@ void pfctl_addrprefix(char *, struct pf_addr *); int pfctl_kill_src_nodes(int, const char *, int); int pfctl_net_kill_states(int, const char *, int); int pfctl_label_kill_states(int, const char *, int); +int pfctl_kill_schedule(int, const char *, int); int pfctl_id_kill_states(int, const char *, int); void pfctl_init_options(struct pfctl *); int pfctl_load_options(struct pfctl *); @@ -117,6 +118,7 @@ const char *optiopt = NULL; char *pf_device = "/dev/pf"; char *ifaceopt; char *tableopt; +char *schedule = NULL; const char *tblcmdopt; int src_node_killers; char *src_node_kill[2]; @@ -654,6 +656,25 @@ pfctl_net_kill_states(int dev, const char *iface, int opts) } int +pfctl_kill_schedule(int dev, const char *sched, int opts) +{ + struct pfioc_schedule_kill psk; + + memset(&psk, 0, sizeof(psk)); + if (sched != NULL && strlcpy(psk.schedule, sched, + sizeof(psk.schedule)) >= sizeof(psk.schedule)) + errx(1, "invalid schedule label: %s", sched); + + if (ioctl(dev, DIOCKILLSCHEDULE, &psk)) + err(1, "DIOCKILLSCHEDULE"); + + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "killed %d states from %s schedule label\n", + psk.numberkilled, sched); + return (0); +} + +int pfctl_label_kill_states(int dev, const char *iface, int opts) { struct pfioc_state_kill psk; @@ -804,10 +825,17 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts) (unsigned long long)(rule->bytes[0] + rule->bytes[1]), (uintmax_t)rule->u_states_cur); if (!(opts & PF_OPT_DEBUG)) +#ifdef PF_USER_INFO printf(" [ Inserted: uid %u pid %u " "State Creations: %-6ju]\n", (unsigned)rule->cuid, (unsigned)rule->cpid, (uintmax_t)rule->u_states_tot); +#else + printf(" [ Inserted: pid %u " + "State Creations: %-6ju]\n", + (unsigned)rule->cpid, + (uintmax_t)rule->u_states_tot); +#endif } } @@ -2004,7 +2032,7 @@ main(int argc, char *argv[]) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2118,6 +2146,12 @@ main(int argc, char *argv[]) opts |= PF_OPT_VERBOSE2; opts |= PF_OPT_VERBOSE; break; + case 'y': + if (schedule != NULL && strlen(schedule) > 64) + errx(1, "Schedule label cannot be more than 64 characters\n"); + schedule = optarg; + mode = O_RDWR; + break; case 'x': debugopt = pfctl_lookup_option(optarg, debugopt_list); if (debugopt == NULL) { @@ -2326,6 +2360,9 @@ main(int argc, char *argv[]) if (src_node_killers) pfctl_kill_src_nodes(dev, ifaceopt, opts); + if (schedule) + pfctl_kill_schedule(dev, schedule, opts); + if (tblcmdopt != NULL) { error = pfctl_command_tables(argc, argv, tableopt, tblcmdopt, rulesopt, anchorname, opts); diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c index a1abfdb..9a21754 100644 --- a/sbin/pfctl/pfctl_altq.c +++ b/sbin/pfctl/pfctl_altq.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <limits.h> #include <math.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -264,15 +265,11 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, pa->ifbandwidth = bw->bw_absolute; else #ifdef __FreeBSD__ - if ((rate = getifspeed(pf->dev, pa->ifname)) == 0) { -#else - if ((rate = getifspeed(pa->ifname)) == 0) { + rate = getifspeed(pf->dev, pa->ifname); + if (rate == 0) + rate = IF_Mbps(1000); #endif - fprintf(stderr, "interface %s does not know its bandwidth, " - "please specify an absolute bandwidth\n", - pa->ifname); - errors++; - } else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0) + if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0) pa->ifbandwidth = rate; errors += eval_queue_opts(pa, opts, pa->ifbandwidth); @@ -735,13 +732,6 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) return (-1); } - if ((opts->rtsc_m1 < opts->rtsc_m2 && opts->rtsc_m1 != 0) || - (opts->lssc_m1 < opts->lssc_m2 && opts->lssc_m1 != 0) || - (opts->ulsc_m1 < opts->ulsc_m2 && opts->ulsc_m1 != 0)) { - warnx("m1 must be zero for convex curve: %s", pa->qname); - return (-1); - } - /* * admission control: * for the real-time service curve, the sum of the service curves diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 1f4375a..5b03a93 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/proc.h> #include <net/if.h> +#include <net/ethernet.h> +#include <net/if_vlan_var.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> @@ -65,6 +67,8 @@ __FBSDID("$FreeBSD$"); void print_op (u_int8_t, const char *, const char *); void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); +void print_ieee8021q_pcp (u_int8_t, uint8_t, uint8_t); +void print_ieee8021q_setpcp (u_int8_t); void print_flags (u_int8_t); void print_fromto(struct pf_rule_addr *, pf_osfp_t, struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); @@ -353,6 +357,47 @@ print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) print_op(op, a1, a2); } +static const char * +ieee8021q_pcp_name(u_int8_t pcp) +{ + const char *s; + + if (pcp == IEEE8021Q_PCP_BE) + s = "be"; + else if (pcp == IEEE8021Q_PCP_BK) + s = "bk"; + else if (pcp == IEEE8021Q_PCP_EE) + s = "ee"; + else if (pcp == IEEE8021Q_PCP_CA) + s = "ca"; + else if (pcp == IEEE8021Q_PCP_VI) + s = "vi"; + else if (pcp == IEEE8021Q_PCP_VO) + s = "vo"; + else if (pcp == IEEE8021Q_PCP_IC) + s = "ic"; + else if (pcp == IEEE8021Q_PCP_NC) + s = "nc"; + else + s = "??"; + return (s); +} + + void +print_ieee8021q_pcp(u_int8_t op, u_int8_t pcp0, u_int8_t pcp1) +{ + + printf(" ieee8021q-pcp"); + print_op(op, ieee8021q_pcp_name(pcp0), ieee8021q_pcp_name(pcp1)); +} + +void +print_ieee8021q_setpcp(u_int8_t pcp) +{ + + printf(" ieee8021q-setpcp %s", ieee8021q_pcp_name(pcp)); +} + void print_flags(u_int8_t f) { @@ -691,8 +736,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) int i, opts; if (verbose) +#ifdef PF_USER_INFO printf("@%d ", r->nr); - if (r->action > PF_NORDR) +#else + printf("@%d(%u) ", r->nr, r->cuid); +#endif + if (r->action == PF_MATCH) + printf("match"); + else if (r->action > PF_NORDR) printf("action(%d)", r->action); else if (anchor_call[0]) { if (anchor_call[0] == '_') { @@ -847,8 +898,10 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) printf(" code %u", r->code-1); } } - if (r->tos) + if (r->tos && (r->rule_flag & PFRULE_TOS)) printf(" tos 0x%2.2x", r->tos); + if (r->tos && (r->rule_flag & PFRULE_DSCP)) + printf(" dscp 0x%2.2x", r->tos & DSCP_MASK); if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) printf(" no state"); else if (r->keep_state == PF_STATE_NORMAL) @@ -873,7 +926,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) printf(" probability %s%%", buf); } opts = 0; - if (r->max_states || r->max_src_nodes || r->max_src_states) + if (r->max_states || r->max_src_nodes || r->max_src_states || r->spare2) opts = 1; if (r->rule_flag & PFRULE_NOSYNC) opts = 1; @@ -920,6 +973,12 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) printf("max-src-conn %u", r->max_src_conn); opts = 0; } + if (r->spare2) { + if (!opts) + printf(", "); + printf("max-packets %u", r->spare2); + opts = 0; + } if (r->max_src_conn_rate.limit) { if (!opts) printf(", "); @@ -999,6 +1058,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) } if (r->label[0]) printf(" label \"%s\"", r->label); + if (r->dnpipe && r->pdnpipe) + printf(" %s(%d, %d)", + r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe, r->pdnpipe); + else if (r->dnpipe) + printf(" %s %d", + r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe); if (r->qname[0] && r->pqname[0]) printf(" queue(%s, %s)", r->qname, r->pqname); else if (r->qname[0]) @@ -1012,6 +1079,13 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) } if (r->rtableid != -1) printf(" rtable %u", r->rtableid); + if (r->ieee8021q_pcp.op != 0) + print_ieee8021q_pcp(r->ieee8021q_pcp.op, + r->ieee8021q_pcp.pcp[0], r->ieee8021q_pcp.pcp[1]); + if (r->ieee8021q_pcp.setpcp & SETPCP_VALID) + print_ieee8021q_setpcp(r->ieee8021q_pcp.setpcp & + SETPCP_PCP_MASK); + if (r->divert.port) { #ifdef __FreeBSD__ printf(" divert-to %u", ntohs(r->divert.port)); diff --git a/sbin/route/route.c b/sbin/route/route.c index f64f525..6f73ded 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1557,10 +1557,15 @@ rtmsg(int cmd, int flags, int fib) print_rtmsg(&rtm, l); if (debugonly) return (0); +testagain: if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { if (errno == EPERM) err(1, "writing to routing socket"); warn("writing to routing socket"); + if (rtm.rtm_type == RTM_CHANGE) { + rtm.rtm_type = RTM_ADD; + goto testagain; + } return (-1); } if (cmd == RTM_GET) { diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y index c551c35..60e779d 100644 --- a/sbin/setkey/parse.y +++ b/sbin/setkey/parse.y @@ -100,6 +100,7 @@ extern void yyerror(const char *); %token F_EXT EXTENSION NOCYCLICSEQ %token ALG_AUTH ALG_AUTH_NOKEY %token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD +%token ALG_ENC_SALT %token ALG_COMP %token F_LIFETIME_HARD F_LIFETIME_SOFT %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY @@ -111,6 +112,7 @@ extern void yyerror(const char *); %type <num> prefix protocol_spec upper_spec %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY +%type <num> ALG_ENC_SALT %type <num> ALG_AUTH ALG_AUTH_NOKEY %type <num> ALG_COMP %type <num> PR_ESP PR_AH PR_IPCOMP PR_TCP @@ -402,6 +404,27 @@ enc_alg return -1; } } + | ALG_ENC_SALT key_string + { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $1; + + p_key_enc_len = $2.len; + + p_key_enc = $2.buf; + /* + * Salted keys include a 4 byte value that is + * not part of the key. + */ + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len - 4)) < 0) { + yyerror(ipsec_strerror()); + return -1; + } + } ; auth_alg diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 index 4306ec2..b6d4157 100644 --- a/sbin/setkey/setkey.8 +++ b/sbin/setkey/setkey.8 @@ -627,11 +627,12 @@ des-deriv 64 ipsec-ciph-des-derived-01 3des-deriv 192 no document rijndael-cbc 128/192/256 rfc3602 aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03 +aes-gcm-16 160/224/288 rfc4106 camellia-cbc 128/192/256 rfc4312 .Ed .Pp Note that the first 128/192/256 bits of a key for -.Li aes-ctr +.Li aes-ctr or aes-gcm-16 will be used as AES key, and remaining 32 bits will be used as nonce. .Pp The following are the list of compression algorithms that can be used diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l index c89982f..7f30859 100644 --- a/sbin/setkey/token.l +++ b/sbin/setkey/token.l @@ -159,15 +159,16 @@ tcp { yylval.num = 0; return(PR_TCP); } {hyphen}E { BEGIN S_ENCALG; return(F_ENC); } <S_ENCALG>des-cbc { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC); } <S_ENCALG>3des-cbc { yylval.num = SADB_EALG_3DESCBC; BEGIN INITIAL; return(ALG_ENC); } -<S_ENCALG>null { yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_NOKEY); } +<S_ENCALG>null { yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC); } <S_ENCALG>simple { yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_OLD); } <S_ENCALG>blowfish-cbc { yylval.num = SADB_X_EALG_BLOWFISHCBC; BEGIN INITIAL; return(ALG_ENC); } <S_ENCALG>cast128-cbc { yylval.num = SADB_X_EALG_CAST128CBC; BEGIN INITIAL; return(ALG_ENC); } <S_ENCALG>des-deriv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); } <S_ENCALG>des-32iv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); } <S_ENCALG>rijndael-cbc { yylval.num = SADB_X_EALG_RIJNDAELCBC; BEGIN INITIAL; return(ALG_ENC); } -<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC_SALT); } <S_ENCALG>camellia-cbc { yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>aes-gcm-16 { yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC_SALT); } /* compression algorithms */ {hyphen}C { return(F_COMP); } |