FreeBSD Bugzilla – Attachment 180465 Details for
Bug 217292
ipfw lookup on fields other than IP source and destination address doesn't work for IPv6
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed patch
s11_ipfw_table.diff (text/plain), 8.37 KB, created by
Andrey V. Elsukov
on 2017-03-03 15:20:39 UTC
(
hide
)
Description:
Proposed patch
Filename:
MIME Type:
Creator:
Andrey V. Elsukov
Created:
2017-03-03 15:20:39 UTC
Size:
8.37 KB
patch
obsolete
>Index: stable/11/sys/netpfil/ipfw/ip_fw2.c >=================================================================== >--- stable/11/sys/netpfil/ipfw/ip_fw2.c (revision 314573) >+++ stable/11/sys/netpfil/ipfw/ip_fw2.c (working copy) >@@ -382,7 +382,7 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, > /* Check by name or by IP address */ > if (cmd->name[0] != '\0') { /* match by name */ > if (cmd->name[0] == '\1') /* use tablearg to match */ >- return ipfw_lookup_table_extended(chain, cmd->p.kidx, 0, >+ return ipfw_lookup_table(chain, cmd->p.kidx, 0, > &ifp->if_index, tablearg); > /* Check name */ > if (cmd->p.glob) { >@@ -1454,88 +1454,134 @@ do { \ > src_ip.s_addr); > break; > >- case O_IP_SRC_LOOKUP: > case O_IP_DST_LOOKUP: >- if (is_ipv4) { >- uint32_t key = >- (cmd->opcode == O_IP_DST_LOOKUP) ? >- dst_ip.s_addr : src_ip.s_addr; >- uint32_t v = 0; >+ { >+ void *pkey; >+ uint32_t vidx, key; >+ uint16_t keylen; > >- if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) { >- /* generic lookup. The key must be >- * in 32bit big-endian format. >- */ >- v = ((ipfw_insn_u32 *)cmd)->d[1]; >- if (v == 0) >- key = dst_ip.s_addr; >- else if (v == 1) >- key = src_ip.s_addr; >- else if (v == 6) /* dscp */ >- key = (ip->ip_tos >> 2) & 0x3f; >- else if (offset != 0) >- break; >- else if (proto != IPPROTO_TCP && >- proto != IPPROTO_UDP) >- break; >- else if (v == 2) >- key = dst_port; >- else if (v == 3) >- key = src_port; >+ if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) { >+ /* Determine lookup key type */ >+ vidx = ((ipfw_insn_u32 *)cmd)->d[1]; >+ if (vidx != 4 /* uid */ && >+ vidx != 5 /* jail */ && >+ is_ipv6 == 0 && is_ipv4 == 0) >+ break; >+ /* Determine key length */ >+ if (vidx == 0 /* dst-ip */ || >+ vidx == 1 /* src-ip */) >+ keylen = is_ipv6 ? >+ sizeof(struct in6_addr): >+ sizeof(in_addr_t); >+ else { >+ keylen = sizeof(key); >+ pkey = &key; >+ } >+ if (vidx == 0 /* dst-ip */) >+ pkey = is_ipv4 ? (void *)&dst_ip: >+ (void *)&args->f_id.dst_ip6; >+ else if (vidx == 1 /* src-ip */) >+ pkey = is_ipv4 ? (void *)&src_ip: >+ (void *)&args->f_id.src_ip6; >+ else if (vidx == 6 /* dscp */) { >+ if (is_ipv4) >+ key = ip->ip_tos >> 2; >+ else { >+ key = args->f_id.flow_id6; >+ key = (key & 0x0f) << 2 | >+ (key & 0xf000) >> 14; >+ } >+ key &= 0x3f; >+ } else if (vidx == 2 /* dst-port */ || >+ vidx == 3 /* src-port */) { >+ /* Skip fragments */ >+ if (offset != 0) >+ break; >+ /* Skip proto without ports */ >+ if (proto != IPPROTO_TCP && >+ proto != IPPROTO_UDP && >+ proto != IPPROTO_SCTP) >+ break; >+ if (vidx == 2 /* dst-port */) >+ key = dst_port; >+ else >+ key = src_port; >+ } > #ifndef USERSPACE >- else if (v == 4 || v == 5) { >- check_uidgid( >- (ipfw_insn_u32 *)cmd, >- args, &ucred_lookup, >+ else if (vidx == 4 /* uid */ || >+ vidx == 5 /* jail */) { >+ check_uidgid( >+ (ipfw_insn_u32 *)cmd, >+ args, &ucred_lookup, > #ifdef __FreeBSD__ >- &ucred_cache); >- if (v == 4 /* O_UID */) >- key = ucred_cache->cr_uid; >- else if (v == 5 /* O_JAIL */) >- key = ucred_cache->cr_prison->pr_id; >+ &ucred_cache); >+ if (vidx == 4 /* uid */) >+ key = ucred_cache->cr_uid; >+ else if (vidx == 5 /* jail */) >+ key = ucred_cache->cr_prison->pr_id; > #else /* !__FreeBSD__ */ >- (void *)&ucred_cache); >- if (v ==4 /* O_UID */) >- key = ucred_cache.uid; >- else if (v == 5 /* O_JAIL */) >- key = ucred_cache.xid; >+ (void *)&ucred_cache); >+ if (vidx == 4 /* uid */) >+ key = ucred_cache.uid; >+ else if (vidx == 5 /* jail */) >+ key = ucred_cache.xid; > #endif /* !__FreeBSD__ */ > } > #endif /* !USERSPACE */ > else >- break; >- } >- match = ipfw_lookup_table(chain, >- cmd->arg1, key, &v); >- if (!match) >+ break; >+ match = ipfw_lookup_table(chain, >+ cmd->arg1, keylen, pkey, &vidx); >+ if (!match) >+ break; >+ tablearg = vidx; > break; >- if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) >- match = >- ((ipfw_insn_u32 *)cmd)->d[0] == v; >- else >- tablearg = v; >+ } >+ /* cmdlen =< F_INSN_SIZE(ipfw_insn_u32) */ >+ /* FALLTHROUGH */ >+ } >+ case O_IP_SRC_LOOKUP: >+ { >+ void *pkey; >+ uint32_t vidx; >+ uint16_t keylen; >+ >+ if (is_ipv4) { >+ keylen = sizeof(in_addr_t); >+ if (cmd->opcode == O_IP_DST_LOOKUP) >+ pkey = &dst_ip; >+ else >+ pkey = &src_ip; > } else if (is_ipv6) { >- uint32_t v = 0; >- void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ? >- &args->f_id.dst_ip6: &args->f_id.src_ip6; >- match = ipfw_lookup_table_extended(chain, >- cmd->arg1, >- sizeof(struct in6_addr), >- pkey, &v); >- if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) >- match = ((ipfw_insn_u32 *)cmd)->d[0] == v; >- if (match) >- tablearg = v; >+ keylen = sizeof(struct in6_addr); >+ if (cmd->opcode == O_IP_DST_LOOKUP) >+ pkey = &args->f_id.dst_ip6; >+ else >+ pkey = &args->f_id.src_ip6; >+ } else >+ break; >+ match = ipfw_lookup_table(chain, cmd->arg1, >+ keylen, pkey, &vidx); >+ if (!match) >+ break; >+ if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) { >+ match = ((ipfw_insn_u32 *)cmd)->d[0] == >+ TARG_VAL(chain, vidx, tag); >+ if (!match) >+ break; > } >+ tablearg = vidx; > break; >+ } > > case O_IP_FLOW_LOOKUP: > { > uint32_t v = 0; >- match = ipfw_lookup_table_extended(chain, >+ match = ipfw_lookup_table(chain, > cmd->arg1, 0, &args->f_id, &v); > if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) >- match = ((ipfw_insn_u32 *)cmd)->d[0] == v; >+ match = ((ipfw_insn_u32 *)cmd)->d[0] == >+ TARG_VAL(chain, v, tag); > if (match) > tablearg = v; > } >Index: stable/11/sys/netpfil/ipfw/ip_fw_private.h >=================================================================== >--- stable/11/sys/netpfil/ipfw/ip_fw_private.h (revision 314573) >+++ stable/11/sys/netpfil/ipfw/ip_fw_private.h (working copy) >@@ -739,9 +739,7 @@ struct table_info; > typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen, > uint32_t *val); > >-int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, >- uint32_t *val); >-int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, >+int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, > void *paddr, uint32_t *val); > int ipfw_init_tables(struct ip_fw_chain *ch, int first); > int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables); >Index: stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c >=================================================================== >--- stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c (revision 314573) >+++ stable/11/sys/netpfil/ipfw/ip_fw_sockopt.c (working copy) >@@ -1821,6 +1821,8 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, > break; > > case O_IP_SRC_LOOKUP: >+ if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) >+ goto bad_size; > case O_IP_DST_LOOKUP: > if (cmd->arg1 >= V_fw_tables_max) { > printf("ipfw: invalid table number %d\n", >Index: stable/11/sys/netpfil/ipfw/ip_fw_table.c >=================================================================== >--- stable/11/sys/netpfil/ipfw/ip_fw_table.c (revision 314573) >+++ stable/11/sys/netpfil/ipfw/ip_fw_table.c (working copy) >@@ -1606,23 +1606,6 @@ ipfw_resize_tables(struct ip_fw_chain *ch, unsigne > } > > /* >- * Lookup an IP @addr in table @tbl. >- * Stores found value in @val. >- * >- * Returns 1 if @addr was found. >- */ >-int >-ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, >- uint32_t *val) >-{ >- struct table_info *ti; >- >- ti = KIDX_TO_TI(ch, tbl); >- >- return (ti->lookup(ti, &addr, sizeof(in_addr_t), val)); >-} >- >-/* > * Lookup an arbtrary key @paddr of legth @plen in table @tbl. > * Stores found value in @val. > * >@@ -1629,7 +1612,7 @@ ipfw_resize_tables(struct ip_fw_chain *ch, unsigne > * Returns 1 if key was found. > */ > int >-ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, >+ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, > void *paddr, uint32_t *val) > { > struct table_info *ti;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 217292
: 180465