Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/ipfw/ip_fw2.c
Show First 20 Lines • Show All 1,185 Lines • ▼ Show 20 Lines | |||||
static inline void | static inline void | ||||
set_match(struct ip_fw_args *args, int slot, | set_match(struct ip_fw_args *args, int slot, | ||||
struct ip_fw_chain *chain) | struct ip_fw_chain *chain) | ||||
{ | { | ||||
args->rule.chain_id = chain->id; | args->rule.chain_id = chain->id; | ||||
args->rule.slot = slot + 1; /* we use 0 as a marker */ | args->rule.slot = slot + 1; /* we use 0 as a marker */ | ||||
args->rule.rule_id = 1 + chain->map[slot]->id; | args->rule.rule_id = 1 + chain->map[slot]->id; | ||||
args->rule.rulenum = chain->map[slot]->rulenum; | args->rule.rulenum = chain->map[slot]->rulenum; | ||||
args->flags |= IPFW_ARGS_REF; | |||||
} | } | ||||
#ifndef LINEAR_SKIPTO | #ifndef LINEAR_SKIPTO | ||||
/* | /* | ||||
* Helper function to enable cached rule lookups using | * Helper function to enable cached rule lookups using | ||||
* cached_id and cached_pos fields in ipfw rule. | * cached_id and cached_pos fields in ipfw rule. | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | #endif | ||||
* | * | ||||
* src_port, dst_port port numbers, in HOST format. Only | * src_port, dst_port port numbers, in HOST format. Only | ||||
* valid for TCP and UDP packets. | * valid for TCP and UDP packets. | ||||
* | * | ||||
* src_ip, dst_ip ip addresses, in NETWORK format. | * src_ip, dst_ip ip addresses, in NETWORK format. | ||||
* Only valid for IPv4 packets. | * Only valid for IPv4 packets. | ||||
*/ | */ | ||||
uint8_t proto; | uint8_t proto; | ||||
uint16_t src_port = 0, dst_port = 0; /* NOTE: host format */ | uint16_t src_port, dst_port; /* NOTE: host format */ | ||||
struct in_addr src_ip, dst_ip; /* NOTE: network format */ | struct in_addr src_ip, dst_ip; /* NOTE: network format */ | ||||
int iplen = 0; | int iplen = 0; | ||||
int pktlen; | int pktlen; | ||||
uint16_t etype = 0; /* Host order stored ether type */ | uint16_t etype; /* Host order stored ether type */ | ||||
/* | |||||
* dyn_dir = MATCH_UNKNOWN when rules unchecked, | |||||
* MATCH_NONE when checked and not matched (q = NULL), | |||||
* MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL) | |||||
*/ | |||||
struct ipfw_dyn_info dyn_info; | struct ipfw_dyn_info dyn_info; | ||||
struct ip_fw *q = NULL; | struct ip_fw *q = NULL; | ||||
struct ip_fw_chain *chain = &V_layer3_chain; | struct ip_fw_chain *chain = &V_layer3_chain; | ||||
/* | /* | ||||
* We store in ulp a pointer to the upper layer protocol header. | * We store in ulp a pointer to the upper layer protocol header. | ||||
* In the ipv4 case this is easy to determine from the 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. | * but for ipv6 we might have some additional headers in the middle. | ||||
Show All 12 Lines | #endif | ||||
int done = 0; /* flag to exit the outer loop */ | int done = 0; /* flag to exit the outer loop */ | ||||
if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready)) | if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready)) | ||||
return (IP_FW_PASS); /* accept */ | return (IP_FW_PASS); /* accept */ | ||||
dst_ip.s_addr = 0; /* make sure it is initialized */ | dst_ip.s_addr = 0; /* make sure it is initialized */ | ||||
src_ip.s_addr = 0; /* make sure it is initialized */ | src_ip.s_addr = 0; /* make sure it is initialized */ | ||||
pktlen = m->m_pkthdr.len; | pktlen = m->m_pkthdr.len; | ||||
args->f_id.fib = M_GETFIB(m); /* note mbuf not altered) */ | |||||
proto = args->f_id.proto = 0; /* mark f_id invalid */ | |||||
/* XXX 0 is a valid proto: IP/IPv6 Hop-by-Hop Option */ | |||||
DYN_INFO_INIT(&dyn_info); | DYN_INFO_INIT(&dyn_info); | ||||
/* | /* | ||||
* PULLUP_TO(len, p, T) makes sure that len + sizeof(T) is contiguous, | * PULLUP_TO(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 | * 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 | * pointer might become stale after other pullups (but we never use it | ||||
* this way). | * this way). | ||||
*/ | */ | ||||
#define PULLUP_TO(_len, p, T) PULLUP_LEN(_len, p, sizeof(T)) | #define PULLUP_TO(_len, p, T) PULLUP_LEN(_len, p, sizeof(T)) | ||||
#define PULLUP_LEN(_len, p, T) \ | #define PULLUP_LEN(_len, p, T) \ | ||||
do { \ | do { \ | ||||
int x = (_len) + T; \ | int x = (_len) + T; \ | ||||
if ((m)->m_len < x) { \ | if ((m)->m_len < x) { \ | ||||
args->m = m = m_pullup(m, x); \ | args->m = m = m_pullup(m, x); \ | ||||
if (m == NULL) \ | if (m == NULL) \ | ||||
goto pullup_failed; \ | goto pullup_failed; \ | ||||
} \ | } \ | ||||
p = (mtod(m, char *) + (_len)); \ | p = (mtod(m, char *) + (_len)); \ | ||||
} while (0) | } while (0) | ||||
/* | /* | ||||
* if we have an ether header, | * if we have an ether header, | ||||
*/ | */ | ||||
if (args->eh) | if (args->flags & IPFW_ARGS_ETHER) | ||||
etype = ntohs(args->eh->ether_type); | etype = ntohs(args->eh->ether_type); | ||||
else | |||||
etype = 0; | |||||
/* Identify IP packets and fill up variables. */ | /* Identify IP packets and fill up variables. */ | ||||
if (pktlen >= sizeof(struct ip6_hdr) && | if (pktlen >= sizeof(struct ip6_hdr) && | ||||
(args->eh == NULL || etype == ETHERTYPE_IPV6) && ip->ip_v == 6) { | (etype == 0 || etype == ETHERTYPE_IPV6) && ip->ip_v == 6) { | ||||
struct ip6_hdr *ip6 = (struct ip6_hdr *)ip; | struct ip6_hdr *ip6 = (struct ip6_hdr *)ip; | ||||
is_ipv6 = 1; | is_ipv6 = 1; | ||||
args->f_id.addr_type = 6; | |||||
hlen = sizeof(struct ip6_hdr); | hlen = sizeof(struct ip6_hdr); | ||||
proto = ip6->ip6_nxt; | proto = ip6->ip6_nxt; | ||||
/* Search extension headers to find upper layer protocols */ | /* Search extension headers to find upper layer protocols */ | ||||
while (ulp == NULL && offset == 0) { | while (ulp == NULL && offset == 0) { | ||||
switch (proto) { | switch (proto) { | ||||
case IPPROTO_ICMPV6: | case IPPROTO_ICMPV6: | ||||
PULLUP_TO(hlen, ulp, struct icmp6_hdr); | PULLUP_TO(hlen, ulp, struct icmp6_hdr); | ||||
icmp6_type = ICMP6(ulp)->icmp6_type; | icmp6_type = ICMP6(ulp)->icmp6_type; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | while (ulp == NULL && offset == 0) { | ||||
if (V_fw_deny_unknown_exthdrs) | if (V_fw_deny_unknown_exthdrs) | ||||
return (IP_FW_DENY); | return (IP_FW_DENY); | ||||
PULLUP_TO(hlen, ulp, struct ip6_ext); | PULLUP_TO(hlen, ulp, struct ip6_ext); | ||||
break; | break; | ||||
} /*switch */ | } /*switch */ | ||||
} | } | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
ip6 = (struct ip6_hdr *)ip; | ip6 = (struct ip6_hdr *)ip; | ||||
args->f_id.addr_type = 6; | |||||
args->f_id.src_ip6 = ip6->ip6_src; | args->f_id.src_ip6 = ip6->ip6_src; | ||||
args->f_id.dst_ip6 = ip6->ip6_dst; | args->f_id.dst_ip6 = ip6->ip6_dst; | ||||
args->f_id.src_ip = 0; | |||||
args->f_id.dst_ip = 0; | |||||
args->f_id.flow_id6 = ntohl(ip6->ip6_flow); | args->f_id.flow_id6 = ntohl(ip6->ip6_flow); | ||||
iplen = ntohs(ip6->ip6_plen) + sizeof(*ip6); | iplen = ntohs(ip6->ip6_plen) + sizeof(*ip6); | ||||
} else if (pktlen >= sizeof(struct ip) && | } else if (pktlen >= sizeof(struct ip) && | ||||
(args->eh == NULL || etype == ETHERTYPE_IP) && ip->ip_v == 4) { | (etype == 0 || etype == ETHERTYPE_IP) && ip->ip_v == 4) { | ||||
is_ipv4 = 1; | is_ipv4 = 1; | ||||
hlen = ip->ip_hl << 2; | hlen = ip->ip_hl << 2; | ||||
args->f_id.addr_type = 4; | |||||
/* | /* | ||||
* Collect parameters into local variables for faster matching. | * Collect parameters into local variables for faster | ||||
* matching. | |||||
*/ | */ | ||||
proto = ip->ip_p; | proto = ip->ip_p; | ||||
src_ip = ip->ip_src; | src_ip = ip->ip_src; | ||||
dst_ip = ip->ip_dst; | dst_ip = ip->ip_dst; | ||||
offset = ntohs(ip->ip_off) & IP_OFFMASK; | offset = ntohs(ip->ip_off) & IP_OFFMASK; | ||||
iplen = ntohs(ip->ip_len); | iplen = ntohs(ip->ip_len); | ||||
if (offset == 0) { | if (offset == 0) { | ||||
Show All 36 Lines | if (offset == 0) { | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
args->f_id.addr_type = 4; | |||||
args->f_id.src_ip = ntohl(src_ip.s_addr); | args->f_id.src_ip = ntohl(src_ip.s_addr); | ||||
args->f_id.dst_ip = ntohl(dst_ip.s_addr); | args->f_id.dst_ip = ntohl(dst_ip.s_addr); | ||||
} else { | |||||
proto = 0; | |||||
src_port = dst_port = 0; | |||||
dst_ip.s_addr = src_ip.s_addr = 0; | |||||
args->f_id.addr_type = 1; /* XXX */ | |||||
} | } | ||||
#undef PULLUP_TO | #undef PULLUP_TO | ||||
pktlen = iplen < pktlen ? iplen: pktlen; | pktlen = iplen < pktlen ? iplen: pktlen; | ||||
if (proto) { /* we may have port numbers, store them */ | |||||
/* Properly initialize the reset of f_id */ | |||||
args->f_id.proto = proto; | args->f_id.proto = proto; | ||||
args->f_id.src_port = src_port = ntohs(src_port); | args->f_id.src_port = src_port = ntohs(src_port); | ||||
args->f_id.dst_port = dst_port = ntohs(dst_port); | args->f_id.dst_port = dst_port = ntohs(dst_port); | ||||
} | args->f_id.fib = M_GETFIB(m); | ||||
IPFW_PF_RLOCK(chain); | IPFW_PF_RLOCK(chain); | ||||
if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */ | if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */ | ||||
IPFW_PF_RUNLOCK(chain); | IPFW_PF_RUNLOCK(chain); | ||||
return (IP_FW_PASS); /* accept */ | return (IP_FW_PASS); /* accept */ | ||||
} | } | ||||
if (args->rule.slot) { | if (args->flags & IPFW_ARGS_REF) { | ||||
/* | /* | ||||
* Packet has already been tagged as a result of a previous | * Packet has already been tagged as a result of a previous | ||||
* match on rule args->rule aka args->rule_id (PIPE, QUEUE, | * match on rule args->rule aka args->rule_id (PIPE, QUEUE, | ||||
* REASS, NETGRAPH, DIVERT/TEE...) | * REASS, NETGRAPH, DIVERT/TEE...) | ||||
* Validate the slot and continue from the next one | * Validate the slot and continue from the next one | ||||
* if still present, otherwise do a lookup. | * if still present, otherwise do a lookup. | ||||
*/ | */ | ||||
f_pos = (args->rule.chain_id == chain->id) ? | f_pos = (args->rule.chain_id == chain->id) ? | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | #endif | ||||
case O_VIA: | case O_VIA: | ||||
match = iface_match(oif ? oif : | match = iface_match(oif ? oif : | ||||
m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd, | m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd, | ||||
chain, &tablearg); | chain, &tablearg); | ||||
break; | break; | ||||
case O_MACADDR2: | case O_MACADDR2: | ||||
if (args->eh != NULL) { /* have MAC header */ | if (args->flags & IPFW_ARGS_ETHER) { | ||||
u_int32_t *want = (u_int32_t *) | u_int32_t *want = (u_int32_t *) | ||||
((ipfw_insn_mac *)cmd)->addr; | ((ipfw_insn_mac *)cmd)->addr; | ||||
u_int32_t *mask = (u_int32_t *) | u_int32_t *mask = (u_int32_t *) | ||||
((ipfw_insn_mac *)cmd)->mask; | ((ipfw_insn_mac *)cmd)->mask; | ||||
u_int32_t *hdr = (u_int32_t *)args->eh; | u_int32_t *hdr = (u_int32_t *)args->eh; | ||||
match = | match = | ||||
( want[0] == (hdr[0] & mask[0]) && | ( want[0] == (hdr[0] & mask[0]) && | ||||
want[1] == (hdr[1] & mask[1]) && | want[1] == (hdr[1] & mask[1]) && | ||||
want[2] == (hdr[2] & mask[2]) ); | want[2] == (hdr[2] & mask[2]) ); | ||||
} | } | ||||
break; | break; | ||||
case O_MAC_TYPE: | case O_MAC_TYPE: | ||||
if (args->eh != NULL) { | if (args->flags & IPFW_ARGS_ETHER) { | ||||
u_int16_t *p = | u_int16_t *p = | ||||
((ipfw_insn_u16 *)cmd)->ports; | ((ipfw_insn_u16 *)cmd)->ports; | ||||
int i; | int i; | ||||
for (i = cmdlen - 1; !match && i>0; | for (i = cmdlen - 1; !match && i>0; | ||||
i--, p += 2) | i--, p += 2) | ||||
match = (etype >= p[0] && | match = (etype >= p[0] && | ||||
etype <= p[1]); | etype <= p[1]); | ||||
} | } | ||||
break; | break; | ||||
case O_FRAG: | case O_FRAG: | ||||
match = (offset != 0); | match = (offset != 0); | ||||
break; | break; | ||||
case O_IN: /* "out" is "not in" */ | case O_IN: /* "out" is "not in" */ | ||||
match = (oif == NULL); | match = (oif == NULL); | ||||
break; | break; | ||||
case O_LAYER2: | case O_LAYER2: | ||||
match = (args->eh != NULL); | match = (args->flags & IPFW_ARGS_ETHER); | ||||
break; | break; | ||||
case O_DIVERTED: | case O_DIVERTED: | ||||
{ | if ((args->flags & IPFW_ARGS_REF) == 0) | ||||
/* For diverted packets, args->rule.info | break; | ||||
/* | |||||
* For diverted packets, args->rule.info | |||||
* contains the divert port (in host format) | * contains the divert port (in host format) | ||||
* reason and direction. | * reason and direction. | ||||
*/ | */ | ||||
uint32_t i = args->rule.info; | match = ((args->rule.info & IPFW_IS_MASK) == | ||||
match = (i&IPFW_IS_MASK) == IPFW_IS_DIVERT && | IPFW_IS_DIVERT) && ( | ||||
cmd->arg1 & ((i & IPFW_INFO_IN) ? 1 : 2); | ((args->rule.info & IPFW_INFO_IN) ? | ||||
} | 1: 2) & cmd->arg1); | ||||
break; | break; | ||||
case O_PROTO: | case O_PROTO: | ||||
/* | /* | ||||
* We do not allow an arg of 0 so the | * We do not allow an arg of 0 so the | ||||
* check of "proto" only suffices. | * check of "proto" only suffices. | ||||
*/ | */ | ||||
match = (proto == cmd->arg1); | match = (proto == cmd->arg1); | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | #endif /* !USERSPACE */ | ||||
case O_IP_SRC_ME: | case O_IP_SRC_ME: | ||||
if (is_ipv4) { | if (is_ipv4) { | ||||
match = in_localip(src_ip); | match = in_localip(src_ip); | ||||
break; | break; | ||||
} | } | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case O_IP6_SRC_ME: | case O_IP6_SRC_ME: | ||||
match= is_ipv6 && ipfw_localip6(&args->f_id.src_ip6); | match = is_ipv6 && | ||||
ipfw_localip6(&args->f_id.src_ip6); | |||||
#endif | #endif | ||||
break; | break; | ||||
case O_IP_DST_SET: | case O_IP_DST_SET: | ||||
case O_IP_SRC_SET: | case O_IP_SRC_SET: | ||||
if (is_ipv4) { | if (is_ipv4) { | ||||
u_int32_t *d = (u_int32_t *)(cmd+1); | u_int32_t *d = (u_int32_t *)(cmd+1); | ||||
u_int32_t addr = | u_int32_t addr = | ||||
Show All 19 Lines | #endif | ||||
case O_IP_DST_ME: | case O_IP_DST_ME: | ||||
if (is_ipv4) { | if (is_ipv4) { | ||||
match = in_localip(dst_ip); | match = in_localip(dst_ip); | ||||
break; | break; | ||||
} | } | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case O_IP6_DST_ME: | case O_IP6_DST_ME: | ||||
match= is_ipv6 && ipfw_localip6(&args->f_id.dst_ip6); | match = is_ipv6 && | ||||
ipfw_localip6(&args->f_id.dst_ip6); | |||||
#endif | #endif | ||||
break; | break; | ||||
case O_IP_SRCPORT: | case O_IP_SRCPORT: | ||||
case O_IP_DSTPORT: | case O_IP_DSTPORT: | ||||
/* | /* | ||||
* offset == 0 && proto != 0 is enough | * offset == 0 && proto != 0 is enough | ||||
▲ Show 20 Lines • Show All 581 Lines • ▼ Show 20 Lines | #endif /* !USERSPACE */ | ||||
args->rule.info |= IPFW_ONEPASS; | args->rule.info |= IPFW_ONEPASS; | ||||
retval = IP_FW_DUMMYNET; | retval = IP_FW_DUMMYNET; | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
break; | break; | ||||
case O_DIVERT: | case O_DIVERT: | ||||
case O_TEE: | case O_TEE: | ||||
if (args->eh) /* not on layer 2 */ | if (args->flags & IPFW_ARGS_ETHER) | ||||
break; | break; /* not on layer 2 */ | ||||
/* otherwise this is terminal */ | /* otherwise this is terminal */ | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
retval = (cmd->opcode == O_DIVERT) ? | retval = (cmd->opcode == O_DIVERT) ? | ||||
IP_FW_DIVERT : IP_FW_TEE; | IP_FW_DIVERT : IP_FW_TEE; | ||||
set_match(args, f_pos, chain); | set_match(args, f_pos, chain); | ||||
args->rule.info = TARG(cmd->arg1, divert); | args->rule.info = TARG(cmd->arg1, divert); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
case O_DENY: | case O_DENY: | ||||
retval = IP_FW_DENY; | retval = IP_FW_DENY; | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
break; | break; | ||||
case O_FORWARD_IP: | case O_FORWARD_IP: | ||||
if (args->eh) /* not valid on layer2 pkts */ | if (args->flags & IPFW_ARGS_ETHER) | ||||
break; | break; /* not valid on layer2 pkts */ | ||||
if (q != f || | if (q != f || | ||||
dyn_info.direction == MATCH_FORWARD) { | dyn_info.direction == MATCH_FORWARD) { | ||||
struct sockaddr_in *sa; | struct sockaddr_in *sa; | ||||
sa = &(((ipfw_insn_sa *)cmd)->sa); | sa = &(((ipfw_insn_sa *)cmd)->sa); | ||||
if (sa->sin_addr.s_addr == INADDR_ANY) { | if (sa->sin_addr.s_addr == INADDR_ANY) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
/* | /* | ||||
* We use O_FORWARD_IP opcode for | * We use O_FORWARD_IP opcode for | ||||
* fwd rule with tablearg, but tables | * fwd rule with tablearg, but tables | ||||
* now support IPv6 addresses. And | * now support IPv6 addresses. And | ||||
* when we are inspecting IPv6 packet, | * when we are inspecting IPv6 packet, | ||||
* we can use nh6 field from | * we can use nh6 field from | ||||
* table_value as next_hop6 address. | * table_value as next_hop6 address. | ||||
*/ | */ | ||||
if (is_ipv6) { | if (is_ipv6) { | ||||
struct sockaddr_in6 *sa6; | struct ip_fw_nh6 *nh6; | ||||
sa6 = args->next_hop6 = | args->flags |= IPFW_ARGS_NH6; | ||||
&args->hopstore6; | nh6 = &args->hopstore6; | ||||
sa6->sin6_family = AF_INET6; | nh6->sin6_addr = TARG_VAL( | ||||
sa6->sin6_len = sizeof(*sa6); | |||||
sa6->sin6_addr = TARG_VAL( | |||||
chain, tablearg, nh6); | chain, tablearg, nh6); | ||||
sa6->sin6_port = sa->sin_port; | nh6->sin6_port = sa->sin_port; | ||||
/* | nh6->sin6_scope_id = TARG_VAL( | ||||
* Set sin6_scope_id only for | chain, tablearg, zoneid); | ||||
* link-local unicast addresses. | |||||
*/ | |||||
if (IN6_IS_ADDR_LINKLOCAL( | |||||
&sa6->sin6_addr)) | |||||
sa6->sin6_scope_id = | |||||
TARG_VAL(chain, | |||||
tablearg, | |||||
zoneid); | |||||
} else | } else | ||||
#endif | #endif | ||||
{ | { | ||||
args->flags |= IPFW_ARGS_NH4; | |||||
args->hopstore.sin_port = | args->hopstore.sin_port = | ||||
sa->sin_port; | sa->sin_port; | ||||
sa = args->next_hop = | sa = &args->hopstore; | ||||
&args->hopstore; | |||||
sa->sin_family = AF_INET; | sa->sin_family = AF_INET; | ||||
sa->sin_len = sizeof(*sa); | sa->sin_len = sizeof(*sa); | ||||
sa->sin_addr.s_addr = htonl( | sa->sin_addr.s_addr = htonl( | ||||
TARG_VAL(chain, tablearg, | TARG_VAL(chain, tablearg, | ||||
nh4)); | nh4)); | ||||
} | } | ||||
} else { | } else { | ||||
args->flags |= IPFW_ARGS_NH4PTR; | |||||
args->next_hop = sa; | args->next_hop = sa; | ||||
} | } | ||||
} | } | ||||
retval = IP_FW_PASS; | retval = IP_FW_PASS; | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
break; | break; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case O_FORWARD_IP6: | case O_FORWARD_IP6: | ||||
if (args->eh) /* not valid on layer2 pkts */ | if (args->flags & IPFW_ARGS_ETHER) | ||||
break; | break; /* not valid on layer2 pkts */ | ||||
if (q != f || | if (q != f || | ||||
dyn_info.direction == MATCH_FORWARD) { | dyn_info.direction == MATCH_FORWARD) { | ||||
struct sockaddr_in6 *sin6; | struct sockaddr_in6 *sin6; | ||||
sin6 = &(((ipfw_insn_sa6 *)cmd)->sa); | sin6 = &(((ipfw_insn_sa6 *)cmd)->sa); | ||||
args->flags |= IPFW_ARGS_NH6PTR; | |||||
args->next_hop6 = sin6; | args->next_hop6 = sin6; | ||||
} | } | ||||
retval = IP_FW_PASS; | retval = IP_FW_PASS; | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
break; | break; | ||||
#endif | #endif | ||||
Show All 12 Lines | #endif | ||||
case O_SETFIB: { | case O_SETFIB: { | ||||
uint32_t fib; | uint32_t fib; | ||||
IPFW_INC_RULE_COUNTER(f, pktlen); | IPFW_INC_RULE_COUNTER(f, pktlen); | ||||
fib = TARG(cmd->arg1, fib) & 0x7FFF; | fib = TARG(cmd->arg1, fib) & 0x7FFF; | ||||
if (fib >= rt_numfibs) | if (fib >= rt_numfibs) | ||||
fib = 0; | fib = 0; | ||||
M_SETFIB(m, fib); | M_SETFIB(m, fib); | ||||
args->f_id.fib = fib; | args->f_id.fib = fib; /* XXX */ | ||||
l = 0; /* exit inner loop */ | l = 0; /* exit inner loop */ | ||||
break; | break; | ||||
} | } | ||||
case O_SETDSCP: { | case O_SETDSCP: { | ||||
uint16_t code; | uint16_t code; | ||||
code = TARG(cmd->arg1, dscp) & 0x3F; | code = TARG(cmd->arg1, dscp) & 0x3F; | ||||
Show All 30 Lines | #endif | ||||
if (!is_ipv4 || !IPFW_NAT_LOADED) { | if (!is_ipv4 || !IPFW_NAT_LOADED) { | ||||
retval = IP_FW_DENY; | retval = IP_FW_DENY; | ||||
break; | break; | ||||
} | } | ||||
struct cfg_nat *t; | struct cfg_nat *t; | ||||
int nat_id; | int nat_id; | ||||
args->rule.info = 0; | |||||
set_match(args, f_pos, chain); | set_match(args, f_pos, chain); | ||||
/* Check if this is 'global' nat rule */ | /* Check if this is 'global' nat rule */ | ||||
if (cmd->arg1 == IP_FW_NAT44_GLOBAL) { | if (cmd->arg1 == IP_FW_NAT44_GLOBAL) { | ||||
retval = ipfw_nat_ptr(args, NULL, m); | retval = ipfw_nat_ptr(args, NULL, m); | ||||
break; | break; | ||||
} | } | ||||
t = ((ipfw_insn_nat *)cmd)->nat; | t = ((ipfw_insn_nat *)cmd)->nat; | ||||
if (t == NULL) { | if (t == NULL) { | ||||
Show All 36 Lines | #endif | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
hlen = ip->ip_hl << 2; | hlen = ip->ip_hl << 2; | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
if (hlen == sizeof(struct ip)) | if (hlen == sizeof(struct ip)) | ||||
ip->ip_sum = in_cksum_hdr(ip); | ip->ip_sum = in_cksum_hdr(ip); | ||||
else | else | ||||
ip->ip_sum = in_cksum(m, hlen); | ip->ip_sum = in_cksum(m, hlen); | ||||
retval = IP_FW_REASS; | retval = IP_FW_REASS; | ||||
args->rule.info = 0; | |||||
set_match(args, f_pos, chain); | set_match(args, f_pos, chain); | ||||
} | } | ||||
done = 1; /* exit outer loop */ | done = 1; /* exit outer loop */ | ||||
break; | break; | ||||
} | } | ||||
case O_EXTERNAL_ACTION: | case O_EXTERNAL_ACTION: | ||||
l = 0; /* in any case exit inner loop */ | l = 0; /* in any case exit inner loop */ | ||||
retval = ipfw_run_eaction(chain, args, | retval = ipfw_run_eaction(chain, args, | ||||
▲ Show 20 Lines • Show All 383 Lines • Show Last 20 Lines |