cregit-Linux how code gets into the kernel

Release 4.8 net/sctp/protocol.c

Directory: net/sctp
/* SCTP kernel implementation
 * (C) Copyright IBM Corp. 2001, 2004
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001 Intel Corp.
 * Copyright (c) 2001 Nokia, Inc.
 * Copyright (c) 2001 La Monte H.P. Yarroll
 *
 * This file is part of the SCTP kernel implementation
 *
 * Initialization/cleanup for SCTP protocol support.
 *
 * 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.
 *
 * 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.
 * 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, see
 * <http://www.gnu.org/licenses/>.
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
 *    lksctp developers <linux-sctp@vger.kernel.org>
 *
 * Written or modified by:
 *    La Monte H.P. Yarroll <piggy@acm.org>
 *    Karl Knutson <karl@athena.chicago.il.us>
 *    Jon Grimm <jgrimm@us.ibm.com>
 *    Sridhar Samudrala <sri@us.ibm.com>
 *    Daisy Chang <daisyc@us.ibm.com>
 *    Ardelle Fan <ardelle.fan@intel.com>
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/seq_file.h>
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <linux/swap.h>
#include <linux/slab.h>
#include <net/net_namespace.h>
#include <net/protocol.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/route.h>
#include <net/sctp/sctp.h>
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_ecn.h>


#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)

/* Global data structures. */

struct sctp_globals sctp_globals __read_mostly;


struct idr sctp_assocs_id;

DEFINE_SPINLOCK(sctp_assocs_id_lock);


static struct sctp_pf *sctp_pf_inet6_specific;

static struct sctp_pf *sctp_pf_inet_specific;

static struct sctp_af *sctp_af_v4_specific;

static struct sctp_af *sctp_af_v6_specific;


struct kmem_cache *sctp_chunk_cachep __read_mostly;

struct kmem_cache *sctp_bucket_cachep __read_mostly;


long sysctl_sctp_mem[3];

int sysctl_sctp_rmem[3];

int sysctl_sctp_wmem[3];

/* Set up the proc fs entry for the SCTP protocol. */

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); if (!net->sctp.proc_net_sctp) goto out_proc_net_sctp; if (sctp_snmp_proc_init(net)) goto out_snmp_proc_init; if (sctp_eps_proc_init(net)) goto out_eps_proc_init; if (sctp_assocs_proc_init(net)) goto out_assocs_proc_init; if (sctp_remaddr_proc_init(net)) goto out_remaddr_proc_init; return 0; out_remaddr_proc_init: sctp_assocs_proc_exit(net); out_assocs_proc_init: sctp_eps_proc_exit(net); out_eps_proc_init: sctp_snmp_proc_exit(net); out_snmp_proc_init: remove_proc_entry("sctp", net->proc_net); net->sctp.proc_net_sctp = NULL; out_proc_net_sctp: return -ENOMEM; #endif /* CONFIG_PROC_FS */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric w. biedermaneric w. biederman5539.57%213.33%
sridhar samudralasridhar samudrala2517.99%320.00%
wei yongjunwei yongjun2014.39%16.67%
jon grimmjon grimm139.35%16.67%
florian westphalflorian westphal85.76%16.67%
neil hormanneil horman64.32%16.67%
david s. millerdavid s. miller42.88%16.67%
alexey dobriyanalexey dobriyan32.16%16.67%
randy dunlaprandy dunlap21.44%16.67%
pavel emelianovpavel emelianov10.72%16.67%
christoph paaschchristoph paasch10.72%16.67%
eric dumazeteric dumazet10.72%16.67%
Total139100.00%15100.00%

/* Clean up the proc fs entry for the SCTP protocol. * Note: Do not make this __exit as it is used in the init error * path. */
static void sctp_proc_exit(struct net *net) { #ifdef CONFIG_PROC_FS sctp_snmp_proc_exit(net); sctp_eps_proc_exit(net); sctp_assocs_proc_exit(net); sctp_remaddr_proc_exit(net); remove_proc_entry("sctp", net->proc_net); net->sctp.proc_net_sctp = NULL; #endif }

Contributors

PersonTokensPropCommitsCommitProp
eric w. biedermaneric w. biederman2852.83%222.22%
jon grimmjon grimm1120.75%111.11%
sridhar samudralasridhar samudrala713.21%333.33%
florian westphalflorian westphal59.43%111.11%
david s. millerdavid s. miller11.89%111.11%
neil hormanneil horman11.89%111.11%
Total53100.00%9100.00%

/* Private helper to extract ipv4 address and stash them in * the protocol structure. */
static void sctp_v4_copy_addrlist(struct list_head *addrlist, struct net_device *dev) { struct in_device *in_dev; struct in_ifaddr *ifa; struct sctp_sockaddr_entry *addr; rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { rcu_read_unlock(); return; } for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { /* Add the address to the local list. */ addr = kzalloc(sizeof(*addr), GFP_ATOMIC); if (addr) { addr->a.v4.sin_family = AF_INET; addr->a.v4.sin_port = 0; addr->a.v4.sin_addr.s_addr = ifa->ifa_local; addr->valid = 1; INIT_LIST_HEAD(&addr->list); list_add_tail(&addr->list, addrlist); } } rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm12280.26%444.44%
vladislav yasevichvladislav yasevich149.21%111.11%
david s. millerdavid s. miller63.95%111.11%
daniel borkmanndaniel borkmann63.95%111.11%
al viroal viro31.97%111.11%
herbert xuherbert xu10.66%111.11%
Total152100.00%9100.00%

/* Extract our IP addresses from the system and stash them in the * protocol structure. */
static void sctp_get_local_addr_list(struct net *net) { struct net_device *dev; struct list_head *pos; struct sctp_af *af; rcu_read_lock(); for_each_netdev_rcu(net, dev) { list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); af->copy_addrlist(&net->sctp.local_addr_list, dev); } } rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm5270.27%330.00%
eric w. biedermaneric w. biederman1114.86%220.00%
eric dumazeteric dumazet56.76%110.00%
pavel emelianovpavel emelianov34.05%110.00%
sridhar samudralasridhar samudrala22.70%220.00%
dave jonesdave jones11.35%110.00%
Total74100.00%10100.00%

/* Free the existing local addresses. */
static void sctp_free_local_addr_list(struct net *net) { struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); list_del(pos); kfree(addr); } }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm4783.93%233.33%
eric w. biedermaneric w. biederman58.93%116.67%
rusty russellrusty russell23.57%116.67%
david s. millerdavid s. miller11.79%116.67%
sridhar samudralasridhar samudrala11.79%116.67%
Total56100.00%6100.00%

/* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, sctp_scope_t scope, gfp_t gfp, int copy_flags) { struct sctp_sockaddr_entry *addr; int error = 0; rcu_read_lock(); list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { if (!addr->valid) continue; if (sctp_in_scope(net, &addr->a, scope)) { /* Now that the address is in scope, check to see if * the address type is really supported by the local * sock as well as the remote peer. */ if ((((AF_INET == addr->a.sa.sa_family) && (copy_flags & SCTP_ADDR4_PEERSUPP))) || (((AF_INET6 == addr->a.sa.sa_family) && (copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_PEERSUPP)))) { error = sctp_add_bind_addr(bp, &addr->a, sizeof(addr->a), SCTP_ADDR_SRC, GFP_ATOMIC); if (error) goto end_copy; } } } end_copy: rcu_read_unlock(); return error; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm12274.39%531.25%
vladislav yasevichvladislav yasevich1810.98%212.50%
eric w. biedermaneric w. biederman84.88%212.50%
marcelo ricardo leitnermarcelo ricardo leitner74.27%16.25%
al viroal viro53.05%318.75%
david s. millerdavid s. miller21.22%16.25%
sridhar samudralasridhar samudrala21.22%212.50%
Total164100.00%16100.00%

/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, int is_saddr) { void *from; __be16 *port; struct sctphdr *sh; port = &addr->v4.sin_port; addr->v4.sin_family = AF_INET; /* Always called on head skb, so this is safe */ sh = sctp_hdr(skb); if (is_saddr) { *port = sh->source; from = &ip_hdr(skb)->saddr; } else { *port = sh->dest; from = &ip_hdr(skb)->daddr; } memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm10990.83%120.00%
arnaldo carvalho de meloarnaldo carvalho de melo97.50%240.00%
al viroal viro10.83%120.00%
marcelo ricardo leitnermarcelo ricardo leitner10.83%120.00%
Total120100.00%5100.00%

/* Initialize an sctp_addr from a socket. */
static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) { addr->v4.sin_family = AF_INET; addr->v4.sin_port = 0; addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm4595.74%133.33%
al viroal viro12.13%133.33%
eric dumazeteric dumazet12.13%133.33%
Total47100.00%3100.00%

/* Initialize sk->sk_rcv_saddr from sctp_addr. */
static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk) { inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm2993.55%133.33%
sridhar samudralasridhar samudrala13.23%133.33%
eric dumazeteric dumazet13.23%133.33%
Total31100.00%3100.00%

/* Initialize sk->sk_daddr from sctp_addr. */
static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) { inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr; }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala3096.77%150.00%
eric dumazeteric dumazet13.23%150.00%
Total31100.00%2100.00%

/* Initialize a sctp_addr from an address parameter. */
static void sctp_v4_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, __be16 port, int iif) { addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala5398.15%150.00%
al viroal viro11.85%150.00%
Total54100.00%2100.00%

/* Initialize an address parameter from a sctp_addr and return the length * of the address parameter. */
static int sctp_v4_to_addr_param(const union sctp_addr *addr, union sctp_addr_param *param) { int length = sizeof(sctp_ipv4addr_param_t); param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; param->v4.param_hdr.length = htons(length); param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; return length; }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala6698.51%150.00%
al viroal viro11.49%150.00%
Total67100.00%2100.00%

/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4, __be16 port) { saddr->v4.sin_family = AF_INET; saddr->v4.sin_port = port; saddr->v4.sin_addr.s_addr = fl4->saddr; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm2655.32%233.33%
sridhar samudralasridhar samudrala1634.04%233.33%
david s. millerdavid s. miller48.51%116.67%
al viroal viro12.13%116.67%
Total47100.00%6100.00%

/* Compare two addresses exactly. */
static int sctp_v4_cmp_addr(const union sctp_addr *addr1, const union sctp_addr *addr2) { if (addr1->sa.sa_family != addr2->sa.sa_family) return 0; if (addr1->v4.sin_port != addr2->v4.sin_port) return 0; if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr) return 0; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm7092.11%266.67%
sridhar samudralasridhar samudrala67.89%133.33%
Total76100.00%3100.00%

/* Initialize addr struct to INADDR_ANY. */
static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) { addr->v4.sin_family = AF_INET; addr->v4.sin_addr.s_addr = htonl(INADDR_ANY); addr->v4.sin_port = port; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm3990.70%250.00%
al viroal viro49.30%250.00%
Total43100.00%4100.00%

/* Is this a wildcard address? */
static int sctp_v4_is_any(const union sctp_addr *addr) { return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm2388.46%150.00%
al viroal viro311.54%150.00%
Total26100.00%2100.00%

/* This function checks if the address is a valid address to be used for * SCTP binding. * * Output: * Return 0 - If the address is a non-unicast or an illegal address. * Return 1 - If the address is a unicast. */
static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp, const struct sk_buff *skb) { /* IPv4 addresses not allowed */ if (sp && ipv6_only_sock(sctp_opt2sk(sp))) return 0; /* Is this a non-unicast address or a unusable SCTP address? */ if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) return 0; /* Is this a broadcast address? */ if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST) return 0; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
vladislav yasevichvladislav yasevich3648.00%233.33%
jon grimmjon grimm3546.67%233.33%
eric dumazeteric dumazet34.00%116.67%
arnaldo carvalho de meloarnaldo carvalho de melo11.33%116.67%
Total75100.00%6100.00%

/* Should this be available for binding? */
static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) { struct net *net = sock_net(&sp->inet.sk); int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr); if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && ret != RTN_LOCAL && !sp->inet.freebind && !net->ipv4.sysctl_ip_nonlocal_bind) return 0; if (ipv6_only_sock(sctp_opt2sk(sp))) return 0; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm5151.52%222.22%
eric w. biedermaneric w. biederman1717.17%222.22%
vladislav yasevichvladislav yasevich1313.13%111.11%
neil hormanneil horman1010.10%111.11%
vincent bernatvincent bernat44.04%111.11%
al viroal viro33.03%111.11%
arnaldo carvalho de meloarnaldo carvalho de melo11.01%111.11%
Total99100.00%9100.00%

/* Checking the loopback, private and other address scopes as defined in * RFC 1918. The IPv4 scoping is based on the draft for SCTP IPv4 * scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>. * * Level 0 - unusable SCTP addresses * Level 1 - loopback address * Level 2 - link-local addresses * Level 3 - private addresses. * Level 4 - global addresses * For INIT and INIT-ACK address list, let L be the level of * of requested destination address, sender and receiver * SHOULD include all of its addresses with level greater * than or equal to L. * * IPv4 scoping can be controlled through sysctl option * net.sctp.addr_scope_policy */
static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) { sctp_scope_t retval; /* Check for unusable SCTP addresses. */ if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) { retval = SCTP_SCOPE_UNUSABLE; } else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) { retval = SCTP_SCOPE_LOOPBACK; } else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) { retval = SCTP_SCOPE_LINK; } else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) || ipv4_is_private_172(addr->v4.sin_addr.s_addr) || ipv4_is_private_192(addr->v4.sin_addr.s_addr)) { retval = SCTP_SCOPE_PRIVATE; } else { retval = SCTP_SCOPE_GLOBAL; } return retval; }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala8365.87%133.33%
joe perchesjoe perches2519.84%133.33%
jon grimmjon grimm1814.29%133.33%
Total126100.00%3100.00%

/* Returns a valid dst cache entry for the given source and destination ip * addresses. If an association is passed, trys to get a dst entry with a * source address that matches an address in the bind address list. */
static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, struct flowi *fl, struct sock *sk) { struct sctp_association *asoc = t->asoc; struct rtable *rt; struct flowi4 *fl4 = &fl->u.ip4; struct sctp_bind_addr *bp; struct sctp_sockaddr_entry *laddr; struct dst_entry *dst = NULL; union sctp_addr *daddr = &t->ipaddr; union sctp_addr dst_saddr; memset(fl4, 0x0, sizeof(struct flowi4)); fl4->daddr = daddr->v4.sin_addr.s_addr; fl4->fl4_dport = daddr->v4.sin_port; fl4->flowi4_proto = IPPROTO_SCTP; if (asoc) { fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; fl4->fl4_sport = htons(asoc->base.bind_addr.port); } if (saddr) { fl4->saddr = saddr->v4.sin_addr.s_addr; fl4->fl4_sport = saddr->v4.sin_port; } 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)) dst = &rt->dst; /* If there is no association or if a source address is passed, no * more validation is required. */ if (!asoc || saddr) goto out; bp = &asoc->base.bind_addr; if (dst) { /* Walk through the bind address list and look for a bind * address that matches the source address of the returned dst. */ sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port)); rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) || (laddr->state != SCTP_ADDR_SRC && !asoc->src_out_of_asoc_ok)) continue; if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) goto out_unlock; } rcu_read_unlock(); /* None of the bound addresses match the source address of the * dst. So release it. */ dst_release(dst); dst = NULL; } /* Walk through the bind address list and try to get a dst that * matches a bind address as the source address. */ rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { struct net_device *odev; if (!laddr->valid) continue; if (laddr->state != SCTP_ADDR_SRC || AF_INET != laddr->a.sa.sa_family) continue; 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)) continue; if (!dst) dst = &rt->dst; /* Ensure the src address belongs to the output * interface. */ odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr, false); if (!odev || odev->ifindex != fl4->flowi4_oif) { if (&rt->dst != dst) dst_release(&rt->dst); continue; } if (dst != &rt->dst) dst_release(dst); dst = &rt->dst; break; } out_unlock: rcu_read_unlock(); out: t->dst = dst; if (dst) pr_debug("rt_dst:%pI4, rt_src:%pI4\n", &fl4->daddr, &fl4->saddr); else pr_debug("no route\n"); }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala21836.27%412.50%
marcelo ricardo leitnermarcelo ricardo leitner9315.47%412.50%
vladislav yasevichvladislav yasevich9014.98%412.50%
david s. millerdavid s. miller528.65%412.50%
wei yongjunwei yongjun355.82%13.12%
xufeng zhangxufeng zhang335.49%13.12%
jon grimmjon grimm284.66%412.50%
gui jianfenggui jianfeng142.33%13.12%
michio hondamichio honda132.16%13.12%
eric w. biedermaneric w. biederman81.33%13.12%
harvey harrisonharvey harrison61.00%26.25%
daniel borkmanndaniel borkmann50.83%13.12%
al viroal viro40.67%39.38%
denis v. lunevdenis v. lunev20.33%13.12%
Total601100.00%32100.00%

/* For v4, the source address is cached in the route entry(dst). So no need * to cache it separately and hence this is an empty routine. */
static void sctp_v4_get_saddr(struct sctp_sock *sk, struct sctp_transport *t, struct flowi *fl) { union sctp_addr *saddr = &t->saddr; struct rtable *rt = (struct rtable *)t->dst; if (rt) { saddr->v4.sin_family = AF_INET; saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr; } }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala4965.33%342.86%
vladislav yasevichvladislav yasevich1418.67%114.29%
david s. millerdavid s. miller68.00%114.29%
hideaki yoshifujihideaki yoshifuji56.67%114.29%
jon grimmjon grimm11.33%114.29%
Total75100.00%7100.00%

/* What interface did this skb arrive on? */
static int sctp_v4_skb_iif(const struct sk_buff *skb) { return inet_iif(skb); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm1583.33%250.00%
eric dumazeteric dumazet211.11%125.00%
david s. millerdavid s. miller15.56%125.00%
Total18100.00%4100.00%

/* Was this packet marked by Explicit Congestion Notification? */
static int sctp_v4_is_ce(const struct sk_buff *skb) { return INET_ECN_is_ce(ip_hdr(skb)->tos); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm2086.96%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo313.04%150.00%
Total23100.00%2100.00%

/* Create and initialize a new sk for the socket returned by accept(). */
static struct sock *sctp_v4_create_accept_sk(struct sock *sk, struct sctp_association *asoc) { struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, sk->sk_prot, 0); struct inet_sock *newinet; if (!newsk) goto out; sock_init_data(NULL, newsk); sctp_copy_sock(newsk, sk, asoc); sock_reset_flag(newsk, SOCK_ZAPPED); newinet = inet_sk(newsk); newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; sk_refcnt_debug_inc(newsk); if (newsk->sk_prot->init(newsk)) { sk_common_release(newsk); newsk = NULL; } out: return newsk; }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala9571.97%215.38%
arnaldo carvalho de meloarnaldo carvalho de melo118.33%538.46%
vladislav yasevichvladislav yasevich118.33%17.69%
thomas grafthomas graf75.30%17.69%
eric w. biedermaneric w. biederman43.03%215.38%
hideaki yoshifujihideaki yoshifuji32.27%17.69%
eric dumazeteric dumazet10.76%17.69%
Total132100.00%13100.00%


static int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) { /* No address mapping for V4 sockets */ return sizeof(struct sockaddr_in); }

Contributors

PersonTokensPropCommitsCommitProp
jon grimmjon grimm1354.17%133.33%
jason gunthorpejason gunthorpe1041.67%133.33%
arnaldo carvalho de meloarnaldo carvalho de melo14.17%133.33%
Total24100.00%3100.00%

/* Dump the v4 addr to the seq file. */
static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) { seq_printf(seq, "%pI4 ", &addr->v4.sin_addr); }

Contributors

PersonTokensPropCommitsCommitProp
sridhar samudralasridhar samudrala2893.33%150.00%
harvey harrisonharvey harrison26.67%150.00%
Total30100.00%2100.00%


static void sctp_v4_ecn_capable(struct sock *sk) { INET_ECN_xmit(sk); }

Contributors

PersonTokensPropCommitsCommitProp
vladislav yasevichvladislav yasevich16100.00%1100.00%
Total16100.00%1100.00%


static void sctp_addr_wq_timeout_handler(unsigned long arg) { struct net *net = (struct net *)arg; struct sctp_sockaddr_entry *addrw, *temp; struct sctp_sock *sp; spin_lock_bh(&net->sctp.addr_wq_lock); list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { 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 */ /* Note. we currently don't handle link local IPv6 addressees */ if (addrw->a.sa.sa_family == AF_INET6) { struct in6_addr *in6; if (ipv6_addr_type(&addrw->a.v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) goto free_next; in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && addrw->state == SCTP_ADDR_NEW) { unsigned long timeo_val; 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); break; } } #endif list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { struct sock *sk; sk = sctp_opt2sk(sp); /* ignore bound-specific endpoints */ if (!sctp_is_ep_boundall(sk)) continue; bh_lock_sock(sk); if (sctp_asconf_mgmt(sp, addrw) < 0) pr_debug("%s: sctp_asconf_mgmt failed\n", __func__); bh_unlock_sock(sk); }