xref: /openbmc/linux/include/net/ip.h (revision f866fbc8)
12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * INET		An implementation of the TCP/IP protocol suite for the LINUX
41da177e4SLinus Torvalds  *		operating system.  INET is implemented using the  BSD Socket
51da177e4SLinus Torvalds  *		interface as the means of communication with the user level.
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *		Definitions for the IP module.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Version:	@(#)ip.h	1.0.2	05/07/93
101da177e4SLinus Torvalds  *
1102c30a84SJesper Juhl  * Authors:	Ross Biro
121da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
131da177e4SLinus Torvalds  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
141da177e4SLinus Torvalds  *
151da177e4SLinus Torvalds  * Changes:
161da177e4SLinus Torvalds  *		Mike McLagan    :       Routing by source
171da177e4SLinus Torvalds  */
181da177e4SLinus Torvalds #ifndef _IP_H
191da177e4SLinus Torvalds #define _IP_H
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #include <linux/types.h>
221da177e4SLinus Torvalds #include <linux/ip.h>
231da177e4SLinus Torvalds #include <linux/in.h>
24c9bdd4b5SArnaldo Carvalho de Melo #include <linux/skbuff.h>
25f0b1e64cSMartin KaFai Lau #include <linux/jhash.h>
26de40a3e8SChristoph Hellwig #include <linux/sockptr.h>
27020e71a3SEric Dumazet #include <linux/static_key.h>
2814c85021SArnaldo Carvalho de Melo 
2914c85021SArnaldo Carvalho de Melo #include <net/inet_sock.h>
30aa661581SFrancesco Fusco #include <net/route.h>
311da177e4SLinus Torvalds #include <net/snmp.h>
3286b08d86SKOVACS Krisztian #include <net/flow.h>
331bd758ebSJiri Pirko #include <net/flow_dissector.h>
34f0b1e64cSMartin KaFai Lau #include <net/netns/hash.h>
35fade5641SVadim Fedorenko #include <net/lwtunnel.h>
361da177e4SLinus Torvalds 
377ed14d97SGao Feng #define IPV4_MAX_PMTU		65535U		/* RFC 2675, Section 5.1 */
38b5476022SEric Dumazet #define IPV4_MIN_MTU		68			/* RFC 791 */
397ed14d97SGao Feng 
409ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem;
419ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem_min;
429ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem_max;
439ab948a9SDavid Ahern 
441da177e4SLinus Torvalds struct sock;
451da177e4SLinus Torvalds 
46fd2c3ef7SEric Dumazet struct inet_skb_parm {
470b922b7aSDavid Ahern 	int			iif;
481da177e4SLinus Torvalds 	struct ip_options	opt;		/* Compiled IP options		*/
49a04a480dSDavid Ahern 	u16			flags;
501da177e4SLinus Torvalds 
51df4d9254SHannes Frederic Sowa #define IPSKB_FORWARDED		BIT(0)
52df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TUNNEL_SIZE	BIT(1)
53df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TRANSFORMED	BIT(2)
54df4d9254SHannes Frederic Sowa #define IPSKB_FRAG_COMPLETE	BIT(3)
55df4d9254SHannes Frederic Sowa #define IPSKB_REROUTED		BIT(4)
56df4d9254SHannes Frederic Sowa #define IPSKB_DOREDIRECT	BIT(5)
57d6b915e2SFlorian Westphal #define IPSKB_FRAG_PMTU		BIT(6)
589ee6c5dcSLance Richardson #define IPSKB_L3SLAVE		BIT(7)
59e6175a2eSEyal Birger #define IPSKB_NOPOLICY		BIT(8)
605f2d04f1SPatrick McHardy 
615f2d04f1SPatrick McHardy 	u16			frag_max_size;
621da177e4SLinus Torvalds };
631da177e4SLinus Torvalds 
64a04a480dSDavid Ahern static inline bool ipv4_l3mdev_skb(u16 flags)
65a04a480dSDavid Ahern {
66a04a480dSDavid Ahern 	return !!(flags & IPSKB_L3SLAVE);
67a04a480dSDavid Ahern }
68a04a480dSDavid Ahern 
69c9bdd4b5SArnaldo Carvalho de Melo static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
70c9bdd4b5SArnaldo Carvalho de Melo {
71eddc9ec5SArnaldo Carvalho de Melo 	return ip_hdr(skb)->ihl * 4;
72c9bdd4b5SArnaldo Carvalho de Melo }
73c9bdd4b5SArnaldo Carvalho de Melo 
74fd2c3ef7SEric Dumazet struct ipcm_cookie {
7524025c46SSoheil Hassas Yeganeh 	struct sockcm_cookie	sockc;
76c1d18f9fSAl Viro 	__be32			addr;
771da177e4SLinus Torvalds 	int			oif;
78f6d8bd05SEric Dumazet 	struct ip_options_rcu	*opt;
793632679dSNicolas Dichtel 	__u8			protocol;
80f02db315SFrancesco Fusco 	__u8			ttl;
81f02db315SFrancesco Fusco 	__s16			tos;
82f02db315SFrancesco Fusco 	char			priority;
83bec1f6f6SWillem de Bruijn 	__u16			gso_size;
841da177e4SLinus Torvalds };
851da177e4SLinus Torvalds 
8635178206SWillem de Bruijn static inline void ipcm_init(struct ipcm_cookie *ipcm)
8735178206SWillem de Bruijn {
8835178206SWillem de Bruijn 	*ipcm = (struct ipcm_cookie) { .tos = -1 };
8935178206SWillem de Bruijn }
9035178206SWillem de Bruijn 
9135178206SWillem de Bruijn static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
9235178206SWillem de Bruijn 				const struct inet_sock *inet)
9335178206SWillem de Bruijn {
9435178206SWillem de Bruijn 	ipcm_init(ipcm);
9535178206SWillem de Bruijn 
963c5b4d69SEric Dumazet 	ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
9735178206SWillem de Bruijn 	ipcm->sockc.tsflags = inet->sk.sk_tsflags;
984c971d2fSEric Dumazet 	ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
9935178206SWillem de Bruijn 	ipcm->addr = inet->inet_saddr;
1003632679dSNicolas Dichtel 	ipcm->protocol = inet->inet_num;
10135178206SWillem de Bruijn }
10235178206SWillem de Bruijn 
1031da177e4SLinus Torvalds #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
1044b261c75SHannes Frederic Sowa #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
1051da177e4SLinus Torvalds 
106fb74c277SDavid Ahern /* return enslaved device index if relevant */
107d6bb2d1eSEric Dumazet static inline int inet_sdif(const struct sk_buff *skb)
108fb74c277SDavid Ahern {
109fb74c277SDavid Ahern #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
110fb74c277SDavid Ahern 	if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
111fb74c277SDavid Ahern 		return IPCB(skb)->iif;
112fb74c277SDavid Ahern #endif
113fb74c277SDavid Ahern 	return 0;
114fb74c277SDavid Ahern }
115fb74c277SDavid Ahern 
1165796ef75SKirill Tkhai /* Special input handler for packets caught by router alert option.
1175796ef75SKirill Tkhai    They are selected only by protocol field, and then processed likely
1185796ef75SKirill Tkhai    local ones; but only if someone wants them! Otherwise, router
1195796ef75SKirill Tkhai    not running rsvpd will kill RSVP.
1205796ef75SKirill Tkhai 
1215796ef75SKirill Tkhai    It is user level problem, what it will make with them.
1225796ef75SKirill Tkhai    I have no idea, how it will masquearde or NAT them (it is joke, joke :-)),
1235796ef75SKirill Tkhai    but receiver should be enough clever f.e. to forward mtrace requests,
1245796ef75SKirill Tkhai    sent to multicast group to reach destination designated router.
1255796ef75SKirill Tkhai  */
1265796ef75SKirill Tkhai 
127fd2c3ef7SEric Dumazet struct ip_ra_chain {
12843a951e9SEric Dumazet 	struct ip_ra_chain __rcu *next;
1291da177e4SLinus Torvalds 	struct sock		*sk;
130592fcb9dSEric Dumazet 	union {
1311da177e4SLinus Torvalds 		void			(*destructor)(struct sock *);
132592fcb9dSEric Dumazet 		struct sock		*saved_sk;
133592fcb9dSEric Dumazet 	};
13466018506SEric Dumazet 	struct rcu_head		rcu;
1351da177e4SLinus Torvalds };
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds /* IP flags. */
1381da177e4SLinus Torvalds #define IP_CE		0x8000		/* Flag: "Congestion"		*/
1391da177e4SLinus Torvalds #define IP_DF		0x4000		/* Flag: "Don't Fragment"	*/
1401da177e4SLinus Torvalds #define IP_MF		0x2000		/* Flag: "More Fragments"	*/
1411da177e4SLinus Torvalds #define IP_OFFSET	0x1FFF		/* "Fragment Offset" part	*/
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds #define IP_FRAG_TIME	(30 * HZ)		/* fragment lifetime	*/
1441da177e4SLinus Torvalds 
14514c85021SArnaldo Carvalho de Melo struct msghdr;
14614c85021SArnaldo Carvalho de Melo struct net_device;
14714c85021SArnaldo Carvalho de Melo struct packet_type;
14814c85021SArnaldo Carvalho de Melo struct rtable;
14914c85021SArnaldo Carvalho de Melo struct sockaddr;
15014c85021SArnaldo Carvalho de Melo 
15172c1d3bdSWANG Cong int igmp_mc_init(void);
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds /*
1541da177e4SLinus Torvalds  *	Functions provided by ip.c
1551da177e4SLinus Torvalds  */
1561da177e4SLinus Torvalds 
157cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
15813d8eaa0SAl Viro 			  __be32 saddr, __be32 daddr,
159de033b7dSWei Wang 			  struct ip_options_rcu *opt, u8 tos);
1605c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
1615c3a0fd7SJoe Perches 	   struct net_device *orig_dev);
16217266ee9SEdward Cree void ip_list_rcv(struct list_head *head, struct packet_type *pt,
16317266ee9SEdward Cree 		 struct net_device *orig_dev);
1645c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb);
16568cb7d53SPaolo Abeni void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
1665c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb);
167ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
168ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
169694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
170694869b3SEric W. Biederman 		   int (*output)(struct net *, struct sock *, struct sk_buff *));
171c8b17be0SPablo Neira Ayuso 
172c8b17be0SPablo Neira Ayuso struct ip_fraglist_iter {
173c8b17be0SPablo Neira Ayuso 	struct sk_buff	*frag;
174c8b17be0SPablo Neira Ayuso 	struct iphdr	*iph;
175c8b17be0SPablo Neira Ayuso 	int		offset;
176c8b17be0SPablo Neira Ayuso 	unsigned int	hlen;
177c8b17be0SPablo Neira Ayuso };
178c8b17be0SPablo Neira Ayuso 
179c8b17be0SPablo Neira Ayuso void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
180c8b17be0SPablo Neira Ayuso 		      unsigned int hlen, struct ip_fraglist_iter *iter);
181c8b17be0SPablo Neira Ayuso void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter);
182c8b17be0SPablo Neira Ayuso 
183c8b17be0SPablo Neira Ayuso static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter)
184c8b17be0SPablo Neira Ayuso {
185c8b17be0SPablo Neira Ayuso 	struct sk_buff *skb = iter->frag;
186c8b17be0SPablo Neira Ayuso 
187c8b17be0SPablo Neira Ayuso 	iter->frag = skb->next;
188c8b17be0SPablo Neira Ayuso 	skb_mark_not_on_list(skb);
189c8b17be0SPablo Neira Ayuso 
190c8b17be0SPablo Neira Ayuso 	return skb;
191c8b17be0SPablo Neira Ayuso }
192c8b17be0SPablo Neira Ayuso 
193065ff79fSPablo Neira Ayuso struct ip_frag_state {
194e7a409c3SEric Dumazet 	bool		DF;
195065ff79fSPablo Neira Ayuso 	unsigned int	hlen;
196065ff79fSPablo Neira Ayuso 	unsigned int	ll_rs;
197065ff79fSPablo Neira Ayuso 	unsigned int	mtu;
198065ff79fSPablo Neira Ayuso 	unsigned int	left;
199065ff79fSPablo Neira Ayuso 	int		offset;
200065ff79fSPablo Neira Ayuso 	int		ptr;
201065ff79fSPablo Neira Ayuso 	__be16		not_last_frag;
202065ff79fSPablo Neira Ayuso };
203065ff79fSPablo Neira Ayuso 
204065ff79fSPablo Neira Ayuso void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
205e7a409c3SEric Dumazet 		  unsigned int mtu, bool DF, struct ip_frag_state *state);
206065ff79fSPablo Neira Ayuso struct sk_buff *ip_frag_next(struct sk_buff *skb,
207065ff79fSPablo Neira Ayuso 			     struct ip_frag_state *state);
208065ff79fSPablo Neira Ayuso 
2095c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip);
210cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
21133224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
212aad88724SEric Dumazet 
21369b9e1e0SXin Long int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
21469b9e1e0SXin Long 		    __u8 tos);
2155c3a0fd7SJoe Perches void ip_init(void);
2165c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4,
2171da177e4SLinus Torvalds 		   int getfrag(void *from, char *to, int offset, int len,
2181da177e4SLinus Torvalds 			       int odd, struct sk_buff *skb),
2191da177e4SLinus Torvalds 		   void *from, int len, int protolen,
2201da177e4SLinus Torvalds 		   struct ipcm_cookie *ipc,
2212e77d89bSEric Dumazet 		   struct rtable **rt,
2221da177e4SLinus Torvalds 		   unsigned int flags);
2235c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
2245c3a0fd7SJoe Perches 		       struct sk_buff *skb);
2255c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2261c32c5adSHerbert Xu 			      struct sk_buff_head *queue,
2271c32c5adSHerbert Xu 			      struct inet_cork *cork);
2285c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb);
2295c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
2305c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk);
2315c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2325c3a0fd7SJoe Perches 			    int getfrag(void *from, char *to, int offset,
2335c3a0fd7SJoe Perches 					int len, int odd, struct sk_buff *skb),
2341c32c5adSHerbert Xu 			    void *from, int length, int transhdrlen,
2355c3a0fd7SJoe Perches 			    struct ipcm_cookie *ipc, struct rtable **rtp,
2361cd7884dSWillem de Bruijn 			    struct inet_cork *cork, unsigned int flags);
2371c32c5adSHerbert Xu 
23805e22e83SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
23969b9e1e0SXin Long 
24077968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
2411c32c5adSHerbert Xu {
24277968b78SDavid S. Miller 	return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
2431c32c5adSHerbert Xu }
2441da177e4SLinus Torvalds 
245726de790SGuillaume Nault /* Get the route scope that should be used when sending a packet. */
246726de790SGuillaume Nault static inline u8 ip_sendmsg_scope(const struct inet_sock *inet,
247726de790SGuillaume Nault 				  const struct ipcm_cookie *ipc,
248726de790SGuillaume Nault 				  const struct msghdr *msg)
249726de790SGuillaume Nault {
250726de790SGuillaume Nault 	if (sock_flag(&inet->sk, SOCK_LOCALROUTE) ||
251726de790SGuillaume Nault 	    msg->msg_flags & MSG_DONTROUTE ||
252726de790SGuillaume Nault 	    (ipc->opt && ipc->opt->opt.is_strictroute))
253726de790SGuillaume Nault 		return RT_SCOPE_LINK;
254726de790SGuillaume Nault 
255726de790SGuillaume Nault 	return RT_SCOPE_UNIVERSE;
256726de790SGuillaume Nault }
257726de790SGuillaume Nault 
258aa661581SFrancesco Fusco static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet)
259aa661581SFrancesco Fusco {
260aa661581SFrancesco Fusco 	return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos);
261aa661581SFrancesco Fusco }
262aa661581SFrancesco Fusco 
2631da177e4SLinus Torvalds /* datagram.c */
26403645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2655c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2661da177e4SLinus Torvalds 
2675c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk);
2688141ed9fSSteffen Klassert 
2691da177e4SLinus Torvalds struct ip_reply_arg {
2701da177e4SLinus Torvalds 	struct kvec iov[1];
27188ef4a5aSKOVACS Krisztian 	int	    flags;
272d6f5493cSAl Viro 	__wsum 	    csum;
2731da177e4SLinus Torvalds 	int	    csumoffset; /* u16 offset of csum in iov[0].iov_base */
2741da177e4SLinus Torvalds 				/* -1 if not needed */
275f0e48dbfSPatrick McHardy 	int	    bound_dev_if;
27666b13d99SEric Dumazet 	u8  	    tos;
277e2d118a1SLorenzo Colitti 	kuid_t	    uid;
2781da177e4SLinus Torvalds };
2791da177e4SLinus Torvalds 
28088ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1
28188ef4a5aSKOVACS Krisztian 
28286b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
28386b08d86SKOVACS Krisztian {
28486b08d86SKOVACS Krisztian 	return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
28586b08d86SKOVACS Krisztian }
28686b08d86SKOVACS Krisztian 
287bdbbb852SEric Dumazet void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
28824a2d43dSEric Dumazet 			   const struct ip_options *sopt,
28924a2d43dSEric Dumazet 			   __be32 daddr, __be32 saddr,
29024a2d43dSEric Dumazet 			   const struct ip_reply_arg *arg,
291c0a8966eSAntoine Tenart 			   unsigned int len, u64 transmit_time, u32 txhash);
2921da177e4SLinus Torvalds 
2934ce3c183SEric Dumazet #define IP_INC_STATS(net, field)	SNMP_INC_STATS64((net)->mib.ip_statistics, field)
29413415e46SEric Dumazet #define __IP_INC_STATS(net, field)	__SNMP_INC_STATS64((net)->mib.ip_statistics, field)
2954ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
29613415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
2974ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29813415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29961a7e260SPavel Emelyanov #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
30013415e46SEric Dumazet #define __NET_INC_STATS(net, field)	__SNMP_INC_STATS((net)->mib.net_statistics, field)
301f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd)	SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
30213415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
3031da177e4SLinus Torvalds 
30459f09ae8SEric Dumazet static inline u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt)
30559f09ae8SEric Dumazet {
30659f09ae8SEric Dumazet 	return  *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt);
30759f09ae8SEric Dumazet }
30859f09ae8SEric Dumazet 
309698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt);
3104ce3c183SEric Dumazet #if BITS_PER_LONG==32
311c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
312c4c6bc31SRaghavendra K T 			 size_t syncp_offset);
313698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off);
3144ce3c183SEric Dumazet #else
315c4c6bc31SRaghavendra K T static inline u64  snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
316c4c6bc31SRaghavendra K T 					size_t syncp_offset)
317c4c6bc31SRaghavendra K T {
318c4c6bc31SRaghavendra K T 	return snmp_get_cpu_field(mib, cpu, offct);
319c4c6bc31SRaghavendra K T 
320c4c6bc31SRaghavendra K T }
321c4c6bc31SRaghavendra K T 
322698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off)
3234ce3c183SEric Dumazet {
3244ce3c183SEric Dumazet 	return snmp_fold_field(mib, offt);
3254ce3c183SEric Dumazet }
3264ce3c183SEric Dumazet #endif
32733490170SYOSHIFUJI Hideaki 
3286348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \
3296348ef2dSJia He { \
3306348ef2dSJia He 	int i, c; \
3316348ef2dSJia He 	for_each_possible_cpu(c) { \
3326348ef2dSJia He 		for (i = 0; stats_list[i].name; i++) \
3336348ef2dSJia He 			buff64[i] += snmp_get_cpu_field64( \
3346348ef2dSJia He 					mib_statistic, \
3356348ef2dSJia He 					c, stats_list[i].entry, \
3366348ef2dSJia He 					offset); \
3376348ef2dSJia He 	} \
3386348ef2dSJia He }
3396348ef2dSJia He 
3406348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \
3416348ef2dSJia He { \
3426348ef2dSJia He 	int i, c; \
3436348ef2dSJia He 	for_each_possible_cpu(c) { \
3446348ef2dSJia He 		for (i = 0; stats_list[i].name; i++) \
3456348ef2dSJia He 			buff[i] += snmp_get_cpu_field( \
3466348ef2dSJia He 						mib_statistic, \
3476348ef2dSJia He 						c, stats_list[i].entry); \
3486348ef2dSJia He 	} \
3496348ef2dSJia He }
3506348ef2dSJia He 
35191d0b78cSJakub Sitnicki void inet_get_local_port_range(const struct net *net, int *low, int *high);
35291d0b78cSJakub Sitnicki void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high);
353227b60f5SStephen Hemminger 
354fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL
35566e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
356e3826f1eSAmerigo Wang {
357122ff243SWANG Cong 	if (!net->ipv4.sysctl_local_reserved_ports)
35830429fbaSMaciej Żenczykowski 		return false;
359122ff243SWANG Cong 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
360e3826f1eSAmerigo Wang }
36120e61da7SWANG Cong 
36220e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name)
36320e61da7SWANG Cong {
36420e61da7SWANG Cong 	return strcmp(name, "default") != 0  && strcmp(name, "all") != 0;
36520e61da7SWANG Cong }
36620e61da7SWANG Cong 
36782f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3684548b683SKrister Johansen {
3699b55c20fSKuniyuki Iwashima 	return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock);
3704548b683SKrister Johansen }
3714548b683SKrister Johansen 
372122ff243SWANG Cong #else
37366e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
374122ff243SWANG Cong {
37530429fbaSMaciej Żenczykowski 	return false;
376122ff243SWANG Cong }
3774548b683SKrister Johansen 
37882f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3794548b683SKrister Johansen {
38082f31ebfSMaciej Żenczykowski 	return port < PROT_SOCK;
3814548b683SKrister Johansen }
382122ff243SWANG Cong #endif
383e3826f1eSAmerigo Wang 
384822c8685SDeepa Dinamani __be32 inet_current_timestamp(void);
385822c8685SDeepa Dinamani 
38620380731SArnaldo Carvalho de Melo /* From inetpeer.c */
38720380731SArnaldo Carvalho de Melo extern int inet_peer_threshold;
38820380731SArnaldo Carvalho de Melo extern int inet_peer_minttl;
38920380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl;
39020380731SArnaldo Carvalho de Melo 
3915c3a0fd7SJoe Perches void ipfrag_init(void);
39220380731SArnaldo Carvalho de Melo 
3935c3a0fd7SJoe Perches void ip_static_sysctl_init(void);
394bd7b1533SAl Viro 
395e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \
39685d0b4dbSKuniyuki Iwashima 	(READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0)
397e110861fSLorenzo Colitti 
398d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph)
399d18cd551SDavid S. Miller {
400d18cd551SDavid S. Miller 	return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
401d18cd551SDavid S. Miller }
402d18cd551SDavid S. Miller 
4031da177e4SLinus Torvalds #ifdef CONFIG_INET
40414c85021SArnaldo Carvalho de Melo #include <net/dst.h>
40514c85021SArnaldo Carvalho de Melo 
4061da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for
4071da177e4SLinus Torvalds  * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
4081da177e4SLinus Torvalds static inline
4091da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph)
4101da177e4SLinus Torvalds {
4115c78f275SAl Viro 	u32 check = (__force u32)iph->check;
4125c78f275SAl Viro 	check += (__force u32)htons(0x0100);
4135c78f275SAl Viro 	iph->check = (__force __sum16)(check + (check>=0xFFFF));
4141da177e4SLinus Torvalds 	return --iph->ttl;
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds 
417d52e5a7eSSabrina Dubroca static inline int ip_mtu_locked(const struct dst_entry *dst)
418d52e5a7eSSabrina Dubroca {
419d52e5a7eSSabrina Dubroca 	const struct rtable *rt = (const struct rtable *)dst;
420d52e5a7eSSabrina Dubroca 
421d52e5a7eSSabrina Dubroca 	return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU);
422d52e5a7eSSabrina Dubroca }
423d52e5a7eSSabrina Dubroca 
4241da177e4SLinus Torvalds static inline
4254e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst)
4261da177e4SLinus Torvalds {
4274e3f5d72SEric Dumazet 	u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
4284e3f5d72SEric Dumazet 
4294e3f5d72SEric Dumazet 	return  pmtudisc == IP_PMTUDISC_DO ||
4304e3f5d72SEric Dumazet 		(pmtudisc == IP_PMTUDISC_WANT &&
431d52e5a7eSSabrina Dubroca 		 !ip_mtu_locked(dst));
4321da177e4SLinus Torvalds }
4331da177e4SLinus Torvalds 
434f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk)
435f87c10a8SHannes Frederic Sowa {
4361b346576SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE &&
4371b346576SHannes Frederic Sowa 	       inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT;
438f87c10a8SHannes Frederic Sowa }
439f87c10a8SHannes Frederic Sowa 
440f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk)
441f87c10a8SHannes Frederic Sowa {
442f87c10a8SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
443f87c10a8SHannes Frederic Sowa }
444f87c10a8SHannes Frederic Sowa 
44560ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk)
4461b346576SHannes Frederic Sowa {
4471b346576SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO ||
4481b346576SHannes Frederic Sowa 	       inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT;
4491b346576SHannes Frederic Sowa }
4501b346576SHannes Frederic Sowa 
451f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
452f87c10a8SHannes Frederic Sowa 						    bool forwarding)
453f87c10a8SHannes Frederic Sowa {
454ac6627a2SVadim Fedorenko 	const struct rtable *rt = container_of(dst, struct rtable, dst);
455f87c10a8SHannes Frederic Sowa 	struct net *net = dev_net(dst->dev);
45602a1b175SMaciej Żenczykowski 	unsigned int mtu;
457f87c10a8SHannes Frederic Sowa 
45860c158dcSKuniyuki Iwashima 	if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
459d52e5a7eSSabrina Dubroca 	    ip_mtu_locked(dst) ||
460ac6627a2SVadim Fedorenko 	    !forwarding) {
461ac6627a2SVadim Fedorenko 		mtu = rt->rt_pmtu;
462ac6627a2SVadim Fedorenko 		if (mtu && time_before(jiffies, rt->dst.expires))
463ac6627a2SVadim Fedorenko 			goto out;
464ac6627a2SVadim Fedorenko 	}
465f87c10a8SHannes Frederic Sowa 
46602a1b175SMaciej Żenczykowski 	/* 'forwarding = true' case should always honour route mtu */
46702a1b175SMaciej Żenczykowski 	mtu = dst_metric_raw(dst, RTAX_MTU);
468ac6627a2SVadim Fedorenko 	if (mtu)
469ac6627a2SVadim Fedorenko 		goto out;
470ac6627a2SVadim Fedorenko 
471ac6627a2SVadim Fedorenko 	mtu = READ_ONCE(dst->dev->mtu);
472ac6627a2SVadim Fedorenko 
473ac6627a2SVadim Fedorenko 	if (unlikely(ip_mtu_locked(dst))) {
474ac6627a2SVadim Fedorenko 		if (rt->rt_uses_gateway && mtu > 576)
475ac6627a2SVadim Fedorenko 			mtu = 576;
476ac6627a2SVadim Fedorenko 	}
477ac6627a2SVadim Fedorenko 
478ac6627a2SVadim Fedorenko out:
479ac6627a2SVadim Fedorenko 	mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
48002a1b175SMaciej Żenczykowski 
481fade5641SVadim Fedorenko 	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
482f87c10a8SHannes Frederic Sowa }
483f87c10a8SHannes Frederic Sowa 
484fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
485fedbb6b4SShmulik Ladkani 					  const struct sk_buff *skb)
486f87c10a8SHannes Frederic Sowa {
487fade5641SVadim Fedorenko 	unsigned int mtu;
488fade5641SVadim Fedorenko 
489caf3f267SEric Dumazet 	if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
490f87c10a8SHannes Frederic Sowa 		bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
491caf3f267SEric Dumazet 
492f87c10a8SHannes Frederic Sowa 		return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
493f87c10a8SHannes Frederic Sowa 	}
494caf3f267SEric Dumazet 
495fade5641SVadim Fedorenko 	mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
496fade5641SVadim Fedorenko 	return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
497f87c10a8SHannes Frederic Sowa }
498f87c10a8SHannes Frederic Sowa 
499767a2217SDavid Ahern struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
500d7e774f3SDavid Ahern 					int fc_mx_len,
501d7e774f3SDavid Ahern 					struct netlink_ext_ack *extack);
502cc5f0eb2SDavid Ahern static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics)
503cc5f0eb2SDavid Ahern {
504cc5f0eb2SDavid Ahern 	if (fib_metrics != &dst_default_metrics &&
505cc5f0eb2SDavid Ahern 	    refcount_dec_and_test(&fib_metrics->refcnt))
506cc5f0eb2SDavid Ahern 		kfree(fib_metrics);
507cc5f0eb2SDavid Ahern }
508a919525aSDavid Ahern 
509e1255ed4SDavid Ahern /* ipv4 and ipv6 both use refcounted metrics if it is not the default */
510e1255ed4SDavid Ahern static inline
511e1255ed4SDavid Ahern void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics)
512e1255ed4SDavid Ahern {
513e1255ed4SDavid Ahern 	dst_init_metrics(dst, fib_metrics->metrics, true);
514e1255ed4SDavid Ahern 
515e1255ed4SDavid Ahern 	if (fib_metrics != &dst_default_metrics) {
516e1255ed4SDavid Ahern 		dst->_metrics |= DST_METRICS_REFCOUNTED;
517e1255ed4SDavid Ahern 		refcount_inc(&fib_metrics->refcnt);
518e1255ed4SDavid Ahern 	}
519e1255ed4SDavid Ahern }
520e1255ed4SDavid Ahern 
5211620a336SDavid Ahern static inline
5221620a336SDavid Ahern void ip_dst_metrics_put(struct dst_entry *dst)
5231620a336SDavid Ahern {
5241620a336SDavid Ahern 	struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
5251620a336SDavid Ahern 
5261620a336SDavid Ahern 	if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
5271620a336SDavid Ahern 		kfree(p);
5281620a336SDavid Ahern }
5291620a336SDavid Ahern 
530b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
53173f156a6SEric Dumazet 
532b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
533b6a7719aSHannes Frederic Sowa 					struct sock *sk, int segs)
5341da177e4SLinus Torvalds {
535703133deSAnsis Atteka 	struct iphdr *iph = ip_hdr(skb);
536703133deSAnsis Atteka 
53723f57406SEric Dumazet 	/* We had many attacks based on IPID, use the private
53823f57406SEric Dumazet 	 * generator as much as we can.
5391da177e4SLinus Torvalds 	 */
540c720c7e8SEric Dumazet 	if (sk && inet_sk(sk)->inet_daddr) {
541*f866fbc8SEric Dumazet 		int val;
542*f866fbc8SEric Dumazet 
543*f866fbc8SEric Dumazet 		/* avoid atomic operations for TCP,
544*f866fbc8SEric Dumazet 		 * as we hold socket lock at this point.
545*f866fbc8SEric Dumazet 		 */
546*f866fbc8SEric Dumazet 		if (sk_is_tcp(sk)) {
547*f866fbc8SEric Dumazet 			sock_owned_by_me(sk);
548*f866fbc8SEric Dumazet 			val = atomic_read(&inet_sk(sk)->inet_id);
549*f866fbc8SEric Dumazet 			atomic_set(&inet_sk(sk)->inet_id, val + segs);
550*f866fbc8SEric Dumazet 		} else {
551*f866fbc8SEric Dumazet 			val = atomic_add_return(segs, &inet_sk(sk)->inet_id);
552*f866fbc8SEric Dumazet 		}
553*f866fbc8SEric Dumazet 		iph->id = htons(val);
55423f57406SEric Dumazet 		return;
55573f156a6SEric Dumazet 	}
55623f57406SEric Dumazet 	if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
55723f57406SEric Dumazet 		iph->id = 0;
55873f156a6SEric Dumazet 	} else {
55923f57406SEric Dumazet 		/* Unfortunately we need the big hammer to get a suitable IPID */
560b6a7719aSHannes Frederic Sowa 		__ip_select_ident(net, iph, segs);
56173f156a6SEric Dumazet 	}
56273f156a6SEric Dumazet }
56373f156a6SEric Dumazet 
564b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
565b6a7719aSHannes Frederic Sowa 				   struct sock *sk)
56673f156a6SEric Dumazet {
567b6a7719aSHannes Frederic Sowa 	ip_select_ident_segs(net, skb, sk, 1);
5681da177e4SLinus Torvalds }
5691da177e4SLinus Torvalds 
570ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
571ed70fcfcSTom Herbert {
572ed70fcfcSTom Herbert 	return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
573ed70fcfcSTom Herbert 				  skb->len, proto, 0);
574ed70fcfcSTom Herbert }
575ed70fcfcSTom Herbert 
576c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store
577c3f83241STom Herbert  * Equivalent to :	flow->v4addrs.src = iph->saddr;
578c3f83241STom Herbert  *			flow->v4addrs.dst = iph->daddr;
579c3f83241STom Herbert  */
580c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow,
581c3f83241STom Herbert 					    const struct iphdr *iph)
582c3f83241STom Herbert {
583c3f83241STom Herbert 	BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) !=
584c3f83241STom Herbert 		     offsetof(typeof(flow->addrs), v4addrs.src) +
585c3f83241STom Herbert 			      sizeof(flow->addrs.v4addrs.src));
58658e0be1eSHangbin Liu 	memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs));
587c3f83241STom Herbert 	flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
588c3f83241STom Herbert }
589c3f83241STom Herbert 
5901da177e4SLinus Torvalds /*
5911da177e4SLinus Torvalds  *	Map a multicast IP onto multicast MAC for type ethernet.
5921da177e4SLinus Torvalds  */
5931da177e4SLinus Torvalds 
594714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf)
5951da177e4SLinus Torvalds {
596714e85beSAl Viro 	__u32 addr=ntohl(naddr);
5971da177e4SLinus Torvalds 	buf[0]=0x01;
5981da177e4SLinus Torvalds 	buf[1]=0x00;
5991da177e4SLinus Torvalds 	buf[2]=0x5e;
6001da177e4SLinus Torvalds 	buf[5]=addr&0xFF;
6011da177e4SLinus Torvalds 	addr>>=8;
6021da177e4SLinus Torvalds 	buf[4]=addr&0xFF;
6031da177e4SLinus Torvalds 	addr>>=8;
6041da177e4SLinus Torvalds 	buf[3]=addr&0x7F;
6051da177e4SLinus Torvalds }
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds /*
6081da177e4SLinus Torvalds  *	Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
6091da177e4SLinus Torvalds  *	Leave P_Key as 0 to be filled in by driver.
6101da177e4SLinus Torvalds  */
6111da177e4SLinus Torvalds 
612a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
6131da177e4SLinus Torvalds {
614714e85beSAl Viro 	__u32 addr;
615a9e527e3SRolf Manderscheid 	unsigned char scope = broadcast[5] & 0xF;
616a9e527e3SRolf Manderscheid 
6171da177e4SLinus Torvalds 	buf[0]  = 0;		/* Reserved */
6181da177e4SLinus Torvalds 	buf[1]  = 0xff;		/* Multicast QPN */
6191da177e4SLinus Torvalds 	buf[2]  = 0xff;
6201da177e4SLinus Torvalds 	buf[3]  = 0xff;
621714e85beSAl Viro 	addr    = ntohl(naddr);
6221da177e4SLinus Torvalds 	buf[4]  = 0xff;
623a9e527e3SRolf Manderscheid 	buf[5]  = 0x10 | scope;	/* scope from broadcast address */
6241da177e4SLinus Torvalds 	buf[6]  = 0x40;		/* IPv4 signature */
6251da177e4SLinus Torvalds 	buf[7]  = 0x1b;
626a9e527e3SRolf Manderscheid 	buf[8]  = broadcast[8];		/* P_Key */
627a9e527e3SRolf Manderscheid 	buf[9]  = broadcast[9];
6281da177e4SLinus Torvalds 	buf[10] = 0;
6291da177e4SLinus Torvalds 	buf[11] = 0;
6301da177e4SLinus Torvalds 	buf[12] = 0;
6311da177e4SLinus Torvalds 	buf[13] = 0;
6321da177e4SLinus Torvalds 	buf[14] = 0;
6331da177e4SLinus Torvalds 	buf[15] = 0;
6341da177e4SLinus Torvalds 	buf[19] = addr & 0xff;
6351da177e4SLinus Torvalds 	addr  >>= 8;
6361da177e4SLinus Torvalds 	buf[18] = addr & 0xff;
6371da177e4SLinus Torvalds 	addr  >>= 8;
6381da177e4SLinus Torvalds 	buf[17] = addr & 0xff;
6391da177e4SLinus Torvalds 	addr  >>= 8;
6401da177e4SLinus Torvalds 	buf[16] = addr & 0x0f;
6411da177e4SLinus Torvalds }
6421da177e4SLinus Torvalds 
64393ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
64493ca3bb5STimo Teräs {
64593ca3bb5STimo Teräs 	if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
64693ca3bb5STimo Teräs 		memcpy(buf, broadcast, 4);
64793ca3bb5STimo Teräs 	else
64893ca3bb5STimo Teräs 		memcpy(buf, &naddr, sizeof(naddr));
64993ca3bb5STimo Teräs }
65093ca3bb5STimo Teräs 
651dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6521da177e4SLinus Torvalds #include <linux/ipv6.h>
6531da177e4SLinus Torvalds #endif
6541da177e4SLinus Torvalds 
6551da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk)
6561da177e4SLinus Torvalds {
657c720c7e8SEric Dumazet 	inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
658dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6591da177e4SLinus Torvalds 	if (sk->sk_family == PF_INET6) {
6601da177e4SLinus Torvalds 		struct ipv6_pinfo *np = inet6_sk(sk);
6611da177e4SLinus Torvalds 
6621da177e4SLinus Torvalds 		memset(&np->saddr, 0, sizeof(np->saddr));
663efe4208fSEric Dumazet 		memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr));
6641da177e4SLinus Torvalds 	}
6651da177e4SLinus Torvalds #endif
6661da177e4SLinus Torvalds }
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds #endif
6691da177e4SLinus Torvalds 
67072afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip)
67172afa352SDavid Ahern {
67272afa352SDavid Ahern 	return (__force unsigned int) ip;
67372afa352SDavid Ahern }
67472afa352SDavid Ahern 
675f0b1e64cSMartin KaFai Lau static inline u32 ipv4_portaddr_hash(const struct net *net,
676f0b1e64cSMartin KaFai Lau 				     __be32 saddr,
677f0b1e64cSMartin KaFai Lau 				     unsigned int port)
678f0b1e64cSMartin KaFai Lau {
679f0b1e64cSMartin KaFai Lau 	return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
680f0b1e64cSMartin KaFai Lau }
681f0b1e64cSMartin KaFai Lau 
6825c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb);
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds /*
685b798232fSRami Rosen  *	Functions provided by ip_fragment.c
6861da177e4SLinus Torvalds  */
6871da177e4SLinus Torvalds 
688fd2c3ef7SEric Dumazet enum ip_defrag_users {
6891da177e4SLinus Torvalds 	IP_DEFRAG_LOCAL_DELIVER,
6901da177e4SLinus Torvalds 	IP_DEFRAG_CALL_RA_CHAIN,
6911da177e4SLinus Torvalds 	IP_DEFRAG_CONNTRACK_IN,
6924be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_IN_END	= IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
6931da177e4SLinus Torvalds 	IP_DEFRAG_CONNTRACK_OUT,
6944be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_OUT_END	= IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
6958fa9ff68SPatrick McHardy 	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
6964be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
6971da177e4SLinus Torvalds 	IP_DEFRAG_VS_IN,
6981da177e4SLinus Torvalds 	IP_DEFRAG_VS_OUT,
699595fc71bSDavid S. Miller 	IP_DEFRAG_VS_FWD,
700595fc71bSDavid S. Miller 	IP_DEFRAG_AF_PACKET,
701bc416d97SEric Dumazet 	IP_DEFRAG_MACVLAN,
7021da177e4SLinus Torvalds };
7031da177e4SLinus Torvalds 
7045cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond'
7055cf42280SAndy Zhou  * and 'upper_bond' inclusively.
7065cf42280SAndy Zhou  */
7075cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user,
7085cf42280SAndy Zhou 					     enum ip_defrag_users lower_bond,
7095cf42280SAndy Zhou 					     enum ip_defrag_users upper_bond)
7105cf42280SAndy Zhou {
7115cf42280SAndy Zhou 	return user >= lower_bond && user <= upper_bond;
7125cf42280SAndy Zhou }
7135cf42280SAndy Zhou 
71419bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
715bc416d97SEric Dumazet #ifdef CONFIG_INET
71619bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
717bc416d97SEric Dumazet #else
71819bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
719bc416d97SEric Dumazet {
720bc416d97SEric Dumazet 	return skb;
721bc416d97SEric Dumazet }
722bc416d97SEric Dumazet #endif
7231da177e4SLinus Torvalds 
7241da177e4SLinus Torvalds /*
7251da177e4SLinus Torvalds  *	Functions provided by ip_forward.c
7261da177e4SLinus Torvalds  */
7271da177e4SLinus Torvalds 
7285c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb);
7291da177e4SLinus Torvalds 
7301da177e4SLinus Torvalds /*
7311da177e4SLinus Torvalds  *	Functions provided by ip_options.c
7321da177e4SLinus Torvalds  */
7331da177e4SLinus Torvalds 
7345c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
7354f0e3040SJakub Kicinski 		      __be32 daddr, struct rtable *rt);
73624a2d43dSEric Dumazet 
73791ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt,
73891ed1e66SPaolo Abeni 		      struct sk_buff *skb, const struct ip_options *sopt);
73991ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
74091ed1e66SPaolo Abeni 				  struct sk_buff *skb)
74124a2d43dSEric Dumazet {
74291ed1e66SPaolo Abeni 	return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
74324a2d43dSEric Dumazet }
74424a2d43dSEric Dumazet 
7455c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb);
7463da1ed7aSNazarov Sergey int __ip_options_compile(struct net *net, struct ip_options *opt,
7473da1ed7aSNazarov Sergey 			 struct sk_buff *skb, __be32 *info);
7485c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt,
7495c3a0fd7SJoe Perches 		       struct sk_buff *skb);
7505c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp,
751de40a3e8SChristoph Hellwig 		   sockptr_t data, int optlen);
7525c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt);
7535c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb);
7548c83f2dfSStephen Suryaputra int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
7551da177e4SLinus Torvalds 
7561da177e4SLinus Torvalds /*
7571da177e4SLinus Torvalds  *	Functions provided by ip_sockglue.c
7581da177e4SLinus Torvalds  */
7591da177e4SLinus Torvalds 
760fbf8866dSShawn Bohrer void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
761ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
762ad959036SPaolo Abeni 			 struct sk_buff *skb, int tlen, int offset);
76324025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
764c8e6ad08SHannes Frederic Sowa 		 struct ipcm_cookie *ipc, bool allow_ipv6);
765020e71a3SEric Dumazet DECLARE_STATIC_KEY_FALSE(ip4_min_ttl);
766ee7f1e13SMartin KaFai Lau int do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
767ee7f1e13SMartin KaFai Lau 		     unsigned int optlen);
768a7b75c5aSChristoph Hellwig int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
7695c3a0fd7SJoe Perches 		  unsigned int optlen);
770fd969f25SMartin KaFai Lau int do_ip_getsockopt(struct sock *sk, int level, int optname,
771fd969f25SMartin KaFai Lau 		     sockptr_t optval, sockptr_t optlen);
7725c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
7735c3a0fd7SJoe Perches 		  int __user *optlen);
7745c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on,
7755c3a0fd7SJoe Perches 		  void (*destructor)(struct sock *));
7761da177e4SLinus Torvalds 
77785fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
7785c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
7795c3a0fd7SJoe Perches 		   u32 info, u8 *payload);
7805c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
7811da177e4SLinus Torvalds 		    u32 info);
7821da177e4SLinus Torvalds 
7835961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
7845961de9fSTom Herbert {
785ad959036SPaolo Abeni 	ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
7865961de9fSTom Herbert }
7875961de9fSTom Herbert 
7884cdf507dSEric Dumazet bool icmp_global_allow(void);
7894cdf507dSEric Dumazet extern int sysctl_icmp_msgs_per_sec;
7904cdf507dSEric Dumazet extern int sysctl_icmp_msgs_burst;
7914cdf507dSEric Dumazet 
79220380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS
7935c3a0fd7SJoe Perches int ip_misc_proc_init(void);
79420380731SArnaldo Carvalho de Melo #endif
79520380731SArnaldo Carvalho de Melo 
7965e1a99eaSHangbin Liu int rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family,
797404eb77eSRoopa Prabhu 				struct netlink_ext_ack *extack);
798404eb77eSRoopa Prabhu 
799501a90c9SEric Dumazet static inline bool inetdev_valid_mtu(unsigned int mtu)
800501a90c9SEric Dumazet {
801501a90c9SEric Dumazet 	return likely(mtu >= IPV4_MIN_MTU);
802501a90c9SEric Dumazet }
803501a90c9SEric Dumazet 
804c4e446bfSChristoph Hellwig void ip_sock_set_freebind(struct sock *sk);
8052de569bdSChristoph Hellwig int ip_sock_set_mtu_discover(struct sock *sk, int val);
806c1f9ec57SChristoph Hellwig void ip_sock_set_pktinfo(struct sock *sk);
807db45c0efSChristoph Hellwig void ip_sock_set_recverr(struct sock *sk);
8086ebf71baSChristoph Hellwig void ip_sock_set_tos(struct sock *sk, int val);
8094f47d5d5SPoorva Sonparote void  __ip_sock_set_tos(struct sock *sk, int val);
8106ebf71baSChristoph Hellwig 
8111da177e4SLinus Torvalds #endif	/* _IP_H */
812