11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * INET An implementation of the TCP/IP protocol suite for the LINUX 31da177e4SLinus Torvalds * operating system. INET is implemented using the BSD Socket 41da177e4SLinus Torvalds * interface as the means of communication with the user level. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Definitions for the IP module. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Version: @(#)ip.h 1.0.2 05/07/93 91da177e4SLinus Torvalds * 1002c30a84SJesper Juhl * Authors: Ross Biro 111da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 121da177e4SLinus Torvalds * Alan Cox, <gw4pts@gw4pts.ampr.org> 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * Changes: 151da177e4SLinus Torvalds * Mike McLagan : Routing by source 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 181da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 191da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 201da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 211da177e4SLinus Torvalds */ 221da177e4SLinus Torvalds #ifndef _IP_H 231da177e4SLinus Torvalds #define _IP_H 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <linux/types.h> 261da177e4SLinus Torvalds #include <linux/ip.h> 271da177e4SLinus Torvalds #include <linux/in.h> 28c9bdd4b5SArnaldo Carvalho de Melo #include <linux/skbuff.h> 2914c85021SArnaldo Carvalho de Melo 3014c85021SArnaldo Carvalho de Melo #include <net/inet_sock.h> 31aa661581SFrancesco Fusco #include <net/route.h> 321da177e4SLinus Torvalds #include <net/snmp.h> 3386b08d86SKOVACS Krisztian #include <net/flow.h> 341bd758ebSJiri Pirko #include <net/flow_dissector.h> 351da177e4SLinus Torvalds 367ed14d97SGao Feng #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ 377ed14d97SGao Feng 381da177e4SLinus Torvalds struct sock; 391da177e4SLinus Torvalds 40fd2c3ef7SEric Dumazet struct inet_skb_parm { 410b922b7aSDavid Ahern int iif; 421da177e4SLinus Torvalds struct ip_options opt; /* Compiled IP options */ 43a04a480dSDavid Ahern u16 flags; 441da177e4SLinus Torvalds 45df4d9254SHannes Frederic Sowa #define IPSKB_FORWARDED BIT(0) 46df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TUNNEL_SIZE BIT(1) 47df4d9254SHannes Frederic Sowa #define IPSKB_XFRM_TRANSFORMED BIT(2) 48df4d9254SHannes Frederic Sowa #define IPSKB_FRAG_COMPLETE BIT(3) 49df4d9254SHannes Frederic Sowa #define IPSKB_REROUTED BIT(4) 50df4d9254SHannes Frederic Sowa #define IPSKB_DOREDIRECT BIT(5) 51d6b915e2SFlorian Westphal #define IPSKB_FRAG_PMTU BIT(6) 529ee6c5dcSLance Richardson #define IPSKB_L3SLAVE BIT(7) 535f2d04f1SPatrick McHardy 545f2d04f1SPatrick McHardy u16 frag_max_size; 551da177e4SLinus Torvalds }; 561da177e4SLinus Torvalds 57a04a480dSDavid Ahern static inline bool ipv4_l3mdev_skb(u16 flags) 58a04a480dSDavid Ahern { 59a04a480dSDavid Ahern return !!(flags & IPSKB_L3SLAVE); 60a04a480dSDavid Ahern } 61a04a480dSDavid Ahern 62c9bdd4b5SArnaldo Carvalho de Melo static inline unsigned int ip_hdrlen(const struct sk_buff *skb) 63c9bdd4b5SArnaldo Carvalho de Melo { 64eddc9ec5SArnaldo Carvalho de Melo return ip_hdr(skb)->ihl * 4; 65c9bdd4b5SArnaldo Carvalho de Melo } 66c9bdd4b5SArnaldo Carvalho de Melo 67fd2c3ef7SEric Dumazet struct ipcm_cookie { 6824025c46SSoheil Hassas Yeganeh struct sockcm_cookie sockc; 69c1d18f9fSAl Viro __be32 addr; 701da177e4SLinus Torvalds int oif; 71f6d8bd05SEric Dumazet struct ip_options_rcu *opt; 722244d07bSOliver Hartkopp __u8 tx_flags; 73f02db315SFrancesco Fusco __u8 ttl; 74f02db315SFrancesco Fusco __s16 tos; 75f02db315SFrancesco Fusco char priority; 761da177e4SLinus Torvalds }; 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) 794b261c75SHannes Frederic Sowa #define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb)) 801da177e4SLinus Torvalds 81*fb74c277SDavid Ahern /* return enslaved device index if relevant */ 82*fb74c277SDavid Ahern static inline int inet_sdif(struct sk_buff *skb) 83*fb74c277SDavid Ahern { 84*fb74c277SDavid Ahern #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) 85*fb74c277SDavid Ahern if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags)) 86*fb74c277SDavid Ahern return IPCB(skb)->iif; 87*fb74c277SDavid Ahern #endif 88*fb74c277SDavid Ahern return 0; 89*fb74c277SDavid Ahern } 90*fb74c277SDavid Ahern 91fd2c3ef7SEric Dumazet struct ip_ra_chain { 9243a951e9SEric Dumazet struct ip_ra_chain __rcu *next; 931da177e4SLinus Torvalds struct sock *sk; 94592fcb9dSEric Dumazet union { 951da177e4SLinus Torvalds void (*destructor)(struct sock *); 96592fcb9dSEric Dumazet struct sock *saved_sk; 97592fcb9dSEric Dumazet }; 9866018506SEric Dumazet struct rcu_head rcu; 991da177e4SLinus Torvalds }; 1001da177e4SLinus Torvalds 10143a951e9SEric Dumazet extern struct ip_ra_chain __rcu *ip_ra_chain; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds /* IP flags. */ 1041da177e4SLinus Torvalds #define IP_CE 0x8000 /* Flag: "Congestion" */ 1051da177e4SLinus Torvalds #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ 1061da177e4SLinus Torvalds #define IP_MF 0x2000 /* Flag: "More Fragments" */ 1071da177e4SLinus Torvalds #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ 1101da177e4SLinus Torvalds 11114c85021SArnaldo Carvalho de Melo struct msghdr; 11214c85021SArnaldo Carvalho de Melo struct net_device; 11314c85021SArnaldo Carvalho de Melo struct packet_type; 11414c85021SArnaldo Carvalho de Melo struct rtable; 11514c85021SArnaldo Carvalho de Melo struct sockaddr; 11614c85021SArnaldo Carvalho de Melo 11772c1d3bdSWANG Cong int igmp_mc_init(void); 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* 1201da177e4SLinus Torvalds * Functions provided by ip.c 1211da177e4SLinus Torvalds */ 1221da177e4SLinus Torvalds 123cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, 12413d8eaa0SAl Viro __be32 saddr, __be32 daddr, 125f6d8bd05SEric Dumazet struct ip_options_rcu *opt); 1265c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, 1275c3a0fd7SJoe Perches struct net_device *orig_dev); 1285c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb); 1295c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb); 130ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); 131ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb); 132694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 133694869b3SEric W. Biederman int (*output)(struct net *, struct sock *, struct sk_buff *)); 1345c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip); 135cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 13633224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 137aad88724SEric Dumazet 138b0270e91SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); 1395c3a0fd7SJoe Perches void ip_init(void); 1405c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4, 1411da177e4SLinus Torvalds int getfrag(void *from, char *to, int offset, int len, 1421da177e4SLinus Torvalds int odd, struct sk_buff *skb), 1431da177e4SLinus Torvalds void *from, int len, int protolen, 1441da177e4SLinus Torvalds struct ipcm_cookie *ipc, 1452e77d89bSEric Dumazet struct rtable **rt, 1461da177e4SLinus Torvalds unsigned int flags); 1475c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, 1485c3a0fd7SJoe Perches struct sk_buff *skb); 1495c3a0fd7SJoe Perches ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, 1501da177e4SLinus Torvalds int offset, size_t size, int flags); 1515c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, 1521c32c5adSHerbert Xu struct sk_buff_head *queue, 1531c32c5adSHerbert Xu struct inet_cork *cork); 1545c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb); 1555c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); 1565c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk); 1575c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4, 1585c3a0fd7SJoe Perches int getfrag(void *from, char *to, int offset, 1595c3a0fd7SJoe Perches int len, int odd, struct sk_buff *skb), 1601c32c5adSHerbert Xu void *from, int length, int transhdrlen, 1615c3a0fd7SJoe Perches struct ipcm_cookie *ipc, struct rtable **rtp, 1621c32c5adSHerbert Xu unsigned int flags); 1631c32c5adSHerbert Xu 16477968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) 1651c32c5adSHerbert Xu { 16677968b78SDavid S. Miller return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base); 1671c32c5adSHerbert Xu } 1681da177e4SLinus Torvalds 169aa661581SFrancesco Fusco static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet) 170aa661581SFrancesco Fusco { 171aa661581SFrancesco Fusco return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos); 172aa661581SFrancesco Fusco } 173aa661581SFrancesco Fusco 174aa661581SFrancesco Fusco static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk) 175aa661581SFrancesco Fusco { 176aa661581SFrancesco Fusco return (ipc->tos != -1) ? RT_CONN_FLAGS_TOS(sk, ipc->tos) : RT_CONN_FLAGS(sk); 177aa661581SFrancesco Fusco } 178aa661581SFrancesco Fusco 1791da177e4SLinus Torvalds /* datagram.c */ 18003645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 1815c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 1821da177e4SLinus Torvalds 1835c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk); 1848141ed9fSSteffen Klassert 1851da177e4SLinus Torvalds struct ip_reply_arg { 1861da177e4SLinus Torvalds struct kvec iov[1]; 18788ef4a5aSKOVACS Krisztian int flags; 188d6f5493cSAl Viro __wsum csum; 1891da177e4SLinus Torvalds int csumoffset; /* u16 offset of csum in iov[0].iov_base */ 1901da177e4SLinus Torvalds /* -1 if not needed */ 191f0e48dbfSPatrick McHardy int bound_dev_if; 19266b13d99SEric Dumazet u8 tos; 193e2d118a1SLorenzo Colitti kuid_t uid; 1941da177e4SLinus Torvalds }; 1951da177e4SLinus Torvalds 19688ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1 19788ef4a5aSKOVACS Krisztian 19886b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) 19986b08d86SKOVACS Krisztian { 20086b08d86SKOVACS Krisztian return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; 20186b08d86SKOVACS Krisztian } 20286b08d86SKOVACS Krisztian 203bdbbb852SEric Dumazet void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, 20424a2d43dSEric Dumazet const struct ip_options *sopt, 20524a2d43dSEric Dumazet __be32 daddr, __be32 saddr, 20624a2d43dSEric Dumazet const struct ip_reply_arg *arg, 20770e73416SDavid S. Miller unsigned int len); 2081da177e4SLinus Torvalds 2094ce3c183SEric Dumazet #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) 21013415e46SEric Dumazet #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) 2114ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 21213415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 2134ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 21413415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 21561a7e260SPavel Emelyanov #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) 21613415e46SEric Dumazet #define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field) 217f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 21813415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 2191da177e4SLinus Torvalds 220c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offct); 221698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt); 2224ce3c183SEric Dumazet #if BITS_PER_LONG==32 223c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 224c4c6bc31SRaghavendra K T size_t syncp_offset); 225698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off); 2264ce3c183SEric Dumazet #else 227c4c6bc31SRaghavendra K T static inline u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 228c4c6bc31SRaghavendra K T size_t syncp_offset) 229c4c6bc31SRaghavendra K T { 230c4c6bc31SRaghavendra K T return snmp_get_cpu_field(mib, cpu, offct); 231c4c6bc31SRaghavendra K T 232c4c6bc31SRaghavendra K T } 233c4c6bc31SRaghavendra K T 234698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off) 2354ce3c183SEric Dumazet { 2364ce3c183SEric Dumazet return snmp_fold_field(mib, offt); 2374ce3c183SEric Dumazet } 2384ce3c183SEric Dumazet #endif 23933490170SYOSHIFUJI Hideaki 2406348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \ 2416348ef2dSJia He { \ 2426348ef2dSJia He int i, c; \ 2436348ef2dSJia He for_each_possible_cpu(c) { \ 2446348ef2dSJia He for (i = 0; stats_list[i].name; i++) \ 2456348ef2dSJia He buff64[i] += snmp_get_cpu_field64( \ 2466348ef2dSJia He mib_statistic, \ 2476348ef2dSJia He c, stats_list[i].entry, \ 2486348ef2dSJia He offset); \ 2496348ef2dSJia He } \ 2506348ef2dSJia He } 2516348ef2dSJia He 2526348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \ 2536348ef2dSJia He { \ 2546348ef2dSJia He int i, c; \ 2556348ef2dSJia He for_each_possible_cpu(c) { \ 2566348ef2dSJia He for (i = 0; stats_list[i].name; i++) \ 2576348ef2dSJia He buff[i] += snmp_get_cpu_field( \ 2586348ef2dSJia He mib_statistic, \ 2596348ef2dSJia He c, stats_list[i].entry); \ 2606348ef2dSJia He } \ 2616348ef2dSJia He } 2626348ef2dSJia He 2630bbf87d8SEric W. Biederman void inet_get_local_port_range(struct net *net, int *low, int *high); 264227b60f5SStephen Hemminger 265fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL 266122ff243SWANG Cong static inline int inet_is_local_reserved_port(struct net *net, int port) 267e3826f1eSAmerigo Wang { 268122ff243SWANG Cong if (!net->ipv4.sysctl_local_reserved_ports) 269122ff243SWANG Cong return 0; 270122ff243SWANG Cong return test_bit(port, net->ipv4.sysctl_local_reserved_ports); 271e3826f1eSAmerigo Wang } 27220e61da7SWANG Cong 27320e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name) 27420e61da7SWANG Cong { 27520e61da7SWANG Cong return strcmp(name, "default") != 0 && strcmp(name, "all") != 0; 27620e61da7SWANG Cong } 27720e61da7SWANG Cong 2784548b683SKrister Johansen static inline int inet_prot_sock(struct net *net) 2794548b683SKrister Johansen { 2804548b683SKrister Johansen return net->ipv4.sysctl_ip_prot_sock; 2814548b683SKrister Johansen } 2824548b683SKrister Johansen 283122ff243SWANG Cong #else 284122ff243SWANG Cong static inline int inet_is_local_reserved_port(struct net *net, int port) 285122ff243SWANG Cong { 286122ff243SWANG Cong return 0; 287122ff243SWANG Cong } 2884548b683SKrister Johansen 2894548b683SKrister Johansen static inline int inet_prot_sock(struct net *net) 2904548b683SKrister Johansen { 2914548b683SKrister Johansen return PROT_SOCK; 2924548b683SKrister Johansen } 293122ff243SWANG Cong #endif 294e3826f1eSAmerigo Wang 295822c8685SDeepa Dinamani __be32 inet_current_timestamp(void); 296822c8685SDeepa Dinamani 29720380731SArnaldo Carvalho de Melo /* From inetpeer.c */ 29820380731SArnaldo Carvalho de Melo extern int inet_peer_threshold; 29920380731SArnaldo Carvalho de Melo extern int inet_peer_minttl; 30020380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl; 30120380731SArnaldo Carvalho de Melo 3025c3a0fd7SJoe Perches void ipfrag_init(void); 30320380731SArnaldo Carvalho de Melo 3045c3a0fd7SJoe Perches void ip_static_sysctl_init(void); 305bd7b1533SAl Viro 306e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \ 307e110861fSLorenzo Colitti ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0) 308e110861fSLorenzo Colitti 309d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph) 310d18cd551SDavid S. Miller { 311d18cd551SDavid S. Miller return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0; 312d18cd551SDavid S. Miller } 313d18cd551SDavid S. Miller 3141da177e4SLinus Torvalds #ifdef CONFIG_INET 31514c85021SArnaldo Carvalho de Melo #include <net/dst.h> 31614c85021SArnaldo Carvalho de Melo 3171da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for 3181da177e4SLinus Torvalds * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ 3191da177e4SLinus Torvalds static inline 3201da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph) 3211da177e4SLinus Torvalds { 3225c78f275SAl Viro u32 check = (__force u32)iph->check; 3235c78f275SAl Viro check += (__force u32)htons(0x0100); 3245c78f275SAl Viro iph->check = (__force __sum16)(check + (check>=0xFFFF)); 3251da177e4SLinus Torvalds return --iph->ttl; 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds static inline 3294e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst) 3301da177e4SLinus Torvalds { 3314e3f5d72SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc); 3324e3f5d72SEric Dumazet 3334e3f5d72SEric Dumazet return pmtudisc == IP_PMTUDISC_DO || 3344e3f5d72SEric Dumazet (pmtudisc == IP_PMTUDISC_WANT && 335a02cec21SEric Dumazet !(dst_metric_locked(dst, RTAX_MTU))); 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 338f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk) 339f87c10a8SHannes Frederic Sowa { 3401b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE && 3411b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT; 342f87c10a8SHannes Frederic Sowa } 343f87c10a8SHannes Frederic Sowa 344f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk) 345f87c10a8SHannes Frederic Sowa { 346f87c10a8SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE; 347f87c10a8SHannes Frederic Sowa } 348f87c10a8SHannes Frederic Sowa 34960ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk) 3501b346576SHannes Frederic Sowa { 3511b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO || 3521b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT; 3531b346576SHannes Frederic Sowa } 3541b346576SHannes Frederic Sowa 355f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, 356f87c10a8SHannes Frederic Sowa bool forwarding) 357f87c10a8SHannes Frederic Sowa { 358f87c10a8SHannes Frederic Sowa struct net *net = dev_net(dst->dev); 359f87c10a8SHannes Frederic Sowa 360f87c10a8SHannes Frederic Sowa if (net->ipv4.sysctl_ip_fwd_use_pmtu || 361f87c10a8SHannes Frederic Sowa dst_metric_locked(dst, RTAX_MTU) || 362f87c10a8SHannes Frederic Sowa !forwarding) 363f87c10a8SHannes Frederic Sowa return dst_mtu(dst); 364f87c10a8SHannes Frederic Sowa 365f87c10a8SHannes Frederic Sowa return min(dst->dev->mtu, IP_MAX_MTU); 366f87c10a8SHannes Frederic Sowa } 367f87c10a8SHannes Frederic Sowa 368fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk, 369fedbb6b4SShmulik Ladkani const struct sk_buff *skb) 370f87c10a8SHannes Frederic Sowa { 371caf3f267SEric Dumazet if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) { 372f87c10a8SHannes Frederic Sowa bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; 373caf3f267SEric Dumazet 374f87c10a8SHannes Frederic Sowa return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); 375f87c10a8SHannes Frederic Sowa } 376caf3f267SEric Dumazet 377caf3f267SEric Dumazet return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU); 378f87c10a8SHannes Frederic Sowa } 379f87c10a8SHannes Frederic Sowa 38004ca6973SEric Dumazet u32 ip_idents_reserve(u32 hash, int segs); 381b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs); 38273f156a6SEric Dumazet 383b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, 384b6a7719aSHannes Frederic Sowa struct sock *sk, int segs) 3851da177e4SLinus Torvalds { 386703133deSAnsis Atteka struct iphdr *iph = ip_hdr(skb); 387703133deSAnsis Atteka 38860ff7467SWANG Cong if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { 3891da177e4SLinus Torvalds /* This is only to work around buggy Windows95/2000 3901da177e4SLinus Torvalds * VJ compression implementations. If the ID field 3911da177e4SLinus Torvalds * does not change, they drop every other packet in 3921da177e4SLinus Torvalds * a TCP stream using header compression. 3931da177e4SLinus Torvalds */ 394c720c7e8SEric Dumazet if (sk && inet_sk(sk)->inet_daddr) { 395c720c7e8SEric Dumazet iph->id = htons(inet_sk(sk)->inet_id); 39673f156a6SEric Dumazet inet_sk(sk)->inet_id += segs; 39773f156a6SEric Dumazet } else { 3981da177e4SLinus Torvalds iph->id = 0; 39973f156a6SEric Dumazet } 40073f156a6SEric Dumazet } else { 401b6a7719aSHannes Frederic Sowa __ip_select_ident(net, iph, segs); 40273f156a6SEric Dumazet } 40373f156a6SEric Dumazet } 40473f156a6SEric Dumazet 405b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb, 406b6a7719aSHannes Frederic Sowa struct sock *sk) 40773f156a6SEric Dumazet { 408b6a7719aSHannes Frederic Sowa ip_select_ident_segs(net, skb, sk, 1); 4091da177e4SLinus Torvalds } 4101da177e4SLinus Torvalds 411ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) 412ed70fcfcSTom Herbert { 413ed70fcfcSTom Herbert return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 414ed70fcfcSTom Herbert skb->len, proto, 0); 415ed70fcfcSTom Herbert } 416ed70fcfcSTom Herbert 417c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store 418c3f83241STom Herbert * Equivalent to : flow->v4addrs.src = iph->saddr; 419c3f83241STom Herbert * flow->v4addrs.dst = iph->daddr; 420c3f83241STom Herbert */ 421c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow, 422c3f83241STom Herbert const struct iphdr *iph) 423c3f83241STom Herbert { 424c3f83241STom Herbert BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != 425c3f83241STom Herbert offsetof(typeof(flow->addrs), v4addrs.src) + 426c3f83241STom Herbert sizeof(flow->addrs.v4addrs.src)); 427c3f83241STom Herbert memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs)); 428c3f83241STom Herbert flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; 429c3f83241STom Herbert } 430c3f83241STom Herbert 4311933a785STom Herbert static inline __wsum inet_gro_compute_pseudo(struct sk_buff *skb, int proto) 4321933a785STom Herbert { 4331933a785STom Herbert const struct iphdr *iph = skb_gro_network_header(skb); 4341933a785STom Herbert 4351933a785STom Herbert return csum_tcpudp_nofold(iph->saddr, iph->daddr, 4361933a785STom Herbert skb_gro_len(skb), proto, 0); 4371933a785STom Herbert } 4381933a785STom Herbert 4391da177e4SLinus Torvalds /* 4401da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type ethernet. 4411da177e4SLinus Torvalds */ 4421da177e4SLinus Torvalds 443714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf) 4441da177e4SLinus Torvalds { 445714e85beSAl Viro __u32 addr=ntohl(naddr); 4461da177e4SLinus Torvalds buf[0]=0x01; 4471da177e4SLinus Torvalds buf[1]=0x00; 4481da177e4SLinus Torvalds buf[2]=0x5e; 4491da177e4SLinus Torvalds buf[5]=addr&0xFF; 4501da177e4SLinus Torvalds addr>>=8; 4511da177e4SLinus Torvalds buf[4]=addr&0xFF; 4521da177e4SLinus Torvalds addr>>=8; 4531da177e4SLinus Torvalds buf[3]=addr&0x7F; 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* 4571da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand. 4581da177e4SLinus Torvalds * Leave P_Key as 0 to be filled in by driver. 4591da177e4SLinus Torvalds */ 4601da177e4SLinus Torvalds 461a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 4621da177e4SLinus Torvalds { 463714e85beSAl Viro __u32 addr; 464a9e527e3SRolf Manderscheid unsigned char scope = broadcast[5] & 0xF; 465a9e527e3SRolf Manderscheid 4661da177e4SLinus Torvalds buf[0] = 0; /* Reserved */ 4671da177e4SLinus Torvalds buf[1] = 0xff; /* Multicast QPN */ 4681da177e4SLinus Torvalds buf[2] = 0xff; 4691da177e4SLinus Torvalds buf[3] = 0xff; 470714e85beSAl Viro addr = ntohl(naddr); 4711da177e4SLinus Torvalds buf[4] = 0xff; 472a9e527e3SRolf Manderscheid buf[5] = 0x10 | scope; /* scope from broadcast address */ 4731da177e4SLinus Torvalds buf[6] = 0x40; /* IPv4 signature */ 4741da177e4SLinus Torvalds buf[7] = 0x1b; 475a9e527e3SRolf Manderscheid buf[8] = broadcast[8]; /* P_Key */ 476a9e527e3SRolf Manderscheid buf[9] = broadcast[9]; 4771da177e4SLinus Torvalds buf[10] = 0; 4781da177e4SLinus Torvalds buf[11] = 0; 4791da177e4SLinus Torvalds buf[12] = 0; 4801da177e4SLinus Torvalds buf[13] = 0; 4811da177e4SLinus Torvalds buf[14] = 0; 4821da177e4SLinus Torvalds buf[15] = 0; 4831da177e4SLinus Torvalds buf[19] = addr & 0xff; 4841da177e4SLinus Torvalds addr >>= 8; 4851da177e4SLinus Torvalds buf[18] = addr & 0xff; 4861da177e4SLinus Torvalds addr >>= 8; 4871da177e4SLinus Torvalds buf[17] = addr & 0xff; 4881da177e4SLinus Torvalds addr >>= 8; 4891da177e4SLinus Torvalds buf[16] = addr & 0x0f; 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds 49293ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 49393ca3bb5STimo Teräs { 49493ca3bb5STimo Teräs if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) 49593ca3bb5STimo Teräs memcpy(buf, broadcast, 4); 49693ca3bb5STimo Teräs else 49793ca3bb5STimo Teräs memcpy(buf, &naddr, sizeof(naddr)); 49893ca3bb5STimo Teräs } 49993ca3bb5STimo Teräs 500dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 5011da177e4SLinus Torvalds #include <linux/ipv6.h> 5021da177e4SLinus Torvalds #endif 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk) 5051da177e4SLinus Torvalds { 506c720c7e8SEric Dumazet inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0; 507dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 5081da177e4SLinus Torvalds if (sk->sk_family == PF_INET6) { 5091da177e4SLinus Torvalds struct ipv6_pinfo *np = inet6_sk(sk); 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds memset(&np->saddr, 0, sizeof(np->saddr)); 512efe4208fSEric Dumazet memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr)); 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds #endif 5151da177e4SLinus Torvalds } 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds #endif 5181da177e4SLinus Torvalds 51972afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip) 52072afa352SDavid Ahern { 52172afa352SDavid Ahern return (__force unsigned int) ip; 52272afa352SDavid Ahern } 52372afa352SDavid Ahern 5245c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb); 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds /* 527b798232fSRami Rosen * Functions provided by ip_fragment.c 5281da177e4SLinus Torvalds */ 5291da177e4SLinus Torvalds 530fd2c3ef7SEric Dumazet enum ip_defrag_users { 5311da177e4SLinus Torvalds IP_DEFRAG_LOCAL_DELIVER, 5321da177e4SLinus Torvalds IP_DEFRAG_CALL_RA_CHAIN, 5331da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_IN, 5344be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX, 5351da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_OUT, 5364be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX, 5378fa9ff68SPatrick McHardy IP_DEFRAG_CONNTRACK_BRIDGE_IN, 5384be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX, 5391da177e4SLinus Torvalds IP_DEFRAG_VS_IN, 5401da177e4SLinus Torvalds IP_DEFRAG_VS_OUT, 541595fc71bSDavid S. Miller IP_DEFRAG_VS_FWD, 542595fc71bSDavid S. Miller IP_DEFRAG_AF_PACKET, 543bc416d97SEric Dumazet IP_DEFRAG_MACVLAN, 5441da177e4SLinus Torvalds }; 5451da177e4SLinus Torvalds 5465cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond' 5475cf42280SAndy Zhou * and 'upper_bond' inclusively. 5485cf42280SAndy Zhou */ 5495cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user, 5505cf42280SAndy Zhou enum ip_defrag_users lower_bond, 5515cf42280SAndy Zhou enum ip_defrag_users upper_bond) 5525cf42280SAndy Zhou { 5535cf42280SAndy Zhou return user >= lower_bond && user <= upper_bond; 5545cf42280SAndy Zhou } 5555cf42280SAndy Zhou 55619bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user); 557bc416d97SEric Dumazet #ifdef CONFIG_INET 55819bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user); 559bc416d97SEric Dumazet #else 56019bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user) 561bc416d97SEric Dumazet { 562bc416d97SEric Dumazet return skb; 563bc416d97SEric Dumazet } 564bc416d97SEric Dumazet #endif 5656ddc0822SPavel Emelyanov int ip_frag_mem(struct net *net); 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds /* 5681da177e4SLinus Torvalds * Functions provided by ip_forward.c 5691da177e4SLinus Torvalds */ 5701da177e4SLinus Torvalds 5715c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb); 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds /* 5741da177e4SLinus Torvalds * Functions provided by ip_options.c 5751da177e4SLinus Torvalds */ 5761da177e4SLinus Torvalds 5775c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt, 578f6d8bd05SEric Dumazet __be32 daddr, struct rtable *rt, int is_frag); 57924a2d43dSEric Dumazet 58091ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt, 58191ed1e66SPaolo Abeni struct sk_buff *skb, const struct ip_options *sopt); 58291ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt, 58391ed1e66SPaolo Abeni struct sk_buff *skb) 58424a2d43dSEric Dumazet { 58591ed1e66SPaolo Abeni return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt); 58624a2d43dSEric Dumazet } 58724a2d43dSEric Dumazet 5885c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb); 5895c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt, 5905c3a0fd7SJoe Perches struct sk_buff *skb); 5915c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp, 5924c6ea29dSArnaldo Carvalho de Melo unsigned char *data, int optlen); 5935c3a0fd7SJoe Perches int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, 5944c6ea29dSArnaldo Carvalho de Melo unsigned char __user *data, int optlen); 5955c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt); 5965c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb); 5975c3a0fd7SJoe Perches int ip_options_rcv_srr(struct sk_buff *skb); 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds /* 6001da177e4SLinus Torvalds * Functions provided by ip_sockglue.c 6011da177e4SLinus Torvalds */ 6021da177e4SLinus Torvalds 603fbf8866dSShawn Bohrer void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb); 604ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, 605ad959036SPaolo Abeni struct sk_buff *skb, int tlen, int offset); 60624025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg, 607c8e6ad08SHannes Frederic Sowa struct ipcm_cookie *ipc, bool allow_ipv6); 6085c3a0fd7SJoe Perches int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, 6095c3a0fd7SJoe Perches unsigned int optlen); 6105c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, 6115c3a0fd7SJoe Perches int __user *optlen); 6125c3a0fd7SJoe Perches int compat_ip_setsockopt(struct sock *sk, int level, int optname, 6135c3a0fd7SJoe Perches char __user *optval, unsigned int optlen); 6145c3a0fd7SJoe Perches int compat_ip_getsockopt(struct sock *sk, int level, int optname, 6155c3a0fd7SJoe Perches char __user *optval, int __user *optlen); 6165c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on, 6175c3a0fd7SJoe Perches void (*destructor)(struct sock *)); 6181da177e4SLinus Torvalds 61985fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); 6205c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, 6215c3a0fd7SJoe Perches u32 info, u8 *payload); 6225c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, 6231da177e4SLinus Torvalds u32 info); 6241da177e4SLinus Torvalds 6255961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 6265961de9fSTom Herbert { 627ad959036SPaolo Abeni ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0); 6285961de9fSTom Herbert } 6295961de9fSTom Herbert 6304cdf507dSEric Dumazet bool icmp_global_allow(void); 6314cdf507dSEric Dumazet extern int sysctl_icmp_msgs_per_sec; 6324cdf507dSEric Dumazet extern int sysctl_icmp_msgs_burst; 6334cdf507dSEric Dumazet 63420380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS 6355c3a0fd7SJoe Perches int ip_misc_proc_init(void); 63620380731SArnaldo Carvalho de Melo #endif 63720380731SArnaldo Carvalho de Melo 6381da177e4SLinus Torvalds #endif /* _IP_H */ 639