aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r--net/sctp/protocol.c120
1 files changed, 64 insertions, 56 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2d518425d59..6789d785e69 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -23,16 +23,12 @@
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with GNU CC; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * along with GNU CC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
*
* Please send any bug reports or fixes you make to the
* email address(es):
- * lksctp developers <lksctp-developers@lists.sourceforge.net>
- *
- * Or submit a bug report through the following website:
- * http://www.sf.net/projects/lksctp
+ * lksctp developers <linux-sctp@vger.kernel.org>
*
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
@@ -41,9 +37,6 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
- *
- * Any bugs reported given to us we will try to fix... any fixes shared will
- * be incorporated into the next SCTP release.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -86,7 +79,7 @@ int sysctl_sctp_rmem[3];
int sysctl_sctp_wmem[3];
/* Set up the proc fs entry for the SCTP protocol. */
-static __net_init int sctp_proc_init(struct net *net)
+static int __net_init sctp_proc_init(struct net *net)
{
#ifdef CONFIG_PROC_FS
net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
@@ -153,7 +146,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
/* Add the address to the local list. */
- addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
+ addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
if (addr) {
addr->a.v4.sin_family = AF_INET;
addr->a.v4.sin_port = 0;
@@ -178,7 +171,7 @@ static void sctp_get_local_addr_list(struct net *net)
rcu_read_lock();
for_each_netdev_rcu(net, dev) {
- __list_for_each(pos, &sctp_address_families) {
+ list_for_each(pos, &sctp_address_families) {
af = list_entry(pos, struct sctp_af, list);
af->copy_addrlist(&net->sctp.local_addr_list, dev);
}
@@ -451,8 +444,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
fl4->fl4_sport = saddr->v4.sin_port;
}
- SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ",
- __func__, &fl4->daddr, &fl4->saddr);
+ pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
+ &fl4->saddr);
rt = ip_route_output_key(sock_net(sk), fl4);
if (!IS_ERR(rt))
@@ -498,8 +491,13 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
continue;
if ((laddr->state == SCTP_ADDR_SRC) &&
(AF_INET == laddr->a.sa.sa_family)) {
- fl4->saddr = laddr->a.v4.sin_addr.s_addr;
fl4->fl4_sport = laddr->a.v4.sin_port;
+ flowi4_update_output(fl4,
+ asoc->base.sk->sk_bound_dev_if,
+ RT_CONN_FLAGS(asoc->base.sk),
+ daddr->v4.sin_addr.s_addr,
+ laddr->a.v4.sin_addr.s_addr);
+
rt = ip_route_output_key(sock_net(sk), fl4);
if (!IS_ERR(rt)) {
dst = &rt->dst;
@@ -513,10 +511,10 @@ out_unlock:
out:
t->dst = dst;
if (dst)
- SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n",
- &fl4->daddr, &fl4->saddr);
+ pr_debug("rt_dst:%pI4, rt_src:%pI4\n",
+ &fl4->daddr, &fl4->saddr);
else
- SCTP_DEBUG_PRINTK("NO ROUTE\n");
+ pr_debug("no route\n");
}
/* For v4, the source address is cached in the route entry(dst). So no need
@@ -595,7 +593,7 @@ static void sctp_v4_ecn_capable(struct sock *sk)
INET_ECN_xmit(sk);
}
-void sctp_addr_wq_timeout_handler(unsigned long arg)
+static void sctp_addr_wq_timeout_handler(unsigned long arg)
{
struct net *net = (struct net *)arg;
struct sctp_sockaddr_entry *addrw, *temp;
@@ -604,9 +602,9 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
spin_lock_bh(&net->sctp.addr_wq_lock);
list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
- SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
- " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
- addrw);
+ pr_debug("%s: the first ent in wq:%p is addr:%pISc for cmd:%d at "
+ "entry:%p\n", __func__, &net->sctp.addr_waitq, &addrw->a.sa,
+ addrw->state, addrw);
#if IS_ENABLED(CONFIG_IPV6)
/* Now we send an ASCONF for each association */
@@ -623,8 +621,10 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
addrw->state == SCTP_ADDR_NEW) {
unsigned long timeo_val;
- SCTP_DEBUG_PRINTK("sctp_timo_handler: this is on DAD, trying %d sec later\n",
- SCTP_ADDRESS_TICK_DELAY);
+ pr_debug("%s: this is on DAD, trying %d sec "
+ "later\n", __func__,
+ SCTP_ADDRESS_TICK_DELAY);
+
timeo_val = jiffies;
timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
mod_timer(&net->sctp.addr_wq_timer, timeo_val);
@@ -639,10 +639,10 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
/* ignore bound-specific endpoints */
if (!sctp_is_ep_boundall(sk))
continue;
- sctp_bh_lock_sock(sk);
+ bh_lock_sock(sk);
if (sctp_asconf_mgmt(sp, addrw) < 0)
- SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
- sctp_bh_unlock_sock(sk);
+ pr_debug("%s: sctp_asconf_mgmt failed\n", __func__);
+ bh_unlock_sock(sk);
}
#if IS_ENABLED(CONFIG_IPV6)
free_next:
@@ -707,9 +707,10 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm
addrw = sctp_addr_wq_lookup(net, addr);
if (addrw) {
if (addrw->state != cmd) {
- SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
- " in wq %p\n", addrw->state, &addrw->a,
- &net->sctp.addr_waitq);
+ pr_debug("%s: offsets existing entry for %d, addr:%pISc "
+ "in wq:%p\n", __func__, addrw->state, &addrw->a.sa,
+ &net->sctp.addr_waitq);
+
list_del(&addrw->list);
kfree(addrw);
}
@@ -725,8 +726,9 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm
}
addrw->state = cmd;
list_add_tail(&addrw->list, &net->sctp.addr_waitq);
- SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
- " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq);
+
+ pr_debug("%s: add new entry for cmd:%d, addr:%pISc in wq:%p\n",
+ __func__, addrw->state, &addrw->a.sa, &net->sctp.addr_waitq);
if (!timer_pending(&net->sctp.addr_wq_timer)) {
timeo_val = jiffies;
@@ -952,16 +954,15 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
{
struct inet_sock *inet = inet_sk(skb->sk);
- SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n",
- __func__, skb, skb->len,
- &transport->fl.u.ip4.saddr,
- &transport->fl.u.ip4.daddr);
+ pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb,
+ skb->len, &transport->fl.u.ip4.saddr, &transport->fl.u.ip4.daddr);
inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
- return ip_queue_xmit(skb, &transport->fl);
+
+ return ip_queue_xmit(&inet->sk, skb, &transport->fl);
}
static struct sctp_af sctp_af_inet;
@@ -1016,7 +1017,6 @@ static struct inet_protosw sctp_seqpacket_protosw = {
.protocol = IPPROTO_SCTP,
.prot = &sctp_prot,
.ops = &inet_seqpacket_ops,
- .no_check = 0,
.flags = SCTP_PROTOSW_FLAG
};
static struct inet_protosw sctp_stream_protosw = {
@@ -1024,7 +1024,6 @@ static struct inet_protosw sctp_stream_protosw = {
.protocol = IPPROTO_SCTP,
.prot = &sctp_prot,
.ops = &inet_seqpacket_ops,
- .no_check = 0,
.flags = SCTP_PROTOSW_FLAG
};
@@ -1034,6 +1033,7 @@ static const struct net_protocol sctp_protocol = {
.err_handler = sctp_v4_err,
.no_policy = 1,
.netns_ok = 1,
+ .icmp_strict_tag_validation = 1,
};
/* IPv4 address related functions. */
@@ -1069,8 +1069,8 @@ static struct sctp_af sctp_af_inet = {
#endif
};
-struct sctp_pf *sctp_get_pf_specific(sa_family_t family) {
-
+struct sctp_pf *sctp_get_pf_specific(sa_family_t family)
+{
switch (family) {
case PF_INET:
return sctp_pf_inet_specific;
@@ -1103,14 +1103,15 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
static inline int init_sctp_mibs(struct net *net)
{
- return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics,
- sizeof(struct sctp_mib),
- __alignof__(struct sctp_mib));
+ net->sctp.sctp_statistics = alloc_percpu(struct sctp_mib);
+ if (!net->sctp.sctp_statistics)
+ return -ENOMEM;
+ return 0;
}
static inline void cleanup_sctp_mibs(struct net *net)
{
- snmp_mib_free((void __percpu **)net->sctp.sctp_statistics);
+ free_percpu(net->sctp.sctp_statistics);
}
static void sctp_v4_pf_init(void)
@@ -1165,7 +1166,7 @@ static void sctp_v4_del_protocol(void)
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
}
-static int sctp_net_init(struct net *net)
+static int __net_init sctp_net_init(struct net *net)
{
int status;
@@ -1190,6 +1191,15 @@ static int sctp_net_init(struct net *net)
/* Whether Cookie Preservative is enabled(1) or not(0) */
net->sctp.cookie_preserve_enable = 1;
+ /* Default sctp sockets to use md5 as their hmac alg */
+#if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5)
+ net->sctp.sctp_hmac_alg = "md5";
+#elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1)
+ net->sctp.sctp_hmac_alg = "sha1";
+#else
+ net->sctp.sctp_hmac_alg = NULL;
+#endif
+
/* Max.Burst - 4 */
net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST;
@@ -1281,7 +1291,7 @@ err_sysctl_register:
return status;
}
-static void sctp_net_exit(struct net *net)
+static void __net_exit sctp_net_exit(struct net *net)
{
/* Free the local address list */
sctp_free_addr_wq(net);
@@ -1303,7 +1313,7 @@ static struct pernet_operations sctp_net_ops = {
};
/* Initialize the universe into something sensible. */
-SCTP_STATIC __init int sctp_init(void)
+static __init int sctp_init(void)
{
int i;
int status = -EINVAL;
@@ -1312,9 +1322,8 @@ SCTP_STATIC __init int sctp_init(void)
int max_share;
int order;
- /* SCTP_DEBUG sanity check. */
- if (!sctp_sanity_check())
- goto out;
+ BUILD_BUG_ON(sizeof(struct sctp_ulpevent) >
+ sizeof(((struct sk_buff *) 0)->cb));
/* Allocate bind_bucket and chunk caches. */
status = -ENOBUFS;
@@ -1394,7 +1403,7 @@ SCTP_STATIC __init int sctp_init(void)
/* Allocate and initialize the endpoint hash table. */
sctp_ep_hashsize = 64;
- sctp_ep_hashtable = (struct sctp_hashbucket *)
+ sctp_ep_hashtable =
kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_ep_hashtable) {
pr_err("Failed endpoint_hash alloc\n");
@@ -1456,7 +1465,6 @@ SCTP_STATIC __init int sctp_init(void)
if (status)
goto err_v6_add_protocol;
- status = 0;
out:
return status;
err_v6_add_protocol:
@@ -1490,7 +1498,7 @@ err_chunk_cachep:
}
/* Exit handler for the SCTP protocol. */
-SCTP_STATIC __exit void sctp_exit(void)
+static __exit void sctp_exit(void)
{
/* BUG. This should probably do something useful like clean
* up all the remaining associations and all that memory.
@@ -1536,7 +1544,7 @@ module_exit(sctp_exit);
*/
MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
-MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
+MODULE_AUTHOR("Linux Kernel SCTP developers <linux-sctp@vger.kernel.org>");
MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");