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
/* Manipulations to be done on this conntrack. */
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;
/* Helper (NULL if none). */
......
......@@ -11,48 +11,42 @@
required to allow inlining of cmpfn. */
#define LIST_FIND(head, cmpfn, type, args...) \
({ \
const struct list_head *__i = (head); \
const struct list_head *__i, *__j = NULL; \
\
ASSERT_READ_LOCK(head); \
do { \
__i = __i->next; \
if (__i == (head)) { \
__i = NULL; \
list_for_each(__i, (head)) \
if (cmpfn((const type)__i , ## args)) { \
__j = __i; \
break; \
} \
} while (!cmpfn((const type)__i , ## args)); \
(type)__i; \
(type)__j; \
})
#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); \
do { \
__i = __i->next; \
if (__i == (head)) { \
__i = NULL; \
list_for_each(__i, (head)) \
if (cmpfn((type)__i , ## args)) { \
__j = __i; \
break; \
} \
} while (!cmpfn((type)__i , ## args)); \
(type)__i; \
(type)__j; \
})
/* Just like LIST_FIND but we search backwards */
#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); \
do { \
__i = __i->prev; \
if (__i == (head)) { \
__i = NULL; \
list_for_each_prev(__i, (head)) \
if (cmpfn((const type)__i , ## args)) { \
__j = __i; \
break; \
} \
} while (!cmpfn((const type)__i , ## args)); \
(type)__i; \
(type)__j; \
})
static inline int
......@@ -100,9 +94,9 @@ list_prepend(struct list_head *head, void *new)
do { \
struct list_head *__i; \
ASSERT_WRITE_LOCK(head); \
for (__i = (head)->next; \
!cmpfn((new), (typeof (new))__i) && __i != (head); \
__i = __i->next); \
list_for_each(__i, (head)) \
if ((new), (typeof (new))__i) \
break; \
list_add((struct list_head *)(new), __i->prev); \
} while(0)
......
......@@ -382,6 +382,7 @@ enum
NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
NET_IPV4_NF_CONNTRACK_BUCKETS=14,
};
/* /proc/sys/net/ipv6 */
......
......@@ -380,7 +380,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
struct ipv6_txoptions *opt,
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);
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
kfree(msf);
break;
}
if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
kfree(msf);
err = -EINVAL;
break;
}
err = ip_mc_msfilter(sk, msf, 0);
kfree(msf);
break;
......
......@@ -1324,7 +1324,7 @@ static int __init ip_auto_config(void)
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,
/* Bring out ya dead! */
static struct ip_conntrack_tuple_hash *
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;
unsigned int i;
READ_LOCK(&ip_conntrack_lock);
for (i = 0; !h && i < ip_conntrack_htable_size; i++) {
h = LIST_FIND(&ip_conntrack_hash[i], do_kill,
for (; !h && *bucket < ip_conntrack_htable_size; (*bucket)++) {
h = LIST_FIND(&ip_conntrack_hash[*bucket], do_kill,
struct ip_conntrack_tuple_hash *, kill, data);
}
if (h)
......@@ -1262,9 +1261,9 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
void *data)
{
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)) != NULL) {
while ((h = get_next_corpse(kill, data, &bucket)) != NULL) {
/* Time to push up daises... */
if (del_timer(&h->ctrack->timeout))
death_by_timeout((unsigned long)h->ctrack);
......
......@@ -275,6 +275,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = {
/* From ip_conntrack_core.c */
extern int ip_conntrack_max;
extern unsigned int ip_conntrack_htable_size;
/* From ip_conntrack_proto_tcp.c */
extern unsigned long ip_ct_tcp_timeout_syn_sent;
......@@ -299,66 +300,159 @@ extern unsigned long ip_ct_generic_timeout;
static struct ctl_table_header *ip_ct_sysctl_header;
static ctl_table ip_ct_sysctl_table[] = {
{NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
&ip_conntrack_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
&ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
&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",
&ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
&ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{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},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
&ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
&ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
&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,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
&ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
&ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
&ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
&ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{0}
{
.ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
.procname = "ip_conntrack_max",
.data = &ip_conntrack_max,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
.procname = "ip_conntrack_buckets",
.data = &ip_conntrack_htable_size,
.maxlen = sizeof(unsigned int),
.mode = 0444,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
.procname = "ip_conntrack_tcp_timeout_syn_sent",
.data = &ip_ct_tcp_timeout_syn_sent,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
.procname = "ip_conntrack_tcp_timeout_syn_recv",
.data = &ip_ct_tcp_timeout_syn_recv,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
.procname = "ip_conntrack_tcp_timeout_established",
.data = &ip_ct_tcp_timeout_established,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
},
{
.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
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",
&ip_conntrack_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{0}
{
.ctl_name = NET_IPV4_NETFILTER,
.procname = "netfilter",
.mode = 0555,
.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[] = {
{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[] = {
{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
static int init_or_cleanup(int init)
......
......@@ -694,7 +694,7 @@ int ipv6_ext_hdr(u8 nexthdr)
* --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;
......@@ -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)))
BUG();
if (nexthdr == NEXTHDR_FRAGMENT) {
struct frag_hdr *fhdr = (struct frag_hdr *) &hdr;
if (ntohs(fhdr->frag_off) & ~0x7)
unsigned short frag_off;
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;
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
......
......@@ -450,6 +450,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
kfree(gsf);
break;
}
if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
kfree(gsf);
retv = -EINVAL;
break;
}
retv = ip6_mc_msfilter(sk, gsf);
kfree(gsf);
......
......@@ -46,3 +46,4 @@ EXPORT_SYMBOL(ip6_append_data);
EXPORT_SYMBOL(ip6_flush_pending_frames);
EXPORT_SYMBOL(ip6_push_pending_frames);
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
EXPORT_SYMBOL(ipv6_skip_exthdr);
......@@ -24,6 +24,7 @@
#include <linux/udp.h>
#include <linux/icmpv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/proc_fs.h>
......@@ -1570,8 +1571,10 @@ tcp_match(const struct sk_buff *skb,
u_int16_t datalen,
int *hotdrop)
{
const struct tcphdr *tcp = hdr;
const struct tcphdr *tcp;
const struct ip6t_tcp *tcpinfo = matchinfo;
int tcpoff;
u8 nexthdr = skb->nh.ipv6h->nexthdr;
/* To quote Alan:
......@@ -1592,6 +1595,24 @@ tcp_match(const struct sk_buff *skb,
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 */
#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
......@@ -1642,8 +1663,10 @@ udp_match(const struct sk_buff *skb,
u_int16_t datalen,
int *hotdrop)
{
const struct udphdr *udp = hdr;
const struct udphdr *udp;
const struct ip6t_udp *udpinfo = matchinfo;
int udpoff;
u8 nexthdr = skb->nh.ipv6h->nexthdr;
if (offset == 0 && datalen < sizeof(struct udphdr)) {
/* We've been asked to examine this packet, and we
......@@ -1653,6 +1676,23 @@ udp_match(const struct sk_buff *skb,
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. */
return !offset
&& port_match(udpinfo->spts[0], udpinfo->spts[1],
......
......@@ -591,12 +591,12 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
if (!buff)
continue;
}
if (sock_queue_rcv_skb(sk2, buff) >= 0)
if (udpv6_queue_rcv_skb(sk2, buff) >= 0)
buff = NULL;
}
if (buff)
kfree_skb(buff);
if (sock_queue_rcv_skb(sk, skb) < 0) {
if (udpv6_queue_rcv_skb(sk, skb) < 0) {
free_skb:
kfree_skb(skb);
}
......
......@@ -207,7 +207,7 @@ static struct file_operations status_fops = {
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)
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