Commit 144abfc2 authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/network-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 95a08114 9abdae11
...@@ -100,9 +100,6 @@ struct ip_nat_info ...@@ -100,9 +100,6 @@ struct ip_nat_info
/* Manipulations to be done on this conntrack. */ /* Manipulations to be done on this conntrack. */
struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS]; struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
/* The mapping type which created us (NULL for null mapping). */
const struct ip_nat_mapping_type *mtype;
struct ip_nat_hash bysource, byipsproto; struct ip_nat_hash bysource, byipsproto;
/* Helper (NULL if none). */ /* Helper (NULL if none). */
......
...@@ -11,48 +11,42 @@ ...@@ -11,48 +11,42 @@
required to allow inlining of cmpfn. */ required to allow inlining of cmpfn. */
#define LIST_FIND(head, cmpfn, type, args...) \ #define LIST_FIND(head, cmpfn, type, args...) \
({ \ ({ \
const struct list_head *__i = (head); \ const struct list_head *__i, *__j = NULL; \
\ \
ASSERT_READ_LOCK(head); \ ASSERT_READ_LOCK(head); \
do { \ list_for_each(__i, (head)) \
__i = __i->next; \ if (cmpfn((const type)__i , ## args)) { \
if (__i == (head)) { \ __j = __i; \
__i = NULL; \
break; \ break; \
} \ } \
} while (!cmpfn((const type)__i , ## args)); \ (type)__j; \
(type)__i; \
}) })
#define LIST_FIND_W(head, cmpfn, type, args...) \ #define LIST_FIND_W(head, cmpfn, type, args...) \
({ \ ({ \
const struct list_head *__i = (head); \ const struct list_head *__i, *__j = NULL; \
\ \
ASSERT_WRITE_LOCK(head); \ ASSERT_WRITE_LOCK(head); \
do { \ list_for_each(__i, (head)) \
__i = __i->next; \ if (cmpfn((type)__i , ## args)) { \
if (__i == (head)) { \ __j = __i; \
__i = NULL; \ break; \
break; \ } \
} \ (type)__j; \
} while (!cmpfn((type)__i , ## args)); \
(type)__i; \
}) })
/* Just like LIST_FIND but we search backwards */ /* Just like LIST_FIND but we search backwards */
#define LIST_FIND_B(head, cmpfn, type, args...) \ #define LIST_FIND_B(head, cmpfn, type, args...) \
({ \ ({ \
const struct list_head *__i = (head); \ const struct list_head *__i, *__j = NULL; \
\ \
ASSERT_READ_LOCK(head); \ ASSERT_READ_LOCK(head); \
do { \ list_for_each_prev(__i, (head)) \
__i = __i->prev; \ if (cmpfn((const type)__i , ## args)) { \
if (__i == (head)) { \ __j = __i; \
__i = NULL; \
break; \ break; \
} \ } \
} while (!cmpfn((const type)__i , ## args)); \ (type)__j; \
(type)__i; \
}) })
static inline int static inline int
...@@ -100,9 +94,9 @@ list_prepend(struct list_head *head, void *new) ...@@ -100,9 +94,9 @@ list_prepend(struct list_head *head, void *new)
do { \ do { \
struct list_head *__i; \ struct list_head *__i; \
ASSERT_WRITE_LOCK(head); \ ASSERT_WRITE_LOCK(head); \
for (__i = (head)->next; \ list_for_each(__i, (head)) \
!cmpfn((new), (typeof (new))__i) && __i != (head); \ if ((new), (typeof (new))__i) \
__i = __i->next); \ break; \
list_add((struct list_head *)(new), __i->prev); \ list_add((struct list_head *)(new), __i->prev); \
} while(0) } while(0)
......
...@@ -382,6 +382,7 @@ enum ...@@ -382,6 +382,7 @@ enum
NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11, NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12, NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13, NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
NET_IPV4_NF_CONNTRACK_BUCKETS=14,
}; };
/* /proc/sys/net/ipv6 */ /* /proc/sys/net/ipv6 */
......
...@@ -380,7 +380,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb, ...@@ -380,7 +380,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
struct ipv6_txoptions *opt, struct ipv6_txoptions *opt,
u8 *proto); u8 *proto);
extern int ipv6_skip_exthdr(struct sk_buff *, int start, extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
u8 *nexthdrp, int len); u8 *nexthdrp, int len);
extern int ipv6_ext_hdr(u8 nexthdr); extern int ipv6_ext_hdr(u8 nexthdr);
......
...@@ -631,6 +631,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -631,6 +631,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
kfree(msf); kfree(msf);
break; break;
} }
if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
kfree(msf);
err = -EINVAL;
break;
}
err = ip_mc_msfilter(sk, msf, 0); err = ip_mc_msfilter(sk, msf, 0);
kfree(msf); kfree(msf);
break; break;
......
...@@ -1324,7 +1324,7 @@ static int __init ip_auto_config(void) ...@@ -1324,7 +1324,7 @@ static int __init ip_auto_config(void)
return 0; return 0;
} }
module_init(ip_auto_config); late_initcall(ip_auto_config);
/* /*
......
...@@ -1240,14 +1240,13 @@ do_kill(const struct ip_conntrack_tuple_hash *i, ...@@ -1240,14 +1240,13 @@ do_kill(const struct ip_conntrack_tuple_hash *i,
/* Bring out ya dead! */ /* Bring out ya dead! */
static struct ip_conntrack_tuple_hash * static struct ip_conntrack_tuple_hash *
get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data), get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data),
void *data) void *data, unsigned int *bucket)
{ {
struct ip_conntrack_tuple_hash *h = NULL; struct ip_conntrack_tuple_hash *h = NULL;
unsigned int i;
READ_LOCK(&ip_conntrack_lock); READ_LOCK(&ip_conntrack_lock);
for (i = 0; !h && i < ip_conntrack_htable_size; i++) { for (; !h && *bucket < ip_conntrack_htable_size; (*bucket)++) {
h = LIST_FIND(&ip_conntrack_hash[i], do_kill, h = LIST_FIND(&ip_conntrack_hash[*bucket], do_kill,
struct ip_conntrack_tuple_hash *, kill, data); struct ip_conntrack_tuple_hash *, kill, data);
} }
if (h) if (h)
...@@ -1262,9 +1261,9 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data), ...@@ -1262,9 +1261,9 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
void *data) void *data)
{ {
struct ip_conntrack_tuple_hash *h; struct ip_conntrack_tuple_hash *h;
unsigned int bucket = 0;
/* This is order n^2, by the way. */ while ((h = get_next_corpse(kill, data, &bucket)) != NULL) {
while ((h = get_next_corpse(kill, data)) != NULL) {
/* Time to push up daises... */ /* Time to push up daises... */
if (del_timer(&h->ctrack->timeout)) if (del_timer(&h->ctrack->timeout))
death_by_timeout((unsigned long)h->ctrack); death_by_timeout((unsigned long)h->ctrack);
......
...@@ -275,6 +275,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = { ...@@ -275,6 +275,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = {
/* From ip_conntrack_core.c */ /* From ip_conntrack_core.c */
extern int ip_conntrack_max; extern int ip_conntrack_max;
extern unsigned int ip_conntrack_htable_size;
/* From ip_conntrack_proto_tcp.c */ /* From ip_conntrack_proto_tcp.c */
extern unsigned long ip_ct_tcp_timeout_syn_sent; extern unsigned long ip_ct_tcp_timeout_syn_sent;
...@@ -299,66 +300,159 @@ extern unsigned long ip_ct_generic_timeout; ...@@ -299,66 +300,159 @@ extern unsigned long ip_ct_generic_timeout;
static struct ctl_table_header *ip_ct_sysctl_header; static struct ctl_table_header *ip_ct_sysctl_header;
static ctl_table ip_ct_sysctl_table[] = { static ctl_table ip_ct_sysctl_table[] = {
{NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max", {
&ip_conntrack_max, sizeof(int), 0644, NULL, .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
&proc_dointvec}, .procname = "ip_conntrack_max",
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent", .data = &ip_conntrack_max,
&ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL, .maxlen = sizeof(int),
&proc_dointvec_jiffies}, .mode = 0644,
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv", .proc_handler = &proc_dointvec,
&ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL, },
&proc_dointvec_jiffies}, {
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established", .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
&ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL, .procname = "ip_conntrack_buckets",
&proc_dointvec_jiffies}, .data = &ip_conntrack_htable_size,
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait", .maxlen = sizeof(unsigned int),
&ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL, .mode = 0444,
&proc_dointvec_jiffies}, .proc_handler = &proc_dointvec,
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait", },
&ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL, {
&proc_dointvec_jiffies}, .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack", .procname = "ip_conntrack_tcp_timeout_syn_sent",
&ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL, .data = &ip_ct_tcp_timeout_syn_sent,
&proc_dointvec_jiffies}, .maxlen = sizeof(unsigned int),
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait", .mode = 0644,
&ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL, .proc_handler = &proc_dointvec_jiffies,
&proc_dointvec_jiffies}, },
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close", {
&ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL, .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
&proc_dointvec_jiffies}, .procname = "ip_conntrack_tcp_timeout_syn_recv",
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout", .data = &ip_ct_tcp_timeout_syn_recv,
&ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL, .maxlen = sizeof(unsigned int),
&proc_dointvec_jiffies}, .mode = 0644,
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream", .proc_handler = &proc_dointvec_jiffies,
&ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL, },
&proc_dointvec_jiffies}, {
{NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout", .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
&ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL, .procname = "ip_conntrack_tcp_timeout_established",
&proc_dointvec_jiffies}, .data = &ip_ct_tcp_timeout_established,
{NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout", .maxlen = sizeof(unsigned int),
&ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL, .mode = 0644,
&proc_dointvec_jiffies}, .proc_handler = &proc_dointvec_jiffies,
{0} },
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
.procname = "ip_conntrack_tcp_timeout_fin_wait",
.data = &ip_ct_tcp_timeout_fin_wait,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
.procname = "ip_conntrack_tcp_timeout_close_wait",
.data = &ip_ct_tcp_timeout_close_wait,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
.procname = "ip_conntrack_tcp_timeout_last_ack",
.data = &ip_ct_tcp_timeout_last_ack,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
.procname = "ip_conntrack_tcp_timeout_time_wait",
.data = &ip_ct_tcp_timeout_time_wait,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
.procname = "ip_conntrack_tcp_timeout_close",
.data = &ip_ct_tcp_timeout_close,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
.procname = "ip_conntrack_udp_timeout",
.data = &ip_ct_udp_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
.procname = "ip_conntrack_udp_timeout_stream",
.data = &ip_ct_udp_timeout_stream,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
.procname = "ip_conntrack_icmp_timeout",
.data = &ip_ct_icmp_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
.procname = "ip_conntrack_generic_timeout",
.data = &ip_ct_generic_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{ .ctl_name = 0 }
}; };
#define NET_IP_CONNTRACK_MAX 2089 #define NET_IP_CONNTRACK_MAX 2089
static ctl_table ip_ct_netfilter_table[] = { static ctl_table ip_ct_netfilter_table[] = {
{NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0}, {
{NET_IP_CONNTRACK_MAX, "ip_conntrack_max", .ctl_name = NET_IPV4_NETFILTER,
&ip_conntrack_max, sizeof(int), 0644, NULL, .procname = "netfilter",
&proc_dointvec}, .mode = 0555,
{0} .child = ip_ct_sysctl_table,
},
{
.ctl_name = NET_IP_CONNTRACK_MAX,
.procname = "ip_conntrack_max",
.data = &ip_conntrack_max,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{ .ctl_name = 0 }
}; };
static ctl_table ip_ct_ipv4_table[] = { static ctl_table ip_ct_ipv4_table[] = {
{NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0}, {
{0} .ctl_name = NET_IPV4,
.procname = "ipv4",
.mode = 0555,
.child = ip_ct_netfilter_table,
},
{ .ctl_name = 0 }
}; };
static ctl_table ip_ct_net_table[] = { static ctl_table ip_ct_net_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0}, {
{0} .ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = ip_ct_ipv4_table,
},
{ .ctl_name = 0 }
}; };
#endif #endif
static int init_or_cleanup(int init) static int init_or_cleanup(int init)
......
...@@ -694,7 +694,7 @@ int ipv6_ext_hdr(u8 nexthdr) ...@@ -694,7 +694,7 @@ int ipv6_ext_hdr(u8 nexthdr)
* --ANK (980726) * --ANK (980726)
*/ */
int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len) int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
{ {
u8 nexthdr = *nexthdrp; u8 nexthdr = *nexthdrp;
...@@ -709,8 +709,16 @@ int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len) ...@@ -709,8 +709,16 @@ int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len)
if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
BUG(); BUG();
if (nexthdr == NEXTHDR_FRAGMENT) { if (nexthdr == NEXTHDR_FRAGMENT) {
struct frag_hdr *fhdr = (struct frag_hdr *) &hdr; unsigned short frag_off;
if (ntohs(fhdr->frag_off) & ~0x7) if (skb_copy_bits(skb,
start+offsetof(struct frag_hdr,
frag_off),
&frag_off,
sizeof(frag_off))) {
return -1;
}
if (ntohs(frag_off) & ~0x7)
break; break;
hdrlen = 8; hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH) } else if (nexthdr == NEXTHDR_AUTH)
......
...@@ -450,6 +450,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, ...@@ -450,6 +450,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
kfree(gsf); kfree(gsf);
break; break;
} }
if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
kfree(gsf);
retv = -EINVAL;
break;
}
retv = ip6_mc_msfilter(sk, gsf); retv = ip6_mc_msfilter(sk, gsf);
kfree(gsf); kfree(gsf);
......
...@@ -46,3 +46,4 @@ EXPORT_SYMBOL(ip6_append_data); ...@@ -46,3 +46,4 @@ EXPORT_SYMBOL(ip6_append_data);
EXPORT_SYMBOL(ip6_flush_pending_frames); EXPORT_SYMBOL(ip6_flush_pending_frames);
EXPORT_SYMBOL(ip6_push_pending_frames); EXPORT_SYMBOL(ip6_push_pending_frames);
EXPORT_SYMBOL(ipv6_push_nfrag_opts); EXPORT_SYMBOL(ipv6_push_nfrag_opts);
EXPORT_SYMBOL(ipv6_skip_exthdr);
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/udp.h> #include <linux/udp.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/ipv6.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
...@@ -1570,8 +1571,10 @@ tcp_match(const struct sk_buff *skb, ...@@ -1570,8 +1571,10 @@ tcp_match(const struct sk_buff *skb,
u_int16_t datalen, u_int16_t datalen,
int *hotdrop) int *hotdrop)
{ {
const struct tcphdr *tcp = hdr; const struct tcphdr *tcp;
const struct ip6t_tcp *tcpinfo = matchinfo; const struct ip6t_tcp *tcpinfo = matchinfo;
int tcpoff;
u8 nexthdr = skb->nh.ipv6h->nexthdr;
/* To quote Alan: /* To quote Alan:
...@@ -1592,6 +1595,24 @@ tcp_match(const struct sk_buff *skb, ...@@ -1592,6 +1595,24 @@ tcp_match(const struct sk_buff *skb,
return 0; return 0;
} }
tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
if (tcpoff < 0 || tcpoff > skb->len) {
duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
*hotdrop = 1;
return 0;
} else if (nexthdr == IPPROTO_FRAGMENT)
return 0;
else if (nexthdr != IPPROTO_TCP ||
skb->len - tcpoff < sizeof(struct tcphdr)) {
/* cannot be occured */
duprintf("tcp_match: cannot get TCP header. Dropping.\n");
*hotdrop = 1;
return 0;
}
tcp = (struct tcphdr *)(skb->data + tcpoff);
/* FIXME: Try tcp doff >> packet len against various stacks --RR */ /* FIXME: Try tcp doff >> packet len against various stacks --RR */
#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
...@@ -1642,8 +1663,10 @@ udp_match(const struct sk_buff *skb, ...@@ -1642,8 +1663,10 @@ udp_match(const struct sk_buff *skb,
u_int16_t datalen, u_int16_t datalen,
int *hotdrop) int *hotdrop)
{ {
const struct udphdr *udp = hdr; const struct udphdr *udp;
const struct ip6t_udp *udpinfo = matchinfo; const struct ip6t_udp *udpinfo = matchinfo;
int udpoff;
u8 nexthdr = skb->nh.ipv6h->nexthdr;
if (offset == 0 && datalen < sizeof(struct udphdr)) { if (offset == 0 && datalen < sizeof(struct udphdr)) {
/* We've been asked to examine this packet, and we /* We've been asked to examine this packet, and we
...@@ -1653,6 +1676,23 @@ udp_match(const struct sk_buff *skb, ...@@ -1653,6 +1676,23 @@ udp_match(const struct sk_buff *skb,
return 0; return 0;
} }
udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
if (udpoff < 0 || udpoff > skb->len) {
duprintf("udp_match: cannot skip exthdr. Dropping.\n");
*hotdrop = 1;
return 0;
} else if (nexthdr == IPPROTO_FRAGMENT)
return 0;
else if (nexthdr != IPPROTO_UDP ||
skb->len - udpoff < sizeof(struct udphdr)) {
duprintf("udp_match: cannot get UDP header. Dropping.\n");
*hotdrop = 1;
return 0;
}
udp = (struct udphdr *)(skb->data + udpoff);
/* Must not be a fragment. */ /* Must not be a fragment. */
return !offset return !offset
&& port_match(udpinfo->spts[0], udpinfo->spts[1], && port_match(udpinfo->spts[0], udpinfo->spts[1],
......
...@@ -591,12 +591,12 @@ static void udpv6_mcast_deliver(struct udphdr *uh, ...@@ -591,12 +591,12 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
if (!buff) if (!buff)
continue; continue;
} }
if (sock_queue_rcv_skb(sk2, buff) >= 0) if (udpv6_queue_rcv_skb(sk2, buff) >= 0)
buff = NULL; buff = NULL;
} }
if (buff) if (buff)
kfree_skb(buff); kfree_skb(buff);
if (sock_queue_rcv_skb(sk, skb) < 0) { if (udpv6_queue_rcv_skb(sk, skb) < 0) {
free_skb: free_skb:
kfree_skb(skb); kfree_skb(skb);
} }
......
...@@ -207,7 +207,7 @@ static struct file_operations status_fops = { ...@@ -207,7 +207,7 @@ static struct file_operations status_fops = {
static int wandev_show(struct seq_file *m, void *v) static int wandev_show(struct seq_file *m, void *v)
{ {
struct wan_device *wandev = v; struct wan_device *wandev = m->private;
if (wandev->magic != ROUTER_MAGIC) if (wandev->magic != ROUTER_MAGIC)
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment