aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-12-03 16:23:12 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 16:23:12 -0500
commit424eff975192553a9ea8bfd51bf65039ffb356ef (patch)
tree5fa7b15715b3ce904f7250c50d09bc921d9f28bf /net/ipv6
parent55dbabee63462a455d8fb57caf08b69db256b012 (diff)
parent3666ed1c4837fd6906da0224c5373d7a2186a193 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_queue.c5
-rw-r--r--net/ipv6/netfilter/ip6_tables.c42
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c4
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c4
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c19
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c47
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c9
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c4
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c14
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
10 files changed, 74 insertions, 86 deletions
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 4c7a18abcaff..db4d5725cce8 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -499,8 +499,7 @@ ipq_rcv_nl_event(struct notifier_block *this,
499{ 499{
500 struct netlink_notify *n = ptr; 500 struct netlink_notify *n = ptr;
501 501
502 if (event == NETLINK_URELEASE && 502 if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) {
503 n->protocol == NETLINK_IP6_FW && n->pid) {
504 write_lock_bh(&queue_lock); 503 write_lock_bh(&queue_lock);
505 if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) 504 if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid))
506 __ipq_reset(); 505 __ipq_reset();
@@ -625,7 +624,7 @@ cleanup_netlink_notifier:
625static void __exit ip6_queue_fini(void) 624static void __exit ip6_queue_fini(void)
626{ 625{
627 nf_unregister_queue_handlers(&nfqh); 626 nf_unregister_queue_handlers(&nfqh);
628 synchronize_net(); 627
629 ipq_flush(NULL, 0); 628 ipq_flush(NULL, 0);
630 629
631#ifdef CONFIG_SYSCTL 630#ifdef CONFIG_SYSCTL
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index cc9f8ef303fd..480d7f8c9802 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -105,9 +105,9 @@ ip6_packet_match(const struct sk_buff *skb,
105#define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg))) 105#define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
106 106
107 if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, 107 if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
108 &ip6info->src), IP6T_INV_SRCIP) 108 &ip6info->src), IP6T_INV_SRCIP) ||
109 || FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, 109 FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
110 &ip6info->dst), IP6T_INV_DSTIP)) { 110 &ip6info->dst), IP6T_INV_DSTIP)) {
111 dprintf("Source or dest mismatch.\n"); 111 dprintf("Source or dest mismatch.\n");
112/* 112/*
113 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, 113 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
@@ -277,11 +277,11 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
277 } else if (s == e) { 277 } else if (s == e) {
278 (*rulenum)++; 278 (*rulenum)++;
279 279
280 if (s->target_offset == sizeof(struct ip6t_entry) 280 if (s->target_offset == sizeof(struct ip6t_entry) &&
281 && strcmp(t->target.u.kernel.target->name, 281 strcmp(t->target.u.kernel.target->name,
282 IP6T_STANDARD_TARGET) == 0 282 IP6T_STANDARD_TARGET) == 0 &&
283 && t->verdict < 0 283 t->verdict < 0 &&
284 && unconditional(&s->ipv6)) { 284 unconditional(&s->ipv6)) {
285 /* Tail of chains: STANDARD target (return/policy) */ 285 /* Tail of chains: STANDARD target (return/policy) */
286 *comment = *chainname == hookname 286 *comment = *chainname == hookname
287 ? comments[NF_IP6_TRACE_COMMENT_POLICY] 287 ? comments[NF_IP6_TRACE_COMMENT_POLICY]
@@ -418,8 +418,8 @@ ip6t_do_table(struct sk_buff *skb,
418 back = get_entry(table_base, back->comefrom); 418 back = get_entry(table_base, back->comefrom);
419 continue; 419 continue;
420 } 420 }
421 if (table_base + v != ip6t_next_entry(e) 421 if (table_base + v != ip6t_next_entry(e) &&
422 && !(e->ipv6.flags & IP6T_F_GOTO)) { 422 !(e->ipv6.flags & IP6T_F_GOTO)) {
423 /* Save old back ptr in next entry */ 423 /* Save old back ptr in next entry */
424 struct ip6t_entry *next = ip6t_next_entry(e); 424 struct ip6t_entry *next = ip6t_next_entry(e);
425 next->comefrom = (void *)back - table_base; 425 next->comefrom = (void *)back - table_base;
@@ -505,11 +505,11 @@ mark_source_chains(struct xt_table_info *newinfo,
505 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); 505 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
506 506
507 /* Unconditional return/END. */ 507 /* Unconditional return/END. */
508 if ((e->target_offset == sizeof(struct ip6t_entry) 508 if ((e->target_offset == sizeof(struct ip6t_entry) &&
509 && (strcmp(t->target.u.user.name, 509 (strcmp(t->target.u.user.name,
510 IP6T_STANDARD_TARGET) == 0) 510 IP6T_STANDARD_TARGET) == 0) &&
511 && t->verdict < 0 511 t->verdict < 0 &&
512 && unconditional(&e->ipv6)) || visited) { 512 unconditional(&e->ipv6)) || visited) {
513 unsigned int oldpos, size; 513 unsigned int oldpos, size;
514 514
515 if ((strcmp(t->target.u.user.name, 515 if ((strcmp(t->target.u.user.name,
@@ -556,8 +556,8 @@ mark_source_chains(struct xt_table_info *newinfo,
556 int newpos = t->verdict; 556 int newpos = t->verdict;
557 557
558 if (strcmp(t->target.u.user.name, 558 if (strcmp(t->target.u.user.name,
559 IP6T_STANDARD_TARGET) == 0 559 IP6T_STANDARD_TARGET) == 0 &&
560 && newpos >= 0) { 560 newpos >= 0) {
561 if (newpos > newinfo->size - 561 if (newpos > newinfo->size -
562 sizeof(struct ip6t_entry)) { 562 sizeof(struct ip6t_entry)) {
563 duprintf("mark_source_chains: " 563 duprintf("mark_source_chains: "
@@ -767,8 +767,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
767{ 767{
768 unsigned int h; 768 unsigned int h;
769 769
770 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 770 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
771 || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { 771 (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
772 duprintf("Bad offset %p\n", e); 772 duprintf("Bad offset %p\n", e);
773 return -EINVAL; 773 return -EINVAL;
774 } 774 }
@@ -1584,8 +1584,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1584 int ret, off, h; 1584 int ret, off, h;
1585 1585
1586 duprintf("check_compat_entry_size_and_hooks %p\n", e); 1586 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1587 if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 1587 if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
1588 || (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) { 1588 (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) {
1589 duprintf("Bad offset %p, limit = %p\n", e, limit); 1589 duprintf("Bad offset %p, limit = %p\n", e, limit);
1590 return -EINVAL; 1590 return -EINVAL;
1591 } 1591 }
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 7018cac4fddc..b285fdf19050 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -249,8 +249,8 @@ static void dump_packet(const struct nf_loginfo *info,
249 /* Max length: 11 "URGP=65535 " */ 249 /* Max length: 11 "URGP=65535 " */
250 printk("URGP=%u ", ntohs(th->urg_ptr)); 250 printk("URGP=%u ", ntohs(th->urg_ptr));
251 251
252 if ((logflags & IP6T_LOG_TCPOPT) 252 if ((logflags & IP6T_LOG_TCPOPT) &&
253 && th->doff * 4 > sizeof(struct tcphdr)) { 253 th->doff * 4 > sizeof(struct tcphdr)) {
254 u_int8_t _opt[60 - sizeof(struct tcphdr)]; 254 u_int8_t _opt[60 - sizeof(struct tcphdr)];
255 const u_int8_t *op; 255 const u_int8_t *op;
256 unsigned int i; 256 unsigned int i;
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 5a7f00cd15ce..8311ca31816a 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -223,8 +223,8 @@ static bool reject_tg6_check(const struct xt_tgchk_param *par)
223 return false; 223 return false;
224 } else if (rejinfo->with == IP6T_TCP_RESET) { 224 } else if (rejinfo->with == IP6T_TCP_RESET) {
225 /* Must specify that it's a TCP packet */ 225 /* Must specify that it's a TCP packet */
226 if (e->ipv6.proto != IPPROTO_TCP 226 if (e->ipv6.proto != IPPROTO_TCP ||
227 || (e->ipv6.invflags & XT_INV_PROTO)) { 227 (e->ipv6.invflags & XT_INV_PROTO)) {
228 printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); 228 printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
229 return false; 229 return false;
230 } 230 }
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 3a82f24746b9..ac0b7c629d78 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -77,17 +77,14 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
77 ahinfo->hdrres, ah->reserved, 77 ahinfo->hdrres, ah->reserved,
78 !(ahinfo->hdrres && ah->reserved)); 78 !(ahinfo->hdrres && ah->reserved));
79 79
80 return (ah != NULL) 80 return (ah != NULL) &&
81 && 81 spi_match(ahinfo->spis[0], ahinfo->spis[1],
82 spi_match(ahinfo->spis[0], ahinfo->spis[1], 82 ntohl(ah->spi),
83 ntohl(ah->spi), 83 !!(ahinfo->invflags & IP6T_AH_INV_SPI)) &&
84 !!(ahinfo->invflags & IP6T_AH_INV_SPI)) 84 (!ahinfo->hdrlen ||
85 && 85 (ahinfo->hdrlen == hdrlen) ^
86 (!ahinfo->hdrlen || 86 !!(ahinfo->invflags & IP6T_AH_INV_LEN)) &&
87 (ahinfo->hdrlen == hdrlen) ^ 87 !(ahinfo->hdrres && ah->reserved);
88 !!(ahinfo->invflags & IP6T_AH_INV_LEN))
89 &&
90 !(ahinfo->hdrres && ah->reserved);
91} 88}
92 89
93static bool ah_mt6_check(const struct xt_mtchk_param *par) 90static bool ah_mt6_check(const struct xt_mtchk_param *par)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 673aa0a5084e..7b91c2598ed5 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -70,41 +70,36 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
70 pr_debug("res %02X %02X%04X %02X ", 70 pr_debug("res %02X %02X%04X %02X ",
71 fraginfo->flags & IP6T_FRAG_RES, fh->reserved, 71 fraginfo->flags & IP6T_FRAG_RES, fh->reserved,
72 ntohs(fh->frag_off) & 0x6, 72 ntohs(fh->frag_off) & 0x6,
73 !((fraginfo->flags & IP6T_FRAG_RES) 73 !((fraginfo->flags & IP6T_FRAG_RES) &&
74 && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); 74 (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
75 pr_debug("first %02X %02X %02X ", 75 pr_debug("first %02X %02X %02X ",
76 fraginfo->flags & IP6T_FRAG_FST, 76 fraginfo->flags & IP6T_FRAG_FST,
77 ntohs(fh->frag_off) & ~0x7, 77 ntohs(fh->frag_off) & ~0x7,
78 !((fraginfo->flags & IP6T_FRAG_FST) 78 !((fraginfo->flags & IP6T_FRAG_FST) &&
79 && (ntohs(fh->frag_off) & ~0x7))); 79 (ntohs(fh->frag_off) & ~0x7)));
80 pr_debug("mf %02X %02X %02X ", 80 pr_debug("mf %02X %02X %02X ",
81 fraginfo->flags & IP6T_FRAG_MF, 81 fraginfo->flags & IP6T_FRAG_MF,
82 ntohs(fh->frag_off) & IP6_MF, 82 ntohs(fh->frag_off) & IP6_MF,
83 !((fraginfo->flags & IP6T_FRAG_MF) 83 !((fraginfo->flags & IP6T_FRAG_MF) &&
84 && !((ntohs(fh->frag_off) & IP6_MF)))); 84 !((ntohs(fh->frag_off) & IP6_MF))));
85 pr_debug("last %02X %02X %02X\n", 85 pr_debug("last %02X %02X %02X\n",
86 fraginfo->flags & IP6T_FRAG_NMF, 86 fraginfo->flags & IP6T_FRAG_NMF,
87 ntohs(fh->frag_off) & IP6_MF, 87 ntohs(fh->frag_off) & IP6_MF,
88 !((fraginfo->flags & IP6T_FRAG_NMF) 88 !((fraginfo->flags & IP6T_FRAG_NMF) &&
89 && (ntohs(fh->frag_off) & IP6_MF))); 89 (ntohs(fh->frag_off) & IP6_MF)));
90 90
91 return (fh != NULL) 91 return (fh != NULL) &&
92 && 92 id_match(fraginfo->ids[0], fraginfo->ids[1],
93 id_match(fraginfo->ids[0], fraginfo->ids[1], 93 ntohl(fh->identification),
94 ntohl(fh->identification), 94 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) &&
95 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) 95 !((fraginfo->flags & IP6T_FRAG_RES) &&
96 && 96 (fh->reserved || (ntohs(fh->frag_off) & 0x6))) &&
97 !((fraginfo->flags & IP6T_FRAG_RES) 97 !((fraginfo->flags & IP6T_FRAG_FST) &&
98 && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) 98 (ntohs(fh->frag_off) & ~0x7)) &&
99 && 99 !((fraginfo->flags & IP6T_FRAG_MF) &&
100 !((fraginfo->flags & IP6T_FRAG_FST) 100 !(ntohs(fh->frag_off) & IP6_MF)) &&
101 && (ntohs(fh->frag_off) & ~0x7)) 101 !((fraginfo->flags & IP6T_FRAG_NMF) &&
102 && 102 (ntohs(fh->frag_off) & IP6_MF));
103 !((fraginfo->flags & IP6T_FRAG_MF)
104 && !(ntohs(fh->frag_off) & IP6_MF))
105 &&
106 !((fraginfo->flags & IP6T_FRAG_NMF)
107 && (ntohs(fh->frag_off) & IP6_MF));
108} 103}
109 104
110static bool frag_mt6_check(const struct xt_mtchk_param *par) 105static bool frag_mt6_check(const struct xt_mtchk_param *par)
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 356b8d6f6baa..b77307fc8743 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -92,16 +92,13 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
92 !((rtinfo->flags & IP6T_RT_RES) && 92 !((rtinfo->flags & IP6T_RT_RES) &&
93 (((const struct rt0_hdr *)rh)->reserved))); 93 (((const struct rt0_hdr *)rh)->reserved)));
94 94
95 ret = (rh != NULL) 95 ret = (rh != NULL) &&
96 &&
97 (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], 96 (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
98 rh->segments_left, 97 rh->segments_left,
99 !!(rtinfo->invflags & IP6T_RT_INV_SGS))) 98 !!(rtinfo->invflags & IP6T_RT_INV_SGS))) &&
100 &&
101 (!(rtinfo->flags & IP6T_RT_LEN) || 99 (!(rtinfo->flags & IP6T_RT_LEN) ||
102 ((rtinfo->hdrlen == hdrlen) ^ 100 ((rtinfo->hdrlen == hdrlen) ^
103 !!(rtinfo->invflags & IP6T_RT_INV_LEN))) 101 !!(rtinfo->invflags & IP6T_RT_INV_LEN))) &&
104 &&
105 (!(rtinfo->flags & IP6T_RT_TYP) || 102 (!(rtinfo->flags & IP6T_RT_TYP) ||
106 ((rtinfo->rt_type == rh->type) ^ 103 ((rtinfo->rt_type == rh->type) ^
107 !!(rtinfo->invflags & IP6T_RT_INV_TYP))); 104 !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 6f4383ad86f9..ad378efd0eb8 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -79,8 +79,8 @@ ip6t_local_out_hook(unsigned int hook,
79{ 79{
80#if 0 80#if 0
81 /* root is playing with raw sockets. */ 81 /* root is playing with raw sockets. */
82 if (skb->len < sizeof(struct iphdr) 82 if (skb->len < sizeof(struct iphdr) ||
83 || ip_hdrlen(skb) < sizeof(struct iphdr)) { 83 ip_hdrlen(skb) < sizeof(struct iphdr)) {
84 if (net_ratelimit()) 84 if (net_ratelimit())
85 printk("ip6t_hook: happy cracking.\n"); 85 printk("ip6t_hook: happy cracking.\n");
86 return NF_ACCEPT; 86 return NF_ACCEPT;
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 0ad91433ed61..a929c19d30e3 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -102,8 +102,8 @@ ip6t_local_out_hook(unsigned int hook,
102 102
103#if 0 103#if 0
104 /* root is playing with raw sockets. */ 104 /* root is playing with raw sockets. */
105 if (skb->len < sizeof(struct iphdr) 105 if (skb->len < sizeof(struct iphdr) ||
106 || ip_hdrlen(skb) < sizeof(struct iphdr)) { 106 ip_hdrlen(skb) < sizeof(struct iphdr)) {
107 if (net_ratelimit()) 107 if (net_ratelimit())
108 printk("ip6t_hook: happy cracking.\n"); 108 printk("ip6t_hook: happy cracking.\n");
109 return NF_ACCEPT; 109 return NF_ACCEPT;
@@ -122,11 +122,11 @@ ip6t_local_out_hook(unsigned int hook,
122 ret = ip6t_do_table(skb, hook, in, out, 122 ret = ip6t_do_table(skb, hook, in, out,
123 dev_net(out)->ipv6.ip6table_mangle); 123 dev_net(out)->ipv6.ip6table_mangle);
124 124
125 if (ret != NF_DROP && ret != NF_STOLEN 125 if (ret != NF_DROP && ret != NF_STOLEN &&
126 && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) 126 (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) ||
127 || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) 127 memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) ||
128 || skb->mark != mark 128 skb->mark != mark ||
129 || ipv6_hdr(skb)->hop_limit != hop_limit)) 129 ipv6_hdr(skb)->hop_limit != hop_limit))
130 return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; 130 return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP;
131 131
132 return ret; 132 return ret;
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 642dcb127bab..0f3df45718ac 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -244,18 +244,18 @@ static const struct nla_policy icmpv6_nla_policy[CTA_PROTO_MAX+1] = {
244static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], 244static int icmpv6_nlattr_to_tuple(struct nlattr *tb[],
245 struct nf_conntrack_tuple *tuple) 245 struct nf_conntrack_tuple *tuple)
246{ 246{
247 if (!tb[CTA_PROTO_ICMPV6_TYPE] 247 if (!tb[CTA_PROTO_ICMPV6_TYPE] ||
248 || !tb[CTA_PROTO_ICMPV6_CODE] 248 !tb[CTA_PROTO_ICMPV6_CODE] ||
249 || !tb[CTA_PROTO_ICMPV6_ID]) 249 !tb[CTA_PROTO_ICMPV6_ID])
250 return -EINVAL; 250 return -EINVAL;
251 251
252 tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); 252 tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]);
253 tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); 253 tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]);
254 tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]); 254 tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]);
255 255
256 if (tuple->dst.u.icmp.type < 128 256 if (tuple->dst.u.icmp.type < 128 ||
257 || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) 257 tuple->dst.u.icmp.type - 128 >= sizeof(invmap) ||
258 || !invmap[tuple->dst.u.icmp.type - 128]) 258 !invmap[tuple->dst.u.icmp.type - 128])
259 return -EINVAL; 259 return -EINVAL;
260 260
261 return 0; 261 return 0;