From owner-freebsd-ipfw@FreeBSD.ORG Mon Apr 19 06:31:15 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1BB6E16A4CE for ; Mon, 19 Apr 2004 06:31:15 -0700 (PDT) Received: from two.zutom.sk (two.zutom.sk [62.176.170.50]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2D14743D2D for ; Mon, 19 Apr 2004 06:31:14 -0700 (PDT) (envelope-from roman@zutom.sk) Received: from zutom.sk (medusa.zutomxx [10.0.0.10]) by two.zutom.sk (8.12.9p2/8.12.9) with ESMTP id i3JDVCrw099953 for ; Mon, 19 Apr 2004 15:31:13 +0200 (CEST) (envelope-from roman@zutom.sk) MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-class: urn:content-classes:message X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 Date: Mon, 19 Apr 2004 15:31:12 +0200 Message-ID: <8346D753500D004191B4F3E45178065B68EF4D@medusa.zutomxx> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: out xmit not match icmp Thread-Index: AcQmEpSyXZqGtGpzSsO8CkiE17LM4g== From: "Roman Mikus" To: Subject: out xmit not match icmp X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Apr 2004 13:31:15 -0000 Hi, I have freebsd 4.9-RELEASE-p3 box with ipfw and 3 interfaces installed. One interface is external with one public ip address, second is internal with private ip addresses and on third is assigned small subnet of public ip addresses. I want to configure firewall which protect internal and freebsd box but will pass traffic for third interface. I have following interfaces: vx0: internal: 10.0.0.8 netmask 255.255.255.0 ed0: external: y.y.y.170 netmask 255.255.255.240 ep0: free zone: x.x.x.162 netmask 255.255.255.240 I'cand send whole firewall config but is derived from simple section in rc.firewall and looks like this: (x.x.x. and y.y.y. and z.z.z. substitutes my real ip addresses) ... 00400 pipe 1 ip from any to any out xmit ed0 00500 pipe 2 ip from any to any in recv ed0 ... 01900 divert 8668 ip from any to any via ed0 02000 divert 8668 ip from any to any via ep0 03000 allow ip from any to x.x.x.161 03100 allow ip from any to x.x.x.163 03200 allow ip from any to x.x.x.164 .. 03400 allow ip from any to x.x.x.166 .. 04200 allow ip from any to x.x.x.174 04300 allow ip from x.x.x.161 to any out recv ep0 xmit ed0 04400 allow ip from x.x.x.163 to any out recv ep0 xmit ed0 04500 allow ip from x.x.x.164 to any out recv ep0 xmit ed0 .. 04700 allow ip from x.x.x.166 to any out recv ep0 xmit ed0 .. 05500 allow ip from x.x.x.174 to any out recv ep0 xmit ed0 ... 65000 deny log ip from any to any Rules between 1900 and 5500 should pass all traffic to and from free zone, but this is true for tcp traffic (telnet) but not for icmp traffic (ping). If I try to ping x.x.x.166 from outside box with ip z.z.z.11 rule 4700 not match, but rule 65000 match and this appears in /var/log/security: Apr 19 15:16:54 ns /kernel: ipfw: 65000 Deny ICMP:0.0 x.x.x.166 z.z.z.11 in via ep0 This is icmp reply from host x.x.x.166 and is blocked, but should't be. Can you tell me why this happens? How else I can pass any traffic for and from my free zone (but still be able to shape traffic on external interface) and to protect everything else? Thanks a lot. Roman From owner-freebsd-ipfw@FreeBSD.ORG Mon Apr 19 11:01:54 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1CD9816A4CE for ; Mon, 19 Apr 2004 11:01:54 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1955143D41 for ; Mon, 19 Apr 2004 11:01:54 -0700 (PDT) (envelope-from owner-bugmaster@freebsd.org) Received: from freefall.freebsd.org (peter@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.10/8.12.10) with ESMTP id i3JI1rbv043193 for ; Mon, 19 Apr 2004 11:01:53 -0700 (PDT) (envelope-from owner-bugmaster@freebsd.org) Received: (from peter@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i3JI1rM5043187 for ipfw@freebsd.org; Mon, 19 Apr 2004 11:01:53 -0700 (PDT) (envelope-from owner-bugmaster@freebsd.org) Date: Mon, 19 Apr 2004 11:01:53 -0700 (PDT) Message-Id: <200404191801.i3JI1rM5043187@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: peter set sender to owner-bugmaster@freebsd.org using -f From: FreeBSD bugmaster To: ipfw@FreeBSD.org Subject: Current problem reports assigned to you X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Apr 2004 18:01:54 -0000 Current FreeBSD problem reports Critical problems Serious problems S Submitted Tracker Resp. Description ------------------------------------------------------------------------------- o [2002/12/27] kern/46557 ipfw ipfw pipe show fails with lots of queues o [2003/04/22] kern/51274 ipfw ipfw2 create dynamic rules with parent nu f [2003/04/24] kern/51341 ipfw ipfw rule 'deny icmp from any to any icmp o [2004/03/03] misc/63724 ipfw IPFW2 Queues dont t work o [2004/03/13] kern/64240 ipfw IPFW tee terminates rule processing 5 problems total. Non-critical problems S Submitted Tracker Resp. Description ------------------------------------------------------------------------------- a [2001/04/13] kern/26534 ipfw Add an option to ipfw to log gid/uid of w o [2002/12/07] kern/46080 ipfw [PATCH] logamount in ipfw2 does not defau o [2002/12/10] kern/46159 ipfw ipfw dynamic rules lifetime feature o [2002/12/27] kern/46564 ipfw IPFilter and IPFW processing order is not o [2003/02/11] kern/48172 ipfw ipfw does not log size and flags o [2003/03/10] kern/49086 ipfw [patch] Make ipfw2 log to different syslo o [2003/03/12] bin/49959 ipfw ipfw tee port rule skips parsing next rul o [2003/04/09] bin/50749 ipfw ipfw2 incorrectly parses ports and port r o [2003/08/25] kern/55984 ipfw [patch] time based firewalling support fo o [2003/12/29] kern/60719 ipfw ipfw: Headerless fragments generate cryp o [2004/01/12] kern/61259 ipfw [patch] make "ipfw tee" work as intended o [2004/02/09] kern/62598 ipfw no logging on ipfw loadable module o [2004/03/08] kern/63961 ipfw ipfw2 uid matching doesn't work correctly 13 problems total. From owner-freebsd-ipfw@FreeBSD.ORG Sat Apr 24 03:13:41 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D0BF516A4CF for ; Sat, 24 Apr 2004 03:13:41 -0700 (PDT) Received: from white.imgsrc.co.jp (ns.imgsrc.co.jp [210.226.20.2]) by mx1.FreeBSD.org (Postfix) with ESMTP id 08F0443D1F for ; Sat, 24 Apr 2004 03:13:41 -0700 (PDT) (envelope-from kuriyama@imgsrc.co.jp) Received: from localhost (localhost [127.0.0.1]) by white.imgsrc.co.jp (Postfix) with ESMTP id B12AB2840AE; Sat, 24 Apr 2004 19:13:39 +0900 (JST) Received: from black.imgsrc.co.jp (black.imgsrc.co.jp [IPv6:2001:218:422:2::130]) by white.imgsrc.co.jp (Postfix) with ESMTP id 3C57328409B; Sat, 24 Apr 2004 19:13:38 +0900 (JST) Received: from black3.imgsrc.co.jp (black3.imgsrc.co.jp [IPv6:2001:218:422:2::9999]) by black.imgsrc.co.jp (Postfix) with ESMTP id 0FD311E4622; Sat, 24 Apr 2004 19:13:38 +0900 (JST) Date: Sat, 24 Apr 2004 19:13:38 +0900 Message-ID: <7mpt9xd6p9.wl@black3.imgsrc.co.jp> From: Jun Kuriyama To: Luigi Rizzo In-Reply-To: <20040114130122.A86000@xorpc.icir.org> References: <20040114130122.A86000@xorpc.icir.org> User-Agent: Wanderlust/2.10.1 (Watching The Wheels) SEMI/1.14.5 (Awara-Onsen) FLIM/1.14.5 (Demachiyanagi) APEL/10.6 Emacs/21.3 (i386--freebsd) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.5 - "Awara-Onsen") Content-Type: text/plain; charset=US-ASCII X-Virus-Scanned: by AMaViS snapshot-20020531 cc: ipfw@freebsd.org Subject: Re: Request for review: ipfw2 for IPV6 X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2004 10:13:41 -0000 At Wed, 14 Jan 2004 21:02:17 +0000 (UTC), Luigi Rizzo wrote: > I am attaching some very experimental (and only partly functional) > code to use ipfw2/dummynet with IPV6. Hi Luigi, I'd like to test this feature. Is there the latest version of your patch? -- Jun Kuriyama // IMG SRC, Inc. // FreeBSD Project From owner-freebsd-ipfw@FreeBSD.ORG Sat Apr 24 03:45:04 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4289916A4CE for ; Sat, 24 Apr 2004 03:45:04 -0700 (PDT) Received: from xorpc.icir.org (xorpc.icir.org [192.150.187.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2050B43D58 for ; Sat, 24 Apr 2004 03:45:04 -0700 (PDT) (envelope-from rizzo@icir.org) Received: from xorpc.icir.org (localhost [127.0.0.1]) by xorpc.icir.org (8.12.9p1/8.12.8) with ESMTP id i3OAj1gd025199; Sat, 24 Apr 2004 03:45:01 -0700 (PDT) (envelope-from rizzo@xorpc.icir.org) Received: (from rizzo@localhost) by xorpc.icir.org (8.12.9p1/8.12.3/Submit) id i3OAj1eq025198; Sat, 24 Apr 2004 03:45:01 -0700 (PDT) (envelope-from rizzo) Date: Sat, 24 Apr 2004 03:45:01 -0700 From: Luigi Rizzo To: Jun Kuriyama Message-ID: <20040424034501.A24992@xorpc.icir.org> References: <20040114130122.A86000@xorpc.icir.org> <7mpt9xd6p9.wl@black3.imgsrc.co.jp> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i In-Reply-To: <7mpt9xd6p9.wl@black3.imgsrc.co.jp>; from kuriyama@imgsrc.co.jp on Sat, Apr 24, 2004 at 07:13:38PM +0900 cc: ipfw@freebsd.org Subject: Re: Request for review: ipfw2 for IPV6 X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2004 10:45:04 -0000 On Sat, Apr 24, 2004 at 07:13:38PM +0900, Jun Kuriyama wrote: > At Wed, 14 Jan 2004 21:02:17 +0000 (UTC), > Luigi Rizzo wrote: > > I am attaching some very experimental (and only partly functional) > > code to use ipfw2/dummynet with IPV6. > > Hi Luigi, > > I'd like to test this feature. Is there the latest version of your > patch? attached -- it was agains a -current of a week ago, so there might be some minor conflicts in the patch due to a recent ipfw change i actually plan to commit this to -current shortly. cheers luigi diff -ubBri /myshare/cvsup/usr/src/sbin/ipfw/ipfw2.c ./sbin/ipfw/ipfw2.c --- /myshare/cvsup/usr/src/sbin/ipfw/ipfw2.c Fri Apr 9 19:26:01 2004 +++ ./sbin/ipfw/ipfw2.c Wed Apr 21 12:48:06 2004 @@ -45,6 +45,8 @@ #include #include +#include /* def. of struct route */ +#include #include #include #include @@ -245,6 +247,13 @@ TOK_DROPTAIL, TOK_PROTO, TOK_WEIGHT, + + TOK_IPV6, + TOK_FLOWID, + TOK_ICMP6TYPES, + TOK_EXT6HDR, + TOK_DSTIP6, + TOK_SRCIP6, }; struct _s_x dummynet_params[] = { @@ -267,6 +276,13 @@ { "delay", TOK_DELAY }, { "pipe", TOK_PIPE }, { "queue", TOK_QUEUE }, + + { "flow-id", TOK_FLOWID}, + { "dst-ipv6", TOK_DSTIP6}, + { "dst-ip6", TOK_DSTIP6}, + { "src-ipv6", TOK_SRCIP6}, + { "src-ip6", TOK_SRCIP6}, + { "dummynet-params", TOK_NULL }, { NULL, 0 } /* terminator */ }; @@ -341,6 +357,16 @@ { "ipsec", TOK_IPSEC }, { "//", TOK_COMMENT }, + { "icmp6type", TOK_ICMP6TYPES }, + { "icmp6types", TOK_ICMP6TYPES }, + { "ext6hdr", TOK_EXT6HDR}, + { "flow-id", TOK_FLOWID}, + { "ipv6", TOK_IPV6}, + { "dst-ipv6", TOK_DSTIP6}, + { "dst-ip6", TOK_DSTIP6}, + { "src-ipv6", TOK_SRCIP6}, + { "src-ip6", TOK_SRCIP6}, + { "not", TOK_NOT }, /* pseudo option */ { "!", /* escape ? */ TOK_NOT }, /* pseudo option */ { "or", TOK_OR }, /* pseudo option */ @@ -828,6 +854,197 @@ } } +/* XXX ipv6 stuff */ +/* + * Print the ip address contained in a command. + */ +static void +print_ip6(ipfw_insn_ip6 *cmd, char const *s) +{ + struct hostent *he = NULL; + int len = F_LEN((ipfw_insn *) cmd) - 1; + struct in6_addr *a = &(cmd->addr6); + char trad[255]; + + printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s); + + if (cmd->o.opcode == O_IP6_SRC_ME || cmd->o.opcode == O_IP6_DST_ME) { + printf("me6"); + return; + } + if (cmd->o.opcode == O_IP6) { + printf(" ipv6"); + return; + } + + /* + * len == 4 indicates a single IP, whereas lists of 1 or more + * addr/mask pairs have len = (2n+1). We convert len to n so we + * use that to count the number of entries. + */ + + for (len = len / 4; len > 0; len -= 2, a += 2) { + int mb = /* mask length */ + (cmd->o.opcode == O_IP6_SRC || cmd->o.opcode == O_IP6_DST) ? + 128 : contigmask((uint8_t *)&(a[1]), 128); + + if (mb == 128 && do_resolv) + he = gethostbyaddr((char *)a, sizeof(*a), AF_INET6); + if (he != NULL) /* resolved to name */ + printf("%s", he->h_name); + else if (mb == 0) /* any */ + printf("any"); + else { /* numeric IP followed by some kind of mask */ + if (inet_ntop(AF_INET6, a, trad, sizeof( trad ) ) == NULL) + printf("Error ntop in print_ip6\n"); + printf("%s", trad ); + if (mb < 0) /* XXX not really legal... */ + printf(":%s", + inet_ntop(AF_INET6, &a[1], trad, sizeof(trad))); + else if (mb < 128) + printf("/%d", mb); + } + if (len > 2) + printf(","); + } +} + +static void +fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av) +{ + uint8_t type; + + cmd->d[0] = 0; + while (*av) { + if (*av == ',') + av++; + type = strtoul(av, &av, 0); + if (*av != ',' && *av != '\0') + errx(EX_DATAERR, "invalid ICMP6 type"); + if (type > ICMP6_MAXTYPE) + errx(EX_DATAERR, "ICMP6 type out of range"); + cmd->d[type / 32] |= ( 1 << (type % 32)); + } + cmd->o.opcode = O_ICMP6TYPE; + cmd->o.len |= F_INSN_SIZE(ipfw_insn_icmp6); +} + + +static void +print_icmp6types(ipfw_insn_u32 *cmd) +{ + int i, j; + char sep= ' '; + + printf(" ipv6 icmp6types"); + for (i = 0; i < 7; i++) + for (j=0; j < 32; ++j) { + if ( (cmd->d[i] & (1 << (j))) == 0) + continue; + printf("%c%d", sep, (i*32 + j)); + sep = ','; + } +} + +static void +print_flow6id( ipfw_insn_u32 *cmd) +{ + uint16_t i, limit = cmd->o.arg1; + char sep = ','; + + printf(" flow-id "); + for( i=0; i < limit; ++i) { + if (i == limit - 1) + sep = ' '; + printf("%d%c", cmd->d[i], sep); + } +} + +/* structure and define for the extension header in ipv6 */ +static struct _s_x ext6hdrcodes[] = { + { "frag", EXT_FRAGMENT }, + { "hopopt", EXT_HOPOPTS }, + { "route", EXT_ROUTING }, + { "ah", EXT_AH }, + { "esp", EXT_ESP }, + { NULL, 0 } +}; + +/* fills command for the extension header filtering */ +int +fill_ext6hdr( ipfw_insn *cmd, char *av) +{ + int tok; + char *s = av; + + cmd->arg1 = 0; + + while(s) { + av = strsep( &s, ",") ; + tok = match_token(ext6hdrcodes, av); + switch (tok) { + case EXT_FRAGMENT: + cmd->arg1 |= EXT_FRAGMENT; + break; + + case EXT_HOPOPTS: + cmd->arg1 |= EXT_HOPOPTS; + break; + + case EXT_ROUTING: + cmd->arg1 |= EXT_ROUTING; + break; + + case EXT_AH: + cmd->arg1 |= EXT_AH; + break; + + case EXT_ESP: + cmd->arg1 |= EXT_ESP; + break; + + default: + errx( EX_DATAERR, "invalid option for ipv6 exten + headear" ); + break; + } + } + if (cmd->arg1 == 0 ) + return 0; + cmd->opcode = O_EXT_HDR; + cmd->len |= F_INSN_SIZE( ipfw_insn ); + return 1; +} + +void +print_ext6hdr( ipfw_insn *cmd ) +{ + char sep = ' '; + + printf(" extension header:"); + if (cmd->arg1 & EXT_FRAGMENT ) { + printf("%cfragmentation", sep); + sep = ','; + } + if (cmd->arg1 & EXT_HOPOPTS ) { + printf("%chop options", sep); + sep = ','; + } + if (cmd->arg1 & EXT_ROUTING ) { + printf("%crouting options", sep); + sep = ','; + } + if (cmd->arg1 & EXT_AH ) { + printf("%cauthentication header", sep); + sep = ','; + } + if (cmd->arg1 & EXT_ESP ) { + printf("%cencapsulated security payload", sep); + } +} + +/* XXX end of ipv6 stuff */ + /* * show_ipfw() prints the body of an ipfw rule. * Because the standard rule has at least proto src_ip dst_ip, we use @@ -846,6 +1063,7 @@ #define HAVE_DSTIP 0x0004 #define HAVE_MAC 0x0008 #define HAVE_MACTYPE 0x0010 +#define HAVE_PROTO6 0x0080 #define HAVE_OPTIONS 0x8000 #define HAVE_IP (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP) @@ -868,6 +1086,8 @@ return; } if ( !(*flags & HAVE_OPTIONS)) { + if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO6)) + printf(" ipv6"); if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO)) printf(" ip"); if ( !(*flags & HAVE_SRCIP) && (want & HAVE_SRCIP)) @@ -1108,6 +1328,37 @@ flags |= HAVE_DSTIP; break; + case O_IP6_SRC: + case O_IP6_SRC_MASK: + case O_IP6_SRC_ME: + show_prerequisites(&flags, HAVE_PROTO6, 0); + if (!(flags & HAVE_SRCIP)) + printf(" from"); + if ((cmd->len & F_OR) && !or_block) + printf(" {"); + print_ip6((ipfw_insn_ip6 *)cmd, + (flags & HAVE_OPTIONS) ? " src-ip6" : ""); + flags |= HAVE_SRCIP | HAVE_PROTO; + break; + + case O_IP6_DST: + case O_IP6_DST_MASK: + case O_IP6_DST_ME: + show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP, 0); + if (!(flags & HAVE_DSTIP)) + printf(" to"); + if ((cmd->len & F_OR) && !or_block) + printf(" {"); + print_ip6((ipfw_insn_ip6 *)cmd, + (flags & HAVE_OPTIONS) ? " dst-ip6" : ""); + flags |= HAVE_DSTIP; + break; + + case O_FLOW6ID: + print_flow6id( (ipfw_insn_u32 *) cmd ); + flags |= HAVE_OPTIONS; + break; + case O_IP_DSTPORT: show_prerequisites(&flags, HAVE_IP, 0); case O_IP_SRCPORT: @@ -1119,13 +1370,14 @@ break; case O_PROTO: { - struct protoent *pe; + struct protoent *pe = NULL; if ((cmd->len & F_OR) && !or_block) printf(" {"); if (cmd->len & F_NOT) printf(" not"); proto = cmd->arg1; + if (proto != 41) /* XXX ipv6 is special */ pe = getprotobynumber(cmd->arg1); if (flags & HAVE_OPTIONS) printf(" proto"); @@ -1298,6 +1550,18 @@ } break; + case O_IP6: + printf(" ipv6"); + break; + + case O_ICMP6TYPE: + print_icmp6types((ipfw_insn_u32 *)cmd); + break; + + case O_EXT_HDR: + print_ext6hdr( (ipfw_insn *) cmd ); + break; + default: printf(" [opcode %d len %d]", cmd->opcode, cmd->len); @@ -1394,30 +1658,41 @@ static void list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q) { - int l; + int l, index_print = 0; + char buff[255]; - printf(" mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", - fs->flow_mask.proto, - fs->flow_mask.src_ip, fs->flow_mask.src_port, - fs->flow_mask.dst_ip, fs->flow_mask.dst_port); if (fs->rq_elements == 0) return; - printf("BKT Prot ___Source IP/port____ " - "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n"); if (do_sort != 0) heapsort(q, fs->rq_elements, sizeof *q, sort_q); - for (l = 0; l < fs->rq_elements; l++) { + + /* + * Do IPv4 stuff + */ + + for (l = 0; l < fs->rq_elements; l++) + if (!IS_IP6_FLOW_ID(&(q[l].id))) { struct in_addr ina; struct protoent *pe; - ina.s_addr = htonl(q[l].id.src_ip); - printf("%3d ", q[l].hash_slot); + if (!index_print) { + index_print = 1; + printf("\n mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", + fs->flow_mask.proto, + fs->flow_mask.src_ip, fs->flow_mask.src_port, + fs->flow_mask.dst_ip, fs->flow_mask.dst_port); + + printf(" BKT Prot ___Source IP/port____ " + "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n"); + } + printf(" %3d ", q[l].hash_slot); pe = getprotobynumber(q[l].id.proto); if (pe) printf("%-4s ", pe->p_name); else printf("%4u ", q[l].id.proto); + ina.s_addr = htonl(q[l].id.src_ip); printf("%15s/%-5d ", inet_ntoa(ina), q[l].id.src_port); ina.s_addr = htonl(q[l].id.dst_ip); @@ -1430,6 +1705,54 @@ printf(" S %20qd F %20qd\n", q[l].S, q[l].F); } + + /* + * Do IPv6 stuff + */ + + index_print = 0; + for (l = 0; l < fs->rq_elements; l++) + if (IS_IP6_FLOW_ID(&(q[l].id))) { + struct protoent *pe; + + if (!index_print) { + index_print = 1; + printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ", + fs->flow_mask.proto, fs->flow_mask.flow_id6 ); + inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6), + buff, sizeof(buff) ); + printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port); + inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6), + buff, sizeof(buff) ); + printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port); + + printf(" BKT ___Prot___ _flow-id_ " + "______________Source IPv6/port_______________ " + "_______________Dest. IPv6/port_______________ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } + printf(" %3d ", q[l].hash_slot); + pe = getprotobynumber(q[l].id.proto); + if (pe) + printf("%9s ", pe->p_name); + else + printf("%9u ", q[l].id.proto); + printf("%7d %39s/%-5d ", q[l].id.flow_id6, + inet_ntop(AF_INET6, &(q[l].id.src_ip6), + buff, sizeof(buff)), + q[l].id.src_port); + printf(" %39s/%-5d ", + inet_ntop(AF_INET6, &(q[l].id.dst_ip6), + buff, sizeof(buff)), + q[l].id.dst_port); + printf(" %4qu %8qu %2u %4u %3u\n", + q[l].tot_pkts, q[l].tot_bytes, + q[l].len, q[l].len_bytes, q[l].drops); + if (verbose) + printf(" S %20qd F %20qd\n", + q[l].S, q[l].F); + } + printf("\n"); } static void @@ -1812,7 +2135,7 @@ if (do_dynamic && ndyn) { printf("## Dynamic rules:\n"); for (lac = ac, lav = av; lac != 0; lac--) { - rnum = strtoul(*lav++, &endptr, 10); + last = rnum = strtoul(*lav++, &endptr, 10); if (*endptr == '-') last = strtoul(endptr+1, &endptr, 10); if (*endptr) @@ -1864,17 +2187,22 @@ "ACTION: check-state | allow | count | deny | reject | skipto N |\n" " {divert|tee} PORT | forward ADDR | pipe N | queue N\n" "ADDR: [ MAC dst src ether_type ] \n" -" [ from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n" +" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n" +" [ ipv6 from IP6ADDR [ PORT ] to IP6ADDR [ PORTLIST ] ]\n" "IPADDR: [not] { any | me | ip/bits{x,y,z} | IPLIST }\n" "IPLIST: { ip | ip/bits | ip:mask }[,IPLIST]\n" +"IP6ADDR: [not] { any | me | me6 | ip6/bits | IP6LIST }\n" +"IP6LIST: { ip6 | ip6/bits }[,IP6LIST]\n" "OPTION_LIST: OPTION [OPTION_LIST]\n" -"OPTION: bridged | {dst-ip|src-ip} ADDR | {dst-port|src-port} LIST |\n" +"OPTION: bridged | {dst-ip|src-ip} IPADDR | {dst-port|src-port} LIST |\n" " estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |\n" " iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |\n" " ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n" " mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n" " setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n" -" verrevpath\n" +" verrevpath | icmp6types LIST | ext6hdr LIST |\n" +" {dst-ip6|src-ip6|dst-ipv6|src-ipv6} IP6ADDR |\n" +" flow-id N[,N]\n" ); exit(0); } @@ -2068,6 +2396,227 @@ cmd->o.len |= len+1; } +/* XXX more ipv6 stuff */ +/* Try to find ipv6 address by hostname */ +static int +lookup_host6 (char *host, struct in6_addr *ip6addr) +{ + struct hostent *he; + + if (!inet_pton(AF_INET6, host, ip6addr)) { + if ((he = gethostbyname2(host, AF_INET6)) == NULL) + return(-1); + memcpy( ip6addr, he->h_addr_list[0], sizeof( struct in6_addr)); + } + return(0); +} + +/* n2mask sets n bits of the mask */ + +static void +n2mask(struct in6_addr *mask, int n) +{ + static int minimask[9] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff + }; + u_char *p; + int i; + + memset(mask, 0, sizeof(struct in6_addr)); + p = (u_char *) mask; + for (i = 0; i < 16; i++, p++, n -= 8) { + if (n >= 8) { + *p = 0xff; + continue; + } + *p = minimask[n]; + break; + } + return; +} + +/* + * fills the addr and mask fields in the instruction as appropriate from av. + * Update length as appropriate. + * The following formats are allowed: + * any matches any IP6. Actually returns an empty instruction. + * me returns O_IP6_*_ME + * + * 03f1::234:123:0342 single IP6 addres + * 03f1::234:123:0342/24 address/mask + * 03f1::234:123:0342/24,03f1::234:123:0343/ List of address + * + * Set of address (as in ipv6) not supported because ipv6 address + * are typically random past the initial prefix. + * Return 1 on success, 0 on failure. + */ + +static int +fill_ip6(ipfw_insn_ip6 *cmd, char *av) +{ + int len = 0; + struct in6_addr *d = &(cmd->addr6); + /* Needed for multiple address. + * Note d[1] points to struct in6_add r mask6 of cmd + */ + + cmd->o.len &= ~F_LEN_MASK; /* zero len */ + + if (!strncmp(av, "any", strlen(av))) + return 1; + + + if (!strncmp(av, "me", strlen(av))) { /* Set the data for "me" opt*/ + cmd->o.len |= F_INSN_SIZE(ipfw_insn); + return 1; + } + if (!strncmp(av, "me6", strlen(av))) { /* Set the data for "me" opt*/ + cmd->o.len |= F_INSN_SIZE(ipfw_insn); + return 1; + } + + av = strdup(av); + while (av) { + /* + * After the address we can have '/' indicating a mask, + * or ',' indicating another address follows. + */ + + char *p; + int masklen; + char md = '\0'; + + if ((p = strpbrk( av, "/,")) ) { + md = *p; /* save the separator */ + *p = '\0'; /* terminate address string */ + p++; /* and skip past it */ + } + /* now p points to NULL, mask or next entry */ + + /* lookup stores address in *d as a side effect */ + if (lookup_host6(av, d) != 0) { + /* failed. Free memory and go */ + errx(EX_DATAERR, "bad address \"%s\"", av); + } + /* next, look at the mask, if any */ + masklen = (md == '/') ? atoi(p) : 128; + if (masklen > 128 || masklen < 0) + errx(EX_DATAERR, "bad width \"%s\''", p); + else + n2mask( &d[1], masklen); + + APPLY_MASK( d, &d[1]) /* mask base address with mask */ + + /* find next separator */ + + if (md == '/') { /* find separator past the mask */ + p = strpbrk(p, ","); + if (p) + p++; + } + av = p; + + /* Check this entry */ + if (masklen == 0) { + /* + * 'any' turns the entire list into a NOP. + * 'not any' never matches, so it is removed from the + * list unless it is the only item, in which case we + * report an error. + */ + if (cmd->o.len & F_NOT) { /* "not any" never matches */ + if (av == NULL && len == 0) /* only this entry */ + errx(EX_DATAERR, "not any never matches"); + } + /* else do nothing and skip this entry */ + continue; + } + + /* + * A single IP can be stored alone + */ + if (masklen == 128 && av == NULL && len == 0) { + len = F_INSN_SIZE(struct in6_addr); + break; + } + + /* Update length and pointer to arguments */ + len += F_INSN_SIZE(struct in6_addr)*2; + d += 2; + } /* end while */ + + /* Total lenght of the command, remember that 1 is the size of the base command */ + cmd->o.len |= len+1; + free(av); + return 1; +} + +/* + * fills command for ipv6 flow-id filtering + * note that the 20 bit flow number is stored in a array of u_int32_t + * it's supported lists of flow-id, so in the o.arg1 we store how many + * additional flow-id we want to filter, the basic is 1 + */ +void +fill_flow6( ipfw_insn_u32 *cmd, char *av ) +{ + u_int32_t type; /* Current flow number */ + u_int16_t nflow = 0; /* Current flow index */ + char *s = av; + cmd->d[0] = 0; /* Initializing the base number*/ + + while (s) { + av = strsep( &s, ",") ; + type = strtoul(av, &av, 0); + if (*av != ',' && *av != '\0') + errx(EX_DATAERR, "invalid ipv6 flow number %s", av); + if (type > 0xfffff) + errx(EX_DATAERR, "flow number out of range %s", av); + cmd->d[nflow] |= type; + nflow++; + } + if( nflow > 0 ) { + cmd->o.opcode = O_FLOW6ID; + cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + nflow; + cmd->o.arg1 = nflow; + } + else { + errx(EX_DATAERR, "invalid ipv6 flow number %s", av); + } +} + +static ipfw_insn * +add_srcip6(ipfw_insn *cmd, char *av) +{ + fill_ip6( (ipfw_insn_ip6 *) cmd, av); + if (F_LEN(cmd) == 0) /* any */ + ; + if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) /* "me" */ + cmd->opcode = O_IP6_SRC_ME; + else if (F_LEN(cmd) == (F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) + /* single IP, no mask*/ + cmd->opcode = O_IP6_SRC; + else /* addr/mask opt */ + cmd->opcode = O_IP6_SRC_MASK; + return cmd; +} + +static ipfw_insn * +add_dstip6(ipfw_insn *cmd, char *av) +{ + fill_ip6((ipfw_insn_ip6 *)cmd, av); + if (F_LEN(cmd) == 0) /* any */ + ; + if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) /* "me" */ + cmd->opcode = O_IP6_DST_ME; + else if (F_LEN(cmd) == (F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) + /* single IP, no mask*/ + cmd->opcode = O_IP6_DST; + else /* addr/mask opt */ + cmd->opcode = O_IP6_DST_MASK; + return cmd; +} +/* end ipv6 stuff */ /* * helper function to process a set of flags and set bits in the @@ -2185,7 +2734,6 @@ struct dn_pipe p; int i; char *end; - uint32_t a; void *par = NULL; memset(&p, 0, sizeof p); @@ -2247,16 +2795,15 @@ */ par = NULL; - p.fs.flow_mask.dst_ip = 0; - p.fs.flow_mask.src_ip = 0; - p.fs.flow_mask.dst_port = 0; - p.fs.flow_mask.src_port = 0; - p.fs.flow_mask.proto = 0; + bzero(&p.fs.flow_mask, sizeof(p.fs.flow_mask)); end = NULL; while (ac >= 1) { uint32_t *p32 = NULL; uint16_t *p16 = NULL; + uint32_t *p20 = NULL; + struct in6_addr *pa6 = NULL; + uint32_t a; /* the mask */ tok = match_token(dummynet_params, *av); ac--; av++; @@ -2270,6 +2817,9 @@ p.fs.flow_mask.dst_port = ~0; p.fs.flow_mask.src_port = ~0; p.fs.flow_mask.proto = ~0; + n2mask( &(p.fs.flow_mask.dst_ip6), 128); + n2mask( &(p.fs.flow_mask.src_ip6), 128); + p.fs.flow_mask.flow_id6 = ~0; p.fs.flags_fs |= DN_HAVE_FLOW_MASK; goto end_mask; @@ -2281,6 +2831,18 @@ p32 = &p.fs.flow_mask.src_ip; break; + case TOK_DSTIP6: + pa6 = &(p.fs.flow_mask.dst_ip6); + break; + + case TOK_SRCIP6: + pa6 = &(p.fs.flow_mask.src_ip6); + break; + + case TOK_FLOWID: + p20 = &p.fs.flow_mask.flow_id6; + break; + case TOK_DSTPORT: p16 = &p.fs.flow_mask.dst_port; break; @@ -2298,22 +2860,35 @@ } if (ac < 1) errx(EX_USAGE, "mask: value missing"); - if (*av[0] == '/') { + if (*av[0] == '/') { /* mask len */ a = strtoul(av[0]+1, &end, 0); + /* convert to a mask for non IPv6 */ + if (pa6 == NULL) a = (a == 32) ? ~0 : (1 << a) - 1; - } else + } else /* explicit mask (non IPv6) */ a = strtoul(av[0], &end, 0); if (p32 != NULL) *p32 = a; else if (p16 != NULL) { - if (a > 65535) + if (a > 0xffff) errx(EX_DATAERR, - "mask: must be 16 bit"); + "port mask must be 16 bit"); *p16 = (uint16_t)a; + } else if (p20 != NULL) { + if (a > 0xfffff) + errx(EX_DATAERR, + "flow_id mask must be 20 bit"); + *p20 = (uint32_t)a; + } else if (pa6 != NULL) { + if (a < 0 || a > 128) + errx(EX_DATAERR, + "in6addr invalid mask len" ); + else + n2mask(pa6, a); } else { - if (a > 255) + if (a > 0xff) errx(EX_DATAERR, - "mask: must be 8 bit"); + "proto mask must be 8 bit"); p.fs.flow_mask.proto = (uint8_t)a; } if (a != 0) @@ -2417,7 +2992,7 @@ break; default: - errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]); + errx(EX_DATAERR, "unrecognised option ``%s''", *av); } } if (do_pipe == 1) { @@ -2633,21 +3208,27 @@ } static ipfw_insn * -add_proto(ipfw_insn *cmd, char *av) +add_proto(ipfw_insn *cmd, char *av, u_char *proto) { struct protoent *pe; - u_char proto = 0; + *proto = IPPROTO_IP; if (!strncmp(av, "all", strlen(av))) ; /* same as "ip" */ - else if ((proto = atoi(av)) > 0) + else if ((*proto = atoi(av)) > 0) ; /* all done! */ else if ((pe = getprotobyname(av)) != NULL) - proto = pe->p_proto; + *proto = pe->p_proto; + else if(!strncmp(av, "ipv6", strlen(av)) || + !strncmp(av, "ip6", strlen(av)) ) + { + *proto = IPPROTO_IPV6; + return cmd; /* special case for ipv6 */ + } else return NULL; - if (proto != IPPROTO_IP) - fill_cmd(cmd, O_PROTO, 0, proto); + if (*proto != IPPROTO_IP && *proto != IPPROTO_IPV6) + fill_cmd(cmd, O_PROTO, 0, *proto); return cmd; } @@ -2694,6 +3275,38 @@ return NULL; } +static ipfw_insn * +add_src(ipfw_insn *cmd, char *av, u_char proto) +{ + struct in6_addr a; + if( proto == IPPROTO_IPV6 || strcmp( av, "me6") == 0 || inet_pton(AF_INET6, av, &a )) + return add_srcip6(cmd, av); + + if (proto == IPPROTO_IP || strcmp( av, "me") == 0 || !inet_pton(AF_INET6, av, &a ) ) + return add_srcip(cmd, av); + + if( !strcmp( av, "any") ) + return cmd; + + return NULL; /* bad address */ +} + +static ipfw_insn * +add_dst(ipfw_insn *cmd, char *av, u_char proto) +{ + struct in6_addr a; + if( proto == IPPROTO_IPV6 || strcmp( av, "me6") == 0 || inet_pton(AF_INET6, av, &a )) + return add_dstip6(cmd, av); + + if (proto == IPPROTO_IP || strcmp( av, "me") == 0 || !inet_pton(AF_INET6, av, &a ) ) + return add_dstip(cmd, av); + + if( !strcmp( av, "any") ) + return cmd; + + return NULL; /* bad address */ +} + /* * Parse arguments and assemble the microinstructions which make up a rule. * Rules are added into the 'rulebuf' and then copied in the correct order @@ -2717,7 +3330,7 @@ */ static uint32_t rulebuf[255], actbuf[255], cmdbuf[255]; - ipfw_insn *src, *dst, *cmd, *action, *prev=NULL; + ipfw_insn *src, *dst, *cmd, *action, *prev=NULL, *retval=NULL; ipfw_insn *first_cmd; /* first match pattern */ struct ip_fw *rule; @@ -2989,11 +3602,9 @@ OR_START(get_proto); NOT_BLOCK; NEED1("missing protocol"); - if (add_proto(cmd, *av)) { + if (add_proto(cmd, *av, &proto)) { av++; ac--; - if (F_LEN(cmd) == 0) /* plain IP */ - proto = 0; - else { + if (F_LEN(cmd) != 0) { /* plain IP */ proto = cmd->arg1; prev = cmd; cmd = next_cmd(cmd); @@ -3017,13 +3629,17 @@ OR_START(source_ip); NOT_BLOCK; /* optional "not" */ NEED1("missing source address"); - if (add_srcip(cmd, *av)) { + retval = add_src( cmd, *av, proto ); + + if( retval ){ ac--; av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; cmd = next_cmd(cmd); } - } + } else + errx(EX_USAGE, "bad source address %s", *av); + OR_BLOCK(source_ip); /* @@ -3052,13 +3668,16 @@ OR_START(dest_ip); NOT_BLOCK; /* optional "not" */ NEED1("missing dst address"); - if (add_dstip(cmd, *av)) { + retval = add_dst(cmd, *av, proto); + + if( retval ){ ac--; av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; cmd = next_cmd(cmd); } - } + } else + errx( EX_USAGE, "bad destination address %s", *av); OR_BLOCK(dest_ip); /* @@ -3164,6 +3784,12 @@ av++; ac--; break; + case TOK_ICMP6TYPES: + NEED1("icmptypes requires list of types"); + fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av); + av++; ac--; + break; + case TOK_IPTTL: NEED1("ipttl requires TTL"); if (strpbrk(*av, "-,")) { @@ -3340,8 +3966,9 @@ case TOK_PROTO: NEED1("missing protocol"); - if (add_proto(cmd, *av)) { - proto = cmd->arg1; + if ( add_proto(cmd, *av, &proto)) { + if ( proto == IPPROTO_IPV6 ) + fill_cmd(cmd, O_IP6, 0, 0); ac--; av++; } else errx(EX_DATAERR, "invalid protocol ``%s''", @@ -3362,6 +3989,20 @@ } break; + case TOK_SRCIP6: + NEED1("missing source IP6"); + if (add_srcip6(cmd, *av)) { + ac--; av++; + } + break; + + case TOK_DSTIP6: + NEED1("missing destination IP6"); + if (add_dstip6(cmd, *av)) { + ac--; av++; + } + break; + case TOK_SRCPORT: NEED1("missing source port"); if (!strncmp(*av, "any", strlen(*av)) || @@ -3408,6 +4049,23 @@ fill_comment(cmd, ac, av); av += ac; ac = 0; + break; + + case TOK_IPV6: + fill_cmd(cmd, O_IP6, 0, 0); + ac--; av++; + break; + + case TOK_EXT6HDR: + fill_ext6hdr( cmd, *av ); + ac--; av++; + break; + + case TOK_FLOWID: + if (proto != IPPROTO_IPV6 ) + errx( EX_USAGE, "flow-id filter is active only for ipv6 protocol\n"); + fill_flow6( (ipfw_insn_u32 *) cmd, *av ); + ac--;av++; break; default: diff -ubBri /myshare/cvsup/usr/src/sys/netinet/ip_dummynet.c ./sys/netinet/ip_dummynet.c --- /myshare/cvsup/usr/src/sys/netinet/ip_dummynet.c Wed Mar 3 02:33:22 2004 +++ ./sys/netinet/ip_dummynet.c Wed Apr 21 13:01:30 2004 @@ -77,6 +77,9 @@ #include /* for struct arpcom */ #include +#include /* for ip6_input, ip6_output prototypes */ +#include + /* * We keep a private variable for the simulation time, but we could * probably use an existing one ("softticks" in sys/kern/kern_timeout.c) @@ -468,6 +471,15 @@ ip_input(m) ; break ; + case DN_TO_IP6_IN: + ip6_input(m) ; + break ; + + case DN_TO_IP6_OUT: + (void)ip6_output(m, NULL, NULL, pkt->flags, + NULL, NULL, NULL); + break ; + case DN_TO_BDG_FWD : /* * The bridge requires/assumes the Ethernet header is @@ -905,36 +917,79 @@ { int i = 0 ; /* we need i and q for new allocations */ struct dn_flow_queue *q, *prev; + int is_v6 = IS_IP6_FLOW_ID(id); if ( !(fs->flags_fs & DN_HAVE_FLOW_MASK) ) q = fs->rq[0] ; else { - /* first, do the masking */ - id->dst_ip &= fs->flow_mask.dst_ip ; - id->src_ip &= fs->flow_mask.src_ip ; + /* first, do the masking, then hash */ id->dst_port &= fs->flow_mask.dst_port ; id->src_port &= fs->flow_mask.src_port ; id->proto &= fs->flow_mask.proto ; id->flags = 0 ; /* we don't care about this one */ - /* then, hash function */ + if (is_v6) { + APPLY_MASK(&id->dst_ip6, &fs->flow_mask.dst_ip6); + APPLY_MASK(&id->src_ip6, &fs->flow_mask.src_ip6); + id->flow_id6 &= fs->flow_mask.flow_id6; + + i = ((id->dst_ip6.__u6_addr.__u6_addr32[0]) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[1]) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[2]) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[3]) & 0xffff)^ + + ((id->dst_ip6.__u6_addr.__u6_addr32[0] >> 15) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[1] >> 15) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[2] >> 15) & 0xffff)^ + ((id->dst_ip6.__u6_addr.__u6_addr32[3] >> 15) & 0xffff)^ + + ((id->src_ip6.__u6_addr.__u6_addr32[0] << 1) & 0xfffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[1] << 1) & 0xfffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[2] << 1) & 0xfffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[3] << 1) & 0xfffff)^ + + ((id->src_ip6.__u6_addr.__u6_addr32[0] << 16) & 0xffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[1] << 16) & 0xffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[2] << 16) & 0xffff)^ + ((id->src_ip6.__u6_addr.__u6_addr32[3] << 16) & 0xffff)^ + + (id->dst_port << 1) ^ (id->src_port) ^ + (id->proto ) ^ + (id->flow_id6); + } else { + id->dst_ip &= fs->flow_mask.dst_ip ; + id->src_ip &= fs->flow_mask.src_ip ; + i = ( (id->dst_ip) & 0xffff ) ^ ( (id->dst_ip >> 15) & 0xffff ) ^ ( (id->src_ip << 1) & 0xffff ) ^ ( (id->src_ip >> 16 ) & 0xffff ) ^ (id->dst_port << 1) ^ (id->src_port) ^ (id->proto ); + } i = i % fs->rq_size ; /* finally, scan the current list for a match */ searches++ ; for (prev=NULL, q = fs->rq[i] ; q ; ) { search_steps++; - if (id->dst_ip == q->id.dst_ip && + if (is_v6 && + IN6_ARE_ADDR_EQUAL(&id->dst_ip6,&q->id.dst_ip6) && + IN6_ARE_ADDR_EQUAL(&id->src_ip6,&q->id.src_ip6) && + id->dst_port == q->id.dst_port && + id->src_port == q->id.src_port && + id->proto == q->id.proto && + id->flags == q->id.flags && + id->flow_id6 == q->id.flow_id6) + break ; /* found */ + + if (!is_v6 && id->dst_ip == q->id.dst_ip && id->src_ip == q->id.src_ip && id->dst_port == q->id.dst_port && id->src_port == q->id.src_port && id->proto == q->id.proto && id->flags == q->id.flags) break ; /* found */ + + /* No match. Check if we can expire the entry */ else if (pipe_expire && q->head == NULL && q->S == q->F+1 ) { /* entry is idle and not in any heap, expire it */ struct dn_flow_queue *old_q = q ; @@ -1072,7 +1127,7 @@ { #if IPFW2 struct dn_flow_set *fs; - ipfw_insn *cmd = rule->cmd + rule->act_ofs; + ipfw_insn *cmd = ACTION_PTR(rule); if (cmd->opcode == O_LOG) cmd += F_LEN(cmd); @@ -1141,7 +1196,7 @@ struct dn_flow_queue *q = NULL ; int is_pipe; #if IPFW2 - ipfw_insn *cmd = fwa->rule->cmd + fwa->rule->act_ofs; + ipfw_insn *cmd = ACTION_PTR(fwa->rule); #endif KASSERT(m->m_nextpkt == NULL, @@ -1227,6 +1282,18 @@ fwa->dst = (struct sockaddr_in *)&(pkt->ro.ro_dst) ; pkt->dn_dst = fwa->dst; pkt->flags = fwa->flags; + } else if (dir == DN_TO_IP6_OUT) { + pkt->ip6opt.ro_or = fwa->dummypar.ro_or; + pkt->ip6opt.flags_or = fwa->dummypar.flags_or; + pkt->ip6opt.origifp_or = fwa->dummypar.origifp_or; + pkt->ip6opt.ifp_or = fwa->dummypar.ifp_or; + pkt->ip6opt.dst_or = fwa->dummypar.dst_or; + if (pkt->ip6opt.ro_or.ro_rt) { /* XXX is it correct? */ + RT_LOCK(pkt->ip6opt.ro_or.ro_rt); + RT_ADDREF(pkt->ip6opt.ro_or.ro_rt); + RT_UNLOCK(pkt->ip6opt.ro_or.ro_rt); + } + pkt->flags = fwa->flags; } if (q->head == NULL) q->head = m; @@ -1325,6 +1392,7 @@ */ #define DN_FREE_PKT(_m) do { \ rt_unref(dn_tag_get(_m)->ro.ro_rt, __func__); \ + rt_unref(dn_tag_get(_m)->ip6opt.ro_or.ro_rt, __func__); \ m_freem(_m); \ } while (0) @@ -2018,7 +2086,7 @@ ip_dn_init(void) { if (bootverbose) - printf("DUMMYNET initialized (011031)\n"); + printf("DUMMYNET with IPv6 initialized (040114)\n"); DUMMYNET_LOCK_INIT(); diff -ubBri /myshare/cvsup/usr/src/sys/netinet/ip_dummynet.h ./sys/netinet/ip_dummynet.h --- /myshare/cvsup/usr/src/sys/netinet/ip_dummynet.h Wed Feb 25 20:55:28 2004 +++ ./sys/netinet/ip_dummynet.h Tue Apr 20 17:13:20 2004 @@ -124,12 +124,15 @@ #define DN_TO_BDG_FWD 3 #define DN_TO_ETH_DEMUX 4 #define DN_TO_ETH_OUT 5 +#define DN_TO_IP6_IN 6 +#define DN_TO_IP6_OUT 7 dn_key output_time; /* when the pkt is due for delivery */ struct ifnet *ifp; /* interface, for ip_output */ struct sockaddr_in *dn_dst ; struct route ro; /* route, for ip_output. MUST COPY */ int flags ; /* flags, for ip_output (IPv6 ?) */ + struct _ip6dn_args ip6opt; /* XXX ipv6 options */ }; #endif /* _KERNEL */ diff -ubBri /myshare/cvsup/usr/src/sys/netinet/ip_fw.h ./sys/netinet/ip_fw.h --- /myshare/cvsup/usr/src/sys/netinet/ip_fw.h Wed Feb 25 20:55:28 2004 +++ ./sys/netinet/ip_fw.h Tue Apr 20 17:12:48 2004 @@ -126,10 +126,32 @@ */ O_IPSEC, /* has ipsec history */ + O_IP6_SRC, /* address without mask */ + O_IP6_SRC_ME, /* my addresses */ + O_IP6_SRC_MASK, /* address with the mask */ + O_IP6_DST, + O_IP6_DST_ME, + O_IP6_DST_MASK, + O_FLOW6ID, /* for flow id tag in the ipv6 pkt */ + O_ICMP6TYPE, /* icmp6 packet type filtering */ + O_EXT_HDR, /* filtering for ipv6 extension header */ + O_IP6, + O_LAST_OPCODE /* not an opcode! */ }; /* + * The extension header are filtered only for presence using a bit vector + * with a flag for each header. + */ + +#define EXT_FRAGMENT 0x1 +#define EXT_HOPOPTS 0x2 +#define EXT_ROUTING 0x4 +#define EXT_AH 0x8 +#define EXT_ESP 0x10 + +/* * Template for instructions. * * ipfw_insn is used for all instructions which require no operands, @@ -265,6 +287,30 @@ u_int32_t log_left; /* how many left to log */ } ipfw_insn_log; +/* Apply ipv6 mask on ipv6 addr */ +#define APPLY_MASK(addr,mask) \ + (addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \ + (addr)->__u6_addr.__u6_addr32[1] &= (mask)->__u6_addr.__u6_addr32[1]; \ + (addr)->__u6_addr.__u6_addr32[2] &= (mask)->__u6_addr.__u6_addr32[2]; \ + (addr)->__u6_addr.__u6_addr32[3] &= (mask)->__u6_addr.__u6_addr32[3]; + +/* Structure for ipv6 */ +typedef struct _ipfw_insn_ip6 { + ipfw_insn o; + struct in6_addr addr6; + struct in6_addr mask6; +} ipfw_insn_ip6; + +/* Used to support icmp6 types */ +typedef struct _ipfw_insn_icmp6 { + ipfw_insn o; + uint32_t d[7]; /* XXX This number si related to the netinet/icmp6.h + * define ICMP6_MAXTYPE + * as follows: n = ICMP6_MAXTYPE/32 + 1 + * Actually is 203 + */ +} ipfw_insn_icmp6; + /* * Here we have the structure representing an ipfw rule. * @@ -327,8 +373,14 @@ u_int16_t src_port; u_int8_t proto; u_int8_t flags; /* protocol-specific flags */ + uint8_t addr_type; /* 4 = ipv4, 6 = ipv6, 1=ether ? */ + struct in6_addr dst_ip6; /* could also store MAC addr! */ + struct in6_addr src_ip6; + u_int32_t flow_id6; }; +#define IS_IP6_FLOW_ID(id) ((id)->addr_type == 6) + /* * Dynamic ipfw rule. */ @@ -384,6 +436,21 @@ #define IP_FW_PORT_DENY_FLAG 0x40000 /* + * Structure for collecting parameters to dummynet for ip6_output forwarding + */ +struct _ip6dn_args { + struct ip6_pktopts *opt_or; + struct route_in6 ro_or; + int flags_or; + struct ip6_moptions *im6o_or; + struct ifnet *origifp_or; + struct ifnet *ifp_or; + struct sockaddr_in6 dst_or; + u_long mtu_or; + struct route_in6 ro_pmtu_or; +}; + +/* * Arguments for calling ipfw_chk() and dummynet_io(). We put them * all into a structure because this way it is easier and more * efficient to pass variables around and extend the interface. @@ -401,6 +468,8 @@ struct ipfw_flow_id f_id; /* grabbed from IP header */ u_int32_t retval; + + struct _ip6dn_args dummypar; /* dummynet->ip6_output */ }; /* diff -ubBri /myshare/cvsup/usr/src/sys/netinet/ip_fw2.c ./sys/netinet/ip_fw2.c --- /myshare/cvsup/usr/src/sys/netinet/ip_fw2.c Wed Feb 25 20:55:28 2004 +++ ./sys/netinet/ip_fw2.c Wed Apr 21 14:16:20 2004 @@ -79,6 +79,9 @@ #include #endif +#include +#include + #include /* XXX for ETHERTYPE_IP */ #include /* XXX for in_cksum */ @@ -261,15 +264,19 @@ ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; /* hook into dummynet */ /* - * This macro maps an ip pointer into a layer3 header pointer of type T + * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T + * Other macros just cast void * into the appropriate type */ #define L3HDR(T, ip) ((T *)((u_int32_t *)(ip) + (ip)->ip_hl)) +#define TCP(p) ((struct tcphdr *)(p)) +#define UDP(p) ((struct udphdr *)(p)) +#define ICMP(p) ((struct icmp *)(p)) +#define ICMP6(p) ((struct icmp6_hdr *)(p)) static __inline int -icmptype_match(struct ip *ip, ipfw_insn_u32 *cmd) +icmptype_match(struct icmp *icmp, ipfw_insn_u32 *cmd) { - int type = L3HDR(struct icmp,ip)->icmp_type; - + int type = icmp->icmp_type; return (type <= ICMP_MAXTYPE && (cmd->d[0] & (1<icmp_type; + int type = icmp->icmp_type; + return (type <= ICMP_MAXTYPE && (TT & (1<th_off << 2) - sizeof(struct tcphdr); @@ -476,6 +483,83 @@ return 1; } +/* + * ipv6 specific rules here... + */ +static __inline int +icmp6type_match (int type, ipfw_insn_u32 *cmd) +{ + return (type <= ICMP6_MAXTYPE && (cmd->d[type/32] & (1<<(type%32)) ) ); +} + +static int +flow6id_match( int curr_flow, ipfw_insn_u32 *cmd ) +{ + int i; + for (i=0; i <= cmd->o.arg1; ++i ) + if (curr_flow == cmd->d[i] ) + return 1; + return 0; +} + +/* support for IP6_*_ME opcodes */ +static int +search_ip6_addr_net (struct in6_addr * ip6_addr) +{ + struct ifnet *mdc; + struct ifaddr *mdc2; + struct in6_ifaddr *fdm; + struct in6_addr copia; + + TAILQ_FOREACH(mdc, &ifnet, if_link) + for (mdc2 = mdc->if_addrlist.tqh_first; mdc2; + mdc2 = mdc2->ifa_list.tqe_next) { + if (!mdc2->ifa_addr) + continue; + if (mdc2->ifa_addr->sa_family == AF_INET6) { + fdm = (struct in6_ifaddr *)mdc2; + copia = fdm->ia_addr.sin6_addr; + /* need for leaving scope_id in the sock_addr */ + in6_clearscope(&copia); + if (IN6_ARE_ADDR_EQUAL(ip6_addr, &copia)) + return 1; + } + } + return 0; +} + +static int +verify_rev_path6(struct in6_addr *src, struct ifnet *ifp) +{ + static struct route_in6 ro; + struct sockaddr_in6 *dst; + + dst = (struct sockaddr_in6 * )&(ro.ro_dst); + + if ( !(IN6_ARE_ADDR_EQUAL (src, &dst->sin6_addr) )) { + bzero(dst, sizeof(*dst)); + dst->sin6_family = AF_INET6; + dst->sin6_len = sizeof(*dst); + dst->sin6_addr = *src; + rtalloc_ign((struct route *)&ro, RTF_CLONING); + } + if ((ro.ro_rt == NULL) || (ifp == NULL) || + (ro.ro_rt->rt_ifp->if_index != ifp->if_index)) + return 0; + return 1; +} +static __inline int +hash_packet6(struct ipfw_flow_id *id) +{ + u_int32_t i; + i= (id->dst_ip6.__u6_addr.__u6_addr32[0]) ^ + (id->dst_ip6.__u6_addr.__u6_addr32[1]) ^ + (id->dst_ip6.__u6_addr.__u6_addr32[2]) ^ + (id->dst_ip6.__u6_addr.__u6_addr32[3]) ^ + (id->dst_port) ^ (id->src_port) ^ (id->flow_id6); + return i; +} +/* end of ipv6 opcodes */ static u_int64_t norule_counter; /* counter for ipfw_log(NULL...) */ @@ -679,7 +763,9 @@ { u_int32_t i; - i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port); + i = IS_IP6_FLOW_ID(id) ? hash_packet6(id): + (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port); + i &= (curr_dyn_buckets - 1); return i; } @@ -818,6 +904,27 @@ } if (pkt->proto == q->id.proto && q->dyn_type != O_LIMIT_PARENT) { + if (IS_IP6_FLOW_ID(pkt)) { + if (IN6_ARE_ADDR_EQUAL(&(pkt->src_ip6), + &(q->id.src_ip6)) && + IN6_ARE_ADDR_EQUAL(&(pkt->dst_ip6), + &(q->id.dst_ip6)) && + pkt->src_port == q->id.src_port && + pkt->dst_port == q->id.dst_port ) { + dir = MATCH_FORWARD; + break; + } + if (IN6_ARE_ADDR_EQUAL(&(pkt->src_ip6), + &(q->id.dst_ip6)) && + IN6_ARE_ADDR_EQUAL(&(pkt->dst_ip6), + &(q->id.src_ip6)) && + pkt->src_port == q->id.dst_port && + pkt->dst_port == q->id.src_port ) { + dir = MATCH_REVERSE; + break; + } + + } else { if (pkt->src_ip == q->id.src_ip && pkt->dst_ip == q->id.dst_ip && pkt->src_port == q->id.src_port && @@ -833,6 +940,7 @@ break; } } + } next: prev = q; q = q->next; @@ -1028,15 +1136,25 @@ IPFW_DYN_LOCK_ASSERT(); if (ipfw_dyn_v) { + int is_v6 = IS_IP6_FLOW_ID(pkt); i = hash_packet( pkt ); for (q = ipfw_dyn_v[i] ; q != NULL ; q=q->next) if (q->dyn_type == O_LIMIT_PARENT && rule== q->rule && pkt->proto == q->id.proto && - pkt->src_ip == q->id.src_ip && - pkt->dst_ip == q->id.dst_ip && pkt->src_port == q->id.src_port && - pkt->dst_port == q->id.dst_port) { + pkt->dst_port == q->id.dst_port && + ( + (is_v6 && + IN6_ARE_ADDR_EQUAL(&(pkt->src_ip6), + &(q->id.src_ip6)) && + IN6_ARE_ADDR_EQUAL(&(pkt->dst_ip6), + &(q->id.dst_ip6))) || + (!is_v6 && + pkt->src_ip == q->id.src_ip && + pkt->dst_ip == q->id.dst_ip) + ) + ) { q->expire = time_second + dyn_short_lifetime; DEB(printf("ipfw: lookup_dyn_parent found 0x%p\n",q);) return q; @@ -1110,10 +1228,17 @@ id.dst_port = id.src_port = 0; id.proto = args->f_id.proto; + if (IS_IP6_FLOW_ID (&(args->f_id))) { + if (limit_mask & DYN_SRC_ADDR) + id.src_ip6 = args->f_id.src_ip6; + if (limit_mask & DYN_DST_ADDR) + id.dst_ip6 = args->f_id.dst_ip6; + } else { if (limit_mask & DYN_SRC_ADDR) id.src_ip = args->f_id.src_ip; if (limit_mask & DYN_DST_ADDR) id.dst_ip = args->f_id.dst_ip; + } if (limit_mask & DYN_SRC_PORT) id.src_port = args->f_id.src_port; if (limit_mask & DYN_DST_PORT) @@ -1455,34 +1580,151 @@ struct in_addr src_ip, dst_ip; /* NOTE: network format */ u_int16_t ip_len=0; int pktlen; + + /* + * dyn_dir = MATCH_UNKNOWN when rules unchecked, + * MATCH_NONE when checked and not matched (q = NULL), + * MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL) + */ int dyn_dir = MATCH_UNKNOWN; ipfw_dyn_rule *q = NULL; struct ip_fw_chain *chain = &layer3_chain; struct m_tag *mtag; + /* + * We store in ulp a pointer to the upper layer protocol header. + * In the ipv4 case this is easy to determine from the header, + * but for ipv6 we might have some additional headers in the middle. + * ulp is NULL if not found. + */ + void *ulp = NULL; /* upper layer protocol pointer. */ + + /* XXX ipv6 variables */ + int is_ipv6 = 0; + u_int16_t ext_hd = 0; /* bits vector for extension header filtering */ + /* end of ipv6 variables */ + if (m->m_flags & M_SKIP_FIREWALL) return 0; /* accept */ - /* - * dyn_dir = MATCH_UNKNOWN when rules unchecked, - * MATCH_NONE when checked and not matched (q = NULL), - * MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL) + pktlen = m->m_pkthdr.len; + proto = args->f_id.proto = 0; /* mark f_id invalid */ + + /* Identify ipv6 packets and fill up variables. */ + if (pktlen >= sizeof(struct ip6_hdr) && + (!args->eh || ntohs(args->eh->ether_type)==ETHERTYPE_IPV6) && + mtod(m, struct ip *)->ip_v == 6) { + + is_ipv6 = 1; + args->f_id.addr_type = 6; + hlen = sizeof(struct ip6_hdr); + proto = mtod(m, struct ip6_hdr *)->ip6_nxt; + + /* + * PULLUP6(len, p, T) makes sure that len + sizeof(T) is + * contiguous, then it sets p to point at the offset "len" in + * the mbuf. WARNING: the pointer might become stale after + * other pullups (but we never use it this way). */ +#define PULLUP6(len, p, T) \ + do { \ + int x = (len) + sizeof(T); \ + if ((m)->m_len < x) { \ + args->m = m = m_pullup(m, x); \ + if (m == 0) \ + goto pullup_failed; \ + } \ + p = (mtod(m, char *) + (len)); \ + } while (0) + + /* Search extension headers to find upper layer protocols */ + while (ulp == NULL) { + switch (proto) { + case IPPROTO_ICMPV6: + PULLUP6(hlen, ulp, struct icmp6_hdr); + args->f_id.flags = ICMP6(ulp)->icmp6_type; + break; + + case IPPROTO_TCP: + PULLUP6(hlen, ulp, struct tcphdr); + dst_port = TCP(ulp)->th_dport; + src_port = TCP(ulp)->th_sport; + args->f_id.flags = TCP(ulp)->th_flags; + break; + + case IPPROTO_UDP: + PULLUP6(hlen, ulp, struct udphdr); + dst_port = UDP(ulp)->uh_dport; + src_port = UDP(ulp)->uh_sport; + break; + + case IPPROTO_HOPOPTS: + PULLUP6(hlen, ulp, struct ip6_hbh); + ext_hd |= EXT_HOPOPTS; + hlen += sizeof(struct ip6_hbh); + proto = ((struct ip6_hbh *)ulp)->ip6h_nxt; + ulp = NULL; + break; + + case IPPROTO_ROUTING: + PULLUP6(hlen, ulp, struct ip6_rthdr); + ext_hd |= EXT_ROUTING; + hlen += sizeof(struct ip6_rthdr); + proto = ((struct ip6_rthdr *)ulp)->ip6r_nxt; + ulp = NULL; + break; + + case IPPROTO_FRAGMENT: + PULLUP6(hlen, ulp, struct ip6_frag); + ext_hd |= EXT_FRAGMENT; + hlen += sizeof (struct ip6_frag); + proto = ((struct ip6_frag *)ulp)->ip6f_nxt; + offset = 1; + ulp = NULL; /* XXX is it correct ? */ + break; + + case IPPROTO_AH: + case IPPROTO_NONE: + case IPPROTO_ESP: + PULLUP6(hlen, ulp, struct ip6_ext); + if (proto == IPPROTO_AH) + ext_hd |= EXT_AH; + else if (proto == IPPROTO_ESP) + ext_hd |= EXT_ESP; + hlen += ((struct ip6_ext *)ulp)->ip6e_len + + sizeof (struct ip6_ext); + proto = ((struct ip6_ext *)ulp)->ip6e_nxt; + ulp = NULL; + break; + + default: + printf("IPFW2: IPV6 - Unknown Extension Header (%d)\n", + proto); + return 0; /* deny */ + break; + } /*switch */ + } + args->f_id.src_ip6 = mtod(m,struct ip6_hdr *)->ip6_src; + args->f_id.dst_ip6 = mtod(m,struct ip6_hdr *)->ip6_dst; + args->f_id.src_ip = 0; + args->f_id.dst_ip = 0; + args->f_id.flow_id6 = ntohs(mtod(m, struct ip6_hdr *)->ip6_flow); + + /* hlen != 0 is used to detect ipv4 packets, so clear it now */ + hlen = 0; + + } else if (pktlen >= sizeof(struct ip) && + (!args->eh || ntohs(args->eh->ether_type) == ETHERTYPE_IP) && + mtod(m, struct ip *)->ip_v == 4) { + ip = mtod(m, struct ip *); - pktlen = m->m_pkthdr.len; - if (args->eh == NULL || /* layer 3 packet */ - ( m->m_pkthdr.len >= sizeof(struct ip) && - ntohs(args->eh->ether_type) == ETHERTYPE_IP)) hlen = ip->ip_hl << 2; + args->f_id.addr_type = 4; /* * Collect parameters into local variables for faster matching. */ - if (hlen == 0) { /* do not grab addresses for non-ip pkts */ - proto = args->f_id.proto = 0; /* mark f_id invalid */ - goto after_ip_checks; - } - proto = args->f_id.proto = ip->ip_p; + proto = ip->ip_p; src_ip = ip->ip_src; dst_ip = ip->ip_dst; if (args->eh != NULL) { /* layer 2 packets are as on the wire */ @@ -1494,60 +1736,42 @@ } pktlen = ip_len < pktlen ? ip_len : pktlen; -#define PULLUP_TO(len) \ - do { \ - if ((m)->m_len < (len)) { \ - args->m = m = m_pullup(m, (len)); \ - if (m == 0) \ - goto pullup_failed; \ - ip = mtod(m, struct ip *); \ - } \ - } while (0) - if (offset == 0) { switch (proto) { case IPPROTO_TCP: - { - struct tcphdr *tcp; - - PULLUP_TO(hlen + sizeof(struct tcphdr)); - tcp = L3HDR(struct tcphdr, ip); - dst_port = tcp->th_dport; - src_port = tcp->th_sport; - args->f_id.flags = tcp->th_flags; - } + PULLUP6(hlen, ulp, struct tcphdr); + dst_port = TCP(ulp)->th_dport; + src_port = TCP(ulp)->th_sport; + args->f_id.flags = TCP(ulp)->th_flags; break; case IPPROTO_UDP: - { - struct udphdr *udp; - - PULLUP_TO(hlen + sizeof(struct udphdr)); - udp = L3HDR(struct udphdr, ip); - dst_port = udp->uh_dport; - src_port = udp->uh_sport; - } + PULLUP6(hlen, ulp, struct udphdr); + dst_port = UDP(ulp)->uh_dport; + src_port = UDP(ulp)->uh_sport; break; case IPPROTO_ICMP: - PULLUP_TO(hlen + 4); /* type, code and checksum. */ - args->f_id.flags = L3HDR(struct icmp, ip)->icmp_type; + /* we only care for 4 bytes: type, code, checksum */ + PULLUP6(hlen, ulp, struct icmp); + args->f_id.flags = ICMP(ulp)->icmp_type; break; default: break; } -#undef PULLUP_TO } args->f_id.src_ip = ntohl(src_ip.s_addr); args->f_id.dst_ip = ntohl(dst_ip.s_addr); + } + if (proto) { /* we may have port numbers, store them */ + args->f_id.proto = proto; args->f_id.src_port = src_port = ntohs(src_port); args->f_id.dst_port = dst_port = ntohs(dst_port); - -after_ip_checks: + } IPFW_LOCK(chain); /* XXX expensive? can we run lock free? */ mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); if (args->rule) { /* * Packet has already been tagged. Look for the next rule @@ -1650,11 +1875,13 @@ case O_UID: /* * We only check offset == 0 && proto != 0, - * as this ensures that we have an IPv4 + * as this ensures that we have a * packet with the ports info. */ if (offset!=0) break; + if (is_ipv6) /* XXX to be fixed later */ + break; if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) match = check_uidgid( @@ -1708,7 +1935,7 @@ break; case O_FRAG: - match = (hlen > 0 && offset != 0); + match = (offset != 0); break; case O_IN: /* "out" is "not in" */ @@ -1793,7 +2020,7 @@ case O_IP_DSTPORT: /* * offset == 0 && proto != 0 is enough - * to guarantee that we have an IPv4 + * to guarantee that we have a * packet with port info. */ if ((proto==IPPROTO_UDP || proto==IPPROTO_TCP) @@ -1813,15 +2040,25 @@ case O_ICMPTYPE: match = (offset == 0 && proto==IPPROTO_ICMP && - icmptype_match(ip, (ipfw_insn_u32 *)cmd) ); + icmptype_match(ICMP(ulp), (ipfw_insn_u32 *)cmd) ); + break; + + case O_ICMP6TYPE: + match = is_ipv6 && offset == 0 && + proto==IPPROTO_ICMPV6 && + icmp6type_match( + ICMP6(ulp)->icmp6_type, + (ipfw_insn_u32 *)cmd); break; case O_IPOPT: - match = (hlen > 0 && ipopts_match(ip, cmd) ); + match = (hlen > 0 && + ipopts_match(mtod(m, struct ip *), cmd) ); break; case O_IPVER: - match = (hlen > 0 && cmd->arg1 == ip->ip_v); + match = (hlen > 0 && + cmd->arg1 == mtod(m, struct ip *)->ip_v); break; case O_IPID: @@ -1835,9 +2072,9 @@ if (cmd->opcode == O_IPLEN) x = ip_len; else if (cmd->opcode == O_IPTTL) - x = ip->ip_ttl; + x = mtod(m, struct ip *)->ip_ttl; else /* must be IPID */ - x = ntohs(ip->ip_id); + x = ntohs(mtod(m, struct ip *)->ip_id); if (cmdlen == 1) { match = (cmd->arg1 == x); break; @@ -1852,48 +2089,46 @@ case O_IPPRECEDENCE: match = (hlen > 0 && - (cmd->arg1 == (ip->ip_tos & 0xe0)) ); + (cmd->arg1 == (mtod(m, struct ip *)->ip_tos & 0xe0)) ); break; case O_IPTOS: match = (hlen > 0 && - flags_match(cmd, ip->ip_tos)); + flags_match(cmd, mtod(m, struct ip *)->ip_tos)); break; case O_TCPFLAGS: match = (proto == IPPROTO_TCP && offset == 0 && - flags_match(cmd, - L3HDR(struct tcphdr,ip)->th_flags)); + flags_match(cmd, TCP(ulp)->th_flags)); break; case O_TCPOPTS: match = (proto == IPPROTO_TCP && offset == 0 && - tcpopts_match(ip, cmd)); + tcpopts_match(TCP(ulp), cmd)); break; case O_TCPSEQ: match = (proto == IPPROTO_TCP && offset == 0 && ((ipfw_insn_u32 *)cmd)->d[0] == - L3HDR(struct tcphdr,ip)->th_seq); + TCP(ulp)->th_seq); break; case O_TCPACK: match = (proto == IPPROTO_TCP && offset == 0 && ((ipfw_insn_u32 *)cmd)->d[0] == - L3HDR(struct tcphdr,ip)->th_ack); + TCP(ulp)->th_ack); break; case O_TCPWIN: match = (proto == IPPROTO_TCP && offset == 0 && - cmd->arg1 == - L3HDR(struct tcphdr,ip)->th_win); + cmd->arg1 == TCP(ulp)->th_win); break; case O_ESTAB: /* reject packets which have SYN only */ /* XXX should i also check for TH_ACK ? */ match = (proto == IPPROTO_TCP && offset == 0 && - (L3HDR(struct tcphdr,ip)->th_flags & + ( TCP(ulp)->th_flags & (TH_RST | TH_ACK | TH_SYN)) != TH_SYN); break; @@ -1909,8 +2144,11 @@ case O_VERREVPATH: /* Outgoing packets automatically pass/match */ - match = ((oif != NULL) || + match = (oif != NULL) || (m->m_pkthdr.rcvif == NULL) || + (is_ipv6 ? + verify_rev_path6(&(args->f_id.src_ip6), + m->m_pkthdr.rcvif) : verify_rev_path(src_ip, m->m_pkthdr.rcvif)); break; @@ -1925,6 +2163,60 @@ /* otherwise no match */ break; + case O_IP6_SRC: + match = is_ipv6 && + IN6_ARE_ADDR_EQUAL(&args->f_id.src_ip6, + &((ipfw_insn_ip6 *)cmd)->addr6); + break; + + case O_IP6_DST: + match = is_ipv6 && + IN6_ARE_ADDR_EQUAL(&args->f_id.dst_ip6, + &((ipfw_insn_ip6 *)cmd)->addr6); + break; + case O_IP6_SRC_MASK: + if (is_ipv6) { + ipfw_insn_ip6 *te = (ipfw_insn_ip6 *)cmd; + struct in6_addr p = args->f_id.src_ip6; + + APPLY_MASK(&p, &te->mask6); + match = IN6_ARE_ADDR_EQUAL(&te->addr6, &p); + } + break; + + case O_IP6_DST_MASK: + if (is_ipv6) { + ipfw_insn_ip6 *te = (ipfw_insn_ip6 *)cmd; + struct in6_addr p = args->f_id.dst_ip6; + + APPLY_MASK(&p, &te->mask6); + match = IN6_ARE_ADDR_EQUAL(&te->addr6, &p); + } + break; + + case O_IP6_SRC_ME: + match= is_ipv6 && search_ip6_addr_net(&args->f_id.src_ip6); + break; + + case O_IP6_DST_ME: + match= is_ipv6 && search_ip6_addr_net(&args->f_id.dst_ip6); + break; + + case O_FLOW6ID: + match = is_ipv6 && + flow6id_match(args->f_id.flow_id6, + (ipfw_insn_u32 *) cmd); + break; + + case O_EXT_HDR: + match = is_ipv6 && + (ext_hd & ((ipfw_insn *) cmd)->arg1); + break; + + case O_IP6: + match = is_ipv6; + break; + /* * The second set of opcodes represents 'actions', * i.e. the terminal part of a rule once the packet @@ -1987,7 +2279,7 @@ if (dyn_dir == MATCH_UNKNOWN && (q = lookup_dyn_rule(&args->f_id, &dyn_dir, proto == IPPROTO_TCP ? - L3HDR(struct tcphdr, ip) : NULL)) + TCP(ulp) : NULL)) != NULL) { /* * Found dynamic entry, update stats @@ -2068,7 +2360,7 @@ */ if (hlen > 0 && (proto != IPPROTO_ICMP || - is_icmp_query(ip)) && + is_icmp_query(ICMP(ulp))) && !(m->m_flags & (M_BCAST|M_MCAST)) && !IN_MULTICAST(ntohl(dst_ip.s_addr))) { send_reject(args, cmd->arg1, @@ -2547,6 +2839,10 @@ case O_ESTAB: case O_VERREVPATH: case O_IPSEC: + case O_IP6_SRC_ME: + case O_IP6_DST_ME: + case O_EXT_HDR: + case O_IP6: if (cmdlen != F_INSN_SIZE(ipfw_insn)) goto bad_size; break; @@ -2660,6 +2956,29 @@ return EINVAL; } break; + + case O_IP6_SRC: + case O_IP6_DST: + if (cmdlen != F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn)) + goto bad_size; + break; + + case O_FLOW6ID: + if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + + ((ipfw_insn_u32 *)cmd)->o.arg1) + goto bad_size; + break; + + case O_IP6_SRC_MASK: + case O_IP6_DST_MASK: + if ( !(cmdlen & 1) || cmdlen > 127) + goto bad_size; + break; + case O_ICMP6TYPE: + if( cmdlen != F_INSN_SIZE( ipfw_insn_icmp6 ) ) + goto bad_size; + break; + default: printf("ipfw: opcode %d, unknown opcode\n", cmd->opcode); @@ -2969,7 +3288,7 @@ } ip_fw_default_rule = layer3_chain.rules; - printf("ipfw2 initialized, divert %s, " + printf("ipfw2 (+ipv6) initialized, divert %s, " "rule-based forwarding enabled, default to %s, logging ", #ifdef IPDIVERT "enabled", diff -ubBri /myshare/cvsup/usr/src/sys/netinet6/ip6_input.c ./sys/netinet6/ip6_input.c --- /myshare/cvsup/usr/src/sys/netinet6/ip6_input.c Wed Apr 7 22:46:15 2004 +++ ./sys/netinet6/ip6_input.c Tue Apr 20 17:16:03 2004 @@ -61,7 +61,7 @@ * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */ -#include "opt_ip6fw.h" +#include "opt_ipfw.h" #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" @@ -126,6 +126,14 @@ #include +#include +#ifdef IPFW2 +#include +#include +#endif + +extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); + extern struct domain inet6domain; u_char ip6_protox[IPPROTO_MAX]; @@ -248,6 +257,25 @@ int srcrt = 0; GIANT_REQUIRED; /* XXX for now */ + +#ifdef IPFW2 + int i, hlen; + struct ip_fw_args args; + args.eh = NULL; + args.oif = NULL; + + M_ASSERTPKTHDR(m); + + args.next_hop = ip_claim_next_hop(m); + args.rule = ip_dn_claim_rule(m); + + if (args.rule) { /* dummynet already filtered us */ + ip6 = mtod(m, struct ip6_hdr *); + hlen = sizeof (struct ip6_hdr); + goto iphack6 ; + } +#endif /* IPFW2 */ + #ifdef IPSEC /* * should the inner packet be considered authentic? @@ -365,7 +393,9 @@ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); goto bad; } - +#ifdef IPFW2 +iphack6: +#endif /* * The following check is not documented in specs. A malicious * party may be able to use IPv4 mapped addr to confuse tcp/udp stack @@ -451,6 +481,52 @@ if (!m) return; } +#ifdef IPFW2 + /* now check with the firewall ipfw2 */ + + if (fw_enable && IPFW_LOADED) { + /* + * If we've been forwarded from the output side, then + * skip the firewall a second time + */ + + if (args.next_hop) + ours=1; /* Non sappiamo che vuol dire qui */ + + args.m = m; + i = ip_fw_chk_ptr(&args); + m = args.m; + + if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */ + if (m) + m_freem(m); + return; + } + ip6 = mtod(m, struct ip6_hdr *); /* just in case m changed */ + if (i == 0 && args.next_hop == NULL) /* common case */ + goto pass6; + if (DUMMYNET_LOADED && (i & IP_FW_PORT_DYNT_FLAG) != 0) { + /* Send packet to the appropriate pipe */ + ip_dn_io_ptr(m, i & 0xffff, DN_TO_IP6_IN, &args); + return; + } +#ifdef IPDIVERT + if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) { + /* Divert or tee packet */ + divert_info = i; + ours=1; + } +#endif + if (i == 0 && args.next_hop != NULL) + goto pass6; + /* + * if we get here, the packet must be dropped + */ + m_freem(m); + return; + } +pass6: +#endif /* IPFW2 */ /* * construct source and destination address structures with diff -ubBri /myshare/cvsup/usr/src/sys/netinet6/ip6_output.c ./sys/netinet6/ip6_output.c --- /myshare/cvsup/usr/src/sys/netinet6/ip6_output.c Wed Apr 7 22:46:15 2004 +++ ./sys/netinet6/ip6_output.c Tue Apr 20 17:16:14 2004 @@ -61,7 +61,7 @@ * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 */ -#include "opt_ip6fw.h" +#include "opt_ipfw.h" #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" @@ -109,8 +109,13 @@ #include #endif /* FAST_IPSEC */ -#include +#include +#ifdef IPFW2 +#include +#include +#endif +#include #include #include @@ -166,11 +171,11 @@ struct inpcb *inp; { struct ip6_hdr *ip6, *mhip6; - struct ifnet *ifp, *origifp; + struct ifnet *ifp = NULL, *origifp; struct mbuf *m = m0; int hlen, tlen, len, off; struct route_in6 ip6route; - struct sockaddr_in6 *dst; + struct sockaddr_in6 *dst = NULL; int error = 0; struct in6_ifaddr *ia = NULL; u_long mtu; @@ -181,6 +186,11 @@ struct route_in6 *ro_pmtu = NULL; int hdrsplit = 0; int needipsec = 0; +#ifdef IPFW2 + struct ip_fw_args args; + struct m_tag *dummytag; +#endif + #if defined(IPSEC) || defined(FAST_IPSEC) int needipsectun = 0; struct secpolicy *sp = NULL; @@ -188,6 +198,46 @@ ip6 = mtod(m, struct ip6_hdr *); finaldst = ip6->ip6_dst; +#ifdef IPFW2 + args.eh = NULL; + args.rule = NULL; /* divert cookie */ + + M_ASSERTPKTHDR(m); + + args.rule = ip_dn_claim_rule(m); + + dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); + if (dummytag != NULL) { + struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1); + /* + * Prevent lower layers from finding the tag + * Cleanup and free is done below + */ + m_tag_unlink(m, dummytag); + /* + * the packet was already tagged, so part of the + * processing was already done, and we need to go down. + * Get parameters from the header. + */ + args.rule = dt->rule; + opt = NULL; + ro = &dt->ip6opt.ro_or; + flags = dt->ip6opt.flags_or; + im6o = NULL; + origifp = dt->ip6opt.origifp_or; + ifp = dt->ip6opt.ifp_or; + dst = &dt->ip6opt.dst_or; + } + if (args.rule ) { /* dummynet already saw us */ + ip6 = mtod(m, struct ip6_hdr *); + hlen = sizeof (struct ip6_hdr) ; + if (ro->ro_rt) + ia = ifatoia6(ro->ro_rt->rt_ifa); + bzero(&exthdrs, sizeof(exthdrs)); + ro_pmtu = ro; + goto send_after_dummynet; + } +#endif /* IPFW2 */ #define MAKE_EXTHDR(hp, mp) \ do { \ @@ -812,7 +862,9 @@ */ if (ifpp) *ifpp = ifp; - +#ifdef IPFW2 +send_after_dummynet: +#endif /* Determine path MTU. */ if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu, &alwaysfrag)) != 0) @@ -890,6 +942,70 @@ /* * Check with the firewall... */ +#ifdef IPFW2 + if (fw_enable && IPFW_LOADED && !args.next_hop) { + /* + * Check with the firewall IPFW2... + * but not if we are already being fwd'd from a firewall. + */ + + struct sockaddr_in6 *old = dst; + args.m = m; + args.next_hop = (struct sockaddr_in *) dst; + args.oif = ifp; + off = ip_fw_chk_ptr(&args); + m = args.m; + dst = (struct sockaddr_in6 *) args.next_hop; + + /* + * On return we must do the following: + * m == NULL -> drop the pkt (old interface, deprecated) + * (off & IP_FW_PORT_DENY_FLAG) -> drop the pkt (new interface) + * 1<=off<= 0xffff -> DIVERT + * (off & IP_FW_PORT_DYNT_FLAG) -> send to a DUMMYNET pipe + * (off & IP_FW_PORT_TEE_FLAG) -> TEE the packet + * dst != old -> IPFIREWALL_FORWARD + * off==0, dst==old -> accept + * If some of the above modules are not compiled in, then + * we should't have to check the corresponding condition + * (because the ipfw control socket should not accept + * unsupported rules), but better play safe and drop + * packets in case of doubt. + */ + if ( (off & IP_FW_PORT_DENY_FLAG) || m == NULL) { + if (m) + m_freem(m); + error = EACCES; + goto done; + } + ip6 = mtod(m, struct ip6_hdr *); /* XXX check if necessary */ + if (off == 0 && dst == old) /* common case */ + goto pass6; + if (DUMMYNET_LOADED && (off & IP_FW_PORT_DYNT_FLAG) != 0) { + /* + * pass the pkt to dummynet. Need to include + * pipe number, m, ifp, ro, dst because these are + * not recomputed in the next pass. + * All other parameters have been already used and + * so they are not needed anymore. + * XXX note: if the ifp or ro entry are deleted + * while a pkt is in dummynet, we are in trouble! + */ + args.dummypar.ro_or = *ro; + args.dummypar.flags_or = flags; + args.dummypar.ifp_or = ifp; + args.dummypar.origifp_or = origifp; + args.dummypar.dst_or = *dst; + args.flags = flags; +if (args.rule != NULL) + error = ip_dn_io_ptr(m, off & 0xffff, DN_TO_IP6_OUT, + &args); + goto done; + } + } +pass6: +#endif /*IPFW2 */ + if (ip6_fw_enable && ip6_fw_chk_ptr) { u_short port = 0; m->m_pkthdr.rcvif = NULL; /* XXX */ From owner-freebsd-ipfw@FreeBSD.ORG Sat Apr 24 07:00:11 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4BA4416A4CE for ; Sat, 24 Apr 2004 07:00:11 -0700 (PDT) Received: from transport.cksoft.de (transport.cksoft.de [62.111.66.27]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7FF9143D5A for ; Sat, 24 Apr 2004 07:00:10 -0700 (PDT) (envelope-from bzeeb-lists@lists.zabbadoz.net) Received: from transport.cksoft.de (localhost [127.0.0.1]) by transport.cksoft.de (Postfix) with ESMTP id 783421FF931; Sat, 24 Apr 2004 16:00:08 +0200 (CEST) Received: by transport.cksoft.de (Postfix, from userid 66) id 6CFB91FF91D; Sat, 24 Apr 2004 16:00:06 +0200 (CEST) Received: by mail.int.zabbadoz.net (Postfix, from userid 1060) id 4A41E153AA; Sat, 24 Apr 2004 13:56:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mail.int.zabbadoz.net (Postfix) with ESMTP id 3FBE015329; Sat, 24 Apr 2004 13:56:59 +0000 (UTC) Date: Sat, 24 Apr 2004 13:56:59 +0000 (UTC) From: "Bjoern A. Zeeb" X-X-Sender: bz@e0-0.zab2.int.zabbadoz.net To: Luigi Rizzo In-Reply-To: <20040424034501.A24992@xorpc.icir.org> Message-ID: References: <20040114130122.A86000@xorpc.icir.org> <7mpt9xd6p9.wl@black3.imgsrc.co.jp> <20040424034501.A24992@xorpc.icir.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Virus-Scanned: by AMaViS cksoft-s20020300-20031204bz on transport.cksoft.de cc: Jun Kuriyama cc: ipfw@freebsd.org Subject: Re: Request for review: ipfw2 for IPV6 X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2004 14:00:11 -0000 On Sat, 24 Apr 2004, Luigi Rizzo wrote: Hi, > i actually plan to commit this to -current shortly. thanks. I still cannot see any #ifdef INET6 in the patch; won't it break kernels w/o INET6 support ? -- Bjoern A. Zeeb bzeeb at Zabbadoz dot NeT 56 69 73 69 74 http://www.zabbadoz.net/ From owner-freebsd-ipfw@FreeBSD.ORG Sat Apr 24 09:12:48 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AB37516A4CE for ; Sat, 24 Apr 2004 09:12:48 -0700 (PDT) Received: from xorpc.icir.org (xorpc.icir.org [192.150.187.68]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9630443D45 for ; Sat, 24 Apr 2004 09:12:48 -0700 (PDT) (envelope-from rizzo@icir.org) Received: from xorpc.icir.org (localhost [127.0.0.1]) by xorpc.icir.org (8.12.9p1/8.12.8) with ESMTP id i3OGCmgd055713; Sat, 24 Apr 2004 09:12:48 -0700 (PDT) (envelope-from rizzo@xorpc.icir.org) Received: (from rizzo@localhost) by xorpc.icir.org (8.12.9p1/8.12.3/Submit) id i3OGClcd055712; Sat, 24 Apr 2004 09:12:47 -0700 (PDT) (envelope-from rizzo) Date: Sat, 24 Apr 2004 09:12:47 -0700 From: Luigi Rizzo To: "Bjoern A. Zeeb" Message-ID: <20040424091247.A55419@xorpc.icir.org> References: <20040114130122.A86000@xorpc.icir.org> <7mpt9xd6p9.wl@black3.imgsrc.co.jp> <20040424034501.A24992@xorpc.icir.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i In-Reply-To: ; from bzeeb-lists@lists.zabbadoz.net on Sat, Apr 24, 2004 at 01:56:59PM +0000 cc: Jun Kuriyama cc: ipfw@freebsd.org Subject: Re: Request for review: ipfw2 for IPV6 X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2004 16:12:48 -0000 On Sat, Apr 24, 2004 at 01:56:59PM +0000, Bjoern A. Zeeb wrote: > On Sat, 24 Apr 2004, Luigi Rizzo wrote: > > Hi, > > > i actually plan to commit this to -current shortly. > > thanks. I still cannot see any #ifdef INET6 in the patch; won't it > break kernels w/o INET6 support ? iwill check, but why should it break things ? this patch does two things: 1) teaches ipfw2 how to parse ipv6 packets 2) puts ipfw2 hooks in the ipv6 code the former does not depend on having INET6 configured in your kernel, the latter is already in the INET6 code. luigi > -- > Bjoern A. Zeeb bzeeb at Zabbadoz dot NeT > 56 69 73 69 74 http://www.zabbadoz.net/ > _______________________________________________ > freebsd-ipfw@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw > To unsubscribe, send any mail to "freebsd-ipfw-unsubscribe@freebsd.org" From owner-freebsd-ipfw@FreeBSD.ORG Sat Apr 24 23:14:56 2004 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B775D16A4CE for ; Sat, 24 Apr 2004 23:14:56 -0700 (PDT) Received: from black3.imgsrc.co.jp (black3.imgsrc.co.jp [210.226.20.147]) by mx1.FreeBSD.org (Postfix) with ESMTP id 08F3143D46 for ; Sat, 24 Apr 2004 23:14:56 -0700 (PDT) (envelope-from kuriyama@imgsrc.co.jp) Received: from localhost (localhost [127.0.0.1]) by black3.imgsrc.co.jp (Postfix) with ESMTP id 9928250B21; Sun, 25 Apr 2004 15:14:54 +0900 (JST) Received: from black3.imgsrc.co.jp (black3.imgsrc.co.jp [IPv6:2001:218:422:2::9999]) by black3.imgsrc.co.jp (Postfix) with ESMTP id 5AF6B5085B; Sun, 25 Apr 2004 15:14:53 +0900 (JST) Date: Sun, 25 Apr 2004 15:14:53 +0900 Message-ID: <7md65wd1nm.wl@black3.imgsrc.co.jp> From: Jun Kuriyama To: Luigi Rizzo In-Reply-To: <20040424034501.A24992@xorpc.icir.org> References: <20040114130122.A86000@xorpc.icir.org> <7mpt9xd6p9.wl@black3.imgsrc.co.jp> User-Agent: Wanderlust/2.10.1 (Watching The Wheels) SEMI/1.14.5 (Awara-Onsen) FLIM/1.14.5 (Demachiyanagi) APEL/10.6 Emacs/21.3 (i386--freebsd) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.5 - "Awara-Onsen") Content-Type: text/plain; charset=US-ASCII X-Virus-Scanned: by amavisd 0.1 cc: ipfw@freebsd.org Subject: Re: Request for review: ipfw2 for IPV6 X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Apr 2004 06:14:56 -0000 At Sat, 24 Apr 2004 03:45:01 -0700, Luigi Rizzo wrote: > attached -- it was agains a -current of a week ago, so there might > be some minor conflicts in the patch due to a recent ipfw change I fixed simple confilcts, but I couldn't finish buildworld. The diff against today's -current is here: http://www.imgsrc.co.jp/~kuriyama/BSD/ipfw2-ipv6-20040425.diff.gz The error logs of buildworld is: ===> sbin/ipfw cc -O -pipe -g -c /usr/src/sbin/ipfw/ipfw2.c In file included from /usr/src/sbin/ipfw/ipfw2.c:49: /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:176: error: field `mld_addr' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:242: error: field `nd_ns_target' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:253: error: field `nd_na_target' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:275: error: field `nd_rd_target' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:276: error: field `nd_rd_dst' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:307: error: field `nd_opt_pi_prefix' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:454: error: field `rpm_prefix' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:470: error: field `rpu_prefix' has incomplete type /usr/obj/usr/src/i386/usr/include/netinet/icmp6.h:488: error: field `rrr_prefix' has incomplete type *** Error code 1 -- Jun Kuriyama // IMG SRC, Inc. // FreeBSD Project