162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 462306a36Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 562306a36Sopenharmony_ci * interface as the means of communication with the user level. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Definitions for the IP module. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Version: @(#)ip.h 1.0.2 05/07/93 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Authors: Ross Biro 1262306a36Sopenharmony_ci * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 1362306a36Sopenharmony_ci * Alan Cox, <gw4pts@gw4pts.ampr.org> 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Changes: 1662306a36Sopenharmony_ci * Mike McLagan : Routing by source 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci#ifndef _IP_H 1962306a36Sopenharmony_ci#define _IP_H 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/types.h> 2262306a36Sopenharmony_ci#include <linux/ip.h> 2362306a36Sopenharmony_ci#include <linux/in.h> 2462306a36Sopenharmony_ci#include <linux/skbuff.h> 2562306a36Sopenharmony_ci#include <linux/jhash.h> 2662306a36Sopenharmony_ci#include <linux/sockptr.h> 2762306a36Sopenharmony_ci#include <linux/static_key.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <net/inet_sock.h> 3062306a36Sopenharmony_ci#include <net/route.h> 3162306a36Sopenharmony_ci#include <net/snmp.h> 3262306a36Sopenharmony_ci#include <net/flow.h> 3362306a36Sopenharmony_ci#include <net/flow_dissector.h> 3462306a36Sopenharmony_ci#include <net/netns/hash.h> 3562306a36Sopenharmony_ci#include <net/lwtunnel.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ 3862306a36Sopenharmony_ci#define IPV4_MIN_MTU 68 /* RFC 791 */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciextern unsigned int sysctl_fib_sync_mem; 4162306a36Sopenharmony_ciextern unsigned int sysctl_fib_sync_mem_min; 4262306a36Sopenharmony_ciextern unsigned int sysctl_fib_sync_mem_max; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistruct sock; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct inet_skb_parm { 4762306a36Sopenharmony_ci int iif; 4862306a36Sopenharmony_ci struct ip_options opt; /* Compiled IP options */ 4962306a36Sopenharmony_ci u16 flags; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define IPSKB_FORWARDED BIT(0) 5262306a36Sopenharmony_ci#define IPSKB_XFRM_TUNNEL_SIZE BIT(1) 5362306a36Sopenharmony_ci#define IPSKB_XFRM_TRANSFORMED BIT(2) 5462306a36Sopenharmony_ci#define IPSKB_FRAG_COMPLETE BIT(3) 5562306a36Sopenharmony_ci#define IPSKB_REROUTED BIT(4) 5662306a36Sopenharmony_ci#define IPSKB_DOREDIRECT BIT(5) 5762306a36Sopenharmony_ci#define IPSKB_FRAG_PMTU BIT(6) 5862306a36Sopenharmony_ci#define IPSKB_L3SLAVE BIT(7) 5962306a36Sopenharmony_ci#define IPSKB_NOPOLICY BIT(8) 6062306a36Sopenharmony_ci#define IPSKB_MULTIPATH BIT(9) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci u16 frag_max_size; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic inline bool ipv4_l3mdev_skb(u16 flags) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci return !!(flags & IPSKB_L3SLAVE); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic inline unsigned int ip_hdrlen(const struct sk_buff *skb) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci return ip_hdr(skb)->ihl * 4; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct ipcm_cookie { 7662306a36Sopenharmony_ci struct sockcm_cookie sockc; 7762306a36Sopenharmony_ci __be32 addr; 7862306a36Sopenharmony_ci int oif; 7962306a36Sopenharmony_ci struct ip_options_rcu *opt; 8062306a36Sopenharmony_ci __u8 protocol; 8162306a36Sopenharmony_ci __u8 ttl; 8262306a36Sopenharmony_ci __s16 tos; 8362306a36Sopenharmony_ci char priority; 8462306a36Sopenharmony_ci __u16 gso_size; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic inline void ipcm_init(struct ipcm_cookie *ipcm) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci *ipcm = (struct ipcm_cookie) { .tos = -1 }; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic inline void ipcm_init_sk(struct ipcm_cookie *ipcm, 9362306a36Sopenharmony_ci const struct inet_sock *inet) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci ipcm_init(ipcm); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark); 9862306a36Sopenharmony_ci ipcm->sockc.tsflags = READ_ONCE(inet->sk.sk_tsflags); 9962306a36Sopenharmony_ci ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); 10062306a36Sopenharmony_ci ipcm->addr = inet->inet_saddr; 10162306a36Sopenharmony_ci ipcm->protocol = inet->inet_num; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) 10562306a36Sopenharmony_ci#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb)) 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* return enslaved device index if relevant */ 10862306a36Sopenharmony_cistatic inline int inet_sdif(const struct sk_buff *skb) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) 11162306a36Sopenharmony_ci if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags)) 11262306a36Sopenharmony_ci return IPCB(skb)->iif; 11362306a36Sopenharmony_ci#endif 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* Special input handler for packets caught by router alert option. 11862306a36Sopenharmony_ci They are selected only by protocol field, and then processed likely 11962306a36Sopenharmony_ci local ones; but only if someone wants them! Otherwise, router 12062306a36Sopenharmony_ci not running rsvpd will kill RSVP. 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci It is user level problem, what it will make with them. 12362306a36Sopenharmony_ci I have no idea, how it will masquearde or NAT them (it is joke, joke :-)), 12462306a36Sopenharmony_ci but receiver should be enough clever f.e. to forward mtrace requests, 12562306a36Sopenharmony_ci sent to multicast group to reach destination designated router. 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct ip_ra_chain { 12962306a36Sopenharmony_ci struct ip_ra_chain __rcu *next; 13062306a36Sopenharmony_ci struct sock *sk; 13162306a36Sopenharmony_ci union { 13262306a36Sopenharmony_ci void (*destructor)(struct sock *); 13362306a36Sopenharmony_ci struct sock *saved_sk; 13462306a36Sopenharmony_ci }; 13562306a36Sopenharmony_ci struct rcu_head rcu; 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* IP flags. */ 13962306a36Sopenharmony_ci#define IP_CE 0x8000 /* Flag: "Congestion" */ 14062306a36Sopenharmony_ci#define IP_DF 0x4000 /* Flag: "Don't Fragment" */ 14162306a36Sopenharmony_ci#define IP_MF 0x2000 /* Flag: "More Fragments" */ 14262306a36Sopenharmony_ci#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistruct msghdr; 14762306a36Sopenharmony_cistruct net_device; 14862306a36Sopenharmony_cistruct packet_type; 14962306a36Sopenharmony_cistruct rtable; 15062306a36Sopenharmony_cistruct sockaddr; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciint igmp_mc_init(void); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* 15562306a36Sopenharmony_ci * Functions provided by ip.c 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciint ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, 15962306a36Sopenharmony_ci __be32 saddr, __be32 daddr, 16062306a36Sopenharmony_ci struct ip_options_rcu *opt, u8 tos); 16162306a36Sopenharmony_ciint ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, 16262306a36Sopenharmony_ci struct net_device *orig_dev); 16362306a36Sopenharmony_civoid ip_list_rcv(struct list_head *head, struct packet_type *pt, 16462306a36Sopenharmony_ci struct net_device *orig_dev); 16562306a36Sopenharmony_ciint ip_local_deliver(struct sk_buff *skb); 16662306a36Sopenharmony_civoid ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto); 16762306a36Sopenharmony_ciint ip_mr_input(struct sk_buff *skb); 16862306a36Sopenharmony_ciint ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); 16962306a36Sopenharmony_ciint ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb); 17062306a36Sopenharmony_ciint ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, 17162306a36Sopenharmony_ci int (*output)(struct net *, struct sock *, struct sk_buff *)); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistruct ip_fraglist_iter { 17462306a36Sopenharmony_ci struct sk_buff *frag; 17562306a36Sopenharmony_ci struct iphdr *iph; 17662306a36Sopenharmony_ci int offset; 17762306a36Sopenharmony_ci unsigned int hlen; 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_civoid ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph, 18162306a36Sopenharmony_ci unsigned int hlen, struct ip_fraglist_iter *iter); 18262306a36Sopenharmony_civoid ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct sk_buff *skb = iter->frag; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci iter->frag = skb->next; 18962306a36Sopenharmony_ci skb_mark_not_on_list(skb); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return skb; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistruct ip_frag_state { 19562306a36Sopenharmony_ci bool DF; 19662306a36Sopenharmony_ci unsigned int hlen; 19762306a36Sopenharmony_ci unsigned int ll_rs; 19862306a36Sopenharmony_ci unsigned int mtu; 19962306a36Sopenharmony_ci unsigned int left; 20062306a36Sopenharmony_ci int offset; 20162306a36Sopenharmony_ci int ptr; 20262306a36Sopenharmony_ci __be16 not_last_frag; 20362306a36Sopenharmony_ci}; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_civoid ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs, 20662306a36Sopenharmony_ci unsigned int mtu, bool DF, struct ip_frag_state *state); 20762306a36Sopenharmony_cistruct sk_buff *ip_frag_next(struct sk_buff *skb, 20862306a36Sopenharmony_ci struct ip_frag_state *state); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_civoid ip_send_check(struct iphdr *ip); 21162306a36Sopenharmony_ciint __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 21262306a36Sopenharmony_ciint ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciint __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, 21562306a36Sopenharmony_ci __u8 tos); 21662306a36Sopenharmony_civoid ip_init(void); 21762306a36Sopenharmony_ciint ip_append_data(struct sock *sk, struct flowi4 *fl4, 21862306a36Sopenharmony_ci int getfrag(void *from, char *to, int offset, int len, 21962306a36Sopenharmony_ci int odd, struct sk_buff *skb), 22062306a36Sopenharmony_ci void *from, int len, int protolen, 22162306a36Sopenharmony_ci struct ipcm_cookie *ipc, 22262306a36Sopenharmony_ci struct rtable **rt, 22362306a36Sopenharmony_ci unsigned int flags); 22462306a36Sopenharmony_ciint ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, 22562306a36Sopenharmony_ci struct sk_buff *skb); 22662306a36Sopenharmony_cistruct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4, 22762306a36Sopenharmony_ci struct sk_buff_head *queue, 22862306a36Sopenharmony_ci struct inet_cork *cork); 22962306a36Sopenharmony_ciint ip_send_skb(struct net *net, struct sk_buff *skb); 23062306a36Sopenharmony_ciint ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4); 23162306a36Sopenharmony_civoid ip_flush_pending_frames(struct sock *sk); 23262306a36Sopenharmony_cistruct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4, 23362306a36Sopenharmony_ci int getfrag(void *from, char *to, int offset, 23462306a36Sopenharmony_ci int len, int odd, struct sk_buff *skb), 23562306a36Sopenharmony_ci void *from, int length, int transhdrlen, 23662306a36Sopenharmony_ci struct ipcm_cookie *ipc, struct rtable **rtp, 23762306a36Sopenharmony_ci struct inet_cork *cork, unsigned int flags); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciint ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* Get the route scope that should be used when sending a packet. */ 24762306a36Sopenharmony_cistatic inline u8 ip_sendmsg_scope(const struct inet_sock *inet, 24862306a36Sopenharmony_ci const struct ipcm_cookie *ipc, 24962306a36Sopenharmony_ci const struct msghdr *msg) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci if (sock_flag(&inet->sk, SOCK_LOCALROUTE) || 25262306a36Sopenharmony_ci msg->msg_flags & MSG_DONTROUTE || 25362306a36Sopenharmony_ci (ipc->opt && ipc->opt->opt.is_strictroute)) 25462306a36Sopenharmony_ci return RT_SCOPE_LINK; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci return RT_SCOPE_UNIVERSE; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci/* datagram.c */ 26562306a36Sopenharmony_ciint __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 26662306a36Sopenharmony_ciint ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_civoid ip4_datagram_release_cb(struct sock *sk); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistruct ip_reply_arg { 27162306a36Sopenharmony_ci struct kvec iov[1]; 27262306a36Sopenharmony_ci int flags; 27362306a36Sopenharmony_ci __wsum csum; 27462306a36Sopenharmony_ci int csumoffset; /* u16 offset of csum in iov[0].iov_base */ 27562306a36Sopenharmony_ci /* -1 if not needed */ 27662306a36Sopenharmony_ci int bound_dev_if; 27762306a36Sopenharmony_ci u8 tos; 27862306a36Sopenharmony_ci kuid_t uid; 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#define IP_REPLY_ARG_NOSRCCHECK 1 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, 28962306a36Sopenharmony_ci const struct ip_options *sopt, 29062306a36Sopenharmony_ci __be32 daddr, __be32 saddr, 29162306a36Sopenharmony_ci const struct ip_reply_arg *arg, 29262306a36Sopenharmony_ci unsigned int len, u64 transmit_time, u32 txhash); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) 29562306a36Sopenharmony_ci#define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) 29662306a36Sopenharmony_ci#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 29762306a36Sopenharmony_ci#define __IP_ADD_STATS(net, field, val) __SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val) 29862306a36Sopenharmony_ci#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 29962306a36Sopenharmony_ci#define __IP_UPD_PO_STATS(net, field, val) __SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val) 30062306a36Sopenharmony_ci#define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) 30162306a36Sopenharmony_ci#define __NET_INC_STATS(net, field) __SNMP_INC_STATS((net)->mib.net_statistics, field) 30262306a36Sopenharmony_ci#define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 30362306a36Sopenharmony_ci#define __NET_ADD_STATS(net, field, adnd) __SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd) 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic inline u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci return *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ciunsigned long snmp_fold_field(void __percpu *mib, int offt); 31162306a36Sopenharmony_ci#if BITS_PER_LONG==32 31262306a36Sopenharmony_ciu64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 31362306a36Sopenharmony_ci size_t syncp_offset); 31462306a36Sopenharmony_ciu64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off); 31562306a36Sopenharmony_ci#else 31662306a36Sopenharmony_cistatic inline u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offct, 31762306a36Sopenharmony_ci size_t syncp_offset) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci return snmp_get_cpu_field(mib, cpu, offct); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci return snmp_fold_field(mib, offt); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci#endif 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci#define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \ 33062306a36Sopenharmony_ci{ \ 33162306a36Sopenharmony_ci int i, c; \ 33262306a36Sopenharmony_ci for_each_possible_cpu(c) { \ 33362306a36Sopenharmony_ci for (i = 0; stats_list[i].name; i++) \ 33462306a36Sopenharmony_ci buff64[i] += snmp_get_cpu_field64( \ 33562306a36Sopenharmony_ci mib_statistic, \ 33662306a36Sopenharmony_ci c, stats_list[i].entry, \ 33762306a36Sopenharmony_ci offset); \ 33862306a36Sopenharmony_ci } \ 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci#define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \ 34262306a36Sopenharmony_ci{ \ 34362306a36Sopenharmony_ci int i, c; \ 34462306a36Sopenharmony_ci for_each_possible_cpu(c) { \ 34562306a36Sopenharmony_ci for (i = 0; stats_list[i].name; i++) \ 34662306a36Sopenharmony_ci buff[i] += snmp_get_cpu_field( \ 34762306a36Sopenharmony_ci mib_statistic, \ 34862306a36Sopenharmony_ci c, stats_list[i].entry); \ 34962306a36Sopenharmony_ci } \ 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_civoid inet_get_local_port_range(const struct net *net, int *low, int *high); 35362306a36Sopenharmony_civoid inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL 35662306a36Sopenharmony_cistatic inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci if (!net->ipv4.sysctl_local_reserved_ports) 35962306a36Sopenharmony_ci return false; 36062306a36Sopenharmony_ci return test_bit(port, net->ipv4.sysctl_local_reserved_ports); 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic inline bool sysctl_dev_name_is_allowed(const char *name) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci return strcmp(name, "default") != 0 && strcmp(name, "all") != 0; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci#else 37462306a36Sopenharmony_cistatic inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci return false; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci return port < PROT_SOCK; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci#endif 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci__be32 inet_current_timestamp(void); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/* From inetpeer.c */ 38862306a36Sopenharmony_ciextern int inet_peer_threshold; 38962306a36Sopenharmony_ciextern int inet_peer_minttl; 39062306a36Sopenharmony_ciextern int inet_peer_maxttl; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_civoid ipfrag_init(void); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_civoid ip_static_sysctl_init(void); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci#define IP4_REPLY_MARK(net, mark) \ 39762306a36Sopenharmony_ci (READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0) 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic inline bool ip_is_fragment(const struct iphdr *iph) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci#ifdef CONFIG_INET 40562306a36Sopenharmony_ci#include <net/dst.h> 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/* The function in 2.2 was invalid, producing wrong result for 40862306a36Sopenharmony_ci * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */ 40962306a36Sopenharmony_cistatic inline 41062306a36Sopenharmony_ciint ip_decrease_ttl(struct iphdr *iph) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci u32 check = (__force u32)iph->check; 41362306a36Sopenharmony_ci check += (__force u32)htons(0x0100); 41462306a36Sopenharmony_ci iph->check = (__force __sum16)(check + (check>=0xFFFF)); 41562306a36Sopenharmony_ci return --iph->ttl; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic inline int ip_mtu_locked(const struct dst_entry *dst) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci const struct rtable *rt = (const struct rtable *)dst; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic inline 42662306a36Sopenharmony_ciint ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci u8 pmtudisc = READ_ONCE(inet_sk(sk)->pmtudisc); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci return pmtudisc == IP_PMTUDISC_DO || 43162306a36Sopenharmony_ci (pmtudisc == IP_PMTUDISC_WANT && 43262306a36Sopenharmony_ci !ip_mtu_locked(dst)); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic inline bool ip_sk_accept_pmtu(const struct sock *sk) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE && 43862306a36Sopenharmony_ci inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic inline bool ip_sk_use_pmtu(const struct sock *sk) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic inline bool ip_sk_ignore_df(const struct sock *sk) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO || 44962306a36Sopenharmony_ci inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, 45362306a36Sopenharmony_ci bool forwarding) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci const struct rtable *rt = container_of(dst, struct rtable, dst); 45662306a36Sopenharmony_ci struct net *net = dev_net(dst->dev); 45762306a36Sopenharmony_ci unsigned int mtu; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || 46062306a36Sopenharmony_ci ip_mtu_locked(dst) || 46162306a36Sopenharmony_ci !forwarding) { 46262306a36Sopenharmony_ci mtu = rt->rt_pmtu; 46362306a36Sopenharmony_ci if (mtu && time_before(jiffies, rt->dst.expires)) 46462306a36Sopenharmony_ci goto out; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci /* 'forwarding = true' case should always honour route mtu */ 46862306a36Sopenharmony_ci mtu = dst_metric_raw(dst, RTAX_MTU); 46962306a36Sopenharmony_ci if (mtu) 47062306a36Sopenharmony_ci goto out; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci mtu = READ_ONCE(dst->dev->mtu); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (unlikely(ip_mtu_locked(dst))) { 47562306a36Sopenharmony_ci if (rt->rt_uses_gateway && mtu > 576) 47662306a36Sopenharmony_ci mtu = 576; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciout: 48062306a36Sopenharmony_ci mtu = min_t(unsigned int, mtu, IP_MAX_MTU); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return mtu - lwtunnel_headroom(dst->lwtstate, mtu); 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic inline unsigned int ip_skb_dst_mtu(struct sock *sk, 48662306a36Sopenharmony_ci const struct sk_buff *skb) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci unsigned int mtu; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) { 49162306a36Sopenharmony_ci bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); 49762306a36Sopenharmony_ci return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistruct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx, 50162306a36Sopenharmony_ci int fc_mx_len, 50262306a36Sopenharmony_ci struct netlink_ext_ack *extack); 50362306a36Sopenharmony_cistatic inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci if (fib_metrics != &dst_default_metrics && 50662306a36Sopenharmony_ci refcount_dec_and_test(&fib_metrics->refcnt)) 50762306a36Sopenharmony_ci kfree(fib_metrics); 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci/* ipv4 and ipv6 both use refcounted metrics if it is not the default */ 51162306a36Sopenharmony_cistatic inline 51262306a36Sopenharmony_civoid ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci dst_init_metrics(dst, fib_metrics->metrics, true); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci if (fib_metrics != &dst_default_metrics) { 51762306a36Sopenharmony_ci dst->_metrics |= DST_METRICS_REFCOUNTED; 51862306a36Sopenharmony_ci refcount_inc(&fib_metrics->refcnt); 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic inline 52362306a36Sopenharmony_civoid ip_dst_metrics_put(struct dst_entry *dst) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) 52862306a36Sopenharmony_ci kfree(p); 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_civoid __ip_select_ident(struct net *net, struct iphdr *iph, int segs); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, 53462306a36Sopenharmony_ci struct sock *sk, int segs) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci struct iphdr *iph = ip_hdr(skb); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci /* We had many attacks based on IPID, use the private 53962306a36Sopenharmony_ci * generator as much as we can. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci if (sk && inet_sk(sk)->inet_daddr) { 54262306a36Sopenharmony_ci int val; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci /* avoid atomic operations for TCP, 54562306a36Sopenharmony_ci * as we hold socket lock at this point. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ci if (sk_is_tcp(sk)) { 54862306a36Sopenharmony_ci sock_owned_by_me(sk); 54962306a36Sopenharmony_ci val = atomic_read(&inet_sk(sk)->inet_id); 55062306a36Sopenharmony_ci atomic_set(&inet_sk(sk)->inet_id, val + segs); 55162306a36Sopenharmony_ci } else { 55262306a36Sopenharmony_ci val = atomic_add_return(segs, &inet_sk(sk)->inet_id); 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci iph->id = htons(val); 55562306a36Sopenharmony_ci return; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { 55862306a36Sopenharmony_ci iph->id = 0; 55962306a36Sopenharmony_ci } else { 56062306a36Sopenharmony_ci /* Unfortunately we need the big hammer to get a suitable IPID */ 56162306a36Sopenharmony_ci __ip_select_ident(net, iph, segs); 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cistatic inline void ip_select_ident(struct net *net, struct sk_buff *skb, 56662306a36Sopenharmony_ci struct sock *sk) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci ip_select_ident_segs(net, skb, sk, 1); 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 57462306a36Sopenharmony_ci skb->len, proto, 0); 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci/* copy IPv4 saddr & daddr to flow_keys, possibly using 64bit load/store 57862306a36Sopenharmony_ci * Equivalent to : flow->v4addrs.src = iph->saddr; 57962306a36Sopenharmony_ci * flow->v4addrs.dst = iph->daddr; 58062306a36Sopenharmony_ci */ 58162306a36Sopenharmony_cistatic inline void iph_to_flow_copy_v4addrs(struct flow_keys *flow, 58262306a36Sopenharmony_ci const struct iphdr *iph) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != 58562306a36Sopenharmony_ci offsetof(typeof(flow->addrs), v4addrs.src) + 58662306a36Sopenharmony_ci sizeof(flow->addrs.v4addrs.src)); 58762306a36Sopenharmony_ci memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs)); 58862306a36Sopenharmony_ci flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci/* 59262306a36Sopenharmony_ci * Map a multicast IP onto multicast MAC for type ethernet. 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic inline void ip_eth_mc_map(__be32 naddr, char *buf) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci __u32 addr=ntohl(naddr); 59862306a36Sopenharmony_ci buf[0]=0x01; 59962306a36Sopenharmony_ci buf[1]=0x00; 60062306a36Sopenharmony_ci buf[2]=0x5e; 60162306a36Sopenharmony_ci buf[5]=addr&0xFF; 60262306a36Sopenharmony_ci addr>>=8; 60362306a36Sopenharmony_ci buf[4]=addr&0xFF; 60462306a36Sopenharmony_ci addr>>=8; 60562306a36Sopenharmony_ci buf[3]=addr&0x7F; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* 60962306a36Sopenharmony_ci * Map a multicast IP onto multicast MAC for type IP-over-InfiniBand. 61062306a36Sopenharmony_ci * Leave P_Key as 0 to be filled in by driver. 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci __u32 addr; 61662306a36Sopenharmony_ci unsigned char scope = broadcast[5] & 0xF; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci buf[0] = 0; /* Reserved */ 61962306a36Sopenharmony_ci buf[1] = 0xff; /* Multicast QPN */ 62062306a36Sopenharmony_ci buf[2] = 0xff; 62162306a36Sopenharmony_ci buf[3] = 0xff; 62262306a36Sopenharmony_ci addr = ntohl(naddr); 62362306a36Sopenharmony_ci buf[4] = 0xff; 62462306a36Sopenharmony_ci buf[5] = 0x10 | scope; /* scope from broadcast address */ 62562306a36Sopenharmony_ci buf[6] = 0x40; /* IPv4 signature */ 62662306a36Sopenharmony_ci buf[7] = 0x1b; 62762306a36Sopenharmony_ci buf[8] = broadcast[8]; /* P_Key */ 62862306a36Sopenharmony_ci buf[9] = broadcast[9]; 62962306a36Sopenharmony_ci buf[10] = 0; 63062306a36Sopenharmony_ci buf[11] = 0; 63162306a36Sopenharmony_ci buf[12] = 0; 63262306a36Sopenharmony_ci buf[13] = 0; 63362306a36Sopenharmony_ci buf[14] = 0; 63462306a36Sopenharmony_ci buf[15] = 0; 63562306a36Sopenharmony_ci buf[19] = addr & 0xff; 63662306a36Sopenharmony_ci addr >>= 8; 63762306a36Sopenharmony_ci buf[18] = addr & 0xff; 63862306a36Sopenharmony_ci addr >>= 8; 63962306a36Sopenharmony_ci buf[17] = addr & 0xff; 64062306a36Sopenharmony_ci addr >>= 8; 64162306a36Sopenharmony_ci buf[16] = addr & 0x0f; 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) 64562306a36Sopenharmony_ci{ 64662306a36Sopenharmony_ci if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) 64762306a36Sopenharmony_ci memcpy(buf, broadcast, 4); 64862306a36Sopenharmony_ci else 64962306a36Sopenharmony_ci memcpy(buf, &naddr, sizeof(naddr)); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 65362306a36Sopenharmony_ci#include <linux/ipv6.h> 65462306a36Sopenharmony_ci#endif 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic __inline__ void inet_reset_saddr(struct sock *sk) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0; 65962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 66062306a36Sopenharmony_ci if (sk->sk_family == PF_INET6) { 66162306a36Sopenharmony_ci struct ipv6_pinfo *np = inet6_sk(sk); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci memset(&np->saddr, 0, sizeof(np->saddr)); 66462306a36Sopenharmony_ci memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr)); 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci#endif 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci#endif 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic inline unsigned int ipv4_addr_hash(__be32 ip) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci return (__force unsigned int) ip; 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_cistatic inline u32 ipv4_portaddr_hash(const struct net *net, 67762306a36Sopenharmony_ci __be32 saddr, 67862306a36Sopenharmony_ci unsigned int port) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cibool ip_call_ra_chain(struct sk_buff *skb); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci/* 68662306a36Sopenharmony_ci * Functions provided by ip_fragment.c 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cienum ip_defrag_users { 69062306a36Sopenharmony_ci IP_DEFRAG_LOCAL_DELIVER, 69162306a36Sopenharmony_ci IP_DEFRAG_CALL_RA_CHAIN, 69262306a36Sopenharmony_ci IP_DEFRAG_CONNTRACK_IN, 69362306a36Sopenharmony_ci __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX, 69462306a36Sopenharmony_ci IP_DEFRAG_CONNTRACK_OUT, 69562306a36Sopenharmony_ci __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX, 69662306a36Sopenharmony_ci IP_DEFRAG_CONNTRACK_BRIDGE_IN, 69762306a36Sopenharmony_ci __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX, 69862306a36Sopenharmony_ci IP_DEFRAG_VS_IN, 69962306a36Sopenharmony_ci IP_DEFRAG_VS_OUT, 70062306a36Sopenharmony_ci IP_DEFRAG_VS_FWD, 70162306a36Sopenharmony_ci IP_DEFRAG_AF_PACKET, 70262306a36Sopenharmony_ci IP_DEFRAG_MACVLAN, 70362306a36Sopenharmony_ci}; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci/* Return true if the value of 'user' is between 'lower_bond' 70662306a36Sopenharmony_ci * and 'upper_bond' inclusively. 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_cistatic inline bool ip_defrag_user_in_between(u32 user, 70962306a36Sopenharmony_ci enum ip_defrag_users lower_bond, 71062306a36Sopenharmony_ci enum ip_defrag_users upper_bond) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci return user >= lower_bond && user <= upper_bond; 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ciint ip_defrag(struct net *net, struct sk_buff *skb, u32 user); 71662306a36Sopenharmony_ci#ifdef CONFIG_INET 71762306a36Sopenharmony_cistruct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user); 71862306a36Sopenharmony_ci#else 71962306a36Sopenharmony_cistatic inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci return skb; 72262306a36Sopenharmony_ci} 72362306a36Sopenharmony_ci#endif 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci/* 72662306a36Sopenharmony_ci * Functions provided by ip_forward.c 72762306a36Sopenharmony_ci */ 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ciint ip_forward(struct sk_buff *skb); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci/* 73262306a36Sopenharmony_ci * Functions provided by ip_options.c 73362306a36Sopenharmony_ci */ 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_civoid ip_options_build(struct sk_buff *skb, struct ip_options *opt, 73662306a36Sopenharmony_ci __be32 daddr, struct rtable *rt); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciint __ip_options_echo(struct net *net, struct ip_options *dopt, 73962306a36Sopenharmony_ci struct sk_buff *skb, const struct ip_options *sopt); 74062306a36Sopenharmony_cistatic inline int ip_options_echo(struct net *net, struct ip_options *dopt, 74162306a36Sopenharmony_ci struct sk_buff *skb) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt); 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_civoid ip_options_fragment(struct sk_buff *skb); 74762306a36Sopenharmony_ciint __ip_options_compile(struct net *net, struct ip_options *opt, 74862306a36Sopenharmony_ci struct sk_buff *skb, __be32 *info); 74962306a36Sopenharmony_ciint ip_options_compile(struct net *net, struct ip_options *opt, 75062306a36Sopenharmony_ci struct sk_buff *skb); 75162306a36Sopenharmony_ciint ip_options_get(struct net *net, struct ip_options_rcu **optp, 75262306a36Sopenharmony_ci sockptr_t data, int optlen); 75362306a36Sopenharmony_civoid ip_options_undo(struct ip_options *opt); 75462306a36Sopenharmony_civoid ip_forward_options(struct sk_buff *skb); 75562306a36Sopenharmony_ciint ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci/* 75862306a36Sopenharmony_ci * Functions provided by ip_sockglue.c 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_civoid ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb, bool drop_dst); 76262306a36Sopenharmony_civoid ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, 76362306a36Sopenharmony_ci struct sk_buff *skb, int tlen, int offset); 76462306a36Sopenharmony_ciint ip_cmsg_send(struct sock *sk, struct msghdr *msg, 76562306a36Sopenharmony_ci struct ipcm_cookie *ipc, bool allow_ipv6); 76662306a36Sopenharmony_ciDECLARE_STATIC_KEY_FALSE(ip4_min_ttl); 76762306a36Sopenharmony_ciint do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, 76862306a36Sopenharmony_ci unsigned int optlen); 76962306a36Sopenharmony_ciint ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, 77062306a36Sopenharmony_ci unsigned int optlen); 77162306a36Sopenharmony_ciint do_ip_getsockopt(struct sock *sk, int level, int optname, 77262306a36Sopenharmony_ci sockptr_t optval, sockptr_t optlen); 77362306a36Sopenharmony_ciint ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, 77462306a36Sopenharmony_ci int __user *optlen); 77562306a36Sopenharmony_ciint ip_ra_control(struct sock *sk, unsigned char on, 77662306a36Sopenharmony_ci void (*destructor)(struct sock *)); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ciint ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); 77962306a36Sopenharmony_civoid ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, 78062306a36Sopenharmony_ci u32 info, u8 *payload); 78162306a36Sopenharmony_civoid ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, 78262306a36Sopenharmony_ci u32 info); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0); 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cibool icmp_global_allow(void); 79062306a36Sopenharmony_ciextern int sysctl_icmp_msgs_per_sec; 79162306a36Sopenharmony_ciextern int sysctl_icmp_msgs_burst; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 79462306a36Sopenharmony_ciint ip_misc_proc_init(void); 79562306a36Sopenharmony_ci#endif 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ciint rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family, 79862306a36Sopenharmony_ci struct netlink_ext_ack *extack); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic inline bool inetdev_valid_mtu(unsigned int mtu) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci return likely(mtu >= IPV4_MIN_MTU); 80362306a36Sopenharmony_ci} 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_civoid ip_sock_set_freebind(struct sock *sk); 80662306a36Sopenharmony_ciint ip_sock_set_mtu_discover(struct sock *sk, int val); 80762306a36Sopenharmony_civoid ip_sock_set_pktinfo(struct sock *sk); 80862306a36Sopenharmony_civoid ip_sock_set_recverr(struct sock *sk); 80962306a36Sopenharmony_civoid ip_sock_set_tos(struct sock *sk, int val); 81062306a36Sopenharmony_civoid __ip_sock_set_tos(struct sock *sk, int val); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci#endif /* _IP_H */ 813