162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 462306a36Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 562306a36Sopenharmony_ci * interface as the means of communication with the user level. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * PF_INET protocol family socket handler. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Authors: Ross Biro 1062306a36Sopenharmony_ci * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 1162306a36Sopenharmony_ci * Florian La Roche, <flla@stud.uni-sb.de> 1262306a36Sopenharmony_ci * Alan Cox, <A.Cox@swansea.ac.uk> 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Changes (see also sock.c) 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * piggy, 1762306a36Sopenharmony_ci * Karl Knutson : Socket protocol table 1862306a36Sopenharmony_ci * A.N.Kuznetsov : Socket death error in accept(). 1962306a36Sopenharmony_ci * John Richardson : Fix non blocking error in connect() 2062306a36Sopenharmony_ci * so sockets that fail to connect 2162306a36Sopenharmony_ci * don't return -EINPROGRESS. 2262306a36Sopenharmony_ci * Alan Cox : Asynchronous I/O support 2362306a36Sopenharmony_ci * Alan Cox : Keep correct socket pointer on sock 2462306a36Sopenharmony_ci * structures 2562306a36Sopenharmony_ci * when accept() ed 2662306a36Sopenharmony_ci * Alan Cox : Semantics of SO_LINGER aren't state 2762306a36Sopenharmony_ci * moved to close when you look carefully. 2862306a36Sopenharmony_ci * With this fixed and the accept bug fixed 2962306a36Sopenharmony_ci * some RPC stuff seems happier. 3062306a36Sopenharmony_ci * Niibe Yutaka : 4.4BSD style write async I/O 3162306a36Sopenharmony_ci * Alan Cox, 3262306a36Sopenharmony_ci * Tony Gale : Fixed reuse semantics. 3362306a36Sopenharmony_ci * Alan Cox : bind() shouldn't abort existing but dead 3462306a36Sopenharmony_ci * sockets. Stops FTP netin:.. I hope. 3562306a36Sopenharmony_ci * Alan Cox : bind() works correctly for RAW sockets. 3662306a36Sopenharmony_ci * Note that FreeBSD at least was broken 3762306a36Sopenharmony_ci * in this respect so be careful with 3862306a36Sopenharmony_ci * compatibility tests... 3962306a36Sopenharmony_ci * Alan Cox : routing cache support 4062306a36Sopenharmony_ci * Alan Cox : memzero the socket structure for 4162306a36Sopenharmony_ci * compactness. 4262306a36Sopenharmony_ci * Matt Day : nonblock connect error handler 4362306a36Sopenharmony_ci * Alan Cox : Allow large numbers of pending sockets 4462306a36Sopenharmony_ci * (eg for big web sites), but only if 4562306a36Sopenharmony_ci * specifically application requested. 4662306a36Sopenharmony_ci * Alan Cox : New buffering throughout IP. Used 4762306a36Sopenharmony_ci * dumbly. 4862306a36Sopenharmony_ci * Alan Cox : New buffering now used smartly. 4962306a36Sopenharmony_ci * Alan Cox : BSD rather than common sense 5062306a36Sopenharmony_ci * interpretation of listen. 5162306a36Sopenharmony_ci * Germano Caronni : Assorted small races. 5262306a36Sopenharmony_ci * Alan Cox : sendmsg/recvmsg basic support. 5362306a36Sopenharmony_ci * Alan Cox : Only sendmsg/recvmsg now supported. 5462306a36Sopenharmony_ci * Alan Cox : Locked down bind (see security list). 5562306a36Sopenharmony_ci * Alan Cox : Loosened bind a little. 5662306a36Sopenharmony_ci * Mike McLagan : ADD/DEL DLCI Ioctls 5762306a36Sopenharmony_ci * Willy Konynenberg : Transparent proxying support. 5862306a36Sopenharmony_ci * David S. Miller : New socket lookup architecture. 5962306a36Sopenharmony_ci * Some other random speedups. 6062306a36Sopenharmony_ci * Cyrus Durgin : Cleaned up file for kmod hacks. 6162306a36Sopenharmony_ci * Andi Kleen : Fix inet_stream_connect TCP race. 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define pr_fmt(fmt) "IPv4: " fmt 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#include <linux/err.h> 6762306a36Sopenharmony_ci#include <linux/errno.h> 6862306a36Sopenharmony_ci#include <linux/types.h> 6962306a36Sopenharmony_ci#include <linux/socket.h> 7062306a36Sopenharmony_ci#include <linux/in.h> 7162306a36Sopenharmony_ci#include <linux/kernel.h> 7262306a36Sopenharmony_ci#include <linux/kmod.h> 7362306a36Sopenharmony_ci#include <linux/sched.h> 7462306a36Sopenharmony_ci#include <linux/timer.h> 7562306a36Sopenharmony_ci#include <linux/string.h> 7662306a36Sopenharmony_ci#include <linux/sockios.h> 7762306a36Sopenharmony_ci#include <linux/net.h> 7862306a36Sopenharmony_ci#include <linux/capability.h> 7962306a36Sopenharmony_ci#include <linux/fcntl.h> 8062306a36Sopenharmony_ci#include <linux/mm.h> 8162306a36Sopenharmony_ci#include <linux/interrupt.h> 8262306a36Sopenharmony_ci#include <linux/stat.h> 8362306a36Sopenharmony_ci#include <linux/init.h> 8462306a36Sopenharmony_ci#include <linux/poll.h> 8562306a36Sopenharmony_ci#include <linux/netfilter_ipv4.h> 8662306a36Sopenharmony_ci#include <linux/random.h> 8762306a36Sopenharmony_ci#include <linux/slab.h> 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#include <linux/uaccess.h> 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#include <linux/inet.h> 9262306a36Sopenharmony_ci#include <linux/igmp.h> 9362306a36Sopenharmony_ci#include <linux/inetdevice.h> 9462306a36Sopenharmony_ci#include <linux/netdevice.h> 9562306a36Sopenharmony_ci#include <net/checksum.h> 9662306a36Sopenharmony_ci#include <net/ip.h> 9762306a36Sopenharmony_ci#include <net/protocol.h> 9862306a36Sopenharmony_ci#include <net/arp.h> 9962306a36Sopenharmony_ci#include <net/route.h> 10062306a36Sopenharmony_ci#include <net/ip_fib.h> 10162306a36Sopenharmony_ci#include <net/inet_connection_sock.h> 10262306a36Sopenharmony_ci#include <net/gro.h> 10362306a36Sopenharmony_ci#include <net/gso.h> 10462306a36Sopenharmony_ci#include <net/tcp.h> 10562306a36Sopenharmony_ci#include <net/udp.h> 10662306a36Sopenharmony_ci#include <net/udplite.h> 10762306a36Sopenharmony_ci#include <net/ping.h> 10862306a36Sopenharmony_ci#include <linux/skbuff.h> 10962306a36Sopenharmony_ci#include <net/sock.h> 11062306a36Sopenharmony_ci#include <net/raw.h> 11162306a36Sopenharmony_ci#include <net/icmp.h> 11262306a36Sopenharmony_ci#include <net/inet_common.h> 11362306a36Sopenharmony_ci#include <net/ip_tunnels.h> 11462306a36Sopenharmony_ci#include <net/xfrm.h> 11562306a36Sopenharmony_ci#include <net/net_namespace.h> 11662306a36Sopenharmony_ci#include <net/secure_seq.h> 11762306a36Sopenharmony_ci#ifdef CONFIG_IP_MROUTE 11862306a36Sopenharmony_ci#include <linux/mroute.h> 11962306a36Sopenharmony_ci#endif 12062306a36Sopenharmony_ci#include <net/l3mdev.h> 12162306a36Sopenharmony_ci#include <net/compat.h> 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#include <trace/events/sock.h> 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* The inetsw table contains everything that inet_create needs to 12662306a36Sopenharmony_ci * build a new socket. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_cistatic struct list_head inetsw[SOCK_MAX]; 12962306a36Sopenharmony_cistatic DEFINE_SPINLOCK(inetsw_lock); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* New destruction routine */ 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_civoid inet_sock_destruct(struct sock *sk) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci __skb_queue_purge(&sk->sk_receive_queue); 13862306a36Sopenharmony_ci __skb_queue_purge(&sk->sk_error_queue); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci sk_mem_reclaim_final(sk); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) { 14362306a36Sopenharmony_ci pr_err("Attempt to release TCP socket in state %d %p\n", 14462306a36Sopenharmony_ci sk->sk_state, sk); 14562306a36Sopenharmony_ci return; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci if (!sock_flag(sk, SOCK_DEAD)) { 14862306a36Sopenharmony_ci pr_err("Attempt to release alive inet socket %p\n", sk); 14962306a36Sopenharmony_ci return; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci WARN_ON_ONCE(atomic_read(&sk->sk_rmem_alloc)); 15362306a36Sopenharmony_ci WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc)); 15462306a36Sopenharmony_ci WARN_ON_ONCE(sk->sk_wmem_queued); 15562306a36Sopenharmony_ci WARN_ON_ONCE(sk_forward_alloc_get(sk)); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci kfree(rcu_dereference_protected(inet->inet_opt, 1)); 15862306a36Sopenharmony_ci dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1)); 15962306a36Sopenharmony_ci dst_release(rcu_dereference_protected(sk->sk_rx_dst, 1)); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ciEXPORT_SYMBOL(inet_sock_destruct); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/* 16462306a36Sopenharmony_ci * The routines beyond this point handle the behaviour of an AF_INET 16562306a36Sopenharmony_ci * socket object. Mostly it punts to the subprotocols of IP to do 16662306a36Sopenharmony_ci * the work. 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/* 17062306a36Sopenharmony_ci * Automatically bind an unbound socket. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic int inet_autobind(struct sock *sk) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct inet_sock *inet; 17662306a36Sopenharmony_ci /* We may need to bind the socket. */ 17762306a36Sopenharmony_ci lock_sock(sk); 17862306a36Sopenharmony_ci inet = inet_sk(sk); 17962306a36Sopenharmony_ci if (!inet->inet_num) { 18062306a36Sopenharmony_ci if (sk->sk_prot->get_port(sk, 0)) { 18162306a36Sopenharmony_ci release_sock(sk); 18262306a36Sopenharmony_ci return -EAGAIN; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci inet->inet_sport = htons(inet->inet_num); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci release_sock(sk); 18762306a36Sopenharmony_ci return 0; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciint __inet_listen_sk(struct sock *sk, int backlog) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci unsigned char old_state = sk->sk_state; 19362306a36Sopenharmony_ci int err, tcp_fastopen; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN))) 19662306a36Sopenharmony_ci return -EINVAL; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci WRITE_ONCE(sk->sk_max_ack_backlog, backlog); 19962306a36Sopenharmony_ci /* Really, if the socket is already in listen state 20062306a36Sopenharmony_ci * we can only allow the backlog to be adjusted. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci if (old_state != TCP_LISTEN) { 20362306a36Sopenharmony_ci /* Enable TFO w/o requiring TCP_FASTOPEN socket option. 20462306a36Sopenharmony_ci * Note that only TCP sockets (SOCK_STREAM) will reach here. 20562306a36Sopenharmony_ci * Also fastopen backlog may already been set via the option 20662306a36Sopenharmony_ci * because the socket was in TCP_LISTEN state previously but 20762306a36Sopenharmony_ci * was shutdown() rather than close(). 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci tcp_fastopen = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fastopen); 21062306a36Sopenharmony_ci if ((tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) && 21162306a36Sopenharmony_ci (tcp_fastopen & TFO_SERVER_ENABLE) && 21262306a36Sopenharmony_ci !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) { 21362306a36Sopenharmony_ci fastopen_queue_tune(sk, backlog); 21462306a36Sopenharmony_ci tcp_fastopen_init_key_once(sock_net(sk)); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci err = inet_csk_listen_start(sk); 21862306a36Sopenharmony_ci if (err) 21962306a36Sopenharmony_ci return err; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_LISTEN_CB, 0, NULL); 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* 22762306a36Sopenharmony_ci * Move a socket into listening state. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ciint inet_listen(struct socket *sock, int backlog) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct sock *sk = sock->sk; 23262306a36Sopenharmony_ci int err = -EINVAL; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci lock_sock(sk); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM) 23762306a36Sopenharmony_ci goto out; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci err = __inet_listen_sk(sk, backlog); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ciout: 24262306a36Sopenharmony_ci release_sock(sk); 24362306a36Sopenharmony_ci return err; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ciEXPORT_SYMBOL(inet_listen); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci/* 24862306a36Sopenharmony_ci * Create an inet socket. 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int inet_create(struct net *net, struct socket *sock, int protocol, 25262306a36Sopenharmony_ci int kern) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct sock *sk; 25562306a36Sopenharmony_ci struct inet_protosw *answer; 25662306a36Sopenharmony_ci struct inet_sock *inet; 25762306a36Sopenharmony_ci struct proto *answer_prot; 25862306a36Sopenharmony_ci unsigned char answer_flags; 25962306a36Sopenharmony_ci int try_loading_module = 0; 26062306a36Sopenharmony_ci int err; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (protocol < 0 || protocol >= IPPROTO_MAX) 26362306a36Sopenharmony_ci return -EINVAL; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci sock->state = SS_UNCONNECTED; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* Look for the requested type/protocol pair. */ 26862306a36Sopenharmony_cilookup_protocol: 26962306a36Sopenharmony_ci err = -ESOCKTNOSUPPORT; 27062306a36Sopenharmony_ci rcu_read_lock(); 27162306a36Sopenharmony_ci list_for_each_entry_rcu(answer, &inetsw[sock->type], list) { 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci err = 0; 27462306a36Sopenharmony_ci /* Check the non-wild match. */ 27562306a36Sopenharmony_ci if (protocol == answer->protocol) { 27662306a36Sopenharmony_ci if (protocol != IPPROTO_IP) 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci } else { 27962306a36Sopenharmony_ci /* Check for the two wild cases. */ 28062306a36Sopenharmony_ci if (IPPROTO_IP == protocol) { 28162306a36Sopenharmony_ci protocol = answer->protocol; 28262306a36Sopenharmony_ci break; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci if (IPPROTO_IP == answer->protocol) 28562306a36Sopenharmony_ci break; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci err = -EPROTONOSUPPORT; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (unlikely(err)) { 29162306a36Sopenharmony_ci if (try_loading_module < 2) { 29262306a36Sopenharmony_ci rcu_read_unlock(); 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * Be more specific, e.g. net-pf-2-proto-132-type-1 29562306a36Sopenharmony_ci * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM) 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci if (++try_loading_module == 1) 29862306a36Sopenharmony_ci request_module("net-pf-%d-proto-%d-type-%d", 29962306a36Sopenharmony_ci PF_INET, protocol, sock->type); 30062306a36Sopenharmony_ci /* 30162306a36Sopenharmony_ci * Fall back to generic, e.g. net-pf-2-proto-132 30262306a36Sopenharmony_ci * (net-pf-PF_INET-proto-IPPROTO_SCTP) 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci else 30562306a36Sopenharmony_ci request_module("net-pf-%d-proto-%d", 30662306a36Sopenharmony_ci PF_INET, protocol); 30762306a36Sopenharmony_ci goto lookup_protocol; 30862306a36Sopenharmony_ci } else 30962306a36Sopenharmony_ci goto out_rcu_unlock; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci err = -EPERM; 31362306a36Sopenharmony_ci if (sock->type == SOCK_RAW && !kern && 31462306a36Sopenharmony_ci !ns_capable(net->user_ns, CAP_NET_RAW)) 31562306a36Sopenharmony_ci goto out_rcu_unlock; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci sock->ops = answer->ops; 31862306a36Sopenharmony_ci answer_prot = answer->prot; 31962306a36Sopenharmony_ci answer_flags = answer->flags; 32062306a36Sopenharmony_ci rcu_read_unlock(); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci WARN_ON(!answer_prot->slab); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci err = -ENOMEM; 32562306a36Sopenharmony_ci sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, kern); 32662306a36Sopenharmony_ci if (!sk) 32762306a36Sopenharmony_ci goto out; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci err = 0; 33062306a36Sopenharmony_ci if (INET_PROTOSW_REUSE & answer_flags) 33162306a36Sopenharmony_ci sk->sk_reuse = SK_CAN_REUSE; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (INET_PROTOSW_ICSK & answer_flags) 33462306a36Sopenharmony_ci inet_init_csk_locks(sk); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci inet = inet_sk(sk); 33762306a36Sopenharmony_ci inet_assign_bit(IS_ICSK, sk, INET_PROTOSW_ICSK & answer_flags); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci inet_clear_bit(NODEFRAG, sk); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (SOCK_RAW == sock->type) { 34262306a36Sopenharmony_ci inet->inet_num = protocol; 34362306a36Sopenharmony_ci if (IPPROTO_RAW == protocol) 34462306a36Sopenharmony_ci inet_set_bit(HDRINCL, sk); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (READ_ONCE(net->ipv4.sysctl_ip_no_pmtu_disc)) 34862306a36Sopenharmony_ci inet->pmtudisc = IP_PMTUDISC_DONT; 34962306a36Sopenharmony_ci else 35062306a36Sopenharmony_ci inet->pmtudisc = IP_PMTUDISC_WANT; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci atomic_set(&inet->inet_id, 0); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci sock_init_data(sock, sk); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci sk->sk_destruct = inet_sock_destruct; 35762306a36Sopenharmony_ci sk->sk_protocol = protocol; 35862306a36Sopenharmony_ci sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; 35962306a36Sopenharmony_ci sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci inet->uc_ttl = -1; 36262306a36Sopenharmony_ci inet_set_bit(MC_LOOP, sk); 36362306a36Sopenharmony_ci inet->mc_ttl = 1; 36462306a36Sopenharmony_ci inet_set_bit(MC_ALL, sk); 36562306a36Sopenharmony_ci inet->mc_index = 0; 36662306a36Sopenharmony_ci inet->mc_list = NULL; 36762306a36Sopenharmony_ci inet->rcv_tos = 0; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (inet->inet_num) { 37062306a36Sopenharmony_ci /* It assumes that any protocol which allows 37162306a36Sopenharmony_ci * the user to assign a number at socket 37262306a36Sopenharmony_ci * creation time automatically 37362306a36Sopenharmony_ci * shares. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci inet->inet_sport = htons(inet->inet_num); 37662306a36Sopenharmony_ci /* Add to protocol hash chains. */ 37762306a36Sopenharmony_ci err = sk->sk_prot->hash(sk); 37862306a36Sopenharmony_ci if (err) { 37962306a36Sopenharmony_ci sk_common_release(sk); 38062306a36Sopenharmony_ci goto out; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (sk->sk_prot->init) { 38562306a36Sopenharmony_ci err = sk->sk_prot->init(sk); 38662306a36Sopenharmony_ci if (err) { 38762306a36Sopenharmony_ci sk_common_release(sk); 38862306a36Sopenharmony_ci goto out; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (!kern) { 39362306a36Sopenharmony_ci err = BPF_CGROUP_RUN_PROG_INET_SOCK(sk); 39462306a36Sopenharmony_ci if (err) { 39562306a36Sopenharmony_ci sk_common_release(sk); 39662306a36Sopenharmony_ci goto out; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ciout: 40062306a36Sopenharmony_ci return err; 40162306a36Sopenharmony_ciout_rcu_unlock: 40262306a36Sopenharmony_ci rcu_read_unlock(); 40362306a36Sopenharmony_ci goto out; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/* 40862306a36Sopenharmony_ci * The peer socket should always be NULL (or else). When we call this 40962306a36Sopenharmony_ci * function we are destroying the object and from then on nobody 41062306a36Sopenharmony_ci * should refer to it. 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_ciint inet_release(struct socket *sock) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci struct sock *sk = sock->sk; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (sk) { 41762306a36Sopenharmony_ci long timeout; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (!sk->sk_kern_sock) 42062306a36Sopenharmony_ci BPF_CGROUP_RUN_PROG_INET_SOCK_RELEASE(sk); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* Applications forget to leave groups before exiting */ 42362306a36Sopenharmony_ci ip_mc_drop_socket(sk); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci /* If linger is set, we don't return until the close 42662306a36Sopenharmony_ci * is complete. Otherwise we return immediately. The 42762306a36Sopenharmony_ci * actually closing is done the same either way. 42862306a36Sopenharmony_ci * 42962306a36Sopenharmony_ci * If the close is due to the process exiting, we never 43062306a36Sopenharmony_ci * linger.. 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_ci timeout = 0; 43362306a36Sopenharmony_ci if (sock_flag(sk, SOCK_LINGER) && 43462306a36Sopenharmony_ci !(current->flags & PF_EXITING)) 43562306a36Sopenharmony_ci timeout = sk->sk_lingertime; 43662306a36Sopenharmony_ci sk->sk_prot->close(sk, timeout); 43762306a36Sopenharmony_ci sock->sk = NULL; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ciEXPORT_SYMBOL(inet_release); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ciint inet_bind_sk(struct sock *sk, struct sockaddr *uaddr, int addr_len) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci u32 flags = BIND_WITH_LOCK; 44662306a36Sopenharmony_ci int err; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* If the socket has its own bind function then use it. (RAW) */ 44962306a36Sopenharmony_ci if (sk->sk_prot->bind) { 45062306a36Sopenharmony_ci return sk->sk_prot->bind(sk, uaddr, addr_len); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci if (addr_len < sizeof(struct sockaddr_in)) 45362306a36Sopenharmony_ci return -EINVAL; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* BPF prog is run before any checks are done so that if the prog 45662306a36Sopenharmony_ci * changes context in a wrong way it will be caught. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ci err = BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, &addr_len, 45962306a36Sopenharmony_ci CGROUP_INET4_BIND, &flags); 46062306a36Sopenharmony_ci if (err) 46162306a36Sopenharmony_ci return err; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci return __inet_bind(sk, uaddr, addr_len, flags); 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ciint inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 46762306a36Sopenharmony_ci{ 46862306a36Sopenharmony_ci return inet_bind_sk(sock->sk, uaddr, addr_len); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ciEXPORT_SYMBOL(inet_bind); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ciint __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, 47362306a36Sopenharmony_ci u32 flags) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; 47662306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 47762306a36Sopenharmony_ci struct net *net = sock_net(sk); 47862306a36Sopenharmony_ci unsigned short snum; 47962306a36Sopenharmony_ci int chk_addr_ret; 48062306a36Sopenharmony_ci u32 tb_id = RT_TABLE_LOCAL; 48162306a36Sopenharmony_ci int err; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (addr->sin_family != AF_INET) { 48462306a36Sopenharmony_ci /* Compatibility games : accept AF_UNSPEC (mapped to AF_INET) 48562306a36Sopenharmony_ci * only if s_addr is INADDR_ANY. 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_ci err = -EAFNOSUPPORT; 48862306a36Sopenharmony_ci if (addr->sin_family != AF_UNSPEC || 48962306a36Sopenharmony_ci addr->sin_addr.s_addr != htonl(INADDR_ANY)) 49062306a36Sopenharmony_ci goto out; 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id; 49462306a36Sopenharmony_ci chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* Not specified by any standard per-se, however it breaks too 49762306a36Sopenharmony_ci * many applications when removed. It is unfortunate since 49862306a36Sopenharmony_ci * allowing applications to make a non-local bind solves 49962306a36Sopenharmony_ci * several problems with systems using dynamic addressing. 50062306a36Sopenharmony_ci * (ie. your servers still start up even if your ISDN link 50162306a36Sopenharmony_ci * is temporarily down) 50262306a36Sopenharmony_ci */ 50362306a36Sopenharmony_ci err = -EADDRNOTAVAIL; 50462306a36Sopenharmony_ci if (!inet_addr_valid_or_nonlocal(net, inet, addr->sin_addr.s_addr, 50562306a36Sopenharmony_ci chk_addr_ret)) 50662306a36Sopenharmony_ci goto out; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci snum = ntohs(addr->sin_port); 50962306a36Sopenharmony_ci err = -EACCES; 51062306a36Sopenharmony_ci if (!(flags & BIND_NO_CAP_NET_BIND_SERVICE) && 51162306a36Sopenharmony_ci snum && inet_port_requires_bind_service(net, snum) && 51262306a36Sopenharmony_ci !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) 51362306a36Sopenharmony_ci goto out; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* We keep a pair of addresses. rcv_saddr is the one 51662306a36Sopenharmony_ci * used by hash lookups, and saddr is used for transmit. 51762306a36Sopenharmony_ci * 51862306a36Sopenharmony_ci * In the BSD API these are the same except where it 51962306a36Sopenharmony_ci * would be illegal to use them (multicast/broadcast) in 52062306a36Sopenharmony_ci * which case the sending device address is used. 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ci if (flags & BIND_WITH_LOCK) 52362306a36Sopenharmony_ci lock_sock(sk); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* Check these errors (active socket, double bind). */ 52662306a36Sopenharmony_ci err = -EINVAL; 52762306a36Sopenharmony_ci if (sk->sk_state != TCP_CLOSE || inet->inet_num) 52862306a36Sopenharmony_ci goto out_release_sock; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr; 53162306a36Sopenharmony_ci if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) 53262306a36Sopenharmony_ci inet->inet_saddr = 0; /* Use device */ 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* Make sure we are allowed to bind here. */ 53562306a36Sopenharmony_ci if (snum || !(inet_test_bit(BIND_ADDRESS_NO_PORT, sk) || 53662306a36Sopenharmony_ci (flags & BIND_FORCE_ADDRESS_NO_PORT))) { 53762306a36Sopenharmony_ci err = sk->sk_prot->get_port(sk, snum); 53862306a36Sopenharmony_ci if (err) { 53962306a36Sopenharmony_ci inet->inet_saddr = inet->inet_rcv_saddr = 0; 54062306a36Sopenharmony_ci goto out_release_sock; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci if (!(flags & BIND_FROM_BPF)) { 54362306a36Sopenharmony_ci err = BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk); 54462306a36Sopenharmony_ci if (err) { 54562306a36Sopenharmony_ci inet->inet_saddr = inet->inet_rcv_saddr = 0; 54662306a36Sopenharmony_ci if (sk->sk_prot->put_port) 54762306a36Sopenharmony_ci sk->sk_prot->put_port(sk); 54862306a36Sopenharmony_ci goto out_release_sock; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (inet->inet_rcv_saddr) 55462306a36Sopenharmony_ci sk->sk_userlocks |= SOCK_BINDADDR_LOCK; 55562306a36Sopenharmony_ci if (snum) 55662306a36Sopenharmony_ci sk->sk_userlocks |= SOCK_BINDPORT_LOCK; 55762306a36Sopenharmony_ci inet->inet_sport = htons(inet->inet_num); 55862306a36Sopenharmony_ci inet->inet_daddr = 0; 55962306a36Sopenharmony_ci inet->inet_dport = 0; 56062306a36Sopenharmony_ci sk_dst_reset(sk); 56162306a36Sopenharmony_ci err = 0; 56262306a36Sopenharmony_ciout_release_sock: 56362306a36Sopenharmony_ci if (flags & BIND_WITH_LOCK) 56462306a36Sopenharmony_ci release_sock(sk); 56562306a36Sopenharmony_ciout: 56662306a36Sopenharmony_ci return err; 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ciint inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, 57062306a36Sopenharmony_ci int addr_len, int flags) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci struct sock *sk = sock->sk; 57362306a36Sopenharmony_ci const struct proto *prot; 57462306a36Sopenharmony_ci int err; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (addr_len < sizeof(uaddr->sa_family)) 57762306a36Sopenharmony_ci return -EINVAL; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci /* IPV6_ADDRFORM can change sk->sk_prot under us. */ 58062306a36Sopenharmony_ci prot = READ_ONCE(sk->sk_prot); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (uaddr->sa_family == AF_UNSPEC) 58362306a36Sopenharmony_ci return prot->disconnect(sk, flags); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (BPF_CGROUP_PRE_CONNECT_ENABLED(sk)) { 58662306a36Sopenharmony_ci err = prot->pre_connect(sk, uaddr, addr_len); 58762306a36Sopenharmony_ci if (err) 58862306a36Sopenharmony_ci return err; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (data_race(!inet_sk(sk)->inet_num) && inet_autobind(sk)) 59262306a36Sopenharmony_ci return -EAGAIN; 59362306a36Sopenharmony_ci return prot->connect(sk, uaddr, addr_len); 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ciEXPORT_SYMBOL(inet_dgram_connect); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic long inet_wait_for_connect(struct sock *sk, long timeo, int writebias) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci DEFINE_WAIT_FUNC(wait, woken_wake_function); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci add_wait_queue(sk_sleep(sk), &wait); 60262306a36Sopenharmony_ci sk->sk_write_pending += writebias; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* Basic assumption: if someone sets sk->sk_err, he _must_ 60562306a36Sopenharmony_ci * change state of the socket from TCP_SYN_*. 60662306a36Sopenharmony_ci * Connect() does not allow to get error notifications 60762306a36Sopenharmony_ci * without closing the socket. 60862306a36Sopenharmony_ci */ 60962306a36Sopenharmony_ci while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 61062306a36Sopenharmony_ci release_sock(sk); 61162306a36Sopenharmony_ci timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); 61262306a36Sopenharmony_ci lock_sock(sk); 61362306a36Sopenharmony_ci if (signal_pending(current) || !timeo) 61462306a36Sopenharmony_ci break; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci remove_wait_queue(sk_sleep(sk), &wait); 61762306a36Sopenharmony_ci sk->sk_write_pending -= writebias; 61862306a36Sopenharmony_ci return timeo; 61962306a36Sopenharmony_ci} 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci/* 62262306a36Sopenharmony_ci * Connect to a remote host. There is regrettably still a little 62362306a36Sopenharmony_ci * TCP 'magic' in here. 62462306a36Sopenharmony_ci */ 62562306a36Sopenharmony_ciint __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, 62662306a36Sopenharmony_ci int addr_len, int flags, int is_sendmsg) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct sock *sk = sock->sk; 62962306a36Sopenharmony_ci int err; 63062306a36Sopenharmony_ci long timeo; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci /* 63362306a36Sopenharmony_ci * uaddr can be NULL and addr_len can be 0 if: 63462306a36Sopenharmony_ci * sk is a TCP fastopen active socket and 63562306a36Sopenharmony_ci * TCP_FASTOPEN_CONNECT sockopt is set and 63662306a36Sopenharmony_ci * we already have a valid cookie for this socket. 63762306a36Sopenharmony_ci * In this case, user can call write() after connect(). 63862306a36Sopenharmony_ci * write() will invoke tcp_sendmsg_fastopen() which calls 63962306a36Sopenharmony_ci * __inet_stream_connect(). 64062306a36Sopenharmony_ci */ 64162306a36Sopenharmony_ci if (uaddr) { 64262306a36Sopenharmony_ci if (addr_len < sizeof(uaddr->sa_family)) 64362306a36Sopenharmony_ci return -EINVAL; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci if (uaddr->sa_family == AF_UNSPEC) { 64662306a36Sopenharmony_ci sk->sk_disconnects++; 64762306a36Sopenharmony_ci err = sk->sk_prot->disconnect(sk, flags); 64862306a36Sopenharmony_ci sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; 64962306a36Sopenharmony_ci goto out; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci switch (sock->state) { 65462306a36Sopenharmony_ci default: 65562306a36Sopenharmony_ci err = -EINVAL; 65662306a36Sopenharmony_ci goto out; 65762306a36Sopenharmony_ci case SS_CONNECTED: 65862306a36Sopenharmony_ci err = -EISCONN; 65962306a36Sopenharmony_ci goto out; 66062306a36Sopenharmony_ci case SS_CONNECTING: 66162306a36Sopenharmony_ci if (inet_test_bit(DEFER_CONNECT, sk)) 66262306a36Sopenharmony_ci err = is_sendmsg ? -EINPROGRESS : -EISCONN; 66362306a36Sopenharmony_ci else 66462306a36Sopenharmony_ci err = -EALREADY; 66562306a36Sopenharmony_ci /* Fall out of switch with err, set for this state */ 66662306a36Sopenharmony_ci break; 66762306a36Sopenharmony_ci case SS_UNCONNECTED: 66862306a36Sopenharmony_ci err = -EISCONN; 66962306a36Sopenharmony_ci if (sk->sk_state != TCP_CLOSE) 67062306a36Sopenharmony_ci goto out; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (BPF_CGROUP_PRE_CONNECT_ENABLED(sk)) { 67362306a36Sopenharmony_ci err = sk->sk_prot->pre_connect(sk, uaddr, addr_len); 67462306a36Sopenharmony_ci if (err) 67562306a36Sopenharmony_ci goto out; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci err = sk->sk_prot->connect(sk, uaddr, addr_len); 67962306a36Sopenharmony_ci if (err < 0) 68062306a36Sopenharmony_ci goto out; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci sock->state = SS_CONNECTING; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci if (!err && inet_test_bit(DEFER_CONNECT, sk)) 68562306a36Sopenharmony_ci goto out; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* Just entered SS_CONNECTING state; the only 68862306a36Sopenharmony_ci * difference is that return value in non-blocking 68962306a36Sopenharmony_ci * case is EINPROGRESS, rather than EALREADY. 69062306a36Sopenharmony_ci */ 69162306a36Sopenharmony_ci err = -EINPROGRESS; 69262306a36Sopenharmony_ci break; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 69862306a36Sopenharmony_ci int writebias = (sk->sk_protocol == IPPROTO_TCP) && 69962306a36Sopenharmony_ci tcp_sk(sk)->fastopen_req && 70062306a36Sopenharmony_ci tcp_sk(sk)->fastopen_req->data ? 1 : 0; 70162306a36Sopenharmony_ci int dis = sk->sk_disconnects; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* Error code is set above */ 70462306a36Sopenharmony_ci if (!timeo || !inet_wait_for_connect(sk, timeo, writebias)) 70562306a36Sopenharmony_ci goto out; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci err = sock_intr_errno(timeo); 70862306a36Sopenharmony_ci if (signal_pending(current)) 70962306a36Sopenharmony_ci goto out; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (dis != sk->sk_disconnects) { 71262306a36Sopenharmony_ci err = -EPIPE; 71362306a36Sopenharmony_ci goto out; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* Connection was closed by RST, timeout, ICMP error 71862306a36Sopenharmony_ci * or another process disconnected us. 71962306a36Sopenharmony_ci */ 72062306a36Sopenharmony_ci if (sk->sk_state == TCP_CLOSE) 72162306a36Sopenharmony_ci goto sock_error; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci /* sk->sk_err may be not zero now, if RECVERR was ordered by user 72462306a36Sopenharmony_ci * and error was received after socket entered established state. 72562306a36Sopenharmony_ci * Hence, it is handled normally after connect() return successfully. 72662306a36Sopenharmony_ci */ 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci sock->state = SS_CONNECTED; 72962306a36Sopenharmony_ci err = 0; 73062306a36Sopenharmony_ciout: 73162306a36Sopenharmony_ci return err; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cisock_error: 73462306a36Sopenharmony_ci err = sock_error(sk) ? : -ECONNABORTED; 73562306a36Sopenharmony_ci sock->state = SS_UNCONNECTED; 73662306a36Sopenharmony_ci sk->sk_disconnects++; 73762306a36Sopenharmony_ci if (sk->sk_prot->disconnect(sk, flags)) 73862306a36Sopenharmony_ci sock->state = SS_DISCONNECTING; 73962306a36Sopenharmony_ci goto out; 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ciEXPORT_SYMBOL(__inet_stream_connect); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ciint inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, 74462306a36Sopenharmony_ci int addr_len, int flags) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci int err; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci lock_sock(sock->sk); 74962306a36Sopenharmony_ci err = __inet_stream_connect(sock, uaddr, addr_len, flags, 0); 75062306a36Sopenharmony_ci release_sock(sock->sk); 75162306a36Sopenharmony_ci return err; 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ciEXPORT_SYMBOL(inet_stream_connect); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_civoid __inet_accept(struct socket *sock, struct socket *newsock, struct sock *newsk) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci sock_rps_record_flow(newsk); 75862306a36Sopenharmony_ci WARN_ON(!((1 << newsk->sk_state) & 75962306a36Sopenharmony_ci (TCPF_ESTABLISHED | TCPF_SYN_RECV | 76062306a36Sopenharmony_ci TCPF_CLOSE_WAIT | TCPF_CLOSE))); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci if (test_bit(SOCK_SUPPORT_ZC, &sock->flags)) 76362306a36Sopenharmony_ci set_bit(SOCK_SUPPORT_ZC, &newsock->flags); 76462306a36Sopenharmony_ci sock_graft(newsk, newsock); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci newsock->state = SS_CONNECTED; 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci/* 77062306a36Sopenharmony_ci * Accept a pending connection. The TCP layer now gives BSD semantics. 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ciint inet_accept(struct socket *sock, struct socket *newsock, int flags, 77462306a36Sopenharmony_ci bool kern) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci struct sock *sk1 = sock->sk, *sk2; 77762306a36Sopenharmony_ci int err = -EINVAL; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* IPV6_ADDRFORM can change sk->sk_prot under us. */ 78062306a36Sopenharmony_ci sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, flags, &err, kern); 78162306a36Sopenharmony_ci if (!sk2) 78262306a36Sopenharmony_ci return err; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci lock_sock(sk2); 78562306a36Sopenharmony_ci __inet_accept(sock, newsock, sk2); 78662306a36Sopenharmony_ci release_sock(sk2); 78762306a36Sopenharmony_ci return 0; 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ciEXPORT_SYMBOL(inet_accept); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci/* 79262306a36Sopenharmony_ci * This does both peername and sockname. 79362306a36Sopenharmony_ci */ 79462306a36Sopenharmony_ciint inet_getname(struct socket *sock, struct sockaddr *uaddr, 79562306a36Sopenharmony_ci int peer) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci struct sock *sk = sock->sk; 79862306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 79962306a36Sopenharmony_ci DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); 80062306a36Sopenharmony_ci int sin_addr_len = sizeof(*sin); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci sin->sin_family = AF_INET; 80362306a36Sopenharmony_ci lock_sock(sk); 80462306a36Sopenharmony_ci if (peer) { 80562306a36Sopenharmony_ci if (!inet->inet_dport || 80662306a36Sopenharmony_ci (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && 80762306a36Sopenharmony_ci peer == 1)) { 80862306a36Sopenharmony_ci release_sock(sk); 80962306a36Sopenharmony_ci return -ENOTCONN; 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci sin->sin_port = inet->inet_dport; 81262306a36Sopenharmony_ci sin->sin_addr.s_addr = inet->inet_daddr; 81362306a36Sopenharmony_ci BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len, 81462306a36Sopenharmony_ci CGROUP_INET4_GETPEERNAME); 81562306a36Sopenharmony_ci } else { 81662306a36Sopenharmony_ci __be32 addr = inet->inet_rcv_saddr; 81762306a36Sopenharmony_ci if (!addr) 81862306a36Sopenharmony_ci addr = inet->inet_saddr; 81962306a36Sopenharmony_ci sin->sin_port = inet->inet_sport; 82062306a36Sopenharmony_ci sin->sin_addr.s_addr = addr; 82162306a36Sopenharmony_ci BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len, 82262306a36Sopenharmony_ci CGROUP_INET4_GETSOCKNAME); 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci release_sock(sk); 82562306a36Sopenharmony_ci memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); 82662306a36Sopenharmony_ci return sin_addr_len; 82762306a36Sopenharmony_ci} 82862306a36Sopenharmony_ciEXPORT_SYMBOL(inet_getname); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ciint inet_send_prepare(struct sock *sk) 83162306a36Sopenharmony_ci{ 83262306a36Sopenharmony_ci sock_rps_record_flow(sk); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci /* We may need to bind the socket. */ 83562306a36Sopenharmony_ci if (data_race(!inet_sk(sk)->inet_num) && !sk->sk_prot->no_autobind && 83662306a36Sopenharmony_ci inet_autobind(sk)) 83762306a36Sopenharmony_ci return -EAGAIN; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci return 0; 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(inet_send_prepare); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ciint inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci struct sock *sk = sock->sk; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (unlikely(inet_send_prepare(sk))) 84862306a36Sopenharmony_ci return -EAGAIN; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return INDIRECT_CALL_2(sk->sk_prot->sendmsg, tcp_sendmsg, udp_sendmsg, 85162306a36Sopenharmony_ci sk, msg, size); 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ciEXPORT_SYMBOL(inet_sendmsg); 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_civoid inet_splice_eof(struct socket *sock) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci const struct proto *prot; 85862306a36Sopenharmony_ci struct sock *sk = sock->sk; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci if (unlikely(inet_send_prepare(sk))) 86162306a36Sopenharmony_ci return; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* IPV6_ADDRFORM can change sk->sk_prot under us. */ 86462306a36Sopenharmony_ci prot = READ_ONCE(sk->sk_prot); 86562306a36Sopenharmony_ci if (prot->splice_eof) 86662306a36Sopenharmony_ci prot->splice_eof(sock); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(inet_splice_eof); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(int udp_recvmsg(struct sock *, struct msghdr *, 87162306a36Sopenharmony_ci size_t, int, int *)); 87262306a36Sopenharmony_ciint inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, 87362306a36Sopenharmony_ci int flags) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct sock *sk = sock->sk; 87662306a36Sopenharmony_ci int addr_len = 0; 87762306a36Sopenharmony_ci int err; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci if (likely(!(flags & MSG_ERRQUEUE))) 88062306a36Sopenharmony_ci sock_rps_record_flow(sk); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci err = INDIRECT_CALL_2(sk->sk_prot->recvmsg, tcp_recvmsg, udp_recvmsg, 88362306a36Sopenharmony_ci sk, msg, size, flags, &addr_len); 88462306a36Sopenharmony_ci if (err >= 0) 88562306a36Sopenharmony_ci msg->msg_namelen = addr_len; 88662306a36Sopenharmony_ci return err; 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ciEXPORT_SYMBOL(inet_recvmsg); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ciint inet_shutdown(struct socket *sock, int how) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci struct sock *sk = sock->sk; 89362306a36Sopenharmony_ci int err = 0; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci /* This should really check to make sure 89662306a36Sopenharmony_ci * the socket is a TCP socket. (WHY AC...) 89762306a36Sopenharmony_ci */ 89862306a36Sopenharmony_ci how++; /* maps 0->1 has the advantage of making bit 1 rcvs and 89962306a36Sopenharmony_ci 1->2 bit 2 snds. 90062306a36Sopenharmony_ci 2->3 */ 90162306a36Sopenharmony_ci if ((how & ~SHUTDOWN_MASK) || !how) /* MAXINT->0 */ 90262306a36Sopenharmony_ci return -EINVAL; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci lock_sock(sk); 90562306a36Sopenharmony_ci if (sock->state == SS_CONNECTING) { 90662306a36Sopenharmony_ci if ((1 << sk->sk_state) & 90762306a36Sopenharmony_ci (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE)) 90862306a36Sopenharmony_ci sock->state = SS_DISCONNECTING; 90962306a36Sopenharmony_ci else 91062306a36Sopenharmony_ci sock->state = SS_CONNECTED; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci switch (sk->sk_state) { 91462306a36Sopenharmony_ci case TCP_CLOSE: 91562306a36Sopenharmony_ci err = -ENOTCONN; 91662306a36Sopenharmony_ci /* Hack to wake up other listeners, who can poll for 91762306a36Sopenharmony_ci EPOLLHUP, even on eg. unconnected UDP sockets -- RR */ 91862306a36Sopenharmony_ci fallthrough; 91962306a36Sopenharmony_ci default: 92062306a36Sopenharmony_ci WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | how); 92162306a36Sopenharmony_ci if (sk->sk_prot->shutdown) 92262306a36Sopenharmony_ci sk->sk_prot->shutdown(sk, how); 92362306a36Sopenharmony_ci break; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci /* Remaining two branches are temporary solution for missing 92662306a36Sopenharmony_ci * close() in multithreaded environment. It is _not_ a good idea, 92762306a36Sopenharmony_ci * but we have no choice until close() is repaired at VFS level. 92862306a36Sopenharmony_ci */ 92962306a36Sopenharmony_ci case TCP_LISTEN: 93062306a36Sopenharmony_ci if (!(how & RCV_SHUTDOWN)) 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci fallthrough; 93362306a36Sopenharmony_ci case TCP_SYN_SENT: 93462306a36Sopenharmony_ci err = sk->sk_prot->disconnect(sk, O_NONBLOCK); 93562306a36Sopenharmony_ci sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; 93662306a36Sopenharmony_ci break; 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci /* Wake up anyone sleeping in poll. */ 94062306a36Sopenharmony_ci sk->sk_state_change(sk); 94162306a36Sopenharmony_ci release_sock(sk); 94262306a36Sopenharmony_ci return err; 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ciEXPORT_SYMBOL(inet_shutdown); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci/* 94762306a36Sopenharmony_ci * ioctl() calls you can issue on an INET socket. Most of these are 94862306a36Sopenharmony_ci * device configuration and stuff and very rarely used. Some ioctls 94962306a36Sopenharmony_ci * pass on to the socket itself. 95062306a36Sopenharmony_ci * 95162306a36Sopenharmony_ci * NOTE: I like the idea of a module for the config stuff. ie ifconfig 95262306a36Sopenharmony_ci * loads the devconfigure module does its configuring and unloads it. 95362306a36Sopenharmony_ci * There's a good 20K of config code hanging around the kernel. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ciint inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 95762306a36Sopenharmony_ci{ 95862306a36Sopenharmony_ci struct sock *sk = sock->sk; 95962306a36Sopenharmony_ci int err = 0; 96062306a36Sopenharmony_ci struct net *net = sock_net(sk); 96162306a36Sopenharmony_ci void __user *p = (void __user *)arg; 96262306a36Sopenharmony_ci struct ifreq ifr; 96362306a36Sopenharmony_ci struct rtentry rt; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci switch (cmd) { 96662306a36Sopenharmony_ci case SIOCADDRT: 96762306a36Sopenharmony_ci case SIOCDELRT: 96862306a36Sopenharmony_ci if (copy_from_user(&rt, p, sizeof(struct rtentry))) 96962306a36Sopenharmony_ci return -EFAULT; 97062306a36Sopenharmony_ci err = ip_rt_ioctl(net, cmd, &rt); 97162306a36Sopenharmony_ci break; 97262306a36Sopenharmony_ci case SIOCRTMSG: 97362306a36Sopenharmony_ci err = -EINVAL; 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci case SIOCDARP: 97662306a36Sopenharmony_ci case SIOCGARP: 97762306a36Sopenharmony_ci case SIOCSARP: 97862306a36Sopenharmony_ci err = arp_ioctl(net, cmd, (void __user *)arg); 97962306a36Sopenharmony_ci break; 98062306a36Sopenharmony_ci case SIOCGIFADDR: 98162306a36Sopenharmony_ci case SIOCGIFBRDADDR: 98262306a36Sopenharmony_ci case SIOCGIFNETMASK: 98362306a36Sopenharmony_ci case SIOCGIFDSTADDR: 98462306a36Sopenharmony_ci case SIOCGIFPFLAGS: 98562306a36Sopenharmony_ci if (get_user_ifreq(&ifr, NULL, p)) 98662306a36Sopenharmony_ci return -EFAULT; 98762306a36Sopenharmony_ci err = devinet_ioctl(net, cmd, &ifr); 98862306a36Sopenharmony_ci if (!err && put_user_ifreq(&ifr, p)) 98962306a36Sopenharmony_ci err = -EFAULT; 99062306a36Sopenharmony_ci break; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci case SIOCSIFADDR: 99362306a36Sopenharmony_ci case SIOCSIFBRDADDR: 99462306a36Sopenharmony_ci case SIOCSIFNETMASK: 99562306a36Sopenharmony_ci case SIOCSIFDSTADDR: 99662306a36Sopenharmony_ci case SIOCSIFPFLAGS: 99762306a36Sopenharmony_ci case SIOCSIFFLAGS: 99862306a36Sopenharmony_ci if (get_user_ifreq(&ifr, NULL, p)) 99962306a36Sopenharmony_ci return -EFAULT; 100062306a36Sopenharmony_ci err = devinet_ioctl(net, cmd, &ifr); 100162306a36Sopenharmony_ci break; 100262306a36Sopenharmony_ci default: 100362306a36Sopenharmony_ci if (sk->sk_prot->ioctl) 100462306a36Sopenharmony_ci err = sk_ioctl(sk, cmd, (void __user *)arg); 100562306a36Sopenharmony_ci else 100662306a36Sopenharmony_ci err = -ENOIOCTLCMD; 100762306a36Sopenharmony_ci break; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci return err; 101062306a36Sopenharmony_ci} 101162306a36Sopenharmony_ciEXPORT_SYMBOL(inet_ioctl); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 101462306a36Sopenharmony_cistatic int inet_compat_routing_ioctl(struct sock *sk, unsigned int cmd, 101562306a36Sopenharmony_ci struct compat_rtentry __user *ur) 101662306a36Sopenharmony_ci{ 101762306a36Sopenharmony_ci compat_uptr_t rtdev; 101862306a36Sopenharmony_ci struct rtentry rt; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci if (copy_from_user(&rt.rt_dst, &ur->rt_dst, 102162306a36Sopenharmony_ci 3 * sizeof(struct sockaddr)) || 102262306a36Sopenharmony_ci get_user(rt.rt_flags, &ur->rt_flags) || 102362306a36Sopenharmony_ci get_user(rt.rt_metric, &ur->rt_metric) || 102462306a36Sopenharmony_ci get_user(rt.rt_mtu, &ur->rt_mtu) || 102562306a36Sopenharmony_ci get_user(rt.rt_window, &ur->rt_window) || 102662306a36Sopenharmony_ci get_user(rt.rt_irtt, &ur->rt_irtt) || 102762306a36Sopenharmony_ci get_user(rtdev, &ur->rt_dev)) 102862306a36Sopenharmony_ci return -EFAULT; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci rt.rt_dev = compat_ptr(rtdev); 103162306a36Sopenharmony_ci return ip_rt_ioctl(sock_net(sk), cmd, &rt); 103262306a36Sopenharmony_ci} 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cistatic int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 103562306a36Sopenharmony_ci{ 103662306a36Sopenharmony_ci void __user *argp = compat_ptr(arg); 103762306a36Sopenharmony_ci struct sock *sk = sock->sk; 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci switch (cmd) { 104062306a36Sopenharmony_ci case SIOCADDRT: 104162306a36Sopenharmony_ci case SIOCDELRT: 104262306a36Sopenharmony_ci return inet_compat_routing_ioctl(sk, cmd, argp); 104362306a36Sopenharmony_ci default: 104462306a36Sopenharmony_ci if (!sk->sk_prot->compat_ioctl) 104562306a36Sopenharmony_ci return -ENOIOCTLCMD; 104662306a36Sopenharmony_ci return sk->sk_prot->compat_ioctl(sk, cmd, arg); 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci} 104962306a36Sopenharmony_ci#endif /* CONFIG_COMPAT */ 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ciconst struct proto_ops inet_stream_ops = { 105262306a36Sopenharmony_ci .family = PF_INET, 105362306a36Sopenharmony_ci .owner = THIS_MODULE, 105462306a36Sopenharmony_ci .release = inet_release, 105562306a36Sopenharmony_ci .bind = inet_bind, 105662306a36Sopenharmony_ci .connect = inet_stream_connect, 105762306a36Sopenharmony_ci .socketpair = sock_no_socketpair, 105862306a36Sopenharmony_ci .accept = inet_accept, 105962306a36Sopenharmony_ci .getname = inet_getname, 106062306a36Sopenharmony_ci .poll = tcp_poll, 106162306a36Sopenharmony_ci .ioctl = inet_ioctl, 106262306a36Sopenharmony_ci .gettstamp = sock_gettstamp, 106362306a36Sopenharmony_ci .listen = inet_listen, 106462306a36Sopenharmony_ci .shutdown = inet_shutdown, 106562306a36Sopenharmony_ci .setsockopt = sock_common_setsockopt, 106662306a36Sopenharmony_ci .getsockopt = sock_common_getsockopt, 106762306a36Sopenharmony_ci .sendmsg = inet_sendmsg, 106862306a36Sopenharmony_ci .recvmsg = inet_recvmsg, 106962306a36Sopenharmony_ci#ifdef CONFIG_MMU 107062306a36Sopenharmony_ci .mmap = tcp_mmap, 107162306a36Sopenharmony_ci#endif 107262306a36Sopenharmony_ci .splice_eof = inet_splice_eof, 107362306a36Sopenharmony_ci .splice_read = tcp_splice_read, 107462306a36Sopenharmony_ci .read_sock = tcp_read_sock, 107562306a36Sopenharmony_ci .read_skb = tcp_read_skb, 107662306a36Sopenharmony_ci .sendmsg_locked = tcp_sendmsg_locked, 107762306a36Sopenharmony_ci .peek_len = tcp_peek_len, 107862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 107962306a36Sopenharmony_ci .compat_ioctl = inet_compat_ioctl, 108062306a36Sopenharmony_ci#endif 108162306a36Sopenharmony_ci .set_rcvlowat = tcp_set_rcvlowat, 108262306a36Sopenharmony_ci}; 108362306a36Sopenharmony_ciEXPORT_SYMBOL(inet_stream_ops); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ciconst struct proto_ops inet_dgram_ops = { 108662306a36Sopenharmony_ci .family = PF_INET, 108762306a36Sopenharmony_ci .owner = THIS_MODULE, 108862306a36Sopenharmony_ci .release = inet_release, 108962306a36Sopenharmony_ci .bind = inet_bind, 109062306a36Sopenharmony_ci .connect = inet_dgram_connect, 109162306a36Sopenharmony_ci .socketpair = sock_no_socketpair, 109262306a36Sopenharmony_ci .accept = sock_no_accept, 109362306a36Sopenharmony_ci .getname = inet_getname, 109462306a36Sopenharmony_ci .poll = udp_poll, 109562306a36Sopenharmony_ci .ioctl = inet_ioctl, 109662306a36Sopenharmony_ci .gettstamp = sock_gettstamp, 109762306a36Sopenharmony_ci .listen = sock_no_listen, 109862306a36Sopenharmony_ci .shutdown = inet_shutdown, 109962306a36Sopenharmony_ci .setsockopt = sock_common_setsockopt, 110062306a36Sopenharmony_ci .getsockopt = sock_common_getsockopt, 110162306a36Sopenharmony_ci .sendmsg = inet_sendmsg, 110262306a36Sopenharmony_ci .read_skb = udp_read_skb, 110362306a36Sopenharmony_ci .recvmsg = inet_recvmsg, 110462306a36Sopenharmony_ci .mmap = sock_no_mmap, 110562306a36Sopenharmony_ci .splice_eof = inet_splice_eof, 110662306a36Sopenharmony_ci .set_peek_off = sk_set_peek_off, 110762306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 110862306a36Sopenharmony_ci .compat_ioctl = inet_compat_ioctl, 110962306a36Sopenharmony_ci#endif 111062306a36Sopenharmony_ci}; 111162306a36Sopenharmony_ciEXPORT_SYMBOL(inet_dgram_ops); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci/* 111462306a36Sopenharmony_ci * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without 111562306a36Sopenharmony_ci * udp_poll 111662306a36Sopenharmony_ci */ 111762306a36Sopenharmony_cistatic const struct proto_ops inet_sockraw_ops = { 111862306a36Sopenharmony_ci .family = PF_INET, 111962306a36Sopenharmony_ci .owner = THIS_MODULE, 112062306a36Sopenharmony_ci .release = inet_release, 112162306a36Sopenharmony_ci .bind = inet_bind, 112262306a36Sopenharmony_ci .connect = inet_dgram_connect, 112362306a36Sopenharmony_ci .socketpair = sock_no_socketpair, 112462306a36Sopenharmony_ci .accept = sock_no_accept, 112562306a36Sopenharmony_ci .getname = inet_getname, 112662306a36Sopenharmony_ci .poll = datagram_poll, 112762306a36Sopenharmony_ci .ioctl = inet_ioctl, 112862306a36Sopenharmony_ci .gettstamp = sock_gettstamp, 112962306a36Sopenharmony_ci .listen = sock_no_listen, 113062306a36Sopenharmony_ci .shutdown = inet_shutdown, 113162306a36Sopenharmony_ci .setsockopt = sock_common_setsockopt, 113262306a36Sopenharmony_ci .getsockopt = sock_common_getsockopt, 113362306a36Sopenharmony_ci .sendmsg = inet_sendmsg, 113462306a36Sopenharmony_ci .recvmsg = inet_recvmsg, 113562306a36Sopenharmony_ci .mmap = sock_no_mmap, 113662306a36Sopenharmony_ci .splice_eof = inet_splice_eof, 113762306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 113862306a36Sopenharmony_ci .compat_ioctl = inet_compat_ioctl, 113962306a36Sopenharmony_ci#endif 114062306a36Sopenharmony_ci}; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_cistatic const struct net_proto_family inet_family_ops = { 114362306a36Sopenharmony_ci .family = PF_INET, 114462306a36Sopenharmony_ci .create = inet_create, 114562306a36Sopenharmony_ci .owner = THIS_MODULE, 114662306a36Sopenharmony_ci}; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci/* Upon startup we insert all the elements in inetsw_array[] into 114962306a36Sopenharmony_ci * the linked list inetsw. 115062306a36Sopenharmony_ci */ 115162306a36Sopenharmony_cistatic struct inet_protosw inetsw_array[] = 115262306a36Sopenharmony_ci{ 115362306a36Sopenharmony_ci { 115462306a36Sopenharmony_ci .type = SOCK_STREAM, 115562306a36Sopenharmony_ci .protocol = IPPROTO_TCP, 115662306a36Sopenharmony_ci .prot = &tcp_prot, 115762306a36Sopenharmony_ci .ops = &inet_stream_ops, 115862306a36Sopenharmony_ci .flags = INET_PROTOSW_PERMANENT | 115962306a36Sopenharmony_ci INET_PROTOSW_ICSK, 116062306a36Sopenharmony_ci }, 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci { 116362306a36Sopenharmony_ci .type = SOCK_DGRAM, 116462306a36Sopenharmony_ci .protocol = IPPROTO_UDP, 116562306a36Sopenharmony_ci .prot = &udp_prot, 116662306a36Sopenharmony_ci .ops = &inet_dgram_ops, 116762306a36Sopenharmony_ci .flags = INET_PROTOSW_PERMANENT, 116862306a36Sopenharmony_ci }, 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci { 117162306a36Sopenharmony_ci .type = SOCK_DGRAM, 117262306a36Sopenharmony_ci .protocol = IPPROTO_ICMP, 117362306a36Sopenharmony_ci .prot = &ping_prot, 117462306a36Sopenharmony_ci .ops = &inet_sockraw_ops, 117562306a36Sopenharmony_ci .flags = INET_PROTOSW_REUSE, 117662306a36Sopenharmony_ci }, 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci { 117962306a36Sopenharmony_ci .type = SOCK_RAW, 118062306a36Sopenharmony_ci .protocol = IPPROTO_IP, /* wild card */ 118162306a36Sopenharmony_ci .prot = &raw_prot, 118262306a36Sopenharmony_ci .ops = &inet_sockraw_ops, 118362306a36Sopenharmony_ci .flags = INET_PROTOSW_REUSE, 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci}; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci#define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array) 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_civoid inet_register_protosw(struct inet_protosw *p) 119062306a36Sopenharmony_ci{ 119162306a36Sopenharmony_ci struct list_head *lh; 119262306a36Sopenharmony_ci struct inet_protosw *answer; 119362306a36Sopenharmony_ci int protocol = p->protocol; 119462306a36Sopenharmony_ci struct list_head *last_perm; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci spin_lock_bh(&inetsw_lock); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci if (p->type >= SOCK_MAX) 119962306a36Sopenharmony_ci goto out_illegal; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci /* If we are trying to override a permanent protocol, bail. */ 120262306a36Sopenharmony_ci last_perm = &inetsw[p->type]; 120362306a36Sopenharmony_ci list_for_each(lh, &inetsw[p->type]) { 120462306a36Sopenharmony_ci answer = list_entry(lh, struct inet_protosw, list); 120562306a36Sopenharmony_ci /* Check only the non-wild match. */ 120662306a36Sopenharmony_ci if ((INET_PROTOSW_PERMANENT & answer->flags) == 0) 120762306a36Sopenharmony_ci break; 120862306a36Sopenharmony_ci if (protocol == answer->protocol) 120962306a36Sopenharmony_ci goto out_permanent; 121062306a36Sopenharmony_ci last_perm = lh; 121162306a36Sopenharmony_ci } 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci /* Add the new entry after the last permanent entry if any, so that 121462306a36Sopenharmony_ci * the new entry does not override a permanent entry when matched with 121562306a36Sopenharmony_ci * a wild-card protocol. But it is allowed to override any existing 121662306a36Sopenharmony_ci * non-permanent entry. This means that when we remove this entry, the 121762306a36Sopenharmony_ci * system automatically returns to the old behavior. 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci list_add_rcu(&p->list, last_perm); 122062306a36Sopenharmony_ciout: 122162306a36Sopenharmony_ci spin_unlock_bh(&inetsw_lock); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci return; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ciout_permanent: 122662306a36Sopenharmony_ci pr_err("Attempt to override permanent protocol %d\n", protocol); 122762306a36Sopenharmony_ci goto out; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ciout_illegal: 123062306a36Sopenharmony_ci pr_err("Ignoring attempt to register invalid socket type %d\n", 123162306a36Sopenharmony_ci p->type); 123262306a36Sopenharmony_ci goto out; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ciEXPORT_SYMBOL(inet_register_protosw); 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_civoid inet_unregister_protosw(struct inet_protosw *p) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci if (INET_PROTOSW_PERMANENT & p->flags) { 123962306a36Sopenharmony_ci pr_err("Attempt to unregister permanent protocol %d\n", 124062306a36Sopenharmony_ci p->protocol); 124162306a36Sopenharmony_ci } else { 124262306a36Sopenharmony_ci spin_lock_bh(&inetsw_lock); 124362306a36Sopenharmony_ci list_del_rcu(&p->list); 124462306a36Sopenharmony_ci spin_unlock_bh(&inetsw_lock); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci synchronize_net(); 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ciEXPORT_SYMBOL(inet_unregister_protosw); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_cistatic int inet_sk_reselect_saddr(struct sock *sk) 125262306a36Sopenharmony_ci{ 125362306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 125462306a36Sopenharmony_ci __be32 old_saddr = inet->inet_saddr; 125562306a36Sopenharmony_ci __be32 daddr = inet->inet_daddr; 125662306a36Sopenharmony_ci struct flowi4 *fl4; 125762306a36Sopenharmony_ci struct rtable *rt; 125862306a36Sopenharmony_ci __be32 new_saddr; 125962306a36Sopenharmony_ci struct ip_options_rcu *inet_opt; 126062306a36Sopenharmony_ci int err; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci inet_opt = rcu_dereference_protected(inet->inet_opt, 126362306a36Sopenharmony_ci lockdep_sock_is_held(sk)); 126462306a36Sopenharmony_ci if (inet_opt && inet_opt->opt.srr) 126562306a36Sopenharmony_ci daddr = inet_opt->opt.faddr; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci /* Query new route. */ 126862306a36Sopenharmony_ci fl4 = &inet->cork.fl.u.ip4; 126962306a36Sopenharmony_ci rt = ip_route_connect(fl4, daddr, 0, sk->sk_bound_dev_if, 127062306a36Sopenharmony_ci sk->sk_protocol, inet->inet_sport, 127162306a36Sopenharmony_ci inet->inet_dport, sk); 127262306a36Sopenharmony_ci if (IS_ERR(rt)) 127362306a36Sopenharmony_ci return PTR_ERR(rt); 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci new_saddr = fl4->saddr; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci if (new_saddr == old_saddr) { 127862306a36Sopenharmony_ci sk_setup_caps(sk, &rt->dst); 127962306a36Sopenharmony_ci return 0; 128062306a36Sopenharmony_ci } 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci err = inet_bhash2_update_saddr(sk, &new_saddr, AF_INET); 128362306a36Sopenharmony_ci if (err) { 128462306a36Sopenharmony_ci ip_rt_put(rt); 128562306a36Sopenharmony_ci return err; 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci sk_setup_caps(sk, &rt->dst); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci if (READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_dynaddr) > 1) { 129162306a36Sopenharmony_ci pr_info("%s(): shifting inet->saddr from %pI4 to %pI4\n", 129262306a36Sopenharmony_ci __func__, &old_saddr, &new_saddr); 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* 129662306a36Sopenharmony_ci * XXX The only one ugly spot where we need to 129762306a36Sopenharmony_ci * XXX really change the sockets identity after 129862306a36Sopenharmony_ci * XXX it has entered the hashes. -DaveM 129962306a36Sopenharmony_ci * 130062306a36Sopenharmony_ci * Besides that, it does not check for connection 130162306a36Sopenharmony_ci * uniqueness. Wait for troubles. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_ci return __sk_prot_rehash(sk); 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ciint inet_sk_rebuild_header(struct sock *sk) 130762306a36Sopenharmony_ci{ 130862306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 130962306a36Sopenharmony_ci struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); 131062306a36Sopenharmony_ci __be32 daddr; 131162306a36Sopenharmony_ci struct ip_options_rcu *inet_opt; 131262306a36Sopenharmony_ci struct flowi4 *fl4; 131362306a36Sopenharmony_ci int err; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci /* Route is OK, nothing to do. */ 131662306a36Sopenharmony_ci if (rt) 131762306a36Sopenharmony_ci return 0; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci /* Reroute. */ 132062306a36Sopenharmony_ci rcu_read_lock(); 132162306a36Sopenharmony_ci inet_opt = rcu_dereference(inet->inet_opt); 132262306a36Sopenharmony_ci daddr = inet->inet_daddr; 132362306a36Sopenharmony_ci if (inet_opt && inet_opt->opt.srr) 132462306a36Sopenharmony_ci daddr = inet_opt->opt.faddr; 132562306a36Sopenharmony_ci rcu_read_unlock(); 132662306a36Sopenharmony_ci fl4 = &inet->cork.fl.u.ip4; 132762306a36Sopenharmony_ci rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, 132862306a36Sopenharmony_ci inet->inet_dport, inet->inet_sport, 132962306a36Sopenharmony_ci sk->sk_protocol, RT_CONN_FLAGS(sk), 133062306a36Sopenharmony_ci sk->sk_bound_dev_if); 133162306a36Sopenharmony_ci if (!IS_ERR(rt)) { 133262306a36Sopenharmony_ci err = 0; 133362306a36Sopenharmony_ci sk_setup_caps(sk, &rt->dst); 133462306a36Sopenharmony_ci } else { 133562306a36Sopenharmony_ci err = PTR_ERR(rt); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci /* Routing failed... */ 133862306a36Sopenharmony_ci sk->sk_route_caps = 0; 133962306a36Sopenharmony_ci /* 134062306a36Sopenharmony_ci * Other protocols have to map its equivalent state to TCP_SYN_SENT. 134162306a36Sopenharmony_ci * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme 134262306a36Sopenharmony_ci */ 134362306a36Sopenharmony_ci if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_dynaddr) || 134462306a36Sopenharmony_ci sk->sk_state != TCP_SYN_SENT || 134562306a36Sopenharmony_ci (sk->sk_userlocks & SOCK_BINDADDR_LOCK) || 134662306a36Sopenharmony_ci (err = inet_sk_reselect_saddr(sk)) != 0) 134762306a36Sopenharmony_ci WRITE_ONCE(sk->sk_err_soft, -err); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci return err; 135162306a36Sopenharmony_ci} 135262306a36Sopenharmony_ciEXPORT_SYMBOL(inet_sk_rebuild_header); 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_civoid inet_sk_set_state(struct sock *sk, int state) 135562306a36Sopenharmony_ci{ 135662306a36Sopenharmony_ci trace_inet_sock_set_state(sk, sk->sk_state, state); 135762306a36Sopenharmony_ci sk->sk_state = state; 135862306a36Sopenharmony_ci} 135962306a36Sopenharmony_ciEXPORT_SYMBOL(inet_sk_set_state); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_civoid inet_sk_state_store(struct sock *sk, int newstate) 136262306a36Sopenharmony_ci{ 136362306a36Sopenharmony_ci trace_inet_sock_set_state(sk, sk->sk_state, newstate); 136462306a36Sopenharmony_ci smp_store_release(&sk->sk_state, newstate); 136562306a36Sopenharmony_ci} 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cistruct sk_buff *inet_gso_segment(struct sk_buff *skb, 136862306a36Sopenharmony_ci netdev_features_t features) 136962306a36Sopenharmony_ci{ 137062306a36Sopenharmony_ci bool udpfrag = false, fixedid = false, gso_partial, encap; 137162306a36Sopenharmony_ci struct sk_buff *segs = ERR_PTR(-EINVAL); 137262306a36Sopenharmony_ci const struct net_offload *ops; 137362306a36Sopenharmony_ci unsigned int offset = 0; 137462306a36Sopenharmony_ci struct iphdr *iph; 137562306a36Sopenharmony_ci int proto, tot_len; 137662306a36Sopenharmony_ci int nhoff; 137762306a36Sopenharmony_ci int ihl; 137862306a36Sopenharmony_ci int id; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci skb_reset_network_header(skb); 138162306a36Sopenharmony_ci nhoff = skb_network_header(skb) - skb_mac_header(skb); 138262306a36Sopenharmony_ci if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) 138362306a36Sopenharmony_ci goto out; 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci iph = ip_hdr(skb); 138662306a36Sopenharmony_ci ihl = iph->ihl * 4; 138762306a36Sopenharmony_ci if (ihl < sizeof(*iph)) 138862306a36Sopenharmony_ci goto out; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci id = ntohs(iph->id); 139162306a36Sopenharmony_ci proto = iph->protocol; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci /* Warning: after this point, iph might be no longer valid */ 139462306a36Sopenharmony_ci if (unlikely(!pskb_may_pull(skb, ihl))) 139562306a36Sopenharmony_ci goto out; 139662306a36Sopenharmony_ci __skb_pull(skb, ihl); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci encap = SKB_GSO_CB(skb)->encap_level > 0; 139962306a36Sopenharmony_ci if (encap) 140062306a36Sopenharmony_ci features &= skb->dev->hw_enc_features; 140162306a36Sopenharmony_ci SKB_GSO_CB(skb)->encap_level += ihl; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci skb_reset_transport_header(skb); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci segs = ERR_PTR(-EPROTONOSUPPORT); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci if (!skb->encapsulation || encap) { 140862306a36Sopenharmony_ci udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP); 140962306a36Sopenharmony_ci fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID); 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci /* fixed ID is invalid if DF bit is not set */ 141262306a36Sopenharmony_ci if (fixedid && !(ip_hdr(skb)->frag_off & htons(IP_DF))) 141362306a36Sopenharmony_ci goto out; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci ops = rcu_dereference(inet_offloads[proto]); 141762306a36Sopenharmony_ci if (likely(ops && ops->callbacks.gso_segment)) { 141862306a36Sopenharmony_ci segs = ops->callbacks.gso_segment(skb, features); 141962306a36Sopenharmony_ci if (!segs) 142062306a36Sopenharmony_ci skb->network_header = skb_mac_header(skb) + nhoff - skb->head; 142162306a36Sopenharmony_ci } 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci if (IS_ERR_OR_NULL(segs)) 142462306a36Sopenharmony_ci goto out; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci gso_partial = !!(skb_shinfo(segs)->gso_type & SKB_GSO_PARTIAL); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci skb = segs; 142962306a36Sopenharmony_ci do { 143062306a36Sopenharmony_ci iph = (struct iphdr *)(skb_mac_header(skb) + nhoff); 143162306a36Sopenharmony_ci if (udpfrag) { 143262306a36Sopenharmony_ci iph->frag_off = htons(offset >> 3); 143362306a36Sopenharmony_ci if (skb->next) 143462306a36Sopenharmony_ci iph->frag_off |= htons(IP_MF); 143562306a36Sopenharmony_ci offset += skb->len - nhoff - ihl; 143662306a36Sopenharmony_ci tot_len = skb->len - nhoff; 143762306a36Sopenharmony_ci } else if (skb_is_gso(skb)) { 143862306a36Sopenharmony_ci if (!fixedid) { 143962306a36Sopenharmony_ci iph->id = htons(id); 144062306a36Sopenharmony_ci id += skb_shinfo(skb)->gso_segs; 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci if (gso_partial) 144462306a36Sopenharmony_ci tot_len = skb_shinfo(skb)->gso_size + 144562306a36Sopenharmony_ci SKB_GSO_CB(skb)->data_offset + 144662306a36Sopenharmony_ci skb->head - (unsigned char *)iph; 144762306a36Sopenharmony_ci else 144862306a36Sopenharmony_ci tot_len = skb->len - nhoff; 144962306a36Sopenharmony_ci } else { 145062306a36Sopenharmony_ci if (!fixedid) 145162306a36Sopenharmony_ci iph->id = htons(id++); 145262306a36Sopenharmony_ci tot_len = skb->len - nhoff; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci iph->tot_len = htons(tot_len); 145562306a36Sopenharmony_ci ip_send_check(iph); 145662306a36Sopenharmony_ci if (encap) 145762306a36Sopenharmony_ci skb_reset_inner_headers(skb); 145862306a36Sopenharmony_ci skb->network_header = (u8 *)iph - skb->head; 145962306a36Sopenharmony_ci skb_reset_mac_len(skb); 146062306a36Sopenharmony_ci } while ((skb = skb->next)); 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ciout: 146362306a36Sopenharmony_ci return segs; 146462306a36Sopenharmony_ci} 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_cistatic struct sk_buff *ipip_gso_segment(struct sk_buff *skb, 146762306a36Sopenharmony_ci netdev_features_t features) 146862306a36Sopenharmony_ci{ 146962306a36Sopenharmony_ci if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4)) 147062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci return inet_gso_segment(skb, features); 147362306a36Sopenharmony_ci} 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_cistruct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb) 147662306a36Sopenharmony_ci{ 147762306a36Sopenharmony_ci const struct net_offload *ops; 147862306a36Sopenharmony_ci struct sk_buff *pp = NULL; 147962306a36Sopenharmony_ci const struct iphdr *iph; 148062306a36Sopenharmony_ci struct sk_buff *p; 148162306a36Sopenharmony_ci unsigned int hlen; 148262306a36Sopenharmony_ci unsigned int off; 148362306a36Sopenharmony_ci unsigned int id; 148462306a36Sopenharmony_ci int flush = 1; 148562306a36Sopenharmony_ci int proto; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci off = skb_gro_offset(skb); 148862306a36Sopenharmony_ci hlen = off + sizeof(*iph); 148962306a36Sopenharmony_ci iph = skb_gro_header(skb, hlen, off); 149062306a36Sopenharmony_ci if (unlikely(!iph)) 149162306a36Sopenharmony_ci goto out; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci proto = iph->protocol; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci ops = rcu_dereference(inet_offloads[proto]); 149662306a36Sopenharmony_ci if (!ops || !ops->callbacks.gro_receive) 149762306a36Sopenharmony_ci goto out; 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci if (*(u8 *)iph != 0x45) 150062306a36Sopenharmony_ci goto out; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci if (ip_is_fragment(iph)) 150362306a36Sopenharmony_ci goto out; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if (unlikely(ip_fast_csum((u8 *)iph, 5))) 150662306a36Sopenharmony_ci goto out; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci NAPI_GRO_CB(skb)->proto = proto; 150962306a36Sopenharmony_ci id = ntohl(*(__be32 *)&iph->id); 151062306a36Sopenharmony_ci flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); 151162306a36Sopenharmony_ci id >>= 16; 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci list_for_each_entry(p, head, list) { 151462306a36Sopenharmony_ci struct iphdr *iph2; 151562306a36Sopenharmony_ci u16 flush_id; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci if (!NAPI_GRO_CB(p)->same_flow) 151862306a36Sopenharmony_ci continue; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci iph2 = (struct iphdr *)(p->data + off); 152162306a36Sopenharmony_ci /* The above works because, with the exception of the top 152262306a36Sopenharmony_ci * (inner most) layer, we only aggregate pkts with the same 152362306a36Sopenharmony_ci * hdr length so all the hdrs we'll need to verify will start 152462306a36Sopenharmony_ci * at the same offset. 152562306a36Sopenharmony_ci */ 152662306a36Sopenharmony_ci if ((iph->protocol ^ iph2->protocol) | 152762306a36Sopenharmony_ci ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | 152862306a36Sopenharmony_ci ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { 152962306a36Sopenharmony_ci NAPI_GRO_CB(p)->same_flow = 0; 153062306a36Sopenharmony_ci continue; 153162306a36Sopenharmony_ci } 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci /* All fields must match except length and checksum. */ 153462306a36Sopenharmony_ci NAPI_GRO_CB(p)->flush |= 153562306a36Sopenharmony_ci (iph->ttl ^ iph2->ttl) | 153662306a36Sopenharmony_ci (iph->tos ^ iph2->tos) | 153762306a36Sopenharmony_ci ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci NAPI_GRO_CB(p)->flush |= flush; 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci /* We need to store of the IP ID check to be included later 154262306a36Sopenharmony_ci * when we can verify that this packet does in fact belong 154362306a36Sopenharmony_ci * to a given flow. 154462306a36Sopenharmony_ci */ 154562306a36Sopenharmony_ci flush_id = (u16)(id - ntohs(iph2->id)); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci /* This bit of code makes it much easier for us to identify 154862306a36Sopenharmony_ci * the cases where we are doing atomic vs non-atomic IP ID 154962306a36Sopenharmony_ci * checks. Specifically an atomic check can return IP ID 155062306a36Sopenharmony_ci * values 0 - 0xFFFF, while a non-atomic check can only 155162306a36Sopenharmony_ci * return 0 or 0xFFFF. 155262306a36Sopenharmony_ci */ 155362306a36Sopenharmony_ci if (!NAPI_GRO_CB(p)->is_atomic || 155462306a36Sopenharmony_ci !(iph->frag_off & htons(IP_DF))) { 155562306a36Sopenharmony_ci flush_id ^= NAPI_GRO_CB(p)->count; 155662306a36Sopenharmony_ci flush_id = flush_id ? 0xFFFF : 0; 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci /* If the previous IP ID value was based on an atomic 156062306a36Sopenharmony_ci * datagram we can overwrite the value and ignore it. 156162306a36Sopenharmony_ci */ 156262306a36Sopenharmony_ci if (NAPI_GRO_CB(skb)->is_atomic) 156362306a36Sopenharmony_ci NAPI_GRO_CB(p)->flush_id = flush_id; 156462306a36Sopenharmony_ci else 156562306a36Sopenharmony_ci NAPI_GRO_CB(p)->flush_id |= flush_id; 156662306a36Sopenharmony_ci } 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci NAPI_GRO_CB(skb)->is_atomic = !!(iph->frag_off & htons(IP_DF)); 156962306a36Sopenharmony_ci NAPI_GRO_CB(skb)->flush |= flush; 157062306a36Sopenharmony_ci skb_set_network_header(skb, off); 157162306a36Sopenharmony_ci /* The above will be needed by the transport layer if there is one 157262306a36Sopenharmony_ci * immediately following this IP hdr. 157362306a36Sopenharmony_ci */ 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci /* Note : No need to call skb_gro_postpull_rcsum() here, 157662306a36Sopenharmony_ci * as we already checked checksum over ipv4 header was 0 157762306a36Sopenharmony_ci */ 157862306a36Sopenharmony_ci skb_gro_pull(skb, sizeof(*iph)); 157962306a36Sopenharmony_ci skb_set_transport_header(skb, skb_gro_offset(skb)); 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci pp = indirect_call_gro_receive(tcp4_gro_receive, udp4_gro_receive, 158262306a36Sopenharmony_ci ops->callbacks.gro_receive, head, skb); 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ciout: 158562306a36Sopenharmony_ci skb_gro_flush_final(skb, pp, flush); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return pp; 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_cistatic struct sk_buff *ipip_gro_receive(struct list_head *head, 159162306a36Sopenharmony_ci struct sk_buff *skb) 159262306a36Sopenharmony_ci{ 159362306a36Sopenharmony_ci if (NAPI_GRO_CB(skb)->encap_mark) { 159462306a36Sopenharmony_ci NAPI_GRO_CB(skb)->flush = 1; 159562306a36Sopenharmony_ci return NULL; 159662306a36Sopenharmony_ci } 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci NAPI_GRO_CB(skb)->encap_mark = 1; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci return inet_gro_receive(head, skb); 160162306a36Sopenharmony_ci} 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci#define SECONDS_PER_DAY 86400 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci/* inet_current_timestamp - Return IP network timestamp 160662306a36Sopenharmony_ci * 160762306a36Sopenharmony_ci * Return milliseconds since midnight in network byte order. 160862306a36Sopenharmony_ci */ 160962306a36Sopenharmony_ci__be32 inet_current_timestamp(void) 161062306a36Sopenharmony_ci{ 161162306a36Sopenharmony_ci u32 secs; 161262306a36Sopenharmony_ci u32 msecs; 161362306a36Sopenharmony_ci struct timespec64 ts; 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci ktime_get_real_ts64(&ts); 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci /* Get secs since midnight. */ 161862306a36Sopenharmony_ci (void)div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, &secs); 161962306a36Sopenharmony_ci /* Convert to msecs. */ 162062306a36Sopenharmony_ci msecs = secs * MSEC_PER_SEC; 162162306a36Sopenharmony_ci /* Convert nsec to msec. */ 162262306a36Sopenharmony_ci msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci /* Convert to network byte order. */ 162562306a36Sopenharmony_ci return htonl(msecs); 162662306a36Sopenharmony_ci} 162762306a36Sopenharmony_ciEXPORT_SYMBOL(inet_current_timestamp); 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ciint inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) 163062306a36Sopenharmony_ci{ 163162306a36Sopenharmony_ci unsigned int family = READ_ONCE(sk->sk_family); 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci if (family == AF_INET) 163462306a36Sopenharmony_ci return ip_recv_error(sk, msg, len, addr_len); 163562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 163662306a36Sopenharmony_ci if (family == AF_INET6) 163762306a36Sopenharmony_ci return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len); 163862306a36Sopenharmony_ci#endif 163962306a36Sopenharmony_ci return -EINVAL; 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ciEXPORT_SYMBOL(inet_recv_error); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ciint inet_gro_complete(struct sk_buff *skb, int nhoff) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci struct iphdr *iph = (struct iphdr *)(skb->data + nhoff); 164662306a36Sopenharmony_ci const struct net_offload *ops; 164762306a36Sopenharmony_ci __be16 totlen = iph->tot_len; 164862306a36Sopenharmony_ci int proto = iph->protocol; 164962306a36Sopenharmony_ci int err = -ENOSYS; 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci if (skb->encapsulation) { 165262306a36Sopenharmony_ci skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IP)); 165362306a36Sopenharmony_ci skb_set_inner_network_header(skb, nhoff); 165462306a36Sopenharmony_ci } 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci iph_set_totlen(iph, skb->len - nhoff); 165762306a36Sopenharmony_ci csum_replace2(&iph->check, totlen, iph->tot_len); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci ops = rcu_dereference(inet_offloads[proto]); 166062306a36Sopenharmony_ci if (WARN_ON(!ops || !ops->callbacks.gro_complete)) 166162306a36Sopenharmony_ci goto out; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci /* Only need to add sizeof(*iph) to get to the next hdr below 166462306a36Sopenharmony_ci * because any hdr with option will have been flushed in 166562306a36Sopenharmony_ci * inet_gro_receive(). 166662306a36Sopenharmony_ci */ 166762306a36Sopenharmony_ci err = INDIRECT_CALL_2(ops->callbacks.gro_complete, 166862306a36Sopenharmony_ci tcp4_gro_complete, udp4_gro_complete, 166962306a36Sopenharmony_ci skb, nhoff + sizeof(*iph)); 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ciout: 167262306a36Sopenharmony_ci return err; 167362306a36Sopenharmony_ci} 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_cistatic int ipip_gro_complete(struct sk_buff *skb, int nhoff) 167662306a36Sopenharmony_ci{ 167762306a36Sopenharmony_ci skb->encapsulation = 1; 167862306a36Sopenharmony_ci skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4; 167962306a36Sopenharmony_ci return inet_gro_complete(skb, nhoff); 168062306a36Sopenharmony_ci} 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ciint inet_ctl_sock_create(struct sock **sk, unsigned short family, 168362306a36Sopenharmony_ci unsigned short type, unsigned char protocol, 168462306a36Sopenharmony_ci struct net *net) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci struct socket *sock; 168762306a36Sopenharmony_ci int rc = sock_create_kern(net, family, type, protocol, &sock); 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci if (rc == 0) { 169062306a36Sopenharmony_ci *sk = sock->sk; 169162306a36Sopenharmony_ci (*sk)->sk_allocation = GFP_ATOMIC; 169262306a36Sopenharmony_ci (*sk)->sk_use_task_frag = false; 169362306a36Sopenharmony_ci /* 169462306a36Sopenharmony_ci * Unhash it so that IP input processing does not even see it, 169562306a36Sopenharmony_ci * we do not wish this socket to see incoming packets. 169662306a36Sopenharmony_ci */ 169762306a36Sopenharmony_ci (*sk)->sk_prot->unhash(*sk); 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci return rc; 170062306a36Sopenharmony_ci} 170162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(inet_ctl_sock_create); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ciunsigned long snmp_fold_field(void __percpu *mib, int offt) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci unsigned long res = 0; 170662306a36Sopenharmony_ci int i; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci for_each_possible_cpu(i) 170962306a36Sopenharmony_ci res += snmp_get_cpu_field(mib, i, offt); 171062306a36Sopenharmony_ci return res; 171162306a36Sopenharmony_ci} 171262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snmp_fold_field); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci#if BITS_PER_LONG==32 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ciu64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offt, 171762306a36Sopenharmony_ci size_t syncp_offset) 171862306a36Sopenharmony_ci{ 171962306a36Sopenharmony_ci void *bhptr; 172062306a36Sopenharmony_ci struct u64_stats_sync *syncp; 172162306a36Sopenharmony_ci u64 v; 172262306a36Sopenharmony_ci unsigned int start; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci bhptr = per_cpu_ptr(mib, cpu); 172562306a36Sopenharmony_ci syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); 172662306a36Sopenharmony_ci do { 172762306a36Sopenharmony_ci start = u64_stats_fetch_begin(syncp); 172862306a36Sopenharmony_ci v = *(((u64 *)bhptr) + offt); 172962306a36Sopenharmony_ci } while (u64_stats_fetch_retry(syncp, start)); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci return v; 173262306a36Sopenharmony_ci} 173362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snmp_get_cpu_field64); 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ciu64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_offset) 173662306a36Sopenharmony_ci{ 173762306a36Sopenharmony_ci u64 res = 0; 173862306a36Sopenharmony_ci int cpu; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci for_each_possible_cpu(cpu) { 174162306a36Sopenharmony_ci res += snmp_get_cpu_field64(mib, cpu, offt, syncp_offset); 174262306a36Sopenharmony_ci } 174362306a36Sopenharmony_ci return res; 174462306a36Sopenharmony_ci} 174562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snmp_fold_field64); 174662306a36Sopenharmony_ci#endif 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTICAST 174962306a36Sopenharmony_cistatic const struct net_protocol igmp_protocol = { 175062306a36Sopenharmony_ci .handler = igmp_rcv, 175162306a36Sopenharmony_ci}; 175262306a36Sopenharmony_ci#endif 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_cistatic const struct net_protocol tcp_protocol = { 175562306a36Sopenharmony_ci .handler = tcp_v4_rcv, 175662306a36Sopenharmony_ci .err_handler = tcp_v4_err, 175762306a36Sopenharmony_ci .no_policy = 1, 175862306a36Sopenharmony_ci .icmp_strict_tag_validation = 1, 175962306a36Sopenharmony_ci}; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_cistatic const struct net_protocol udp_protocol = { 176262306a36Sopenharmony_ci .handler = udp_rcv, 176362306a36Sopenharmony_ci .err_handler = udp_err, 176462306a36Sopenharmony_ci .no_policy = 1, 176562306a36Sopenharmony_ci}; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_cistatic const struct net_protocol icmp_protocol = { 176862306a36Sopenharmony_ci .handler = icmp_rcv, 176962306a36Sopenharmony_ci .err_handler = icmp_err, 177062306a36Sopenharmony_ci .no_policy = 1, 177162306a36Sopenharmony_ci}; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_cistatic __net_init int ipv4_mib_init_net(struct net *net) 177462306a36Sopenharmony_ci{ 177562306a36Sopenharmony_ci int i; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci net->mib.tcp_statistics = alloc_percpu(struct tcp_mib); 177862306a36Sopenharmony_ci if (!net->mib.tcp_statistics) 177962306a36Sopenharmony_ci goto err_tcp_mib; 178062306a36Sopenharmony_ci net->mib.ip_statistics = alloc_percpu(struct ipstats_mib); 178162306a36Sopenharmony_ci if (!net->mib.ip_statistics) 178262306a36Sopenharmony_ci goto err_ip_mib; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci for_each_possible_cpu(i) { 178562306a36Sopenharmony_ci struct ipstats_mib *af_inet_stats; 178662306a36Sopenharmony_ci af_inet_stats = per_cpu_ptr(net->mib.ip_statistics, i); 178762306a36Sopenharmony_ci u64_stats_init(&af_inet_stats->syncp); 178862306a36Sopenharmony_ci } 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci net->mib.net_statistics = alloc_percpu(struct linux_mib); 179162306a36Sopenharmony_ci if (!net->mib.net_statistics) 179262306a36Sopenharmony_ci goto err_net_mib; 179362306a36Sopenharmony_ci net->mib.udp_statistics = alloc_percpu(struct udp_mib); 179462306a36Sopenharmony_ci if (!net->mib.udp_statistics) 179562306a36Sopenharmony_ci goto err_udp_mib; 179662306a36Sopenharmony_ci net->mib.udplite_statistics = alloc_percpu(struct udp_mib); 179762306a36Sopenharmony_ci if (!net->mib.udplite_statistics) 179862306a36Sopenharmony_ci goto err_udplite_mib; 179962306a36Sopenharmony_ci net->mib.icmp_statistics = alloc_percpu(struct icmp_mib); 180062306a36Sopenharmony_ci if (!net->mib.icmp_statistics) 180162306a36Sopenharmony_ci goto err_icmp_mib; 180262306a36Sopenharmony_ci net->mib.icmpmsg_statistics = kzalloc(sizeof(struct icmpmsg_mib), 180362306a36Sopenharmony_ci GFP_KERNEL); 180462306a36Sopenharmony_ci if (!net->mib.icmpmsg_statistics) 180562306a36Sopenharmony_ci goto err_icmpmsg_mib; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci tcp_mib_init(net); 180862306a36Sopenharmony_ci return 0; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_cierr_icmpmsg_mib: 181162306a36Sopenharmony_ci free_percpu(net->mib.icmp_statistics); 181262306a36Sopenharmony_cierr_icmp_mib: 181362306a36Sopenharmony_ci free_percpu(net->mib.udplite_statistics); 181462306a36Sopenharmony_cierr_udplite_mib: 181562306a36Sopenharmony_ci free_percpu(net->mib.udp_statistics); 181662306a36Sopenharmony_cierr_udp_mib: 181762306a36Sopenharmony_ci free_percpu(net->mib.net_statistics); 181862306a36Sopenharmony_cierr_net_mib: 181962306a36Sopenharmony_ci free_percpu(net->mib.ip_statistics); 182062306a36Sopenharmony_cierr_ip_mib: 182162306a36Sopenharmony_ci free_percpu(net->mib.tcp_statistics); 182262306a36Sopenharmony_cierr_tcp_mib: 182362306a36Sopenharmony_ci return -ENOMEM; 182462306a36Sopenharmony_ci} 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_cistatic __net_exit void ipv4_mib_exit_net(struct net *net) 182762306a36Sopenharmony_ci{ 182862306a36Sopenharmony_ci kfree(net->mib.icmpmsg_statistics); 182962306a36Sopenharmony_ci free_percpu(net->mib.icmp_statistics); 183062306a36Sopenharmony_ci free_percpu(net->mib.udplite_statistics); 183162306a36Sopenharmony_ci free_percpu(net->mib.udp_statistics); 183262306a36Sopenharmony_ci free_percpu(net->mib.net_statistics); 183362306a36Sopenharmony_ci free_percpu(net->mib.ip_statistics); 183462306a36Sopenharmony_ci free_percpu(net->mib.tcp_statistics); 183562306a36Sopenharmony_ci#ifdef CONFIG_MPTCP 183662306a36Sopenharmony_ci /* allocated on demand, see mptcp_init_sock() */ 183762306a36Sopenharmony_ci free_percpu(net->mib.mptcp_statistics); 183862306a36Sopenharmony_ci#endif 183962306a36Sopenharmony_ci} 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_cistatic __net_initdata struct pernet_operations ipv4_mib_ops = { 184262306a36Sopenharmony_ci .init = ipv4_mib_init_net, 184362306a36Sopenharmony_ci .exit = ipv4_mib_exit_net, 184462306a36Sopenharmony_ci}; 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_cistatic int __init init_ipv4_mibs(void) 184762306a36Sopenharmony_ci{ 184862306a36Sopenharmony_ci return register_pernet_subsys(&ipv4_mib_ops); 184962306a36Sopenharmony_ci} 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_cistatic __net_init int inet_init_net(struct net *net) 185262306a36Sopenharmony_ci{ 185362306a36Sopenharmony_ci /* 185462306a36Sopenharmony_ci * Set defaults for local port range 185562306a36Sopenharmony_ci */ 185662306a36Sopenharmony_ci seqlock_init(&net->ipv4.ip_local_ports.lock); 185762306a36Sopenharmony_ci net->ipv4.ip_local_ports.range[0] = 32768; 185862306a36Sopenharmony_ci net->ipv4.ip_local_ports.range[1] = 60999; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci seqlock_init(&net->ipv4.ping_group_range.lock); 186162306a36Sopenharmony_ci /* 186262306a36Sopenharmony_ci * Sane defaults - nobody may create ping sockets. 186362306a36Sopenharmony_ci * Boot scripts should set this to distro-specific group. 186462306a36Sopenharmony_ci */ 186562306a36Sopenharmony_ci net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1); 186662306a36Sopenharmony_ci net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci /* Default values for sysctl-controlled parameters. 186962306a36Sopenharmony_ci * We set them here, in case sysctl is not compiled. 187062306a36Sopenharmony_ci */ 187162306a36Sopenharmony_ci net->ipv4.sysctl_ip_default_ttl = IPDEFTTL; 187262306a36Sopenharmony_ci net->ipv4.sysctl_ip_fwd_update_priority = 1; 187362306a36Sopenharmony_ci net->ipv4.sysctl_ip_dynaddr = 0; 187462306a36Sopenharmony_ci net->ipv4.sysctl_ip_early_demux = 1; 187562306a36Sopenharmony_ci net->ipv4.sysctl_udp_early_demux = 1; 187662306a36Sopenharmony_ci net->ipv4.sysctl_tcp_early_demux = 1; 187762306a36Sopenharmony_ci net->ipv4.sysctl_nexthop_compat_mode = 1; 187862306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL 187962306a36Sopenharmony_ci net->ipv4.sysctl_ip_prot_sock = PROT_SOCK; 188062306a36Sopenharmony_ci#endif 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci /* Some igmp sysctl, whose values are always used */ 188362306a36Sopenharmony_ci net->ipv4.sysctl_igmp_max_memberships = 20; 188462306a36Sopenharmony_ci net->ipv4.sysctl_igmp_max_msf = 10; 188562306a36Sopenharmony_ci /* IGMP reports for link-local multicast groups are enabled by default */ 188662306a36Sopenharmony_ci net->ipv4.sysctl_igmp_llm_reports = 1; 188762306a36Sopenharmony_ci net->ipv4.sysctl_igmp_qrv = 2; 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci net->ipv4.sysctl_fib_notify_on_flag_change = 0; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci return 0; 189262306a36Sopenharmony_ci} 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_cistatic __net_initdata struct pernet_operations af_inet_ops = { 189562306a36Sopenharmony_ci .init = inet_init_net, 189662306a36Sopenharmony_ci}; 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_cistatic int __init init_inet_pernet_ops(void) 189962306a36Sopenharmony_ci{ 190062306a36Sopenharmony_ci return register_pernet_subsys(&af_inet_ops); 190162306a36Sopenharmony_ci} 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_cistatic int ipv4_proc_init(void); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci/* 190662306a36Sopenharmony_ci * IP protocol layer initialiser 190762306a36Sopenharmony_ci */ 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_cistatic struct packet_offload ip_packet_offload __read_mostly = { 191062306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_IP), 191162306a36Sopenharmony_ci .callbacks = { 191262306a36Sopenharmony_ci .gso_segment = inet_gso_segment, 191362306a36Sopenharmony_ci .gro_receive = inet_gro_receive, 191462306a36Sopenharmony_ci .gro_complete = inet_gro_complete, 191562306a36Sopenharmony_ci }, 191662306a36Sopenharmony_ci}; 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_cistatic const struct net_offload ipip_offload = { 191962306a36Sopenharmony_ci .callbacks = { 192062306a36Sopenharmony_ci .gso_segment = ipip_gso_segment, 192162306a36Sopenharmony_ci .gro_receive = ipip_gro_receive, 192262306a36Sopenharmony_ci .gro_complete = ipip_gro_complete, 192362306a36Sopenharmony_ci }, 192462306a36Sopenharmony_ci}; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_cistatic int __init ipip_offload_init(void) 192762306a36Sopenharmony_ci{ 192862306a36Sopenharmony_ci return inet_add_offload(&ipip_offload, IPPROTO_IPIP); 192962306a36Sopenharmony_ci} 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_cistatic int __init ipv4_offload_init(void) 193262306a36Sopenharmony_ci{ 193362306a36Sopenharmony_ci /* 193462306a36Sopenharmony_ci * Add offloads 193562306a36Sopenharmony_ci */ 193662306a36Sopenharmony_ci if (udpv4_offload_init() < 0) 193762306a36Sopenharmony_ci pr_crit("%s: Cannot add UDP protocol offload\n", __func__); 193862306a36Sopenharmony_ci if (tcpv4_offload_init() < 0) 193962306a36Sopenharmony_ci pr_crit("%s: Cannot add TCP protocol offload\n", __func__); 194062306a36Sopenharmony_ci if (ipip_offload_init() < 0) 194162306a36Sopenharmony_ci pr_crit("%s: Cannot add IPIP protocol offload\n", __func__); 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci dev_add_offload(&ip_packet_offload); 194462306a36Sopenharmony_ci return 0; 194562306a36Sopenharmony_ci} 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_cifs_initcall(ipv4_offload_init); 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_cistatic struct packet_type ip_packet_type __read_mostly = { 195062306a36Sopenharmony_ci .type = cpu_to_be16(ETH_P_IP), 195162306a36Sopenharmony_ci .func = ip_rcv, 195262306a36Sopenharmony_ci .list_func = ip_list_rcv, 195362306a36Sopenharmony_ci}; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_cistatic int __init inet_init(void) 195662306a36Sopenharmony_ci{ 195762306a36Sopenharmony_ci struct inet_protosw *q; 195862306a36Sopenharmony_ci struct list_head *r; 195962306a36Sopenharmony_ci int rc; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci sock_skb_cb_check_size(sizeof(struct inet_skb_parm)); 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci raw_hashinfo_init(&raw_v4_hashinfo); 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci rc = proto_register(&tcp_prot, 1); 196662306a36Sopenharmony_ci if (rc) 196762306a36Sopenharmony_ci goto out; 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci rc = proto_register(&udp_prot, 1); 197062306a36Sopenharmony_ci if (rc) 197162306a36Sopenharmony_ci goto out_unregister_tcp_proto; 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci rc = proto_register(&raw_prot, 1); 197462306a36Sopenharmony_ci if (rc) 197562306a36Sopenharmony_ci goto out_unregister_udp_proto; 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci rc = proto_register(&ping_prot, 1); 197862306a36Sopenharmony_ci if (rc) 197962306a36Sopenharmony_ci goto out_unregister_raw_proto; 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci /* 198262306a36Sopenharmony_ci * Tell SOCKET that we are alive... 198362306a36Sopenharmony_ci */ 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci (void)sock_register(&inet_family_ops); 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL 198862306a36Sopenharmony_ci ip_static_sysctl_init(); 198962306a36Sopenharmony_ci#endif 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci /* 199262306a36Sopenharmony_ci * Add all the base protocols. 199362306a36Sopenharmony_ci */ 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) 199662306a36Sopenharmony_ci pr_crit("%s: Cannot add ICMP protocol\n", __func__); 199762306a36Sopenharmony_ci if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) 199862306a36Sopenharmony_ci pr_crit("%s: Cannot add UDP protocol\n", __func__); 199962306a36Sopenharmony_ci if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) 200062306a36Sopenharmony_ci pr_crit("%s: Cannot add TCP protocol\n", __func__); 200162306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTICAST 200262306a36Sopenharmony_ci if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) 200362306a36Sopenharmony_ci pr_crit("%s: Cannot add IGMP protocol\n", __func__); 200462306a36Sopenharmony_ci#endif 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci /* Register the socket-side information for inet_create. */ 200762306a36Sopenharmony_ci for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) 200862306a36Sopenharmony_ci INIT_LIST_HEAD(r); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) 201162306a36Sopenharmony_ci inet_register_protosw(q); 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci /* 201462306a36Sopenharmony_ci * Set the ARP module up 201562306a36Sopenharmony_ci */ 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci arp_init(); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci /* 202062306a36Sopenharmony_ci * Set the IP module up 202162306a36Sopenharmony_ci */ 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci ip_init(); 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci /* Initialise per-cpu ipv4 mibs */ 202662306a36Sopenharmony_ci if (init_ipv4_mibs()) 202762306a36Sopenharmony_ci panic("%s: Cannot init ipv4 mibs\n", __func__); 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci /* Setup TCP slab cache for open requests. */ 203062306a36Sopenharmony_ci tcp_init(); 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci /* Setup UDP memory threshold */ 203362306a36Sopenharmony_ci udp_init(); 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci /* Add UDP-Lite (RFC 3828) */ 203662306a36Sopenharmony_ci udplite4_register(); 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci raw_init(); 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci ping_init(); 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci /* 204362306a36Sopenharmony_ci * Set the ICMP layer up 204462306a36Sopenharmony_ci */ 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci if (icmp_init() < 0) 204762306a36Sopenharmony_ci panic("Failed to create the ICMP control socket.\n"); 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci /* 205062306a36Sopenharmony_ci * Initialise the multicast router 205162306a36Sopenharmony_ci */ 205262306a36Sopenharmony_ci#if defined(CONFIG_IP_MROUTE) 205362306a36Sopenharmony_ci if (ip_mr_init()) 205462306a36Sopenharmony_ci pr_crit("%s: Cannot init ipv4 mroute\n", __func__); 205562306a36Sopenharmony_ci#endif 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci if (init_inet_pernet_ops()) 205862306a36Sopenharmony_ci pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci ipv4_proc_init(); 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci ipfrag_init(); 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci dev_add_pack(&ip_packet_type); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci ip_tunnel_core_init(); 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci rc = 0; 206962306a36Sopenharmony_ciout: 207062306a36Sopenharmony_ci return rc; 207162306a36Sopenharmony_ciout_unregister_raw_proto: 207262306a36Sopenharmony_ci proto_unregister(&raw_prot); 207362306a36Sopenharmony_ciout_unregister_udp_proto: 207462306a36Sopenharmony_ci proto_unregister(&udp_prot); 207562306a36Sopenharmony_ciout_unregister_tcp_proto: 207662306a36Sopenharmony_ci proto_unregister(&tcp_prot); 207762306a36Sopenharmony_ci goto out; 207862306a36Sopenharmony_ci} 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_cifs_initcall(inet_init); 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci/* ------------------------------------------------------------------------ */ 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 208562306a36Sopenharmony_cistatic int __init ipv4_proc_init(void) 208662306a36Sopenharmony_ci{ 208762306a36Sopenharmony_ci int rc = 0; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci if (raw_proc_init()) 209062306a36Sopenharmony_ci goto out_raw; 209162306a36Sopenharmony_ci if (tcp4_proc_init()) 209262306a36Sopenharmony_ci goto out_tcp; 209362306a36Sopenharmony_ci if (udp4_proc_init()) 209462306a36Sopenharmony_ci goto out_udp; 209562306a36Sopenharmony_ci if (ping_proc_init()) 209662306a36Sopenharmony_ci goto out_ping; 209762306a36Sopenharmony_ci if (ip_misc_proc_init()) 209862306a36Sopenharmony_ci goto out_misc; 209962306a36Sopenharmony_ciout: 210062306a36Sopenharmony_ci return rc; 210162306a36Sopenharmony_ciout_misc: 210262306a36Sopenharmony_ci ping_proc_exit(); 210362306a36Sopenharmony_ciout_ping: 210462306a36Sopenharmony_ci udp4_proc_exit(); 210562306a36Sopenharmony_ciout_udp: 210662306a36Sopenharmony_ci tcp4_proc_exit(); 210762306a36Sopenharmony_ciout_tcp: 210862306a36Sopenharmony_ci raw_proc_exit(); 210962306a36Sopenharmony_ciout_raw: 211062306a36Sopenharmony_ci rc = -ENOMEM; 211162306a36Sopenharmony_ci goto out; 211262306a36Sopenharmony_ci} 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci#else /* CONFIG_PROC_FS */ 211562306a36Sopenharmony_cistatic int __init ipv4_proc_init(void) 211662306a36Sopenharmony_ci{ 211762306a36Sopenharmony_ci return 0; 211862306a36Sopenharmony_ci} 211962306a36Sopenharmony_ci#endif /* CONFIG_PROC_FS */ 2120