Browse Source

- Cleaned up the ip rules/DDoS section of the code. (the allow,deny and deny,allow cases were switched)
- Updated the information about ip rules and DDoS protection in packet_athena.conf and commented out the line "allow: all" so connections are rejected when a DDoS is detected.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9647 54d463be-8e91-2dee-dedb-b68131a5f0ec

FlavioJS 18 years ago
parent
commit
a7ee9a9961
5 changed files with 232 additions and 191 deletions
  1. 2 0
      Changelog-Trunk.txt
  2. 4 0
      conf-tmpl/Changelog.txt
  3. 21 14
      conf-tmpl/packet_athena.conf
  4. 203 175
      src/common/socket.c
  5. 2 2
      src/common/socket.h

+ 2 - 0
Changelog-Trunk.txt

@@ -4,6 +4,8 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2007/01/12
 2007/01/12
+	* Cleaned up the ip rules/DDoS section of the code. (the allow,deny and 
+	  deny,allow cases were switched)
 	* Fixed autotrading characters not being able to reconnect. Seams like I 
 	* Fixed autotrading characters not being able to reconnect. Seams like I 
 	  misunderstood how id_db and pc_db are used. [FlavioJS]
 	  misunderstood how id_db and pc_db are used. [FlavioJS]
 2007/01/11
 2007/01/11

+ 4 - 0
conf-tmpl/Changelog.txt

@@ -1,5 +1,9 @@
 Date	Added
 Date	Added
 
 
+2007/01/12
+	* Updated the information about ip rules and DDoS protection in 
+	  packet_athena.conf and commented out the line "allow: all" so 
+	  connections are rejected when a DDoS is detected. [FlavioJS]
 2007/01/08
 2007/01/08
 	* Added the console plugin to plugin_athena.conf commented out. [FlavioJS]
 	* Added the console plugin to plugin_athena.conf commented out. [FlavioJS]
 2007/01/05
 2007/01/05

+ 21 - 14
conf-tmpl/packet_athena.conf

@@ -17,40 +17,47 @@ mode_neg: yes
 
 
 //----- IP Rules Settings -----
 //----- IP Rules Settings -----
 
 
-// Do we check IP's before allowing incoming connections?
+// If IP's are checked when connecting.
+// This also enables DDoS protection.
 enable_ip_rules: yes
 enable_ip_rules: yes
 
 
-// Decide the order of access restriction (Same as apache?)
-// deny,allow Is the standard
+// Order of the checks
+//   deny,allow     : Checks deny rules, then allow rules. Allows if no rules match.
+//   allow,deny     : Checks allow rules, then deny rules. Allows if no rules match.
+//   mutual-failure : Allows only if an allow rule matches and no deny rules match.
+// (default is deny,allow)
 
 
 order: deny,allow
 order: deny,allow
 // order: allow,deny
 // order: allow,deny
 // order: mutual-failture
 // order: mutual-failture
 
 
-// The IP list which it uses to access controls
-//   allow    : Allows access regardless of permissions
-//   deny     : Completely disallow
-//   Žw’è–³‚µ : If the permission check encounters mutual-failure(whatever that means) it will disallow access
+// IP rules
+//   allow : Accepts connections from the ip range (even if flagged as DDoS)
+//   deny  : Rejects connections from the ip range
+// The rules are processed in order, the first matching rule of each list (allow and deny) is used
 
 
 // allow: 127.0.0.1
 // allow: 127.0.0.1
 // allow: 192.168.0.0/16
 // allow: 192.168.0.0/16
 // allow: 10.0.0.0/255.0.0.0
 // allow: 10.0.0.0/255.0.0.0
-allow: all
+// allow: all
 
 
 // deny: 127.0.0.1
 // deny: 127.0.0.1
 
 
 
 
-//---- Ddos Protection Settings ----
-//     If there is a connection request within ddos_interval msec for ddos_count number of times, it will assume it is a ddos attack
+//---- DDoS Protection Settings ----
+// If ddos_count connection request are made within ddos_interval msec, it assumes it's a DDoS attack
 
 
-// Consecutive intervals(msec)
+// Consecutive attempts interval (msec)
+// (default is 3000 msecs, 3 seconds)
 ddos_interval: 3000
 ddos_interval: 3000
 
 
-// Connection frequency
+// Consecutive attempts trigger
+// (default is 10 attemps)
 ddos_count: 5
 ddos_count: 5
 
 
-// The time interval after which the threat of ddos is assumed to be gone
-// After this amount of time, the ddos restrictions are lifted.
+// The time interval after which the threat of DDoS is assumed to be gone. (msec)
+// After this amount of time, the DDoS restrictions are lifted.
+// (default is 600000 msecs, 10 minutes)
 ddos_autoreset: 600000
 ddos_autoreset: 600000
 
 
 
 

+ 203 - 175
src/common/socket.c

@@ -73,25 +73,6 @@ int ip_rules = 1;
 static int mode_neg=1;
 static int mode_neg=1;
 static size_t frame_size=TCP_FRAME_LEN;
 static size_t frame_size=TCP_FRAME_LEN;
 
 
-#ifndef MINICORE
-enum {
-	ACO_DENY_ALLOW=0,
-	ACO_ALLOW_DENY,
-	ACO_MUTUAL_FAILTURE,
-};
-
-static struct _access_control *access_allow;
-static struct _access_control *access_deny;
-static int access_order=ACO_DENY_ALLOW;
-static int access_allownum=0;
-static int access_denynum=0;
-static int access_debug=0;
-static int ddos_count     = 10;
-static int ddos_interval  = 3000;
-static int ddos_autoreset = 600*1000;
-#endif
-
-
 // values derived from freya
 // values derived from freya
 // a player that send more than 2k is probably a hacker without be parsed
 // a player that send more than 2k is probably a hacker without be parsed
 // biggest known packet: S 0153 <len>.w <emblem data>.?B -> 24x24 256 color .bmp (0153 + len.w + 1618/1654/1756 bytes)
 // biggest known packet: S 0153 <len>.w <emblem data>.?B -> 24x24 256 color .bmp (0153 + len.w + 1618/1654/1756 bytes)
@@ -283,17 +264,18 @@ static int connect_client(int listen_fd)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if(fd_max<=fd) fd_max=fd+1;
-
 	setsocketopts(fd);
 	setsocketopts(fd);
 	set_nonblocking(fd, 1);
 	set_nonblocking(fd, 1);
 
 
-	if (ip_rules && !connect_check(*(unsigned int*)(&client_address.sin_addr))) {
+	if( ip_rules && !connect_check(*(uint32*)(&client_address.sin_addr)) ){
 		do_close(fd);
 		do_close(fd);
 		return -1;
 		return -1;
 	} else
 	} else
 		FD_SET(fd,&readfds);
 		FD_SET(fd,&readfds);
 
 
+	if( fd_max <= fd )
+		fd_max = fd + 1;
+
 	CREATE(session[fd], struct socket_data, 1);
 	CREATE(session[fd], struct socket_data, 1);
 	CREATE(session[fd]->rdata, unsigned char, rfifo_size);
 	CREATE(session[fd]->rdata, unsigned char, rfifo_size);
 	CREATE(session[fd]->wdata, unsigned char, wfifo_size);
 	CREATE(session[fd]->wdata, unsigned char, wfifo_size);
@@ -768,45 +750,72 @@ int do_parsepacket(void)
 	return 0;
 	return 0;
 }
 }
 
 
-/* DDoS 攻撃対策 */
+//////////////////////////////
 #ifndef MINICORE
 #ifndef MINICORE
-struct _access_control {
-	unsigned int ip;
-	unsigned int mask;
+//////////////////////////////
+// IP rules and DDoS protection
+
+typedef struct _connect_history {
+	struct _connect_history* next;
+	uint32 ip;
+	uint32 tick;
+	int count;
+	unsigned ddos : 1;
+} ConnectHistory;
+
+typedef struct _access_control {
+	uint32 ip;
+	uint32 mask;
+} AccessControl;
+
+enum _aco {
+	ACO_DENY_ALLOW,
+	ACO_ALLOW_DENY,
+	ACO_MUTUAL_FAILURE
 };
 };
 
 
-struct _connect_history {
-	struct _connect_history *next;
-	struct _connect_history *prev;
-	int    status;
-	int    count;
-	unsigned int ip;
-	unsigned int tick;
-};
-static struct _connect_history *connect_history[0x10000];
-static int connect_check_(unsigned int ip);
+static AccessControl* access_allow = NULL;
+static AccessControl* access_deny = NULL;
+static int access_order    = ACO_DENY_ALLOW;
+static int access_allownum = 0;
+static int access_denynum  = 0;
+static int access_debug    = 0;
+static int ddos_count     = 10;
+static int ddos_interval  = 3*1000;
+static int ddos_autoreset = 10*60*1000;
+/// Connection history, an array of linked lists.
+/// The array's index for any ip is ip&0xFFFF
+static ConnectHistory* connect_history[0x10000];
+
+static int connect_check_(uint32 ip);
 
 
-// 接続できるかどうかの確認
-//   false : 接続OK
-//   true  : 接続NG
-static int connect_check(unsigned int ip) {
+/// Verifies if the IP can connect. (with debug info)
+/// @see connect_check_()
+static int connect_check(uint32 ip)
+{
 	int result = connect_check_(ip);
 	int result = connect_check_(ip);
-	if(access_debug) {
+	if( access_debug ){
 		ShowMessage("connect_check: Connection from %d.%d.%d.%d %s\n",
 		ShowMessage("connect_check: Connection from %d.%d.%d.%d %s\n",
 			CONVIP(ip),result ? "allowed." : "denied!");
 			CONVIP(ip),result ? "allowed." : "denied!");
 	}
 	}
 	return result;
 	return result;
 }
 }
 
 
-static int connect_check_(unsigned int ip) {
-	struct _connect_history *hist     = connect_history[ip & 0xFFFF];
-	struct _connect_history *hist_new;
-	int    i,is_allowip = 0,is_denyip = 0,connect_ok = 0;
-
-	// allow , deny リストに入っているか確認
-	for(i = 0;i < access_allownum; i++) {
-		if((ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask)) {
-			if(access_debug) {
+/// Verifies if the IP can connect.
+///  0      : Connection Rejected
+///  1 or 2 : Connection Accepted
+static int connect_check_(uint32 ip)
+{
+	ConnectHistory* hist = connect_history[ip&0xFFFF];
+	int i;
+	int is_allowip = 0;
+	int is_denyip = 0;
+	int connect_ok = 0;
+
+	// Search the allow list
+	for( i=0; i < access_allownum; ++i ){
+		if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){
+			if( access_debug ){
 				ShowMessage("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
 				ShowMessage("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
 					CONVIP(ip),
 					CONVIP(ip),
 					CONVIP(access_allow[i].ip),
 					CONVIP(access_allow[i].ip),
@@ -816,9 +825,10 @@ static int connect_check_(unsigned int ip) {
 			break;
 			break;
 		}
 		}
 	}
 	}
-	for(i = 0;i < access_denynum; i++) {
-		if((ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask)) {
-			if(access_debug) {
+	// Search the deny list
+	for( i=0; i < access_denynum; ++i ){
+		if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){
+			if( access_debug ){
 				ShowMessage("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
 				ShowMessage("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
 					CONVIP(ip),
 					CONVIP(ip),
 					CONVIP(access_deny[i].ip),
 					CONVIP(access_deny[i].ip),
@@ -828,61 +838,55 @@ static int connect_check_(unsigned int ip) {
 			break;
 			break;
 		}
 		}
 	}
 	}
-	// コネクト出来るかどうか確認
-	// connect_ok
-	//   0 : 無条件に拒否
-	//   1 : 田代砲チェックの結果次第
-	//   2 : 無条件に許可
+	// Decide connection status
+	//  0 : Reject
+	//  1 : Accept
+	//  2 : Unconditional Accept (accepts even if flagged as DDoS)
 	switch(access_order) {
 	switch(access_order) {
 	case ACO_DENY_ALLOW:
 	case ACO_DENY_ALLOW:
 	default:
 	default:
-		if(is_allowip) {
-			connect_ok = 2;
-		} else if(is_denyip) {
-			connect_ok = 0;
-		} else {
-			connect_ok = 1;
-		}
+		if( is_denyip )
+			connect_ok = 0; // Reject
+		else if( is_allowip )
+			connect_ok = 2; // Unconditional Accept
+		else
+			connect_ok = 1; // Accept
 		break;
 		break;
 	case ACO_ALLOW_DENY:
 	case ACO_ALLOW_DENY:
-		if(is_denyip) {
-			connect_ok = 0;
-		} else if(is_allowip) {
-			connect_ok = 2;
-		} else {
-			connect_ok = 1;
-		}
+		if( is_allowip )
+			connect_ok = 2; // Unconditional Accept
+		else if( is_denyip )
+			connect_ok = 0; // Reject
+		else
+			connect_ok = 1; // Accept
 		break;
 		break;
-	case ACO_MUTUAL_FAILTURE:
-		if(is_allowip) {
-			connect_ok = 2;
-		} else {
-			connect_ok = 0;
-		}
+	case ACO_MUTUAL_FAILURE:
+		if( is_allowip && !is_denyip )
+			connect_ok = 2; // Unconditional Accept
+		else
+			connect_ok = 0; // Reject
 		break;
 		break;
 	}
 	}
 
 
-	// 接続履歴を調べる
-	while(hist) {
-		if(ip == hist->ip) {
-			// 同じIP発見
-			if(hist->status) {
-				// ban フラグが立ってる
+	// Inspect connection history
+	while( hist ) {
+		if( ip == hist->ip )
+		{// IP found
+			if( hist->ddos )
+			{// flagged as DDoS
 				return (connect_ok == 2 ? 1 : 0);
 				return (connect_ok == 2 ? 1 : 0);
-			} else if(DIFF_TICK(gettick(),hist->tick) < ddos_interval) {
-				// ddos_interval秒以内にリクエスト有り
+			} else if( DIFF_TICK(gettick(),hist->tick) < ddos_interval )
+			{// connection within ddos_interval
 				hist->tick = gettick();
 				hist->tick = gettick();
-				if(hist->count++ >= ddos_count) {
-					// ddos 攻撃を検出
-					hist->status = 1;
-					ShowWarning("connect_check: DDOS Attack detected from %d.%d.%d.%d!\n",
-						CONVIP(ip));
+				if( hist->count++ >= ddos_count )
+				{// DDoS attack detected
+					hist->ddos = 1;
+					ShowWarning("connect_check: DDoS Attack detected from %d.%d.%d.%d!\n", CONVIP(ip));
 					return (connect_ok == 2 ? 1 : 0);
 					return (connect_ok == 2 ? 1 : 0);
-				} else {
-					return connect_ok;
 				}
 				}
-			} else {
-				// ddos_interval秒以内にリクエスト無いのでタイマークリア
+				return connect_ok;
+			} else
+			{// not within ddos_interval, clear data
 				hist->tick  = gettick();
 				hist->tick  = gettick();
 				hist->count = 0;
 				hist->count = 0;
 				return connect_ok;
 				return connect_ok;
@@ -890,80 +894,92 @@ static int connect_check_(unsigned int ip) {
 		}
 		}
 		hist = hist->next;
 		hist = hist->next;
 	}
 	}
-	// IPリストに無いので新規作成
-	hist_new = (struct _connect_history *) aCalloc(1,sizeof(struct _connect_history));
-	hist_new->ip   = ip;
-	hist_new->tick = gettick();
-	if(connect_history[ip & 0xFFFF] != NULL) {
-		hist = connect_history[ip & 0xFFFF];
-		hist->prev = hist_new;
-		hist_new->next = hist;
-	}
-	connect_history[ip & 0xFFFF] = hist_new;
+	// IP not found, add to history
+	CREATE(hist, ConnectHistory, 1);
+	memset(hist, 0, sizeof(ConnectHistory));
+	hist->ip   = ip;
+	hist->tick = gettick();
+	hist->next = connect_history[ip&0xFFFF];
+	connect_history[ip&0xFFFF] = hist;
 	return connect_ok;
 	return connect_ok;
 }
 }
 
 
-static int connect_check_clear(int tid,unsigned int tick,int id,int data) {
+/// Timer function.
+/// Deletes old connection history records.
+static int connect_check_clear(int tid, unsigned int tick, int id, int data)
+{
 	int i;
 	int i;
 	int clear = 0;
 	int clear = 0;
 	int list  = 0;
 	int list  = 0;
-	struct _connect_history *hist , *hist2;
-	for(i = 0;i < 0x10000 ; i++) {
-		hist = connect_history[i];
-		while(hist) {
-			if ((DIFF_TICK(tick,hist->tick) > ddos_interval * 3 && !hist->status) ||
-				(DIFF_TICK(tick,hist->tick) > ddos_autoreset && hist->status)) {
-				// clear data
-				hist2 = hist->next;
-				if(hist->prev) {
-					hist->prev->next = hist->next;
-				} else {
-					connect_history[i] = hist->next;
-				}
-				if(hist->next) {
-					hist->next->prev = hist->prev;
-				}
+	ConnectHistory root;
+	ConnectHistory* prev_hist;
+	ConnectHistory* hist;
+
+	for( i=0; i < 0x10000 ; ++i ){
+		prev_hist = &root;
+		root.next = hist = connect_history[i];
+		while( hist ){
+			if( (!hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_interval*3) ||
+					(hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_autoreset) )
+			{// Remove connection history
+				prev_hist->next = hist->next;
 				aFree(hist);
 				aFree(hist);
-				hist = hist2;
+				hist = prev_hist->next;
 				clear++;
 				clear++;
 			} else {
 			} else {
+				prev_hist = hist;
 				hist = hist->next;
 				hist = hist->next;
 			}
 			}
 			list++;
 			list++;
 		}
 		}
+		connect_history[i] = root.next;
 	}
 	}
-	if(access_debug) {
+	if( access_debug ){
 		ShowMessage("connect_check_clear: Cleared %d of %d from IP list.\n", clear, list);
 		ShowMessage("connect_check_clear: Cleared %d of %d from IP list.\n", clear, list);
 	}
 	}
 	return list;
 	return list;
 }
 }
 
 
-// IPマスクチェック
-int access_ipmask(const char *str,struct _access_control* acc)
+/// Parses the ip address and mask and puts it into acc.
+/// Returns 1 is successful, 0 otherwise.
+int access_ipmask(const char* str, AccessControl* acc)
 {
 {
-	unsigned int mask=0,i=0,m,ip, a0,a1,a2,a3;
-	if( !strcmp(str,"all") ) {
+	uint32 ip;
+	uint32 mask;
+	unsigned int a[4];
+	unsigned int m[4];
+	int n;
+
+	if( strcmp(str,"all") == 0 ){
 		ip   = 0;
 		ip   = 0;
 		mask = 0;
 		mask = 0;
 	} else {
 	} else {
-		if( sscanf(str,"%d.%d.%d.%d%n",&a0,&a1,&a2,&a3,&i)!=4 || i==0) {
-			ShowError("access_ipmask: Unknown format %s!\n",str);
+		if( ((n=sscanf(str,"%u.%u.%u.%u/%u.%u.%u.%u",a,a+1,a+2,a+3,m,m+1,m+2,m+3)) != 8 && // not an ip + standard mask
+				(n=sscanf(str,"%u.%u.%u.%u/%u",a,a+1,a+2,a+3,m)) != 5 && // not an ip + bit mask
+				(n=sscanf(str,"%u.%u.%u.%u",a,a+1,a+2,a+3)) != 4 ) || // not an ip
+				a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 || // invalid ip
+				(n == 8 && (m[0] > 255 || m[1] > 255 || m[2] > 255 || m[3] > 255)) || // invalid standard mask
+				(n == 5 && m[0] > 32) ){ // invalid bit mask
 			return 0;
 			return 0;
 		}
 		}
-		ip = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0;
-
-		if(sscanf(str+i,"/%d.%d.%d.%d",&a0,&a1,&a2,&a3)==4 ){
-			mask = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0;
-		} else if(sscanf(str+i,"/%d",&m) == 1) {
-			for(i=0;i<m;i++) {
+		ip = (uint32)(a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24));
+		if( n == 8 )
+		{// standard mask
+			mask = (uint32)(a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24));
+		} else if( n == 5 )
+		{// bit mask
+			mask = 0;
+			while( m[0] ){
 				mask = (mask >> 1) | 0x80000000;
 				mask = (mask >> 1) | 0x80000000;
+				--m[0];
 			}
 			}
 			mask = ntohl(mask);
 			mask = ntohl(mask);
-		} else {
+		} else
+		{// just this ip
 			mask = 0xFFFFFFFF;
 			mask = 0xFFFFFFFF;
 		}
 		}
 	}
 	}
-	if(access_debug) {
+	if( access_debug ){
 		ShowMessage("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n",
 		ShowMessage("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n",
 			CONVIP(ip), CONVIP(mask));
 			CONVIP(ip), CONVIP(mask));
 	}
 	}
@@ -971,7 +987,9 @@ int access_ipmask(const char *str,struct _access_control* acc)
 	acc->mask = mask;
 	acc->mask = mask;
 	return 1;
 	return 1;
 }
 }
+//////////////////////////////
 #endif
 #endif
+//////////////////////////////
 
 
 int socket_config_read(const char *cfgName) {
 int socket_config_read(const char *cfgName) {
 	int i;
 	int i;
@@ -992,39 +1010,46 @@ int socket_config_read(const char *cfgName) {
 		if(strcmpi(w1,"stall_time")==0){
 		if(strcmpi(w1,"stall_time")==0){
 			stall_time = atoi(w2);
 			stall_time = atoi(w2);
 	#ifndef MINICORE
 	#ifndef MINICORE
-		} else if(strcmpi(w1,"enable_ip_rules")==0){
-			if(strcmpi(w2,"yes")==0)
+		} else if( strcmpi(w1,"enable_ip_rules") == 0 ){
+			if( strcmpi(w2,"yes") == 0 )
 				ip_rules = 1;
 				ip_rules = 1;
-			else if(strcmpi(w2,"no")==0)
+			else if( strcmpi(w2,"no") == 0 )
 				ip_rules = 0;
 				ip_rules = 0;
-			else ip_rules = atoi(w2);
-		} else if(strcmpi(w1,"order")==0){
-			access_order=atoi(w2);
-			if(strcmpi(w2,"deny,allow")==0) access_order=ACO_DENY_ALLOW;
-			if(strcmpi(w2,"allow,deny")==0) access_order=ACO_ALLOW_DENY;
-			if(strcmpi(w2,"mutual-failure")==0) access_order=ACO_MUTUAL_FAILTURE;
-		} else if(strcmpi(w1,"allow")==0){
-			access_allow = (struct _access_control *) aRealloc(access_allow,(access_allownum+1)*sizeof(struct _access_control));
-			if(access_ipmask(w2,&access_allow[access_allownum])) {
-				access_allownum++;
-			}
-		} else if(strcmpi(w1,"deny")==0){
-			access_deny = (struct _access_control *) aRealloc(access_deny,(access_denynum+1)*sizeof(struct _access_control));
-			if(access_ipmask(w2,&access_deny[access_denynum])) {
-				access_denynum++;
-			}
-		} else if(!strcmpi(w1,"ddos_interval")){
+			else
+				ip_rules = atoi(w2);
+		} else if( strcmpi(w1,"order") == 0 ){
+			access_order = atoi(w2);
+			if( strcmpi(w2,"deny,allow") == 0 )
+				access_order = ACO_DENY_ALLOW;
+			else if( strcmpi(w2,"allow,deny") == 0 )
+				access_order=ACO_ALLOW_DENY;
+			else if( strcmpi(w2,"mutual-failure") == 0 )
+				access_order=ACO_MUTUAL_FAILURE;
+		} else if( strcmpi(w1,"allow") == 0 ){
+			RECREATE(access_deny, AccessControl, access_denynum+1);
+			if( access_ipmask(w2,&access_allow[access_allownum]) )
+				++access_allownum;
+			else
+				ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
+		} else if( strcmpi(w1,"deny") == 0 ){
+			RECREATE(access_deny, AccessControl, access_denynum+1);
+			if( access_ipmask(w2,&access_deny[access_denynum]) )
+				++access_denynum;
+			else
+				ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
+		} else if( strcmpi(w1,"ddos_interval") == 0){
 			ddos_interval = atoi(w2);
 			ddos_interval = atoi(w2);
-		} else if(!strcmpi(w1,"ddos_count")){
+		} else if( strcmpi(w1,"ddos_count") == 0){
 			ddos_count = atoi(w2);
 			ddos_count = atoi(w2);
-		} else if(!strcmpi(w1,"ddos_autoreset")){
+		} else if( strcmpi(w1,"ddos_autoreset") == 0){
 			ddos_autoreset = atoi(w2);
 			ddos_autoreset = atoi(w2);
-		} else if(!strcmpi(w1,"debug")){
-			if(strcmpi(w2,"yes")==0)
+		} else if( strcmpi(w1,"debug") == 0){
+			if( strcmpi(w2,"yes") == 0 )
 				access_debug = 1;
 				access_debug = 1;
-			else if(strcmpi(w2,"no")==0)
+			else if( strcmpi(w2,"no") == 0 )
 				access_debug = 0;
 				access_debug = 0;
-			else access_debug = atoi(w2);
+			else
+				access_debug = atoi(w2);
 	#endif
 	#endif
 		} else if (strcmpi(w1, "mode_neg") == 0)
 		} else if (strcmpi(w1, "mode_neg") == 0)
 		{
 		{
@@ -1070,18 +1095,20 @@ void socket_final (void)
 {
 {
 	int i;
 	int i;
 #ifndef MINICORE
 #ifndef MINICORE
-	struct _connect_history *hist , *hist2;
-	for(i = 0; i < 0x10000; i++) {
+	ConnectHistory* hist;
+	ConnectHistory* next_hist;
+
+	for( i=0; i < 0x10000; ++i ){
 		hist = connect_history[i];
 		hist = connect_history[i];
-		while(hist) {
-			hist2 = hist->next;
+		while( hist ){
+			next_hist = hist->next;
 			aFree(hist);
 			aFree(hist);
-			hist = hist2;
+			hist = next_hist;
 		}
 		}
 	}
 	}
-	if (access_allow)
+	if( access_allow )
 		aFree(access_allow);
 		aFree(access_allow);
-	if (access_deny)
+	if( access_deny )
 		aFree(access_deny);
 		aFree(access_deny);
 #endif
 #endif
 
 
@@ -1235,20 +1262,21 @@ void socket_init(void)
 	func_parse_table[SESSION_RAW].func = default_func_parse;
 	func_parse_table[SESSION_RAW].func = default_func_parse;
 
 
 #ifndef MINICORE
 #ifndef MINICORE
-	// とりあえず5分ごとに不要なデータを削除する
+	// Delete old connection history every 5 minutes
+	memset(connect_history, 0, sizeof(connect_history));
 	add_timer_func_list(connect_check_clear, "connect_check_clear");
 	add_timer_func_list(connect_check_clear, "connect_check_clear");
-	add_timer_interval(gettick()+1000,connect_check_clear,0,0,300*1000);
+	add_timer_interval(gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
 #endif
 #endif
 }
 }
 
 
 
 
-bool session_isValid(int fd)
+int session_isValid(int fd)
 {	//End of Exam has pointed out that fd==0 is actually an unconnected session! [Skotlex]
 {	//End of Exam has pointed out that fd==0 is actually an unconnected session! [Skotlex]
 	//But this is not so true, it is used... for... something. The console uses it, would this not cause problems? [Skotlex]
 	//But this is not so true, it is used... for... something. The console uses it, would this not cause problems? [Skotlex]
 	return ( (fd>0) && (fd<FD_SETSIZE) && (NULL!=session[fd]) );
 	return ( (fd>0) && (fd<FD_SETSIZE) && (NULL!=session[fd]) );
 }
 }
 
 
-bool session_isActive(int fd)
+int session_isActive(int fd)
 {
 {
 	return ( session_isValid(fd) && !session[fd]->eof );
 	return ( session_isValid(fd) && !session[fd]->eof );
 }
 }

+ 2 - 2
src/common/socket.h

@@ -143,8 +143,8 @@ extern int fd_max;
 
 
 //////////////////////////////////
 //////////////////////////////////
 // some checking on sockets
 // some checking on sockets
-extern bool session_isValid(int fd);
-extern bool session_isActive(int fd);
+extern int session_isValid(int fd);
+extern int session_isActive(int fd);
 //////////////////////////////////
 //////////////////////////////////
 
 
 // Function prototype declaration
 // Function prototype declaration