You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							966 lines
						
					
					
						
							29 KiB
						
					
					
				
			
		
		
	
	
							966 lines
						
					
					
						
							29 KiB
						
					
					
				| # --- SDE-COPYRIGHT-NOTE-BEGIN --- | |
| # This copyright note is auto-generated by ./scripts/Create-CopyPatch. | |
| # | |
| # Filename: package/.../ipvsadm/inject_2.4.29_ip_vs.h.patch | |
| # Copyright (C) 2004 - 2006 The T2 SDE Project | |
| # | |
| # More information can be found in the files COPYING and README. | |
| # | |
| # This patch file is dual-licensed. It is available under the license the | |
| # patched project is licensed under, as long as it is an OpenSource license | |
| # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms | |
| # of the GNU General Public License as published by the Free Software | |
| # Foundation; either version 2 of the License, or (at your option) any later | |
| # version. | |
| # --- SDE-COPYRIGHT-NOTE-END --- | |
| --- ./Makefile.orig	2005-02-03 19:09:08.000000000 -0300 | |
| +++ ./Makefile	2005-02-03 19:09:23.000000000 -0300 | |
| @@ -59,7 +59,7 @@ | |
|  		echo "rpm";			\ | |
|  	fi ) | |
|   | |
| -IP_VS_H_DEFINE = $(shell if [ ! -f ../ip_vs.h ]; then \ | |
| +IP_VS_H_DEFINE = $(shell if [ ! -f ip_vs.h ]; then \ | |
|  	echo "-DHAVE_NET_IP_VS_H"; fi;) | |
|   | |
|  ifeq (,$(FORCE_GETOPT)) | |
| --- /dev/null	2004-11-09 23:14:49.000000000 -0300 | |
| +++ ./ip_vs.h	2005-02-03 19:04:00.000000000 -0300 | |
| @@ -0,0 +1,937 @@ | |
| +/* | |
| + *      IP Virtual Server | |
| + *      data structure and functionality definitions | |
| + */ | |
| + | |
| +#ifndef _IP_VS_H | |
| +#define _IP_VS_H | |
| + | |
| +#include <asm/types.h>          /* For __uXX types */ | |
| + | |
| +#define IP_VS_VERSION_CODE            0x01000C | |
| +#define NVERSION(version)                       \ | |
| +	(version >> 16) & 0xFF,                 \ | |
| +	(version >> 8) & 0xFF,                  \ | |
| +	version & 0xFF | |
| + | |
| +/* | |
| + *      Virtual Service Flags | |
| + */ | |
| +#define IP_VS_SVC_F_PERSISTENT        0x0001    /* persistent port */ | |
| +#define IP_VS_SVC_F_HASHED            0x0002    /* hashed entry */ | |
| + | |
| +/* | |
| + *      Destination Server Flags | |
| + */ | |
| +#define IP_VS_DEST_F_AVAILABLE        0x0001    /* Available tag */ | |
| + | |
| +/* | |
| + *      IPVS sync daemon states | |
| + */ | |
| +#define IP_VS_STATE_NONE    0           /* daemon is stopped */ | |
| +#define IP_VS_STATE_MASTER  1           /* started as master */ | |
| +#define IP_VS_STATE_BACKUP  2           /* started as backup */ | |
| + | |
| +/* | |
| + *      IPVS socket options | |
| + */ | |
| +#define IP_VS_BASE_CTL		(64+1024+64)		/* base */ | |
| + | |
| +#define IP_VS_SO_SET_NONE	IP_VS_BASE_CTL	        /* just peek */ | |
| +#define IP_VS_SO_SET_INSERT	(IP_VS_BASE_CTL+1) | |
| +#define IP_VS_SO_SET_ADD	(IP_VS_BASE_CTL+2) | |
| +#define IP_VS_SO_SET_EDIT	(IP_VS_BASE_CTL+3) | |
| +#define IP_VS_SO_SET_DEL	(IP_VS_BASE_CTL+4) | |
| +#define IP_VS_SO_SET_FLUSH	(IP_VS_BASE_CTL+5) | |
| +#define IP_VS_SO_SET_LIST	(IP_VS_BASE_CTL+6) | |
| +#define IP_VS_SO_SET_ADDDEST	(IP_VS_BASE_CTL+7) | |
| +#define IP_VS_SO_SET_DELDEST	(IP_VS_BASE_CTL+8) | |
| +#define IP_VS_SO_SET_EDITDEST	(IP_VS_BASE_CTL+9) | |
| +#define IP_VS_SO_SET_TIMEOUTS	(IP_VS_BASE_CTL+10) | |
| +#define IP_VS_SO_SET_STARTDAEMON (IP_VS_BASE_CTL+11) | |
| +#define IP_VS_SO_SET_STOPDAEMON (IP_VS_BASE_CTL+12) | |
| +#define IP_VS_SO_SET_RESTORE    (IP_VS_BASE_CTL+13) | |
| +#define IP_VS_SO_SET_SAVE       (IP_VS_BASE_CTL+14) | |
| +#define IP_VS_SO_SET_ZERO	(IP_VS_BASE_CTL+15) | |
| +#define IP_VS_SO_SET_MAX	IP_VS_SO_SET_ZERO | |
| + | |
| +#define IP_VS_SO_GET_VERSION	IP_VS_BASE_CTL | |
| +#define IP_VS_SO_GET_INFO	(IP_VS_BASE_CTL+1) | |
| +#define IP_VS_SO_GET_SERVICES	(IP_VS_BASE_CTL+2) | |
| +#define IP_VS_SO_GET_SERVICE	(IP_VS_BASE_CTL+3) | |
| +#define IP_VS_SO_GET_DESTS	(IP_VS_BASE_CTL+4) | |
| +#define IP_VS_SO_GET_DEST	(IP_VS_BASE_CTL+5)	/* not used now */ | |
| +#define IP_VS_SO_GET_TIMEOUTS	(IP_VS_BASE_CTL+6) | |
| +#define IP_VS_SO_GET_DAEMON	(IP_VS_BASE_CTL+7) | |
| +#define IP_VS_SO_GET_MAX	IP_VS_SO_GET_DAEMON | |
| + | |
| + | |
| +/* | |
| + *      IPVS Connection Flags | |
| + */ | |
| +#define IP_VS_CONN_F_FWD_MASK         0x0007    /* mask for the fwd methods */ | |
| +#define IP_VS_CONN_F_MASQ	      0x0000    /* masquerading */ | |
| +#define IP_VS_CONN_F_LOCALNODE	      0x0001    /* local node */ | |
| +#define IP_VS_CONN_F_TUNNEL	      0x0002    /* tunneling */ | |
| +#define IP_VS_CONN_F_DROUTE           0x0003    /* direct routing */ | |
| +#define IP_VS_CONN_F_BYPASS           0x0004    /* cache bypass */ | |
| +#define IP_VS_CONN_F_HASHED	      0x0040	/* hashed entry */ | |
| +#define IP_VS_CONN_F_NOOUTPUT         0x0080    /* no output packets */ | |
| +#define IP_VS_CONN_F_INACTIVE         0x0100    /* not established */ | |
| +#define IP_VS_CONN_F_OUT_SEQ          0x0200    /* must do output seq adjust */ | |
| +#define IP_VS_CONN_F_IN_SEQ           0x0400    /* must do input seq adjust */ | |
| +#define IP_VS_CONN_F_SEQ_MASK         0x0600    /* in/out sequence mask */ | |
| +#define IP_VS_CONN_F_NO_CPORT         0x0800    /* no client port set yet */ | |
| + | |
| +/* Move it to better place one day, for now keep it unique */ | |
| +#define NFC_IPVS_PROPERTY	0x10000 | |
| + | |
| +#define IP_VS_SCHEDNAME_MAXLEN         16 | |
| +#define IP_VS_IFNAME_MAXLEN            16 | |
| + | |
| +struct ip_vs_rule_user { | |
| +	/* global options */ | |
| +	int             tcp_timeout;    /* timeout values */ | |
| +	int             tcp_fin_timeout; | |
| +	int             udp_timeout; | |
| +	int             state;          /* sync daemon state */ | |
| +	char            mcast_ifn[IP_VS_IFNAME_MAXLEN]; | |
| +					/* multicast interface name */ | |
| +	int		syncid; | |
| + | |
| +	/* virtual service options */ | |
| +	u_int16_t	protocol; | |
| +	u_int32_t	vaddr;          /* virtual address */ | |
| +	u_int16_t	vport; | |
| +	u_int32_t       vfwmark;        /* firwall mark of virtual service*/ | |
| +	char            sched_name[IP_VS_SCHEDNAME_MAXLEN]; | |
| +	unsigned	vs_flags;       /* virtual service flags */ | |
| +	unsigned        timeout;        /* persistent timeout in ticks */ | |
| +	u_int32_t	netmask;        /* persistent netmask */ | |
| + | |
| +	/* destination specific options */ | |
| +	u_int32_t	daddr;          /* destination address */ | |
| +	u_int16_t	dport; | |
| +	unsigned        conn_flags;     /* destination flags */ | |
| +	int             weight;         /* destination weight */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	IPVS statistics object (for user space) | |
| + */ | |
| +struct ip_vs_stats_user | |
| +{ | |
| +	__u32                   conns;          /* connections scheduled */ | |
| +	__u32                   inpkts;         /* incoming packets */ | |
| +	__u32                   outpkts;        /* outgoing packets */ | |
| +	__u64                   inbytes;        /* incoming bytes */ | |
| +	__u64                   outbytes;       /* outgoing bytes */ | |
| + | |
| +	__u32			cps;		/* current connection rate */ | |
| +	__u32			inpps;		/* current in packet rate */ | |
| +	__u32			outpps;		/* current out packet rate */ | |
| +	__u32			inbps;		/* current in byte rate */ | |
| +	__u32			outbps;		/* current out byte rate */ | |
| +}; | |
| + | |
| + | |
| +/* The argument to IP_VS_SO_GET_INFO */ | |
| +struct ip_vs_getinfo { | |
| +	/* version number */ | |
| +	unsigned int	version; | |
| + | |
| +	/* size of connection hash table */ | |
| +	unsigned int	size; | |
| + | |
| +	/* number of virtual services */ | |
| +	unsigned int	num_services; | |
| +}; | |
| + | |
| +/* The argument to IP_VS_SO_GET_SERVICE */ | |
| +struct ip_vs_service_user { | |
| +	/* which service: user fills this in */ | |
| +	u_int16_t	protocol; | |
| +	u_int32_t	addr;           /* virtual address */ | |
| +	u_int16_t	port; | |
| +	u_int32_t       fwmark;         /* firwall mark of virtual service */ | |
| + | |
| +	/* service options */ | |
| +	char            sched_name[IP_VS_SCHEDNAME_MAXLEN]; | |
| +	unsigned	flags;          /* virtual service flags */ | |
| +	unsigned        timeout;        /* persistent timeout in ticks */ | |
| +	u_int32_t	netmask;        /* persistent netmask */ | |
| + | |
| +	/* number of real servers */ | |
| +	unsigned int    num_dests; | |
| + | |
| +	/* statistics */ | |
| +	struct ip_vs_stats_user stats; | |
| +}; | |
| + | |
| +struct ip_vs_dest_user { | |
| +	u_int32_t	addr;           /* destination address */ | |
| +	u_int16_t	port; | |
| +	unsigned	flags;		/* destination flags */ | |
| +	int		weight;         /* destination weight */ | |
| +	u_int32_t	activeconns;	/* active connections */ | |
| +	u_int32_t	inactconns;	/* inactive connections */ | |
| + | |
| +	/* statistics */ | |
| +	struct ip_vs_stats_user stats; | |
| +}; | |
| + | |
| +/* The argument to IP_VS_SO_GET_DESTS */ | |
| +struct ip_vs_get_dests { | |
| +	/* which service: user fills this in */ | |
| +	u_int16_t	protocol; | |
| +	u_int32_t	addr;           /* virtual address */ | |
| +	u_int16_t	port; | |
| +	u_int32_t       fwmark;         /* firwall mark of virtual service */ | |
| + | |
| +	/* number of real servers */ | |
| +	unsigned int    num_dests; | |
| + | |
| +	/* the real servers */ | |
| +	struct ip_vs_dest_user entrytable[0]; | |
| +}; | |
| + | |
| +/* The argument to IP_VS_SO_GET_SERVICES */ | |
| +struct ip_vs_get_services { | |
| +	/* number of virtual services */ | |
| +	unsigned int num_services; | |
| + | |
| +	/* service table */ | |
| +	struct ip_vs_service_user entrytable[0]; | |
| +}; | |
| + | |
| +/* The argument to IP_VS_SO_GET_TIMEOUTS */ | |
| +struct ip_vs_timeout_user { | |
| +	int             tcp_timeout; | |
| +	int             tcp_fin_timeout; | |
| +	int             udp_timeout; | |
| +}; | |
| + | |
| +/* The argument to IP_VS_SO_GET_DAEMON */ | |
| +struct ip_vs_daemon_user { | |
| +	int	state;					/* sync daemon state */ | |
| +	char	mcast_master_ifn[IP_VS_IFNAME_MAXLEN];	/* mcast master interface name */ | |
| +	char	mcast_backup_ifn[IP_VS_IFNAME_MAXLEN];	/* mcast backup interface name */ | |
| +}; | |
| + | |
| + | |
| +#ifdef __KERNEL__ | |
| + | |
| +#include <linux/config.h> | |
| +#include <linux/list.h>                 /* for struct list_head */ | |
| +#include <linux/spinlock.h>             /* for struct rwlock_t */ | |
| +#include <linux/skbuff.h>               /* for struct sk_buff */ | |
| +#include <linux/ip.h>                   /* for struct iphdr */ | |
| +#include <asm/atomic.h>                 /* for struct atomic_t */ | |
| +#include <linux/netdevice.h>		/* for struct neighbour; */ | |
| +#include <net/dst.h>			/* for struct dst_entry */ | |
| +#include <net/route.h>			/* for ip_route_output */ | |
| +#include <net/tcp.h> | |
| +#include <net/udp.h> | |
| + | |
| + | |
| +#ifdef CONFIG_IP_VS_DEBUG | |
| +extern int ip_vs_get_debug_level(void); | |
| +#define IP_VS_DBG(level, msg...)			\ | |
| +    do {						\ | |
| +	    if (level <= ip_vs_get_debug_level())	\ | |
| +		    printk(KERN_DEBUG "IPVS: " msg);	\ | |
| +    } while (0) | |
| +#define IP_VS_DBG_RL(msg...)				\ | |
| +    do {						\ | |
| +	    if (net_ratelimit())			\ | |
| +		    printk(KERN_DEBUG "IPVS: " msg);	\ | |
| +    } while (0) | |
| +#else	/* NO DEBUGGING at ALL */ | |
| +#define IP_VS_DBG(level, msg...)  do {} while (0) | |
| +#define IP_VS_DBG_RL(msg...)  do {} while (0) | |
| +#endif | |
| + | |
| +#define IP_VS_BUG() BUG() | |
| +#define IP_VS_ERR(msg...) printk(KERN_ERR "IPVS: " msg) | |
| +#define IP_VS_INFO(msg...) printk(KERN_INFO "IPVS: " msg) | |
| +#define IP_VS_WARNING(msg...) \ | |
| +	printk(KERN_WARNING "IPVS: " msg) | |
| +#define IP_VS_ERR_RL(msg...)				\ | |
| +    do {						\ | |
| +	    if (net_ratelimit())			\ | |
| +		    printk(KERN_ERR "IPVS: " msg);	\ | |
| +    } while (0) | |
| + | |
| +#ifdef CONFIG_IP_VS_DEBUG | |
| +#define EnterFunction(level)						\ | |
| +    do {								\ | |
| +	    if (level <= ip_vs_get_debug_level())			\ | |
| +		    printk(KERN_DEBUG "Enter: %s, %s line %i\n",	\ | |
| +			   __FUNCTION__, __FILE__, __LINE__);		\ | |
| +    } while (0) | |
| +#define LeaveFunction(level)                                            \ | |
| +    do {                                                                \ | |
| +	    if (level <= ip_vs_get_debug_level())                       \ | |
| +			printk(KERN_DEBUG "Leave: %s, %s line %i\n",    \ | |
| +			       __FUNCTION__, __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  __constant_htons(21) | |
| +#define FTPDATA  __constant_htons(20) | |
| + | |
| + | |
| +/* | |
| + *      IPVS sysctl variables under the /proc/sys/net/ipv4/vs/ | |
| + */ | |
| +#define NET_IPV4_VS              21 | |
| + | |
| +enum { | |
| +	NET_IPV4_VS_DEBUG_LEVEL=1, | |
| +	NET_IPV4_VS_AMEMTHRESH=2, | |
| +	NET_IPV4_VS_AMDROPRATE=3, | |
| +	NET_IPV4_VS_DROP_ENTRY=4, | |
| +	NET_IPV4_VS_DROP_PACKET=5, | |
| +	NET_IPV4_VS_SECURE_TCP=6, | |
| +	NET_IPV4_VS_TO_ES=7, | |
| +	NET_IPV4_VS_TO_SS=8, | |
| +	NET_IPV4_VS_TO_SR=9, | |
| +	NET_IPV4_VS_TO_FW=10, | |
| +	NET_IPV4_VS_TO_TW=11, | |
| +	NET_IPV4_VS_TO_CL=12, | |
| +	NET_IPV4_VS_TO_CW=13, | |
| +	NET_IPV4_VS_TO_LA=14, | |
| +	NET_IPV4_VS_TO_LI=15, | |
| +	NET_IPV4_VS_TO_SA=16, | |
| +	NET_IPV4_VS_TO_UDP=17, | |
| +	NET_IPV4_VS_TO_ICMP=18, | |
| +	NET_IPV4_VS_LBLC_EXPIRE=19, | |
| +	NET_IPV4_VS_LBLCR_EXPIRE=20, | |
| +	NET_IPV4_VS_CACHE_BYPASS=22, | |
| +	NET_IPV4_VS_EXPIRE_NODEST_CONN=23, | |
| +	NET_IPV4_VS_SYNC_THRESHOLD=24, | |
| +	NET_IPV4_VS_NAT_ICMP_SEND=25, | |
| +	NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE=26, | |
| +	NET_IPV4_VS_LAST | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *      IPVS State Values | |
| + */ | |
| +enum { | |
| +	IP_VS_S_NONE = 0, | |
| +	IP_VS_S_ESTABLISHED, | |
| +	IP_VS_S_SYN_SENT, | |
| +	IP_VS_S_SYN_RECV, | |
| +	IP_VS_S_FIN_WAIT, | |
| +	IP_VS_S_TIME_WAIT, | |
| +	IP_VS_S_CLOSE, | |
| +	IP_VS_S_CLOSE_WAIT, | |
| +	IP_VS_S_LAST_ACK, | |
| +	IP_VS_S_LISTEN, | |
| +	IP_VS_S_SYNACK, | |
| +	IP_VS_S_UDP, | |
| +	IP_VS_S_ICMP, | |
| +	IP_VS_S_LAST | |
| +}; | |
| + | |
| + | |
| +struct ip_vs_timeout_table { | |
| +	atomic_t refcnt; | |
| +	int scale; | |
| +	int timeout[IP_VS_S_LAST+1]; | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	Transport protocol header | |
| + */ | |
| +union ip_vs_tphdr { | |
| +	unsigned char *raw; | |
| +	struct udphdr *uh; | |
| +	struct tcphdr *th; | |
| +	struct icmphdr *icmph; | |
| +	__u16 *portp; | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	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 */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	IPVS statistics object | |
| + */ | |
| +struct ip_vs_stats | |
| +{ | |
| +	__u32                   conns;          /* connections scheduled */ | |
| +	__u32                   inpkts;         /* incoming packets */ | |
| +	__u32                   outpkts;        /* outgoing packets */ | |
| +	__u64                   inbytes;        /* incoming bytes */ | |
| +	__u64                   outbytes;       /* outgoing bytes */ | |
| + | |
| +	__u32			cps;		/* current connection rate */ | |
| +	__u32			inpps;		/* current in packet rate */ | |
| +	__u32			outpps;		/* current out packet rate */ | |
| +	__u32			inbps;		/* current in byte rate */ | |
| +	__u32			outbps;		/* current out byte rate */ | |
| + | |
| +	spinlock_t              lock;           /* spin lock */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	IP_VS structure allocated for each dynamically scheduled connection | |
| + */ | |
| +struct ip_vs_conn { | |
| +	struct list_head        c_list;         /* hashed list heads */ | |
| + | |
| +	/* Protocol, addresses and port numbers */ | |
| +	__u32                   caddr;          /* client address */ | |
| +	__u32                   vaddr;          /* virtual address */ | |
| +	__u32                   daddr;          /* destination address */ | |
| +	__u16                   cport; | |
| +	__u16                   vport; | |
| +	__u16                   dport; | |
| +	__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 */ | |
| +	struct ip_vs_timeout_table *timeout_table; | |
| + | |
| +	/* Flags and state transition */ | |
| +	spinlock_t              lock;           /* lock for state transition */ | |
| +	volatile __u16          flags;          /* status flags */ | |
| +	volatile __u16          state;          /* state info */ | |
| + | |
| +	/* Control members */ | |
| +	struct ip_vs_conn       *control;       /* Master control connection */ | |
| +	atomic_t                n_control;      /* Number of controlled ones */ | |
| +	struct ip_vs_dest       *dest;          /* real server */ | |
| +	atomic_t                in_pkts;        /* incoming packet counter */ | |
| + | |
| +	/* packet transmitter for different forwarding methods */ | |
| +	int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp); | |
| + | |
| +	/* Note: we can group the following members into a structure, | |
| +	   in order to save more space, and the following members are | |
| +	   only used in VS/NAT anyway */ | |
| +	struct ip_vs_app        *app;           /* bound ip_vs_app object */ | |
| +	void                    *app_data;      /* Application private data */ | |
| +	struct ip_vs_seq        in_seq;         /* incoming seq. struct */ | |
| +	struct ip_vs_seq        out_seq;        /* outgoing seq. struct */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	The information about the virtual service offered to the net | |
| + *	and the forwarding entries | |
| + */ | |
| +struct ip_vs_service { | |
| +	struct list_head	s_list;   /* for normal service table */ | |
| +	struct list_head	f_list;   /* for fwmark-based service table */ | |
| +	atomic_t		refcnt;   /* reference counter */ | |
| +	atomic_t		usecnt;   /* use counter */ | |
| + | |
| +	__u16			protocol; /* which protocol (TCP/UDP) */ | |
| +	__u32			addr;	  /* IP address for virtual service */ | |
| +	__u16			port;	  /* port number for the service */ | |
| +	__u32                   fwmark;   /* firewall mark of the service */ | |
| +	unsigned		flags;	  /* service status flags */ | |
| +	unsigned		timeout;  /* persistent timeout in ticks */ | |
| +	__u32			netmask;  /* grouping granularity */ | |
| + | |
| +	struct list_head	destinations;  /* real server d-linked list */ | |
| +	__u32			num_dests;     /* number of servers */ | |
| +	struct ip_vs_stats      stats;         /* statistics for the service */ | |
| + | |
| +	/* for scheduling */ | |
| +	struct ip_vs_scheduler	*scheduler;    /* bound scheduler object */ | |
| +	rwlock_t		sched_lock;    /* lock sched_data */ | |
| +	void			*sched_data;   /* scheduler application data */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	The real server destination forwarding entry | |
| + *	with ip address, port number, and so on. | |
| + */ | |
| +struct ip_vs_dest { | |
| +	struct list_head	n_list;   /* for the dests in the service */ | |
| +	struct list_head	d_list;   /* for table with all the dests */ | |
| + | |
| +	__u32			addr;	  /* IP address of real server */ | |
| +	__u16			port;	  /* port number of the service */ | |
| +	unsigned		flags;	  /* dest status flags */ | |
| +	atomic_t		weight;	  /* server weight */ | |
| +	atomic_t		conn_flags;	/* flags to copy to conn */ | |
| +	atomic_t		activeconns;	/* active connections */ | |
| +	atomic_t		inactconns;     /* inactive connections */ | |
| +	atomic_t		refcnt;	        /* reference counter */ | |
| +	struct ip_vs_stats      stats;          /* statistics */ | |
| + | |
| +	/* for destination cache */ | |
| +	spinlock_t		dst_lock;	/* lock dst_cache */ | |
| +	struct dst_entry	*dst_cache;	/* destination cache entry */ | |
| +	u32			dst_rtos;	/* RT_TOS(tos) for dst */ | |
| + | |
| +	/* for virtual service */ | |
| +	struct ip_vs_service    *svc;     /* service that it belongs to */ | |
| +	__u16			protocol; /* which protocol (TCP/UDP) */ | |
| +	__u32			vaddr;	  /* IP address for virtual service */ | |
| +	__u16			vport;	  /* port number for the service */ | |
| +	__u32                   vfwmark;  /* firewall mark of the service */ | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	The scheduler object | |
| + */ | |
| +struct ip_vs_scheduler { | |
| +	struct list_head        n_list;   /* d-linked list head */ | |
| +	char			*name;    /* scheduler name */ | |
| +	atomic_t                refcnt;   /* reference counter */ | |
| +	struct module		*module;  /* THIS_MODULE/NULL */ | |
| + | |
| +	/* scheduler initializing service */ | |
| +	int (*init_service)(struct ip_vs_service *svc); | |
| +	/* scheduling service finish */ | |
| +	int (*done_service)(struct ip_vs_service *svc); | |
| +	/* scheduler updating service */ | |
| +	int (*update_service)(struct ip_vs_service *svc); | |
| + | |
| +	/* selecting a server from the given service */ | |
| +	struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc, | |
| +				       struct iphdr *iph); | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *	The application module object | |
| + */ | |
| +struct ip_vs_app | |
| +{ | |
| +	struct list_head        n_list;   /* d-linked list head */ | |
| +	char                    *name;    /* name of application module */ | |
| +	unsigned                type;     /* type = proto<<16 | port | |
| +					     (host byte order)*/ | |
| +	struct module		*module;  /* THIS_MODULE/NULL */ | |
| + | |
| +	/* ip_vs_app initializer */ | |
| +	int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *); | |
| +	/* ip_vs_app finish */ | |
| +	int (*done_conn)(struct ip_vs_app *, struct ip_vs_conn *); | |
| +	/* output hook */ | |
| +	int (*pkt_out)(struct ip_vs_app *, | |
| +		       struct ip_vs_conn *, struct sk_buff *); | |
| +	/* input hook */ | |
| +	int (*pkt_in)(struct ip_vs_app *, | |
| +		      struct ip_vs_conn *, struct sk_buff *); | |
| +}; | |
| + | |
| + | |
| +/* | |
| + *      IPVS core functions | |
| + *      (from ip_vs_core.c) | |
| + */ | |
| +extern const char *ip_vs_proto_name(unsigned proto); | |
| +extern unsigned int check_for_ip_vs_out(struct sk_buff **skb_p, | |
| +					int (*okfn)(struct sk_buff *)); | |
| + | |
| + | |
| +/* | |
| + *     ip_vs_conn handling functions | |
| + *     (from ip_vs_conn.c) | |
| + */ | |
| + | |
| +/* | |
| + *     IPVS connection entry hash table | |
| + */ | |
| +#ifndef CONFIG_IP_VS_TAB_BITS | |
| +#define CONFIG_IP_VS_TAB_BITS   12 | |
| +#endif | |
| +/* make sure that IP_VS_CONN_TAB_BITS is located in [8, 20] */ | |
| +#if CONFIG_IP_VS_TAB_BITS < 8 | |
| +#define IP_VS_CONN_TAB_BITS	8 | |
| +#endif | |
| +#if CONFIG_IP_VS_TAB_BITS > 20 | |
| +#define IP_VS_CONN_TAB_BITS	20 | |
| +#endif | |
| +#if 8 <= CONFIG_IP_VS_TAB_BITS && CONFIG_IP_VS_TAB_BITS <= 20 | |
| +#define IP_VS_CONN_TAB_BITS	CONFIG_IP_VS_TAB_BITS | |
| +#endif | |
| +#define IP_VS_CONN_TAB_SIZE     (1 << IP_VS_CONN_TAB_BITS) | |
| +#define IP_VS_CONN_TAB_MASK     (IP_VS_CONN_TAB_SIZE - 1) | |
| + | |
| +#define VS_STATE_INPUT	        0 | |
| +#define VS_STATE_OUTPUT	        4 | |
| +#define VS_STATE_INPUT_ONLY	8 | |
| + | |
| +extern struct ip_vs_timeout_table vs_timeout_table; | |
| +extern struct ip_vs_timeout_table vs_timeout_table_dos; | |
| + | |
| +extern struct ip_vs_conn *ip_vs_conn_in_get | |
| +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); | |
| +extern struct ip_vs_conn *ip_vs_conn_out_get | |
| +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); | |
| + | |
| +/* put back the conn without restarting its timer */ | |
| +static inline void __ip_vs_conn_put(struct ip_vs_conn *cp) | |
| +{ | |
| +	atomic_dec(&cp->refcnt); | |
| +} | |
| +extern void ip_vs_conn_put(struct ip_vs_conn *cp); | |
| + | |
| +extern struct ip_vs_conn * | |
| +ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport, | |
| +	       __u32 daddr, __u16 dport, unsigned flags, | |
| +	       struct ip_vs_dest *dest); | |
| +extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp); | |
| + | |
| +extern const char * ip_vs_state_name(int state); | |
| +extern int ip_vs_set_state(struct ip_vs_conn *cp, int state_off, | |
| +			   struct iphdr *iph, void *tp); | |
| +extern int ip_vs_conn_listen(struct ip_vs_conn *cp); | |
| +extern int ip_vs_check_template(struct ip_vs_conn *ct); | |
| +extern void ip_vs_secure_tcp_set(int on); | |
| +extern void ip_vs_random_dropentry(void); | |
| +extern int ip_vs_conn_init(void); | |
| +extern void ip_vs_conn_cleanup(void); | |
| + | |
| +static inline void ip_vs_control_del(struct ip_vs_conn *cp) | |
| +{ | |
| +	struct ip_vs_conn *ctl_cp = cp->control; | |
| +	if (!ctl_cp) { | |
| +		IP_VS_ERR("request control DEL for uncontrolled: " | |
| +			  "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", | |
| +			  NIPQUAD(cp->caddr),ntohs(cp->cport), | |
| +			  NIPQUAD(cp->vaddr),ntohs(cp->vport)); | |
| +		return; | |
| +	} | |
| + | |
| +	IP_VS_DBG(7, "DELeting control for: " | |
| +		  "cp.dst=%d.%d.%d.%d:%d ctl_cp.dst=%d.%d.%d.%d:%d\n", | |
| +		  NIPQUAD(cp->caddr),ntohs(cp->cport), | |
| +		  NIPQUAD(ctl_cp->caddr),ntohs(ctl_cp->cport)); | |
| + | |
| +	cp->control = NULL; | |
| +	if (atomic_read(&ctl_cp->n_control) == 0) { | |
| +		IP_VS_ERR("BUG control DEL with n=0 : " | |
| +			  "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", | |
| +			  NIPQUAD(cp->caddr),ntohs(cp->cport), | |
| +			  NIPQUAD(cp->vaddr),ntohs(cp->vport)); | |
| +		return; | |
| +	} | |
| +	atomic_dec(&ctl_cp->n_control); | |
| +} | |
| + | |
| +static inline void | |
| +ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) | |
| +{ | |
| +	if (cp->control) { | |
| +		IP_VS_ERR("request control ADD for already controlled: " | |
| +			  "%d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n", | |
| +			  NIPQUAD(cp->caddr),ntohs(cp->cport), | |
| +			  NIPQUAD(cp->vaddr),ntohs(cp->vport)); | |
| +		ip_vs_control_del(cp); | |
| +	} | |
| + | |
| +	IP_VS_DBG(7, "ADDing control for: " | |
| +		  "cp.dst=%d.%d.%d.%d:%d ctl_cp.dst=%d.%d.%d.%d:%d\n", | |
| +		  NIPQUAD(cp->caddr),ntohs(cp->cport), | |
| +		  NIPQUAD(ctl_cp->caddr),ntohs(ctl_cp->cport)); | |
| + | |
| +	cp->control = ctl_cp; | |
| +	atomic_inc(&ctl_cp->n_control); | |
| +} | |
| + | |
| + | |
| +/* | |
| + *      IPVS application functions | |
| + *      (from ip_vs_app.c) | |
| + */ | |
| +#define IP_VS_APP_MAX_PORTS  8 | |
| +extern int register_ip_vs_app(struct ip_vs_app *mapp, | |
| +			      unsigned short proto, __u16 port); | |
| +extern int unregister_ip_vs_app(struct ip_vs_app *mapp); | |
| +extern struct ip_vs_app * ip_vs_bind_app(struct ip_vs_conn *cp); | |
| +extern int ip_vs_unbind_app(struct ip_vs_conn *cp); | |
| +extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb); | |
| +extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb); | |
| +extern int ip_vs_skb_replace(struct sk_buff *skb, int pri, | |
| +			     char *o_buf, int o_len, char *n_buf, int n_len); | |
| +extern int ip_vs_app_init(void); | |
| +extern void ip_vs_app_cleanup(void); | |
| + | |
| + | |
| +/* | |
| + *      Registering/unregistering scheduler functions | |
| + *      (from ip_vs_sched.c) | |
| + */ | |
| +extern int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); | |
| +extern int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); | |
| +extern int ip_vs_bind_scheduler(struct ip_vs_service *svc, | |
| +				struct ip_vs_scheduler *scheduler); | |
| +extern int ip_vs_unbind_scheduler(struct ip_vs_service *svc); | |
| +extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name); | |
| +extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler); | |
| + | |
| + | |
| +/* | |
| + *      IPVS control data and functions | |
| + *      (from ip_vs_ctl.c) | |
| + */ | |
| +extern int sysctl_ip_vs_cache_bypass; | |
| +extern int sysctl_ip_vs_expire_nodest_conn; | |
| +extern int sysctl_ip_vs_expire_quiescent_template; | |
| +extern int sysctl_ip_vs_sync_threshold; | |
| +extern int sysctl_ip_vs_nat_icmp_send; | |
| +extern struct ip_vs_stats ip_vs_stats; | |
| + | |
| +extern struct ip_vs_service *ip_vs_service_get(__u32 fwmark, | |
| +					       __u16 protocol, | |
| +					       __u32 vaddr, __u16 vport); | |
| +static inline void ip_vs_service_put(struct ip_vs_service *svc) | |
| +{ | |
| +	atomic_dec(&svc->usecnt); | |
| +} | |
| + | |
| +extern struct ip_vs_dest * | |
| +ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport); | |
| +extern void ip_vs_random_dropentry(void); | |
| +extern int ip_vs_control_init(void); | |
| +extern void ip_vs_control_cleanup(void); | |
| + | |
| + | |
| +/* | |
| + *      IPVS sync daemon data and function prototypes | |
| + *      (from ip_vs_sync.c) | |
| + */ | |
| +extern volatile int ip_vs_sync_state; | |
| +extern char ip_vs_mcast_master_ifn[IP_VS_IFNAME_MAXLEN]; | |
| +extern char ip_vs_mcast_backup_ifn[IP_VS_IFNAME_MAXLEN]; | |
| +extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid); | |
| +extern int stop_sync_thread(int state); | |
| +extern void ip_vs_sync_conn(struct ip_vs_conn *cp); | |
| + | |
| + | |
| +/* | |
| + *      IPVS rate estimator prototypes (from ip_vs_est.c) | |
| + */ | |
| +extern int ip_vs_new_estimator(struct ip_vs_stats *stats); | |
| +extern void ip_vs_kill_estimator(struct ip_vs_stats *stats); | |
| +extern void ip_vs_zero_estimator(struct ip_vs_stats *stats); | |
| + | |
| + | |
| +/* | |
| + *	This is a simple mechanism to ignore packets when | |
| + *	we are loaded. Just set ip_vs_drop_rate to 'n' and | |
| + *	we start to drop 1/rate of the packets | |
| + */ | |
| +extern int ip_vs_drop_rate; | |
| +extern int ip_vs_drop_counter; | |
| + | |
| +static __inline__ int ip_vs_todrop(void) | |
| +{ | |
| +	if (!ip_vs_drop_rate) return 0; | |
| +	if (--ip_vs_drop_counter > 0) return 0; | |
| +	ip_vs_drop_counter = ip_vs_drop_rate; | |
| +	return 1; | |
| +} | |
| + | |
| + | |
| +/* | |
| + *      ip_vs_fwd_tag returns the forwarding tag of the connection | |
| + */ | |
| +#define IP_VS_FWD_METHOD(cp)  (cp->flags & IP_VS_CONN_F_FWD_MASK) | |
| + | |
| +extern __inline__ char ip_vs_fwd_tag(struct ip_vs_conn *cp) | |
| +{ | |
| +	char fwd; | |
| + | |
| +	switch (IP_VS_FWD_METHOD(cp)) { | |
| +	case IP_VS_CONN_F_MASQ: | |
| +		fwd = 'M'; break; | |
| +	case IP_VS_CONN_F_LOCALNODE: | |
| +		fwd = 'L'; break; | |
| +	case IP_VS_CONN_F_TUNNEL: | |
| +		fwd = 'T'; break; | |
| +	case IP_VS_CONN_F_DROUTE: | |
| +		fwd = 'R'; break; | |
| +	case IP_VS_CONN_F_BYPASS: | |
| +		fwd = 'B'; break; | |
| +	default: | |
| +		fwd = '?'; break; | |
| +	} | |
| +	return fwd; | |
| +} | |
| + | |
| + | |
| +/* | |
| + *	transport layer header checking | |
| + */ | |
| +extern inline int ip_vs_header_check(struct sk_buff *skb, int proto, int ihl) | |
| +{ | |
| +	int len; | |
| + | |
| +	switch (proto) { | |
| +	case IPPROTO_TCP: | |
| +		len = ihl + sizeof(struct tcphdr); | |
| +		/* we don't care about TCP options */ | |
| +		break; | |
| +	case IPPROTO_UDP: | |
| +		len = ihl + sizeof(struct udphdr); | |
| +		break; | |
| +	default: | |
| +		len = 0; | |
| +	} | |
| + | |
| +	/* guarantee protocol header available in skb data area */ | |
| +	if (!pskb_may_pull(skb, len)) | |
| +		return -1; | |
| +	else | |
| +		return 0; | |
| +} | |
| + | |
| + | |
| +/* | |
| + *      Destination cache | |
| + */ | |
| +static inline void | |
| +__ip_vs_dst_set(struct ip_vs_dest *dest, u32 rtos, struct dst_entry *dst) | |
| +{ | |
| +	struct dst_entry *old_dst; | |
| + | |
| +	old_dst = dest->dst_cache; | |
| +	dest->dst_cache = dst; | |
| +	dest->dst_rtos = rtos; | |
| +	dst_release(old_dst); | |
| +} | |
| + | |
| +static inline void | |
| +__ip_vs_dst_reset(struct ip_vs_dest *dest) | |
| +{ | |
| +	struct dst_entry *old_dst; | |
| + | |
| +	old_dst = dest->dst_cache; | |
| +	dest->dst_cache = NULL; | |
| +	dst_release(old_dst); | |
| +} | |
| + | |
| +static inline struct dst_entry * | |
| +__ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie) | |
| +{ | |
| +	struct dst_entry *dst = dest->dst_cache; | |
| + | |
| +	if (!dst) | |
| +		return NULL; | |
| +	if ((dst->obsolete || rtos != dest->dst_rtos) && | |
| +	    dst->ops->check(dst, cookie) == NULL) { | |
| +		dest->dst_cache = 0; | |
| +		return NULL; | |
| +	} | |
| +	dst_hold(dst); | |
| +	return dst; | |
| +} | |
| + | |
| +static inline struct rtable * | |
| +__ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) | |
| +{ | |
| +	struct rtable *rt;			/* Route to the other host */ | |
| +	struct ip_vs_dest *dest = cp->dest; | |
| + | |
| +	if (dest) { | |
| +		spin_lock(&dest->dst_lock); | |
| +		if (!(rt = (struct rtable *) | |
| +		      __ip_vs_dst_check(dest, rtos, 0))) { | |
| +			if (ip_route_output(&rt, dest->addr, 0, rtos, 0)) { | |
| +				spin_unlock(&dest->dst_lock); | |
| +				IP_VS_DBG_RL("ip_route_output error, " | |
| +					     "dest: %u.%u.%u.%u\n", | |
| +					     NIPQUAD(dest->addr)); | |
| +				return NULL; | |
| +			} | |
| +			__ip_vs_dst_set(dest, rtos, dst_clone(&rt->u.dst)); | |
| +			IP_VS_DBG(10, "new dst %u.%u.%u.%u, refcnt=%d, rtos=%X\n", | |
| +				  NIPQUAD(dest->addr), | |
| +				  atomic_read(&rt->u.dst.__refcnt), rtos); | |
| +		} | |
| +		spin_unlock(&dest->dst_lock); | |
| +	} else { | |
| +		if (ip_route_output(&rt, cp->daddr, 0, rtos, 0)) { | |
| +			IP_VS_DBG_RL("ip_route_output error, dest: " | |
| +				     "%u.%u.%u.%u\n", NIPQUAD(cp->daddr)); | |
| +			return NULL; | |
| +		} | |
| +	} | |
| + | |
| +	return rt; | |
| +} | |
| + | |
| +static inline u16 ip_vs_check_diff(u32 old, u32 new, u16 oldsum) | |
| +{ | |
| +	u32 diff[2] = { old, new }; | |
| + | |
| +	return csum_fold(csum_partial((char *) diff, sizeof(diff), | |
| +				      oldsum ^ 0xFFFF)); | |
| +} | |
| + | |
| +static inline void ip_vs_fast_check_update(union ip_vs_tphdr *h, | |
| +	u32 oldip, u32 newip, u16 oldport, u16 newport, u8 protocol) | |
| +{ | |
| +	u16 *checkp; | |
| + | |
| +	if (protocol == IPPROTO_TCP) | |
| +		checkp = &h->th->check; | |
| +	else | |
| +		checkp = &h->uh->check; | |
| +	*checkp = ip_vs_check_diff(~oldip, newip, | |
| +				   ip_vs_check_diff(oldport ^ 0xFFFF, | |
| +						    newport, *checkp)); | |
| +	if (!*checkp && protocol == IPPROTO_UDP) | |
| +		*checkp = 0xFFFF; | |
| +} | |
| + | |
| +static inline int | |
| +ip_vs_skb_cow(struct sk_buff *skb, unsigned int headroom, | |
| +	      struct iphdr **iph_p, unsigned char **t_p) | |
| +{ | |
| +	int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb); | |
| + | |
| +	if (delta < 0) | |
| +		delta = 0; | |
| + | |
| +	if (delta || skb_cloned(skb)) { | |
| +		if (pskb_expand_head(skb, (delta+15)&~15, 0, GFP_ATOMIC)) | |
| +			return -ENOMEM; | |
| + | |
| +		/* skb data changed, update pointers */ | |
| +		*iph_p = skb->nh.iph; | |
| +		*t_p = (char*) (*iph_p) + (*iph_p)->ihl * 4; | |
| +	} | |
| +	return 0; | |
| +} | |
| + | |
| +#endif /* __KERNEL__ */ | |
| + | |
| +#endif	/* _IP_VS_H */
 | |
| 
 |