⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_vs_proto_tcp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
#define sCW IP_VS_TCP_S_CLOSE_WAIT#define sLA IP_VS_TCP_S_LAST_ACK#define sLI IP_VS_TCP_S_LISTEN#define sSA IP_VS_TCP_S_SYNACKstruct tcp_states_t {	int next_state[IP_VS_TCP_S_LAST];};static const char * tcp_state_name(int state){	if (state >= IP_VS_TCP_S_LAST)		return "ERR!";	return tcp_state_name_table[state] ? tcp_state_name_table[state] : "?";}static struct tcp_states_t tcp_states [] = {/*	INPUT *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }},/*	OUTPUT *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI, sSR }},/*fin*/ {{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES, sES }},/*rst*/ {{sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL, sCL }},/*	INPUT-ONLY *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},};static struct tcp_states_t tcp_states_dos [] = {/*	INPUT *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSA }},/*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sSA }},/*ack*/ {{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI, sSA }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},/*	OUTPUT *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSS, sES, sSS, sSA, sSS, sSS, sSS, sSS, sSS, sLI, sSA }},/*fin*/ {{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES, sES }},/*rst*/ {{sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL, sCL }},/*	INPUT-ONLY *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA	*//*syn*/ {{sSA, sES, sES, sSR, sSA, sSA, sSA, sSA, sSA, sSA, sSA }},/*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},};static struct tcp_states_t *tcp_state_table = tcp_states;static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags){	int on = (flags & 1);		/* secure_tcp */	/*	** FIXME: change secure_tcp to independent sysctl var	** or make it per-service or per-app because it is valid	** for most if not for all of the applications. Something	** like "capabilities" (flags) for each object.	*/	tcp_state_table = (on? tcp_states_dos : tcp_states);}static inttcp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to){	return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_TCP_S_LAST,				       tcp_state_name_table, sname, to);}static inline int tcp_state_idx(struct tcphdr *th){	if (th->rst)		return 3;	if (th->syn)		return 0;	if (th->fin)		return 1;	if (th->ack)		return 2;	return -1;}static inline voidset_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,	      int direction, struct tcphdr *th){	int state_idx;	int new_state = IP_VS_TCP_S_CLOSE;	int state_off = tcp_state_off[direction];	/*	 *    Update state offset to INPUT_ONLY if necessary	 *    or delete NO_OUTPUT flag if output packet detected	 */	if (cp->flags & IP_VS_CONN_F_NOOUTPUT) {		if (state_off == TCP_DIR_OUTPUT)			cp->flags &= ~IP_VS_CONN_F_NOOUTPUT;		else			state_off = TCP_DIR_INPUT_ONLY;	}	if ((state_idx = tcp_state_idx(th)) < 0) {		IP_VS_DBG(8, "tcp_state_idx=%d!!!\n", state_idx);		goto tcp_state_out;	}	new_state = tcp_state_table[state_off+state_idx].next_state[cp->state];  tcp_state_out:	if (new_state != cp->state) {		struct ip_vs_dest *dest = cp->dest;		IP_VS_DBG(8, "%s %s [%c%c%c%c] %u.%u.%u.%u:%d->"			  "%u.%u.%u.%u:%d state: %s->%s cnt:%d\n",			  pp->name,			  (state_off==TCP_DIR_OUTPUT)?"output ":"input ",			  th->syn? 'S' : '.',			  th->fin? 'F' : '.',			  th->ack? 'A' : '.',			  th->rst? 'R' : '.',			  NIPQUAD(cp->daddr), ntohs(cp->dport),			  NIPQUAD(cp->caddr), ntohs(cp->cport),			  tcp_state_name(cp->state),			  tcp_state_name(new_state),			  atomic_read(&cp->refcnt));		if (dest) {			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&			    (new_state != IP_VS_TCP_S_ESTABLISHED)) {				atomic_dec(&dest->activeconns);				atomic_inc(&dest->inactconns);				cp->flags |= IP_VS_CONN_F_INACTIVE;			} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&				   (new_state == IP_VS_TCP_S_ESTABLISHED)) {				atomic_inc(&dest->activeconns);				atomic_dec(&dest->inactconns);				cp->flags &= ~IP_VS_CONN_F_INACTIVE;			}		}	}	cp->timeout = pp->timeout_table[cp->state = new_state];}/* *	Handle state transitions */static inttcp_state_transition(struct ip_vs_conn *cp, int direction,		     const struct sk_buff *skb,		     struct ip_vs_protocol *pp){	struct tcphdr _tcph, *th;	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,				sizeof(_tcph), &_tcph);	if (th == NULL)		return 0;	spin_lock(&cp->lock);	set_tcp_state(pp, cp, direction, th);	spin_unlock(&cp->lock);	return 1;}/* *	Hash table for TCP application incarnations */#define	TCP_APP_TAB_BITS	4#define	TCP_APP_TAB_SIZE	(1 << TCP_APP_TAB_BITS)#define	TCP_APP_TAB_MASK	(TCP_APP_TAB_SIZE - 1)static struct list_head tcp_apps[TCP_APP_TAB_SIZE];static DEFINE_SPINLOCK(tcp_app_lock);static inline __u16 tcp_app_hashkey(__u16 port){	return ((port >> TCP_APP_TAB_BITS) ^ port) & TCP_APP_TAB_MASK;}static int tcp_register_app(struct ip_vs_app *inc){	struct ip_vs_app *i;	__u16 hash, port = inc->port;	int ret = 0;	hash = tcp_app_hashkey(port);	spin_lock_bh(&tcp_app_lock);	list_for_each_entry(i, &tcp_apps[hash], p_list) {		if (i->port == port) {			ret = -EEXIST;			goto out;		}	}	list_add(&inc->p_list, &tcp_apps[hash]);	atomic_inc(&ip_vs_protocol_tcp.appcnt);  out:	spin_unlock_bh(&tcp_app_lock);	return ret;}static voidtcp_unregister_app(struct ip_vs_app *inc){	spin_lock_bh(&tcp_app_lock);	atomic_dec(&ip_vs_protocol_tcp.appcnt);	list_del(&inc->p_list);	spin_unlock_bh(&tcp_app_lock);}static inttcp_app_conn_bind(struct ip_vs_conn *cp){	int hash;	struct ip_vs_app *inc;	int result = 0;	/* Default binding: bind app only for NAT */	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)		return 0;	/* Lookup application incarnations and bind the right one */	hash = tcp_app_hashkey(cp->vport);	spin_lock(&tcp_app_lock);	list_for_each_entry(inc, &tcp_apps[hash], p_list) {		if (inc->port == cp->vport) {			if (unlikely(!ip_vs_app_inc_get(inc)))				break;			spin_unlock(&tcp_app_lock);			IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"				  "%u.%u.%u.%u:%u to app %s on port %u\n",				  __FUNCTION__,				  NIPQUAD(cp->caddr), ntohs(cp->cport),				  NIPQUAD(cp->vaddr), ntohs(cp->vport),				  inc->name, ntohs(inc->port));			cp->app = inc;			if (inc->init_conn)				result = inc->init_conn(inc, cp);			goto out;		}	}	spin_unlock(&tcp_app_lock);  out:	return result;}/* *	Set LISTEN timeout. (ip_vs_conn_put will setup timer) */void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp){	spin_lock(&cp->lock);	cp->state = IP_VS_TCP_S_LISTEN;	cp->timeout = ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_LISTEN];	spin_unlock(&cp->lock);}static void ip_vs_tcp_init(struct ip_vs_protocol *pp){	IP_VS_INIT_HASH_TABLE(tcp_apps);	pp->timeout_table = tcp_timeouts;}static void ip_vs_tcp_exit(struct ip_vs_protocol *pp){}struct ip_vs_protocol ip_vs_protocol_tcp = {	.name =			"TCP",	.protocol =		IPPROTO_TCP,	.dont_defrag =		0,	.appcnt =		ATOMIC_INIT(0),	.init =			ip_vs_tcp_init,	.exit =			ip_vs_tcp_exit,	.register_app =		tcp_register_app,	.unregister_app =	tcp_unregister_app,	.conn_schedule =	tcp_conn_schedule,	.conn_in_get =		tcp_conn_in_get,	.conn_out_get =		tcp_conn_out_get,	.snat_handler =		tcp_snat_handler,	.dnat_handler =		tcp_dnat_handler,	.csum_check =		tcp_csum_check,	.state_name =		tcp_state_name,	.state_transition =	tcp_state_transition,	.app_conn_bind =	tcp_app_conn_bind,	.debug_packet =		ip_vs_tcpudp_debug_packet,	.timeout_change =	tcp_timeout_change,	.set_state_timeout =	tcp_set_state_timeout,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -