cregit-Linux how code gets into the kernel

Release 4.11 net/ipv4/af_inet.c

Directory: net/ipv4
/*
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
 *              operating system.  INET is implemented using the  BSD Socket
 *              interface as the means of communication with the user level.
 *
 *              PF_INET protocol family socket handler.
 *
 * Authors:     Ross Biro
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *              Florian La Roche, <flla@stud.uni-sb.de>
 *              Alan Cox, <A.Cox@swansea.ac.uk>
 *
 * Changes (see also sock.c)
 *
 *              piggy,
 *              Karl Knutson    :       Socket protocol table
 *              A.N.Kuznetsov   :       Socket death error in accept().
 *              John Richardson :       Fix non blocking error in connect()
 *                                      so sockets that fail to connect
 *                                      don't return -EINPROGRESS.
 *              Alan Cox        :       Asynchronous I/O support
 *              Alan Cox        :       Keep correct socket pointer on sock
 *                                      structures
 *                                      when accept() ed
 *              Alan Cox        :       Semantics of SO_LINGER aren't state
 *                                      moved to close when you look carefully.
 *                                      With this fixed and the accept bug fixed
 *                                      some RPC stuff seems happier.
 *              Niibe Yutaka    :       4.4BSD style write async I/O
 *              Alan Cox,
 *              Tony Gale       :       Fixed reuse semantics.
 *              Alan Cox        :       bind() shouldn't abort existing but dead
 *                                      sockets. Stops FTP netin:.. I hope.
 *              Alan Cox        :       bind() works correctly for RAW sockets.
 *                                      Note that FreeBSD at least was broken
 *                                      in this respect so be careful with
 *                                      compatibility tests...
 *              Alan Cox        :       routing cache support
 *              Alan Cox        :       memzero the socket structure for
 *                                      compactness.
 *              Matt Day        :       nonblock connect error handler
 *              Alan Cox        :       Allow large numbers of pending sockets
 *                                      (eg for big web sites), but only if
 *                                      specifically application requested.
 *              Alan Cox        :       New buffering throughout IP. Used
 *                                      dumbly.
 *              Alan Cox        :       New buffering now used smartly.
 *              Alan Cox        :       BSD rather than common sense
 *                                      interpretation of listen.
 *              Germano Caronni :       Assorted small races.
 *              Alan Cox        :       sendmsg/recvmsg basic support.
 *              Alan Cox        :       Only sendmsg/recvmsg now supported.
 *              Alan Cox        :       Locked down bind (see security list).
 *              Alan Cox        :       Loosened bind a little.
 *              Mike McLagan    :       ADD/DEL DLCI Ioctls
 *      Willy Konynenberg       :       Transparent proxying support.
 *              David S. Miller :       New socket lookup architecture.
 *                                      Some other random speedups.
 *              Cyrus Durgin    :       Cleaned up file for kmod hacks.
 *              Andi Kleen      :       Fix inet_stream_connect TCP race.
 *
 *              This program 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 of the License, or (at your option) any later version.
 */


#define pr_fmt(fmt) "IPv4: " fmt

#include <linux/err.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/netfilter_ipv4.h>
#include <linux/random.h>
#include <linux/slab.h>

#include <linux/uaccess.h>

#include <linux/inet.h>
#include <linux/igmp.h>
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <net/checksum.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/arp.h>
#include <net/route.h>
#include <net/ip_fib.h>
#include <net/inet_connection_sock.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/udplite.h>
#include <net/ping.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/raw.h>
#include <net/icmp.h>
#include <net/inet_common.h>
#include <net/ip_tunnels.h>
#include <net/xfrm.h>
#include <net/net_namespace.h>
#include <net/secure_seq.h>
#ifdef CONFIG_IP_MROUTE
#include <linux/mroute.h>
#endif
#include <net/l3mdev.h>


/* The inetsw table contains everything that inet_create needs to
 * build a new socket.
 */

static struct list_head inetsw[SOCK_MAX];
static DEFINE_SPINLOCK(inetsw_lock);

/* New destruction routine */


void inet_sock_destruct(struct sock *sk) { struct inet_sock *inet = inet_sk(sk); __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_error_queue); sk_mem_reclaim(sk); if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) { pr_err("Attempt to release TCP socket in state %d %p\n", sk->sk_state, sk); return; } if (!sock_flag(sk, SOCK_DEAD)) { pr_err("Attempt to release alive inet socket %p\n", sk); return; } WARN_ON(atomic_read(&sk->sk_rmem_alloc)); WARN_ON(atomic_read(&sk->sk_wmem_alloc)); WARN_ON(sk->sk_wmem_queued); WARN_ON(sk->sk_forward_alloc); kfree(rcu_dereference_protected(inet->inet_opt, 1)); dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); dst_release(sk->sk_rx_dst); sk_refcnt_debug_dec(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10565.22%840.00%
David S. Miller1710.56%210.00%
Arnaldo Carvalho de Melo159.32%420.00%
Eric Dumazet138.07%315.00%
Hideo Aoki53.11%15.00%
Ilpo Järvinen42.48%15.00%
James Morris21.24%15.00%
Total161100.00%20100.00%

EXPORT_SYMBOL(inet_sock_destruct); /* * The routines beyond this point handle the behaviour of an AF_INET * socket object. Mostly it punts to the subprotocols of IP to do * the work. */ /* * Automatically bind an unbound socket. */
static int inet_autobind(struct sock *sk) { struct inet_sock *inet; /* We may need to bind the socket. */ lock_sock(sk); inet = inet_sk(sk); if (!inet->inet_num) { if (sk->sk_prot->get_port(sk, 0)) { release_sock(sk); return -EAGAIN; } inet->inet_sport = htons(inet->inet_num); } release_sock(sk); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)6175.31%861.54%
Arnaldo Carvalho de Melo911.11%323.08%
David S. Miller89.88%17.69%
Eric Dumazet33.70%17.69%
Total81100.00%13100.00%

/* * Move a socket into listening state. */
int inet_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; unsigned char old_state; int err; lock_sock(sk); err = -EINVAL; if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM) goto out; old_state = sk->sk_state; if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN))) goto out; /* Really, if the socket is already in listen state * we can only allow the backlog to be adjusted. */ if (old_state != TCP_LISTEN) { /* Enable TFO w/o requiring TCP_FASTOPEN socket option. * Note that only TCP sockets (SOCK_STREAM) will reach here. * Also fastopen backlog may already been set via the option * because the socket was in TCP_LISTEN state previously but * was shutdown() rather than close(). */ if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) && (sysctl_tcp_fastopen & TFO_SERVER_ENABLE) && !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) { fastopen_queue_tune(sk, backlog); tcp_fastopen_init_key_once(true); } err = inet_csk_listen_start(sk, backlog); if (err) goto out; } sk->sk_max_ack_backlog = backlog; err = 0; out: release_sock(sk); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)12272.62%642.86%
Jerry Chu2514.88%17.14%
Yuchung Cheng74.17%17.14%
Christoph Paasch52.98%17.14%
Eric Dumazet42.38%214.29%
Arnaldo Carvalho de Melo42.38%214.29%
Ian Morris10.60%17.14%
Total168100.00%14100.00%

EXPORT_SYMBOL(inet_listen); /* * Create an inet socket. */
static int inet_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; struct inet_protosw *answer; struct inet_sock *inet; struct proto *answer_prot; unsigned char answer_flags; int try_loading_module = 0; int err; if (protocol < 0 || protocol >= IPPROTO_MAX) return -EINVAL; sock->state = SS_UNCONNECTED; /* Look for the requested type/protocol pair. */ lookup_protocol: err = -ESOCKTNOSUPPORT; rcu_read_lock(); list_for_each_entry_rcu(answer, &inetsw[sock->type], list) { err = 0; /* Check the non-wild match. */ if (protocol == answer->protocol) { if (protocol != IPPROTO_IP) break; } else { /* Check for the two wild cases. */ if (IPPROTO_IP == protocol) { protocol = answer->protocol; break; } if (IPPROTO_IP == answer->protocol) break; } err = -EPROTONOSUPPORT; } if (unlikely(err)) { if (try_loading_module < 2) { rcu_read_unlock(); /* * Be more specific, e.g. net-pf-2-proto-132-type-1 * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM) */ if (++try_loading_module == 1) request_module("net-pf-%d-proto-%d-type-%d", PF_INET, protocol, sock->type); /* * Fall back to generic, e.g. net-pf-2-proto-132 * (net-pf-PF_INET-proto-IPPROTO_SCTP) */ else request_module("net-pf-%d-proto-%d", PF_INET, protocol); goto lookup_protocol; } else goto out_rcu_unlock; } err = -EPERM; if (sock->type == SOCK_RAW && !kern && !ns_capable(net->user_ns, CAP_NET_RAW)) goto out_rcu_unlock; sock->ops = answer->ops; answer_prot = answer->prot; answer_flags = answer->flags; rcu_read_unlock(); WARN_ON(!answer_prot->slab); err = -ENOBUFS; sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, kern); if (!sk) goto out; err = 0; if (INET_PROTOSW_REUSE & answer_flags) sk->sk_reuse = SK_CAN_REUSE; inet = inet_sk(sk); inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; inet->nodefrag = 0; if (SOCK_RAW == sock->type) { inet->inet_num = protocol; if (IPPROTO_RAW == protocol) inet->hdrincl = 1; } if (net->ipv4.sysctl_ip_no_pmtu_disc) inet->pmtudisc = IP_PMTUDISC_DONT; else inet->pmtudisc = IP_PMTUDISC_WANT; inet->inet_id = 0; sock_init_data(sock, sk); sk->sk_destruct = inet_sock_destruct; sk->sk_protocol = protocol; sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; inet->uc_ttl = -1; inet->mc_loop = 1; inet->mc_ttl = 1; inet->mc_all = 1; inet->mc_index = 0; inet->mc_list = NULL; inet->rcv_tos = 0; sk_refcnt_debug_inc(sk); if (inet->inet_num) { /* It assumes that any protocol which allows * the user to assign a number at socket * creation time automatically * shares. */ inet->inet_sport = htons(inet->inet_num); /* Add to protocol hash chains. */ err = sk->sk_prot->hash(sk); if (err) { sk_common_release(sk); goto out; } } if (sk->sk_prot->init) { err = sk->sk_prot->init(sk); if (err) { sk_common_release(sk); goto out; } } if (!kern) { err = BPF_CGROUP_RUN_PROG_INET_SOCK(sk); if (err) { sk_common_release(sk); goto out; } } out: return err; out_rcu_unlock: rcu_read_unlock(); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)19032.09%1428.00%
Arnaldo Carvalho de Melo14925.17%816.00%
Linus Torvalds7913.34%24.00%
David Ahern335.57%12.00%
David S. Miller274.56%36.00%
Hannes Frederic Sowa183.04%24.00%
Craig Gallek162.70%12.00%
Eric W. Biedermann142.36%36.00%
Eric Paris111.86%36.00%
Herbert Xu101.69%12.00%
Paul E. McKenney71.18%12.00%
Nivedita Singhvi61.01%12.00%
Jiri Olsa61.01%12.00%
Jiri Benc61.01%12.00%
Stephen Hemminger50.84%12.00%
Eric Dumazet50.84%12.00%
Paul Moore40.68%24.00%
Denis V. Lunev20.34%12.00%
Ian Morris20.34%12.00%
Pavel Emelyanov10.17%12.00%
Ilpo Järvinen10.17%12.00%
Total592100.00%50100.00%

/* * The peer socket should always be NULL (or else). When we call this * function we are destroying the object and from then on nobody * should refer to it. */
int inet_release(struct socket *sock) { struct sock *sk = sock->sk; if (sk) { long timeout; /* Applications forget to leave groups before exiting */ ip_mc_drop_socket(sk); /* If linger is set, we don't return until the close * is complete. Otherwise we return immediately. The * actually closing is done the same either way. * * If the close is due to the process exiting, we never * linger.. */ timeout = 0; if (sock_flag(sk, SOCK_LINGER) && !(current->flags & PF_EXITING)) timeout = sk->sk_lingertime; sock->sk = NULL; sk->sk_prot->close(sk, timeout); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7691.57%770.00%
Arnaldo Carvalho de Melo56.02%220.00%
James Morris22.41%110.00%
Total83100.00%10100.00%

EXPORT_SYMBOL(inet_release);
int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); struct net *net = sock_net(sk); unsigned short snum; int chk_addr_ret; u32 tb_id = RT_TABLE_LOCAL; int err; /* If the socket has its own bind function then use it. (RAW) */ if (sk->sk_prot->bind) { err = sk->sk_prot->bind(sk, uaddr, addr_len); goto out; } err = -EINVAL; if (addr_len < sizeof(struct sockaddr_in)) goto out; if (addr->sin_family != AF_INET) { /* Compatibility games : accept AF_UNSPEC (mapped to AF_INET) * only if s_addr is INADDR_ANY. */ err = -EAFNOSUPPORT; if (addr->sin_family != AF_UNSPEC || addr->sin_addr.s_addr != htonl(INADDR_ANY)) goto out; } tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id; chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id); /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since * allowing applications to make a non-local bind solves * several problems with systems using dynamic addressing. * (ie. your servers still start up even if your ISDN link * is temporarily down) */ err = -EADDRNOTAVAIL; if (!net->ipv4.sysctl_ip_nonlocal_bind && !(inet->freebind || inet->transparent) && addr->sin_addr.s_addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; snum = ntohs(addr->sin_port); err = -EACCES; if (snum && snum < inet_prot_sock(net) && !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) goto out; /* We keep a pair of addresses. rcv_saddr is the one * used by hash lookups, and saddr is used for transmit. * * In the BSD API these are the same except where it * would be illegal to use them (multicast/broadcast) in * which case the sending device address is used. */ lock_sock(sk); /* Check these errors (active socket, double bind). */ err = -EINVAL; if (sk->sk_state != TCP_CLOSE || inet->inet_num) goto out_release_sock; inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) inet->inet_saddr = 0; /* Use device */ /* Make sure we are allowed to bind here. */ if ((snum || !inet->bind_address_no_port) && sk->sk_prot->get_port(sk, snum)) { inet->inet_saddr = inet->inet_rcv_saddr = 0; err = -EADDRINUSE; goto out_release_sock; } if (inet->inet_rcv_saddr) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; inet->inet_sport = htons(inet->inet_num); inet->inet_daddr = 0; inet->inet_dport = 0; sk_dst_reset(sk); err = 0; out_release_sock: release_sock(sk); out: return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)26359.10%1745.95%
Arnaldo Carvalho de Melo4610.34%38.11%
Eric Dumazet408.99%38.11%
David Ahern235.17%410.81%
David S. Miller214.72%25.41%
Marcus Meissner184.04%25.41%
Eric W. Biedermann173.82%25.41%
Tóth László Attila61.35%12.70%
Vincent Bernat40.90%12.70%
Krister Johansen40.90%12.70%
Al Viro30.67%12.70%
Total445100.00%37100.00%

EXPORT_SYMBOL(inet_bind);
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; if (addr_len < sizeof(uaddr->sa_family)) return -EINVAL; if (uaddr->sa_family == AF_UNSPEC) return sk->sk_prot->disconnect(sk, flags); if (!inet_sk(sk)->inet_num && inet_autobind(sk)) return -EAGAIN; return sk->sk_prot->connect(sk, uaddr, addr_len); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7677.55%555.56%
Changli Gao1515.31%111.11%
David S. Miller44.08%111.11%
Arnaldo Carvalho de Melo22.04%111.11%
Eric Dumazet11.02%111.11%
Total98100.00%9100.00%

EXPORT_SYMBOL(inet_dgram_connect);
static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias) { DEFINE_WAIT_FUNC(wait, woken_wake_function); add_wait_queue(sk_sleep(sk), &wait); sk->sk_write_pending += writebias; /* Basic assumption: if someone sets sk->sk_err, he _must_ * change state of the socket from TCP_SYN_*. * Connect() does not allow to get error notifications * without closing the socket. */ while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { release_sock(sk); timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); lock_sock(sk); if (signal_pending(current) || !timeo) break; } remove_wait_queue(sk_sleep(sk), &wait); sk->sk_write_pending -= writebias; return timeo; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7768.14%450.00%
Yuchung Cheng1513.27%112.50%
Américo Wang119.73%112.50%
Eric Dumazet65.31%112.50%
Arnaldo Carvalho de Melo43.54%112.50%
Total113100.00%8100.00%

/* * Connect to a remote host. There is regrettably still a little * TCP 'magic' in here. */
int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags, int is_sendmsg) { struct sock *sk = sock->sk; int err; long timeo; /* * uaddr can be NULL and addr_len can be 0 if: * sk is a TCP fastopen active socket and * TCP_FASTOPEN_CONNECT sockopt is set and * we already have a valid cookie for this socket. * In this case, user can call write() after connect(). * write() will invoke tcp_sendmsg_fastopen() which calls * __inet_stream_connect(). */ if (uaddr) { if (addr_len < sizeof(uaddr->sa_family)) return -EINVAL; if (uaddr->sa_family == AF_UNSPEC) { err = sk->sk_prot->disconnect(sk, flags); sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; goto out; } } switch (sock->state) { default: err = -EINVAL; goto out; case SS_CONNECTED: err = -EISCONN; goto out; case SS_CONNECTING: if (inet_sk(sk)->defer_connect) err = is_sendmsg ? -EINPROGRESS : -EISCONN; else err = -EALREADY; /* Fall out of switch with err, set for this state */ break; case SS_UNCONNECTED: err = -EISCONN; if (sk->sk_state != TCP_CLOSE) goto out; err = sk->sk_prot->connect(sk, uaddr, addr_len); if (err < 0) goto out; sock->state = SS_CONNECTING; if (!err && inet_sk(sk)->defer_connect) goto out; /* Just entered SS_CONNECTING state; the only * difference is that return value in non-blocking * case is EINPROGRESS, rather than EALREADY. */ err = -EINPROGRESS; break; } timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { int writebias = (sk->sk_protocol == IPPROTO_TCP) && tcp_sk(sk)->fastopen_req && tcp_sk(sk)->fastopen_req->data ? 1 : 0; /* Error code is set above */ if (!timeo || !inet_wait_for_connect(sk, timeo, writebias)) goto out; err = sock_intr_errno(timeo); if (signal_pending(current)) goto out; } /* Connection was closed by RST, timeout, ICMP error * or another process disconnected us. */ if (sk->sk_state == TCP_CLOSE) goto sock_error; /* sk->sk_err may be not zero now, if RECVERR was ordered by user * and error was received after socket entered established state. * Hence, it is handled normally after connect() return successfully. */ sock->state = SS_CONNECTED; err = 0; out: return err; sock_error: err = sock_error(sk) ? : -ECONNABORTED; sock->state = SS_UNCONNECTED; if (sk->sk_prot->disconnect(sk, flags)) sock->state = SS_DISCONNECTING; goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)29074.17%1266.67%
Wei Wang379.46%15.56%
Yuchung Cheng348.70%211.11%
Changli Gao153.84%15.56%
Willy Tarreau82.05%15.56%
Arnaldo Carvalho de Melo71.79%15.56%
Total391100.00%18100.00%

EXPORT_SYMBOL(__inet_stream_connect);
int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { int err; lock_sock(sock->sk); err = __inet_stream_connect(sock, uaddr, addr_len, flags, 0); release_sock(sock->sk); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Yuchung Cheng5496.43%150.00%
Willy Tarreau23.57%150.00%
Total56100.00%2100.00%

EXPORT_SYMBOL(inet_stream_connect); /* * Accept a pending connection. The TCP layer now gives BSD semantics. */
int inet_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) { struct sock *sk1 = sock->sk; int err = -EINVAL; struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err, kern); if (!sk2) goto do_err; lock_sock(sk2); sock_rps_record_flow(sk2); WARN_ON(!((1 << sk2->sk_state) & (TCPF_ESTABLISHED | TCPF_SYN_RECV | TCPF_CLOSE_WAIT | TCPF_CLOSE))); sock_graft(sk2, newsock); newsock->state = SS_CONNECTED; err = 0; release_sock(sk2); do_err: return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9575.40%857.14%
Arnaldo Carvalho de Melo1511.90%214.29%
David Howells53.97%17.14%
Eric Dumazet53.97%17.14%
Ilpo Järvinen43.17%17.14%
Jerry Chu21.59%17.14%
Total126100.00%14100.00%

EXPORT_SYMBOL(inet_accept); /* * This does both peername and sockname. */
int inet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); sin->sin_family = AF_INET; if (peer) { if (!inet->inet_dport || (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && peer == 1)) return -ENOTCONN; sin->sin_port = inet->inet_dport; sin->sin_addr.s_addr = inet->inet_daddr; } else { __be32 addr = inet->inet_rcv_saddr; if (!addr) addr = inet->inet_saddr; sin->sin_port = inet->inet_sport; sin->sin_addr.s_addr = addr; } memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); *uaddr_len = sizeof(*sin); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13172.78%642.86%
Alexey Kuznetsov168.89%17.14%
David S. Miller147.78%17.14%
Cyrill V. Gorcunov73.89%17.14%
Eric Dumazet63.33%17.14%
Arnaldo Carvalho de Melo52.78%321.43%
Al Viro10.56%17.14%
Total180100.00%14100.00%

EXPORT_SYMBOL(inet_getname);
int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct sock *sk = sock->sk; sock_rps_record_flow(sk); /* We may need to bind the socket. */ if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && inet_autobind(sk)) return -EAGAIN; return sk->sk_prot->sendmsg(sk, msg, size); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5473.97%330.00%
Changli Gao79.59%110.00%
David S. Miller56.85%220.00%
Tom Herbert45.48%110.00%
Arnaldo Carvalho de Melo11.37%110.00%
Stephen Hemminger11.37%110.00%
Eric Dumazet11.37%110.00%
Total73100.00%10100.00%

EXPORT_SYMBOL(inet_sendmsg);
ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { struct sock *sk = sock->sk; sock_rps_record_flow(sk); /* We may need to bind the socket. */ if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && inet_autobind(sk)) return -EAGAIN; if (sk->sk_prot->sendpage) return sk->sk_prot->sendpage(sk, page, offset, size, flags); return sock_no_sendpage(sock, page, offset, size, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Kuznetsov9085.71%116.67%
Changli Gao76.67%116.67%
Tom Herbert43.81%116.67%
Arnaldo Carvalho de Melo21.90%116.67%
Eric Dumazet10.95%116.67%
David S. Miller10.95%116.67%
Total105100.00%6100.00%

EXPORT_SYMBOL(inet_sendpage);
int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; int addr_len = 0; int err; sock_rps_record_flow(sk); err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err; }

Contributors

PersonTokensPropCommitsCommitProp
Tom Herbert8498.82%150.00%
David S. Miller11.18%150.00%
Total85100.00%2100.00%

EXPORT_SYMBOL(inet_recvmsg);
int inet_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; int err = 0; /* This should really check to make sure * the socket is a TCP socket. (WHY AC...) */ how++; /* maps 0->1 has the advantage of making bit 1 rcvs and 1->2 bit 2 snds. 2->3 */ if ((how & ~SHUTDOWN_MASK) || !how) /* MAXINT->0 */ return -EINVAL; lock_sock(sk); if (sock->state == SS_CONNECTING) { if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE)) sock->state = SS_DISCONNECTING; else sock->state = SS_CONNECTED; } switch (sk->sk_state) { case TCP_CLOSE: err = -ENOTCONN; /* Hack to wake up other listeners, who can poll for POLLHUP, even on eg. unconnected UDP sockets -- RR */ default: sk->sk_shutdown |= how; if (sk->sk_prot->shutdown) sk->sk_prot->shutdown(sk, how); break; /* Remaining two branches are temporary solution for missing * close() in multithreaded environment. It is _not_ a good idea, * but we have no choice until close() is repaired at VFS level. */ case TCP_LISTEN: if (!(how & RCV_SHUTDOWN)) break; /* Fall through */ case TCP_SYN_SENT: err = sk->sk_prot->disconnect(sk, O_NONBLOCK); sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; break; } /* Wake up anyone sleeping in poll. */ sk->sk_state_change(sk); release_sock(sk); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)18995.94%880.00%
Arnaldo Carvalho de Melo84.06%220.00%
Total197100.00%10100.00%

EXPORT_SYMBOL(inet_shutdown); /* * ioctl() calls you can issue on an INET socket. Most of these are * device configuration and stuff and very rarely used. Some ioctls * pass on to the socket itself. * * NOTE: I like the idea of a module for the config stuff. ie ifconfig * loads the devconfigure module does its configuring and unloads it. * There's a good 20K of config code hanging around the kernel. */
int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; int err = 0; struct net *net = sock_net(sk); switch (cmd) { case SIOCGSTAMP: err = sock_get_timestamp(sk, (struct timeval __user *)arg); break; case SIOCGSTAMPNS: err = sock_get_timestampns(sk, (struct timespec __user *)arg); break; case SIOCADDRT: case SIOCDELRT: case SIOCRTMSG: err = ip_rt_ioctl(net, cmd, (void __user *)arg); break; case SIOCDARP: case SIOCGARP: case SIOCSARP: err = arp_ioctl(net, cmd, (void __user *)arg); break; case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFBRDADDR: case SIOCSIFBRDADDR: case SIOCGIFNETMASK: case SIOCSIFNETMASK: case SIOCGIFDSTADDR: case SIOCSIFDSTADDR: case SIOCSIFPFLAGS: case SIOCGIFPFLAGS: case SIOCSIFFLAGS: err = devinet_ioctl(net, cmd, (void __user *)arg); break; default: if (sk->sk_prot->ioctl) err = sk->sk_prot->ioctl(sk, cmd, arg); else err = -ENOIOCTLCMD; break; } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)15168.02%736.84%
Arnaldo Carvalho de Melo229.91%210.53%
Eric Dumazet198.56%15.26%
Denis V. Lunev125.41%210.53%
Christoph Hellwig52.25%15.26%
Andi Kleen52.25%15.26%
Hideaki Yoshifuji / 吉藤英明31.35%15.26%
Al Viro20.90%15.26%
Stephen Hemminger10.45%15.26%
Pavel Emelyanov10.45%15.26%
Linus Torvalds10.45%15.26%
Total222100.00%19100.00%

EXPORT_SYMBOL(inet_ioctl); #ifdef CONFIG_COMPAT
static int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; int err = -ENOIOCTLCMD; if (sk->sk_prot->compat_ioctl) err = sk->sk_prot->compat_ioctl(sk, cmd, arg); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann5998.33%150.00%
Gerrit Renker11.67%150.00%
Total60100.00%2100.00%

#endif const struct proto_ops inet_stream_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, .bind = inet_bind, .connect = inet_stream_connect, .socketpair = sock_no_socketpair, .accept = inet_accept, .getname = inet_getname, .poll = tcp_poll, .ioctl = inet_ioctl, .listen = inet_listen, .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, .splice_read = tcp_splice_read, .read_sock = tcp_read_sock, .peek_len = tcp_peek_len, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, .compat_ioctl = inet_compat_ioctl, #endif }; EXPORT_SYMBOL(inet_stream_ops); const struct proto_ops inet_dgram_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, .bind = inet_bind, .connect = inet_dgram_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = inet_getname, .poll = udp_poll, .ioctl = inet_ioctl, .listen = sock_no_listen, .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, .set_peek_off = sk_set_peek_off, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, .compat_ioctl = inet_compat_ioctl, #endif }; EXPORT_SYMBOL(inet_dgram_ops); /* * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without * udp_poll */ static const struct proto_ops inet_sockraw_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, .bind = inet_bind, .connect = inet_dgram_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = inet_getname, .poll = datagram_poll, .ioctl = inet_ioctl, .listen = sock_no_listen, .shutdown = inet_shutdown, .setsockopt = sock_common_setsockopt, .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, .recvmsg = inet_recvmsg, .mmap = sock_no_mmap, .sendpage = inet_sendpage, #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, .compat_ioctl = inet_compat_ioctl, #endif }; static const struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, .owner = THIS_MODULE, }; /* Upon startup we insert all the elements in inetsw_array[] into * the linked list inetsw. */ static struct inet_protosw inetsw_array[] = { { .type = SOCK_STREAM, .protocol = IPPROTO_TCP, .prot = &tcp_prot, .ops = &inet_stream_ops, .flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, }, { .type = SOCK_DGRAM, .protocol = IPPROTO_UDP, .prot = &udp_prot, .ops = &inet_dgram_ops, .flags = INET_PROTOSW_PERMANENT, }, { .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, .ops = &inet_dgram_ops, .flags = INET_PROTOSW_REUSE, }, { .type = SOCK_RAW, .protocol = IPPROTO_IP, /* wild card */ .prot = &raw_prot, .ops = &inet_sockraw_ops, .flags = INET_PROTOSW_REUSE, } }; #define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
void inet_register_protosw(struct inet_protosw *p) { struct list_head *lh; struct inet_protosw *answer; int protocol = p->protocol; struct list_head *last_perm; spin_lock_bh(&inetsw_lock); if (p->type >= SOCK_MAX) goto out_illegal; /* If we are trying to override a permanent protocol, bail. */ last_perm = &inetsw[p->type]; list_for_each(lh, &inetsw[p->type]) { answer = list_entry(lh, struct inet_protosw, list); /* Check only the non-wild match. */ if ((INET_PROTOSW_PERMANENT & answer->flags) == 0) break; if (protocol == answer->protocol) goto out_permanent; last_perm = lh; } /* Add the new entry after the last permanent entry if any, so that * the new entry does not override a permanent entry when matched with * a wild-card protocol. But it is allowed to override any existing * non-permanent entry. This means that when we remove this entry, the * system automatically returns to the old behavior. */ list_add_rcu(&p->list, last_perm); out: spin_unlock_bh(&inetsw_lock); return; out_permanent: pr_err("Attempt to override permanent protocol %d\n", protocol); goto out; out_illegal: pr_err("Ignoring attempt to register invalid socket type %d\n", p->type); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds10467.10%112.50%
Sridhar Samudrala2918.71%112.50%
Junwei (Martin) Zhang85.16%112.50%
Stephen Hemminger74.52%112.50%
Joe Perches42.58%112.50%
Hideaki Yoshifuji / 吉藤英明10.65%112.50%
Patrick McHardy10.65%112.50%
Arnaldo Carvalho de Melo10.65%112.50%
Total155100.00%8100.00%

EXPORT_SYMBOL(inet_register_protosw);
void inet_unregister_protosw(struct inet_protosw *p) { if (INET_PROTOSW_PERMANENT & p->flags) { pr_err("Attempt to unregister permanent protocol %d\n", p->protocol); } else { spin_lock_bh(&inetsw_lock); list_del_rcu(&p->list); spin_unlock_bh(&inetsw_lock); synchronize_net(); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4276.36%120.00%
Stephen Hemminger1018.18%240.00%
Joe Perches23.64%120.00%
Arnaldo Carvalho de Melo11.82%120.00%
Total55100.00%5100.00%

EXPORT_SYMBOL(inet_unregister_protosw);
static int inet_sk_reselect_saddr(struct sock *sk) { struct inet_sock *inet = inet_sk(sk); __be32 old_saddr = inet->inet_saddr; __be32 daddr = inet->inet_daddr; struct flowi4 *fl4; struct rtable *rt; __be32 new_saddr; struct ip_options_rcu *inet_opt; inet_opt = rcu_dereference_protected(inet->inet_opt, lockdep_sock_is_held(sk)); if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; /* Query new route. */ fl4 = &inet->cork.fl.u.ip4; rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, sk->sk_protocol, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) return PTR_ERR(rt); sk_setup_caps(sk, &rt->dst); new_saddr = fl4->saddr; if (new_saddr == old_saddr) return 0; if (sock_net(sk)->ipv4.sysctl_ip_dynaddr > 1) { pr_info("%s(): shifting inet->saddr from %pI4 to %pI4\n", __func__, &old_saddr, &new_saddr); } inet->inet_saddr = inet->inet_rcv_saddr = new_saddr; /* * XXX The only one ugly spot where we need to * XXX really change the sockets identity after * XXX it has entered the hashes. -DaveM * * Besides that, it does not check for connection * uniqueness. Wait for troubles. */ return __sk_prot_rehash(sk); }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo13160.65%17.14%
David S. Miller4018.52%428.57%
Eric Dumazet2913.43%214.29%
Nikolay Borisov73.24%17.14%
Harvey Harrison41.85%214.29%
Al Viro20.93%17.14%
Craig Gallek10.46%17.14%
Joe Perches10.46%17.14%
Hannes Frederic Sowa10.46%17.14%
Total216100.00%14100.00%


int inet_sk_rebuild_header(struct sock *sk) { struct inet_sock *inet = inet_sk(sk); struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); __be32 daddr; struct ip_options_rcu *inet_opt; struct flowi4 *fl4; int err; /* Route is OK, nothing to do. */ if (rt) return 0; /* Reroute. */ rcu_read_lock(); inet_opt = rcu_dereference(inet->inet_opt); daddr = inet->inet_daddr; if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; rcu_read_unlock(); fl4 = &inet->cork.fl.u.ip4; rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); if (!IS_ERR(rt)) { err = 0; sk_setup_caps(sk, &rt->dst); } else { err = PTR_ERR(rt); /* Routing failed... */ sk->sk_route_caps = 0; /* * Other protocols have to map its equivalent state to TCP_SYN_SENT. * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme */ if (!sock_net(sk)->ipv4.sysctl_ip_dynaddr || sk->sk_state != TCP_SYN_SENT || (sk->sk_userlocks & SOCK_BINDADDR_LOCK) || (err = inet_sk_reselect_saddr(sk)) != 0) sk->sk_err_soft = -err; } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo14659.84%17.14%
David S. Miller5622.95%428.57%
Eric Dumazet2711.07%214.29%
Nikolay Borisov72.87%17.14%
Hideaki Yoshifuji / 吉藤英明20.82%17.14%
Venkat Yekkirala20.82%17.14%
Denis V. Lunev20.82%214.29%
Atis Elsts10.41%17.14%
Al Viro10.41%17.14%
Total244100.00%14100.00%

EXPORT_SYMBOL(inet_sk_rebuild_header);
struct sk_buff *inet_gso_segment(struct sk_buff *skb, netdev_features_t features) { bool udpfrag = false, fixedid = false, gso_partial, encap; struct sk_buff *segs = ERR_PTR(-EINVAL); const struct net_offload *ops; unsigned int offset = 0; struct iphdr *iph; int proto, tot_len; int nhoff; int ihl; int id; skb_reset_network_header(skb); nhoff = skb_network_header(skb) - skb_mac_header(skb); if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) goto out; iph = ip_hdr(skb); ihl = iph->ihl * 4; if (ihl < sizeof(*iph)) goto out; id = ntohs(iph->id); proto = iph->protocol; /* Warning: after this point, iph might be no longer valid */ if (unlikely(!pskb_may_pull(skb, ihl))) goto out; __skb_pull(skb, ihl); encap = SKB_GSO_CB(skb)->encap_level > 0; if (encap) features &= skb->dev->hw_enc_features; SKB_GSO_CB(skb)->encap_level += ihl; skb_reset_transport_header(skb); segs = ERR_PTR(-EPROTONOSUPPORT); if (!skb->encapsulation || encap) { udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP); fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID); /* fixed ID is invalid if DF bit is not set */ if (fixedid && !(ip_hdr(skb)->frag_off & htons(IP_DF))) goto out; } ops = rcu_dereference(inet_offloads[proto]); if (likely(ops && ops->callbacks.gso_segment)) segs = ops->callbacks.gso_segment(skb, features); if (IS_ERR_OR_NULL(segs)) goto out; gso_partial = !!(skb_shinfo(segs)->gso_type & SKB_GSO_PARTIAL); skb = segs; do { iph = (struct iphdr *)(skb_mac_header(skb) + nhoff); if (udpfrag) { iph->frag_off = htons(offset >> 3); if (skb->next) iph->frag_off |= htons(IP_MF); offset += skb->len - nhoff - ihl; tot_len = skb->len - nhoff; } else if (skb_is_gso(skb)) { if (!fixedid) { iph->id = htons(id); id += skb_shinfo(skb)->gso_segs; } if (gso_partial) tot_len = skb_shinfo(skb)->gso_size + SKB_GSO_CB(skb)->data_offset + skb->head - (unsigned char *)iph; else tot_len = skb->len - nhoff; } else { if (!fixedid) iph->id = htons(id++); tot_len = skb->len - nhoff; } iph->tot_len = htons(tot_len); ip_send_check(iph); if (encap) skb_reset_inner_headers(skb); skb->network_header = (u8 *)iph - skb->head; } while ((skb = skb->next)); out: return segs; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Xu20936.60%313.04%
Alexander Duyck13623.82%28.70%
Eric Dumazet11319.79%417.39%
Sridhar Samudrala417.18%14.35%
Steffen Klassert305.25%14.35%
Hannes Frederic Sowa152.63%14.35%
Arnaldo Carvalho de Melo91.58%28.70%
Vlad Yasevich61.05%28.70%
David S. Miller50.88%14.35%
Pravin B Shelar30.53%28.70%
Florian Westphal10.18%14.35%
Hideaki Yoshifuji / 吉藤英明10.18%14.35%
Michał Mirosław10.18%14.35%
Alexey Dobriyan10.18%14.35%
Total571100.00%23100.00%

EXPORT_SYMBOL(inet_gso_segment);
struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb) { const struct net_offload *ops; struct sk_buff **pp = NULL; struct sk_buff *p; const struct iphdr *iph; unsigned int hlen; unsigned int off; unsigned int id; int flush = 1; int proto; off = skb_gro_offset(skb); hlen = off + sizeof(*iph); iph = skb_gro_header_fast(skb, off); if (skb_gro_header_hard(skb, hlen)) { iph = skb_gro_header_slow(skb, hlen, off); if (unlikely(!iph)) goto out; } proto = iph->protocol; rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); if (!ops || !ops->callbacks.gro_receive) goto out_unlock; if (*(u8 *)iph != 0x45) goto out_unlock; if (ip_is_fragment(iph)) goto out_unlock; if (unlikely(ip_fast_csum((u8 *)iph, 5))) goto out_unlock; id = ntohl(*(__be32 *)&iph->id); flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); id >>= 16; for (p = *head; p; p = p->next) { struct iphdr *iph2; u16 flush_id; if (!NAPI_GRO_CB(p)->same_flow) continue; iph2 = (struct iphdr *)(p->data + off); /* The above works because, with the exception of the top * (inner most) layer, we only aggregate pkts with the same * hdr length so all the hdrs we'll need to verify will start * at the same offset. */ if ((iph->protocol ^ iph2->protocol) | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { NAPI_GRO_CB(p)->same_flow = 0; continue; } /* All fields must match except length and checksum. */ NAPI_GRO_CB(p)->flush |= (iph->ttl ^ iph2->ttl) | (iph->tos ^ iph2->tos) | ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)); NAPI_GRO_CB(p)->flush |= flush; /* We need to store of the IP ID check to be included later * when we can verify that this packet does in fact belong * to a given flow. */ flush_id = (u16)(id - ntohs(iph2->id)); /* This bit of code makes it much easier for us to identify * the cases where we are doing atomic vs non-atomic IP ID * checks. Specifically an atomic check can return IP ID * values 0 - 0xFFFF, while a non-atomic check can only * return 0 or 0xFFFF. */ if (!NAPI_GRO_CB(p)->is_atomic || !(iph->frag_off & htons(IP_DF))) { flush_id ^= NAPI_GRO_CB(p)->count; flush_id = flush_id ? 0xFFFF : 0; } /* If the previous IP ID value was based on an atomic * datagram we can overwrite the value and ignore it. */ if (NAPI_GRO_CB(skb)->is_atomic) NAPI_GRO_CB(p)->flush_id = flush_id; else NAPI_GRO_CB(p)->flush_id |= flush_id; } NAPI_GRO_CB(skb)->is_atomic = !!(iph->frag_off & htons(IP_DF)); NAPI_GRO_CB(skb)->flush |= flush; skb_set_network_header(skb, off); /* The above will be needed by the transport layer if there is one * immediately following this IP hdr. */ /* Note : No need to call skb_gro_postpull_rcsum() here, * as we already checked checksum over ipv4 header was 0 */ skb_gro_pull(skb, sizeof(*iph)); skb_set_transport_header(skb, skb_gro_offset(skb)); pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); out_unlock: rcu_read_unlock(); out: skb_gro_flush_final(skb, pp, flush); return pp; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Xu40868.34%525.00%
Alexander Duyck8814.74%15.00%
Eric Dumazet477.87%630.00%
Jerry Chu294.86%210.00%
Steffen Klassert152.51%210.00%
Vlad Yasevich61.01%210.00%
Sabrina Dubroca30.50%15.00%
Alexey Dobriyan10.17%15.00%
Total597100.00%20100.00%

EXPORT_SYMBOL(inet_gro_receive);
static struct sk_buff **ipip_gro_receive(struct sk_buff **head, struct sk_buff *skb) { if (NAPI_GRO_CB(skb)->encap_mark) { NAPI_GRO_CB(skb)->flush = 1; return NULL; } NAPI_GRO_CB(skb)->encap_mark = 1; return inet_gro_receive(head, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Jesse Gross60100.00%1100.00%
Total60100.00%1100.00%

#define SECONDS_PER_DAY 86400 /* inet_current_timestamp - Return IP network timestamp * * Return milliseconds since midnight in network byte order. */
__be32 inet_current_timestamp(void) { u32 secs; u32 msecs; struct timespec64 ts; ktime_get_real_ts64(&ts); /* Get secs since midnight. */ (void)div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, &secs); /* Convert to msecs. */ msecs = secs * MSEC_PER_SEC; /* Convert nsec to msec. */ msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC; /* Convert to network byte order. */ return htonl(msecs); }

Contributors

PersonTokensPropCommitsCommitProp
Deepa Dinamani65100.00%2100.00%
Total65100.00%2100.00%

EXPORT_SYMBOL(inet_current_timestamp);
int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) { if (sk->sk_family == AF_INET) return ip_recv_error(sk, msg, len, addr_len); #if IS_ENABLED(CONFIG_IPV6) if (sk->sk_family == AF_INET6) return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len); #endif return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Willem de Bruijn76100.00%1100.00%
Total76100.00%1100.00%


int inet_gro_complete(struct sk_buff *skb, int nhoff) { __be16 newlen = htons(skb->len - nhoff); struct iphdr *iph = (struct iphdr *)(skb->data + nhoff); const struct net_offload *ops; int proto = iph->protocol; int err = -ENOSYS; if (skb->encapsulation) { skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IP)); skb_set_inner_network_header(skb, nhoff); } csum_replace2(&iph->check, iph->tot_len, newlen); iph->tot_len = newlen; rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); if (WARN_ON(!ops || !ops->callbacks.gro_complete)) goto out_unlock; /* Only need to add sizeof(*iph) to get to the next hdr below * because any hdr with option will have been flushed in * inet_gro_receive(). */ err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph)); out_unlock: rcu_read_unlock(); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Xu9657.83%114.29%
Jerry Chu3722.29%228.57%
David S. Miller159.04%114.29%
Paolo Abeni127.23%114.29%
Vlad Yasevich63.61%228.57%
Total166100.00%7100.00%

EXPORT_SYMBOL(inet_gro_complete);
static int ipip_gro_complete(struct sk_buff *skb, int nhoff) { skb->encapsulation = 1; skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4; return inet_gro_complete(skb, nhoff); }

Contributors

PersonTokensPropCommitsCommitProp
Jesse Gross3697.30%150.00%
Tom Herbert12.70%150.00%
Total37100.00%2100.00%


int inet_ctl_sock_create(struct sock **sk, unsigned short family, unsigned short type, unsigned char protocol, struct net *net) { struct socket *sock; int rc = sock_create_kern(net, family, type, protocol, &sock); if (rc == 0) { *sk = sock->sk; (*sk)->sk_allocation = GFP_ATOMIC; /* * Unhash it so that IP input processing does not even see it, * we do not wish this socket to see incoming packets. */ (*sk)->sk_prot->unhash(*sk); } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Denis V. Lunev8997.80%360.00%
Eric W. Biedermann22.20%240.00%
Total91100.00%5100.00%

EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt) { return *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt); }

Contributors

PersonTokensPropCommitsCommitProp
Raghavendra K T36100.00%1100.00%
Total36100.00%1100.00%

EXPORT_SYMBOL_GPL(snmp_get_cpu_field);
unsigned long snmp_fold_field(void __percpu *mib, int offt) { unsigned long res = 0; int i; for_each_possible_cpu(i) res += snmp_get_cpu_field(mib, i, offt); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Xu3790.24%133.33%
Raghavendra K T37.32%133.33%
Tejun Heo12.44%133.33%
Total41100.00%3100.00%

EXPORT_SYMBOL_GPL(snmp_fold_field); #if BITS_PER_LONG==32
u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offt, size_t syncp_offset) { void *bhptr; struct u64_stats_sync *syncp; u64 v; unsigned int start; bhptr = per_cpu_ptr(mib, cpu); syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); do { start = u64_stats_fetch_begin_irq(syncp); v = *(((u64 *)bhptr) + offt); } while (u64_stats_fetch_retry_irq(syncp, start)); return v; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet8488.42%240.00%
Raghavendra K T88.42%120.00%
Eric W. Biedermann22.11%120.00%
David S. Miller11.05%120.00%
Total95100.00%5100.00%

EXPORT_SYMBOL_GPL(snmp_get_cpu_field64);
u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_offset) { u64 res = 0; int cpu; for_each_possible_cpu(cpu) { res += snmp_get_cpu_field64(mib, cpu, offt, syncp_offset); } return res; }

Contributors

PersonTokensPropCommitsCommitProp
Raghavendra K T3678.26%125.00%
Eric Dumazet817.39%125.00%
David S. Miller12.17%125.00%
Madalin Bucur12.17%125.00%
Total46100.00%4100.00%

EXPORT_SYMBOL_GPL(snmp_fold_field64); #endif #ifdef CONFIG_IP_MULTICAST static const struct net_protocol igmp_protocol = { .handler = igmp_rcv, .netns_ok = 1, }; #endif static const struct net_protocol tcp_protocol = { .early_demux = tcp_v4_early_demux, .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .no_policy = 1, .netns_ok = 1, .icmp_strict_tag_validation = 1, }; static const struct net_protocol udp_protocol = { .early_demux = udp_v4_early_demux, .handler = udp_rcv, .err_handler = udp_err, .no_policy = 1, .netns_ok = 1, }; static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, .err_handler = icmp_err, .no_policy = 1, .netns_ok = 1, };
static __net_init int ipv4_mib_init_net(struct net *net) { int i; net->mib.tcp_statistics = alloc_percpu(struct tcp_mib); if (!net->mib.tcp_statistics) goto err_tcp_mib; net->mib.ip_statistics = alloc_percpu(struct ipstats_mib); if (!net->mib.ip_statistics) goto err_ip_mib; for_each_possible_cpu(i) { struct ipstats_mib *af_inet_stats; af_inet_stats = per_cpu_ptr(net->mib.ip_statistics, i); u64_stats_init(&af_inet_stats->syncp); } net->mib.net_statistics = alloc_percpu(struct linux_mib); if (!net->mib.net_statistics) goto err_net_mib; net->mib.udp_statistics = alloc_percpu(struct udp_mib); if (!net->mib.udp_statistics) goto err_udp_mib; net->mib.udplite_statistics = alloc_percpu(struct udp_mib); if (!net->mib.udplite_statistics) goto err_udplite_mib; net->mib.icmp_statistics = alloc_percpu(struct icmp_mib); if (!net->mib.icmp_statistics) goto err_icmp_mib; net->mib.icmpmsg_statistics = kzalloc(sizeof(struct icmpmsg_mib), GFP_KERNEL); if (!net->mib.icmpmsg_statistics) goto err_icmpmsg_mib; tcp_mib_init(net); return 0; err_icmpmsg_mib: free_percpu(net->mib.icmp_statistics); err_icmp_mib: free_percpu(net->mib.udplite_statistics); err_udplite_mib: free_percpu(net->mib.udp_statistics); err_udp_mib: free_percpu(net->mib.net_statistics); err_net_mib: free_percpu(net->mib.ip_statistics); err_ip_mib: free_percpu(net->mib.tcp_statistics); err_tcp_mib: return -ENOMEM; }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov15752.33%866.67%
Américo Wang6822.67%18.33%
John Stultz4113.67%18.33%
Eric Dumazet3411.33%216.67%
Total300100.00%12100.00%


static __net_exit void ipv4_mib_exit_net(struct net *net) { kfree(net->mib.icmpmsg_statistics); free_percpu(net->mib.icmp_statistics); free_percpu(net->mib.udplite_statistics); free_percpu(net->mib.udp_statistics); free_percpu(net->mib.net_statistics); free_percpu(net->mib.ip_statistics); free_percpu(net->mib.tcp_statistics); }

Contributors

PersonTokensPropCommitsCommitProp
Pavel Emelyanov6890.67%880.00%
Américo Wang68.00%110.00%
Eric Dumazet11.33%110.00%
Total75100.00%10100.00%

static __net_initdata struct pernet_operations ipv4_mib_ops = { .init = ipv4_mib_init_net, .exit = ipv4_mib_exit_net, };
static int __init init_ipv4_mibs(void) { return register_pernet_subsys(&ipv4_mib_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Ravikiran G. Thirumalai1062.50%133.33%
Pavel Emelyanov637.50%266.67%
Total16100.00%3100.00%


static __net_init int inet_init_net(struct net *net) { /* * Set defaults for local port range */ seqlock_init(&net->ipv4.ip_local_ports.lock); net->ipv4.ip_local_ports.range[0] = 32768; net->ipv4.ip_local_ports.range[1] = 60999; seqlock_init(&net->ipv4.ping_group_range.lock); /* * Sane defaults - nobody may create ping sockets. * Boot scripts should set this to distro-specific group. */ net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1); net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0); /* Default values for sysctl-controlled parameters. * We set them here, in case sysctl is not compiled. */ net->ipv4.sysctl_ip_default_ttl = IPDEFTTL; net->ipv4.sysctl_ip_dynaddr = 0; net->ipv4.sysctl_ip_early_demux = 1; #ifdef CONFIG_SYSCTL net->ipv4.sysctl_ip_prot_sock = PROT_SOCK; #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Américo Wang10472.73%240.00%
Ezequiel García2517.48%120.00%
Krister Johansen139.09%120.00%
Eric Dumazet10.70%120.00%
Total143100.00%5100.00%


static __net_exit void inet_exit_net(struct net *net) { }

Contributors

PersonTokensPropCommitsCommitProp
Américo Wang11100.00%1100.00%
Total11100.00%1100.00%

static __net_initdata struct pernet_operations af_inet_ops = { .init = inet_init_net, .exit = inet_exit_net, };
static int __init init_inet_pernet_ops(void) { return register_pernet_subsys(&af_inet_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Américo Wang16100.00%1100.00%
Total16100.00%1100.00%

static int ipv4_proc_init(void); /* * IP protocol layer initialiser */ static struct packet_offload ip_packet_offload __read_mostly = { .type = cpu_to_be16(ETH_P_IP), .callbacks = { .gso_segment = inet_gso_segment, .gro_receive = inet_gro_receive, .gro_complete = inet_gro_complete, }, }; static const struct net_offload ipip_offload = { .callbacks = { .gso_segment = inet_gso_segment, .gro_receive = ipip_gro_receive, .gro_complete = ipip_gro_complete, }, };
static int __init ipv4_offload_init(void) { /* * Add offloads */ if (udpv4_offload_init() < 0) pr_crit("%s: Cannot add UDP protocol offload\n", __func__); if (tcpv4_offload_init() < 0) pr_crit("%s: Cannot add TCP protocol offload\n", __func__); dev_add_offload(&ip_packet_offload); inet_add_offload(&ipip_offload, IPPROTO_IPIP); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vlad Yasevich4276.36%125.00%
Eric Dumazet814.55%125.00%
Daniel Borkmann59.09%250.00%
Total55100.00%4100.00%

fs_initcall(ipv4_offload_init); static struct packet_type ip_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IP), .func = ip_rcv, };
static int __init inet_init(void) { struct inet_protosw *q; struct list_head *r; int rc = -EINVAL; sock_skb_cb_check_size(sizeof(struct inet_skb_parm)); rc = proto_register(&tcp_prot, 1); if (rc) goto out; rc = proto_register(&udp_prot, 1); if (rc) goto out_unregister_tcp_proto; rc = proto_register(&raw_prot, 1); if (rc) goto out_unregister_udp_proto; rc = proto_register(&ping_prot, 1); if (rc) goto out_unregister_raw_proto; /* * Tell SOCKET that we are alive... */ (void)sock_register(&inet_family_ops); #ifdef CONFIG_SYSCTL ip_static_sysctl_init(); #endif /* * Add all the base protocols. */ if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) pr_crit("%s: Cannot add ICMP protocol\n", __func__); if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) pr_crit("%s: Cannot add UDP protocol\n", __func__); if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) pr_crit("%s: Cannot add TCP protocol\n", __func__); #ifdef CONFIG_IP_MULTICAST if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) pr_crit("%s: Cannot add IGMP protocol\n", __func__); #endif /* Register the socket-side information for inet_create. */ for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) INIT_LIST_HEAD(r); for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) inet_register_protosw(q); /* * Set the ARP module up */ arp_init(); /* * Set the IP module up */ ip_init(); /* Setup TCP slab cache for open requests. */ tcp_init(); /* Setup UDP memory threshold */ udp_init(); /* Add UDP-Lite (RFC 3828) */ udplite4_register(); ping_init(); /* * Set the ICMP layer up */ if (icmp_init() < 0) panic("Failed to create the ICMP control socket.\n"); /* * Initialise the multicast router */ #if defined(CONFIG_IP_MROUTE) if (ip_mr_init()) pr_crit("%s: Cannot init ipv4 mroute\n", __func__); #endif if (init_inet_pernet_ops()) pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__); /* * Initialise per-cpu ipv4 mibs */ if (init_ipv4_mibs()) pr_crit("%s: Cannot init ipv4 mibs\n", __func__); ipv4_proc_init(); ipfrag_init(); dev_add_pack(&ip_packet_type); ip_tunnel_core_init(); rc = 0; out: return rc; out_unregister_raw_proto: proto_unregister(&raw_prot); out_unregister_udp_proto: proto_unregister(&udp_prot); out_unregister_tcp_proto: proto_unregister(&tcp_prot); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
David S. Miller7419.27%39.38%
Linus Torvalds (pre-git)6617.19%825.00%
Arnaldo Carvalho de Melo6416.67%39.38%
Linus Torvalds5815.10%13.12%
Vasiliy Kulikov287.29%13.12%
Joe Perches246.25%13.12%
Américo Wang133.39%26.25%
Denis V. Lunev102.60%26.25%
Ravikiran G. Thirumalai92.34%13.12%
Al Viro82.08%13.12%
Herbert Xu61.56%13.12%
Wang Chen51.30%13.12%
Olaf Kirch41.04%13.12%
Gerrit Renker41.04%13.12%
Hideo Aoki41.04%13.12%
Thomas Graf30.78%13.12%
Hideaki Yoshifuji / 吉藤英明30.78%26.25%
Eyal Birger10.26%13.12%
Total384100.00%32100.00%

fs_initcall(inet_init); /* ------------------------------------------------------------------------ */ #ifdef CONFIG_PROC_FS
static int __init ipv4_proc_init(void) { int rc = 0; if (raw_proc_init()) goto out_raw; if (tcp4_proc_init()) goto out_tcp; if (udp4_proc_init()) goto out_udp; if (ping_proc_init()) goto out_ping; if (ip_misc_proc_init()) goto out_misc; out: return rc; out_misc: ping_proc_exit(); out_ping: udp4_proc_exit(); out_udp: tcp4_proc_exit(); out_tcp: raw_proc_exit(); out_raw: rc = -ENOMEM; goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo7179.78%450.00%
Vasiliy Kulikov1314.61%112.50%
Hideaki Yoshifuji / 吉藤英明44.49%225.00%
Adrian Bunk11.12%112.50%
Total89100.00%8100.00%

#else /* CONFIG_PROC_FS */
static int __init ipv4_proc_init(void) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo1191.67%150.00%
Adrian Bunk18.33%150.00%
Total12100.00%2100.00%

#endif /* CONFIG_PROC_FS */

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)216726.98%5617.50%
Arnaldo Carvalho de Melo82710.30%257.81%
Herbert Xu8009.96%123.75%
Eric Dumazet5677.06%299.06%
David S. Miller3704.61%206.25%
Linus Torvalds3674.57%51.56%
Pavel Emelyanov2543.16%113.44%
Américo Wang2473.08%51.56%
Alexander Duyck2242.79%30.94%
Denis V. Lunev1351.68%113.44%
Tom Herbert1341.67%51.56%
Alexey Kuznetsov1201.49%41.25%
Yuchung Cheng1151.43%30.94%
Eric W. Biedermann1141.42%92.81%
Vlad Yasevich1031.28%41.25%
Rusty Russell1021.27%10.31%
Jesse Gross981.22%20.62%
Mitchell Blank Jr.971.21%10.31%
Jerry Chu931.16%41.25%
Raghavendra K T931.16%10.31%
Vasiliy Kulikov770.96%10.31%
Willem de Bruijn760.95%10.31%
Deepa Dinamani750.93%20.62%
Sridhar Samudrala700.87%20.62%
David Ahern590.73%51.56%
Changli Gao510.63%20.62%
Steffen Klassert450.56%30.94%
John Stultz410.51%10.31%
Hannes Frederic Sowa390.49%51.56%
Joe Perches380.47%20.62%
Wei Wang370.46%10.31%
Stephen Hemminger300.37%72.19%
Ezequiel García250.31%10.31%
Ravikiran G. Thirumalai190.24%10.31%
Marcus Meissner180.22%20.62%
Craig Gallek170.21%10.31%
Al Viro170.21%51.56%
Krister Johansen170.21%10.31%
Hideaki Yoshifuji / 吉藤英明150.19%61.88%
Nikolay Borisov140.17%10.31%
Paolo Abeni120.15%10.31%
Eric Paris110.14%30.94%
Alexey Dobriyan110.14%20.62%
Willy Tarreau100.12%10.31%
Ilpo Järvinen90.11%10.31%
Hideo Aoki90.11%10.31%
Junwei (Martin) Zhang80.10%10.31%
Gerrit Renker80.10%20.62%
Cyrill V. Gorcunov70.09%10.31%
Paul E. McKenney70.09%10.31%
Nivedita Singhvi60.07%10.31%
Tóth László Attila60.07%10.31%
Jiri Olsa60.07%10.31%
Thomas Graf60.07%10.31%
Christoph Hellwig60.07%20.62%
Jiri Benc60.07%10.31%
Daniel Borkmann50.06%20.62%
Christoph Paasch50.06%10.31%
Wang Chen50.06%10.31%
David Howells50.06%10.31%
Jens Axboe50.06%10.31%
Harvey Harrison50.06%30.94%
Andi Kleen50.06%10.31%
Shawn Bohrer50.06%10.31%
samanthakumar50.06%10.31%
Paul Moore40.05%20.62%
James Morris40.05%10.31%
Thomas Gleixner40.05%10.31%
Tejun Heo40.05%20.62%
Adrian Bunk40.05%20.62%
Olaf Kirch40.05%10.31%
Vincent Bernat40.05%10.31%
Pravin B Shelar30.04%20.62%
Ian Morris30.04%10.31%
Sabrina Dubroca30.04%10.31%
Randy Dunlap30.04%10.31%
Venkat Yekkirala20.02%10.31%
Madalin Bucur10.01%10.31%
Eyal Birger10.01%10.31%
Heiko Carstens10.01%10.31%
Florian Westphal10.01%10.31%
Cheng Renquan10.01%10.31%
Li Wei10.01%10.31%
Atis Elsts10.01%10.31%
Paul Gortmaker10.01%10.31%
Michał Mirosław10.01%10.31%
Patrick McHardy10.01%10.31%
Total8032100.00%320100.00%
Directory: net/ipv4
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.