diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/bind_addr.c | 4 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 4 | ||||
-rw-r--r-- | net/sctp/protocol.c | 4 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 8 | ||||
-rw-r--r-- | net/sctp/socket.c | 73 |
5 files changed, 77 insertions, 16 deletions
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index a27511ebc4cb..ceefda025e2d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -209,6 +209,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, | |||
209 | int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) | 209 | int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) |
210 | { | 210 | { |
211 | struct sctp_sockaddr_entry *addr, *temp; | 211 | struct sctp_sockaddr_entry *addr, *temp; |
212 | int found = 0; | ||
212 | 213 | ||
213 | /* We hold the socket lock when calling this function, | 214 | /* We hold the socket lock when calling this function, |
214 | * and that acts as a writer synchronizing lock. | 215 | * and that acts as a writer synchronizing lock. |
@@ -216,13 +217,14 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) | |||
216 | list_for_each_entry_safe(addr, temp, &bp->address_list, list) { | 217 | list_for_each_entry_safe(addr, temp, &bp->address_list, list) { |
217 | if (sctp_cmp_addr_exact(&addr->a, del_addr)) { | 218 | if (sctp_cmp_addr_exact(&addr->a, del_addr)) { |
218 | /* Found the exact match. */ | 219 | /* Found the exact match. */ |
220 | found = 1; | ||
219 | addr->valid = 0; | 221 | addr->valid = 0; |
220 | list_del_rcu(&addr->list); | 222 | list_del_rcu(&addr->list); |
221 | break; | 223 | break; |
222 | } | 224 | } |
223 | } | 225 | } |
224 | 226 | ||
225 | if (addr && !addr->valid) { | 227 | if (found) { |
226 | call_rcu(&addr->rcu, sctp_local_addr_free); | 228 | call_rcu(&addr->rcu, sctp_local_addr_free); |
227 | SCTP_DBG_OBJCNT_DEC(addr); | 229 | SCTP_DBG_OBJCNT_DEC(addr); |
228 | return 0; | 230 | return 0; |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 87f940587d5f..9aa0733aee87 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -89,6 +89,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
89 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; | 89 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; |
90 | struct sctp_sockaddr_entry *addr = NULL; | 90 | struct sctp_sockaddr_entry *addr = NULL; |
91 | struct sctp_sockaddr_entry *temp; | 91 | struct sctp_sockaddr_entry *temp; |
92 | int found = 0; | ||
92 | 93 | ||
93 | switch (ev) { | 94 | switch (ev) { |
94 | case NETDEV_UP: | 95 | case NETDEV_UP: |
@@ -111,13 +112,14 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
111 | &sctp_local_addr_list, list) { | 112 | &sctp_local_addr_list, list) { |
112 | if (ipv6_addr_equal(&addr->a.v6.sin6_addr, | 113 | if (ipv6_addr_equal(&addr->a.v6.sin6_addr, |
113 | &ifa->addr)) { | 114 | &ifa->addr)) { |
115 | found = 1; | ||
114 | addr->valid = 0; | 116 | addr->valid = 0; |
115 | list_del_rcu(&addr->list); | 117 | list_del_rcu(&addr->list); |
116 | break; | 118 | break; |
117 | } | 119 | } |
118 | } | 120 | } |
119 | spin_unlock_bh(&sctp_local_addr_lock); | 121 | spin_unlock_bh(&sctp_local_addr_lock); |
120 | if (addr && !addr->valid) | 122 | if (found) |
121 | call_rcu(&addr->rcu, sctp_local_addr_free); | 123 | call_rcu(&addr->rcu, sctp_local_addr_free); |
122 | break; | 124 | break; |
123 | } | 125 | } |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 688546dccd82..ad0a4069b95b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -628,6 +628,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
628 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 628 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
629 | struct sctp_sockaddr_entry *addr = NULL; | 629 | struct sctp_sockaddr_entry *addr = NULL; |
630 | struct sctp_sockaddr_entry *temp; | 630 | struct sctp_sockaddr_entry *temp; |
631 | int found = 0; | ||
631 | 632 | ||
632 | switch (ev) { | 633 | switch (ev) { |
633 | case NETDEV_UP: | 634 | case NETDEV_UP: |
@@ -647,13 +648,14 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
647 | list_for_each_entry_safe(addr, temp, | 648 | list_for_each_entry_safe(addr, temp, |
648 | &sctp_local_addr_list, list) { | 649 | &sctp_local_addr_list, list) { |
649 | if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { | 650 | if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { |
651 | found = 1; | ||
650 | addr->valid = 0; | 652 | addr->valid = 0; |
651 | list_del_rcu(&addr->list); | 653 | list_del_rcu(&addr->list); |
652 | break; | 654 | break; |
653 | } | 655 | } |
654 | } | 656 | } |
655 | spin_unlock_bh(&sctp_local_addr_lock); | 657 | spin_unlock_bh(&sctp_local_addr_lock); |
656 | if (addr && !addr->valid) | 658 | if (found) |
657 | call_rcu(&addr->rcu, sctp_local_addr_free); | 659 | call_rcu(&addr->rcu, sctp_local_addr_free); |
658 | break; | 660 | break; |
659 | } | 661 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e45be4e3f80d..578630e8e00d 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2375,6 +2375,14 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2375 | asoc->peer.ipv4_address = 0; | 2375 | asoc->peer.ipv4_address = 0; |
2376 | asoc->peer.ipv6_address = 0; | 2376 | asoc->peer.ipv6_address = 0; |
2377 | 2377 | ||
2378 | /* Assume that peer supports the address family | ||
2379 | * by which it sends a packet. | ||
2380 | */ | ||
2381 | if (peer_addr->sa.sa_family == AF_INET6) | ||
2382 | asoc->peer.ipv6_address = 1; | ||
2383 | else if (peer_addr->sa.sa_family == AF_INET) | ||
2384 | asoc->peer.ipv4_address = 1; | ||
2385 | |||
2378 | /* Cycle through address types; avoid divide by 0. */ | 2386 | /* Cycle through address types; avoid divide by 0. */ |
2379 | sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); | 2387 | sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); |
2380 | if (sat) | 2388 | if (sat) |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 939892691a26..d994d822900d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2933,17 +2933,39 @@ static int sctp_setsockopt_maxburst(struct sock *sk, | |||
2933 | char __user *optval, | 2933 | char __user *optval, |
2934 | int optlen) | 2934 | int optlen) |
2935 | { | 2935 | { |
2936 | struct sctp_assoc_value params; | ||
2937 | struct sctp_sock *sp; | ||
2938 | struct sctp_association *asoc; | ||
2936 | int val; | 2939 | int val; |
2940 | int assoc_id = 0; | ||
2937 | 2941 | ||
2938 | if (optlen != sizeof(int)) | 2942 | if (optlen < sizeof(int)) |
2939 | return -EINVAL; | 2943 | return -EINVAL; |
2940 | if (get_user(val, (int __user *)optval)) | ||
2941 | return -EFAULT; | ||
2942 | 2944 | ||
2943 | if (val < 0) | 2945 | if (optlen == sizeof(int)) { |
2946 | printk(KERN_WARNING | ||
2947 | "SCTP: Use of int in max_burst socket option deprecated\n"); | ||
2948 | printk(KERN_WARNING | ||
2949 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
2950 | if (copy_from_user(&val, optval, optlen)) | ||
2951 | return -EFAULT; | ||
2952 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2953 | if (copy_from_user(¶ms, optval, optlen)) | ||
2954 | return -EFAULT; | ||
2955 | val = params.assoc_value; | ||
2956 | assoc_id = params.assoc_id; | ||
2957 | } else | ||
2944 | return -EINVAL; | 2958 | return -EINVAL; |
2945 | 2959 | ||
2946 | sctp_sk(sk)->max_burst = val; | 2960 | sp = sctp_sk(sk); |
2961 | |||
2962 | if (assoc_id != 0) { | ||
2963 | asoc = sctp_id2assoc(sk, assoc_id); | ||
2964 | if (!asoc) | ||
2965 | return -EINVAL; | ||
2966 | asoc->max_burst = val; | ||
2967 | } else | ||
2968 | sp->max_burst = val; | ||
2947 | 2969 | ||
2948 | return 0; | 2970 | return 0; |
2949 | } | 2971 | } |
@@ -5005,20 +5027,45 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
5005 | char __user *optval, | 5027 | char __user *optval, |
5006 | int __user *optlen) | 5028 | int __user *optlen) |
5007 | { | 5029 | { |
5008 | int val; | 5030 | struct sctp_assoc_value params; |
5031 | struct sctp_sock *sp; | ||
5032 | struct sctp_association *asoc; | ||
5009 | 5033 | ||
5010 | if (len < sizeof(int)) | 5034 | if (len < sizeof(int)) |
5011 | return -EINVAL; | 5035 | return -EINVAL; |
5012 | 5036 | ||
5013 | len = sizeof(int); | 5037 | if (len == sizeof(int)) { |
5038 | printk(KERN_WARNING | ||
5039 | "SCTP: Use of int in max_burst socket option deprecated\n"); | ||
5040 | printk(KERN_WARNING | ||
5041 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
5042 | params.assoc_id = 0; | ||
5043 | } else if (len == sizeof (struct sctp_assoc_value)) { | ||
5044 | if (copy_from_user(¶ms, optval, len)) | ||
5045 | return -EFAULT; | ||
5046 | } else | ||
5047 | return -EINVAL; | ||
5014 | 5048 | ||
5015 | val = sctp_sk(sk)->max_burst; | 5049 | sp = sctp_sk(sk); |
5016 | if (put_user(len, optlen)) | 5050 | |
5017 | return -EFAULT; | 5051 | if (params.assoc_id != 0) { |
5018 | if (copy_to_user(optval, &val, len)) | 5052 | asoc = sctp_id2assoc(sk, params.assoc_id); |
5019 | return -EFAULT; | 5053 | if (!asoc) |
5054 | return -EINVAL; | ||
5055 | params.assoc_value = asoc->max_burst; | ||
5056 | } else | ||
5057 | params.assoc_value = sp->max_burst; | ||
5058 | |||
5059 | if (len == sizeof(int)) { | ||
5060 | if (copy_to_user(optval, ¶ms.assoc_value, len)) | ||
5061 | return -EFAULT; | ||
5062 | } else { | ||
5063 | if (copy_to_user(optval, ¶ms, len)) | ||
5064 | return -EFAULT; | ||
5065 | } | ||
5066 | |||
5067 | return 0; | ||
5020 | 5068 | ||
5021 | return -ENOTSUPP; | ||
5022 | } | 5069 | } |
5023 | 5070 | ||
5024 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | 5071 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, |