Module Name: src Committed By: spz Date: Thu Jul 19 21:52:29 UTC 2012
Modified Files: src/sys/net/npf: npf.h npf_alg_icmp.c npf_impl.h npf_inet.c npf_instr.c npf_ncode.h npf_processor.c npf_session.c src/usr.sbin/npf/npfctl: npf_build.c npf_data.c npf_disassemble.c npf_ncgen.c npf_parse.y npf_scan.l npf_var.h npfctl.h Log Message: teach npf ipv6-icmp reviewed by rmind@ To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/net/npf/npf.h cvs rdiff -u -r1.10 -r1.11 src/sys/net/npf/npf_alg_icmp.c cvs rdiff -u -r1.18 -r1.19 src/sys/net/npf/npf_impl.h cvs rdiff -u -r1.14 -r1.15 src/sys/net/npf/npf_inet.c cvs rdiff -u -r1.13 -r1.14 src/sys/net/npf/npf_instr.c cvs rdiff -u -r1.9 -r1.10 src/sys/net/npf/npf_ncode.h cvs rdiff -u -r1.11 -r1.12 src/sys/net/npf/npf_processor.c cvs rdiff -u -r1.15 -r1.16 src/sys/net/npf/npf_session.c cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/npf/npfctl/npf_build.c cvs rdiff -u -r1.15 -r1.16 src/usr.sbin/npf/npfctl/npf_data.c cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/npf/npfctl/npf_disassemble.c cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/npf/npfctl/npf_ncgen.c cvs rdiff -u -r1.10 -r1.11 src/usr.sbin/npf/npfctl/npf_parse.y cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/npf/npfctl/npf_scan.l cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/npf/npfctl/npf_var.h cvs rdiff -u -r1.17 -r1.18 src/usr.sbin/npf/npfctl/npfctl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/npf/npf.h diff -u src/sys/net/npf/npf.h:1.19 src/sys/net/npf/npf.h:1.20 --- src/sys/net/npf/npf.h:1.19 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf.h Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.19 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.20 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -74,6 +74,7 @@ typedef struct npf_rproc npf_rproc_t; #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> +#include <netinet/icmp6.h> #define NPC_IP4 0x01 /* Indicates fetched IPv4 header. */ #define NPC_IP6 0x02 /* Indicates IPv6 header. */ @@ -104,9 +105,10 @@ typedef struct { } npc_ip; /* TCP, UDP, ICMP. */ union { - struct tcphdr tcp; - struct udphdr udp; - struct icmp icmp; + struct tcphdr tcp; + struct udphdr udp; + struct icmp icmp; + struct icmp6_hdr icmp6; } npc_l4; } npf_cache_t; Index: src/sys/net/npf/npf_alg_icmp.c diff -u src/sys/net/npf/npf_alg_icmp.c:1.10 src/sys/net/npf/npf_alg_icmp.c:1.11 --- src/sys/net/npf/npf_alg_icmp.c:1.10 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf_alg_icmp.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_alg_icmp.c,v 1.10 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf_alg_icmp.c,v 1.11 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.10 2012/07/15 00:23:00 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.11 2012/07/19 21:52:29 spz Exp $"); #include <sys/param.h> #include <sys/module.h> @@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> +#include <netinet/icmp6.h> #include <net/pfil.h> #include "npf_impl.h" @@ -156,54 +157,102 @@ npfa_icmp_match(npf_cache_t *npc, nbuf_t static bool npf_icmp_uniqid(const int type, npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr) { - struct icmp *ic; - u_int offby; - - /* Per RFC 792. */ - switch (type) { - case ICMP_UNREACH: - case ICMP_SOURCEQUENCH: - case ICMP_REDIRECT: - case ICMP_TIMXCEED: - case ICMP_PARAMPROB: - /* Should contain original IP header. */ - offby = offsetof(struct icmp, icmp_ip); - if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) { - return false; - } - /* Fetch into the cache. */ - if (!npf_fetch_ip(npc, nbuf, n_ptr)) { - return false; - } - switch (npf_cache_ipproto(npc)) { - case IPPROTO_TCP: - return npf_fetch_tcp(npc, nbuf, n_ptr); - case IPPROTO_UDP: - return npf_fetch_udp(npc, nbuf, n_ptr); + struct icmp *ic; + struct icmp6_hdr *ic6; + u_int offby; + + if (npf_iscached(npc, NPC_IP4)) { + /* Per RFC 792. */ + switch (type) { + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + /* Should contain original IP header. */ + offby = offsetof(struct icmp, icmp_ip); + if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) { + return false; + } + /* Fetch into the cache. */ + if (!npf_fetch_ip(npc, nbuf, n_ptr)) { + return false; + } + switch (npf_cache_ipproto(npc)) { + case IPPROTO_TCP: + return npf_fetch_tcp(npc, nbuf, n_ptr); + case IPPROTO_UDP: + return npf_fetch_udp(npc, nbuf, n_ptr); + default: + return false; + } + return true; + + case ICMP_ECHOREPLY: + case ICMP_ECHO: + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_IREQ: + case ICMP_IREQREPLY: + /* Should contain ICMP query ID. */ + ic = &npc->npc_l4.icmp; + offby = offsetof(struct icmp, icmp_id); + if (nbuf_advfetch(&nbuf, &n_ptr, offby, + sizeof(uint16_t), &ic->icmp_id)) { + return false; + } + npc->npc_info |= NPC_ICMP_ID; + return true; default: - return false; + break; } - return true; - - case ICMP_ECHOREPLY: - case ICMP_ECHO: - case ICMP_TSTAMP: - case ICMP_TSTAMPREPLY: - case ICMP_IREQ: - case ICMP_IREQREPLY: - /* Should contain ICMP query ID. */ - ic = &npc->npc_l4.icmp; - offby = offsetof(struct icmp, icmp_id); - if (nbuf_advfetch(&nbuf, &n_ptr, offby, - sizeof(uint16_t), &ic->icmp_id)) { - return false; + /* No unique IDs. */ + return false; + } + if (npf_iscached(npc, NPC_IP6)) { + switch (type) { + /* Per RFC 4443. */ + case ICMP6_DST_UNREACH: + case ICMP6_PACKET_TOO_BIG: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PARAM_PROB: + /* Should contain original IP header. */ + offby = sizeof(struct icmp6_hdr); + if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) { + return false; + } + /* Fetch into the cache. */ + if (!npf_fetch_ip(npc, nbuf, n_ptr)) { + return false; + } + switch (npf_cache_ipproto(npc)) { + case IPPROTO_TCP: + return npf_fetch_tcp(npc, nbuf, n_ptr); + case IPPROTO_UDP: + return npf_fetch_udp(npc, nbuf, n_ptr); + default: + return false; + } + return true; + + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: + /* Should contain ICMP query ID. */ + ic6 = &npc->npc_l4.icmp6; + offby = offsetof(struct icmp6_hdr, icmp6_id); + if (nbuf_advfetch(&nbuf, &n_ptr, offby, + sizeof(uint16_t), &ic6->icmp6_id)) { + return false; + } + npc->npc_info |= NPC_ICMP_ID; + return true; + default: + break; } - npc->npc_info |= NPC_ICMP_ID; - return true; - default: - break; + /* No unique IDs. */ + return false; } - /* No unique IDs. */ + /* Whatever protocol that may have been ... */ return false; } Index: src/sys/net/npf/npf_impl.h diff -u src/sys/net/npf/npf_impl.h:1.18 src/sys/net/npf/npf_impl.h:1.19 --- src/sys/net/npf/npf_impl.h:1.18 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf_impl.h Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.18 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf_impl.h,v 1.19 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -208,6 +208,7 @@ int npf_match_tcp_ports(npf_cache_t *, int npf_match_udp_ports(npf_cache_t *, nbuf_t *, void *, const int, const uint32_t); int npf_match_icmp4(npf_cache_t *, nbuf_t *, void *, uint32_t); +int npf_match_icmp6(npf_cache_t *, nbuf_t *, void *, uint32_t); int npf_match_tcpfl(npf_cache_t *, nbuf_t *, void *, uint32_t); /* Tableset interface. */ Index: src/sys/net/npf/npf_inet.c diff -u src/sys/net/npf/npf_inet.c:1.14 src/sys/net/npf/npf_inet.c:1.15 --- src/sys/net/npf/npf_inet.c:1.14 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf_inet.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_inet.c,v 1.14 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf_inet.c,v 1.15 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.14 2012/07/15 00:23:00 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.15 2012/07/19 21:52:29 spz Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -463,14 +463,18 @@ npf_fetch_icmp(npf_cache_t *npc, nbuf_t if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) { return false; } - if (npf_cache_ipproto(npc) != IPPROTO_ICMP) { + if (npf_cache_ipproto(npc) != IPPROTO_ICMP && + npf_cache_ipproto(npc) != IPPROTO_ICMPV6) { return false; } ic = &npc->npc_l4.icmp; hlen = npf_cache_hlen(npc); /* Fetch basic ICMP header, up to the "data" point. */ - iclen = offsetof(struct icmp, icmp_data); + CTASSERT(offsetof(struct icmp, icmp_void) == + offsetof(struct icmp6_hdr, icmp6_data32)); + + iclen = offsetof(struct icmp, icmp_void); if (nbuf_advfetch(&nbuf, &n_ptr, hlen, iclen, ic)) { return false; } @@ -503,6 +507,7 @@ npf_cache_all(npf_cache_t *npc, nbuf_t * (void)npf_fetch_udp(npc, nbuf, n_ptr); break; case IPPROTO_ICMP: + case IPPROTO_ICMPV6: (void)npf_fetch_icmp(npc, nbuf, n_ptr); break; } Index: src/sys/net/npf/npf_instr.c diff -u src/sys/net/npf/npf_instr.c:1.13 src/sys/net/npf/npf_instr.c:1.14 --- src/sys/net/npf/npf_instr.c:1.13 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf_instr.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_instr.c,v 1.13 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf_instr.c,v 1.14 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.13 2012/07/15 00:23:00 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.14 2012/07/19 21:52:29 spz Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -237,6 +237,37 @@ npf_match_icmp4(npf_cache_t *npc, nbuf_t } /* + * npf_match_icmp6: match ICMPv6 packet. + */ +int +npf_match_icmp6(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, uint32_t tc) +{ + struct icmp6_hdr *ic6 = &npc->npc_l4.icmp6; + + if (!npf_iscached(npc, NPC_ICMP)) { + if (!npf_fetch_icmp(npc, nbuf, n_ptr)) { + return -1; + } + KASSERT(npf_iscached(npc, NPC_ICMP)); + } + + /* Match code/type, if required. */ + if ((1 << 31) & tc) { + const uint8_t type = (tc >> 8) & 0xff; + if (type != ic6->icmp6_type) { + return -1; + } + } + if ((1 << 30) & tc) { + const uint8_t code = tc & 0xff; + if (code != ic6->icmp6_code) { + return -1; + } + } + return 0; +} + +/* * npf_match_tcpfl: match TCP flags. */ int Index: src/sys/net/npf/npf_ncode.h diff -u src/sys/net/npf/npf_ncode.h:1.9 src/sys/net/npf/npf_ncode.h:1.10 --- src/sys/net/npf/npf_ncode.h:1.9 Sun Jul 1 23:21:06 2012 +++ src/sys/net/npf/npf_ncode.h Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_ncode.h,v 1.9 2012/07/01 23:21:06 rmind Exp $ */ +/* $NetBSD: npf_ncode.h,v 1.10 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2010 The NetBSD Foundation, Inc. @@ -118,6 +118,7 @@ int npf_ncode_validate(const void *, siz #define NPF_OPCODE_TABLE 0x91 #define NPF_OPCODE_ICMP4 0x92 #define NPF_OPCODE_IP6MASK 0x93 +#define NPF_OPCODE_ICMP6 0x94 #define NPF_OPCODE_TCP_PORTS 0xa0 #define NPF_OPCODE_UDP_PORTS 0xa1 @@ -139,7 +140,7 @@ int npf_ncode_validate(const void *, siz # define NPF_OPERAND_SUBNET 9 # define NPF_OPERAND_LENGTH 10 # define NPF_OPERAND_TABLE_ID 11 -# define NPF_OPERAND_ICMP4_TYPE_CODE 12 +# define NPF_OPERAND_ICMP_TYPE_CODE 12 # define NPF_OPERAND_TCP_FLAGS_MASK 13 # define NPF_OPERAND_PORT_RANGE 14 # define NPF_OPERAND_PROTO 15 @@ -330,7 +331,13 @@ static const struct npf_instruction { [NPF_OPCODE_ICMP4] = { .name = "icmp4", .op = { - [0] = NPF_OPERAND_ICMP4_TYPE_CODE, + [0] = NPF_OPERAND_ICMP_TYPE_CODE, + }, + }, + [NPF_OPCODE_ICMP6] = { + .name = "icmp6", + .op = { + [0] = NPF_OPERAND_ICMP_TYPE_CODE, }, }, [NPF_OPCODE_IP6MASK] = { Index: src/sys/net/npf/npf_processor.c diff -u src/sys/net/npf/npf_processor.c:1.11 src/sys/net/npf/npf_processor.c:1.12 --- src/sys/net/npf/npf_processor.c:1.11 Sun Jul 1 23:21:06 2012 +++ src/sys/net/npf/npf_processor.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_processor.c,v 1.11 2012/07/01 23:21:06 rmind Exp $ */ +/* $NetBSD: npf_processor.c,v 1.12 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2010 The NetBSD Foundation, Inc. @@ -50,7 +50,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.11 2012/07/01 23:21:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.12 2012/07/19 21:52:29 spz Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -316,6 +316,11 @@ cisc_like: i_ptr = nc_fetch_word(i_ptr, &n); cmpval = npf_match_icmp4(npc, nbuf, n_ptr, n); break; + case NPF_OPCODE_ICMP6: + /* ICMP type/code. */ + i_ptr = nc_fetch_word(i_ptr, &n); + cmpval = npf_match_icmp6(npc, nbuf, n_ptr, n); + break; case NPF_OPCODE_PROTO: i_ptr = nc_fetch_word(i_ptr, &n); cmpval = npf_match_proto(npc, nbuf, n_ptr, n); @@ -480,6 +485,7 @@ jmp_check: error = nc_ptr_check(&iptr, nc, sz, 1, NULL, 0); break; case NPF_OPCODE_ICMP4: + case NPF_OPCODE_ICMP6: error = nc_ptr_check(&iptr, nc, sz, 1, NULL, 0); break; case NPF_OPCODE_PROTO: Index: src/sys/net/npf/npf_session.c diff -u src/sys/net/npf/npf_session.c:1.15 src/sys/net/npf/npf_session.c:1.16 --- src/sys/net/npf/npf_session.c:1.15 Sun Jul 15 00:23:00 2012 +++ src/sys/net/npf/npf_session.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_session.c,v 1.15 2012/07/15 00:23:00 rmind Exp $ */ +/* $NetBSD: npf_session.c,v 1.16 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2010-2012 The NetBSD Foundation, Inc. @@ -80,7 +80,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.15 2012/07/15 00:23:00 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.16 2012/07/19 21:52:29 spz Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -495,7 +495,15 @@ npf_session_inspect(npf_cache_t *npc, nb senkey.se_dst_id = ic->icmp_id; break; } - /* FALLTHROUGH */ + return NULL; + case IPPROTO_ICMPV6: + if (npf_iscached(key, NPC_ICMP_ID)) { + const struct icmp6_hdr *ic6 = &key->npc_l4.icmp6; + senkey.se_src_id = ic6->icmp6_id; + senkey.se_dst_id = ic6->icmp6_id; + break; + } + return NULL; default: /* Unsupported protocol. */ return NULL; @@ -636,7 +644,18 @@ npf_session_establish(const npf_cache_t fw->se_dst_id = ic->icmp_id; break; } - /* FALLTHROUGH */ + ok = false; + goto out; + case IPPROTO_ICMPV6: + if (npf_iscached(npc, NPC_ICMP_ID)) { + /* ICMP query ID. */ + const struct icmp6_hdr *ic6 = &npc->npc_l4.icmp6; + fw->se_src_id = ic6->icmp6_id; + fw->se_dst_id = ic6->icmp6_id; + break; + } + ok = false; + goto out; default: /* Unsupported. */ ok = false; Index: src/usr.sbin/npf/npfctl/npf_build.c diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.11 src/usr.sbin/npf/npfctl/npf_build.c:1.12 --- src/usr.sbin/npf/npfctl/npf_build.c:1.11 Sun Jul 15 00:22:58 2012 +++ src/usr.sbin/npf/npfctl/npf_build.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_build.c,v 1.11 2012/07/15 00:22:58 rmind Exp $ */ +/* $NetBSD: npf_build.c,v 1.12 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_build.c,v 1.11 2012/07/15 00:22:58 rmind Exp $"); +__RCSID("$NetBSD: npf_build.c,v 1.12 2012/07/19 21:52:29 spz Exp $"); #include <sys/types.h> #include <sys/ioctl.h> @@ -246,6 +246,21 @@ npfctl_build_proto(nc_ctx_t *nc, sa_fami npfctl_gennc_icmp(nc, *icmp_type, *icmp_code); nop = false; break; + case IPPROTO_ICMPV6: + /* + * Build ICMP block. + */ + if (!nop) { + goto invop; + } + assert(npfvar_get_count(popts) == 2); + + int *icmp6_type, *icmp6_code; + icmp6_type = npfvar_get_data(popts, NPFVAR_ICMP6, 0); + icmp6_code = npfvar_get_data(popts, NPFVAR_ICMP6, 1); + npfctl_gennc_icmp6(nc, *icmp6_type, *icmp6_code); + nop = false; + break; case -1: pflag = NC_MATCH_TCP | NC_MATCH_UDP; nop = false; Index: src/usr.sbin/npf/npfctl/npf_data.c diff -u src/usr.sbin/npf/npfctl/npf_data.c:1.15 src/usr.sbin/npf/npfctl/npf_data.c:1.16 --- src/usr.sbin/npf/npfctl/npf_data.c:1.15 Sun Jul 15 00:22:59 2012 +++ src/usr.sbin/npf/npfctl/npf_data.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_data.c,v 1.15 2012/07/15 00:22:59 rmind Exp $ */ +/* $NetBSD: npf_data.c,v 1.16 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_data.c,v 1.15 2012/07/15 00:22:59 rmind Exp $"); +__RCSID("$NetBSD: npf_data.c,v 1.16 2012/07/19 21:52:29 spz Exp $"); #include <sys/types.h> #include <sys/null.h> @@ -41,6 +41,8 @@ __RCSID("$NetBSD: npf_data.c,v 1.15 2012 #include <netinet/ip.h> #define ICMP_STRINGS #include <netinet/ip_icmp.h> +#define ICMP6_STRINGS +#include <netinet/icmp6.h> #include <netinet/tcp.h> #include <net/if.h> @@ -440,71 +442,142 @@ npfctl_parse_tcpflag(const char *s) } uint8_t -npfctl_icmptype(const char *type) +npfctl_icmptype(int proto, const char *type) { - for (uint8_t ul = 0; icmp_type[ul]; ul++) - if (strcmp(icmp_type[ul], type) == 0) - return ul; + uint8_t ul; + + switch (proto) { + case IPPROTO_ICMP: + for (ul = 0; icmp_type[ul]; ul++) + if (strcmp(icmp_type[ul], type) == 0) + return ul; + break; + case IPPROTO_ICMPV6: + for (ul = 0; icmp6_type_err[ul]; ul++) + if (strcmp(icmp6_type_err[ul], type) == 0) + return ul; + for (ul = 0; icmp6_type_info[ul]; ul++) + if (strcmp(icmp6_type_info[ul], type) == 0) + return (ul+128); + break; + default: + assert(false); + } + + yyerror("unknown icmp-type %s", type); return ~0; } uint8_t -npfctl_icmpcode(uint8_t type, const char *code) +npfctl_icmpcode(int proto, uint8_t type, const char *code) { const char **arr; - switch (type) { - case ICMP_ECHOREPLY: - case ICMP_SOURCEQUENCH: - case ICMP_ALTHOSTADDR: - case ICMP_ECHO: - case ICMP_ROUTERSOLICIT: - case ICMP_TSTAMP: - case ICMP_TSTAMPREPLY: - case ICMP_IREQ: - case ICMP_IREQREPLY: - case ICMP_MASKREQ: - case ICMP_MASKREPLY: - arr = icmp_code_none; - break; - case ICMP_ROUTERADVERT: - arr = icmp_code_routeradvert; - break; - case ICMP_UNREACH: - arr = icmp_code_unreach; - break; - case ICMP_REDIRECT: - arr = icmp_code_redirect; - break; - case ICMP_TIMXCEED: - arr = icmp_code_timxceed; - break; - case ICMP_PARAMPROB: - arr = icmp_code_paramprob; + switch (proto) { + case IPPROTO_ICMP: + switch (type) { + case ICMP_ECHOREPLY: + case ICMP_SOURCEQUENCH: + case ICMP_ALTHOSTADDR: + case ICMP_ECHO: + case ICMP_ROUTERSOLICIT: + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_IREQ: + case ICMP_IREQREPLY: + case ICMP_MASKREQ: + case ICMP_MASKREPLY: + arr = icmp_code_none; + break; + case ICMP_ROUTERADVERT: + arr = icmp_code_routeradvert; + break; + case ICMP_UNREACH: + arr = icmp_code_unreach; + break; + case ICMP_REDIRECT: + arr = icmp_code_redirect; + break; + case ICMP_TIMXCEED: + arr = icmp_code_timxceed; + break; + case ICMP_PARAMPROB: + arr = icmp_code_paramprob; + break; + case ICMP_PHOTURIS: + arr = icmp_code_photuris; + break; + default: + yyerror("unknown icmp-type %d while parsing code %s", + type, code); + return ~0; + } break; - case ICMP_PHOTURIS: - arr = icmp_code_photuris; + case IPPROTO_ICMPV6: + switch (type) { + case ICMP6_DST_UNREACH: + arr = icmp6_code_unreach; + break; + case ICMP6_TIME_EXCEEDED: + arr = icmp6_code_timxceed; + break; + case ICMP6_PARAM_PROB: + arr = icmp6_code_paramprob; + break; + case ICMP6_PACKET_TOO_BIG: + /* code-less info ICMPs */ + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: + case MLD_LISTENER_QUERY: + case MLD_LISTENER_REPORT: + case MLD_LISTENER_DONE: + case ND_ROUTER_SOLICIT: + case ND_ROUTER_ADVERT: + case ND_NEIGHBOR_SOLICIT: + case ND_NEIGHBOR_ADVERT: + case ND_REDIRECT: + arr = icmp6_code_none; + break; + /* XXX TODO: info ICMPs with code values */ + default: + yyerror("unknown icmp-type %d while parsing code %s", + type, code); + return ~0; + } break; default: - return ~0; + assert(false); } for (uint8_t ul = 0; arr[ul]; ul++) { if (strcmp(arr[ul], code) == 0) return ul; } + yyerror("unknown code %s for icmp-type %d", code, type); return ~0; } npfvar_t * -npfctl_parse_icmp(int type, int code) +npfctl_parse_icmp(int proto, int type, int code) { - npfvar_t *vp = npfvar_create(".icmp"); + npfvar_t *vp=npfvar_create(".icmp"); + int varnum; + + switch (proto) { + case IPPROTO_ICMP: + varnum = NPFVAR_ICMP; + break; + case IPPROTO_ICMPV6: + varnum = NPFVAR_ICMP6; + break; + default: + assert(false); + } - if (!npfvar_add_element(vp, NPFVAR_ICMP, &type, sizeof(type))) + if (!npfvar_add_element(vp, varnum, &type, sizeof(type))) goto out; - if (!npfvar_add_element(vp, NPFVAR_ICMP, &code, sizeof(code))) + if (!npfvar_add_element(vp, varnum, &code, sizeof(code))) goto out; return vp; @@ -512,3 +585,4 @@ out: npfvar_destroy(vp); return NULL; } + Index: src/usr.sbin/npf/npfctl/npf_disassemble.c diff -u src/usr.sbin/npf/npfctl/npf_disassemble.c:1.7 src/usr.sbin/npf/npfctl/npf_disassemble.c:1.8 --- src/usr.sbin/npf/npfctl/npf_disassemble.c:1.7 Sun Jul 15 00:22:59 2012 +++ src/usr.sbin/npf/npfctl/npf_disassemble.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_disassemble.c,v 1.7 2012/07/15 00:22:59 rmind Exp $ */ +/* $NetBSD: npf_disassemble.c,v 1.8 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_disassemble.c,v 1.7 2012/07/15 00:22:59 rmind Exp $"); +__RCSID("$NetBSD: npf_disassemble.c,v 1.8 2012/07/19 21:52:29 spz Exp $"); #include <stdio.h> #include <stdlib.h> @@ -232,7 +232,7 @@ npfctl_ncode_operand(nc_inf_t *ni, char snprintf(buf, bufsiz, "id=%d", op); break; - case NPF_OPERAND_ICMP4_TYPE_CODE: { + case NPF_OPERAND_ICMP_TYPE_CODE: { uint8_t type = (op & 31) ? op >> 8 : 0; uint8_t code = (op & 30) ? op & 0xff : 0; Index: src/usr.sbin/npf/npfctl/npf_ncgen.c diff -u src/usr.sbin/npf/npfctl/npf_ncgen.c:1.12 src/usr.sbin/npf/npfctl/npf_ncgen.c:1.13 --- src/usr.sbin/npf/npfctl/npf_ncgen.c:1.12 Sun Jul 15 00:22:59 2012 +++ src/usr.sbin/npf/npfctl/npf_ncgen.c Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_ncgen.c,v 1.12 2012/07/15 00:22:59 rmind Exp $ */ +/* $NetBSD: npf_ncgen.c,v 1.13 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_ncgen.c,v 1.12 2012/07/15 00:22:59 rmind Exp $"); +__RCSID("$NetBSD: npf_ncgen.c,v 1.13 2012/07/19 21:52:29 spz Exp $"); #include <stdlib.h> #include <stddef.h> @@ -343,6 +343,26 @@ npfctl_gennc_icmp(nc_ctx_t *ctx, int typ } /* + * npfctl_gennc_icmp6: fragment to match ICMPV6 type and code. + */ +void +npfctl_gennc_icmp6(nc_ctx_t *ctx, int type, int code) +{ + uint32_t *nc = npfctl_ncgen_getptr(ctx, 4 /* words */); + + /* OP, code, type (2 words) */ + *nc++ = NPF_OPCODE_ICMP6; + *nc++ = (type == -1 ? 0 : (1 << 31) | ((type & 0xff) << 8)) | + (code == -1 ? 0 : (1 << 30) | (code & 0xff)); + + /* Comparison block (2 words). */ + npfctl_ncgen_addjmp(ctx, &nc); + + /* + 4 words. */ + npfctl_ncgen_putptr(ctx, nc); +} + +/* * npfctl_gennc_tbl: fragment to match IPv4 source/destination address of * the packet against table specified by ID. */ Index: src/usr.sbin/npf/npfctl/npf_parse.y diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.10 src/usr.sbin/npf/npfctl/npf_parse.y:1.11 --- src/usr.sbin/npf/npfctl/npf_parse.y:1.10 Sun Jul 15 00:22:59 2012 +++ src/usr.sbin/npf/npfctl/npf_parse.y Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_parse.y,v 1.10 2012/07/15 00:22:59 rmind Exp $ */ +/* $NetBSD: npf_parse.y,v 1.11 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -120,7 +120,8 @@ yyerror(const char *fmt, ...) %token TO %token TREE %token TYPE -%token ICMP +%token <num> ICMP +%token <num> ICMP6 %token <num> HEX %token <str> IDENTIFIER @@ -471,6 +472,11 @@ opt_proto $$.op_proto = IPPROTO_ICMP; $$.op_opts = $3; } + | PROTO ICMP6 icmp_type_and_code + { + $$.op_proto = IPPROTO_ICMPV6; + $$.op_opts = $3; + } | PROTO some_name { $$.op_proto = npfctl_protono($2); @@ -633,24 +639,24 @@ port icmp_type_and_code : ICMPTYPE icmp_type { - $$ = npfctl_parse_icmp($2, -1); + $$ = npfctl_parse_icmp($<num>0, $2, -1); } | ICMPTYPE icmp_type CODE NUM { - $$ = npfctl_parse_icmp($2, $4); + $$ = npfctl_parse_icmp($<num>0, $2, $4); } | ICMPTYPE icmp_type CODE IDENTIFIER { - $$ = npfctl_parse_icmp($2, npfctl_icmpcode($2, $4)); + $$ = npfctl_parse_icmp($<num>0, $2, npfctl_icmpcode($<num>0, $2, $4)); } | ICMPTYPE icmp_type CODE VAR_ID { char *s = npfvar_expand_string(npfvar_lookup($4)); - $$ = npfctl_parse_icmp($2, npfctl_icmpcode($2, s)); + $$ = npfctl_parse_icmp($<num>0, $2, npfctl_icmpcode($<num>0, $2, s)); } | { - $$ = npfctl_parse_icmp(-1, -1); + $$ = npfctl_parse_icmp($<num>0, -1, -1); } ; @@ -675,11 +681,11 @@ tcp_flags icmp_type : NUM { $$ = $1; } - | IDENTIFIER { $$ = npfctl_icmptype($1); } + | IDENTIFIER { $$ = npfctl_icmptype($<num>-1, $1); } | VAR_ID { char *s = npfvar_expand_string(npfvar_lookup($1)); - $$ = npfctl_icmptype(s); + $$ = npfctl_icmptype($<num>-1, s); } ; Index: src/usr.sbin/npf/npfctl/npf_scan.l diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.4 src/usr.sbin/npf/npfctl/npf_scan.l:1.5 --- src/usr.sbin/npf/npfctl/npf_scan.l:1.4 Sun Jul 1 23:21:07 2012 +++ src/usr.sbin/npf/npfctl/npf_scan.l Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_scan.l,v 1.4 2012/07/01 23:21:07 rmind Exp $ */ +/* $NetBSD: npf_scan.l,v 1.5 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -85,7 +85,9 @@ inet return INET; proto return PROTO; family return FAMILY; tcp return TCP; -icmp return ICMP; +icmp { yylval.num = IPPROTO_ICMP; return ICMP; } +ipv6-icmp { yylval.num = IPPROTO_ICMPV6; return ICMP6; } +\"ipv6-icmp\" { yylval.num = IPPROTO_ICMPV6; return ICMP6; } return-rst return RETURNRST; return-icmp return RETURNICMP; return return RETURN; Index: src/usr.sbin/npf/npfctl/npf_var.h diff -u src/usr.sbin/npf/npfctl/npf_var.h:1.2 src/usr.sbin/npf/npfctl/npf_var.h:1.3 --- src/usr.sbin/npf/npfctl/npf_var.h:1.2 Sun Feb 26 21:50:05 2012 +++ src/usr.sbin/npf/npfctl/npf_var.h Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_var.h,v 1.2 2012/02/26 21:50:05 christos Exp $ */ +/* $NetBSD: npf_var.h,v 1.3 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -48,11 +48,12 @@ #define NPFVAR_ICMP 8 #define NPFVAR_PROC_OP 9 #define NPFVAR_MODULE_ARG 10 +#define NPFVAR_ICMP6 11 #ifdef _NPFVAR_PRIVATE static const char *npfvar_types[ ] = { "string", "identifier", "var_id", "num", "table", "fam", "port_range", - "tcpflag", "icmp", "proc_op", "module_arg" + "tcpflag", "icmp", "proc_op", "module_arg", "icmp6" }; #endif Index: src/usr.sbin/npf/npfctl/npfctl.h diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.17 src/usr.sbin/npf/npfctl/npfctl.h:1.18 --- src/usr.sbin/npf/npfctl/npfctl.h:1.17 Sun Jul 15 00:22:59 2012 +++ src/usr.sbin/npf/npfctl/npfctl.h Thu Jul 19 21:52:29 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.h,v 1.17 2012/07/15 00:22:59 rmind Exp $ */ +/* $NetBSD: npfctl.h,v 1.18 2012/07/19 21:52:29 spz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -99,13 +99,12 @@ void npfctl_print_error(const nl_error_ bool npfctl_table_exists_p(const char *); int npfctl_protono(const char *); in_port_t npfctl_portno(const char *); -uint8_t npfctl_icmpcode(uint8_t, const char *); -uint8_t npfctl_icmptype(const char *); +uint8_t npfctl_icmpcode(int, uint8_t, const char *); +uint8_t npfctl_icmptype(int, const char *); unsigned long npfctl_find_ifindex(const char *); npfvar_t * npfctl_parse_tcpflag(const char *); npfvar_t * npfctl_parse_table_id(const char *); -npfvar_t * npfctl_parse_icmpcode(const char *); -npfvar_t * npfctl_parse_icmp(int, int); +npfvar_t * npfctl_parse_icmp(int, int, int); npfvar_t * npfctl_parse_iface(const char *); npfvar_t * npfctl_parse_port_range(in_port_t, in_port_t); npfvar_t * npfctl_parse_port_range_variable(const char *); @@ -125,6 +124,7 @@ typedef struct nc_ctx nc_ctx_t; #define NC_MATCH_TCP 0x04 #define NC_MATCH_UDP 0x08 #define NC_MATCH_ICMP 0x10 +#define NC_MATCH_ICMP6 0x20 nc_ctx_t * npfctl_ncgen_create(void); void * npfctl_ncgen_complete(nc_ctx_t *, size_t *); @@ -139,6 +139,7 @@ void npfctl_gennc_v6cidr(nc_ctx_t *, in const npf_netmask_t); void npfctl_gennc_ports(nc_ctx_t *, int, in_port_t, in_port_t); void npfctl_gennc_icmp(nc_ctx_t *, int, int); +void npfctl_gennc_icmp6(nc_ctx_t *, int, int); void npfctl_gennc_tbl(nc_ctx_t *, int, u_int); void npfctl_gennc_tcpfl(nc_ctx_t *, uint8_t, uint8_t); void npfctl_gennc_proto(nc_ctx_t *ctx, uint8_t, uint8_t);