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.c88
1 files changed, 81 insertions, 7 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 406d957d08fb..9e65758cb038 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -110,7 +110,6 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
110static int sctp_autobind(struct sock *sk); 110static int sctp_autobind(struct sock *sk);
111static void sctp_sock_migrate(struct sock *, struct sock *, 111static void sctp_sock_migrate(struct sock *, struct sock *,
112 struct sctp_association *, sctp_socket_type_t); 112 struct sctp_association *, sctp_socket_type_t);
113static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
114 113
115extern struct kmem_cache *sctp_bucket_cachep; 114extern struct kmem_cache *sctp_bucket_cachep;
116extern long sysctl_sctp_mem[3]; 115extern long sysctl_sctp_mem[3];
@@ -336,6 +335,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
336/* Bind a local address either to an endpoint or to an association. */ 335/* Bind a local address either to an endpoint or to an association. */
337SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) 336SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
338{ 337{
338 struct net *net = sock_net(sk);
339 struct sctp_sock *sp = sctp_sk(sk); 339 struct sctp_sock *sp = sctp_sk(sk);
340 struct sctp_endpoint *ep = sp->ep; 340 struct sctp_endpoint *ep = sp->ep;
341 struct sctp_bind_addr *bp = &ep->base.bind_addr; 341 struct sctp_bind_addr *bp = &ep->base.bind_addr;
@@ -379,7 +379,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
379 } 379 }
380 } 380 }
381 381
382 if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 382 if (snum && snum < PROT_SOCK &&
383 !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
383 return -EACCES; 384 return -EACCES;
384 385
385 /* See if the address matches any of the addresses we may have 386 /* See if the address matches any of the addresses we may have
@@ -610,6 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
610 2*asoc->pathmtu, 4380)); 611 2*asoc->pathmtu, 4380));
611 trans->ssthresh = asoc->peer.i.a_rwnd; 612 trans->ssthresh = asoc->peer.i.a_rwnd;
612 trans->rto = asoc->rto_initial; 613 trans->rto = asoc->rto_initial;
614 sctp_max_rto(asoc, trans);
613 trans->rtt = trans->srtt = trans->rttvar = 0; 615 trans->rtt = trans->srtt = trans->rttvar = 0;
614 sctp_transport_route(trans, NULL, 616 sctp_transport_route(trans, NULL,
615 sctp_sk(asoc->base.sk)); 617 sctp_sk(asoc->base.sk));
@@ -1162,7 +1164,7 @@ static int __sctp_connect(struct sock* sk,
1162 * be permitted to open new associations. 1164 * be permitted to open new associations.
1163 */ 1165 */
1164 if (ep->base.bind_addr.port < PROT_SOCK && 1166 if (ep->base.bind_addr.port < PROT_SOCK &&
1165 !capable(CAP_NET_BIND_SERVICE)) { 1167 !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
1166 err = -EACCES; 1168 err = -EACCES;
1167 goto out_free; 1169 goto out_free;
1168 } 1170 }
@@ -1791,7 +1793,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
1791 * associations. 1793 * associations.
1792 */ 1794 */
1793 if (ep->base.bind_addr.port < PROT_SOCK && 1795 if (ep->base.bind_addr.port < PROT_SOCK &&
1794 !capable(CAP_NET_BIND_SERVICE)) { 1796 !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
1795 err = -EACCES; 1797 err = -EACCES;
1796 goto out_unlock; 1798 goto out_unlock;
1797 } 1799 }
@@ -3890,6 +3892,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
3890 sp->default_rcv_context = 0; 3892 sp->default_rcv_context = 0;
3891 sp->max_burst = net->sctp.max_burst; 3893 sp->max_burst = net->sctp.max_burst;
3892 3894
3895 sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg;
3896
3893 /* Initialize default setup parameters. These parameters 3897 /* Initialize default setup parameters. These parameters
3894 * can be modified with the SCTP_INITMSG socket option or 3898 * can be modified with the SCTP_INITMSG socket option or
3895 * overridden by the SCTP_INIT CMSG. 3899 * overridden by the SCTP_INIT CMSG.
@@ -5632,6 +5636,71 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
5632 return 0; 5636 return 0;
5633} 5637}
5634 5638
5639/*
5640 * SCTP_GET_ASSOC_STATS
5641 *
5642 * This option retrieves local per endpoint statistics. It is modeled
5643 * after OpenSolaris' implementation
5644 */
5645static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
5646 char __user *optval,
5647 int __user *optlen)
5648{
5649 struct sctp_assoc_stats sas;
5650 struct sctp_association *asoc = NULL;
5651
5652 /* User must provide at least the assoc id */
5653 if (len < sizeof(sctp_assoc_t))
5654 return -EINVAL;
5655
5656 if (copy_from_user(&sas, optval, len))
5657 return -EFAULT;
5658
5659 asoc = sctp_id2assoc(sk, sas.sas_assoc_id);
5660 if (!asoc)
5661 return -EINVAL;
5662
5663 sas.sas_rtxchunks = asoc->stats.rtxchunks;
5664 sas.sas_gapcnt = asoc->stats.gapcnt;
5665 sas.sas_outofseqtsns = asoc->stats.outofseqtsns;
5666 sas.sas_osacks = asoc->stats.osacks;
5667 sas.sas_isacks = asoc->stats.isacks;
5668 sas.sas_octrlchunks = asoc->stats.octrlchunks;
5669 sas.sas_ictrlchunks = asoc->stats.ictrlchunks;
5670 sas.sas_oodchunks = asoc->stats.oodchunks;
5671 sas.sas_iodchunks = asoc->stats.iodchunks;
5672 sas.sas_ouodchunks = asoc->stats.ouodchunks;
5673 sas.sas_iuodchunks = asoc->stats.iuodchunks;
5674 sas.sas_idupchunks = asoc->stats.idupchunks;
5675 sas.sas_opackets = asoc->stats.opackets;
5676 sas.sas_ipackets = asoc->stats.ipackets;
5677
5678 /* New high max rto observed, will return 0 if not a single
5679 * RTO update took place. obs_rto_ipaddr will be bogus
5680 * in such a case
5681 */
5682 sas.sas_maxrto = asoc->stats.max_obs_rto;
5683 memcpy(&sas.sas_obs_rto_ipaddr, &asoc->stats.obs_rto_ipaddr,
5684 sizeof(struct sockaddr_storage));
5685
5686 /* Mark beginning of a new observation period */
5687 asoc->stats.max_obs_rto = asoc->rto_min;
5688
5689 /* Allow the struct to grow and fill in as much as possible */
5690 len = min_t(size_t, len, sizeof(sas));
5691
5692 if (put_user(len, optlen))
5693 return -EFAULT;
5694
5695 SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n",
5696 len, sas.sas_assoc_id);
5697
5698 if (copy_to_user(optval, &sas, len))
5699 return -EFAULT;
5700
5701 return 0;
5702}
5703
5635SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5704SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5636 char __user *optval, int __user *optlen) 5705 char __user *optval, int __user *optlen)
5637{ 5706{
@@ -5773,6 +5842,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5773 case SCTP_PEER_ADDR_THLDS: 5842 case SCTP_PEER_ADDR_THLDS:
5774 retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen); 5843 retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen);
5775 break; 5844 break;
5845 case SCTP_GET_ASSOC_STATS:
5846 retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
5847 break;
5776 default: 5848 default:
5777 retval = -ENOPROTOOPT; 5849 retval = -ENOPROTOOPT;
5778 break; 5850 break;
@@ -5981,13 +6053,15 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog)
5981 struct sctp_sock *sp = sctp_sk(sk); 6053 struct sctp_sock *sp = sctp_sk(sk);
5982 struct sctp_endpoint *ep = sp->ep; 6054 struct sctp_endpoint *ep = sp->ep;
5983 struct crypto_hash *tfm = NULL; 6055 struct crypto_hash *tfm = NULL;
6056 char alg[32];
5984 6057
5985 /* Allocate HMAC for generating cookie. */ 6058 /* Allocate HMAC for generating cookie. */
5986 if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { 6059 if (!sp->hmac && sp->sctp_hmac_alg) {
5987 tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); 6060 sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg);
6061 tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC);
5988 if (IS_ERR(tfm)) { 6062 if (IS_ERR(tfm)) {
5989 net_info_ratelimited("failed to load transform for %s: %ld\n", 6063 net_info_ratelimited("failed to load transform for %s: %ld\n",
5990 sctp_hmac_alg, PTR_ERR(tfm)); 6064 sp->sctp_hmac_alg, PTR_ERR(tfm));
5991 return -ENOSYS; 6065 return -ENOSYS;
5992 } 6066 }
5993 sctp_sk(sk)->hmac = tfm; 6067 sctp_sk(sk)->hmac = tfm;