1607 lines · 45.8 KB · C
RawDownload
/* 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/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 */ /* Generic access of ipvs struct */static inline struct netns_ipvs *net_ipvs(struct net* net){	return net->ipvs;} /* Get net ptr from skb in traffic cases * use skb_sknet when call is from userland (ioctl or netlink) */static inline struct net *skb_net(const struct sk_buff *skb){#ifdef CONFIG_NET_NS#ifdef CONFIG_IP_VS_DEBUG	/*	 * This is used for debug only.	 * Start with the most likely hit	 * End with BUG	 */	if (likely(skb->dev && dev_net(skb->dev)))		return dev_net(skb->dev);	if (skb_dst(skb) && skb_dst(skb)->dev)		return dev_net(skb_dst(skb)->dev);	WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",		      __func__, __LINE__);	if (likely(skb->sk && sock_net(skb->sk)))		return sock_net(skb->sk);	pr_err("There is no net ptr to find in the skb in %s() line:%d\n",		__func__, __LINE__);	BUG();#else	return dev_net(skb->dev ? : skb_dst(skb)->dev);#endif#else	return &init_net;#endif} static inline struct net *skb_sknet(const struct sk_buff *skb){#ifdef CONFIG_NET_NS#ifdef CONFIG_IP_VS_DEBUG	/* Start with the most likely hit */	if (likely(skb->sk && sock_net(skb->sk)))		return sock_net(skb->sk);	WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n",		       __func__, __LINE__);	if (likely(skb->dev && dev_net(skb->dev)))		return dev_net(skb->dev);	pr_err("There is no net ptr to find in the skb in %s() line:%d\n",		__func__, __LINE__);	BUG();#else	return sock_net(skb->sk);#endif#else	return &init_net;#endif} /* This one needed for single_open_net since net is stored directly in * private not as a struct i.e. seq_file_net can't be used. */static inline struct net *seq_file_single_net(struct seq_file *seq){#ifdef CONFIG_NET_NS	return (struct net *)seq->private;#else	return &init_net;#endif} /* Connections' size value needed by ip_vs_ctl.c */extern int ip_vs_conn_tab_size; struct ip_vs_iphdr {	__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,				      const struct ip_vs_iphdr *ipvsh){	return skb_header_pointer(skb, offset, len, buffer);} static inline voidip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr){	const struct iphdr *iph = nh; 	iphdr->len	= iph->ihl * 4;	iphdr->fragoffs	= 0;	iphdr->protocol	= iph->protocol;	iphdr->saddr.ip	= iph->saddr;	iphdr->daddr.ip	= iph->daddr;} /* 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 voidip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		const struct ipv6hdr *iph =			(struct ipv6hdr *)skb_network_header(skb);		iphdr->saddr.in6 = iph->saddr;		iphdr->daddr.in6 = iph->daddr;		/* ipv6_find_hdr() updates len, flags */		iphdr->len	 = 0;		iphdr->flags	 = 0;		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,						 &iphdr->fragoffs,						 &iphdr->flags);	} else#endif	{		const struct iphdr *iph =			(struct iphdr *)skb_network_header(skb);		iphdr->len	= iph->ihl * 4;		iphdr->fragoffs	= 0;		iphdr->protocol	= iph->protocol;		iphdr->saddr.ip	= iph->saddr;		iphdr->daddr.ip	= iph->daddr;	}} 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}; /* 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 net *net, struct ip_vs_proto_data *pd); 	void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd); 	int (*conn_schedule)(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)(int af,		       const struct sk_buff *skb,		       const struct ip_vs_iphdr *iph,		       int inverse); 	struct ip_vs_conn *	(*conn_out_get)(int af,			const struct sk_buff *skb,			const struct ip_vs_iphdr *iph,			int inverse); 	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); 	int (*csum_check)(int af, struct sk_buff *skb,			  struct ip_vs_protocol *pp); 	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 net *net, struct ip_vs_app *inc); 	void (*unregister_app)(struct net *net, 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 net *net,

Lines 1–500 of 1607.