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

📄 ip_conntrack_proto_sctp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Connection tracking protocol helper module for SCTP. *  * SCTP is defined in RFC 2960. References to various sections in this code  * are to this RFC. *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. *//* * Added support for proc manipulation of timeouts. */#include <linux/types.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/netfilter.h>#include <linux/module.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/sctp.h>#include <linux/string.h>#include <linux/seq_file.h>#include <linux/netfilter_ipv4/ip_conntrack.h>#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>#if 0#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)#else#define DEBUGP(format, args...)#endif/* Protects conntrack->proto.sctp */static DEFINE_RWLOCK(sctp_lock);/* FIXME: Examine ipfilter's timeouts and conntrack transitions more   closely.  They're more complex. --RR    And so for me for SCTP :D -Kiran */static const char *sctp_conntrack_names[] = {	"NONE",	"CLOSED",	"COOKIE_WAIT",	"COOKIE_ECHOED",	"ESTABLISHED",	"SHUTDOWN_SENT",	"SHUTDOWN_RECD",	"SHUTDOWN_ACK_SENT",};#define SECS  * HZ#define MINS  * 60 SECS#define HOURS * 60 MINS#define DAYS  * 24 HOURSstatic unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;static unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;static unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;static unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;static unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;static unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;static unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;static const unsigned long * sctp_timeouts[]= { NULL,                                  /* SCTP_CONNTRACK_NONE  */    &ip_ct_sctp_timeout_closed,	           /* SCTP_CONNTRACK_CLOSED */    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */ };#define sNO SCTP_CONNTRACK_NONE#define	sCL SCTP_CONNTRACK_CLOSED#define	sCW SCTP_CONNTRACK_COOKIE_WAIT#define	sCE SCTP_CONNTRACK_COOKIE_ECHOED#define	sES SCTP_CONNTRACK_ESTABLISHED#define	sSS SCTP_CONNTRACK_SHUTDOWN_SENT#define	sSR SCTP_CONNTRACK_SHUTDOWN_RECD#define	sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT#define	sIV SCTP_CONNTRACK_MAX/* 	These are the descriptions of the states:NOTE: These state names are tantalizingly similar to the states of an SCTP endpoint. But the interpretation of the states is a little different,considering that these are the states of the connection and not of an end point. Please note the subtleties. -KiranNONE              - Nothing so far.COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also                     an INIT_ACK chunk in the reply direction.COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite                    to that of the SHUTDOWN chunk.CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of                     the SHUTDOWN chunk. Connection is closed.*//* TODO - I have assumed that the first INIT is in the original direction.  This messes things when an INIT comes in the reply direction in CLOSED state. - Check the error type in the reply dir before transitioning from cookie echoed to closed. - Sec 5.2.4 of RFC 2960 - Multi Homing support.*//* SCTP conntrack state transitions */static const enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {	{/*	ORIGINAL	*//*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA *//* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*//* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO *//* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir *//* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}	},	{/*	REPLY	*//*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA *//* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO *//* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir *//* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}	}};static int sctp_pkt_to_tuple(const struct sk_buff *skb,			     unsigned int dataoff,			     struct ip_conntrack_tuple *tuple){	sctp_sctphdr_t _hdr, *hp;	DEBUGP(__FUNCTION__);	DEBUGP("\n");	/* Actually only need first 8 bytes. */	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);	if (hp == NULL)		return 0;	tuple->src.u.sctp.port = hp->source;	tuple->dst.u.sctp.port = hp->dest;	return 1;}static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,			     const struct ip_conntrack_tuple *orig){	DEBUGP(__FUNCTION__);	DEBUGP("\n");	tuple->src.u.sctp.port = orig->dst.u.sctp.port;	tuple->dst.u.sctp.port = orig->src.u.sctp.port;	return 1;}/* Print out the per-protocol part of the tuple. */static int sctp_print_tuple(struct seq_file *s,			    const struct ip_conntrack_tuple *tuple){	DEBUGP(__FUNCTION__);	DEBUGP("\n");	return seq_printf(s, "sport=%hu dport=%hu ",			  ntohs(tuple->src.u.sctp.port),			  ntohs(tuple->dst.u.sctp.port));}/* Print out the private part of the conntrack. */static int sctp_print_conntrack(struct seq_file *s,				const struct ip_conntrack *conntrack){	enum sctp_conntrack state;	DEBUGP(__FUNCTION__);	DEBUGP("\n");	read_lock_bh(&sctp_lock);	state = conntrack->proto.sctp.state;	read_unlock_bh(&sctp_lock);	return seq_printf(s, "%s ", sctp_conntrack_names[state]);}#define for_each_sctp_chunk(skb, sch, _sch, offset, count)		\for (offset = skb->nh.iph->ihl * 4 + sizeof(sctp_sctphdr_t), count = 0;	\	offset < skb->len &&						\	(sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch));	\	offset += (htons(sch->length) + 3) & ~3, count++)/* Some validity checks to make sure the chunks are fine */static int do_basic_checks(struct ip_conntrack *conntrack,			   const struct sk_buff *skb,			   char *map){	u_int32_t offset, count;	sctp_chunkhdr_t _sch, *sch;	int flag;	DEBUGP(__FUNCTION__);	DEBUGP("\n");	flag = 0;	for_each_sctp_chunk (skb, sch, _sch, offset, count) {		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);		if (sch->type == SCTP_CID_INIT 			|| sch->type == SCTP_CID_INIT_ACK			|| sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {			flag = 1;		}		/* Cookie Ack/Echo chunks not the first OR 		   Init / Init Ack / Shutdown compl chunks not the only chunks */		if ((sch->type == SCTP_CID_COOKIE_ACK 			|| sch->type == SCTP_CID_COOKIE_ECHO			|| flag)		     && count !=0 ) {			DEBUGP("Basic checks failed\n");			return 1;		}		if (map) {			set_bit(sch->type, (void *)map);		}	}	DEBUGP("Basic checks passed\n");	return 0;}static int new_state(enum ip_conntrack_dir dir,		     enum sctp_conntrack cur_state,		     int chunk_type){	int i;	DEBUGP(__FUNCTION__);	DEBUGP("\n");	DEBUGP("Chunk type: %d\n", chunk_type);	switch (chunk_type) {		case SCTP_CID_INIT: 			DEBUGP("SCTP_CID_INIT\n");			i = 0; break;		case SCTP_CID_INIT_ACK: 			DEBUGP("SCTP_CID_INIT_ACK\n");			i = 1; break;		case SCTP_CID_ABORT: 			DEBUGP("SCTP_CID_ABORT\n");			i = 2; break;		case SCTP_CID_SHUTDOWN: 			DEBUGP("SCTP_CID_SHUTDOWN\n");			i = 3; break;		case SCTP_CID_SHUTDOWN_ACK: 			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");			i = 4; break;		case SCTP_CID_ERROR: 			DEBUGP("SCTP_CID_ERROR\n");			i = 5; break;		case SCTP_CID_COOKIE_ECHO: 			DEBUGP("SCTP_CID_COOKIE_ECHO\n");			i = 6; break;		case SCTP_CID_COOKIE_ACK: 			DEBUGP("SCTP_CID_COOKIE_ACK\n");			i = 7; break;		case SCTP_CID_SHUTDOWN_COMPLETE: 			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");			i = 8; break;		default:			/* Other chunks like DATA, SACK, HEARTBEAT and			its ACK do not cause a change in state */			DEBUGP("Unknown chunk type, Will stay in %s\n", 						sctp_conntrack_names[cur_state]);			return cur_state;	}	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 			dir, sctp_conntrack_names[cur_state], chunk_type,			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);	return sctp_conntracks[dir][i][cur_state];}/* Returns verdict for packet, or -1 for invalid. */static int sctp_packet(struct ip_conntrack *conntrack,		       const struct sk_buff *skb,		       enum ip_conntrack_info ctinfo){	enum sctp_conntrack newconntrack, oldsctpstate;	struct iphdr *iph = skb->nh.iph;	sctp_sctphdr_t _sctph, *sh;	sctp_chunkhdr_t _sch, *sch;	u_int32_t offset, count;	char map[256 / sizeof (char)] = {0};	DEBUGP(__FUNCTION__);	DEBUGP("\n");	sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);	if (sh == NULL)		return -1;	if (do_basic_checks(conntrack, skb, map) != 0)

⌨️ 快捷键说明

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