1685 lines · 48.0 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* IP Virtual Server * data structure and functionality definitions */ #ifndef _NET_IP_VS_H#define _NET_IP_VS_H #include <linux/ip_vs.h>                /* definitions shared with userland */ #include <asm/types.h>                  /* for __uXX types */ #include <linux/list.h>                 /* for struct list_head */#include <linux/spinlock.h>             /* for struct rwlock_t */#include <linux/atomic.h>               /* for struct atomic_t */#include <linux/refcount.h>             /* for struct refcount_t */ #include <linux/compiler.h>#include <linux/timer.h>#include <linux/bug.h> #include <net/checksum.h>#include <linux/netfilter.h>		/* for union nf_inet_addr */#include <linux/ip.h>#include <linux/ipv6.h>			/* for struct ipv6hdr */#include <net/ipv6.h>#if IS_ENABLED(CONFIG_IP_VS_IPV6)#include <linux/netfilter_ipv6/ip6_tables.h>#endif#if IS_ENABLED(CONFIG_NF_CONNTRACK)#include <net/netfilter/nf_conntrack.h>#endif#include <net/net_namespace.h>		/* Netw namespace */ #define IP_VS_HDR_INVERSE	1#define IP_VS_HDR_ICMP		2 /* Generic access of ipvs struct */static inline struct netns_ipvs *net_ipvs(struct net* net){	return net->ipvs;} /* Connections' size value needed by ip_vs_ctl.c */extern int ip_vs_conn_tab_size; struct ip_vs_iphdr {	int hdr_flags;	/* ipvs flags */	__u32 off;	/* Where IP or IPv4 header starts */	__u32 len;	/* IPv4 simply where L4 starts			 * IPv6 where L4 Transport Header starts */	__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/	__s16 protocol;	__s32 flags;	union nf_inet_addr saddr;	union nf_inet_addr daddr;}; static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,				      int len, void *buffer){	return skb_header_pointer(skb, offset, len, buffer);} /* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6. * IPv6 requires some extra work, as finding proper header position, * depend on the IPv6 extension headers. */static inline intip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset,		       int hdr_flags, struct ip_vs_iphdr *iphdr){	iphdr->hdr_flags = hdr_flags;	iphdr->off = offset; #ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		struct ipv6hdr _iph;		const struct ipv6hdr *iph = skb_header_pointer(			skb, offset, sizeof(_iph), &_iph);		if (!iph)			return 0; 		iphdr->saddr.in6 = iph->saddr;		iphdr->daddr.in6 = iph->daddr;		/* ipv6_find_hdr() updates len, flags */		iphdr->len	 = offset;		iphdr->flags	 = 0;		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,						 &iphdr->fragoffs,						 &iphdr->flags);		if (iphdr->protocol < 0)			return 0;	} else#endif	{		struct iphdr _iph;		const struct iphdr *iph = skb_header_pointer(			skb, offset, sizeof(_iph), &_iph);		if (!iph)			return 0; 		iphdr->len	= offset + iph->ihl * 4;		iphdr->fragoffs	= 0;		iphdr->protocol	= iph->protocol;		iphdr->saddr.ip	= iph->saddr;		iphdr->daddr.ip	= iph->daddr;	} 	return 1;} static inline intip_vs_fill_iph_skb_icmp(int af, const struct sk_buff *skb, int offset,			bool inverse, struct ip_vs_iphdr *iphdr){	int hdr_flags = IP_VS_HDR_ICMP; 	if (inverse)		hdr_flags |= IP_VS_HDR_INVERSE; 	return ip_vs_fill_iph_skb_off(af, skb, offset, hdr_flags, iphdr);} static inline intip_vs_fill_iph_skb(int af, const struct sk_buff *skb, bool inverse,		   struct ip_vs_iphdr *iphdr){	int hdr_flags = 0; 	if (inverse)		hdr_flags |= IP_VS_HDR_INVERSE; 	return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb),				      hdr_flags, iphdr);} static inline boolip_vs_iph_inverse(const struct ip_vs_iphdr *iph){	return !!(iph->hdr_flags & IP_VS_HDR_INVERSE);} static inline boolip_vs_iph_icmp(const struct ip_vs_iphdr *iph){	return !!(iph->hdr_flags & IP_VS_HDR_ICMP);} static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,				   const union nf_inet_addr *src){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		dst->in6 = src->in6;	else#endif	dst->ip = src->ip;} static inline void ip_vs_addr_set(int af, union nf_inet_addr *dst,				  const union nf_inet_addr *src){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		dst->in6 = src->in6;		return;	}#endif	dst->ip = src->ip;	dst->all[1] = 0;	dst->all[2] = 0;	dst->all[3] = 0;} static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a,				   const union nf_inet_addr *b){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		return ipv6_addr_equal(&a->in6, &b->in6);#endif	return a->ip == b->ip;} #ifdef CONFIG_IP_VS_DEBUG#include <linux/net.h> int ip_vs_get_debug_level(void); static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,					 const union nf_inet_addr *addr,					 int *idx){	int len;#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6)		len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",			       &addr->in6) + 1;	else#endif		len = snprintf(&buf[*idx], buf_len - *idx, "%pI4",			       &addr->ip) + 1; 	*idx += len;	BUG_ON(*idx > buf_len + 1);	return &buf[*idx - len];} #define IP_VS_DBG_BUF(level, msg, ...)					\	do {								\		char ip_vs_dbg_buf[160];				\		int ip_vs_dbg_idx = 0;					\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_ERR_BUF(msg...)						\	do {								\		char ip_vs_dbg_buf[160];				\		int ip_vs_dbg_idx = 0;					\		pr_err(msg);						\	} while (0) /* Only use from within IP_VS_DBG_BUF() or IP_VS_ERR_BUF macros */#define IP_VS_DBG_ADDR(af, addr)					\	ip_vs_dbg_addr(af, ip_vs_dbg_buf,				\		       sizeof(ip_vs_dbg_buf), addr,			\		       &ip_vs_dbg_idx) #define IP_VS_DBG(level, msg, ...)					\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_DBG_RL(msg, ...)						\	do {								\		if (net_ratelimit())					\			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\	} while (0)#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)			\	do {								\		if (level <= ip_vs_get_debug_level())			\			pp->debug_packet(af, pp, skb, ofs, msg);	\	} while (0)#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)			\	do {								\		if (level <= ip_vs_get_debug_level() &&			\		    net_ratelimit())					\			pp->debug_packet(af, pp, skb, ofs, msg);	\	} while (0)#else	/* NO DEBUGGING at ALL */#define IP_VS_DBG_BUF(level, msg...)  do {} while (0)#define IP_VS_ERR_BUF(msg...)  do {} while (0)#define IP_VS_DBG(level, msg...)  do {} while (0)#define IP_VS_DBG_RL(msg...)  do {} while (0)#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)#endif #define IP_VS_BUG() BUG()#define IP_VS_ERR_RL(msg, ...)						\	do {								\		if (net_ratelimit())					\			pr_err(msg, ##__VA_ARGS__);			\	} while (0) #ifdef CONFIG_IP_VS_DEBUG#define EnterFunction(level)						\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG				\			       pr_fmt("Enter: %s, %s line %i\n"),	\			       __func__, __FILE__, __LINE__);		\	} while (0)#define LeaveFunction(level)						\	do {								\		if (level <= ip_vs_get_debug_level())			\			printk(KERN_DEBUG				\			       pr_fmt("Leave: %s, %s line %i\n"),	\			       __func__, __FILE__, __LINE__);		\	} while (0)#else#define EnterFunction(level)   do {} while (0)#define LeaveFunction(level)   do {} while (0)#endif /* The port number of FTP service (in network order). */#define FTPPORT  cpu_to_be16(21)#define FTPDATA  cpu_to_be16(20) /* TCP State Values */enum {	IP_VS_TCP_S_NONE = 0,	IP_VS_TCP_S_ESTABLISHED,	IP_VS_TCP_S_SYN_SENT,	IP_VS_TCP_S_SYN_RECV,	IP_VS_TCP_S_FIN_WAIT,	IP_VS_TCP_S_TIME_WAIT,	IP_VS_TCP_S_CLOSE,	IP_VS_TCP_S_CLOSE_WAIT,	IP_VS_TCP_S_LAST_ACK,	IP_VS_TCP_S_LISTEN,	IP_VS_TCP_S_SYNACK,	IP_VS_TCP_S_LAST}; /* UDP State Values */enum {	IP_VS_UDP_S_NORMAL,	IP_VS_UDP_S_LAST,}; /* ICMP State Values */enum {	IP_VS_ICMP_S_NORMAL,	IP_VS_ICMP_S_LAST,}; /* SCTP State Values */enum ip_vs_sctp_states {	IP_VS_SCTP_S_NONE,	IP_VS_SCTP_S_INIT1,	IP_VS_SCTP_S_INIT,	IP_VS_SCTP_S_COOKIE_SENT,	IP_VS_SCTP_S_COOKIE_REPLIED,	IP_VS_SCTP_S_COOKIE_WAIT,	IP_VS_SCTP_S_COOKIE,	IP_VS_SCTP_S_COOKIE_ECHOED,	IP_VS_SCTP_S_ESTABLISHED,	IP_VS_SCTP_S_SHUTDOWN_SENT,	IP_VS_SCTP_S_SHUTDOWN_RECEIVED,	IP_VS_SCTP_S_SHUTDOWN_ACK_SENT,	IP_VS_SCTP_S_REJECTED,	IP_VS_SCTP_S_CLOSED,	IP_VS_SCTP_S_LAST}; /* Connection templates use bits from state */#define IP_VS_CTPL_S_NONE		0x0000#define IP_VS_CTPL_S_ASSURED		0x0001#define IP_VS_CTPL_S_LAST		0x0002 /* Delta sequence info structure * Each ip_vs_conn has 2 (output AND input seq. changes). * Only used in the VS/NAT. */struct ip_vs_seq {	__u32			init_seq;	/* Add delta from this seq */	__u32			delta;		/* Delta in sequence numbers */	__u32			previous_delta;	/* Delta in sequence numbers						 * before last resized pkt */}; /* counters per cpu */struct ip_vs_counters {	__u64		conns;		/* connections scheduled */	__u64		inpkts;		/* incoming packets */	__u64		outpkts;	/* outgoing packets */	__u64		inbytes;	/* incoming bytes */	__u64		outbytes;	/* outgoing bytes */};/* Stats per cpu */struct ip_vs_cpu_stats {	struct ip_vs_counters   cnt;	struct u64_stats_sync   syncp;}; /* IPVS statistics objects */struct ip_vs_estimator {	struct list_head	list; 	u64			last_inbytes;	u64			last_outbytes;	u64			last_conns;	u64			last_inpkts;	u64			last_outpkts; 	u64			cps;	u64			inpps;	u64			outpps;	u64			inbps;	u64			outbps;}; /* * IPVS statistics object, 64-bit kernel version of struct ip_vs_stats_user */struct ip_vs_kstats {	u64			conns;		/* connections scheduled */	u64			inpkts;		/* incoming packets */	u64			outpkts;	/* outgoing packets */	u64			inbytes;	/* incoming bytes */	u64			outbytes;	/* outgoing bytes */ 	u64			cps;		/* current connection rate */	u64			inpps;		/* current in packet rate */	u64			outpps;		/* current out packet rate */	u64			inbps;		/* current in byte rate */	u64			outbps;		/* current out byte rate */}; struct ip_vs_stats {	struct ip_vs_kstats	kstats;		/* kernel statistics */	struct ip_vs_estimator	est;		/* estimator */	struct ip_vs_cpu_stats __percpu	*cpustats;	/* per cpu counters */	spinlock_t		lock;		/* spin lock */	struct ip_vs_kstats	kstats0;	/* reset values */}; struct dst_entry;struct iphdr;struct ip_vs_conn;struct ip_vs_app;struct sk_buff;struct ip_vs_proto_data; struct ip_vs_protocol {	struct ip_vs_protocol	*next;	char			*name;	u16			protocol;	u16			num_states;	int			dont_defrag; 	void (*init)(struct ip_vs_protocol *pp); 	void (*exit)(struct ip_vs_protocol *pp); 	int (*init_netns)(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd); 	void (*exit_netns)(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd); 	int (*conn_schedule)(struct netns_ipvs *ipvs,			     int af, struct sk_buff *skb,			     struct ip_vs_proto_data *pd,			     int *verdict, struct ip_vs_conn **cpp,			     struct ip_vs_iphdr *iph); 	struct ip_vs_conn *	(*conn_in_get)(struct netns_ipvs *ipvs,		       int af,		       const struct sk_buff *skb,		       const struct ip_vs_iphdr *iph); 	struct ip_vs_conn *	(*conn_out_get)(struct netns_ipvs *ipvs,			int af,			const struct sk_buff *skb,			const struct ip_vs_iphdr *iph); 	int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,			    struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); 	int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,			    struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); 	const char *(*state_name)(int state); 	void (*state_transition)(struct ip_vs_conn *cp, int direction,				 const struct sk_buff *skb,				 struct ip_vs_proto_data *pd); 	int (*register_app)(struct netns_ipvs *ipvs, struct ip_vs_app *inc); 	void (*unregister_app)(struct netns_ipvs *ipvs, struct ip_vs_app *inc); 	int (*app_conn_bind)(struct ip_vs_conn *cp); 	void (*debug_packet)(int af, struct ip_vs_protocol *pp,			     const struct sk_buff *skb,			     int offset,			     const char *msg); 	void (*timeout_change)(struct ip_vs_proto_data *pd, int flags);}; /* protocol data per netns */struct ip_vs_proto_data {	struct ip_vs_proto_data	*next;	struct ip_vs_protocol	*pp;	int			*timeout_table;	/* protocol timeout table */	atomic_t		appcnt;		/* counter of proto app incs. */	struct tcp_states_t	*tcp_state_table;}; struct ip_vs_protocol   *ip_vs_proto_get(unsigned short proto);struct ip_vs_proto_data *ip_vs_proto_data_get(struct netns_ipvs *ipvs,					      unsigned short proto); struct ip_vs_conn_param {	struct netns_ipvs		*ipvs;	const union nf_inet_addr	*caddr;	const union nf_inet_addr	*vaddr;	__be16				cport;	__be16				vport;	__u16				protocol;	u16				af; 	const struct ip_vs_pe		*pe;	char				*pe_data;	__u8				pe_data_len;

Lines 1–500 of 1685.