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, <[email protected]>
131da177e4SLinus Torvalds * Alan Cox, <[email protected]>
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>
36356d054aSIdo Schimmel #include <net/inet_dscp.h>
371da177e4SLinus Torvalds
387ed14d97SGao Feng #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
39b5476022SEric Dumazet #define IPV4_MIN_MTU 68 /* RFC 791 */
407ed14d97SGao Feng
419ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem;
429ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem_min;
439ab948a9SDavid Ahern extern unsigned int sysctl_fib_sync_mem_max;
449ab948a9SDavid Ahern
451da177e4SLinus Torvalds struct sock;
461da177e4SLinus Torvalds
47fd2c3ef7SEric Dumazet struct inet_skb_parm {
480b922b7aSDavid Ahern int iif;
491da177e4SLinus Torvalds struct ip_options opt; /* Compiled IP options */
50a04a480dSDavid Ahern u16 flags;
511da177e4SLinus Torvalds
52df4d9254SHannes Frederic Sowa #define IPSKB_FORWARDED BIT(0)
53df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TUNNEL_SIZE BIT(1)
54df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TRANSFORMED BIT(2)
55df4d9254SHannes Frederic Sowa #define IPSKB_FRAG_COMPLETE BIT(3)
56df4d9254SHannes Frederic Sowa #define IPSKB_REROUTED BIT(4)
57df4d9254SHannes Frederic Sowa #define IPSKB_DOREDIRECT BIT(5)
58d6b915e2SFlorian Westphal #define IPSKB_FRAG_PMTU BIT(6)
599ee6c5dcSLance Richardson #define IPSKB_L3SLAVE BIT(7)
60e6175a2eSEyal Birger #define IPSKB_NOPOLICY BIT(8)
616ac66cb0SSriram Yagnaraman #define IPSKB_MULTIPATH BIT(9)
625f2d04f1SPatrick McHardy
635f2d04f1SPatrick McHardy u16 frag_max_size;
641da177e4SLinus Torvalds };
651da177e4SLinus Torvalds
ipv4_l3mdev_skb(u16 flags)66a04a480dSDavid Ahern static inline bool ipv4_l3mdev_skb(u16 flags)
67a04a480dSDavid Ahern {
68a04a480dSDavid Ahern return !!(flags & IPSKB_L3SLAVE);
69a04a480dSDavid Ahern }
70a04a480dSDavid Ahern
ip_hdrlen(const struct sk_buff * skb)71c9bdd4b5SArnaldo Carvalho de Melo static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
72c9bdd4b5SArnaldo Carvalho de Melo {
73eddc9ec5SArnaldo Carvalho de Melo return ip_hdr(skb)->ihl * 4;
74c9bdd4b5SArnaldo Carvalho de Melo }
75c9bdd4b5SArnaldo Carvalho de Melo
76fd2c3ef7SEric Dumazet struct ipcm_cookie {
7724025c46SSoheil Hassas Yeganeh struct sockcm_cookie sockc;
78c1d18f9fSAl Viro __be32 addr;
791da177e4SLinus Torvalds int oif;
80f6d8bd05SEric Dumazet struct ip_options_rcu *opt;
813632679dSNicolas Dichtel __u8 protocol;
82f02db315SFrancesco Fusco __u8 ttl;
83f02db315SFrancesco Fusco __s16 tos;
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 {
959329b583SWillem de Bruijn *ipcm = (struct ipcm_cookie) {
969329b583SWillem de Bruijn .tos = READ_ONCE(inet->tos),
979329b583SWillem de Bruijn };
9835178206SWillem de Bruijn
9994788792SWillem de Bruijn sockcm_init(&ipcm->sockc, &inet->sk);
10094788792SWillem de Bruijn
1014c971d2fSEric Dumazet ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
10235178206SWillem de Bruijn ipcm->addr = inet->inet_saddr;
1033632679dSNicolas Dichtel ipcm->protocol = inet->inet_num;
10435178206SWillem de Bruijn }
10535178206SWillem de Bruijn
1061da177e4SLinus Torvalds #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
1074b261c75SHannes Frederic Sowa #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
1081da177e4SLinus Torvalds
109fb74c277SDavid Ahern /* return enslaved device index if relevant */
inet_sdif(const struct sk_buff * skb)110d6bb2d1eSEric Dumazet static inline int inet_sdif(const struct sk_buff *skb)
111fb74c277SDavid Ahern {
112fb74c277SDavid Ahern #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
113fb74c277SDavid Ahern if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
114fb74c277SDavid Ahern return IPCB(skb)->iif;
115fb74c277SDavid Ahern #endif
116fb74c277SDavid Ahern return 0;
117fb74c277SDavid Ahern }
118fb74c277SDavid Ahern
1195796ef75SKirill Tkhai /* Special input handler for packets caught by router alert option.
1205796ef75SKirill Tkhai They are selected only by protocol field, and then processed likely
1215796ef75SKirill Tkhai local ones; but only if someone wants them! Otherwise, router
1225796ef75SKirill Tkhai not running rsvpd will kill RSVP.
1235796ef75SKirill Tkhai
1245796ef75SKirill Tkhai It is user level problem, what it will make with them.
1255796ef75SKirill Tkhai I have no idea, how it will masquearde or NAT them (it is joke, joke :-)),
1265796ef75SKirill Tkhai but receiver should be enough clever f.e. to forward mtrace requests,
1275796ef75SKirill Tkhai sent to multicast group to reach destination designated router.
1285796ef75SKirill Tkhai */
1295796ef75SKirill Tkhai
130fd2c3ef7SEric Dumazet struct ip_ra_chain {
13143a951e9SEric Dumazet struct ip_ra_chain __rcu *next;
1321da177e4SLinus Torvalds struct sock *sk;
133592fcb9dSEric Dumazet union {
1341da177e4SLinus Torvalds void (*destructor)(struct sock *);
135592fcb9dSEric Dumazet struct sock *saved_sk;
136592fcb9dSEric Dumazet };
13766018506SEric Dumazet struct rcu_head rcu;
1381da177e4SLinus Torvalds };
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds /* IP flags. */
1411da177e4SLinus Torvalds #define IP_CE 0x8000 /* Flag: "Congestion" */
1421da177e4SLinus Torvalds #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
1431da177e4SLinus Torvalds #define IP_MF 0x2000 /* Flag: "More Fragments" */
1441da177e4SLinus Torvalds #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
1451da177e4SLinus Torvalds
1461da177e4SLinus Torvalds #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
1471da177e4SLinus Torvalds
14814c85021SArnaldo Carvalho de Melo struct msghdr;
14914c85021SArnaldo Carvalho de Melo struct net_device;
15014c85021SArnaldo Carvalho de Melo struct packet_type;
15114c85021SArnaldo Carvalho de Melo struct rtable;
15214c85021SArnaldo Carvalho de Melo struct sockaddr;
15314c85021SArnaldo Carvalho de Melo
15472c1d3bdSWANG Cong int igmp_mc_init(void);
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds /*
1571da177e4SLinus Torvalds * Functions provided by ip.c
1581da177e4SLinus Torvalds */
1591da177e4SLinus Torvalds
160cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
16113d8eaa0SAl Viro __be32 saddr, __be32 daddr,
162de033b7dSWei Wang struct ip_options_rcu *opt, u8 tos);
1635c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
1645c3a0fd7SJoe Perches struct net_device *orig_dev);
16517266ee9SEdward Cree void ip_list_rcv(struct list_head *head, struct packet_type *pt,
16617266ee9SEdward Cree struct net_device *orig_dev);
1675c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb);
16868cb7d53SPaolo Abeni void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
1695c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb);
170ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
171ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
172694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
173694869b3SEric W. Biederman int (*output)(struct net *, struct sock *, struct sk_buff *));
174c8b17be0SPablo Neira Ayuso
175c8b17be0SPablo Neira Ayuso struct ip_fraglist_iter {
176c8b17be0SPablo Neira Ayuso struct sk_buff *frag;
177c8b17be0SPablo Neira Ayuso struct iphdr *iph;
178c8b17be0SPablo Neira Ayuso int offset;
179c8b17be0SPablo Neira Ayuso unsigned int hlen;
180c8b17be0SPablo Neira Ayuso };
181c8b17be0SPablo Neira Ayuso
182c8b17be0SPablo Neira Ayuso void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
183c8b17be0SPablo Neira Ayuso unsigned int hlen, struct ip_fraglist_iter *iter);
184c8b17be0SPablo Neira Ayuso void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter);
185c8b17be0SPablo Neira Ayuso
ip_fraglist_next(struct ip_fraglist_iter * iter)186c8b17be0SPablo Neira Ayuso static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter)
187c8b17be0SPablo Neira Ayuso {
188c8b17be0SPablo Neira Ayuso struct sk_buff *skb = iter->frag;
189c8b17be0SPablo Neira Ayuso
190c8b17be0SPablo Neira Ayuso iter->frag = skb->next;
191c8b17be0SPablo Neira Ayuso skb_mark_not_on_list(skb);
192c8b17be0SPablo Neira Ayuso
193c8b17be0SPablo Neira Ayuso return skb;
194c8b17be0SPablo Neira Ayuso }
195c8b17be0SPablo Neira Ayuso
196065ff79fSPablo Neira Ayuso struct ip_frag_state {
197e7a409c3SEric Dumazet bool DF;
198065ff79fSPablo Neira Ayuso unsigned int hlen;
199065ff79fSPablo Neira Ayuso unsigned int ll_rs;
200065ff79fSPablo Neira Ayuso unsigned int mtu;
201065ff79fSPablo Neira Ayuso unsigned int left;
202065ff79fSPablo Neira Ayuso int offset;
203065ff79fSPablo Neira Ayuso int ptr;
204065ff79fSPablo Neira Ayuso __be16 not_last_frag;
205065ff79fSPablo Neira Ayuso };
206065ff79fSPablo Neira Ayuso
207065ff79fSPablo Neira Ayuso void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
208e7a409c3SEric Dumazet unsigned int mtu, bool DF, struct ip_frag_state *state);
209065ff79fSPablo Neira Ayuso struct sk_buff *ip_frag_next(struct sk_buff *skb,
210065ff79fSPablo Neira Ayuso struct ip_frag_state *state);
211065ff79fSPablo Neira Ayuso
2125c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip);
213cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
21433224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
215aad88724SEric Dumazet
21669b9e1e0SXin Long int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
21769b9e1e0SXin Long __u8 tos);
2185c3a0fd7SJoe Perches void ip_init(void);
2195c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4,
2201da177e4SLinus Torvalds int getfrag(void *from, char *to, int offset, int len,
2211da177e4SLinus Torvalds int odd, struct sk_buff *skb),
2221da177e4SLinus Torvalds void *from, int len, int protolen,
2231da177e4SLinus Torvalds struct ipcm_cookie *ipc,
2242e77d89bSEric Dumazet struct rtable **rt,
2251da177e4SLinus Torvalds unsigned int flags);
2265c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
2275c3a0fd7SJoe Perches struct sk_buff *skb);
2285c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2291c32c5adSHerbert Xu struct sk_buff_head *queue,
2301c32c5adSHerbert Xu struct inet_cork *cork);
2315c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb);
2325c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
2335c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk);
2345c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
2355c3a0fd7SJoe Perches int getfrag(void *from, char *to, int offset,
2365c3a0fd7SJoe Perches int len, int odd, struct sk_buff *skb),
2371c32c5adSHerbert Xu void *from, int length, int transhdrlen,
2385c3a0fd7SJoe Perches struct ipcm_cookie *ipc, struct rtable **rtp,
2391cd7884dSWillem de Bruijn struct inet_cork *cork, unsigned int flags);
2401c32c5adSHerbert Xu
24105e22e83SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
24269b9e1e0SXin Long
ip_finish_skb(struct sock * sk,struct flowi4 * fl4)24377968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
2441c32c5adSHerbert Xu {
24577968b78SDavid S. Miller return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
2461c32c5adSHerbert Xu }
2471da177e4SLinus Torvalds
248726de790SGuillaume 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)249726de790SGuillaume Nault static inline u8 ip_sendmsg_scope(const struct inet_sock *inet,
250726de790SGuillaume Nault const struct ipcm_cookie *ipc,
251726de790SGuillaume Nault const struct msghdr *msg)
252726de790SGuillaume Nault {
253726de790SGuillaume Nault if (sock_flag(&inet->sk, SOCK_LOCALROUTE) ||
254726de790SGuillaume Nault msg->msg_flags & MSG_DONTROUTE ||
255726de790SGuillaume Nault (ipc->opt && ipc->opt->opt.is_strictroute))
256726de790SGuillaume Nault return RT_SCOPE_LINK;
257726de790SGuillaume Nault
258726de790SGuillaume Nault return RT_SCOPE_UNIVERSE;
259726de790SGuillaume Nault }
260726de790SGuillaume Nault
2611da177e4SLinus Torvalds /* datagram.c */
26203645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2635c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
2641da177e4SLinus Torvalds
2655c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk);
2668141ed9fSSteffen Klassert
2671da177e4SLinus Torvalds struct ip_reply_arg {
2681da177e4SLinus Torvalds struct kvec iov[1];
26988ef4a5aSKOVACS Krisztian int flags;
270d6f5493cSAl Viro __wsum csum;
2711da177e4SLinus Torvalds int csumoffset; /* u16 offset of csum in iov[0].iov_base */
2721da177e4SLinus Torvalds /* -1 if not needed */
273f0e48dbfSPatrick McHardy int bound_dev_if;
27466b13d99SEric Dumazet u8 tos;
275e2d118a1SLorenzo Colitti kuid_t uid;
2761da177e4SLinus Torvalds };
2771da177e4SLinus Torvalds
27888ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1
27988ef4a5aSKOVACS Krisztian
ip_reply_arg_flowi_flags(const struct ip_reply_arg * arg)28086b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
28186b08d86SKOVACS Krisztian {
28286b08d86SKOVACS Krisztian return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
28386b08d86SKOVACS Krisztian }
28486b08d86SKOVACS Krisztian
28579636038SEric Dumazet void ip_send_unicast_reply(struct sock *sk, const struct sock *orig_sk,
28679636038SEric Dumazet struct sk_buff *skb,
28724a2d43dSEric Dumazet const struct ip_options *sopt,
28824a2d43dSEric Dumazet __be32 daddr, __be32 saddr,
28924a2d43dSEric Dumazet const struct ip_reply_arg *arg,
290c0a8966eSAntoine Tenart unsigned int len, u64 transmit_time, u32 txhash);
2911da177e4SLinus Torvalds
2924ce3c183SEric Dumazet #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
29313415e46SEric Dumazet #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field)
2944ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
29513415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
2964ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29713415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
29861a7e260SPavel Emelyanov #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
29913415e46SEric Dumazet #define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field)
300f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
30113415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
3021da177e4SLinus Torvalds
snmp_get_cpu_field(void __percpu * mib,int cpu,int offt)30359f09ae8SEric Dumazet static inline u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt)
30459f09ae8SEric Dumazet {
30559f09ae8SEric Dumazet return *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt);
30659f09ae8SEric Dumazet }
30759f09ae8SEric Dumazet
308698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt);
3094ce3c183SEric Dumazet #if BITS_PER_LONG==32
310c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
311c4c6bc31SRaghavendra K T size_t syncp_offset);
312698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off);
3134ce3c183SEric Dumazet #else
snmp_get_cpu_field64(void __percpu * mib,int cpu,int offct,size_t syncp_offset)314c4c6bc31SRaghavendra K T static inline u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct,
315c4c6bc31SRaghavendra K T size_t syncp_offset)
316c4c6bc31SRaghavendra K T {
317c4c6bc31SRaghavendra K T return snmp_get_cpu_field(mib, cpu, offct);
318c4c6bc31SRaghavendra K T
319c4c6bc31SRaghavendra K T }
320c4c6bc31SRaghavendra K T
snmp_fold_field64(void __percpu * mib,int offt,size_t syncp_off)321698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off)
3224ce3c183SEric Dumazet {
3234ce3c183SEric Dumazet return snmp_fold_field(mib, offt);
3244ce3c183SEric Dumazet }
3254ce3c183SEric Dumazet #endif
32633490170SYOSHIFUJI Hideaki
3276348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \
3286348ef2dSJia He { \
3296348ef2dSJia He int i, c; \
3306348ef2dSJia He for_each_possible_cpu(c) { \
3316348ef2dSJia He for (i = 0; stats_list[i].name; i++) \
3326348ef2dSJia He buff64[i] += snmp_get_cpu_field64( \
3336348ef2dSJia He mib_statistic, \
3346348ef2dSJia He c, stats_list[i].entry, \
3356348ef2dSJia He offset); \
3366348ef2dSJia He } \
3376348ef2dSJia He }
3386348ef2dSJia He
3396348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \
3406348ef2dSJia He { \
3416348ef2dSJia He int i, c; \
3426348ef2dSJia He for_each_possible_cpu(c) { \
3436348ef2dSJia He for (i = 0; stats_list[i].name; i++) \
3446348ef2dSJia He buff[i] += snmp_get_cpu_field( \
3456348ef2dSJia He mib_statistic, \
3466348ef2dSJia He c, stats_list[i].entry); \
3476348ef2dSJia He } \
3486348ef2dSJia He }
3496348ef2dSJia He
inet_get_local_port_range(const struct net * net,int * low,int * high)350d9f28735SDavid Laight static inline void inet_get_local_port_range(const struct net *net, int *low, int *high)
351d9f28735SDavid Laight {
352d9f28735SDavid Laight u32 range = READ_ONCE(net->ipv4.ip_local_ports.range);
353d9f28735SDavid Laight
354d9f28735SDavid Laight *low = range & 0xffff;
355d9f28735SDavid Laight *high = range >> 16;
356d9f28735SDavid Laight }
35741db7626SEric Dumazet bool inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high);
358227b60f5SStephen Hemminger
359fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL
inet_is_local_reserved_port(const struct net * net,unsigned short port)360d4438ce6SEric Dumazet static inline bool inet_is_local_reserved_port(const struct net *net, unsigned short port)
361e3826f1eSAmerigo Wang {
362122ff243SWANG Cong if (!net->ipv4.sysctl_local_reserved_ports)
36330429fbaSMaciej Żenczykowski return false;
364122ff243SWANG Cong return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
365e3826f1eSAmerigo Wang }
36620e61da7SWANG Cong
sysctl_dev_name_is_allowed(const char * name)36720e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name)
36820e61da7SWANG Cong {
36920e61da7SWANG Cong return strcmp(name, "default") != 0 && strcmp(name, "all") != 0;
37020e61da7SWANG Cong }
37120e61da7SWANG Cong
inet_port_requires_bind_service(struct net * net,unsigned short port)37282f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3734548b683SKrister Johansen {
3749b55c20fSKuniyuki Iwashima return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock);
3754548b683SKrister Johansen }
3764548b683SKrister Johansen
377122ff243SWANG Cong #else
inet_is_local_reserved_port(struct net * net,unsigned short port)37866e2f5f7SMaciej Żenczykowski static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
379122ff243SWANG Cong {
38030429fbaSMaciej Żenczykowski return false;
381122ff243SWANG Cong }
3824548b683SKrister Johansen
inet_port_requires_bind_service(struct net * net,unsigned short port)38382f31ebfSMaciej Żenczykowski static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
3844548b683SKrister Johansen {
38582f31ebfSMaciej Żenczykowski return port < PROT_SOCK;
3864548b683SKrister Johansen }
387122ff243SWANG Cong #endif
388e3826f1eSAmerigo Wang
389822c8685SDeepa Dinamani __be32 inet_current_timestamp(void);
390822c8685SDeepa Dinamani
39120380731SArnaldo Carvalho de Melo /* From inetpeer.c */
39220380731SArnaldo Carvalho de Melo extern int inet_peer_threshold;
39320380731SArnaldo Carvalho de Melo extern int inet_peer_minttl;
39420380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl;
39520380731SArnaldo Carvalho de Melo
3965c3a0fd7SJoe Perches void ipfrag_init(void);
39720380731SArnaldo Carvalho de Melo
3985c3a0fd7SJoe Perches void ip_static_sysctl_init(void);
399bd7b1533SAl Viro
400e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \
40185d0b4dbSKuniyuki Iwashima (READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0)
402e110861fSLorenzo Colitti
ip_is_fragment(const struct iphdr * iph)403d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph)
404d18cd551SDavid S. Miller {
405d18cd551SDavid S. Miller return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
406d18cd551SDavid S. Miller }
407d18cd551SDavid S. Miller
4081da177e4SLinus Torvalds #ifdef CONFIG_INET
40914c85021SArnaldo Carvalho de Melo #include <net/dst.h>
41014c85021SArnaldo Carvalho de Melo
4111da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for
4121da177e4SLinus Torvalds * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
4131da177e4SLinus Torvalds static inline
ip_decrease_ttl(struct iphdr * iph)4141da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph)
4151da177e4SLinus Torvalds {
4165c78f275SAl Viro u32 check = (__force u32)iph->check;
4175c78f275SAl Viro check += (__force u32)htons(0x0100);
4185c78f275SAl Viro iph->check = (__force __sum16)(check + (check>=0xFFFF));
4191da177e4SLinus Torvalds return --iph->ttl;
4201da177e4SLinus Torvalds }
4211da177e4SLinus Torvalds
ip4h_dscp(const struct iphdr * ip4h)4227e863e5dSGuillaume Nault static inline dscp_t ip4h_dscp(const struct iphdr *ip4h)
4237e863e5dSGuillaume Nault {
4247e863e5dSGuillaume Nault return inet_dsfield_to_dscp(ip4h->tos);
4257e863e5dSGuillaume Nault }
4267e863e5dSGuillaume Nault
ip_mtu_locked(const struct dst_entry * dst)427d52e5a7eSSabrina Dubroca static inline int ip_mtu_locked(const struct dst_entry *dst)
428d52e5a7eSSabrina Dubroca {
42905d6d492SEric Dumazet const struct rtable *rt = dst_rtable(dst);
430d52e5a7eSSabrina Dubroca
431d52e5a7eSSabrina Dubroca return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU);
432d52e5a7eSSabrina Dubroca }
433d52e5a7eSSabrina Dubroca
4341da177e4SLinus Torvalds static inline
ip_dont_fragment(const struct sock * sk,const struct dst_entry * dst)4354e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst)
4361da177e4SLinus Torvalds {
4374e3f5d72SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
4384e3f5d72SEric Dumazet
4394e3f5d72SEric Dumazet return pmtudisc == IP_PMTUDISC_DO ||
4404e3f5d72SEric Dumazet (pmtudisc == IP_PMTUDISC_WANT &&
441d52e5a7eSSabrina Dubroca !ip_mtu_locked(dst));
4421da177e4SLinus Torvalds }
4431da177e4SLinus Torvalds
ip_sk_accept_pmtu(const struct sock * sk)444f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk)
445f87c10a8SHannes Frederic Sowa {
446ceaa7141SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
447ceaa7141SEric Dumazet
448ceaa7141SEric Dumazet return pmtudisc != IP_PMTUDISC_INTERFACE &&
449ceaa7141SEric Dumazet pmtudisc != IP_PMTUDISC_OMIT;
450f87c10a8SHannes Frederic Sowa }
451f87c10a8SHannes Frederic Sowa
ip_sk_use_pmtu(const struct sock * sk)452f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk)
453f87c10a8SHannes Frederic Sowa {
454ceaa7141SEric Dumazet return READ_ONCE(inet_sk(sk)->pmtudisc) < IP_PMTUDISC_PROBE;
455f87c10a8SHannes Frederic Sowa }
456f87c10a8SHannes Frederic Sowa
ip_sk_ignore_df(const struct sock * sk)45760ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk)
4581b346576SHannes Frederic Sowa {
459ceaa7141SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc);
460ceaa7141SEric Dumazet
461ceaa7141SEric Dumazet return pmtudisc < IP_PMTUDISC_DO || pmtudisc == IP_PMTUDISC_OMIT;
4621b346576SHannes Frederic Sowa }
4631b346576SHannes Frederic Sowa
ip_dst_mtu_maybe_forward(const struct dst_entry * dst,bool forwarding)464f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
465f87c10a8SHannes Frederic Sowa bool forwarding)
466f87c10a8SHannes Frederic Sowa {
46705d6d492SEric Dumazet const struct rtable *rt = dst_rtable(dst);
468071d8012SEric Dumazet unsigned int mtu, res;
469071d8012SEric Dumazet struct net *net;
470f87c10a8SHannes Frederic Sowa
471071d8012SEric Dumazet rcu_read_lock();
472071d8012SEric Dumazet
473071d8012SEric Dumazet net = dev_net_rcu(dst->dev);
47460c158dcSKuniyuki Iwashima if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
475d52e5a7eSSabrina Dubroca ip_mtu_locked(dst) ||
476ac6627a2SVadim Fedorenko !forwarding) {
477ac6627a2SVadim Fedorenko mtu = rt->rt_pmtu;
478ac6627a2SVadim Fedorenko if (mtu && time_before(jiffies, rt->dst.expires))
479ac6627a2SVadim Fedorenko goto out;
480ac6627a2SVadim Fedorenko }
481f87c10a8SHannes Frederic Sowa
48202a1b175SMaciej Żenczykowski /* 'forwarding = true' case should always honour route mtu */
48302a1b175SMaciej Żenczykowski mtu = dst_metric_raw(dst, RTAX_MTU);
484ac6627a2SVadim Fedorenko if (mtu)
485ac6627a2SVadim Fedorenko goto out;
486ac6627a2SVadim Fedorenko
487ac6627a2SVadim Fedorenko mtu = READ_ONCE(dst->dev->mtu);
488ac6627a2SVadim Fedorenko
489ac6627a2SVadim Fedorenko if (unlikely(ip_mtu_locked(dst))) {
490ac6627a2SVadim Fedorenko if (rt->rt_uses_gateway && mtu > 576)
491ac6627a2SVadim Fedorenko mtu = 576;
492ac6627a2SVadim Fedorenko }
493ac6627a2SVadim Fedorenko
494ac6627a2SVadim Fedorenko out:
495ac6627a2SVadim Fedorenko mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
49602a1b175SMaciej Żenczykowski
497071d8012SEric Dumazet res = mtu - lwtunnel_headroom(dst->lwtstate, mtu);
498071d8012SEric Dumazet
499071d8012SEric Dumazet rcu_read_unlock();
500071d8012SEric Dumazet
501071d8012SEric Dumazet return res;
502f87c10a8SHannes Frederic Sowa }
503f87c10a8SHannes Frederic Sowa
ip_skb_dst_mtu(struct sock * sk,const struct sk_buff * skb)504fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
505fedbb6b4SShmulik Ladkani const struct sk_buff *skb)
506f87c10a8SHannes Frederic Sowa {
507fade5641SVadim Fedorenko unsigned int mtu;
508fade5641SVadim Fedorenko
509caf3f267SEric Dumazet if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
510f87c10a8SHannes Frederic Sowa bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
511caf3f267SEric Dumazet
512f87c10a8SHannes Frederic Sowa return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
513f87c10a8SHannes Frederic Sowa }
514caf3f267SEric Dumazet
515fade5641SVadim Fedorenko mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
516fade5641SVadim Fedorenko return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
517f87c10a8SHannes Frederic Sowa }
518f87c10a8SHannes Frederic Sowa
51961e2bbafSJason Xing struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
520d7e774f3SDavid Ahern struct netlink_ext_ack *extack);
ip_fib_metrics_put(struct dst_metrics * fib_metrics)521cc5f0eb2SDavid Ahern static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics)
522cc5f0eb2SDavid Ahern {
523cc5f0eb2SDavid Ahern if (fib_metrics != &dst_default_metrics &&
524cc5f0eb2SDavid Ahern refcount_dec_and_test(&fib_metrics->refcnt))
525cc5f0eb2SDavid Ahern kfree(fib_metrics);
526cc5f0eb2SDavid Ahern }
527a919525aSDavid Ahern
528e1255ed4SDavid Ahern /* ipv4 and ipv6 both use refcounted metrics if it is not the default */
529e1255ed4SDavid Ahern static inline
ip_dst_init_metrics(struct dst_entry * dst,struct dst_metrics * fib_metrics)530e1255ed4SDavid Ahern void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics)
531e1255ed4SDavid Ahern {
532e1255ed4SDavid Ahern dst_init_metrics(dst, fib_metrics->metrics, true);
533e1255ed4SDavid Ahern
534e1255ed4SDavid Ahern if (fib_metrics != &dst_default_metrics) {
535e1255ed4SDavid Ahern dst->_metrics |= DST_METRICS_REFCOUNTED;
536e1255ed4SDavid Ahern refcount_inc(&fib_metrics->refcnt);
537e1255ed4SDavid Ahern }
538e1255ed4SDavid Ahern }
539e1255ed4SDavid Ahern
5401620a336SDavid Ahern static inline
ip_dst_metrics_put(struct dst_entry * dst)5411620a336SDavid Ahern void ip_dst_metrics_put(struct dst_entry *dst)
5421620a336SDavid Ahern {
5431620a336SDavid Ahern struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
5441620a336SDavid Ahern
5451620a336SDavid Ahern if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
5461620a336SDavid Ahern kfree(p);
5471620a336SDavid Ahern }
5481620a336SDavid Ahern
549b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
55073f156a6SEric Dumazet
ip_select_ident_segs(struct net * net,struct sk_buff * skb,struct sock * sk,int segs)551b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
552b6a7719aSHannes Frederic Sowa struct sock *sk, int segs)
5531da177e4SLinus Torvalds {
554703133deSAnsis Atteka struct iphdr *iph = ip_hdr(skb);
555703133deSAnsis Atteka
55623f57406SEric Dumazet /* We had many attacks based on IPID, use the private
55723f57406SEric Dumazet * generator as much as we can.
5581da177e4SLinus Torvalds */
559c720c7e8SEric Dumazet if (sk && inet_sk(sk)->inet_daddr) {
560f866fbc8SEric Dumazet int val;
561f866fbc8SEric Dumazet
562f866fbc8SEric Dumazet /* avoid atomic operations for TCP,
563f866fbc8SEric Dumazet * as we hold socket lock at this point.
564f866fbc8SEric Dumazet */
565f866fbc8SEric Dumazet if (sk_is_tcp(sk)) {
566f866fbc8SEric Dumazet sock_owned_by_me(sk);
567f866fbc8SEric Dumazet val = atomic_read(&inet_sk(sk)->inet_id);
568f866fbc8SEric Dumazet atomic_set(&inet_sk(sk)->inet_id, val + segs);
569f866fbc8SEric Dumazet } else {
570f866fbc8SEric Dumazet val = atomic_add_return(segs, &inet_sk(sk)->inet_id);
571f866fbc8SEric Dumazet }
572f866fbc8SEric Dumazet iph->id = htons(val);
57323f57406SEric Dumazet return;
57473f156a6SEric Dumazet }
57523f57406SEric Dumazet if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
57623f57406SEric Dumazet iph->id = 0;
57773f156a6SEric Dumazet } else {
57823f57406SEric Dumazet /* Unfortunately we need the big hammer to get a suitable IPID */
579b6a7719aSHannes Frederic Sowa __ip_select_ident(net, iph, segs);
58073f156a6SEric Dumazet }
58173f156a6SEric Dumazet }
58273f156a6SEric Dumazet
ip_select_ident(struct net * net,struct sk_buff * skb,struct sock * sk)583b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb,
584b6a7719aSHannes Frederic Sowa struct sock *sk)
58573f156a6SEric Dumazet {
586b6a7719aSHannes Frederic Sowa ip_select_ident_segs(net, skb, sk, 1);
5871da177e4SLinus Torvalds }
5881da177e4SLinus Torvalds
inet_compute_pseudo(struct sk_buff * skb,int proto)589ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
590ed70fcfcSTom Herbert {
591ed70fcfcSTom Herbert return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
592ed70fcfcSTom Herbert skb->len, proto, 0);
593ed70fcfcSTom Herbert }
594ed70fcfcSTom Herbert
595c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store
596c3f83241STom Herbert * Equivalent to : flow->v4addrs.src = iph->saddr;
597c3f83241STom Herbert * flow->v4addrs.dst = iph->daddr;
598c3f83241STom Herbert */
iph_to_flow_copy_v4addrs(struct flow_keys * flow,const struct iphdr * iph)599c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow,
600c3f83241STom Herbert const struct iphdr *iph)
601c3f83241STom Herbert {
602c3f83241STom Herbert BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) !=
603c3f83241STom Herbert offsetof(typeof(flow->addrs), v4addrs.src) +
604c3f83241STom Herbert sizeof(flow->addrs.v4addrs.src));
60558e0be1eSHangbin Liu memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs));
606c3f83241STom Herbert flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
607c3f83241STom Herbert }
608c3f83241STom Herbert
6091da177e4SLinus Torvalds /*
6101da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type ethernet.
6111da177e4SLinus Torvalds */
6121da177e4SLinus Torvalds
ip_eth_mc_map(__be32 naddr,char * buf)613714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf)
6141da177e4SLinus Torvalds {
615714e85beSAl Viro __u32 addr=ntohl(naddr);
6161da177e4SLinus Torvalds buf[0]=0x01;
6171da177e4SLinus Torvalds buf[1]=0x00;
6181da177e4SLinus Torvalds buf[2]=0x5e;
6191da177e4SLinus Torvalds buf[5]=addr&0xFF;
6201da177e4SLinus Torvalds addr>>=8;
6211da177e4SLinus Torvalds buf[4]=addr&0xFF;
6221da177e4SLinus Torvalds addr>>=8;
6231da177e4SLinus Torvalds buf[3]=addr&0x7F;
6241da177e4SLinus Torvalds }
6251da177e4SLinus Torvalds
6261da177e4SLinus Torvalds /*
6271da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
6281da177e4SLinus Torvalds * Leave P_Key as 0 to be filled in by driver.
6291da177e4SLinus Torvalds */
6301da177e4SLinus Torvalds
ip_ib_mc_map(__be32 naddr,const unsigned char * broadcast,char * buf)631a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
6321da177e4SLinus Torvalds {
633714e85beSAl Viro __u32 addr;
634a9e527e3SRolf Manderscheid unsigned char scope = broadcast[5] & 0xF;
635a9e527e3SRolf Manderscheid
6361da177e4SLinus Torvalds buf[0] = 0; /* Reserved */
6371da177e4SLinus Torvalds buf[1] = 0xff; /* Multicast QPN */
6381da177e4SLinus Torvalds buf[2] = 0xff;
6391da177e4SLinus Torvalds buf[3] = 0xff;
640714e85beSAl Viro addr = ntohl(naddr);
6411da177e4SLinus Torvalds buf[4] = 0xff;
642a9e527e3SRolf Manderscheid buf[5] = 0x10 | scope; /* scope from broadcast address */
6431da177e4SLinus Torvalds buf[6] = 0x40; /* IPv4 signature */
6441da177e4SLinus Torvalds buf[7] = 0x1b;
645a9e527e3SRolf Manderscheid buf[8] = broadcast[8]; /* P_Key */
646a9e527e3SRolf Manderscheid buf[9] = broadcast[9];
6471da177e4SLinus Torvalds buf[10] = 0;
6481da177e4SLinus Torvalds buf[11] = 0;
6491da177e4SLinus Torvalds buf[12] = 0;
6501da177e4SLinus Torvalds buf[13] = 0;
6511da177e4SLinus Torvalds buf[14] = 0;
6521da177e4SLinus Torvalds buf[15] = 0;
6531da177e4SLinus Torvalds buf[19] = addr & 0xff;
6541da177e4SLinus Torvalds addr >>= 8;
6551da177e4SLinus Torvalds buf[18] = addr & 0xff;
6561da177e4SLinus Torvalds addr >>= 8;
6571da177e4SLinus Torvalds buf[17] = addr & 0xff;
6581da177e4SLinus Torvalds addr >>= 8;
6591da177e4SLinus Torvalds buf[16] = addr & 0x0f;
6601da177e4SLinus Torvalds }
6611da177e4SLinus Torvalds
ip_ipgre_mc_map(__be32 naddr,const unsigned char * broadcast,char * buf)66293ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
66393ca3bb5STimo Teräs {
66493ca3bb5STimo Teräs if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
66593ca3bb5STimo Teräs memcpy(buf, broadcast, 4);
66693ca3bb5STimo Teräs else
66793ca3bb5STimo Teräs memcpy(buf, &naddr, sizeof(naddr));
66893ca3bb5STimo Teräs }
66993ca3bb5STimo Teräs
670dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6711da177e4SLinus Torvalds #include <linux/ipv6.h>
6721da177e4SLinus Torvalds #endif
6731da177e4SLinus Torvalds
inet_reset_saddr(struct sock * sk)6741da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk)
6751da177e4SLinus Torvalds {
676c720c7e8SEric Dumazet inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
677dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
6781da177e4SLinus Torvalds if (sk->sk_family == PF_INET6) {
6791da177e4SLinus Torvalds struct ipv6_pinfo *np = inet6_sk(sk);
6801da177e4SLinus Torvalds
6811da177e4SLinus Torvalds memset(&np->saddr, 0, sizeof(np->saddr));
682efe4208fSEric Dumazet memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr));
6831da177e4SLinus Torvalds }
6841da177e4SLinus Torvalds #endif
6851da177e4SLinus Torvalds }
6861da177e4SLinus Torvalds
6871da177e4SLinus Torvalds #endif
6881da177e4SLinus Torvalds
689*8965c160SStanislav Fomichev #if IS_MODULE(CONFIG_IPV6)
690*8965c160SStanislav Fomichev #define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X)
691*8965c160SStanislav Fomichev #define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X)
692*8965c160SStanislav Fomichev #else
693*8965c160SStanislav Fomichev #define EXPORT_IPV6_MOD(X)
694*8965c160SStanislav Fomichev #define EXPORT_IPV6_MOD_GPL(X)
695*8965c160SStanislav Fomichev #endif
696*8965c160SStanislav Fomichev
ipv4_addr_hash(__be32 ip)69772afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip)
69872afa352SDavid Ahern {
69972afa352SDavid Ahern return (__force unsigned int) ip;
70072afa352SDavid Ahern }
70172afa352SDavid Ahern
__ipv4_addr_hash(const __be32 ip,const u32 initval)702c972c1c4SKuniyuki Iwashima static inline u32 __ipv4_addr_hash(const __be32 ip, const u32 initval)
703c972c1c4SKuniyuki Iwashima {
704c972c1c4SKuniyuki Iwashima return jhash_1word((__force u32)ip, initval);
705c972c1c4SKuniyuki Iwashima }
706c972c1c4SKuniyuki Iwashima
ipv4_portaddr_hash(const struct net * net,__be32 saddr,unsigned int port)707f0b1e64cSMartin KaFai Lau static inline u32 ipv4_portaddr_hash(const struct net *net,
708f0b1e64cSMartin KaFai Lau __be32 saddr,
709f0b1e64cSMartin KaFai Lau unsigned int port)
710f0b1e64cSMartin KaFai Lau {
711f0b1e64cSMartin KaFai Lau return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
712f0b1e64cSMartin KaFai Lau }
713f0b1e64cSMartin KaFai Lau
7145c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb);
7151da177e4SLinus Torvalds
7161da177e4SLinus Torvalds /*
717b798232fSRami Rosen * Functions provided by ip_fragment.c
7181da177e4SLinus Torvalds */
7191da177e4SLinus Torvalds
720fd2c3ef7SEric Dumazet enum ip_defrag_users {
7211da177e4SLinus Torvalds IP_DEFRAG_LOCAL_DELIVER,
7221da177e4SLinus Torvalds IP_DEFRAG_CALL_RA_CHAIN,
7231da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_IN,
7244be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
7251da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_OUT,
7264be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
7278fa9ff68SPatrick McHardy IP_DEFRAG_CONNTRACK_BRIDGE_IN,
7284be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
7291da177e4SLinus Torvalds IP_DEFRAG_VS_IN,
7301da177e4SLinus Torvalds IP_DEFRAG_VS_OUT,
731595fc71bSDavid S. Miller IP_DEFRAG_VS_FWD,
732595fc71bSDavid S. Miller IP_DEFRAG_AF_PACKET,
733bc416d97SEric Dumazet IP_DEFRAG_MACVLAN,
7341da177e4SLinus Torvalds };
7351da177e4SLinus Torvalds
7365cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond'
7375cf42280SAndy Zhou * and 'upper_bond' inclusively.
7385cf42280SAndy Zhou */
ip_defrag_user_in_between(u32 user,enum ip_defrag_users lower_bond,enum ip_defrag_users upper_bond)7395cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user,
7405cf42280SAndy Zhou enum ip_defrag_users lower_bond,
7415cf42280SAndy Zhou enum ip_defrag_users upper_bond)
7425cf42280SAndy Zhou {
7435cf42280SAndy Zhou return user >= lower_bond && user <= upper_bond;
7445cf42280SAndy Zhou }
7455cf42280SAndy Zhou
74619bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
747bc416d97SEric Dumazet #ifdef CONFIG_INET
74819bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
749bc416d97SEric Dumazet #else
ip_check_defrag(struct net * net,struct sk_buff * skb,u32 user)75019bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
751bc416d97SEric Dumazet {
752bc416d97SEric Dumazet return skb;
753bc416d97SEric Dumazet }
754bc416d97SEric Dumazet #endif
7551da177e4SLinus Torvalds
7561da177e4SLinus Torvalds /*
7571da177e4SLinus Torvalds * Functions provided by ip_forward.c
7581da177e4SLinus Torvalds */
7591da177e4SLinus Torvalds
7605c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb);
7611da177e4SLinus Torvalds
7621da177e4SLinus Torvalds /*
7631da177e4SLinus Torvalds * Functions provided by ip_options.c
7641da177e4SLinus Torvalds */
7651da177e4SLinus Torvalds
7665c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
7674f0e3040SJakub Kicinski __be32 daddr, struct rtable *rt);
76824a2d43dSEric Dumazet
76991ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt,
77091ed1e66SPaolo Abeni struct sk_buff *skb, const struct ip_options *sopt);
ip_options_echo(struct net * net,struct ip_options * dopt,struct sk_buff * skb)77191ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
77291ed1e66SPaolo Abeni struct sk_buff *skb)
77324a2d43dSEric Dumazet {
77491ed1e66SPaolo Abeni return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
77524a2d43dSEric Dumazet }
77624a2d43dSEric Dumazet
7775c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb);
7783da1ed7aSNazarov Sergey int __ip_options_compile(struct net *net, struct ip_options *opt,
7793da1ed7aSNazarov Sergey struct sk_buff *skb, __be32 *info);
7805c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt,
7815c3a0fd7SJoe Perches struct sk_buff *skb);
7825c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp,
783de40a3e8SChristoph Hellwig sockptr_t data, int optlen);
7845c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt);
7855c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb);
7868c83f2dfSStephen Suryaputra int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
7871da177e4SLinus Torvalds
7881da177e4SLinus Torvalds /*
7891da177e4SLinus Torvalds * Functions provided by ip_sockglue.c
7901da177e4SLinus Torvalds */
7911da177e4SLinus Torvalds
792e622502cSNicolas Dichtel void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb, bool drop_dst);
793ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
794ad959036SPaolo Abeni struct sk_buff *skb, int tlen, int offset);
79524025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
796c8e6ad08SHannes Frederic Sowa struct ipcm_cookie *ipc, bool allow_ipv6);
797020e71a3SEric Dumazet DECLARE_STATIC_KEY_FALSE(ip4_min_ttl);
798ee7f1e13SMartin KaFai Lau int do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
799ee7f1e13SMartin KaFai Lau unsigned int optlen);
800a7b75c5aSChristoph Hellwig int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
8015c3a0fd7SJoe Perches unsigned int optlen);
802fd969f25SMartin KaFai Lau int do_ip_getsockopt(struct sock *sk, int level, int optname,
803fd969f25SMartin KaFai Lau sockptr_t optval, sockptr_t optlen);
8045c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
8055c3a0fd7SJoe Perches int __user *optlen);
8065c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on,
8075c3a0fd7SJoe Perches void (*destructor)(struct sock *));
8081da177e4SLinus Torvalds
80985fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
8105c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
8115c3a0fd7SJoe Perches u32 info, u8 *payload);
8125c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
8131da177e4SLinus Torvalds u32 info);
8141da177e4SLinus Torvalds
ip_cmsg_recv(struct msghdr * msg,struct sk_buff * skb)8155961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
8165961de9fSTom Herbert {
817ad959036SPaolo Abeni ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
8185961de9fSTom Herbert }
8195961de9fSTom Herbert
820b056b4cdSEric Dumazet bool icmp_global_allow(struct net *net);
821b056b4cdSEric Dumazet void icmp_global_consume(struct net *net);
8228c2bd38bSEric Dumazet
82320380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS
8245c3a0fd7SJoe Perches int ip_misc_proc_init(void);
82520380731SArnaldo Carvalho de Melo #endif
82620380731SArnaldo Carvalho de Melo
8275e1a99eaSHangbin Liu int rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family,
828404eb77eSRoopa Prabhu struct netlink_ext_ack *extack);
829404eb77eSRoopa Prabhu
inetdev_valid_mtu(unsigned int mtu)830501a90c9SEric Dumazet static inline bool inetdev_valid_mtu(unsigned int mtu)
831501a90c9SEric Dumazet {
832501a90c9SEric Dumazet return likely(mtu >= IPV4_MIN_MTU);
833501a90c9SEric Dumazet }
834501a90c9SEric Dumazet
835c4e446bfSChristoph Hellwig void ip_sock_set_freebind(struct sock *sk);
8362de569bdSChristoph Hellwig int ip_sock_set_mtu_discover(struct sock *sk, int val);
837c1f9ec57SChristoph Hellwig void ip_sock_set_pktinfo(struct sock *sk);
838db45c0efSChristoph Hellwig void ip_sock_set_recverr(struct sock *sk);
8396ebf71baSChristoph Hellwig void ip_sock_set_tos(struct sock *sk, int val);
840878d951cSEric Dumazet void __ip_sock_set_tos(struct sock *sk, int val);
8416ebf71baSChristoph Hellwig
8421da177e4SLinus Torvalds #endif /* _IP_H */
843