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
This commit is contained in:
Коммит
bcbc713470
|
@ -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)
|
||||||
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 @@
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
(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)
|
||||||
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 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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[] = {
|
||||||
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);
|
||||||
|
|
||||||
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,
|
||||||
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[] = {
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче