X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fsctp%2Fsocket.c;h=1316694d0a21ee77fe4473565f4d820ca7d2abbd;hb=7524d7d6de5d5d3f081de8cf5479819fad339661;hp=dc2f9221f092223c70c9c81ef12ea8c6c9d02e07;hpb=8d8ad9d7c4bfe79bc91b7fc419ecfb9dcdfe6a51;p=linux-2.6 diff --git a/net/sctp/socket.c b/net/sctp/socket.c index dc2f9221f0..1316694d0a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1,4 +1,4 @@ -/* SCTP kernel reference Implementation +/* SCTP kernel implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. @@ -6,7 +6,7 @@ * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll * - * This file is part of the SCTP kernel reference Implementation + * This file is part of the SCTP kernel implementation * * These functions interface with the sockets layer to implement the * SCTP Extensions for the Sockets API. @@ -15,13 +15,13 @@ * functions--this file is the functions which populate the struct proto * for SCTP which is the BOTTOM of the sockets interface. * - * The SCTP reference implementation is free software; + * This SCTP implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * - * The SCTP reference implementation is distributed in the hope that it + * This SCTP implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied * ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -174,7 +174,8 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk) sizeof(struct sctp_chunk); atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); - sk_charge_skb(sk, chunk->skb); + sk->sk_wmem_queued += chunk->skb->truesize; + sk_mem_charge(sk, chunk->skb->truesize); } /* Verify that this is a valid address. */ @@ -390,7 +391,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) /* Add the address to the bind address list. * Use GFP_ATOMIC since BHs will be disabled. */ - ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); + ret = sctp_add_bind_addr(bp, addr, SCTP_ADDR_SRC, GFP_ATOMIC); /* Copy back into socket for getsockname() use. */ if (!ret) { @@ -524,7 +525,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, ep = sp->ep; SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", - __FUNCTION__, sk, addrs, addrcnt); + __func__, sk, addrs, addrcnt); list_for_each(pos, &ep->asocs) { asoc = list_entry(pos, struct sctp_association, asocs); @@ -585,8 +586,8 @@ static int sctp_send_asconf_add_ip(struct sock *sk, addr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(addr->v4.sin_family); memcpy(&saveaddr, addr, af->sockaddr_len); - retval = sctp_add_bind_addr(bp, &saveaddr, 0, - GFP_ATOMIC); + retval = sctp_add_bind_addr(bp, &saveaddr, + SCTP_ADDR_NEW, GFP_ATOMIC); addr_buf += af->sockaddr_len; } } @@ -710,7 +711,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, ep = sp->ep; SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", - __FUNCTION__, sk, addrs, addrcnt); + __func__, sk, addrs, addrcnt); list_for_each(pos, &ep->asocs) { asoc = list_entry(pos, struct sctp_association, asocs); @@ -777,7 +778,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, af = sctp_get_af_specific(laddr->v4.sin_family); list_for_each_entry(saddr, &bp->address_list, list) { if (sctp_cmp_addr_exact(&saddr->a, laddr)) - saddr->use_as_src = 0; + saddr->state = SCTP_ADDR_DEL; } addr_buf += af->sockaddr_len; } @@ -1196,7 +1197,7 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, struct sockaddr *kaddrs; SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", - __FUNCTION__, sk, addrs, addrs_size); + __func__, sk, addrs, addrs_size); if (unlikely(addrs_size <= 0)) return -EINVAL; @@ -1910,7 +1911,8 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, * rwnd by that amount. If all the data in the skb is read, * rwnd is updated when the event is freed. */ - sctp_assoc_rwnd_increase(event->asoc, copied); + if (!sctp_ulpevent_is_notification(event)) + sctp_assoc_rwnd_increase(event->asoc, copied); goto out; } else if ((event->msg_flags & MSG_NOTIFICATION) || (event->msg_flags & MSG_EOR)) @@ -1962,7 +1964,7 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk, static int sctp_setsockopt_events(struct sock *sk, char __user *optval, int optlen) { - if (optlen != sizeof(struct sctp_event_subscribe)) + if (optlen > sizeof(struct sctp_event_subscribe)) return -EINVAL; if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) return -EFAULT; @@ -3278,7 +3280,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, sctp_lock_sock(sk); SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", - __FUNCTION__, sk, addr, addr_len); + __func__, sk, addr, addr_len); /* Validate addr_len before calling common connect/connectx routine. */ af = sctp_get_af_specific(addr->sa_family); @@ -3799,7 +3801,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval goto out; } - SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc); + SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc); retval = sctp_do_peeloff(asoc, &newsock); if (retval < 0) @@ -3813,7 +3815,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval } SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n", - __FUNCTION__, sk, asoc, newsock->sk, retval); + __func__, sk, asoc, newsock->sk, retval); /* Return the fd mapped to the new socket. */ peeloff.sd = retval; @@ -4313,6 +4315,9 @@ static int sctp_copy_laddrs_old(struct sock *sk, __u16 port, (AF_INET6 == addr->a.sa.sa_family)) continue; memcpy(&temp, &addr->a, sizeof(temp)); + if (!temp.v4.sin_port) + temp.v4.sin_port = htons(port); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; @@ -4345,6 +4350,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, (AF_INET6 == addr->a.sa.sa_family)) continue; memcpy(&temp, &addr->a, sizeof(temp)); + if (!temp.v4.sin_port) + temp.v4.sin_port = htons(port); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; @@ -5062,6 +5070,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; + u32 num_chunks; char __user *to; if (len <= sizeof(struct sctp_authchunks)) @@ -5078,12 +5087,15 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, ch = asoc->peer.peer_chunks; /* See if the user provided enough room for all the data */ - if (len < ntohs(ch->param_hdr.length)) + num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); + if (len < num_chunks) return -EINVAL; - len = ntohs(ch->param_hdr.length); + len = num_chunks; if (put_user(len, optlen)) return -EFAULT; + if (put_user(num_chunks, &p->gauth_number_of_chunks)) + return -EFAULT; if (copy_to_user(to, ch->chunks, len)) return -EFAULT; @@ -5097,6 +5109,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; + u32 num_chunks; char __user *to; if (len <= sizeof(struct sctp_authchunks)) @@ -5115,12 +5128,15 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, else ch = sctp_sk(sk)->ep->auth_chunk_list; - if (len < ntohs(ch->param_hdr.length)) + num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); + if (len < num_chunks) return -EINVAL; - len = ntohs(ch->param_hdr.length); + len = num_chunks; if (put_user(len, optlen)) return -EFAULT; + if (put_user(num_chunks, &p->gauth_number_of_chunks)) + return -EFAULT; if (copy_to_user(to, ch->chunks, len)) return -EFAULT; @@ -6035,10 +6051,10 @@ static void sctp_wfree(struct sk_buff *skb) atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); /* - * This undoes what is done via sk_charge_skb + * This undoes what is done via sctp_set_owner_w and sk_mem_charge */ sk->sk_wmem_queued -= skb->truesize; - sk->sk_forward_alloc += skb->truesize; + sk_mem_uncharge(sk, skb->truesize); sock_wfree(skb); __sctp_write_space(asoc); @@ -6059,9 +6075,9 @@ void sctp_sock_rfree(struct sk_buff *skb) atomic_sub(event->rmem_len, &sk->sk_rmem_alloc); /* - * Mimic the behavior of sk_stream_rfree + * Mimic the behavior of sock_rfree */ - sk->sk_forward_alloc += event->rmem_len; + sk_mem_uncharge(sk, event->rmem_len); } @@ -6170,7 +6186,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p) long current_timeo = *timeo_p; DEFINE_WAIT(wait); - SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc, + SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc, (long)(*timeo_p)); /* Increment the association's refcnt. */ @@ -6480,6 +6496,7 @@ struct proto sctp_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + .sockets_allocated = &sctp_sockets_allocated, REF_PROTO_INUSE(sctp) }; @@ -6513,6 +6530,7 @@ struct proto sctpv6_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + .sockets_allocated = &sctp_sockets_allocated, REF_PROTO_INUSE(sctpv6) }; #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */