Commit bcbc7134 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  bridge: don't allow setting hello time to zero
  netns : fix kernel panic in timewait socket destruction
  pkt_sched: Fix qdisc state in net_tx_action()
  netfilter: nf_conntrack_irc: make sure string is terminated before calling simple_strtoul
  netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet
  netfilter: nf_conntrack_gre: more locking around keymap list
  netfilter: nf_conntrack_sip: de-static helper pointers
parents b364e2f5 8d4698f7
...@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw, ...@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
struct inet_timewait_death_row *twdr); struct inet_timewait_death_row *twdr);
extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
struct inet_timewait_death_row *twdr, int family);
static inline static inline
struct net *twsk_net(const struct inet_timewait_sock *twsk) struct net *twsk_net(const struct inet_timewait_sock *twsk)
{ {
......
...@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return 0; return 0;
case BRCTL_SET_BRIDGE_HELLO_TIME: case BRCTL_SET_BRIDGE_HELLO_TIME:
{
unsigned long t = clock_t_to_jiffies(args[1]);
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (t < HZ)
return -EINVAL;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br->bridge_hello_time = clock_t_to_jiffies(args[1]); br->bridge_hello_time = t;
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
br->hello_time = br->bridge_hello_time; br->hello_time = br->bridge_hello_time;
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
return 0; return 0;
}
case BRCTL_SET_BRIDGE_MAX_AGE: case BRCTL_SET_BRIDGE_MAX_AGE:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
......
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
*/ */
static ssize_t store_bridge_parm(struct device *d, static ssize_t store_bridge_parm(struct device *d,
const char *buf, size_t len, const char *buf, size_t len,
void (*set)(struct net_bridge *, unsigned long)) int (*set)(struct net_bridge *, unsigned long))
{ {
struct net_bridge *br = to_bridge(d); struct net_bridge *br = to_bridge(d);
char *endp; char *endp;
unsigned long val; unsigned long val;
int err;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d, ...@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d,
return -EINVAL; return -EINVAL;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
(*set)(br, val); err = (*set)(br, val);
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
return len; return err ? err : len;
} }
...@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d, ...@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d,
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
} }
static void set_forward_delay(struct net_bridge *br, unsigned long val) static int set_forward_delay(struct net_bridge *br, unsigned long val)
{ {
unsigned long delay = clock_t_to_jiffies(val); unsigned long delay = clock_t_to_jiffies(val);
br->forward_delay = delay; br->forward_delay = delay;
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
br->bridge_forward_delay = delay; br->bridge_forward_delay = delay;
return 0;
} }
static ssize_t store_forward_delay(struct device *d, static ssize_t store_forward_delay(struct device *d,
...@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, ...@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
jiffies_to_clock_t(to_bridge(d)->hello_time)); jiffies_to_clock_t(to_bridge(d)->hello_time));
} }
static void set_hello_time(struct net_bridge *br, unsigned long val) static int set_hello_time(struct net_bridge *br, unsigned long val)
{ {
unsigned long t = clock_t_to_jiffies(val); unsigned long t = clock_t_to_jiffies(val);
if (t < HZ)
return -EINVAL;
br->hello_time = t; br->hello_time = t;
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
br->bridge_hello_time = t; br->bridge_hello_time = t;
return 0;
} }
static ssize_t store_hello_time(struct device *d, static ssize_t store_hello_time(struct device *d,
...@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr, ...@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
jiffies_to_clock_t(to_bridge(d)->max_age)); jiffies_to_clock_t(to_bridge(d)->max_age));
} }
static void set_max_age(struct net_bridge *br, unsigned long val) static int set_max_age(struct net_bridge *br, unsigned long val)
{ {
unsigned long t = clock_t_to_jiffies(val); unsigned long t = clock_t_to_jiffies(val);
br->max_age = t; br->max_age = t;
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
br->bridge_max_age = t; br->bridge_max_age = t;
return 0;
} }
static ssize_t store_max_age(struct device *d, struct device_attribute *attr, static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
...@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d, ...@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d,
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
} }
static void set_ageing_time(struct net_bridge *br, unsigned long val) static int set_ageing_time(struct net_bridge *br, unsigned long val)
{ {
br->ageing_time = clock_t_to_jiffies(val); br->ageing_time = clock_t_to_jiffies(val);
return 0;
} }
static ssize_t store_ageing_time(struct device *d, static ssize_t store_ageing_time(struct device *d,
...@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr, ...@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr,
(br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
} }
static void set_priority(struct net_bridge *br, unsigned long val) static int set_priority(struct net_bridge *br, unsigned long val)
{ {
br_stp_set_bridge_priority(br, (u16) val); br_stp_set_bridge_priority(br, (u16) val);
return 0;
} }
static ssize_t store_priority(struct device *d, struct device_attribute *attr, static ssize_t store_priority(struct device *d, struct device_attribute *attr,
......
...@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h) ...@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h)
spin_unlock(root_lock); spin_unlock(root_lock);
} else { } else {
if (!test_bit(__QDISC_STATE_DEACTIVATED, if (!test_bit(__QDISC_STATE_DEACTIVATED,
&q->state)) &q->state)) {
__netif_reschedule(q); __netif_reschedule(q);
} else {
smp_mb__before_clear_bit();
clear_bit(__QDISC_STATE_SCHED,
&q->state);
}
} }
} }
} }
......
...@@ -409,3 +409,38 @@ void inet_twdr_twcal_tick(unsigned long data) ...@@ -409,3 +409,38 @@ void inet_twdr_twcal_tick(unsigned long data)
} }
EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
struct inet_timewait_death_row *twdr, int family)
{
struct inet_timewait_sock *tw;
struct sock *sk;
struct hlist_node *node;
int h;
local_bh_disable();
for (h = 0; h < (hashinfo->ehash_size); h++) {
struct inet_ehash_bucket *head =
inet_ehash_bucket(hashinfo, h);
rwlock_t *lock = inet_ehash_lockp(hashinfo, h);
restart:
write_lock(lock);
sk_for_each(sk, node, &head->twchain) {
tw = inet_twsk(sk);
if (!net_eq(twsk_net(tw), net) ||
tw->tw_family != family)
continue;
atomic_inc(&tw->tw_refcnt);
write_unlock(lock);
inet_twsk_deschedule(tw, twdr);
inet_twsk_put(tw);
goto restart;
}
write_unlock(lock);
}
local_bh_enable();
}
EXPORT_SYMBOL_GPL(inet_twsk_purge);
...@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net) ...@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net)
static void __net_exit tcp_sk_exit(struct net *net) static void __net_exit tcp_sk_exit(struct net *net)
{ {
inet_ctl_sock_destroy(net->ipv4.tcp_sock); inet_ctl_sock_destroy(net->ipv4.tcp_sock);
inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
} }
static struct pernet_operations __net_initdata tcp_sk_ops = { static struct pernet_operations __net_initdata tcp_sk_ops = {
......
...@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net) ...@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net)
static void tcpv6_net_exit(struct net *net) static void tcpv6_net_exit(struct net *net)
{ {
inet_ctl_sock_destroy(net->ipv6.tcp_sk); inet_ctl_sock_destroy(net->ipv6.tcp_sk);
inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
} }
static struct pernet_operations tcpv6_net_ops = { static struct pernet_operations tcpv6_net_ops = {
......
...@@ -68,11 +68,21 @@ static const char *const dccprotos[] = { ...@@ -68,11 +68,21 @@ static const char *const dccprotos[] = {
static int parse_dcc(char *data, const char *data_end, u_int32_t *ip, static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
u_int16_t *port, char **ad_beg_p, char **ad_end_p) u_int16_t *port, char **ad_beg_p, char **ad_end_p)
{ {
char *tmp;
/* at least 12: "AAAAAAAA P\1\n" */ /* at least 12: "AAAAAAAA P\1\n" */
while (*data++ != ' ') while (*data++ != ' ')
if (data > data_end - 12) if (data > data_end - 12)
return -1; return -1;
/* Make sure we have a newline character within the packet boundaries
* because simple_strtoul parses until the first invalid character. */
for (tmp = data; tmp <= data_end; tmp++)
if (*tmp == '\n')
break;
if (tmp > data_end || *tmp != '\n')
return -1;
*ad_beg_p = data; *ad_beg_p = data;
*ip = simple_strtoul(data, &data, 10); *ip = simple_strtoul(data, &data, 10);
......
...@@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list); ...@@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list);
void nf_ct_gre_keymap_flush(void) void nf_ct_gre_keymap_flush(void)
{ {
struct list_head *pos, *n; struct nf_ct_gre_keymap *km, *tmp;
write_lock_bh(&nf_ct_gre_lock); write_lock_bh(&nf_ct_gre_lock);
list_for_each_safe(pos, n, &gre_keymap_list) { list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) {
list_del(pos); list_del(&km->list);
kfree(pos); kfree(km);
} }
write_unlock_bh(&nf_ct_gre_lock); write_unlock_bh(&nf_ct_gre_lock);
} }
...@@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, ...@@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
kmp = &help->help.ct_pptp_info.keymap[dir]; kmp = &help->help.ct_pptp_info.keymap[dir];
if (*kmp) { if (*kmp) {
/* check whether it's a retransmission */ /* check whether it's a retransmission */
read_lock_bh(&nf_ct_gre_lock);
list_for_each_entry(km, &gre_keymap_list, list) { list_for_each_entry(km, &gre_keymap_list, list) {
if (gre_key_cmpfn(km, t) && km == *kmp) if (gre_key_cmpfn(km, t) && km == *kmp) {
read_unlock_bh(&nf_ct_gre_lock);
return 0; return 0;
}
} }
read_unlock_bh(&nf_ct_gre_lock);
pr_debug("trying to override keymap_%s for ct %p\n", pr_debug("trying to override keymap_%s for ct %p\n",
dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
return -EEXIST; return -EEXIST;
......
...@@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = { ...@@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = {
static int process_sip_response(struct sk_buff *skb, static int process_sip_response(struct sk_buff *skb,
const char **dptr, unsigned int *datalen) const char **dptr, unsigned int *datalen)
{ {
static const struct sip_handler *handler;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
unsigned int matchoff, matchlen; unsigned int matchoff, matchlen;
...@@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb, ...@@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb,
dataoff = matchoff + matchlen + 1; dataoff = matchoff + matchlen + 1;
for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
const struct sip_handler *handler;
handler = &sip_handlers[i]; handler = &sip_handlers[i];
if (handler->response == NULL) if (handler->response == NULL)
continue; continue;
...@@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb, ...@@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb,
static int process_sip_request(struct sk_buff *skb, static int process_sip_request(struct sk_buff *skb,
const char **dptr, unsigned int *datalen) const char **dptr, unsigned int *datalen)
{ {
static const struct sip_handler *handler;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
unsigned int matchoff, matchlen; unsigned int matchoff, matchlen;
unsigned int cseq, i; unsigned int cseq, i;
for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
const struct sip_handler *handler;
handler = &sip_handlers[i]; handler = &sip_handlers[i];
if (handler->request == NULL) if (handler->request == NULL)
continue; continue;
......
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