diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-08 18:17:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-08 18:17:25 -0400 |
commit | cdbb92b31d3c465aa96bd09f2d42c39b87b32bee (patch) | |
tree | 370e29681529882d7e4c766a19f0612885583464 /net | |
parent | 2ec2b482b10a1ed3493c224f1893cddd3d33833b (diff) | |
parent | 69849375d6b13e94d08cdc94b49b11fbab454a0e (diff) |
Merge branch 'linus' into core/rcu
Diffstat (limited to 'net')
-rw-r--r-- | net/ax25/af_ax25.c | 3 | ||||
-rw-r--r-- | net/ax25/ax25_std_timer.c | 8 | ||||
-rw-r--r-- | net/core/dev.c | 43 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_hybla.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv6/route.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
-rw-r--r-- | net/iucv/iucv.c | 3 | ||||
-rw-r--r-- | net/key/af_key.c | 30 | ||||
-rw-r--r-- | net/netrom/af_netrom.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 37 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 48 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 12 |
15 files changed, 127 insertions, 76 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 01c83e2a4c19..28c71574a781 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -317,6 +317,9 @@ void ax25_destroy_socket(ax25_cb *ax25) | |||
317 | /* Queue the unaccepted socket for death */ | 317 | /* Queue the unaccepted socket for death */ |
318 | sock_orphan(skb->sk); | 318 | sock_orphan(skb->sk); |
319 | 319 | ||
320 | /* 9A4GL: hack to release unaccepted sockets */ | ||
321 | skb->sk->sk_state = TCP_LISTEN; | ||
322 | |||
320 | ax25_start_heartbeat(sax25); | 323 | ax25_start_heartbeat(sax25); |
321 | sax25->state = AX25_STATE_0; | 324 | sax25->state = AX25_STATE_0; |
322 | } | 325 | } |
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c index cdc7e751ef36..96e4b9273250 100644 --- a/net/ax25/ax25_std_timer.c +++ b/net/ax25/ax25_std_timer.c | |||
@@ -39,9 +39,11 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25) | |||
39 | 39 | ||
40 | switch (ax25->state) { | 40 | switch (ax25->state) { |
41 | case AX25_STATE_0: | 41 | case AX25_STATE_0: |
42 | if (!sk || | 42 | /* Magic here: If we listen() and a new link dies before it |
43 | sock_flag(sk, SOCK_DESTROY) || | 43 | is accepted() it isn't 'dead' so doesn't get removed. */ |
44 | sock_flag(sk, SOCK_DEAD)) { | 44 | if (!sk || sock_flag(sk, SOCK_DESTROY) || |
45 | (sk->sk_state == TCP_LISTEN && | ||
46 | sock_flag(sk, SOCK_DEAD))) { | ||
45 | if (sk) { | 47 | if (sk) { |
46 | sock_hold(sk); | 48 | sock_hold(sk); |
47 | ax25_destroy_socket(ax25); | 49 | ax25_destroy_socket(ax25); |
diff --git a/net/core/dev.c b/net/core/dev.c index e8eb2b478344..0ae08d3f57e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2918,6 +2918,12 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
2918 | return 0; | 2918 | return 0; |
2919 | } | 2919 | } |
2920 | 2920 | ||
2921 | static void dev_change_rx_flags(struct net_device *dev, int flags) | ||
2922 | { | ||
2923 | if (dev->flags & IFF_UP && dev->change_rx_flags) | ||
2924 | dev->change_rx_flags(dev, flags); | ||
2925 | } | ||
2926 | |||
2921 | static int __dev_set_promiscuity(struct net_device *dev, int inc) | 2927 | static int __dev_set_promiscuity(struct net_device *dev, int inc) |
2922 | { | 2928 | { |
2923 | unsigned short old_flags = dev->flags; | 2929 | unsigned short old_flags = dev->flags; |
@@ -2955,8 +2961,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc) | |||
2955 | current->uid, current->gid, | 2961 | current->uid, current->gid, |
2956 | audit_get_sessionid(current)); | 2962 | audit_get_sessionid(current)); |
2957 | 2963 | ||
2958 | if (dev->change_rx_flags) | 2964 | dev_change_rx_flags(dev, IFF_PROMISC); |
2959 | dev->change_rx_flags(dev, IFF_PROMISC); | ||
2960 | } | 2965 | } |
2961 | return 0; | 2966 | return 0; |
2962 | } | 2967 | } |
@@ -3022,8 +3027,7 @@ int dev_set_allmulti(struct net_device *dev, int inc) | |||
3022 | } | 3027 | } |
3023 | } | 3028 | } |
3024 | if (dev->flags ^ old_flags) { | 3029 | if (dev->flags ^ old_flags) { |
3025 | if (dev->change_rx_flags) | 3030 | dev_change_rx_flags(dev, IFF_ALLMULTI); |
3026 | dev->change_rx_flags(dev, IFF_ALLMULTI); | ||
3027 | dev_set_rx_mode(dev); | 3031 | dev_set_rx_mode(dev); |
3028 | } | 3032 | } |
3029 | return 0; | 3033 | return 0; |
@@ -3347,8 +3351,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
3347 | * Load in the correct multicast list now the flags have changed. | 3351 | * Load in the correct multicast list now the flags have changed. |
3348 | */ | 3352 | */ |
3349 | 3353 | ||
3350 | if (dev->change_rx_flags && (old_flags ^ flags) & IFF_MULTICAST) | 3354 | if ((old_flags ^ flags) & IFF_MULTICAST) |
3351 | dev->change_rx_flags(dev, IFF_MULTICAST); | 3355 | dev_change_rx_flags(dev, IFF_MULTICAST); |
3352 | 3356 | ||
3353 | dev_set_rx_mode(dev); | 3357 | dev_set_rx_mode(dev); |
3354 | 3358 | ||
@@ -3808,14 +3812,11 @@ static int dev_new_index(struct net *net) | |||
3808 | } | 3812 | } |
3809 | 3813 | ||
3810 | /* Delayed registration/unregisteration */ | 3814 | /* Delayed registration/unregisteration */ |
3811 | static DEFINE_SPINLOCK(net_todo_list_lock); | ||
3812 | static LIST_HEAD(net_todo_list); | 3815 | static LIST_HEAD(net_todo_list); |
3813 | 3816 | ||
3814 | static void net_set_todo(struct net_device *dev) | 3817 | static void net_set_todo(struct net_device *dev) |
3815 | { | 3818 | { |
3816 | spin_lock(&net_todo_list_lock); | ||
3817 | list_add_tail(&dev->todo_list, &net_todo_list); | 3819 | list_add_tail(&dev->todo_list, &net_todo_list); |
3818 | spin_unlock(&net_todo_list_lock); | ||
3819 | } | 3820 | } |
3820 | 3821 | ||
3821 | static void rollback_registered(struct net_device *dev) | 3822 | static void rollback_registered(struct net_device *dev) |
@@ -4142,33 +4143,24 @@ static void netdev_wait_allrefs(struct net_device *dev) | |||
4142 | * free_netdev(y1); | 4143 | * free_netdev(y1); |
4143 | * free_netdev(y2); | 4144 | * free_netdev(y2); |
4144 | * | 4145 | * |
4145 | * We are invoked by rtnl_unlock() after it drops the semaphore. | 4146 | * We are invoked by rtnl_unlock(). |
4146 | * This allows us to deal with problems: | 4147 | * This allows us to deal with problems: |
4147 | * 1) We can delete sysfs objects which invoke hotplug | 4148 | * 1) We can delete sysfs objects which invoke hotplug |
4148 | * without deadlocking with linkwatch via keventd. | 4149 | * without deadlocking with linkwatch via keventd. |
4149 | * 2) Since we run with the RTNL semaphore not held, we can sleep | 4150 | * 2) Since we run with the RTNL semaphore not held, we can sleep |
4150 | * safely in order to wait for the netdev refcnt to drop to zero. | 4151 | * safely in order to wait for the netdev refcnt to drop to zero. |
4152 | * | ||
4153 | * We must not return until all unregister events added during | ||
4154 | * the interval the lock was held have been completed. | ||
4151 | */ | 4155 | */ |
4152 | static DEFINE_MUTEX(net_todo_run_mutex); | ||
4153 | void netdev_run_todo(void) | 4156 | void netdev_run_todo(void) |
4154 | { | 4157 | { |
4155 | struct list_head list; | 4158 | struct list_head list; |
4156 | 4159 | ||
4157 | /* Need to guard against multiple cpu's getting out of order. */ | ||
4158 | mutex_lock(&net_todo_run_mutex); | ||
4159 | |||
4160 | /* Not safe to do outside the semaphore. We must not return | ||
4161 | * until all unregister events invoked by the local processor | ||
4162 | * have been completed (either by this todo run, or one on | ||
4163 | * another cpu). | ||
4164 | */ | ||
4165 | if (list_empty(&net_todo_list)) | ||
4166 | goto out; | ||
4167 | |||
4168 | /* Snapshot list, allow later requests */ | 4160 | /* Snapshot list, allow later requests */ |
4169 | spin_lock(&net_todo_list_lock); | ||
4170 | list_replace_init(&net_todo_list, &list); | 4161 | list_replace_init(&net_todo_list, &list); |
4171 | spin_unlock(&net_todo_list_lock); | 4162 | |
4163 | __rtnl_unlock(); | ||
4172 | 4164 | ||
4173 | while (!list_empty(&list)) { | 4165 | while (!list_empty(&list)) { |
4174 | struct net_device *dev | 4166 | struct net_device *dev |
@@ -4200,9 +4192,6 @@ void netdev_run_todo(void) | |||
4200 | /* Free network device */ | 4192 | /* Free network device */ |
4201 | kobject_put(&dev->dev.kobj); | 4193 | kobject_put(&dev->dev.kobj); |
4202 | } | 4194 | } |
4203 | |||
4204 | out: | ||
4205 | mutex_unlock(&net_todo_run_mutex); | ||
4206 | } | 4195 | } |
4207 | 4196 | ||
4208 | static struct net_device_stats *internal_stats(struct net_device *dev) | 4197 | static struct net_device_stats *internal_stats(struct net_device *dev) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 71edb8b36341..d6381c2a4693 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -73,7 +73,7 @@ void __rtnl_unlock(void) | |||
73 | 73 | ||
74 | void rtnl_unlock(void) | 74 | void rtnl_unlock(void) |
75 | { | 75 | { |
76 | mutex_unlock(&rtnl_mutex); | 76 | /* This fellow will unlock it for us. */ |
77 | netdev_run_todo(); | 77 | netdev_run_todo(); |
78 | } | 78 | } |
79 | 79 | ||
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c index bfcbd148a89d..c209e054a634 100644 --- a/net/ipv4/tcp_hybla.c +++ b/net/ipv4/tcp_hybla.c | |||
@@ -150,7 +150,11 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | |||
150 | ca->snd_cwnd_cents -= 128; | 150 | ca->snd_cwnd_cents -= 128; |
151 | tp->snd_cwnd_cnt = 0; | 151 | tp->snd_cwnd_cnt = 0; |
152 | } | 152 | } |
153 | 153 | /* check when cwnd has not been incremented for a while */ | |
154 | if (increment == 0 && odd == 0 && tp->snd_cwnd_cnt >= tp->snd_cwnd) { | ||
155 | tp->snd_cwnd++; | ||
156 | tp->snd_cwnd_cnt = 0; | ||
157 | } | ||
154 | /* clamp down slowstart cwnd to ssthresh value. */ | 158 | /* clamp down slowstart cwnd to ssthresh value. */ |
155 | if (is_slowstart) | 159 | if (is_slowstart) |
156 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); | 160 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 67ccce2a96bd..7abc6b80d47d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4879,7 +4879,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
4879 | goto no_ack; | 4879 | goto no_ack; |
4880 | } | 4880 | } |
4881 | 4881 | ||
4882 | __tcp_ack_snd_check(sk, 0); | 4882 | if (!copied_early || tp->rcv_nxt != tp->rcv_wup) |
4883 | __tcp_ack_snd_check(sk, 0); | ||
4883 | no_ack: | 4884 | no_ack: |
4884 | #ifdef CONFIG_NET_DMA | 4885 | #ifdef CONFIG_NET_DMA |
4885 | if (copied_early) | 4886 | if (copied_early) |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1b4fee20fc93..011478e46c40 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -618,7 +618,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
618 | ]; | 618 | ]; |
619 | } rep; | 619 | } rep; |
620 | struct ip_reply_arg arg; | 620 | struct ip_reply_arg arg; |
621 | struct net *net = dev_net(skb->dev); | 621 | struct net *net = dev_net(skb->dst->dev); |
622 | 622 | ||
623 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 623 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
624 | memset(&arg, 0, sizeof(arg)); | 624 | memset(&arg, 0, sizeof(arg)); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9af6115f0f50..63442a1e741c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2688,6 +2688,8 @@ int __init ip6_route_init(void) | |||
2688 | if (ret) | 2688 | if (ret) |
2689 | goto out_kmem_cache; | 2689 | goto out_kmem_cache; |
2690 | 2690 | ||
2691 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | ||
2692 | |||
2691 | /* Registering of the loopback is done before this portion of code, | 2693 | /* Registering of the loopback is done before this portion of code, |
2692 | * the loopback reference in rt6_info will not be taken, do it | 2694 | * the loopback reference in rt6_info will not be taken, do it |
2693 | * manually for init_net */ | 2695 | * manually for init_net */ |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b585c850a89a..10e22fd48222 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1050 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1050 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1051 | struct sk_buff *buff; | 1051 | struct sk_buff *buff; |
1052 | struct flowi fl; | 1052 | struct flowi fl; |
1053 | struct net *net = dev_net(skb->dev); | 1053 | struct net *net = dev_net(skb->dst->dev); |
1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1055 | unsigned int tot_len = sizeof(struct tcphdr); | 1055 | unsigned int tot_len = sizeof(struct tcphdr); |
1056 | __be32 *topt; | 1056 | __be32 *topt; |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 705959b31e24..d7b54b5bfa69 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -524,7 +524,6 @@ static int iucv_enable(void) | |||
524 | get_online_cpus(); | 524 | get_online_cpus(); |
525 | for_each_online_cpu(cpu) | 525 | for_each_online_cpu(cpu) |
526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | 526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
527 | preempt_enable(); | ||
528 | if (cpus_empty(iucv_buffer_cpumask)) | 527 | if (cpus_empty(iucv_buffer_cpumask)) |
529 | /* No cpu could declare an iucv buffer. */ | 528 | /* No cpu could declare an iucv buffer. */ |
530 | goto out_path; | 529 | goto out_path; |
@@ -547,7 +546,9 @@ out: | |||
547 | */ | 546 | */ |
548 | static void iucv_disable(void) | 547 | static void iucv_disable(void) |
549 | { | 548 | { |
549 | get_online_cpus(); | ||
550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); | 550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); |
551 | put_online_cpus(); | ||
551 | kfree(iucv_path_table); | 552 | kfree(iucv_path_table); |
552 | } | 553 | } |
553 | 554 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index d628df97e02e..b7f5a1c353ee 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk) | |||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static int pfkey_do_dump(struct pfkey_sock *pfk) | 76 | static void pfkey_terminate_dump(struct pfkey_sock *pfk) |
77 | { | 77 | { |
78 | int rc; | 78 | if (pfk->dump.dump) { |
79 | 79 | pfk->dump.done(pfk); | |
80 | rc = pfk->dump.dump(pfk); | 80 | pfk->dump.dump = NULL; |
81 | if (rc == -ENOBUFS) | 81 | pfk->dump.done = NULL; |
82 | return 0; | 82 | } |
83 | |||
84 | pfk->dump.done(pfk); | ||
85 | pfk->dump.dump = NULL; | ||
86 | pfk->dump.done = NULL; | ||
87 | return rc; | ||
88 | } | 83 | } |
89 | 84 | ||
90 | static void pfkey_sock_destruct(struct sock *sk) | 85 | static void pfkey_sock_destruct(struct sock *sk) |
91 | { | 86 | { |
87 | pfkey_terminate_dump(pfkey_sk(sk)); | ||
92 | skb_queue_purge(&sk->sk_receive_queue); | 88 | skb_queue_purge(&sk->sk_receive_queue); |
93 | 89 | ||
94 | if (!sock_flag(sk, SOCK_DEAD)) { | 90 | if (!sock_flag(sk, SOCK_DEAD)) { |
@@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, | |||
310 | return err; | 306 | return err; |
311 | } | 307 | } |
312 | 308 | ||
309 | static int pfkey_do_dump(struct pfkey_sock *pfk) | ||
310 | { | ||
311 | int rc; | ||
312 | |||
313 | rc = pfk->dump.dump(pfk); | ||
314 | if (rc == -ENOBUFS) | ||
315 | return 0; | ||
316 | |||
317 | pfkey_terminate_dump(pfk); | ||
318 | return rc; | ||
319 | } | ||
320 | |||
313 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) | 321 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) |
314 | { | 322 | { |
315 | *new = *orig; | 323 | *new = *orig; |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 532e4faa29f7..9f1ea4a27b35 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -525,6 +525,7 @@ static int nr_release(struct socket *sock) | |||
525 | if (sk == NULL) return 0; | 525 | if (sk == NULL) return 0; |
526 | 526 | ||
527 | sock_hold(sk); | 527 | sock_hold(sk); |
528 | sock_orphan(sk); | ||
528 | lock_sock(sk); | 529 | lock_sock(sk); |
529 | nr = nr_sk(sk); | 530 | nr = nr_sk(sk); |
530 | 531 | ||
@@ -548,7 +549,6 @@ static int nr_release(struct socket *sock) | |||
548 | sk->sk_state = TCP_CLOSE; | 549 | sk->sk_state = TCP_CLOSE; |
549 | sk->sk_shutdown |= SEND_SHUTDOWN; | 550 | sk->sk_shutdown |= SEND_SHUTDOWN; |
550 | sk->sk_state_change(sk); | 551 | sk->sk_state_change(sk); |
551 | sock_orphan(sk); | ||
552 | sock_set_flag(sk, SOCK_DESTROY); | 552 | sock_set_flag(sk, SOCK_DESTROY); |
553 | break; | 553 | break; |
554 | 554 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b599cbba4fbe..d68869f966c3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1012,6 +1012,29 @@ end: | |||
1012 | return retval; | 1012 | return retval; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
1016 | const struct sctp_association *asoc, | ||
1017 | const struct sctp_chunk *chunk, | ||
1018 | struct sctp_paramhdr *param) | ||
1019 | { | ||
1020 | struct sctp_chunk *retval; | ||
1021 | static const char error[] = "The following parameter had invalid length:"; | ||
1022 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
1023 | sizeof(sctp_paramhdr_t); | ||
1024 | |||
1025 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
1026 | if (!retval) | ||
1027 | goto nodata; | ||
1028 | |||
1029 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
1030 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1031 | sctp_addto_chunk(retval, sizeof(error), error); | ||
1032 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
1033 | |||
1034 | nodata: | ||
1035 | return retval; | ||
1036 | } | ||
1037 | |||
1015 | /* Make a HEARTBEAT chunk. */ | 1038 | /* Make a HEARTBEAT chunk. */ |
1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1039 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1017 | const struct sctp_transport *transport, | 1040 | const struct sctp_transport *transport, |
@@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1782 | const struct sctp_chunk *chunk, | 1805 | const struct sctp_chunk *chunk, |
1783 | struct sctp_chunk **errp) | 1806 | struct sctp_chunk **errp) |
1784 | { | 1807 | { |
1785 | static const char error[] = "The following parameter had invalid length:"; | ||
1786 | size_t payload_len = WORD_ROUND(sizeof(error)) + | ||
1787 | sizeof(sctp_paramhdr_t); | ||
1788 | |||
1789 | |||
1790 | /* This is a fatal error. Any accumulated non-fatal errors are | 1808 | /* This is a fatal error. Any accumulated non-fatal errors are |
1791 | * not reported. | 1809 | * not reported. |
1792 | */ | 1810 | */ |
@@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1794 | sctp_chunk_free(*errp); | 1812 | sctp_chunk_free(*errp); |
1795 | 1813 | ||
1796 | /* Create an error chunk and fill it in with our payload. */ | 1814 | /* Create an error chunk and fill it in with our payload. */ |
1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1815 | *errp = sctp_make_violation_paramlen(asoc, chunk, param); |
1798 | |||
1799 | if (*errp) { | ||
1800 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | ||
1801 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1802 | sctp_addto_chunk(*errp, sizeof(error), error); | ||
1803 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
1804 | } | ||
1805 | 1816 | ||
1806 | return 0; | 1817 | return 0; |
1807 | } | 1818 | } |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..7c622af2ce55 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
119 | const struct sctp_endpoint *ep, | 119 | const struct sctp_endpoint *ep, |
120 | const struct sctp_association *asoc, | 120 | const struct sctp_association *asoc, |
121 | const sctp_subtype_t type, | 121 | const sctp_subtype_t type, |
122 | void *arg, | 122 | void *arg, void *ext, |
123 | sctp_cmd_seq_t *commands); | 123 | sctp_cmd_seq_t *commands); |
124 | 124 | ||
125 | static sctp_disposition_t sctp_sf_violation_ctsn( | 125 | static sctp_disposition_t sctp_sf_violation_ctsn( |
@@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3425 | addr_param = (union sctp_addr_param *)hdr->params; | 3425 | addr_param = (union sctp_addr_param *)hdr->params; |
3426 | length = ntohs(addr_param->p.length); | 3426 | length = ntohs(addr_param->p.length); |
3427 | if (length < sizeof(sctp_paramhdr_t)) | 3427 | if (length < sizeof(sctp_paramhdr_t)) |
3428 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3428 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3429 | (void *)addr_param, commands); | 3429 | (void *)addr_param, commands); |
3430 | 3430 | ||
3431 | /* Verify the ASCONF chunk before processing it. */ | 3431 | /* Verify the ASCONF chunk before processing it. */ |
@@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3433 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3433 | (sctp_paramhdr_t *)((void *)addr_param + length), |
3434 | (void *)chunk->chunk_end, | 3434 | (void *)chunk->chunk_end, |
3435 | &err_param)) | 3435 | &err_param)) |
3436 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3436 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3437 | (void *)&err_param, commands); | 3437 | (void *)err_param, commands); |
3438 | 3438 | ||
3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
3440 | * the endpoint stored in a new association variable | 3440 | * the endpoint stored in a new association variable |
@@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3542 | (sctp_paramhdr_t *)addip_hdr->params, | 3542 | (sctp_paramhdr_t *)addip_hdr->params, |
3543 | (void *)asconf_ack->chunk_end, | 3543 | (void *)asconf_ack->chunk_end, |
3544 | &err_param)) | 3544 | &err_param)) |
3545 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3545 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3546 | (void *)&err_param, commands); | 3546 | (void *)err_param, commands); |
3547 | 3547 | ||
3548 | if (last_asconf) { | 3548 | if (last_asconf) { |
3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; | 3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; |
@@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
4240 | const struct sctp_endpoint *ep, | 4240 | const struct sctp_endpoint *ep, |
4241 | const struct sctp_association *asoc, | 4241 | const struct sctp_association *asoc, |
4242 | const sctp_subtype_t type, | 4242 | const sctp_subtype_t type, |
4243 | void *arg, | 4243 | void *arg, void *ext, |
4244 | sctp_cmd_seq_t *commands) { | 4244 | sctp_cmd_seq_t *commands) |
4245 | static const char err_str[] = "The following parameter had invalid length:"; | 4245 | { |
4246 | struct sctp_chunk *chunk = arg; | ||
4247 | struct sctp_paramhdr *param = ext; | ||
4248 | struct sctp_chunk *abort = NULL; | ||
4246 | 4249 | ||
4247 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4250 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
4248 | sizeof(err_str)); | 4251 | goto discard; |
4252 | |||
4253 | /* Make the abort chunk. */ | ||
4254 | abort = sctp_make_violation_paramlen(asoc, chunk, param); | ||
4255 | if (!abort) | ||
4256 | goto nomem; | ||
4257 | |||
4258 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4259 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | ||
4260 | |||
4261 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4262 | SCTP_ERROR(ECONNABORTED)); | ||
4263 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
4264 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | ||
4265 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
4266 | |||
4267 | discard: | ||
4268 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4269 | |||
4270 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
4271 | |||
4272 | return SCTP_DISPOSITION_ABORT; | ||
4273 | nomem: | ||
4274 | return SCTP_DISPOSITION_NOMEM; | ||
4249 | } | 4275 | } |
4250 | 4276 | ||
4251 | /* Handle a protocol violation when the peer trying to advance the | 4277 | /* Handle a protocol violation when the peer trying to advance the |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e982..dc50f1e71f76 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) | |||
27 | - skb_headroom(skb); | 27 | - skb_headroom(skb); |
28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); | 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); |
29 | 29 | ||
30 | if (nhead > 0 || ntail > 0) | 30 | if (nhead <= 0) { |
31 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | 31 | if (ntail <= 0) |
32 | 32 | return 0; | |
33 | return 0; | 33 | nhead = 0; |
34 | } else if (ntail < 0) | ||
35 | ntail = 0; | ||
36 | |||
37 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | ||
34 | } | 38 | } |
35 | 39 | ||
36 | static int xfrm_output_one(struct sk_buff *skb, int err) | 40 | static int xfrm_output_one(struct sk_buff *skb, int err) |