diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/bind_addr.c | 4 | ||||
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 4 | ||||
-rw-r--r-- | net/sctp/protocol.c | 14 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 8 | ||||
-rw-r--r-- | net/sctp/socket.c | 73 |
6 files changed, 83 insertions, 22 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/input.c b/net/sctp/input.c index 4db5a75e01ce..c1d7e3b5c4b4 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -944,7 +944,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, | |||
944 | static struct sctp_association *__sctp_rcv_asconf_lookup( | 944 | static struct sctp_association *__sctp_rcv_asconf_lookup( |
945 | sctp_chunkhdr_t *ch, | 945 | sctp_chunkhdr_t *ch, |
946 | const union sctp_addr *laddr, | 946 | const union sctp_addr *laddr, |
947 | __be32 peer_port, | 947 | __be16 peer_port, |
948 | struct sctp_transport **transportp) | 948 | struct sctp_transport **transportp) |
949 | { | 949 | { |
950 | sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch; | 950 | sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch; |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2622215cd357..1937be583cd7 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 87512f14cf71..25be8f04de6e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -337,14 +337,14 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1, | |||
337 | static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) | 337 | static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) |
338 | { | 338 | { |
339 | addr->v4.sin_family = AF_INET; | 339 | addr->v4.sin_family = AF_INET; |
340 | addr->v4.sin_addr.s_addr = INADDR_ANY; | 340 | addr->v4.sin_addr.s_addr = htonl(INADDR_ANY); |
341 | addr->v4.sin_port = port; | 341 | addr->v4.sin_port = port; |
342 | } | 342 | } |
343 | 343 | ||
344 | /* Is this a wildcard address? */ | 344 | /* Is this a wildcard address? */ |
345 | static int sctp_v4_is_any(const union sctp_addr *addr) | 345 | static int sctp_v4_is_any(const union sctp_addr *addr) |
346 | { | 346 | { |
347 | return INADDR_ANY == addr->v4.sin_addr.s_addr; | 347 | return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr; |
348 | } | 348 | } |
349 | 349 | ||
350 | /* This function checks if the address is a valid address to be used for | 350 | /* This function checks if the address is a valid address to be used for |
@@ -375,7 +375,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) | |||
375 | int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); | 375 | int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); |
376 | 376 | ||
377 | 377 | ||
378 | if (addr->v4.sin_addr.s_addr != INADDR_ANY && | 378 | if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && |
379 | ret != RTN_LOCAL && | 379 | ret != RTN_LOCAL && |
380 | !sp->inet.freebind && | 380 | !sp->inet.freebind && |
381 | !sysctl_ip_nonlocal_bind) | 381 | !sysctl_ip_nonlocal_bind) |
@@ -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 | if (ifa->ifa_dev->dev->nd_net != &init_net) | 633 | if (ifa->ifa_dev->dev->nd_net != &init_net) |
633 | return NOTIFY_DONE; | 634 | return NOTIFY_DONE; |
@@ -650,13 +651,14 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
650 | list_for_each_entry_safe(addr, temp, | 651 | list_for_each_entry_safe(addr, temp, |
651 | &sctp_local_addr_list, list) { | 652 | &sctp_local_addr_list, list) { |
652 | if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { | 653 | if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { |
654 | found = 1; | ||
653 | addr->valid = 0; | 655 | addr->valid = 0; |
654 | list_del_rcu(&addr->list); | 656 | list_del_rcu(&addr->list); |
655 | break; | 657 | break; |
656 | } | 658 | } |
657 | } | 659 | } |
658 | spin_unlock_bh(&sctp_local_addr_lock); | 660 | spin_unlock_bh(&sctp_local_addr_lock); |
659 | if (addr && !addr->valid) | 661 | if (found) |
660 | call_rcu(&addr->rcu, sctp_local_addr_free); | 662 | call_rcu(&addr->rcu, sctp_local_addr_free); |
661 | break; | 663 | break; |
662 | } | 664 | } |
@@ -786,8 +788,8 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, | |||
786 | /* PF_INET only supports AF_INET addresses. */ | 788 | /* PF_INET only supports AF_INET addresses. */ |
787 | if (addr1->sa.sa_family != addr2->sa.sa_family) | 789 | if (addr1->sa.sa_family != addr2->sa.sa_family) |
788 | return 0; | 790 | return 0; |
789 | if (INADDR_ANY == addr1->v4.sin_addr.s_addr || | 791 | if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr || |
790 | INADDR_ANY == addr2->v4.sin_addr.s_addr) | 792 | htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr) |
791 | return 1; | 793 | return 1; |
792 | if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr) | 794 | if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr) |
793 | return 1; | 795 | return 1; |
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 1316694d0a21..a3138a0fe2c5 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, |