xref: /openbmc/linux/include/net/ip.h (revision 4c971d2f)
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)
595f2d04f1SPatrick McHardy 
605f2d04f1SPatrick McHardy 	u16			frag_max_size;
611da177e4SLinus Torvalds };
621da177e4SLinus Torvalds 
63a04a480dSDavid Ahern static inline bool ipv4_l3mdev_skb(u16 flags)
64a04a480dSDavid Ahern {
65a04a480dSDavid Ahern 	return !!(flags & IPSKB_L3SLAVE);
66a04a480dSDavid Ahern }
67a04a480dSDavid Ahern 
68c9bdd4b5SArnaldo Carvalho de Melo static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
69c9bdd4b5SArnaldo Carvalho de Melo {
70eddc9ec5SArnaldo Carvalho de Melo 	return ip_hdr(skb)->ihl * 4;
71c9bdd4b5SArnaldo Carvalho de Melo }
72c9bdd4b5SArnaldo Carvalho de Melo 
73fd2c3ef7SEric Dumazet struct ipcm_cookie {
7424025c46SSoheil Hassas Yeganeh 	struct sockcm_cookie	sockc;
75c1d18f9fSAl Viro 	__be32			addr;
761da177e4SLinus Torvalds 	int			oif;
77f6d8bd05SEric Dumazet 	struct ip_options_rcu	*opt;
78f02db315SFrancesco Fusco 	__u8			ttl;
79f02db315SFrancesco Fusco 	__s16			tos;
80f02db315SFrancesco Fusco 	char			priority;
81bec1f6f6SWillem de Bruijn 	__u16			gso_size;
821da177e4SLinus Torvalds };
831da177e4SLinus Torvalds 
8435178206SWillem de Bruijn static inline void ipcm_init(struct ipcm_cookie *ipcm)
8535178206SWillem de Bruijn {
8635178206SWillem de Bruijn 	*ipcm = (struct ipcm_cookie) { .tos = -1 };
8735178206SWillem de Bruijn }
8835178206SWillem de Bruijn 
8935178206SWillem de Bruijn static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
9035178206SWillem de Bruijn 				const struct inet_sock *inet)
9135178206SWillem de Bruijn {
9235178206SWillem de Bruijn 	ipcm_init(ipcm);
9335178206SWillem de Bruijn 
94c6af0c22SWillem de Bruijn 	ipcm->sockc.mark = inet->sk.sk_mark;
9535178206SWillem de Bruijn 	ipcm->sockc.tsflags = inet->sk.sk_tsflags;
96*4c971d2fSEric Dumazet 	ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
9735178206SWillem de Bruijn 	ipcm->addr = inet->inet_saddr;
9835178206SWillem de Bruijn }
9935178206SWillem de Bruijn 
1001da177e4SLinus Torvalds #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
1014b261c75SHannes Frederic Sowa #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
1021da177e4SLinus Torvalds 
103fb74c277SDavid Ahern /* return enslaved device index if relevant */
104d6bb2d1eSEric Dumazet static inline int inet_sdif(const struct sk_buff *skb)
105fb74c277SDavid Ahern {
106fb74c277SDavid Ahern #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
107fb74c277SDavid Ahern 	if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
108fb74c277SDavid Ahern 		return IPCB(skb)->iif;
109fb74c277SDavid Ahern #endif
110fb74c277SDavid Ahern 	return 0;
111fb74c277SDavid Ahern }
112fb74c277SDavid Ahern 
1135796ef75SKirill Tkhai /* Special input handler for packets caught by router alert option.
1145796ef75SKirill Tkhai    They are selected only by protocol field, and then processed likely
1155796ef75SKirill Tkhai    local ones; but only if someone wants them! Otherwise, router
1165796ef75SKirill Tkhai    not running rsvpd will kill RSVP.
1175796ef75SKirill Tkhai 
1185796ef75SKirill Tkhai    It is user level problem, what it will make with them.
1195796ef75SKirill Tkhai    I have no idea, how it will masquearde or NAT them (it is joke, joke :-)),
1205796ef75SKirill Tkhai    but receiver should be enough clever f.e. to forward mtrace requests,
1215796ef75SKirill Tkhai    sent to multicast group to reach destination designated router.
1225796ef75SKirill Tkhai  */
1235796ef75SKirill Tkhai 
124fd2c3ef7SEric Dumazet struct ip_ra_chain {
12543a951e9SEric Dumazet 	struct ip_ra_chain __rcu *next;
1261da177e4SLinus Torvalds 	struct sock		*sk;
127592fcb9dSEric Dumazet 	union {
1281da177e4SLinus Torvalds 		void			(*destructor)(struct sock *);
129592fcb9dSEric Dumazet 		struct sock		*saved_sk;
130592fcb9dSEric Dumazet 	};
13166018506SEric Dumazet 	struct rcu_head		rcu;
1321da177e4SLinus Torvalds };
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds /* IP flags. */
1351da177e4SLinus Torvalds #define IP_CE		0x8000		/* Flag: "Congestion"		*/
1361da177e4SLinus Torvalds #define IP_DF		0x4000		/* Flag: "Don't Fragment"	*/
1371da177e4SLinus Torvalds #define IP_MF		0x2000		/* Flag: "More Fragments"	*/
1381da177e4SLinus Torvalds #define IP_OFFSET	0x1FFF		/* "Fragment Offset" part	*/
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds #define IP_FRAG_TIME	(30 * HZ)		/* fragment lifetime	*/
1411da177e4SLinus Torvalds 
14214c85021SArnaldo Carvalho de Melo struct msghdr;
14314c85021SArnaldo Carvalho de Melo struct net_device;
14414c85021SArnaldo Carvalho de Melo struct packet_type;
14514c85021SArnaldo Carvalho de Melo struct rtable;
14614c85021SArnaldo Carvalho de Melo struct sockaddr;
14714c85021SArnaldo Carvalho de Melo 
14872c1d3bdSWANG Cong int igmp_mc_init(void);
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds /*
1511da177e4SLinus Torvalds  *	Functions provided by ip.c
1521da177e4SLinus Torvalds  */
1531da177e4SLinus Torvalds 
154cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
15513d8eaa0SAl Viro 			  __be32 saddr, __be32 daddr,
156de033b7dSWei Wang 			  struct ip_options_rcu *opt, u8 tos);
1575c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
1585c3a0fd7SJoe Perches 	   struct net_device *orig_dev);
15917266ee9SEdward Cree void ip_list_rcv(struct list_head *head, struct packet_type *pt,
16017266ee9SEdward Cree 		 struct net_device *orig_dev);
1615c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb);
16268cb7d53SPaolo Abeni void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
1635c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb);
164ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
165ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
166694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
167694869b3SEric W. Biederman 		   int (*output)(struct net *, struct sock *, struct sk_buff *));
168c8b17be0SPablo Neira Ayuso 
169c8b17be0SPablo Neira Ayuso struct ip_fraglist_iter {
170c8b17be0SPablo Neira Ayuso 	struct sk_buff	*frag;
171c8b17be0SPablo Neira Ayuso 	struct iphdr	*iph;
172c8b17be0SPablo Neira Ayuso 	int		offset;
173c8b17be0SPablo Neira Ayuso 	unsigned int	hlen;
174c8b17be0SPablo Neira Ayuso };
175c8b17be0SPablo Neira Ayuso 
176c8b17be0SPablo Neira Ayuso void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
177c8b17be0SPablo Neira Ayuso 		      unsigned int hlen, struct ip_fraglist_iter *iter);
178c8b17be0SPablo Neira Ayuso void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter);
179c8b17be0SPablo Neira Ayuso 
180c8b17be0SPablo Neira Ayuso static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter)
181c8b17be0SPablo Neira Ayuso {
182c8b17be0SPablo Neira Ayuso 	struct sk_buff *skb = iter->frag;
183c8b17be0SPablo Neira Ayuso 
184c8b17be0SPablo Neira Ayuso 	iter->frag = skb->next;
185c8b17be0SPablo Neira Ayuso 	skb_mark_not_on_list(skb);
186c8b17be0SPablo Neira Ayuso 
187c8b17be0SPablo Neira Ayuso 	return skb;
188c8b17be0SPablo Neira Ayuso }
189c8b17be0SPablo Neira Ayuso 
190065ff79fSPablo Neira Ayuso struct ip_frag_state {
191e7a409c3SEric Dumazet 	bool		DF;
192065ff79fSPablo Neira Ayuso 	unsigned int	hlen;
193065ff79fSPablo Neira Ayuso 	unsigned int	ll_rs;
194065ff79fSPablo Neira Ayuso 	unsigned int	mtu;
195065ff79fSPablo Neira Ayuso 	unsigned int	left;
196065ff79fSPablo Neira Ayuso 	int		offset;
197065ff79fSPablo Neira Ayuso 	int		ptr;
198065ff79fSPablo Neira Ayuso 	__be16		not_last_frag;
199065ff79fSPablo Neira Ayuso };
200065ff79fSPablo Neira Ayuso 
201065ff79fSPablo Neira Ayuso void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
202e7a409c3SEric Dumazet 		  unsigned int mtu, bool DF, struct ip_frag_state *state);
203065ff79fSPablo Neira Ayuso struct sk_buff *ip_frag_next(struct sk_buff *skb,
204065ff79fSPablo Neira Ayuso 			     struct ip_frag_state *state);
205065ff79fSPablo Neira Ayuso 
2065c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip);
207cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
20833224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
209aad88724SEric Dumazet 
21069b9e1e0SXin Long int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
21169b9e1e0SXin Long 		    __u8 tos);
2125c3a0fd7SJoe Perches void ip_init(void);
2135c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4,
2141da177e4SLinus Torvalds 		   int getfrag(void *from, char *to, int offset, int len,
2151da177e4SLinus Torvalds 			       int odd, struct sk_buff *skb),
2161da177e4SLinus Torvalds 		   void *from, int len, int protolen,
2171da177e4SLinus Torvalds 		   struct ipcm_cookie *ipc,
2182e77d89bSEric Dumazet 		   struct rtable **rt,
2191da177e4SLinus Torvalds 		   unsigned int flags);
2205c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
2215c3a0fd7SJoe Perches 		       struct sk_buff *skb);
2225c3a0fd7SJoe Perches ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
2231da177e4SLinus Torvalds 		       int offset, size_t size, int flags);
2245c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2251c32c5adSHerbert Xu 			      struct sk_buff_head *queue,
2261c32c5adSHerbert Xu 			      struct inet_cork *cork);
2275c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb);
2285c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
2295c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk);
2305c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2315c3a0fd7SJoe Perches 			    int getfrag(void *from, char *to, int offset,
2325c3a0fd7SJoe Perches 					int len, int odd, struct sk_buff *skb),
2331c32c5adSHerbert Xu 			    void *from, int length, int transhdrlen,
2345c3a0fd7SJoe Perches 			    struct ipcm_cookie *ipc, struct rtable **rtp,
2351cd7884dSWillem de Bruijn 			    struct inet_cork *cork, unsigned int flags);
2361c32c5adSHerbert Xu 
23705e22e83SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
23869b9e1e0SXin Long 
23977968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
2401c32c5adSHerbert Xu {
24177968b78SDavid S. Miller 	return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
2421c32c5adSHerbert Xu }
2431da177e4SLinus Torvalds 
244aa661581SFrancesco Fusco static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet)
245aa661581SFrancesco Fusco {
246aa661581SFrancesco Fusco 	return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos);
247aa661581SFrancesco Fusco }
248aa661581SFrancesco Fusco 
249aa661581SFrancesco Fusco static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk)
250aa661581SFrancesco Fusco {
251aa661581SFrancesco Fusco 	return (ipc->tos != -1) ? RT_CONN_FLAGS_TOS(sk, ipc->tos) : RT_CONN_FLAGS(sk);
252aa661581SFrancesco Fusco }
253aa661581SFrancesco Fusco 
2541da177e4SLinus Torvalds /* datagram.c */
25503645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2565c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2571da177e4SLinus Torvalds 
2585c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk);
2598141ed9fSSteffen Klassert 
2601da177e4SLinus Torvalds struct ip_reply_arg {
2611da177e4SLinus Torvalds 	struct kvec iov[1];
26288ef4a5aSKOVACS Krisztian 	int	    flags;
263d6f5493cSAl Viro 	__wsum 	    csum;
2641da177e4SLinus Torvalds 	int	    csumoffset; /* u16 offset of csum in iov[0].iov_base */
2651da177e4SLinus Torvalds 				/* -1 if not needed */
266f0e48dbfSPatrick McHardy 	int	    bound_dev_if;
26766b13d99SEric Dumazet 	u8  	    tos;
268e2d118a1SLorenzo Colitti 	kuid_t	    uid;
2691da177e4SLinus Torvalds };
2701da177e4SLinus Torvalds 
27188ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1
27288ef4a5aSKOVACS Krisztian 
27386b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
27486b08d86SKOVACS Krisztian {
27586b08d86SKOVACS Krisztian 	return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
27686b08d86SKOVACS Krisztian }
27786b08d86SKOVACS Krisztian 
278bdbbb852SEric Dumazet void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
27924a2d43dSEric Dumazet 			   const struct ip_options *sopt,
28024a2d43dSEric Dumazet 			   __be32 daddr, __be32 saddr,
28124a2d43dSEric Dumazet 			   const struct ip_reply_arg *arg,
282d6fb396cSEric Dumazet 			   unsigned int len, u64 transmit_time);
2831da177e4SLinus Torvalds 
2844ce3c183SEric Dumazet #define IP_INC_STATS(net, field)	SNMP_INC_STATS64((net)->mib.ip_statistics, field)
28513415e46SEric Dumazet #define __IP_INC_STATS(net, field)	__SNMP_INC_STATS64((net)->mib.ip_statistics, field)
2864ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
28713415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
2884ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
28913415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29061a7e260SPavel Emelyanov #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
29113415e46SEric Dumazet #define __NET_INC_STATS(net, field)	__SNMP_INC_STATS((net)->mib.net_statistics, field)
292f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd)	SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
29313415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
2941da177e4SLinus Torvalds 
29559f09ae8SEric Dumazet static inline u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt)
29659f09ae8SEric Dumazet {
29759f09ae8SEric Dumazet 	return  *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt);
29859f09ae8SEric Dumazet }
29959f09ae8SEric Dumazet 
300698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt);
3014ce3c183SEric Dumazet #if BITS_PER_LONG==32
302c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
303c4c6bc31SRaghavendra K T 			 size_t syncp_offset);
304698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off);
3054ce3c183SEric Dumazet #else
306c4c6bc31SRaghavendra K T static inline u64  snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
307c4c6bc31SRaghavendra K T 					size_t syncp_offset)
308c4c6bc31SRaghavendra K T {
309c4c6bc31SRaghavendra K T 	return snmp_get_cpu_field(mib, cpu, offct);
310c4c6bc31SRaghavendra K T 
311c4c6bc31SRaghavendra K T }
312c4c6bc31SRaghavendra K T 
313698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off)
3144ce3c183SEric Dumazet {
3154ce3c183SEric Dumazet 	return snmp_fold_field(mib, offt);
3164ce3c183SEric Dumazet }
3174ce3c183SEric Dumazet #endif
31833490170SYOSHIFUJI Hideaki 
3196348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \
3206348ef2dSJia He { \
3216348ef2dSJia He 	int i, c; \
3226348ef2dSJia He 	for_each_possible_cpu(c) { \
3236348ef2dSJia He 		for (i = 0; stats_list[i].name; i++) \
3246348ef2dSJia He 			buff64[i] += snmp_get_cpu_field64( \
3256348ef2dSJia He 					mib_statistic, \
3266348ef2dSJia He 					c, stats_list[i].entry, \
3276348ef2dSJia He 					offset); \
3286348ef2dSJia He 	} \
3296348ef2dSJia He }
3306348ef2dSJia He 
3316348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \
3326348ef2dSJia He { \
3336348ef2dSJia He 	int i, c; \
3346348ef2dSJia He 	for_each_possible_cpu(c) { \
3356348ef2dSJia He 		for (i = 0; stats_list[i].name; i++) \
3366348ef2dSJia He 			buff[i] += snmp_get_cpu_field( \
3376348ef2dSJia He 						mib_statistic, \
3386348ef2dSJia He 						c, stats_list[i].entry); \
3396348ef2dSJia He 	} \
3406348ef2dSJia He }
3416348ef2dSJia He 
3420bbf87d8SEric W. Biederman void inet_get_local_port_range(struct net *net, int *low, int *high);
343227b60f5SStephen Hemminger 
344fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL
34566e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
346e3826f1eSAmerigo Wang {
347122ff243SWANG Cong 	if (!net->ipv4.sysctl_local_reserved_ports)
34830429fbaSMaciej Żenczykowski 		return false;
349122ff243SWANG Cong 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
350e3826f1eSAmerigo Wang }
35120e61da7SWANG Cong 
35220e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name)
35320e61da7SWANG Cong {
35420e61da7SWANG Cong 	return strcmp(name, "default") != 0  && strcmp(name, "all") != 0;
35520e61da7SWANG Cong }
35620e61da7SWANG Cong 
35782f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3584548b683SKrister Johansen {
35982f31ebfSMaciej Żenczykowski 	return port < net->ipv4.sysctl_ip_prot_sock;
3604548b683SKrister Johansen }
3614548b683SKrister Johansen 
362122ff243SWANG Cong #else
36366e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
364122ff243SWANG Cong {
36530429fbaSMaciej Żenczykowski 	return false;
366122ff243SWANG Cong }
3674548b683SKrister Johansen 
36882f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3694548b683SKrister Johansen {
37082f31ebfSMaciej Żenczykowski 	return port < PROT_SOCK;
3714548b683SKrister Johansen }
372122ff243SWANG Cong #endif
373e3826f1eSAmerigo Wang 
374822c8685SDeepa Dinamani __be32 inet_current_timestamp(void);
375822c8685SDeepa Dinamani 
37620380731SArnaldo Carvalho de Melo /* From inetpeer.c */
37720380731SArnaldo Carvalho de Melo extern int inet_peer_threshold;
37820380731SArnaldo Carvalho de Melo extern int inet_peer_minttl;
37920380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl;
38020380731SArnaldo Carvalho de Melo 
3815c3a0fd7SJoe Perches void ipfrag_init(void);
38220380731SArnaldo Carvalho de Melo 
3835c3a0fd7SJoe Perches void ip_static_sysctl_init(void);
384bd7b1533SAl Viro 
385e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \
386e110861fSLorenzo Colitti 	((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0)
387e110861fSLorenzo Colitti 
388d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph)
389d18cd551SDavid S. Miller {
390d18cd551SDavid S. Miller 	return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
391d18cd551SDavid S. Miller }
392d18cd551SDavid S. Miller 
3931da177e4SLinus Torvalds #ifdef CONFIG_INET
39414c85021SArnaldo Carvalho de Melo #include <net/dst.h>
39514c85021SArnaldo Carvalho de Melo 
3961da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for
3971da177e4SLinus Torvalds  * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
3981da177e4SLinus Torvalds static inline
3991da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph)
4001da177e4SLinus Torvalds {
4015c78f275SAl Viro 	u32 check = (__force u32)iph->check;
4025c78f275SAl Viro 	check += (__force u32)htons(0x0100);
4035c78f275SAl Viro 	iph->check = (__force __sum16)(check + (check>=0xFFFF));
4041da177e4SLinus Torvalds 	return --iph->ttl;
4051da177e4SLinus Torvalds }
4061da177e4SLinus Torvalds 
407d52e5a7eSSabrina Dubroca static inline int ip_mtu_locked(const struct dst_entry *dst)
408d52e5a7eSSabrina Dubroca {
409d52e5a7eSSabrina Dubroca 	const struct rtable *rt = (const struct rtable *)dst;
410d52e5a7eSSabrina Dubroca 
411d52e5a7eSSabrina Dubroca 	return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU);
412d52e5a7eSSabrina Dubroca }
413d52e5a7eSSabrina Dubroca 
4141da177e4SLinus Torvalds static inline
4154e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst)
4161da177e4SLinus Torvalds {
4174e3f5d72SEric Dumazet 	u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
4184e3f5d72SEric Dumazet 
4194e3f5d72SEric Dumazet 	return  pmtudisc == IP_PMTUDISC_DO ||
4204e3f5d72SEric Dumazet 		(pmtudisc == IP_PMTUDISC_WANT &&
421d52e5a7eSSabrina Dubroca 		 !ip_mtu_locked(dst));
4221da177e4SLinus Torvalds }
4231da177e4SLinus Torvalds 
424f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk)
425f87c10a8SHannes Frederic Sowa {
4261b346576SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE &&
4271b346576SHannes Frederic Sowa 	       inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT;
428f87c10a8SHannes Frederic Sowa }
429f87c10a8SHannes Frederic Sowa 
430f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk)
431f87c10a8SHannes Frederic Sowa {
432f87c10a8SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
433f87c10a8SHannes Frederic Sowa }
434f87c10a8SHannes Frederic Sowa 
43560ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk)
4361b346576SHannes Frederic Sowa {
4371b346576SHannes Frederic Sowa 	return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO ||
4381b346576SHannes Frederic Sowa 	       inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT;
4391b346576SHannes Frederic Sowa }
4401b346576SHannes Frederic Sowa 
441f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
442f87c10a8SHannes Frederic Sowa 						    bool forwarding)
443f87c10a8SHannes Frederic Sowa {
444ac6627a2SVadim Fedorenko 	const struct rtable *rt = container_of(dst, struct rtable, dst);
445f87c10a8SHannes Frederic Sowa 	struct net *net = dev_net(dst->dev);
44602a1b175SMaciej Żenczykowski 	unsigned int mtu;
447f87c10a8SHannes Frederic Sowa 
448f87c10a8SHannes Frederic Sowa 	if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
449d52e5a7eSSabrina Dubroca 	    ip_mtu_locked(dst) ||
450ac6627a2SVadim Fedorenko 	    !forwarding) {
451ac6627a2SVadim Fedorenko 		mtu = rt->rt_pmtu;
452ac6627a2SVadim Fedorenko 		if (mtu && time_before(jiffies, rt->dst.expires))
453ac6627a2SVadim Fedorenko 			goto out;
454ac6627a2SVadim Fedorenko 	}
455f87c10a8SHannes Frederic Sowa 
45602a1b175SMaciej Żenczykowski 	/* 'forwarding = true' case should always honour route mtu */
45702a1b175SMaciej Żenczykowski 	mtu = dst_metric_raw(dst, RTAX_MTU);
458ac6627a2SVadim Fedorenko 	if (mtu)
459ac6627a2SVadim Fedorenko 		goto out;
460ac6627a2SVadim Fedorenko 
461ac6627a2SVadim Fedorenko 	mtu = READ_ONCE(dst->dev->mtu);
462ac6627a2SVadim Fedorenko 
463ac6627a2SVadim Fedorenko 	if (unlikely(ip_mtu_locked(dst))) {
464ac6627a2SVadim Fedorenko 		if (rt->rt_uses_gateway && mtu > 576)
465ac6627a2SVadim Fedorenko 			mtu = 576;
466ac6627a2SVadim Fedorenko 	}
467ac6627a2SVadim Fedorenko 
468ac6627a2SVadim Fedorenko out:
469ac6627a2SVadim Fedorenko 	mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
47002a1b175SMaciej Żenczykowski 
471fade5641SVadim Fedorenko 	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
472f87c10a8SHannes Frederic Sowa }
473f87c10a8SHannes Frederic Sowa 
474fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
475fedbb6b4SShmulik Ladkani 					  const struct sk_buff *skb)
476f87c10a8SHannes Frederic Sowa {
477fade5641SVadim Fedorenko 	unsigned int mtu;
478fade5641SVadim Fedorenko 
479caf3f267SEric Dumazet 	if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
480f87c10a8SHannes Frederic Sowa 		bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
481caf3f267SEric Dumazet 
482f87c10a8SHannes Frederic Sowa 		return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
483f87c10a8SHannes Frederic Sowa 	}
484caf3f267SEric Dumazet 
485fade5641SVadim Fedorenko 	mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
486fade5641SVadim Fedorenko 	return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
487f87c10a8SHannes Frederic Sowa }
488f87c10a8SHannes Frederic Sowa 
489767a2217SDavid Ahern struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
490d7e774f3SDavid Ahern 					int fc_mx_len,
491d7e774f3SDavid Ahern 					struct netlink_ext_ack *extack);
492cc5f0eb2SDavid Ahern static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics)
493cc5f0eb2SDavid Ahern {
494cc5f0eb2SDavid Ahern 	if (fib_metrics != &dst_default_metrics &&
495cc5f0eb2SDavid Ahern 	    refcount_dec_and_test(&fib_metrics->refcnt))
496cc5f0eb2SDavid Ahern 		kfree(fib_metrics);
497cc5f0eb2SDavid Ahern }
498a919525aSDavid Ahern 
499e1255ed4SDavid Ahern /* ipv4 and ipv6 both use refcounted metrics if it is not the default */
500e1255ed4SDavid Ahern static inline
501e1255ed4SDavid Ahern void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics)
502e1255ed4SDavid Ahern {
503e1255ed4SDavid Ahern 	dst_init_metrics(dst, fib_metrics->metrics, true);
504e1255ed4SDavid Ahern 
505e1255ed4SDavid Ahern 	if (fib_metrics != &dst_default_metrics) {
506e1255ed4SDavid Ahern 		dst->_metrics |= DST_METRICS_REFCOUNTED;
507e1255ed4SDavid Ahern 		refcount_inc(&fib_metrics->refcnt);
508e1255ed4SDavid Ahern 	}
509e1255ed4SDavid Ahern }
510e1255ed4SDavid Ahern 
5111620a336SDavid Ahern static inline
5121620a336SDavid Ahern void ip_dst_metrics_put(struct dst_entry *dst)
5131620a336SDavid Ahern {
5141620a336SDavid Ahern 	struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
5151620a336SDavid Ahern 
5161620a336SDavid Ahern 	if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
5171620a336SDavid Ahern 		kfree(p);
5181620a336SDavid Ahern }
5191620a336SDavid Ahern 
520b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
52173f156a6SEric Dumazet 
522b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
523b6a7719aSHannes Frederic Sowa 					struct sock *sk, int segs)
5241da177e4SLinus Torvalds {
525703133deSAnsis Atteka 	struct iphdr *iph = ip_hdr(skb);
526703133deSAnsis Atteka 
52723f57406SEric Dumazet 	/* We had many attacks based on IPID, use the private
52823f57406SEric Dumazet 	 * generator as much as we can.
5291da177e4SLinus Torvalds 	 */
530c720c7e8SEric Dumazet 	if (sk && inet_sk(sk)->inet_daddr) {
531c720c7e8SEric Dumazet 		iph->id = htons(inet_sk(sk)->inet_id);
53273f156a6SEric Dumazet 		inet_sk(sk)->inet_id += segs;
53323f57406SEric Dumazet 		return;
53473f156a6SEric Dumazet 	}
53523f57406SEric Dumazet 	if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
53623f57406SEric Dumazet 		iph->id = 0;
53773f156a6SEric Dumazet 	} else {
53823f57406SEric Dumazet 		/* Unfortunately we need the big hammer to get a suitable IPID */
539b6a7719aSHannes Frederic Sowa 		__ip_select_ident(net, iph, segs);
54073f156a6SEric Dumazet 	}
54173f156a6SEric Dumazet }
54273f156a6SEric Dumazet 
543b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
544b6a7719aSHannes Frederic Sowa 				   struct sock *sk)
54573f156a6SEric Dumazet {
546b6a7719aSHannes Frederic Sowa 	ip_select_ident_segs(net, skb, sk, 1);
5471da177e4SLinus Torvalds }
5481da177e4SLinus Torvalds 
549ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
550ed70fcfcSTom Herbert {
551ed70fcfcSTom Herbert 	return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
552ed70fcfcSTom Herbert 				  skb->len, proto, 0);
553ed70fcfcSTom Herbert }
554ed70fcfcSTom Herbert 
555c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store
556c3f83241STom Herbert  * Equivalent to :	flow->v4addrs.src = iph->saddr;
557c3f83241STom Herbert  *			flow->v4addrs.dst = iph->daddr;
558c3f83241STom Herbert  */
559c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow,
560c3f83241STom Herbert 					    const struct iphdr *iph)
561c3f83241STom Herbert {
562c3f83241STom Herbert 	BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) !=
563c3f83241STom Herbert 		     offsetof(typeof(flow->addrs), v4addrs.src) +
564c3f83241STom Herbert 			      sizeof(flow->addrs.v4addrs.src));
565c3f83241STom Herbert 	memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs));
566c3f83241STom Herbert 	flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
567c3f83241STom Herbert }
568c3f83241STom Herbert 
5691da177e4SLinus Torvalds /*
5701da177e4SLinus Torvalds  *	Map a multicast IP onto multicast MAC for type ethernet.
5711da177e4SLinus Torvalds  */
5721da177e4SLinus Torvalds 
573714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf)
5741da177e4SLinus Torvalds {
575714e85beSAl Viro 	__u32 addr=ntohl(naddr);
5761da177e4SLinus Torvalds 	buf[0]=0x01;
5771da177e4SLinus Torvalds 	buf[1]=0x00;
5781da177e4SLinus Torvalds 	buf[2]=0x5e;
5791da177e4SLinus Torvalds 	buf[5]=addr&0xFF;
5801da177e4SLinus Torvalds 	addr>>=8;
5811da177e4SLinus Torvalds 	buf[4]=addr&0xFF;
5821da177e4SLinus Torvalds 	addr>>=8;
5831da177e4SLinus Torvalds 	buf[3]=addr&0x7F;
5841da177e4SLinus Torvalds }
5851da177e4SLinus Torvalds 
5861da177e4SLinus Torvalds /*
5871da177e4SLinus Torvalds  *	Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
5881da177e4SLinus Torvalds  *	Leave P_Key as 0 to be filled in by driver.
5891da177e4SLinus Torvalds  */
5901da177e4SLinus Torvalds 
591a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
5921da177e4SLinus Torvalds {
593714e85beSAl Viro 	__u32 addr;
594a9e527e3SRolf Manderscheid 	unsigned char scope = broadcast[5] & 0xF;
595a9e527e3SRolf Manderscheid 
5961da177e4SLinus Torvalds 	buf[0]  = 0;		/* Reserved */
5971da177e4SLinus Torvalds 	buf[1]  = 0xff;		/* Multicast QPN */
5981da177e4SLinus Torvalds 	buf[2]  = 0xff;
5991da177e4SLinus Torvalds 	buf[3]  = 0xff;
600714e85beSAl Viro 	addr    = ntohl(naddr);
6011da177e4SLinus Torvalds 	buf[4]  = 0xff;
602a9e527e3SRolf Manderscheid 	buf[5]  = 0x10 | scope;	/* scope from broadcast address */
6031da177e4SLinus Torvalds 	buf[6]  = 0x40;		/* IPv4 signature */
6041da177e4SLinus Torvalds 	buf[7]  = 0x1b;
605a9e527e3SRolf Manderscheid 	buf[8]  = broadcast[8];		/* P_Key */
606a9e527e3SRolf Manderscheid 	buf[9]  = broadcast[9];
6071da177e4SLinus Torvalds 	buf[10] = 0;
6081da177e4SLinus Torvalds 	buf[11] = 0;
6091da177e4SLinus Torvalds 	buf[12] = 0;
6101da177e4SLinus Torvalds 	buf[13] = 0;
6111da177e4SLinus Torvalds 	buf[14] = 0;
6121da177e4SLinus Torvalds 	buf[15] = 0;
6131da177e4SLinus Torvalds 	buf[19] = addr & 0xff;
6141da177e4SLinus Torvalds 	addr  >>= 8;
6151da177e4SLinus Torvalds 	buf[18] = addr & 0xff;
6161da177e4SLinus Torvalds 	addr  >>= 8;
6171da177e4SLinus Torvalds 	buf[17] = addr & 0xff;
6181da177e4SLinus Torvalds 	addr  >>= 8;
6191da177e4SLinus Torvalds 	buf[16] = addr & 0x0f;
6201da177e4SLinus Torvalds }
6211da177e4SLinus Torvalds 
62293ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
62393ca3bb5STimo Teräs {
62493ca3bb5STimo Teräs 	if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
62593ca3bb5STimo Teräs 		memcpy(buf, broadcast, 4);
62693ca3bb5STimo Teräs 	else
62793ca3bb5STimo Teräs 		memcpy(buf, &naddr, sizeof(naddr));
62893ca3bb5STimo Teräs }
62993ca3bb5STimo Teräs 
630dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6311da177e4SLinus Torvalds #include <linux/ipv6.h>
6321da177e4SLinus Torvalds #endif
6331da177e4SLinus Torvalds 
6341da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk)
6351da177e4SLinus Torvalds {
636c720c7e8SEric Dumazet 	inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
637dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6381da177e4SLinus Torvalds 	if (sk->sk_family == PF_INET6) {
6391da177e4SLinus Torvalds 		struct ipv6_pinfo *np = inet6_sk(sk);
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 		memset(&np->saddr, 0, sizeof(np->saddr));
642efe4208fSEric Dumazet 		memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr));
6431da177e4SLinus Torvalds 	}
6441da177e4SLinus Torvalds #endif
6451da177e4SLinus Torvalds }
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds #endif
6481da177e4SLinus Torvalds 
64972afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip)
65072afa352SDavid Ahern {
65172afa352SDavid Ahern 	return (__force unsigned int) ip;
65272afa352SDavid Ahern }
65372afa352SDavid Ahern 
654f0b1e64cSMartin KaFai Lau static inline u32 ipv4_portaddr_hash(const struct net *net,
655f0b1e64cSMartin KaFai Lau 				     __be32 saddr,
656f0b1e64cSMartin KaFai Lau 				     unsigned int port)
657f0b1e64cSMartin KaFai Lau {
658f0b1e64cSMartin KaFai Lau 	return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
659f0b1e64cSMartin KaFai Lau }
660f0b1e64cSMartin KaFai Lau 
6615c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb);
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds /*
664b798232fSRami Rosen  *	Functions provided by ip_fragment.c
6651da177e4SLinus Torvalds  */
6661da177e4SLinus Torvalds 
667fd2c3ef7SEric Dumazet enum ip_defrag_users {
6681da177e4SLinus Torvalds 	IP_DEFRAG_LOCAL_DELIVER,
6691da177e4SLinus Torvalds 	IP_DEFRAG_CALL_RA_CHAIN,
6701da177e4SLinus Torvalds 	IP_DEFRAG_CONNTRACK_IN,
6714be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_IN_END	= IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
6721da177e4SLinus Torvalds 	IP_DEFRAG_CONNTRACK_OUT,
6734be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_OUT_END	= IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
6748fa9ff68SPatrick McHardy 	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
6754be929beSAlexey Dobriyan 	__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
6761da177e4SLinus Torvalds 	IP_DEFRAG_VS_IN,
6771da177e4SLinus Torvalds 	IP_DEFRAG_VS_OUT,
678595fc71bSDavid S. Miller 	IP_DEFRAG_VS_FWD,
679595fc71bSDavid S. Miller 	IP_DEFRAG_AF_PACKET,
680bc416d97SEric Dumazet 	IP_DEFRAG_MACVLAN,
6811da177e4SLinus Torvalds };
6821da177e4SLinus Torvalds 
6835cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond'
6845cf42280SAndy Zhou  * and 'upper_bond' inclusively.
6855cf42280SAndy Zhou  */
6865cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user,
6875cf42280SAndy Zhou 					     enum ip_defrag_users lower_bond,
6885cf42280SAndy Zhou 					     enum ip_defrag_users upper_bond)
6895cf42280SAndy Zhou {
6905cf42280SAndy Zhou 	return user >= lower_bond && user <= upper_bond;
6915cf42280SAndy Zhou }
6925cf42280SAndy Zhou 
69319bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
694bc416d97SEric Dumazet #ifdef CONFIG_INET
69519bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
696bc416d97SEric Dumazet #else
69719bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
698bc416d97SEric Dumazet {
699bc416d97SEric Dumazet 	return skb;
700bc416d97SEric Dumazet }
701bc416d97SEric Dumazet #endif
7021da177e4SLinus Torvalds 
7031da177e4SLinus Torvalds /*
7041da177e4SLinus Torvalds  *	Functions provided by ip_forward.c
7051da177e4SLinus Torvalds  */
7061da177e4SLinus Torvalds 
7075c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb);
7081da177e4SLinus Torvalds 
7091da177e4SLinus Torvalds /*
7101da177e4SLinus Torvalds  *	Functions provided by ip_options.c
7111da177e4SLinus Torvalds  */
7121da177e4SLinus Torvalds 
7135c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
7144f0e3040SJakub Kicinski 		      __be32 daddr, struct rtable *rt);
71524a2d43dSEric Dumazet 
71691ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt,
71791ed1e66SPaolo Abeni 		      struct sk_buff *skb, const struct ip_options *sopt);
71891ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
71991ed1e66SPaolo Abeni 				  struct sk_buff *skb)
72024a2d43dSEric Dumazet {
72191ed1e66SPaolo Abeni 	return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
72224a2d43dSEric Dumazet }
72324a2d43dSEric Dumazet 
7245c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb);
7253da1ed7aSNazarov Sergey int __ip_options_compile(struct net *net, struct ip_options *opt,
7263da1ed7aSNazarov Sergey 			 struct sk_buff *skb, __be32 *info);
7275c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt,
7285c3a0fd7SJoe Perches 		       struct sk_buff *skb);
7295c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp,
730de40a3e8SChristoph Hellwig 		   sockptr_t data, int optlen);
7315c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt);
7325c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb);
7338c83f2dfSStephen Suryaputra int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
7341da177e4SLinus Torvalds 
7351da177e4SLinus Torvalds /*
7361da177e4SLinus Torvalds  *	Functions provided by ip_sockglue.c
7371da177e4SLinus Torvalds  */
7381da177e4SLinus Torvalds 
739fbf8866dSShawn Bohrer void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
740ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
741ad959036SPaolo Abeni 			 struct sk_buff *skb, int tlen, int offset);
74224025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
743c8e6ad08SHannes Frederic Sowa 		 struct ipcm_cookie *ipc, bool allow_ipv6);
744020e71a3SEric Dumazet DECLARE_STATIC_KEY_FALSE(ip4_min_ttl);
745a7b75c5aSChristoph Hellwig int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
7465c3a0fd7SJoe Perches 		  unsigned int optlen);
7475c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
7485c3a0fd7SJoe Perches 		  int __user *optlen);
7495c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on,
7505c3a0fd7SJoe Perches 		  void (*destructor)(struct sock *));
7511da177e4SLinus Torvalds 
75285fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
7535c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
7545c3a0fd7SJoe Perches 		   u32 info, u8 *payload);
7555c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
7561da177e4SLinus Torvalds 		    u32 info);
7571da177e4SLinus Torvalds 
7585961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
7595961de9fSTom Herbert {
760ad959036SPaolo Abeni 	ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
7615961de9fSTom Herbert }
7625961de9fSTom Herbert 
7634cdf507dSEric Dumazet bool icmp_global_allow(void);
7644cdf507dSEric Dumazet extern int sysctl_icmp_msgs_per_sec;
7654cdf507dSEric Dumazet extern int sysctl_icmp_msgs_burst;
7664cdf507dSEric Dumazet 
76720380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS
7685c3a0fd7SJoe Perches int ip_misc_proc_init(void);
76920380731SArnaldo Carvalho de Melo #endif
77020380731SArnaldo Carvalho de Melo 
7715e1a99eaSHangbin Liu int rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family,
772404eb77eSRoopa Prabhu 				struct netlink_ext_ack *extack);
773404eb77eSRoopa Prabhu 
774501a90c9SEric Dumazet static inline bool inetdev_valid_mtu(unsigned int mtu)
775501a90c9SEric Dumazet {
776501a90c9SEric Dumazet 	return likely(mtu >= IPV4_MIN_MTU);
777501a90c9SEric Dumazet }
778501a90c9SEric Dumazet 
779c4e446bfSChristoph Hellwig void ip_sock_set_freebind(struct sock *sk);
7802de569bdSChristoph Hellwig int ip_sock_set_mtu_discover(struct sock *sk, int val);
781c1f9ec57SChristoph Hellwig void ip_sock_set_pktinfo(struct sock *sk);
782db45c0efSChristoph Hellwig void ip_sock_set_recverr(struct sock *sk);
7836ebf71baSChristoph Hellwig void ip_sock_set_tos(struct sock *sk, int val);
7844f47d5d5SPoorva Sonparote void  __ip_sock_set_tos(struct sock *sk, int val);
7856ebf71baSChristoph Hellwig 
7861da177e4SLinus Torvalds #endif	/* _IP_H */
787