1695 lines · 42.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * INET		An implementation of the TCP/IP protocol suite for the LINUX *		operating system.  INET is implemented using the  BSD Socket *		interface as the means of communication with the user level. * *		The Internet Protocol (IP) output module. * * Authors:	Ross Biro *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> *		Donald Becker, <becker@super.org> *		Alan Cox, <Alan.Cox@linux.org> *		Richard Underwood *		Stefan Becker, <stefanb@yello.ping.de> *		Jorge Cwik, <jorge@laser.satlink.net> *		Arnt Gulbrandsen, <agulbra@nvg.unit.no> *		Hirokazu Takahashi, <taka@valinux.co.jp> * *	See ip_input.c for original log * *	Fixes: *		Alan Cox	:	Missing nonblock feature in ip_build_xmit. *		Mike Kilburn	:	htons() missing in ip_build_xmit. *		Bradford Johnson:	Fix faulty handling of some frames when *					no route is found. *		Alexander Demenshin:	Missing sk/skb free in ip_queue_xmit *					(in case if packet not accepted by *					output firewall rules) *		Mike McLagan	:	Routing by source *		Alexey Kuznetsov:	use new route cache *		Andi Kleen:		Fix broken PMTU recovery and remove *					some redundant tests. *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma. *		Andi Kleen	: 	Replace ip_reply with ip_send_reply. *		Andi Kleen	:	Split fast and slow ip_build_xmit path *					for decreased register pressure on x86 *					and more readability. *		Marc Boucher	:	When call_out_firewall returns FW_QUEUE, *					silently drop skb instead of failing with -EPERM. *		Detlev Wengorz	:	Copy protocol for fragments. *		Hirokazu Takahashi:	HW checksumming for outgoing UDP *					datagrams. *		Hirokazu Takahashi:	sendfile() on UDP works now. */ #include <linux/uaccess.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/highmem.h>#include <linux/slab.h> #include <linux/socket.h>#include <linux/sockios.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/init.h> #include <net/flow.h>#include <net/snmp.h>#include <net/ip.h>#include <net/protocol.h>#include <net/route.h>#include <net/xfrm.h>#include <linux/skbuff.h>#include <net/sock.h>#include <net/arp.h>#include <net/icmp.h>#include <net/checksum.h>#include <net/gso.h>#include <net/inetpeer.h>#include <net/lwtunnel.h>#include <net/inet_dscp.h>#include <linux/bpf-cgroup.h>#include <linux/igmp.h>#include <linux/netfilter_ipv4.h>#include <linux/netfilter_bridge.h>#include <linux/netlink.h>#include <linux/tcp.h>#include <net/psp.h> static intip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,	    unsigned int mtu,	    int (*output)(struct net *, struct sock *, struct sk_buff *)); /* Generate a checksum for an outgoing IP datagram. */void ip_send_check(struct iphdr *iph){	iph->check = 0;	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);}EXPORT_SYMBOL(ip_send_check); int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb){	struct iphdr *iph = ip_hdr(skb); 	IP_INC_STATS(net, IPSTATS_MIB_OUTREQUESTS); 	iph_set_totlen(iph, skb->len);	ip_send_check(iph); 	/* if egress device is enslaved to an L3 master device pass the	 * skb to its handler for processing	 */	skb = l3mdev_ip_out(sk, skb);	if (unlikely(!skb))		return 0; 	skb->protocol = htons(ETH_P_IP); 	return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,		       net, sk, skb, NULL, skb_dst_dev(skb),		       dst_output);} int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb){	int err; 	err = __ip_local_out(net, sk, skb);	if (likely(err == 1))		err = dst_output(net, sk, skb); 	return err;}EXPORT_SYMBOL_GPL(ip_local_out); static inline int ip_select_ttl(const struct inet_sock *inet,				const struct dst_entry *dst){	int ttl = READ_ONCE(inet->uc_ttl); 	if (ttl < 0)		ttl = ip4_dst_hoplimit(dst);	return ttl;} /* *		Add an ip header to a skbuff and send it out. * */int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,			  __be32 saddr, __be32 daddr, struct ip_options_rcu *opt,			  u8 tos){	const struct inet_sock *inet = inet_sk(sk);	struct rtable *rt = skb_rtable(skb);	struct net *net = sock_net(sk);	struct iphdr *iph; 	/* Build the IP header. */	skb_push(skb, sizeof(struct iphdr) + (opt ? opt->opt.optlen : 0));	skb_reset_network_header(skb);	iph = ip_hdr(skb);	iph->version  = 4;	iph->ihl      = 5;	iph->tos      = tos;	iph->ttl      = ip_select_ttl(inet, &rt->dst);	iph->daddr    = (opt && opt->opt.srr ? opt->opt.faddr : daddr);	iph->saddr    = saddr;	iph->protocol = sk->sk_protocol;	/* Do not bother generating IPID for small packets (eg SYNACK) */	if (skb->len <= IPV4_MIN_MTU || ip_dont_fragment(sk, &rt->dst)) {		iph->frag_off = htons(IP_DF);		iph->id = 0;	} else {		iph->frag_off = 0;		/* TCP packets here are SYNACK with fat IPv4/TCP options.		 * Avoid using the hashed IP ident generator.		 */		if (sk->sk_protocol == IPPROTO_TCP)			iph->id = (__force __be16)get_random_u16();		else			__ip_select_ident(net, iph, 1);	} 	if (opt && opt->opt.optlen) {		iph->ihl += opt->opt.optlen>>2;		ip_options_build(skb, &opt->opt, daddr, rt);	} 	skb->priority = READ_ONCE(sk->sk_priority);	if (!skb->mark)		skb->mark = READ_ONCE(sk->sk_mark); 	/* Send it out. */	return ip_local_out(net, skb->sk, skb);} static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb){	struct dst_entry *dst = skb_dst(skb);	struct rtable *rt = dst_rtable(dst);	struct net_device *dev = dst_dev(dst);	unsigned int hh_len = LL_RESERVED_SPACE(dev);	struct neighbour *neigh;	bool is_v6gw = false; 	if (rt->rt_type == RTN_MULTICAST) {		IP_UPD_PO_STATS(net, IPSTATS_MIB_OUTMCAST, skb->len);	} else if (rt->rt_type == RTN_BROADCAST)		IP_UPD_PO_STATS(net, IPSTATS_MIB_OUTBCAST, skb->len); 	/* OUTOCTETS should be counted after fragment */	IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {		skb = skb_expand_head(skb, hh_len);		if (!skb)			return -ENOMEM;	} 	if (lwtunnel_xmit_redirect(dst->lwtstate)) {		int res = lwtunnel_xmit(skb); 		if (res != LWTUNNEL_XMIT_CONTINUE)			return res;	} 	rcu_read_lock();	neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);	if (!IS_ERR(neigh)) {		int res; 		sock_confirm_neigh(skb, neigh);		/* if crossing protocols, can not use the cached header */		res = neigh_output(neigh, skb, is_v6gw);		rcu_read_unlock();		return res;	}	rcu_read_unlock(); 	net_dbg_ratelimited("%s: No header cache and no neighbour!\n",			    __func__);	kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);	return PTR_ERR(neigh);} static int ip_finish_output_gso(struct net *net, struct sock *sk,				struct sk_buff *skb, unsigned int mtu){	struct sk_buff *segs, *nskb;	netdev_features_t features;	int ret = 0; 	/* common case: seglen is <= mtu	 */	if (skb_gso_validate_network_len(skb, mtu))		return ip_finish_output2(net, sk, skb); 	/* Slowpath -  GSO segment length exceeds the egress MTU.	 *	 * This can happen in several cases:	 *  - Forwarding of a TCP GRO skb, when DF flag is not set.	 *  - Forwarding of an skb that arrived on a virtualization interface	 *    (virtio-net/vhost/tap) with TSO/GSO size set by other network	 *    stack.	 *  - Local GSO skb transmitted on an NETIF_F_TSO tunnel stacked over an	 *    interface with a smaller MTU.	 *  - Arriving GRO skb (or GSO skb in a virtualized environment) that is	 *    bridged to a NETIF_F_TSO tunnel stacked over an interface with an	 *    insufficient MTU.	 */	features = netif_skb_features(skb);	BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_GSO_CB_OFFSET);	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);	if (IS_ERR_OR_NULL(segs)) {		kfree_skb(skb);		return -ENOMEM;	} 	consume_skb(skb); 	skb_list_walk_safe(segs, segs, nskb) {		int err; 		skb_mark_not_on_list(segs);		err = ip_fragment(net, sk, segs, mtu, ip_finish_output2); 		if (err && ret == 0)			ret = err;	} 	return ret;} static int __ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb){	unsigned int mtu; #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)	/* Policy lookup after SNAT yielded a new policy */	if (skb_dst(skb)->xfrm) {		IPCB(skb)->flags |= IPSKB_REROUTED;		return dst_output(net, sk, skb);	}#endif	mtu = ip_skb_dst_mtu(sk, skb);	if (skb_is_gso(skb))		return ip_finish_output_gso(net, sk, skb, mtu); 	if (skb->len > mtu || IPCB(skb)->frag_max_size)		return ip_fragment(net, sk, skb, mtu, ip_finish_output2); 	return ip_finish_output2(net, sk, skb);} static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb){	int ret; 	ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);	switch (ret) {	case NET_XMIT_SUCCESS:		return __ip_finish_output(net, sk, skb);	case NET_XMIT_CN:		return __ip_finish_output(net, sk, skb) ? : ret;	default:		kfree_skb_reason(skb, SKB_DROP_REASON_BPF_CGROUP_EGRESS);		return ret;	}} static int ip_mc_finish_output(struct net *net, struct sock *sk,			       struct sk_buff *skb){	struct rtable *new_rt;	bool do_cn = false;	int ret, err; 	ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb);	switch (ret) {	case NET_XMIT_CN:		do_cn = true;		fallthrough;	case NET_XMIT_SUCCESS:		break;	default:		kfree_skb_reason(skb, SKB_DROP_REASON_BPF_CGROUP_EGRESS);		return ret;	} 	/* Reset rt_iif so that inet_iif() will return skb->skb_iif. Setting	 * this to non-zero causes ipi_ifindex in in_pktinfo to be overwritten,	 * see ipv4_pktinfo_prepare().	 */	new_rt = rt_dst_clone(net->loopback_dev, skb_rtable(skb));	if (new_rt) {		new_rt->rt_iif = 0;		skb_dst_drop(skb);		skb_dst_set(skb, &new_rt->dst);	} 	err = dev_loopback_xmit(net, sk, skb);	return (do_cn && err) ? ret : err;} int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb){	struct rtable *rt = skb_rtable(skb);	struct net_device *dev = rt->dst.dev; 	/*	 *	If the indicated interface is up and running, send the packet.	 */	skb->dev = dev;	skb->protocol = htons(ETH_P_IP); 	/*	 *	Multicasts are looped back for other local users	 */ 	if (rt->rt_flags&RTCF_MULTICAST) {		if (sk_mc_loop(sk)#ifdef CONFIG_IP_MROUTE		/* Small optimization: do not loopback not local frames,		   which returned after forwarding; they will be  dropped		   by ip_mr_input in any case.		   Note, that local frames are looped back to be delivered		   to local recipients. 		   This check is duplicated in ip_mr_input at the moment.		 */		    &&		    ((rt->rt_flags & RTCF_LOCAL) ||		     !(IPCB(skb)->flags & IPSKB_FORWARDED))#endif		   ) {			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);			if (newskb)				NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,					net, sk, newskb, NULL, newskb->dev,					ip_mc_finish_output);		} 		/* Multicasts with ttl 0 must not go beyond the host */ 		if (ip_hdr(skb)->ttl == 0) {			kfree_skb(skb);			return 0;		}	} 	if (rt->rt_flags&RTCF_BROADCAST) {		struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);		if (newskb)			NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,				net, sk, newskb, NULL, newskb->dev,				ip_mc_finish_output);	} 	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,			    net, sk, skb, NULL, skb->dev,			    ip_finish_output,			    !(IPCB(skb)->flags & IPSKB_REROUTED));} int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb){	struct net_device *dev, *indev = skb->dev;	int ret_val; 	rcu_read_lock();	dev = skb_dst_dev_rcu(skb);	skb->dev = dev;	skb->protocol = htons(ETH_P_IP); 	ret_val = NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,				net, sk, skb, indev, dev,				ip_finish_output,				!(IPCB(skb)->flags & IPSKB_REROUTED));	rcu_read_unlock();	return ret_val;}EXPORT_SYMBOL(ip_output); /* * copy saddr and daddr, possibly using 64bit load/stores * Equivalent to : *   iph->saddr = fl4->saddr; *   iph->daddr = fl4->daddr; */static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4){	BUILD_BUG_ON(offsetof(typeof(*fl4), daddr) !=		     offsetof(typeof(*fl4), saddr) + sizeof(fl4->saddr)); 	iph->saddr = fl4->saddr;	iph->daddr = fl4->daddr;} /* Note: skb->sk can be different from sk, in case of tunnels */int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,		    __u8 tos){	struct inet_sock *inet = inet_sk(sk);	struct net *net = sock_net(sk);	struct ip_options_rcu *inet_opt;	struct flowi4 *fl4;	struct rtable *rt;	struct iphdr *iph;	int res; 	/* Skip all of this if the packet is already routed,	 * f.e. by something like SCTP.	 */	rcu_read_lock();	inet_opt = rcu_dereference(inet->inet_opt);	fl4 = &fl->u.ip4;	rt = skb_rtable(skb);	if (rt)		goto packet_routed; 	/* Make sure we can route this packet. */	rt = dst_rtable(__sk_dst_check(sk, 0));	if (!rt) {		inet_sk_init_flowi4(inet, fl4); 		/* sctp_v4_xmit() uses its own DSCP value */		fl4->flowi4_dscp = inet_dsfield_to_dscp(tos); 		/* If this fails, retransmit mechanism of transport layer will		 * keep trying until route appears or the connection times		 * itself out.		 */		rt = ip_route_output_flow(net, fl4, sk);		if (IS_ERR(rt))			goto no_route;		sk_setup_caps(sk, &rt->dst);	}	skb_dst_set_noref(skb, &rt->dst);

Lines 1–500 of 1695.