aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c118
1 files changed, 94 insertions, 24 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1e8132b8c4d9..bdd8bd428b64 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2746,6 +2746,46 @@ static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
2746 return 0; 2746 return 0;
2747} 2747}
2748 2748
2749/*
2750 * 7.1.29. Set or Get the default context (SCTP_CONTEXT)
2751 *
2752 * The context field in the sctp_sndrcvinfo structure is normally only
2753 * used when a failed message is retrieved holding the value that was
2754 * sent down on the actual send call. This option allows the setting of
2755 * a default context on an association basis that will be received on
2756 * reading messages from the peer. This is especially helpful in the
2757 * one-2-many model for an application to keep some reference to an
2758 * internal state machine that is processing messages on the
2759 * association. Note that the setting of this value only effects
2760 * received messages from the peer and does not effect the value that is
2761 * saved with outbound messages.
2762 */
2763static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
2764 int optlen)
2765{
2766 struct sctp_assoc_value params;
2767 struct sctp_sock *sp;
2768 struct sctp_association *asoc;
2769
2770 if (optlen != sizeof(struct sctp_assoc_value))
2771 return -EINVAL;
2772 if (copy_from_user(&params, optval, optlen))
2773 return -EFAULT;
2774
2775 sp = sctp_sk(sk);
2776
2777 if (params.assoc_id != 0) {
2778 asoc = sctp_id2assoc(sk, params.assoc_id);
2779 if (!asoc)
2780 return -EINVAL;
2781 asoc->default_rcv_context = params.assoc_value;
2782 } else {
2783 sp->default_rcv_context = params.assoc_value;
2784 }
2785
2786 return 0;
2787}
2788
2749/* API 6.2 setsockopt(), getsockopt() 2789/* API 6.2 setsockopt(), getsockopt()
2750 * 2790 *
2751 * Applications use setsockopt() and getsockopt() to set or retrieve 2791 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -2857,6 +2897,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
2857 case SCTP_ADAPTION_LAYER: 2897 case SCTP_ADAPTION_LAYER:
2858 retval = sctp_setsockopt_adaption_layer(sk, optval, optlen); 2898 retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
2859 break; 2899 break;
2900 case SCTP_CONTEXT:
2901 retval = sctp_setsockopt_context(sk, optval, optlen);
2902 break;
2860 2903
2861 default: 2904 default:
2862 retval = -ENOPROTOOPT; 2905 retval = -ENOPROTOOPT;
@@ -3016,6 +3059,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
3016 sp->default_context = 0; 3059 sp->default_context = 0;
3017 sp->default_timetolive = 0; 3060 sp->default_timetolive = 0;
3018 3061
3062 sp->default_rcv_context = 0;
3063
3019 /* Initialize default setup parameters. These parameters 3064 /* Initialize default setup parameters. These parameters
3020 * can be modified with the SCTP_INITMSG socket option or 3065 * can be modified with the SCTP_INITMSG socket option or
3021 * overridden by the SCTP_INIT CMSG. 3066 * overridden by the SCTP_INIT CMSG.
@@ -3821,10 +3866,9 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
3821 sctp_assoc_t id; 3866 sctp_assoc_t id;
3822 struct sctp_bind_addr *bp; 3867 struct sctp_bind_addr *bp;
3823 struct sctp_association *asoc; 3868 struct sctp_association *asoc;
3824 struct list_head *pos; 3869 struct list_head *pos, *temp;
3825 struct sctp_sockaddr_entry *addr; 3870 struct sctp_sockaddr_entry *addr;
3826 rwlock_t *addr_lock; 3871 rwlock_t *addr_lock;
3827 unsigned long flags;
3828 int cnt = 0; 3872 int cnt = 0;
3829 3873
3830 if (len != sizeof(sctp_assoc_t)) 3874 if (len != sizeof(sctp_assoc_t))
@@ -3859,8 +3903,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
3859 addr = list_entry(bp->address_list.next, 3903 addr = list_entry(bp->address_list.next,
3860 struct sctp_sockaddr_entry, list); 3904 struct sctp_sockaddr_entry, list);
3861 if (sctp_is_any(&addr->a)) { 3905 if (sctp_is_any(&addr->a)) {
3862 sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); 3906 list_for_each_safe(pos, temp, &sctp_local_addr_list) {
3863 list_for_each(pos, &sctp_local_addr_list) {
3864 addr = list_entry(pos, 3907 addr = list_entry(pos,
3865 struct sctp_sockaddr_entry, 3908 struct sctp_sockaddr_entry,
3866 list); 3909 list);
@@ -3869,8 +3912,6 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
3869 continue; 3912 continue;
3870 cnt++; 3913 cnt++;
3871 } 3914 }
3872 sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
3873 flags);
3874 } else { 3915 } else {
3875 cnt = 1; 3916 cnt = 1;
3876 } 3917 }
@@ -3892,15 +3933,13 @@ done:
3892static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, 3933static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs,
3893 void __user *to) 3934 void __user *to)
3894{ 3935{
3895 struct list_head *pos; 3936 struct list_head *pos, *next;
3896 struct sctp_sockaddr_entry *addr; 3937 struct sctp_sockaddr_entry *addr;
3897 unsigned long flags;
3898 union sctp_addr temp; 3938 union sctp_addr temp;
3899 int cnt = 0; 3939 int cnt = 0;
3900 int addrlen; 3940 int addrlen;
3901 3941
3902 sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); 3942 list_for_each_safe(pos, next, &sctp_local_addr_list) {
3903 list_for_each(pos, &sctp_local_addr_list) {
3904 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 3943 addr = list_entry(pos, struct sctp_sockaddr_entry, list);
3905 if ((PF_INET == sk->sk_family) && 3944 if ((PF_INET == sk->sk_family) &&
3906 (AF_INET6 == addr->a.sa.sa_family)) 3945 (AF_INET6 == addr->a.sa.sa_family))
@@ -3909,16 +3948,13 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
3909 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), 3948 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
3910 &temp); 3949 &temp);
3911 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 3950 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
3912 if (copy_to_user(to, &temp, addrlen)) { 3951 if (copy_to_user(to, &temp, addrlen))
3913 sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
3914 flags);
3915 return -EFAULT; 3952 return -EFAULT;
3916 } 3953
3917 to += addrlen; 3954 to += addrlen;
3918 cnt ++; 3955 cnt ++;
3919 if (cnt >= max_addrs) break; 3956 if (cnt >= max_addrs) break;
3920 } 3957 }
3921 sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
3922 3958
3923 return cnt; 3959 return cnt;
3924} 3960}
@@ -3926,15 +3962,13 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
3926static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, 3962static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
3927 void __user **to, size_t space_left) 3963 void __user **to, size_t space_left)
3928{ 3964{
3929 struct list_head *pos; 3965 struct list_head *pos, *next;
3930 struct sctp_sockaddr_entry *addr; 3966 struct sctp_sockaddr_entry *addr;
3931 unsigned long flags;
3932 union sctp_addr temp; 3967 union sctp_addr temp;
3933 int cnt = 0; 3968 int cnt = 0;
3934 int addrlen; 3969 int addrlen;
3935 3970
3936 sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); 3971 list_for_each_safe(pos, next, &sctp_local_addr_list) {
3937 list_for_each(pos, &sctp_local_addr_list) {
3938 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 3972 addr = list_entry(pos, struct sctp_sockaddr_entry, list);
3939 if ((PF_INET == sk->sk_family) && 3973 if ((PF_INET == sk->sk_family) &&
3940 (AF_INET6 == addr->a.sa.sa_family)) 3974 (AF_INET6 == addr->a.sa.sa_family))
@@ -3945,16 +3979,13 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
3945 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 3979 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
3946 if(space_left<addrlen) 3980 if(space_left<addrlen)
3947 return -ENOMEM; 3981 return -ENOMEM;
3948 if (copy_to_user(*to, &temp, addrlen)) { 3982 if (copy_to_user(*to, &temp, addrlen))
3949 sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
3950 flags);
3951 return -EFAULT; 3983 return -EFAULT;
3952 } 3984
3953 *to += addrlen; 3985 *to += addrlen;
3954 cnt ++; 3986 cnt ++;
3955 space_left -= addrlen; 3987 space_left -= addrlen;
3956 } 3988 }
3957 sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
3958 3989
3959 return cnt; 3990 return cnt;
3960} 3991}
@@ -4435,6 +4466,42 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
4435} 4466}
4436 4467
4437/* 4468/*
4469 * 7.1.29. Set or Get the default context (SCTP_CONTEXT)
4470 * (chapter and verse is quoted at sctp_setsockopt_context())
4471 */
4472static int sctp_getsockopt_context(struct sock *sk, int len,
4473 char __user *optval, int __user *optlen)
4474{
4475 struct sctp_assoc_value params;
4476 struct sctp_sock *sp;
4477 struct sctp_association *asoc;
4478
4479 if (len != sizeof(struct sctp_assoc_value))
4480 return -EINVAL;
4481
4482 if (copy_from_user(&params, optval, len))
4483 return -EFAULT;
4484
4485 sp = sctp_sk(sk);
4486
4487 if (params.assoc_id != 0) {
4488 asoc = sctp_id2assoc(sk, params.assoc_id);
4489 if (!asoc)
4490 return -EINVAL;
4491 params.assoc_value = asoc->default_rcv_context;
4492 } else {
4493 params.assoc_value = sp->default_rcv_context;
4494 }
4495
4496 if (put_user(len, optlen))
4497 return -EFAULT;
4498 if (copy_to_user(optval, &params, len))
4499 return -EFAULT;
4500
4501 return 0;
4502}
4503
4504/*
4438 * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) 4505 * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
4439 * 4506 *
4440 * This socket option specifies the maximum size to put in any outgoing 4507 * This socket option specifies the maximum size to put in any outgoing
@@ -4572,6 +4639,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
4572 retval = sctp_getsockopt_adaption_layer(sk, len, optval, 4639 retval = sctp_getsockopt_adaption_layer(sk, len, optval,
4573 optlen); 4640 optlen);
4574 break; 4641 break;
4642 case SCTP_CONTEXT:
4643 retval = sctp_getsockopt_context(sk, len, optval, optlen);
4644 break;
4575 default: 4645 default:
4576 retval = -ENOPROTOOPT; 4646 retval = -ENOPROTOOPT;
4577 break; 4647 break;