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 81fd2c3ef7SEric Dumazet struct ip_ra_chain { 8243a951e9SEric Dumazet struct ip_ra_chain __rcu *next; 831da177e4SLinus Torvalds struct sock *sk; 84592fcb9dSEric Dumazet union { 851da177e4SLinus Torvalds void (*destructor)(struct sock *); 86592fcb9dSEric Dumazet struct sock *saved_sk; 87592fcb9dSEric Dumazet }; 8866018506SEric Dumazet struct rcu_head rcu; 891da177e4SLinus Torvalds }; 901da177e4SLinus Torvalds 9143a951e9SEric Dumazet extern struct ip_ra_chain __rcu *ip_ra_chain; 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds /* IP flags. */ 941da177e4SLinus Torvalds #define IP_CE 0x8000 /* Flag: "Congestion" */ 951da177e4SLinus Torvalds #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ 961da177e4SLinus Torvalds #define IP_MF 0x2000 /* Flag: "More Fragments" */ 971da177e4SLinus Torvalds #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds #define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ 1001da177e4SLinus Torvalds 10114c85021SArnaldo Carvalho de Melo struct msghdr; 10214c85021SArnaldo Carvalho de Melo struct net_device; 10314c85021SArnaldo Carvalho de Melo struct packet_type; 10414c85021SArnaldo Carvalho de Melo struct rtable; 10514c85021SArnaldo Carvalho de Melo struct sockaddr; 10614c85021SArnaldo Carvalho de Melo 10772c1d3bdSWANG Cong int igmp_mc_init(void); 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds /* 1101da177e4SLinus Torvalds * Functions provided by ip.c 1111da177e4SLinus Torvalds */ 1121da177e4SLinus Torvalds 113cfe673b0SEric Dumazet int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, 11413d8eaa0SAl Viro __be32 saddr, __be32 daddr, 115f6d8bd05SEric Dumazet struct ip_options_rcu *opt); 1165c3a0fd7SJoe Perches int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, 1175c3a0fd7SJoe Perches struct net_device *orig_dev); 1185c3a0fd7SJoe Perches int ip_local_deliver(struct sk_buff *skb); 1195c3a0fd7SJoe Perches int ip_mr_input(struct sk_buff *skb); 120ede2059dSEric W. Biederman int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); 121ede2059dSEric W. Biederman int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb); 122694869b3SEric W. Biederman int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 123694869b3SEric W. Biederman int (*output)(struct net *, struct sock *, struct sk_buff *)); 1245c3a0fd7SJoe Perches void ip_send_check(struct iphdr *ip); 125cf91a99dSEric W. Biederman int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 12633224b16SEric W. Biederman int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 127aad88724SEric Dumazet 128b0270e91SEric Dumazet int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); 1295c3a0fd7SJoe Perches void ip_init(void); 1305c3a0fd7SJoe Perches int ip_append_data(struct sock *sk, struct flowi4 *fl4, 1311da177e4SLinus Torvalds int getfrag(void *from, char *to, int offset, int len, 1321da177e4SLinus Torvalds int odd, struct sk_buff *skb), 1331da177e4SLinus Torvalds void *from, int len, int protolen, 1341da177e4SLinus Torvalds struct ipcm_cookie *ipc, 1352e77d89bSEric Dumazet struct rtable **rt, 1361da177e4SLinus Torvalds unsigned int flags); 1375c3a0fd7SJoe Perches int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, 1385c3a0fd7SJoe Perches struct sk_buff *skb); 1395c3a0fd7SJoe Perches ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, 1401da177e4SLinus Torvalds int offset, size_t size, int flags); 1415c3a0fd7SJoe Perches struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, 1421c32c5adSHerbert Xu struct sk_buff_head *queue, 1431c32c5adSHerbert Xu struct inet_cork *cork); 1445c3a0fd7SJoe Perches int ip_send_skb(struct net *net, struct sk_buff *skb); 1455c3a0fd7SJoe Perches int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); 1465c3a0fd7SJoe Perches void ip_flush_pending_frames(struct sock *sk); 1475c3a0fd7SJoe Perches struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4, 1485c3a0fd7SJoe Perches int getfrag(void *from, char *to, int offset, 1495c3a0fd7SJoe Perches int len, int odd, struct sk_buff *skb), 1501c32c5adSHerbert Xu void *from, int length, int transhdrlen, 1515c3a0fd7SJoe Perches struct ipcm_cookie *ipc, struct rtable **rtp, 1521c32c5adSHerbert Xu unsigned int flags); 1531c32c5adSHerbert Xu 15477968b78SDavid S. Miller static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) 1551c32c5adSHerbert Xu { 15677968b78SDavid S. Miller return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base); 1571c32c5adSHerbert Xu } 1581da177e4SLinus Torvalds 159aa661581SFrancesco Fusco static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet) 160aa661581SFrancesco Fusco { 161aa661581SFrancesco Fusco return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos); 162aa661581SFrancesco Fusco } 163aa661581SFrancesco Fusco 164aa661581SFrancesco Fusco static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk) 165aa661581SFrancesco Fusco { 166aa661581SFrancesco Fusco return (ipc->tos != -1) ? RT_CONN_FLAGS_TOS(sk, ipc->tos) : RT_CONN_FLAGS(sk); 167aa661581SFrancesco Fusco } 168aa661581SFrancesco Fusco 1691da177e4SLinus Torvalds /* datagram.c */ 17003645a11SEric Dumazet int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 1715c3a0fd7SJoe Perches int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 1721da177e4SLinus Torvalds 1735c3a0fd7SJoe Perches void ip4_datagram_release_cb(struct sock *sk); 1748141ed9fSSteffen Klassert 1751da177e4SLinus Torvalds struct ip_reply_arg { 1761da177e4SLinus Torvalds struct kvec iov[1]; 17788ef4a5aSKOVACS Krisztian int flags; 178d6f5493cSAl Viro __wsum csum; 1791da177e4SLinus Torvalds int csumoffset; /* u16 offset of csum in iov[0].iov_base */ 1801da177e4SLinus Torvalds /* -1 if not needed */ 181f0e48dbfSPatrick McHardy int bound_dev_if; 18266b13d99SEric Dumazet u8 tos; 183e2d118a1SLorenzo Colitti kuid_t uid; 1841da177e4SLinus Torvalds }; 1851da177e4SLinus Torvalds 18688ef4a5aSKOVACS Krisztian #define IP_REPLY_ARG_NOSRCCHECK 1 18788ef4a5aSKOVACS Krisztian 18886b08d86SKOVACS Krisztian static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) 18986b08d86SKOVACS Krisztian { 19086b08d86SKOVACS Krisztian return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; 19186b08d86SKOVACS Krisztian } 19286b08d86SKOVACS Krisztian 193bdbbb852SEric Dumazet void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, 19424a2d43dSEric Dumazet const struct ip_options *sopt, 19524a2d43dSEric Dumazet __be32 daddr, __be32 saddr, 19624a2d43dSEric Dumazet const struct ip_reply_arg *arg, 19770e73416SDavid S. Miller unsigned int len); 1981da177e4SLinus Torvalds 1994ce3c183SEric Dumazet #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) 20013415e46SEric Dumazet #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) 2014ce3c183SEric Dumazet #define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 20213415e46SEric Dumazet #define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 2034ce3c183SEric Dumazet #define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 20413415e46SEric Dumazet #define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 20561a7e260SPavel Emelyanov #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) 20613415e46SEric Dumazet #define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field) 207f7324acdSDavid S. Miller #define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 20813415e46SEric Dumazet #define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 2091da177e4SLinus Torvalds 210c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offct); 211698365faSWANG Cong unsigned long snmp_fold_field(void __percpu *mib, int offt); 2124ce3c183SEric Dumazet #if BITS_PER_LONG==32 213c4c6bc31SRaghavendra K T u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 214c4c6bc31SRaghavendra K T size_t syncp_offset); 215698365faSWANG Cong u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off); 2164ce3c183SEric Dumazet #else 217c4c6bc31SRaghavendra K T static inline u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 218c4c6bc31SRaghavendra K T size_t syncp_offset) 219c4c6bc31SRaghavendra K T { 220c4c6bc31SRaghavendra K T return snmp_get_cpu_field(mib, cpu, offct); 221c4c6bc31SRaghavendra K T 222c4c6bc31SRaghavendra K T } 223c4c6bc31SRaghavendra K T 224698365faSWANG Cong static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off) 2254ce3c183SEric Dumazet { 2264ce3c183SEric Dumazet return snmp_fold_field(mib, offt); 2274ce3c183SEric Dumazet } 2284ce3c183SEric Dumazet #endif 22933490170SYOSHIFUJI Hideaki 2306348ef2dSJia He #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \ 2316348ef2dSJia He { \ 2326348ef2dSJia He int i, c; \ 2336348ef2dSJia He for_each_possible_cpu(c) { \ 2346348ef2dSJia He for (i = 0; stats_list[i].name; i++) \ 2356348ef2dSJia He buff64[i] += snmp_get_cpu_field64( \ 2366348ef2dSJia He mib_statistic, \ 2376348ef2dSJia He c, stats_list[i].entry, \ 2386348ef2dSJia He offset); \ 2396348ef2dSJia He } \ 2406348ef2dSJia He } 2416348ef2dSJia He 2426348ef2dSJia He #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \ 2436348ef2dSJia He { \ 2446348ef2dSJia He int i, c; \ 2456348ef2dSJia He for_each_possible_cpu(c) { \ 2466348ef2dSJia He for (i = 0; stats_list[i].name; i++) \ 2476348ef2dSJia He buff[i] += snmp_get_cpu_field( \ 2486348ef2dSJia He mib_statistic, \ 2496348ef2dSJia He c, stats_list[i].entry); \ 2506348ef2dSJia He } \ 2516348ef2dSJia He } 2526348ef2dSJia He 2530bbf87d8SEric W. Biederman void inet_get_local_port_range(struct net *net, int *low, int *high); 254227b60f5SStephen Hemminger 255fcd77db0SDavid S. Miller #ifdef CONFIG_SYSCTL 256122ff243SWANG Cong static inline int inet_is_local_reserved_port(struct net *net, int port) 257e3826f1eSAmerigo Wang { 258122ff243SWANG Cong if (!net->ipv4.sysctl_local_reserved_ports) 259122ff243SWANG Cong return 0; 260122ff243SWANG Cong return test_bit(port, net->ipv4.sysctl_local_reserved_ports); 261e3826f1eSAmerigo Wang } 26220e61da7SWANG Cong 26320e61da7SWANG Cong static inline bool sysctl_dev_name_is_allowed(const char *name) 26420e61da7SWANG Cong { 26520e61da7SWANG Cong return strcmp(name, "default") != 0 && strcmp(name, "all") != 0; 26620e61da7SWANG Cong } 26720e61da7SWANG Cong 2684548b683SKrister Johansen static inline int inet_prot_sock(struct net *net) 2694548b683SKrister Johansen { 2704548b683SKrister Johansen return net->ipv4.sysctl_ip_prot_sock; 2714548b683SKrister Johansen } 2724548b683SKrister Johansen 273122ff243SWANG Cong #else 274122ff243SWANG Cong static inline int inet_is_local_reserved_port(struct net *net, int port) 275122ff243SWANG Cong { 276122ff243SWANG Cong return 0; 277122ff243SWANG Cong } 2784548b683SKrister Johansen 2794548b683SKrister Johansen static inline int inet_prot_sock(struct net *net) 2804548b683SKrister Johansen { 2814548b683SKrister Johansen return PROT_SOCK; 2824548b683SKrister Johansen } 283122ff243SWANG Cong #endif 284e3826f1eSAmerigo Wang 285822c8685SDeepa Dinamani __be32 inet_current_timestamp(void); 286822c8685SDeepa Dinamani 28720380731SArnaldo Carvalho de Melo /* From inetpeer.c */ 28820380731SArnaldo Carvalho de Melo extern int inet_peer_threshold; 28920380731SArnaldo Carvalho de Melo extern int inet_peer_minttl; 29020380731SArnaldo Carvalho de Melo extern int inet_peer_maxttl; 29120380731SArnaldo Carvalho de Melo 2925c3a0fd7SJoe Perches void ipfrag_init(void); 29320380731SArnaldo Carvalho de Melo 2945c3a0fd7SJoe Perches void ip_static_sysctl_init(void); 295bd7b1533SAl Viro 296e110861fSLorenzo Colitti #define IP4_REPLY_MARK(net, mark) \ 297e110861fSLorenzo Colitti ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0) 298e110861fSLorenzo Colitti 299d18cd551SDavid S. Miller static inline bool ip_is_fragment(const struct iphdr *iph) 300d18cd551SDavid S. Miller { 301d18cd551SDavid S. Miller return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0; 302d18cd551SDavid S. Miller } 303d18cd551SDavid S. Miller 3041da177e4SLinus Torvalds #ifdef CONFIG_INET 30514c85021SArnaldo Carvalho de Melo #include <net/dst.h> 30614c85021SArnaldo Carvalho de Melo 3071da177e4SLinus Torvalds /* The function in 2.2 was invalid, producing wrong result for 3081da177e4SLinus Torvalds * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ 3091da177e4SLinus Torvalds static inline 3101da177e4SLinus Torvalds int ip_decrease_ttl(struct iphdr *iph) 3111da177e4SLinus Torvalds { 3125c78f275SAl Viro u32 check = (__force u32)iph->check; 3135c78f275SAl Viro check += (__force u32)htons(0x0100); 3145c78f275SAl Viro iph->check = (__force __sum16)(check + (check>=0xFFFF)); 3151da177e4SLinus Torvalds return --iph->ttl; 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds static inline 3194e3f5d72SEric Dumazet int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst) 3201da177e4SLinus Torvalds { 3214e3f5d72SEric Dumazet u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc); 3224e3f5d72SEric Dumazet 3234e3f5d72SEric Dumazet return pmtudisc == IP_PMTUDISC_DO || 3244e3f5d72SEric Dumazet (pmtudisc == IP_PMTUDISC_WANT && 325a02cec21SEric Dumazet !(dst_metric_locked(dst, RTAX_MTU))); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 328f87c10a8SHannes Frederic Sowa static inline bool ip_sk_accept_pmtu(const struct sock *sk) 329f87c10a8SHannes Frederic Sowa { 3301b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE && 3311b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT; 332f87c10a8SHannes Frederic Sowa } 333f87c10a8SHannes Frederic Sowa 334f87c10a8SHannes Frederic Sowa static inline bool ip_sk_use_pmtu(const struct sock *sk) 335f87c10a8SHannes Frederic Sowa { 336f87c10a8SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE; 337f87c10a8SHannes Frederic Sowa } 338f87c10a8SHannes Frederic Sowa 33960ff7467SWANG Cong static inline bool ip_sk_ignore_df(const struct sock *sk) 3401b346576SHannes Frederic Sowa { 3411b346576SHannes Frederic Sowa return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO || 3421b346576SHannes Frederic Sowa inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT; 3431b346576SHannes Frederic Sowa } 3441b346576SHannes Frederic Sowa 345f87c10a8SHannes Frederic Sowa static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, 346f87c10a8SHannes Frederic Sowa bool forwarding) 347f87c10a8SHannes Frederic Sowa { 348f87c10a8SHannes Frederic Sowa struct net *net = dev_net(dst->dev); 349f87c10a8SHannes Frederic Sowa 350f87c10a8SHannes Frederic Sowa if (net->ipv4.sysctl_ip_fwd_use_pmtu || 351f87c10a8SHannes Frederic Sowa dst_metric_locked(dst, RTAX_MTU) || 352f87c10a8SHannes Frederic Sowa !forwarding) 353f87c10a8SHannes Frederic Sowa return dst_mtu(dst); 354f87c10a8SHannes Frederic Sowa 355f87c10a8SHannes Frederic Sowa return min(dst->dev->mtu, IP_MAX_MTU); 356f87c10a8SHannes Frederic Sowa } 357f87c10a8SHannes Frederic Sowa 358fedbb6b4SShmulik Ladkani static inline unsigned int ip_skb_dst_mtu(struct sock *sk, 359fedbb6b4SShmulik Ladkani const struct sk_buff *skb) 360f87c10a8SHannes Frederic Sowa { 361caf3f267SEric Dumazet if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) { 362f87c10a8SHannes Frederic Sowa bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; 363caf3f267SEric Dumazet 364f87c10a8SHannes Frederic Sowa return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); 365f87c10a8SHannes Frederic Sowa } 366caf3f267SEric Dumazet 367caf3f267SEric Dumazet return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU); 368f87c10a8SHannes Frederic Sowa } 369f87c10a8SHannes Frederic Sowa 37004ca6973SEric Dumazet u32 ip_idents_reserve(u32 hash, int segs); 371b6a7719aSHannes Frederic Sowa void __ip_select_ident(struct net *net, struct iphdr *iph, int segs); 37273f156a6SEric Dumazet 373b6a7719aSHannes Frederic Sowa static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, 374b6a7719aSHannes Frederic Sowa struct sock *sk, int segs) 3751da177e4SLinus Torvalds { 376703133deSAnsis Atteka struct iphdr *iph = ip_hdr(skb); 377703133deSAnsis Atteka 37860ff7467SWANG Cong if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { 3791da177e4SLinus Torvalds /* This is only to work around buggy Windows95/2000 3801da177e4SLinus Torvalds * VJ compression implementations. If the ID field 3811da177e4SLinus Torvalds * does not change, they drop every other packet in 3821da177e4SLinus Torvalds * a TCP stream using header compression. 3831da177e4SLinus Torvalds */ 384c720c7e8SEric Dumazet if (sk && inet_sk(sk)->inet_daddr) { 385c720c7e8SEric Dumazet iph->id = htons(inet_sk(sk)->inet_id); 38673f156a6SEric Dumazet inet_sk(sk)->inet_id += segs; 38773f156a6SEric Dumazet } else { 3881da177e4SLinus Torvalds iph->id = 0; 38973f156a6SEric Dumazet } 39073f156a6SEric Dumazet } else { 391b6a7719aSHannes Frederic Sowa __ip_select_ident(net, iph, segs); 39273f156a6SEric Dumazet } 39373f156a6SEric Dumazet } 39473f156a6SEric Dumazet 395b6a7719aSHannes Frederic Sowa static inline void ip_select_ident(struct net *net, struct sk_buff *skb, 396b6a7719aSHannes Frederic Sowa struct sock *sk) 39773f156a6SEric Dumazet { 398b6a7719aSHannes Frederic Sowa ip_select_ident_segs(net, skb, sk, 1); 3991da177e4SLinus Torvalds } 4001da177e4SLinus Torvalds 401ed70fcfcSTom Herbert static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) 402ed70fcfcSTom Herbert { 403ed70fcfcSTom Herbert return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 404ed70fcfcSTom Herbert skb->len, proto, 0); 405ed70fcfcSTom Herbert } 406ed70fcfcSTom Herbert 407c3f83241STom Herbert /* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store 408c3f83241STom Herbert * Equivalent to : flow->v4addrs.src = iph->saddr; 409c3f83241STom Herbert * flow->v4addrs.dst = iph->daddr; 410c3f83241STom Herbert */ 411c3f83241STom Herbert static inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow, 412c3f83241STom Herbert const struct iphdr *iph) 413c3f83241STom Herbert { 414c3f83241STom Herbert BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != 415c3f83241STom Herbert offsetof(typeof(flow->addrs), v4addrs.src) + 416c3f83241STom Herbert sizeof(flow->addrs.v4addrs.src)); 417c3f83241STom Herbert memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs)); 418c3f83241STom Herbert flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; 419c3f83241STom Herbert } 420c3f83241STom Herbert 4211933a785STom Herbert static inline __wsum inet_gro_compute_pseudo(struct sk_buff *skb, int proto) 4221933a785STom Herbert { 4231933a785STom Herbert const struct iphdr *iph = skb_gro_network_header(skb); 4241933a785STom Herbert 4251933a785STom Herbert return csum_tcpudp_nofold(iph->saddr, iph->daddr, 4261933a785STom Herbert skb_gro_len(skb), proto, 0); 4271933a785STom Herbert } 4281933a785STom Herbert 4291da177e4SLinus Torvalds /* 4301da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type ethernet. 4311da177e4SLinus Torvalds */ 4321da177e4SLinus Torvalds 433714e85beSAl Viro static inline void ip_eth_mc_map(__be32 naddr, char *buf) 4341da177e4SLinus Torvalds { 435714e85beSAl Viro __u32 addr=ntohl(naddr); 4361da177e4SLinus Torvalds buf[0]=0x01; 4371da177e4SLinus Torvalds buf[1]=0x00; 4381da177e4SLinus Torvalds buf[2]=0x5e; 4391da177e4SLinus Torvalds buf[5]=addr&0xFF; 4401da177e4SLinus Torvalds addr>>=8; 4411da177e4SLinus Torvalds buf[4]=addr&0xFF; 4421da177e4SLinus Torvalds addr>>=8; 4431da177e4SLinus Torvalds buf[3]=addr&0x7F; 4441da177e4SLinus Torvalds } 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds /* 4471da177e4SLinus Torvalds * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand. 4481da177e4SLinus Torvalds * Leave P_Key as 0 to be filled in by driver. 4491da177e4SLinus Torvalds */ 4501da177e4SLinus Torvalds 451a9e527e3SRolf Manderscheid static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 4521da177e4SLinus Torvalds { 453714e85beSAl Viro __u32 addr; 454a9e527e3SRolf Manderscheid unsigned char scope = broadcast[5] & 0xF; 455a9e527e3SRolf Manderscheid 4561da177e4SLinus Torvalds buf[0] = 0; /* Reserved */ 4571da177e4SLinus Torvalds buf[1] = 0xff; /* Multicast QPN */ 4581da177e4SLinus Torvalds buf[2] = 0xff; 4591da177e4SLinus Torvalds buf[3] = 0xff; 460714e85beSAl Viro addr = ntohl(naddr); 4611da177e4SLinus Torvalds buf[4] = 0xff; 462a9e527e3SRolf Manderscheid buf[5] = 0x10 | scope; /* scope from broadcast address */ 4631da177e4SLinus Torvalds buf[6] = 0x40; /* IPv4 signature */ 4641da177e4SLinus Torvalds buf[7] = 0x1b; 465a9e527e3SRolf Manderscheid buf[8] = broadcast[8]; /* P_Key */ 466a9e527e3SRolf Manderscheid buf[9] = broadcast[9]; 4671da177e4SLinus Torvalds buf[10] = 0; 4681da177e4SLinus Torvalds buf[11] = 0; 4691da177e4SLinus Torvalds buf[12] = 0; 4701da177e4SLinus Torvalds buf[13] = 0; 4711da177e4SLinus Torvalds buf[14] = 0; 4721da177e4SLinus Torvalds buf[15] = 0; 4731da177e4SLinus Torvalds buf[19] = addr & 0xff; 4741da177e4SLinus Torvalds addr >>= 8; 4751da177e4SLinus Torvalds buf[18] = addr & 0xff; 4761da177e4SLinus Torvalds addr >>= 8; 4771da177e4SLinus Torvalds buf[17] = addr & 0xff; 4781da177e4SLinus Torvalds addr >>= 8; 4791da177e4SLinus Torvalds buf[16] = addr & 0x0f; 4801da177e4SLinus Torvalds } 4811da177e4SLinus Torvalds 48293ca3bb5STimo Teräs static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 48393ca3bb5STimo Teräs { 48493ca3bb5STimo Teräs if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) 48593ca3bb5STimo Teräs memcpy(buf, broadcast, 4); 48693ca3bb5STimo Teräs else 48793ca3bb5STimo Teräs memcpy(buf, &naddr, sizeof(naddr)); 48893ca3bb5STimo Teräs } 48993ca3bb5STimo Teräs 490dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 4911da177e4SLinus Torvalds #include <linux/ipv6.h> 4921da177e4SLinus Torvalds #endif 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds static __inline__ void inet_reset_saddr(struct sock *sk) 4951da177e4SLinus Torvalds { 496c720c7e8SEric Dumazet inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0; 497dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 4981da177e4SLinus Torvalds if (sk->sk_family == PF_INET6) { 4991da177e4SLinus Torvalds struct ipv6_pinfo *np = inet6_sk(sk); 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds memset(&np->saddr, 0, sizeof(np->saddr)); 502efe4208fSEric Dumazet memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr)); 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds #endif 5051da177e4SLinus Torvalds } 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds #endif 5081da177e4SLinus Torvalds 50972afa352SDavid Ahern static inline unsigned int ipv4_addr_hash(__be32 ip) 51072afa352SDavid Ahern { 51172afa352SDavid Ahern return (__force unsigned int) ip; 51272afa352SDavid Ahern } 51372afa352SDavid Ahern 5145c3a0fd7SJoe Perches bool ip_call_ra_chain(struct sk_buff *skb); 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds /* 517b798232fSRami Rosen * Functions provided by ip_fragment.c 5181da177e4SLinus Torvalds */ 5191da177e4SLinus Torvalds 520fd2c3ef7SEric Dumazet enum ip_defrag_users { 5211da177e4SLinus Torvalds IP_DEFRAG_LOCAL_DELIVER, 5221da177e4SLinus Torvalds IP_DEFRAG_CALL_RA_CHAIN, 5231da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_IN, 5244be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX, 5251da177e4SLinus Torvalds IP_DEFRAG_CONNTRACK_OUT, 5264be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX, 5278fa9ff68SPatrick McHardy IP_DEFRAG_CONNTRACK_BRIDGE_IN, 5284be929beSAlexey Dobriyan __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX, 5291da177e4SLinus Torvalds IP_DEFRAG_VS_IN, 5301da177e4SLinus Torvalds IP_DEFRAG_VS_OUT, 531595fc71bSDavid S. Miller IP_DEFRAG_VS_FWD, 532595fc71bSDavid S. Miller IP_DEFRAG_AF_PACKET, 533bc416d97SEric Dumazet IP_DEFRAG_MACVLAN, 5341da177e4SLinus Torvalds }; 5351da177e4SLinus Torvalds 5365cf42280SAndy Zhou /* Return true if the value of 'user' is between 'lower_bond' 5375cf42280SAndy Zhou * and 'upper_bond' inclusively. 5385cf42280SAndy Zhou */ 5395cf42280SAndy Zhou static inline bool ip_defrag_user_in_between(u32 user, 5405cf42280SAndy Zhou enum ip_defrag_users lower_bond, 5415cf42280SAndy Zhou enum ip_defrag_users upper_bond) 5425cf42280SAndy Zhou { 5435cf42280SAndy Zhou return user >= lower_bond && user <= upper_bond; 5445cf42280SAndy Zhou } 5455cf42280SAndy Zhou 54619bcf9f2SEric W. Biederman int ip_defrag(struct net *net, struct sk_buff *skb, u32 user); 547bc416d97SEric Dumazet #ifdef CONFIG_INET 54819bcf9f2SEric W. Biederman struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user); 549bc416d97SEric Dumazet #else 55019bcf9f2SEric W. Biederman static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user) 551bc416d97SEric Dumazet { 552bc416d97SEric Dumazet return skb; 553bc416d97SEric Dumazet } 554bc416d97SEric Dumazet #endif 5556ddc0822SPavel Emelyanov int ip_frag_mem(struct net *net); 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds /* 5581da177e4SLinus Torvalds * Functions provided by ip_forward.c 5591da177e4SLinus Torvalds */ 5601da177e4SLinus Torvalds 5615c3a0fd7SJoe Perches int ip_forward(struct sk_buff *skb); 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds /* 5641da177e4SLinus Torvalds * Functions provided by ip_options.c 5651da177e4SLinus Torvalds */ 5661da177e4SLinus Torvalds 5675c3a0fd7SJoe Perches void ip_options_build(struct sk_buff *skb, struct ip_options *opt, 568f6d8bd05SEric Dumazet __be32 daddr, struct rtable *rt, int is_frag); 56924a2d43dSEric Dumazet 57091ed1e66SPaolo Abeni int __ip_options_echo(struct net *net, struct ip_options *dopt, 57191ed1e66SPaolo Abeni struct sk_buff *skb, const struct ip_options *sopt); 57291ed1e66SPaolo Abeni static inline int ip_options_echo(struct net *net, struct ip_options *dopt, 57391ed1e66SPaolo Abeni struct sk_buff *skb) 57424a2d43dSEric Dumazet { 57591ed1e66SPaolo Abeni return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt); 57624a2d43dSEric Dumazet } 57724a2d43dSEric Dumazet 5785c3a0fd7SJoe Perches void ip_options_fragment(struct sk_buff *skb); 5795c3a0fd7SJoe Perches int ip_options_compile(struct net *net, struct ip_options *opt, 5805c3a0fd7SJoe Perches struct sk_buff *skb); 5815c3a0fd7SJoe Perches int ip_options_get(struct net *net, struct ip_options_rcu **optp, 5824c6ea29dSArnaldo Carvalho de Melo unsigned char *data, int optlen); 5835c3a0fd7SJoe Perches int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, 5844c6ea29dSArnaldo Carvalho de Melo unsigned char __user *data, int optlen); 5855c3a0fd7SJoe Perches void ip_options_undo(struct ip_options *opt); 5865c3a0fd7SJoe Perches void ip_forward_options(struct sk_buff *skb); 5875c3a0fd7SJoe Perches int ip_options_rcv_srr(struct sk_buff *skb); 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds /* 5901da177e4SLinus Torvalds * Functions provided by ip_sockglue.c 5911da177e4SLinus Torvalds */ 5921da177e4SLinus Torvalds 593fbf8866dSShawn Bohrer void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb); 594ad959036SPaolo Abeni void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, 595ad959036SPaolo Abeni struct sk_buff *skb, int tlen, int offset); 59624025c46SSoheil Hassas Yeganeh int ip_cmsg_send(struct sock *sk, struct msghdr *msg, 597c8e6ad08SHannes Frederic Sowa struct ipcm_cookie *ipc, bool allow_ipv6); 5985c3a0fd7SJoe Perches int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, 5995c3a0fd7SJoe Perches unsigned int optlen); 6005c3a0fd7SJoe Perches int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, 6015c3a0fd7SJoe Perches int __user *optlen); 6025c3a0fd7SJoe Perches int compat_ip_setsockopt(struct sock *sk, int level, int optname, 6035c3a0fd7SJoe Perches char __user *optval, unsigned int optlen); 6045c3a0fd7SJoe Perches int compat_ip_getsockopt(struct sock *sk, int level, int optname, 6055c3a0fd7SJoe Perches char __user *optval, int __user *optlen); 6065c3a0fd7SJoe Perches int ip_ra_control(struct sock *sk, unsigned char on, 6075c3a0fd7SJoe Perches void (*destructor)(struct sock *)); 6081da177e4SLinus Torvalds 60985fbaa75SHannes Frederic Sowa int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); 6105c3a0fd7SJoe Perches void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, 6115c3a0fd7SJoe Perches u32 info, u8 *payload); 6125c3a0fd7SJoe Perches void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, 6131da177e4SLinus Torvalds u32 info); 6141da177e4SLinus Torvalds 6155961de9fSTom Herbert static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 6165961de9fSTom Herbert { 617ad959036SPaolo Abeni ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0); 6185961de9fSTom Herbert } 6195961de9fSTom Herbert 6204cdf507dSEric Dumazet bool icmp_global_allow(void); 6214cdf507dSEric Dumazet extern int sysctl_icmp_msgs_per_sec; 6224cdf507dSEric Dumazet extern int sysctl_icmp_msgs_burst; 6234cdf507dSEric Dumazet 62420380731SArnaldo Carvalho de Melo #ifdef CONFIG_PROC_FS 6255c3a0fd7SJoe Perches int ip_misc_proc_init(void); 62620380731SArnaldo Carvalho de Melo #endif 62720380731SArnaldo Carvalho de Melo 6281da177e4SLinus Torvalds #endif /* _IP_H */ 629