aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/bind_addr.c4
-rw-r--r--net/sctp/ipv6.c4
-rw-r--r--net/sctp/protocol.c4
-rw-r--r--net/sctp/sm_make_chunk.c8
-rw-r--r--net/sctp/socket.c73
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,
209int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) 209int 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(&params, 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(&params, 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, &params.assoc_value, len))
5061 return -EFAULT;
5062 } else {
5063 if (copy_to_user(optval, &params, len))
5064 return -EFAULT;
5065 }
5066
5067 return 0;
5020 5068
5021 return -ENOTSUPP;
5022} 5069}
5023 5070
5024static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 5071static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,