Add support for IPv4 only rules to IPFW2 now that it supports IPv6 as well.

This is the last requirement before we can retire ip6fw.

Reviewed by:	dwhite, brooks(earlier version)
Submitted by:	dwhite (manpage)
Silence from:	-ipfw
This commit is contained in:
Max Laier 2005-06-03 01:10:28 +00:00
parent d24ff94b24
commit 57cd6d263b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146894
4 changed files with 80 additions and 26 deletions

View File

@ -623,7 +623,7 @@ The search terminates.
.It Cm fwd | forward Ar ipaddr Ns Op , Ns Ar port .It Cm fwd | forward Ar ipaddr Ns Op , Ns Ar port
Change the next-hop on matching packets to Change the next-hop on matching packets to
.Ar ipaddr , .Ar ipaddr ,
which can be an IP address in dotted quad format or a host name. which can be an IP address or a host name.
The search terminates if this rule matches. The search terminates if this rule matches.
.Pp .Pp
If If
@ -805,14 +805,16 @@ Rule fields have the following meaning:
.It Ar protocol : Oo Cm not Oc Ar protocol-name | protocol-number .It Ar protocol : Oo Cm not Oc Ar protocol-name | protocol-number
An IP protocol specified by number or name An IP protocol specified by number or name
(for a complete list see (for a complete list see
.Pa /etc/protocols ) . .Pa /etc/protocols ) ,
The or one of the following keywords:
.Cm ip , .Bl -tag -width indent
.Cm ip6 , .It Cm ip4 | ipv4
.Cm ipv6 , Matches IPv4 packets.
or .It Cm ip6 | ipv6
.Cm all Matches IPv6 packets.
keywords mean any protocol will match. .It Cm ip | all
Matches any packet.
.El
.Pp .Pp
The The
.Cm { Ar protocol Cm or ... } .Cm { Ar protocol Cm or ... }
@ -861,7 +863,7 @@ Hostnames are resolved at the time the rule is added to the firewall list.
.It Ar addr Ns / Ns Ar masklen .It Ar addr Ns / Ns Ar masklen
Matches all addresses with base Matches all addresses with base
.Ar addr .Ar addr
(specified as a dotted quad or a hostname) (specified as an IP address or a hostname)
and mask width of and mask width of
.Cm masklen .Cm masklen
bits. bits.
@ -870,7 +872,7 @@ all IP numbers from 1.2.3.0 to 1.2.3.127 .
.It Ar addr Ns : Ns Ar mask .It Ar addr Ns : Ns Ar mask
Matches all addresses with base Matches all addresses with base
.Ar addr .Ar addr
(specified as a dotted quad or a hostname) (specified as an IP address or a hostname)
and the mask of and the mask of
.Ar mask , .Ar mask ,
specified as a dotted quad. specified as a dotted quad.
@ -887,7 +889,7 @@ error-prone.
.It Ar list : Bro Ar num | num-num Brc Ns Op Ns , Ns Ar list .It Ar list : Bro Ar num | num-num Brc Ns Op Ns , Ns Ar list
Matches all addresses with base address Matches all addresses with base address
.Ar addr .Ar addr
(specified as a dotted quad or a hostname) (specified as an IP address or a hostname)
and whose last byte is in the list between braces { } . and whose last byte is in the list between braces { } .
Note that there must be no spaces between braces and Note that there must be no spaces between braces and
numbers (spaces after commas are allowed). numbers (spaces after commas are allowed).
@ -1444,7 +1446,7 @@ Each entry is represented by an
.Ar addr Ns Op / Ns Ar masklen .Ar addr Ns Op / Ns Ar masklen
and will match all addresses with base and will match all addresses with base
.Ar addr .Ar addr
(specified as a dotted quad or a hostname) (specified as an IP address or a hostname)
and mask width of and mask width of
.Ar masklen .Ar masklen
bits. bits.

View File

@ -275,6 +275,8 @@ enum tokens {
TOK_EXT6HDR, TOK_EXT6HDR,
TOK_DSTIP6, TOK_DSTIP6,
TOK_SRCIP6, TOK_SRCIP6,
TOK_IPV4,
}; };
struct _s_x dummynet_params[] = { struct _s_x dummynet_params[] = {
@ -395,6 +397,8 @@ struct _s_x rule_options[] = {
{ "flow-id", TOK_FLOWID}, { "flow-id", TOK_FLOWID},
{ "ipv6", TOK_IPV6}, { "ipv6", TOK_IPV6},
{ "ip6", TOK_IPV6}, { "ip6", TOK_IPV6},
{ "ipv4", TOK_IPV4},
{ "ip4", TOK_IPV4},
{ "dst-ipv6", TOK_DSTIP6}, { "dst-ipv6", TOK_DSTIP6},
{ "dst-ip6", TOK_DSTIP6}, { "dst-ip6", TOK_DSTIP6},
{ "src-ipv6", TOK_SRCIP6}, { "src-ipv6", TOK_SRCIP6},
@ -1260,6 +1264,7 @@ print_ext6hdr( ipfw_insn *cmd )
#define HAVE_DSTIP 0x0004 #define HAVE_DSTIP 0x0004
#define HAVE_MAC 0x0008 #define HAVE_MAC 0x0008
#define HAVE_MACTYPE 0x0010 #define HAVE_MACTYPE 0x0010
#define HAVE_PROTO4 0x0040
#define HAVE_PROTO6 0x0080 #define HAVE_PROTO6 0x0080
#define HAVE_OPTIONS 0x8000 #define HAVE_OPTIONS 0x8000
@ -1283,11 +1288,14 @@ show_prerequisites(int *flags, int want, int cmd)
return; return;
} }
if ( !(*flags & HAVE_OPTIONS)) { if ( !(*flags & HAVE_OPTIONS)) {
/* XXX BED: !(*flags & HAVE_PROTO) in patch */
if ( !(*flags & HAVE_PROTO6) && (want & HAVE_PROTO6))
printf(" ipv6");
if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO)) if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO))
printf(" ip"); if ( (*flags & HAVE_PROTO4))
printf(" ip4");
else if ( (*flags & HAVE_PROTO6))
printf(" ip6");
else
printf(" ip");
if ( !(*flags & HAVE_SRCIP) && (want & HAVE_SRCIP)) if ( !(*flags & HAVE_SRCIP) && (want & HAVE_SRCIP))
printf(" from any"); printf(" from any");
if ( !(*flags & HAVE_DSTIP) && (want & HAVE_DSTIP)) if ( !(*flags & HAVE_DSTIP) && (want & HAVE_DSTIP))
@ -1468,9 +1476,23 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
/* /*
* then print the body. * then print the body.
*/ */
for (l = rule->act_ofs, cmd = rule->cmd ;
l > 0 ; l -= F_LEN(cmd) , cmd += F_LEN(cmd)) {
if ((cmd->len & F_OR) || (cmd->len & F_NOT))
continue;
if (cmd->opcode == O_IP4) {
flags |= HAVE_PROTO4;
break;
} else if (cmd->opcode == O_IP6) {
flags |= HAVE_PROTO6;
break;
}
}
if (rule->_pad & 1) { /* empty rules before options */ if (rule->_pad & 1) { /* empty rules before options */
if (!do_compact) if (!do_compact) {
printf(" ip from any to any"); show_prerequisites(&flags, HAVE_PROTO, 0);
printf(" from any to any");
}
flags |= HAVE_IP | HAVE_OPTIONS; flags |= HAVE_IP | HAVE_OPTIONS;
} }
@ -1600,6 +1622,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
printf(" not"); printf(" not");
proto = cmd->arg1; proto = cmd->arg1;
pe = getprotobynumber(cmd->arg1); pe = getprotobynumber(cmd->arg1);
if ((flags & (HAVE_PROTO4 | HAVE_PROTO6)) &&
!(flags & HAVE_PROTO))
show_prerequisites(&flags,
HAVE_IP | HAVE_OPTIONS, 0);
if (flags & HAVE_OPTIONS) if (flags & HAVE_OPTIONS)
printf(" proto"); printf(" proto");
if (pe) if (pe)
@ -1611,6 +1637,12 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
break; break;
default: /*options ... */ default: /*options ... */
if (!(cmd->len & (F_OR|F_NOT)))
if (((cmd->opcode == O_IP6) &&
(flags & HAVE_PROTO6)) ||
((cmd->opcode == O_IP4) &&
(flags & HAVE_PROTO4)))
break;
show_prerequisites(&flags, HAVE_IP | HAVE_OPTIONS, 0); show_prerequisites(&flags, HAVE_IP | HAVE_OPTIONS, 0);
if ((cmd->len & F_OR) && !or_block) if ((cmd->len & F_OR) && !or_block)
printf(" {"); printf(" {");
@ -1810,10 +1842,14 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
} }
break; break;
case O_IP6: case O_IP6:
printf(" ipv6"); printf(" ipv6");
break; break;
case O_IP4:
printf(" ipv4");
break;
case O_ICMP6TYPE: case O_ICMP6TYPE:
print_icmp6types((ipfw_insn_u32 *)cmd); print_icmp6types((ipfw_insn_u32 *)cmd);
break; break;
@ -3506,13 +3542,18 @@ add_proto(ipfw_insn *cmd, char *av, u_char *proto)
*proto = IPPROTO_IP; *proto = IPPROTO_IP;
if (_substrcmp(av, "all") == 0) if (_substrcmp(av, "all") == 0)
; /* same as "ip" */ ; /* do not set O_IP4 nor O_IP6 */
else if ((*proto = atoi(av)) > 0) else if (strcmp(av, "ipv4") == 0 || strcmp(av, "ip4") == 0)
/* explicit "just IPv4" rule */
fill_cmd(cmd, O_IP4, 0, 0);
else if (strcmp(av, "ipv6") == 0 || strcmp(av, "ip6") == 0) {
/* explicit "just IPv6" rule */
*proto = IPPROTO_IPV6;
fill_cmd(cmd, O_IP6, 0, 0);
} else if ((*proto = atoi(av)) > 0)
; /* all done! */ ; /* all done! */
else if ((pe = getprotobyname(av)) != NULL) else if ((pe = getprotobyname(av)) != NULL)
*proto = pe->p_proto; *proto = pe->p_proto;
else if (strcmp(av, "ipv6") == 0 || strcmp(av, "ip6") == 0)
*proto = IPPROTO_IPV6;
else else
return NULL; return NULL;
if (*proto != IPPROTO_IP && *proto != IPPROTO_IPV6) if (*proto != IPPROTO_IP && *proto != IPPROTO_IPV6)
@ -4347,8 +4388,6 @@ add(int ac, char *av[])
case TOK_PROTO: case TOK_PROTO:
NEED1("missing protocol"); NEED1("missing protocol");
if (add_proto(cmd, *av, &proto)) { if (add_proto(cmd, *av, &proto)) {
if (proto == IPPROTO_IPV6)
fill_cmd(cmd, O_IP6, 0, 0);
ac--; av++; ac--; av++;
} else } else
errx(EX_DATAERR, "invalid protocol ``%s''", errx(EX_DATAERR, "invalid protocol ``%s''",
@ -4435,6 +4474,10 @@ add(int ac, char *av[])
fill_cmd(cmd, O_IP6, 0, 0); fill_cmd(cmd, O_IP6, 0, 0);
break; break;
case TOK_IPV4:
fill_cmd(cmd, O_IP4, 0, 0);
break;
case TOK_EXT6HDR: case TOK_EXT6HDR:
fill_ext6hdr( cmd, *av ); fill_ext6hdr( cmd, *av );
ac--; av++; ac--; av++;

View File

@ -153,6 +153,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_NETGRAPH, /* send to ng_ipfw */ O_NETGRAPH, /* send to ng_ipfw */
O_NGTEE, /* copy to ng_ipfw */ O_NGTEE, /* copy to ng_ipfw */
O_IP4,
O_LAST_OPCODE /* not an opcode! */ O_LAST_OPCODE /* not an opcode! */
}; };

View File

@ -1961,6 +1961,7 @@ ipfw_chk(struct ip_fw_args *args)
int is_ipv6 = 0; int is_ipv6 = 0;
u_int16_t ext_hd = 0; /* bits vector for extension header filtering */ u_int16_t ext_hd = 0; /* bits vector for extension header filtering */
/* end of ipv6 variables */ /* end of ipv6 variables */
int is_ipv4 = 0;
if (m->m_flags & M_SKIP_FIREWALL) if (m->m_flags & M_SKIP_FIREWALL)
return (IP_FW_PASS); /* accept */ return (IP_FW_PASS); /* accept */
@ -2076,6 +2077,7 @@ do { \
} else if (pktlen >= sizeof(struct ip) && } else if (pktlen >= sizeof(struct ip) &&
(args->eh == NULL || ntohs(args->eh->ether_type) == ETHERTYPE_IP) && (args->eh == NULL || ntohs(args->eh->ether_type) == ETHERTYPE_IP) &&
mtod(m, struct ip *)->ip_v == 4) { mtod(m, struct ip *)->ip_v == 4) {
is_ipv4 = 1;
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2; hlen = ip->ip_hl << 2;
args->f_id.addr_type = 4; args->f_id.addr_type = 4;
@ -2677,6 +2679,10 @@ do { \
break; break;
#endif #endif
case O_IP4:
match = is_ipv4;
break;
/* /*
* The second set of opcodes represents 'actions', * The second set of opcodes represents 'actions',
* i.e. the terminal part of a rule once the packet * i.e. the terminal part of a rule once the packet
@ -3322,6 +3328,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_IP6_DST_ME: case O_IP6_DST_ME:
case O_EXT_HDR: case O_EXT_HDR:
case O_IP6: case O_IP6:
case O_IP4:
if (cmdlen != F_INSN_SIZE(ipfw_insn)) if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size; goto bad_size;
break; break;