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)
606ac66cb0SSriram Yagnaraman #define IPSKB_MULTIPATH BIT(9)
615f2d04f1SPatrick McHardy
625f2d04f1SPatrick McHardy u16 frag_max_size;
631da177e4SLinus Torvalds };
641da177e4SLinus Torvalds
ipv4_l3mdev_skb(u16 flags)65a04a480dSDavid Ahern static inline bool ipv4_l3mdev_skb(u16 flags)
66a04a480dSDavid Ahern {
67a04a480dSDavid Ahern return !!(flags & IPSKB_L3SLAVE);
68a04a480dSDavid Ahern }
69a04a480dSDavid Ahern
ip_hdrlen(const struct sk_buff * skb)70c9bdd4b5SArnaldo Carvalho de Melo static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
71c9bdd4b5SArnaldo Carvalho de Melo {
72eddc9ec5SArnaldo Carvalho de Melo return ip_hdr(skb)->ihl * 4;
73c9bdd4b5SArnaldo Carvalho de Melo }
74c9bdd4b5SArnaldo Carvalho de Melo
75fd2c3ef7SEric Dumazet struct ipcm_cookie {
7624025c46SSoheil Hassas Yeganeh struct sockcm_cookie sockc;
77c1d18f9fSAl Viro __be32 addr;
781da177e4SLinus Torvalds int oif;
79f6d8bd05SEric Dumazet struct ip_options_rcu *opt;
803632679dSNicolas Dichtel __u8 protocol;
81f02db315SFrancesco Fusco __u8 ttl;
82f02db315SFrancesco Fusco __s16 tos;
83f02db315SFrancesco Fusco char priority;
84bec1f6f6SWillem de Bruijn __u16 gso_size;
851da177e4SLinus Torvalds };
861da177e4SLinus Torvalds
ipcm_init(struct ipcm_cookie * ipcm)8735178206SWillem de Bruijn static inline void ipcm_init(struct ipcm_cookie *ipcm)
8835178206SWillem de Bruijn {
8935178206SWillem de Bruijn *ipcm = (struct ipcm_cookie) { .tos = -1 };
9035178206SWillem de Bruijn }
9135178206SWillem de Bruijn
ipcm_init_sk(struct ipcm_cookie * ipcm,const struct inet_sock * inet)9235178206SWillem de Bruijn static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
9335178206SWillem de Bruijn const struct inet_sock *inet)
9435178206SWillem de Bruijn {
9535178206SWillem de Bruijn ipcm_init(ipcm);
9635178206SWillem de Bruijn
973c5b4d69SEric Dumazet ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
98e3390b30SEric Dumazet ipcm->sockc.tsflags = READ_ONCE(inet->sk.sk_tsflags);
994c971d2fSEric Dumazet ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
10035178206SWillem de Bruijn ipcm->addr = inet->inet_saddr;
1013632679dSNicolas Dichtel ipcm->protocol = inet->inet_num;
10235178206SWillem de Bruijn }
10335178206SWillem de Bruijn
1041da177e4SLinus Torvalds #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
1054b261c75SHannes Frederic Sowa #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
1061da177e4SLinus Torvalds
107fb74c277SDavid Ahern /* return enslaved device index if relevant */
inet_sdif(const struct sk_buff * skb)108d6bb2d1eSEric Dumazet static inline int inet_sdif(const struct sk_buff *skb)
109fb74c277SDavid Ahern {
110fb74c277SDavid Ahern #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
111fb74c277SDavid Ahern if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
112fb74c277SDavid Ahern return IPCB(skb)->iif;
113fb74c277SDavid Ahern #endif
114fb74c277SDavid Ahern return 0;
115fb74c277SDavid Ahern }
116fb74c277SDavid Ahern
1175796ef75SKirill Tkhai /* Special input handler for packets caught by router alert option.
1185796ef75SKirill Tkhai They are selected only by protocol field, and then processed likely
1195796ef75SKirill Tkhai local ones; but only if someone wants them! Otherwise, router
1205796ef75SKirill Tkhai not running rsvpd will kill RSVP.
1215796ef75SKirill Tkhai
1225796ef75SKirill Tkhai It is user level problem, what it will make with them.
1235796ef75SKirill Tkhai I have no idea, how it will masquearde or NAT them (it is joke, joke :-)),
1245796ef75SKirill Tkhai but receiver should be enough clever f.e. to forward mtrace requests,
1255796ef75SKirill Tkhai sent to multicast group to reach destination designated router.
1265796ef75SKirill Tkhai */
1275796ef75SKirill Tkhai
128fd2c3ef7SEric Dumazet struct ip_ra_chain {
12943a951e9SEric Dumazet struct ip_ra_chain __rcu *next;
1301da177e4SLinus Torvalds struct sock *sk;
131592fcb9dSEric Dumazet union {
1321da177e4SLinus Torvalds void (*destructor)(struct sock *);
133592fcb9dSEric Dumazet struct sock *saved_sk;
134592fcb9dSEric Dumazet };
13566018506SEric Dumazet struct rcu_head rcu;
1361da177e4SLinus Torvalds };
1371da177e4SLinus Torvalds
1381da177e4SLinus Torvalds /* IP flags. */
1391da177e4SLinus Torvalds #define IP_CE 0x8000 /* Flag: "Congestion" */
1401da177e4SLinus Torvalds #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
1411da177e4SLinus Torvalds #define IP_MF 0x2000 /* Flag: "More Fragments" */
1421da177e4SLinus Torvalds #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
1451da177e4SLinus Torvalds
14614c85021SArnaldo Carvalho de Melo struct msghdr;
14714c85021SArnaldo Carvalho de Melo struct net_device;
14814c85021SArnaldo Carvalho de Melo struct packet_type;
14914c85021SArnaldo Carvalho de Melo struct rtable;
15014c85021SArnaldo Carvalho de Melo struct sockaddr;
15114c85021SArnaldo Carvalho de Melo
15272c1d3bdSWANG Cong int igmp_mc_init(void);
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds * Functions provided by ip.c
1561da177e4SLinus Torvalds */
1571da177e4SLinus Torvalds
158cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
15913d8eaa0SAl Viro __be32 saddr, __be32 daddr,
160de033b7dSWei Wang struct ip_options_rcu *opt, u8 tos);
1615c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
1625c3a0fd7SJoe Perches struct net_device *orig_dev);
16317266ee9SEdward Cree void ip_list_rcv(struct list_head *head, struct packet_type *pt,
16417266ee9SEdward Cree struct net_device *orig_dev);
1655c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb);
16668cb7d53SPaolo Abeni void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
1675c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb);
168ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
169ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
170694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
171694869b3SEric W. Biederman int (*output)(struct net *, struct sock *, struct sk_buff *));
172c8b17be0SPablo Neira Ayuso
173c8b17be0SPablo Neira Ayuso struct ip_fraglist_iter {
174c8b17be0SPablo Neira Ayuso struct sk_buff *frag;
175c8b17be0SPablo Neira Ayuso struct iphdr *iph;
176c8b17be0SPablo Neira Ayuso int offset;
177c8b17be0SPablo Neira Ayuso unsigned int hlen;
178c8b17be0SPablo Neira Ayuso };
179c8b17be0SPablo Neira Ayuso
180c8b17be0SPablo Neira Ayuso void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
181c8b17be0SPablo Neira Ayuso unsigned int hlen, struct ip_fraglist_iter *iter);
182c8b17be0SPablo Neira Ayuso void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter);
183c8b17be0SPablo Neira Ayuso
ip_fraglist_next(struct ip_fraglist_iter * iter)184c8b17be0SPablo Neira Ayuso static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter)
185c8b17be0SPablo Neira Ayuso {
186c8b17be0SPablo Neira Ayuso struct sk_buff *skb = iter->frag;
187c8b17be0SPablo Neira Ayuso
188c8b17be0SPablo Neira Ayuso iter->frag = skb->next;
189c8b17be0SPablo Neira Ayuso skb_mark_not_on_list(skb);
190c8b17be0SPablo Neira Ayuso
191c8b17be0SPablo Neira Ayuso return skb;
192c8b17be0SPablo Neira Ayuso }
193c8b17be0SPablo Neira Ayuso
194065ff79fSPablo Neira Ayuso struct ip_frag_state {
195e7a409c3SEric Dumazet bool DF;
196065ff79fSPablo Neira Ayuso unsigned int hlen;
197065ff79fSPablo Neira Ayuso unsigned int ll_rs;
198065ff79fSPablo Neira Ayuso unsigned int mtu;
199065ff79fSPablo Neira Ayuso unsigned int left;
200065ff79fSPablo Neira Ayuso int offset;
201065ff79fSPablo Neira Ayuso int ptr;
202065ff79fSPablo Neira Ayuso __be16 not_last_frag;
203065ff79fSPablo Neira Ayuso };
204065ff79fSPablo Neira Ayuso
205065ff79fSPablo Neira Ayuso void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
206e7a409c3SEric Dumazet unsigned int mtu, bool DF, struct ip_frag_state *state);
207065ff79fSPablo Neira Ayuso struct sk_buff *ip_frag_next(struct sk_buff *skb,
208065ff79fSPablo Neira Ayuso struct ip_frag_state *state);
209065ff79fSPablo Neira Ayuso
2105c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip);
211cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
21233224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
213aad88724SEric Dumazet
21469b9e1e0SXin Long int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
21569b9e1e0SXin Long __u8 tos);
2165c3a0fd7SJoe Perches void ip_init(void);
2175c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4,
2181da177e4SLinus Torvalds int getfrag(void *from, char *to, int offset, int len,
2191da177e4SLinus Torvalds int odd, struct sk_buff *skb),
2201da177e4SLinus Torvalds void *from, int len, int protolen,
2211da177e4SLinus Torvalds struct ipcm_cookie *ipc,
2222e77d89bSEric Dumazet struct rtable **rt,
2231da177e4SLinus Torvalds unsigned int flags);
2245c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
2255c3a0fd7SJoe Perches struct sk_buff *skb);
2265c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2271c32c5adSHerbert Xu struct sk_buff_head *queue,
2281c32c5adSHerbert Xu struct inet_cork *cork);
2295c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb);
2305c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
2315c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk);
2325c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2335c3a0fd7SJoe Perches int getfrag(void *from, char *to, int offset,
2345c3a0fd7SJoe Perches int len, int odd, struct sk_buff *skb),
2351c32c5adSHerbert Xu void *from, int length, int transhdrlen,
2365c3a0fd7SJoe Perches struct ipcm_cookie *ipc, struct rtable **rtp,
2371cd7884dSWillem de Bruijn struct inet_cork *cork, unsigned int flags);
2381c32c5adSHerbert Xu
23905e22e83SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
24069b9e1e0SXin Long
ip_finish_skb(struct sock * sk,struct flowi4 * fl4)24177968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
2421c32c5adSHerbert Xu {
24377968b78SDavid S. Miller return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
2441c32c5adSHerbert Xu }
2451da177e4SLinus Torvalds
246726de790SGuillaume Nault /* Get the route scope that should be used when sending a packet. */
ip_sendmsg_scope(const struct inet_sock * inet,const struct ipcm_cookie * ipc,const struct msghdr * msg)247726de790SGuillaume Nault static inline u8 ip_sendmsg_scope(const struct inet_sock *inet,
248726de790SGuillaume Nault const struct ipcm_cookie *ipc,
249726de790SGuillaume Nault const struct msghdr *msg)
250726de790SGuillaume Nault {
251726de790SGuillaume Nault if (sock_flag(&inet->sk, SOCK_LOCALROUTE) ||
252726de790SGuillaume Nault msg->msg_flags & MSG_DONTROUTE ||
253726de790SGuillaume Nault (ipc->opt && ipc->opt->opt.is_strictroute))
254726de790SGuillaume Nault return RT_SCOPE_LINK;
255726de790SGuillaume Nault
256726de790SGuillaume Nault return RT_SCOPE_UNIVERSE;
257726de790SGuillaume Nault }
258726de790SGuillaume Nault
get_rttos(struct ipcm_cookie * ipc,struct inet_sock * inet)259aa661581SFrancesco Fusco static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet)
260aa661581SFrancesco Fusco {
261aa661581SFrancesco Fusco return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos);
262aa661581SFrancesco Fusco }
263aa661581SFrancesco Fusco
2641da177e4SLinus Torvalds /* datagram.c */
26503645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2665c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2671da177e4SLinus Torvalds
2685c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk);
2698141ed9fSSteffen Klassert
2701da177e4SLinus Torvalds struct ip_reply_arg {
2711da177e4SLinus Torvalds struct kvec iov[1];
27288ef4a5aSKOVACS Krisztian int flags;
273d6f5493cSAl Viro __wsum csum;
2741da177e4SLinus Torvalds int csumoffset; /* u16 offset of csum in iov[0].iov_base */
2751da177e4SLinus Torvalds /* -1 if not needed */
276f0e48dbfSPatrick McHardy int bound_dev_if;
27766b13d99SEric Dumazet u8 tos;
278e2d118a1SLorenzo Colitti kuid_t uid;
2791da177e4SLinus Torvalds };
2801da177e4SLinus Torvalds
28188ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1
28288ef4a5aSKOVACS Krisztian
ip_reply_arg_flowi_flags(const struct ip_reply_arg * arg)28386b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
28486b08d86SKOVACS Krisztian {
28586b08d86SKOVACS Krisztian return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
28686b08d86SKOVACS Krisztian }
28786b08d86SKOVACS Krisztian
288bdbbb852SEric Dumazet void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
28924a2d43dSEric Dumazet const struct ip_options *sopt,
29024a2d43dSEric Dumazet __be32 daddr, __be32 saddr,
29124a2d43dSEric Dumazet const struct ip_reply_arg *arg,
292c0a8966eSAntoine Tenart unsigned int len, u64 transmit_time, u32 txhash);
2931da177e4SLinus Torvalds
2944ce3c183SEric Dumazet #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
29513415e46SEric Dumazet #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field)
2964ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
29713415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
2984ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29913415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
30061a7e260SPavel Emelyanov #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
30113415e46SEric Dumazet #define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field)
302f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
30313415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
3041da177e4SLinus Torvalds
snmp_get_cpu_field(void __percpu * mib,int cpu,int offt)30559f09ae8SEric Dumazet static inline u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt)
30659f09ae8SEric Dumazet {
30759f09ae8SEric Dumazet return *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt);
30859f09ae8SEric Dumazet }
30959f09ae8SEric Dumazet
310698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt);
3114ce3c183SEric Dumazet #if BITS_PER_LONG==32
312c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
313c4c6bc31SRaghavendra K T size_t syncp_offset);
314698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off);
3154ce3c183SEric Dumazet #else
snmp_get_cpu_field64(void __percpu * mib,int cpu,int offct,size_t syncp_offset)316c4c6bc31SRaghavendra K T static inline u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
317c4c6bc31SRaghavendra K T size_t syncp_offset)
318c4c6bc31SRaghavendra K T {
319c4c6bc31SRaghavendra K T return snmp_get_cpu_field(mib, cpu, offct);
320c4c6bc31SRaghavendra K T
321c4c6bc31SRaghavendra K T }
322c4c6bc31SRaghavendra K T
snmp_fold_field64(void __percpu * mib,int offt,size_t syncp_off)323698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off)
3244ce3c183SEric Dumazet {
3254ce3c183SEric Dumazet return snmp_fold_field(mib, offt);
3264ce3c183SEric Dumazet }
3274ce3c183SEric Dumazet #endif
32833490170SYOSHIFUJI Hideaki
3296348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \
3306348ef2dSJia He { \
3316348ef2dSJia He int i, c; \
3326348ef2dSJia He for_each_possible_cpu(c) { \
3336348ef2dSJia He for (i = 0; stats_list[i].name; i++) \
3346348ef2dSJia He buff64[i] += snmp_get_cpu_field64( \
3356348ef2dSJia He mib_statistic, \
3366348ef2dSJia He c, stats_list[i].entry, \
3376348ef2dSJia He offset); \
3386348ef2dSJia He } \
3396348ef2dSJia He }
3406348ef2dSJia He
3416348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \
3426348ef2dSJia He { \
3436348ef2dSJia He int i, c; \
3446348ef2dSJia He for_each_possible_cpu(c) { \
3456348ef2dSJia He for (i = 0; stats_list[i].name; i++) \
3466348ef2dSJia He buff[i] += snmp_get_cpu_field( \
3476348ef2dSJia He mib_statistic, \
3486348ef2dSJia He c, stats_list[i].entry); \
3496348ef2dSJia He } \
3506348ef2dSJia He }
3516348ef2dSJia He
35291d0b78cSJakub Sitnicki void inet_get_local_port_range(const struct net *net, int *low, int *high);
35391d0b78cSJakub Sitnicki void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high);
354227b60f5SStephen Hemminger
355fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL
inet_is_local_reserved_port(struct net * net,unsigned short port)35666e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
357e3826f1eSAmerigo Wang {
358122ff243SWANG Cong if (!net->ipv4.sysctl_local_reserved_ports)
35930429fbaSMaciej Żenczykowski return false;
360122ff243SWANG Cong return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
361e3826f1eSAmerigo Wang }
36220e61da7SWANG Cong
sysctl_dev_name_is_allowed(const char * name)36320e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name)
36420e61da7SWANG Cong {
36520e61da7SWANG Cong return strcmp(name, "default") != 0 && strcmp(name, "all") != 0;
36620e61da7SWANG Cong }
36720e61da7SWANG Cong
inet_port_requires_bind_service(struct net * net,unsigned short port)36882f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3694548b683SKrister Johansen {
3709b55c20fSKuniyuki Iwashima return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock);
3714548b683SKrister Johansen }
3724548b683SKrister Johansen
373122ff243SWANG Cong #else
inet_is_local_reserved_port(struct net * net,unsigned short port)37466e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
375122ff243SWANG Cong {
37630429fbaSMaciej Żenczykowski return false;
377122ff243SWANG Cong }
3784548b683SKrister Johansen
inet_port_requires_bind_service(struct net * net,unsigned short port)37982f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3804548b683SKrister Johansen {
38182f31ebfSMaciej Żenczykowski return port < PROT_SOCK;
3824548b683SKrister Johansen }
383122ff243SWANG Cong #endif
384e3826f1eSAmerigo Wang
385822c8685SDeepa Dinamani __be32 inet_current_timestamp(void);
386822c8685SDeepa Dinamani
38720380731SArnaldo Carvalho de Melo /* From inetpeer.c */
38820380731SArnaldo Carvalho de Melo extern int inet_peer_threshold;
38920380731SArnaldo Carvalho de Melo extern int inet_peer_minttl;
39020380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl;
39120380731SArnaldo Carvalho de Melo
3925c3a0fd7SJoe Perches void ipfrag_init(void);
39320380731SArnaldo Carvalho de Melo
3945c3a0fd7SJoe Perches void ip_static_sysctl_init(void);
395bd7b1533SAl Viro
396e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \
39785d0b4dbSKuniyuki Iwashima (READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0)
398e110861fSLorenzo Colitti
ip_is_fragment(const struct iphdr * iph)399d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph)
400d18cd551SDavid S. Miller {
401d18cd551SDavid S. Miller return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
402d18cd551SDavid S. Miller }
403d18cd551SDavid S. Miller
4041da177e4SLinus Torvalds #ifdef CONFIG_INET
40514c85021SArnaldo Carvalho de Melo #include <net/dst.h>
40614c85021SArnaldo Carvalho de Melo
4071da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for
4081da177e4SLinus Torvalds * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
4091da177e4SLinus Torvalds static inline
ip_decrease_ttl(struct iphdr * iph)4101da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph)
4111da177e4SLinus Torvalds {
4125c78f275SAl Viro u32 check = (__force u32)iph->check;
4135c78f275SAl Viro check += (__force u32)htons(0x0100);
4145c78f275SAl Viro iph->check = (__force __sum16)(check + (check>=0xFFFF));
4151da177e4SLinus Torvalds return --iph->ttl;
4161da177e4SLinus Torvalds }
4171da177e4SLinus Torvalds
ip4h_dscp(const struct iphdr * ip4h)418*661c63cbSGuillaume Nault static inline dscp_t ip4h_dscp(const struct iphdr *ip4h)
419*661c63cbSGuillaume Nault {
420*661c63cbSGuillaume Nault return inet_dsfield_to_dscp(ip4h->tos);
421*661c63cbSGuillaume Nault }
422*661c63cbSGuillaume Nault
ip_mtu_locked(const struct dst_entry * dst)423d52e5a7eSSabrina Dubroca static inline int ip_mtu_locked(const struct dst_entry *dst)
424d52e5a7eSSabrina Dubroca {
425d52e5a7eSSabrina Dubroca const struct rtable *rt = (const struct rtable *)dst;
426d52e5a7eSSabrina Dubroca
427d52e5a7eSSabrina Dubroca return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU);
428d52e5a7eSSabrina Dubroca }
429d52e5a7eSSabrina Dubroca
4301da177e4SLinus Torvalds static inline
ip_dont_fragment(const struct sock * sk,const struct dst_entry * dst)4314e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst)
4321da177e4SLinus Torvalds {
4334e3f5d72SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
4344e3f5d72SEric Dumazet
4354e3f5d72SEric Dumazet return pmtudisc == IP_PMTUDISC_DO ||
4364e3f5d72SEric Dumazet (pmtudisc == IP_PMTUDISC_WANT &&
437d52e5a7eSSabrina Dubroca !ip_mtu_locked(dst));
4381da177e4SLinus Torvalds }
4391da177e4SLinus Torvalds
ip_sk_accept_pmtu(const struct sock * sk)440f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk)
441f87c10a8SHannes Frederic Sowa {
4421b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE &&
4431b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT;
444f87c10a8SHannes Frederic Sowa }
445f87c10a8SHannes Frederic Sowa
ip_sk_use_pmtu(const struct sock * sk)446f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk)
447f87c10a8SHannes Frederic Sowa {
448f87c10a8SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
449f87c10a8SHannes Frederic Sowa }
450f87c10a8SHannes Frederic Sowa
ip_sk_ignore_df(const struct sock * sk)45160ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk)
4521b346576SHannes Frederic Sowa {
4531b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO ||
4541b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT;
4551b346576SHannes Frederic Sowa }
4561b346576SHannes Frederic Sowa
ip_dst_mtu_maybe_forward(const struct dst_entry * dst,bool forwarding)457f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
458f87c10a8SHannes Frederic Sowa bool forwarding)
459f87c10a8SHannes Frederic Sowa {
460ac6627a2SVadim Fedorenko const struct rtable *rt = container_of(dst, struct rtable, dst);
461f87c10a8SHannes Frederic Sowa struct net *net = dev_net(dst->dev);
46202a1b175SMaciej Żenczykowski unsigned int mtu;
463f87c10a8SHannes Frederic Sowa
46460c158dcSKuniyuki Iwashima if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
465d52e5a7eSSabrina Dubroca ip_mtu_locked(dst) ||
466ac6627a2SVadim Fedorenko !forwarding) {
467ac6627a2SVadim Fedorenko mtu = rt->rt_pmtu;
468ac6627a2SVadim Fedorenko if (mtu && time_before(jiffies, rt->dst.expires))
469ac6627a2SVadim Fedorenko goto out;
470ac6627a2SVadim Fedorenko }
471f87c10a8SHannes Frederic Sowa
47202a1b175SMaciej Żenczykowski /* 'forwarding = true' case should always honour route mtu */
47302a1b175SMaciej Żenczykowski mtu = dst_metric_raw(dst, RTAX_MTU);
474ac6627a2SVadim Fedorenko if (mtu)
475ac6627a2SVadim Fedorenko goto out;
476ac6627a2SVadim Fedorenko
477ac6627a2SVadim Fedorenko mtu = READ_ONCE(dst->dev->mtu);
478ac6627a2SVadim Fedorenko
479ac6627a2SVadim Fedorenko if (unlikely(ip_mtu_locked(dst))) {
480ac6627a2SVadim Fedorenko if (rt->rt_uses_gateway && mtu > 576)
481ac6627a2SVadim Fedorenko mtu = 576;
482ac6627a2SVadim Fedorenko }
483ac6627a2SVadim Fedorenko
484ac6627a2SVadim Fedorenko out:
485ac6627a2SVadim Fedorenko mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
48602a1b175SMaciej Żenczykowski
487fade5641SVadim Fedorenko return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
488f87c10a8SHannes Frederic Sowa }
489f87c10a8SHannes Frederic Sowa
ip_skb_dst_mtu(struct sock * sk,const struct sk_buff * skb)490fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
491fedbb6b4SShmulik Ladkani const struct sk_buff *skb)
492f87c10a8SHannes Frederic Sowa {
493fade5641SVadim Fedorenko unsigned int mtu;
494fade5641SVadim Fedorenko
495caf3f267SEric Dumazet if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
496f87c10a8SHannes Frederic Sowa bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
497caf3f267SEric Dumazet
498f87c10a8SHannes Frederic Sowa return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
499f87c10a8SHannes Frederic Sowa }
500caf3f267SEric Dumazet
501fade5641SVadim Fedorenko mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
502fade5641SVadim Fedorenko return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
503f87c10a8SHannes Frederic Sowa }
504f87c10a8SHannes Frederic Sowa
50569f397e6SJason Xing struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
506d7e774f3SDavid Ahern struct netlink_ext_ack *extack);
ip_fib_metrics_put(struct dst_metrics * fib_metrics)507cc5f0eb2SDavid Ahern static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics)
508cc5f0eb2SDavid Ahern {
509cc5f0eb2SDavid Ahern if (fib_metrics != &dst_default_metrics &&
510cc5f0eb2SDavid Ahern refcount_dec_and_test(&fib_metrics->refcnt))
511cc5f0eb2SDavid Ahern kfree(fib_metrics);
512cc5f0eb2SDavid Ahern }
513a919525aSDavid Ahern
514e1255ed4SDavid Ahern /* ipv4 and ipv6 both use refcounted metrics if it is not the default */
515e1255ed4SDavid Ahern static inline
ip_dst_init_metrics(struct dst_entry * dst,struct dst_metrics * fib_metrics)516e1255ed4SDavid Ahern void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics)
517e1255ed4SDavid Ahern {
518e1255ed4SDavid Ahern dst_init_metrics(dst, fib_metrics->metrics, true);
519e1255ed4SDavid Ahern
520e1255ed4SDavid Ahern if (fib_metrics != &dst_default_metrics) {
521e1255ed4SDavid Ahern dst->_metrics |= DST_METRICS_REFCOUNTED;
522e1255ed4SDavid Ahern refcount_inc(&fib_metrics->refcnt);
523e1255ed4SDavid Ahern }
524e1255ed4SDavid Ahern }
525e1255ed4SDavid Ahern
5261620a336SDavid Ahern static inline
ip_dst_metrics_put(struct dst_entry * dst)5271620a336SDavid Ahern void ip_dst_metrics_put(struct dst_entry *dst)
5281620a336SDavid Ahern {
5291620a336SDavid Ahern struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
5301620a336SDavid Ahern
5311620a336SDavid Ahern if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
5321620a336SDavid Ahern kfree(p);
5331620a336SDavid Ahern }
5341620a336SDavid Ahern
535b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
53673f156a6SEric Dumazet
ip_select_ident_segs(struct net * net,struct sk_buff * skb,struct sock * sk,int segs)537b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
538b6a7719aSHannes Frederic Sowa struct sock *sk, int segs)
5391da177e4SLinus Torvalds {
540703133deSAnsis Atteka struct iphdr *iph = ip_hdr(skb);
541703133deSAnsis Atteka
54223f57406SEric Dumazet /* We had many attacks based on IPID, use the private
54323f57406SEric Dumazet * generator as much as we can.
5441da177e4SLinus Torvalds */
545c720c7e8SEric Dumazet if (sk && inet_sk(sk)->inet_daddr) {
546f866fbc8SEric Dumazet int val;
547f866fbc8SEric Dumazet
548f866fbc8SEric Dumazet /* avoid atomic operations for TCP,
549f866fbc8SEric Dumazet * as we hold socket lock at this point.
550f866fbc8SEric Dumazet */
551f866fbc8SEric Dumazet if (sk_is_tcp(sk)) {
552f866fbc8SEric Dumazet sock_owned_by_me(sk);
553f866fbc8SEric Dumazet val = atomic_read(&inet_sk(sk)->inet_id);
554f866fbc8SEric Dumazet atomic_set(&inet_sk(sk)->inet_id, val + segs);
555f866fbc8SEric Dumazet } else {
556f866fbc8SEric Dumazet val = atomic_add_return(segs, &inet_sk(sk)->inet_id);
557f866fbc8SEric Dumazet }
558f866fbc8SEric Dumazet iph->id = htons(val);
55923f57406SEric Dumazet return;
56073f156a6SEric Dumazet }
56123f57406SEric Dumazet if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
56223f57406SEric Dumazet iph->id = 0;
56373f156a6SEric Dumazet } else {
56423f57406SEric Dumazet /* Unfortunately we need the big hammer to get a suitable IPID */
565b6a7719aSHannes Frederic Sowa __ip_select_ident(net, iph, segs);
56673f156a6SEric Dumazet }
56773f156a6SEric Dumazet }
56873f156a6SEric Dumazet
ip_select_ident(struct net * net,struct sk_buff * skb,struct sock * sk)569b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
570b6a7719aSHannes Frederic Sowa struct sock *sk)
57173f156a6SEric Dumazet {
572b6a7719aSHannes Frederic Sowa ip_select_ident_segs(net, skb, sk, 1);
5731da177e4SLinus Torvalds }
5741da177e4SLinus Torvalds
inet_compute_pseudo(struct sk_buff * skb,int proto)575ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
576ed70fcfcSTom Herbert {
577ed70fcfcSTom Herbert return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
578ed70fcfcSTom Herbert skb->len, proto, 0);
579ed70fcfcSTom Herbert }
580ed70fcfcSTom Herbert
581c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store
582c3f83241STom Herbert * Equivalent to : flow->v4addrs.src = iph->saddr;
583c3f83241STom Herbert * flow->v4addrs.dst = iph->daddr;
584c3f83241STom Herbert */
iph_to_flow_copy_v4addrs(struct flow_keys * flow,const struct iphdr * iph)585c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow,
586c3f83241STom Herbert const struct iphdr *iph)
587c3f83241STom Herbert {
588c3f83241STom Herbert BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) !=
589c3f83241STom Herbert offsetof(typeof(flow->addrs), v4addrs.src) +
590c3f83241STom Herbert sizeof(flow->addrs.v4addrs.src));
59158e0be1eSHangbin Liu memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs));
592c3f83241STom Herbert flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
593c3f83241STom Herbert }
594c3f83241STom Herbert
5951da177e4SLinus Torvalds /*
5961da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type ethernet.
5971da177e4SLinus Torvalds */
5981da177e4SLinus Torvalds
ip_eth_mc_map(__be32 naddr,char * buf)599714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf)
6001da177e4SLinus Torvalds {
601714e85beSAl Viro __u32 addr=ntohl(naddr);
6021da177e4SLinus Torvalds buf[0]=0x01;
6031da177e4SLinus Torvalds buf[1]=0x00;
6041da177e4SLinus Torvalds buf[2]=0x5e;
6051da177e4SLinus Torvalds buf[5]=addr&0xFF;
6061da177e4SLinus Torvalds addr>>=8;
6071da177e4SLinus Torvalds buf[4]=addr&0xFF;
6081da177e4SLinus Torvalds addr>>=8;
6091da177e4SLinus Torvalds buf[3]=addr&0x7F;
6101da177e4SLinus Torvalds }
6111da177e4SLinus Torvalds
6121da177e4SLinus Torvalds /*
6131da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
6141da177e4SLinus Torvalds * Leave P_Key as 0 to be filled in by driver.
6151da177e4SLinus Torvalds */
6161da177e4SLinus Torvalds
ip_ib_mc_map(__be32 naddr,const unsigned char * broadcast,char * buf)617a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
6181da177e4SLinus Torvalds {
619714e85beSAl Viro __u32 addr;
620a9e527e3SRolf Manderscheid unsigned char scope = broadcast[5] & 0xF;
621a9e527e3SRolf Manderscheid
6221da177e4SLinus Torvalds buf[0] = 0; /* Reserved */
6231da177e4SLinus Torvalds buf[1] = 0xff; /* Multicast QPN */
6241da177e4SLinus Torvalds buf[2] = 0xff;
6251da177e4SLinus Torvalds buf[3] = 0xff;
626714e85beSAl Viro addr = ntohl(naddr);
6271da177e4SLinus Torvalds buf[4] = 0xff;
628a9e527e3SRolf Manderscheid buf[5] = 0x10 | scope; /* scope from broadcast address */
6291da177e4SLinus Torvalds buf[6] = 0x40; /* IPv4 signature */
6301da177e4SLinus Torvalds buf[7] = 0x1b;
631a9e527e3SRolf Manderscheid buf[8] = broadcast[8]; /* P_Key */
632a9e527e3SRolf Manderscheid buf[9] = broadcast[9];
6331da177e4SLinus Torvalds buf[10] = 0;
6341da177e4SLinus Torvalds buf[11] = 0;
6351da177e4SLinus Torvalds buf[12] = 0;
6361da177e4SLinus Torvalds buf[13] = 0;
6371da177e4SLinus Torvalds buf[14] = 0;
6381da177e4SLinus Torvalds buf[15] = 0;
6391da177e4SLinus Torvalds buf[19] = addr & 0xff;
6401da177e4SLinus Torvalds addr >>= 8;
6411da177e4SLinus Torvalds buf[18] = addr & 0xff;
6421da177e4SLinus Torvalds addr >>= 8;
6431da177e4SLinus Torvalds buf[17] = addr & 0xff;
6441da177e4SLinus Torvalds addr >>= 8;
6451da177e4SLinus Torvalds buf[16] = addr & 0x0f;
6461da177e4SLinus Torvalds }
6471da177e4SLinus Torvalds
ip_ipgre_mc_map(__be32 naddr,const unsigned char * broadcast,char * buf)64893ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
64993ca3bb5STimo Teräs {
65093ca3bb5STimo Teräs if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
65193ca3bb5STimo Teräs memcpy(buf, broadcast, 4);
65293ca3bb5STimo Teräs else
65393ca3bb5STimo Teräs memcpy(buf, &naddr, sizeof(naddr));
65493ca3bb5STimo Teräs }
65593ca3bb5STimo Teräs
656dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6571da177e4SLinus Torvalds #include <linux/ipv6.h>
6581da177e4SLinus Torvalds #endif
6591da177e4SLinus Torvalds
inet_reset_saddr(struct sock * sk)6601da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk)
6611da177e4SLinus Torvalds {
662c720c7e8SEric Dumazet inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
663dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6641da177e4SLinus Torvalds if (sk->sk_family == PF_INET6) {
6651da177e4SLinus Torvalds struct ipv6_pinfo *np = inet6_sk(sk);
6661da177e4SLinus Torvalds
6671da177e4SLinus Torvalds memset(&np->saddr, 0, sizeof(np->saddr));
668efe4208fSEric Dumazet memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr));
6691da177e4SLinus Torvalds }
6701da177e4SLinus Torvalds #endif
6711da177e4SLinus Torvalds }
6721da177e4SLinus Torvalds
6731da177e4SLinus Torvalds #endif
6741da177e4SLinus Torvalds
ipv4_addr_hash(__be32 ip)67572afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip)
67672afa352SDavid Ahern {
67772afa352SDavid Ahern return (__force unsigned int) ip;
67872afa352SDavid Ahern }
67972afa352SDavid Ahern
ipv4_portaddr_hash(const struct net * net,__be32 saddr,unsigned int port)680f0b1e64cSMartin KaFai Lau static inline u32 ipv4_portaddr_hash(const struct net *net,
681f0b1e64cSMartin KaFai Lau __be32 saddr,
682f0b1e64cSMartin KaFai Lau unsigned int port)
683f0b1e64cSMartin KaFai Lau {
684f0b1e64cSMartin KaFai Lau return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
685f0b1e64cSMartin KaFai Lau }
686f0b1e64cSMartin KaFai Lau
6875c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb);
6881da177e4SLinus Torvalds
6891da177e4SLinus Torvalds /*
690b798232fSRami Rosen * Functions provided by ip_fragment.c
6911da177e4SLinus Torvalds */
6921da177e4SLinus Torvalds
693fd2c3ef7SEric Dumazet enum ip_defrag_users {
6941da177e4SLinus Torvalds IP_DEFRAG_LOCAL_DELIVER,
6951da177e4SLinus Torvalds IP_DEFRAG_CALL_RA_CHAIN,
6961da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_IN,
6974be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
6981da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_OUT,
6994be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
7008fa9ff68SPatrick McHardy IP_DEFRAG_CONNTRACK_BRIDGE_IN,
7014be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
7021da177e4SLinus Torvalds IP_DEFRAG_VS_IN,
7031da177e4SLinus Torvalds IP_DEFRAG_VS_OUT,
704595fc71bSDavid S. Miller IP_DEFRAG_VS_FWD,
705595fc71bSDavid S. Miller IP_DEFRAG_AF_PACKET,
706bc416d97SEric Dumazet IP_DEFRAG_MACVLAN,
7071da177e4SLinus Torvalds };
7081da177e4SLinus Torvalds
7095cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond'
7105cf42280SAndy Zhou * and 'upper_bond' inclusively.
7115cf42280SAndy Zhou */
ip_defrag_user_in_between(u32 user,enum ip_defrag_users lower_bond,enum ip_defrag_users upper_bond)7125cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user,
7135cf42280SAndy Zhou enum ip_defrag_users lower_bond,
7145cf42280SAndy Zhou enum ip_defrag_users upper_bond)
7155cf42280SAndy Zhou {
7165cf42280SAndy Zhou return user >= lower_bond && user <= upper_bond;
7175cf42280SAndy Zhou }
7185cf42280SAndy Zhou
71919bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
720bc416d97SEric Dumazet #ifdef CONFIG_INET
72119bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
722bc416d97SEric Dumazet #else
ip_check_defrag(struct net * net,struct sk_buff * skb,u32 user)72319bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
724bc416d97SEric Dumazet {
725bc416d97SEric Dumazet return skb;
726bc416d97SEric Dumazet }
727bc416d97SEric Dumazet #endif
7281da177e4SLinus Torvalds
7291da177e4SLinus Torvalds /*
7301da177e4SLinus Torvalds * Functions provided by ip_forward.c
7311da177e4SLinus Torvalds */
7321da177e4SLinus Torvalds
7335c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb);
7341da177e4SLinus Torvalds
7351da177e4SLinus Torvalds /*
7361da177e4SLinus Torvalds * Functions provided by ip_options.c
7371da177e4SLinus Torvalds */
7381da177e4SLinus Torvalds
7395c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
7404f0e3040SJakub Kicinski __be32 daddr, struct rtable *rt);
74124a2d43dSEric Dumazet
74291ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt,
74391ed1e66SPaolo Abeni struct sk_buff *skb, const struct ip_options *sopt);
ip_options_echo(struct net * net,struct ip_options * dopt,struct sk_buff * skb)74491ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
74591ed1e66SPaolo Abeni struct sk_buff *skb)
74624a2d43dSEric Dumazet {
74791ed1e66SPaolo Abeni return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
74824a2d43dSEric Dumazet }
74924a2d43dSEric Dumazet
7505c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb);
7513da1ed7aSNazarov Sergey int __ip_options_compile(struct net *net, struct ip_options *opt,
7523da1ed7aSNazarov Sergey struct sk_buff *skb, __be32 *info);
7535c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt,
7545c3a0fd7SJoe Perches struct sk_buff *skb);
7555c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp,
756de40a3e8SChristoph Hellwig sockptr_t data, int optlen);
7575c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt);
7585c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb);
7598c83f2dfSStephen Suryaputra int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
7601da177e4SLinus Torvalds
7611da177e4SLinus Torvalds /*
7621da177e4SLinus Torvalds * Functions provided by ip_sockglue.c
7631da177e4SLinus Torvalds */
7641da177e4SLinus Torvalds
765dcaafdbaSNicolas Dichtel void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb, bool drop_dst);
766ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
767ad959036SPaolo Abeni struct sk_buff *skb, int tlen, int offset);
76824025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
769c8e6ad08SHannes Frederic Sowa struct ipcm_cookie *ipc, bool allow_ipv6);
770020e71a3SEric Dumazet DECLARE_STATIC_KEY_FALSE(ip4_min_ttl);
771ee7f1e13SMartin KaFai Lau int do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
772ee7f1e13SMartin KaFai Lau unsigned int optlen);
773a7b75c5aSChristoph Hellwig int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
7745c3a0fd7SJoe Perches unsigned int optlen);
775fd969f25SMartin KaFai Lau int do_ip_getsockopt(struct sock *sk, int level, int optname,
776fd969f25SMartin KaFai Lau sockptr_t optval, sockptr_t optlen);
7775c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
7785c3a0fd7SJoe Perches int __user *optlen);
7795c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on,
7805c3a0fd7SJoe Perches void (*destructor)(struct sock *));
7811da177e4SLinus Torvalds
78285fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
7835c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
7845c3a0fd7SJoe Perches u32 info, u8 *payload);
7855c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
7861da177e4SLinus Torvalds u32 info);
7871da177e4SLinus Torvalds
ip_cmsg_recv(struct msghdr * msg,struct sk_buff * skb)7885961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
7895961de9fSTom Herbert {
790ad959036SPaolo Abeni ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
7915961de9fSTom Herbert }
7925961de9fSTom Herbert
7934cdf507dSEric Dumazet bool icmp_global_allow(void);
794662ec522SEric Dumazet void icmp_global_consume(void);
795662ec522SEric Dumazet
7964cdf507dSEric Dumazet extern int sysctl_icmp_msgs_per_sec;
7974cdf507dSEric Dumazet extern int sysctl_icmp_msgs_burst;
7984cdf507dSEric Dumazet
79920380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS
8005c3a0fd7SJoe Perches int ip_misc_proc_init(void);
80120380731SArnaldo Carvalho de Melo #endif
80220380731SArnaldo Carvalho de Melo
8035e1a99eaSHangbin Liu int rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family,
804404eb77eSRoopa Prabhu struct netlink_ext_ack *extack);
805404eb77eSRoopa Prabhu
inetdev_valid_mtu(unsigned int mtu)806501a90c9SEric Dumazet static inline bool inetdev_valid_mtu(unsigned int mtu)
807501a90c9SEric Dumazet {
808501a90c9SEric Dumazet return likely(mtu >= IPV4_MIN_MTU);
809501a90c9SEric Dumazet }
810501a90c9SEric Dumazet
811c4e446bfSChristoph Hellwig void ip_sock_set_freebind(struct sock *sk);
8122de569bdSChristoph Hellwig int ip_sock_set_mtu_discover(struct sock *sk, int val);
813c1f9ec57SChristoph Hellwig void ip_sock_set_pktinfo(struct sock *sk);
814db45c0efSChristoph Hellwig void ip_sock_set_recverr(struct sock *sk);
8156ebf71baSChristoph Hellwig void ip_sock_set_tos(struct sock *sk, int val);
8164f47d5d5SPoorva Sonparote void __ip_sock_set_tos(struct sock *sk, int val);
8176ebf71baSChristoph Hellwig
8181da177e4SLinus Torvalds #endif /* _IP_H */
819