1495 lines · 41.7 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 defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)#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 && skb->dev->nd_net))		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 && skb->sk->sk_net))		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 && skb->sk->sk_net))		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 && skb->dev->nd_net))		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 {	int len;	__u8 protocol;	union nf_inet_addr saddr;	union nf_inet_addr daddr;}; static inline voidip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr){#ifdef CONFIG_IP_VS_IPV6	if (af == AF_INET6) {		const struct ipv6hdr *iph = nh;		iphdr->len = sizeof(struct ipv6hdr);		iphdr->protocol = iph->nexthdr;		iphdr->saddr.in6 = iph->saddr;		iphdr->daddr.in6 = iph->daddr;	} else#endif	{		const struct iphdr *iph = nh;		iphdr->len = iph->ihl * 4;		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 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> extern 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, "[%pI6]",			       &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 #define	IP_VS_WAIT_WHILE(expr)	while (expr) { cpu_relax(); }  /* *      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_INIT_CLI,	IP_VS_SCTP_S_INIT_SER,	IP_VS_SCTP_S_INIT_ACK_CLI,	IP_VS_SCTP_S_INIT_ACK_SER,	IP_VS_SCTP_S_ECHO_CLI,	IP_VS_SCTP_S_ECHO_SER,	IP_VS_SCTP_S_ESTABLISHED,	IP_VS_SCTP_S_SHUT_CLI,	IP_VS_SCTP_S_SHUT_SER,	IP_VS_SCTP_S_SHUT_ACK_CLI,	IP_VS_SCTP_S_SHUT_ACK_SER,	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 {	__u32		conns;		/* connections scheduled */	__u32		inpkts;		/* incoming packets */	__u32		outpkts;	/* outgoing packets */	__u64		inbytes;	/* incoming bytes */	__u64		outbytes;	/* outgoing bytes */};/* * Stats per cpu */struct ip_vs_cpu_stats {	struct ip_vs_counters   ustats;	struct u64_stats_sync   syncp;}; /* *	IPVS statistics objects */struct ip_vs_estimator {	struct list_head	list; 	u64			last_inbytes;	u64			last_outbytes;	u32			last_conns;	u32			last_inpkts;	u32			last_outpkts; 	u32			cps;	u32			inpps;	u32			outpps;	u32			inbps;	u32			outbps;}; struct ip_vs_stats {	struct ip_vs_stats_user	ustats;		/* statistics */	struct ip_vs_estimator	est;		/* estimator */	struct ip_vs_cpu_stats	*cpustats;	/* per cpu counters */	spinlock_t		lock;		/* spin lock */	struct ip_vs_stats_user	ustats0;	/* 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_conn *	(*conn_in_get)(int af,		       const struct sk_buff *skb,		       const struct ip_vs_iphdr *iph,		       unsigned int proto_off,		       int inverse); 	struct ip_vs_conn *	(*conn_out_get)(int af,			const struct sk_buff *skb,			const struct ip_vs_iphdr *iph,			unsigned int proto_off,			int inverse); 	int (*snat_handler)(struct sk_buff *skb,			    struct ip_vs_protocol *pp, struct ip_vs_conn *cp); 	int (*dnat_handler)(struct sk_buff *skb,			    struct ip_vs_protocol *pp, struct ip_vs_conn *cp); 	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;}; extern struct ip_vs_protocol   *ip_vs_proto_get(unsigned short proto);extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net,						     unsigned short proto); struct ip_vs_conn_param {	struct net			*net;	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;}; /* *	IP_VS structure allocated for each dynamically scheduled connection */struct ip_vs_conn {	struct hlist_node	c_list;         /* hashed list heads */#ifdef CONFIG_NET_NS	struct net              *net;           /* Name space */#endif	/* Protocol, addresses and port numbers */	u16                     af;             /* address family */	__be16                  cport;	__be16                  vport;	__be16                  dport;	__u32                   fwmark;         /* Fire wall mark from skb */	union nf_inet_addr      caddr;          /* client address */	union nf_inet_addr      vaddr;          /* virtual address */	union nf_inet_addr      daddr;          /* destination address */	volatile __u32          flags;          /* status flags */	__u16                   protocol;       /* Which protocol (TCP/UDP) */ 	/* counter and timer */	atomic_t		refcnt;		/* reference count */	struct timer_list	timer;		/* Expiration timer */	volatile unsigned long	timeout;	/* timeout */ 	/* Flags and state transition */

Lines 1–500 of 1495.