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

📄 ipt_recent.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 'match' is our primary function, called by the kernel whenever a rule is * hit with our module as an option to it. * What this function does depends on what was specifically asked of it by * the user: * --set -- Add or update last seen time of the source address of the packet *   -- matchinfo->check_set == IPT_RECENT_SET * --rcheck -- Just check if the source address is in the list *   -- matchinfo->check_set == IPT_RECENT_CHECK * --update -- If the source address is in the list, update last_seen *   -- matchinfo->check_set == IPT_RECENT_UPDATE * --remove -- If the source address is in the list, remove it *   -- matchinfo->check_set == IPT_RECENT_REMOVE * --seconds -- Option to --rcheck/--update, only match if last_seen within seconds *   -- matchinfo->seconds * --hitcount -- Option to --rcheck/--update, only match if seen hitcount times *   -- matchinfo->hit_count * --seconds and --hitcount can be combined */static intmatch(const struct sk_buff *skb,      const struct net_device *in,      const struct net_device *out,      const void *matchinfo,      int offset,      int *hotdrop){	int pkt_count, hits_found, ans;	unsigned long now;	const struct ipt_recent_info *info = matchinfo;	u_int32_t addr = 0, time_temp;	u_int8_t ttl = skb->nh.iph->ttl;	int *hash_table;	int orig_hash_result, hash_result, temp, location = 0, time_loc, end_collision_chain = -1;	struct time_info_list *time_info;	struct recent_ip_tables *curr_table;	struct recent_ip_tables *last_table;	struct recent_ip_list *r_list;#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");#endif	/* Default is false ^ info->invert */	ans = info->invert;#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);#endif	/* if out != NULL then routing has been done and TTL changed.	 * We change it back here internally for match what came in before routing. */	if(out) ttl++;	/* Find the right table */	spin_lock_bh(&recent_lock);	curr_table = r_tables;	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (curr_table = curr_table->next) );#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);#endif	spin_unlock_bh(&recent_lock);	/* Table with this name not found, match impossible */	if(!curr_table) { return ans; }	/* Make sure no one is changing the list while we work with it */	spin_lock_bh(&curr_table->list_lock);	r_list = curr_table->table;	if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;	if(!addr) { #ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);#endif		spin_unlock_bh(&curr_table->list_lock);		return ans;	}#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);#endif	/* Get jiffies now in case they changed while we were waiting for a lock */	now = jiffies;	hash_table = curr_table->hash_table;	time_info = curr_table->time_info;	orig_hash_result = hash_result = hash_func(addr,ip_list_hash_size);	/* Hash entry at this result used */	/* Check for TTL match if requested.  If TTL is zero then a match would never	 * happen, so match regardless of existing TTL in that case.  Zero means the	 * entry was added via the /proc interface anyway, so we will just use the	 * first TTL we get for that IP address. */	if(info->check_set & IPT_RECENT_TTL) {		while(hash_table[hash_result] != -1 && !(r_list[hash_table[hash_result]].addr == addr &&			(!r_list[hash_table[hash_result]].ttl || r_list[hash_table[hash_result]].ttl == ttl))) {			/* Collision in hash table */			hash_result = (hash_result + 1) % ip_list_hash_size;		}	} else {		while(hash_table[hash_result] != -1 && r_list[hash_table[hash_result]].addr != addr) {			/* Collision in hash table */			hash_result = (hash_result + 1) % ip_list_hash_size;		}	}	if(hash_table[hash_result] == -1 && !(info->check_set & IPT_RECENT_SET)) {		/* IP not in list and not asked to SET */		spin_unlock_bh(&curr_table->list_lock);		return ans;	}	/* Check if we need to handle the collision, do not need to on REMOVE */	if(orig_hash_result != hash_result && !(info->check_set & IPT_RECENT_REMOVE)) {#ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision in hash table. (or: %d,hr: %d,oa: %u,ha: %u)\n",				 orig_hash_result,				 hash_result,				 r_list[hash_table[orig_hash_result]].addr,				 addr);#endif		/* We had a collision.		 * orig_hash_result is where we started, hash_result is where we ended up.		 * So, swap them because we are likely to see the same guy again sooner */#ifdef DEBUG		if(debug) {		  printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[orig_hash_result] = %d\n",hash_table[orig_hash_result]);		  printk(KERN_INFO RECENT_NAME ": match(): Collision; r_list[hash_table[orig_hash_result]].hash_entry = %d\n",				r_list[hash_table[orig_hash_result]].hash_entry);		}#endif		r_list[hash_table[orig_hash_result]].hash_entry = hash_result;		temp = hash_table[orig_hash_result];#ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);#endif		hash_table[orig_hash_result] = hash_table[hash_result];		hash_table[hash_result] = temp;		temp = hash_result;		hash_result = orig_hash_result;		orig_hash_result = temp;		time_info[r_list[hash_table[orig_hash_result]].time_pos].position = hash_table[orig_hash_result];		if(hash_table[hash_result] != -1) {			r_list[hash_table[hash_result]].hash_entry = hash_result;			time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];		}#ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");#endif	}	if(hash_table[hash_result] == -1) {#ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",				 hash_result, addr);#endif		/* New item found and IPT_RECENT_SET, so we need to add it */		location = time_info[curr_table->time_pos].position;		hash_table[r_list[location].hash_entry] = -1;		hash_table[hash_result] = location;		memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));		r_list[location].time_pos = curr_table->time_pos;		r_list[location].addr = addr;		r_list[location].ttl = ttl;		r_list[location].last_seen = now;		r_list[location].oldest_pkt = 1;		r_list[location].last_pkts[0] = now;		r_list[location].hash_entry = hash_result;		time_info[curr_table->time_pos].time = r_list[location].last_seen;		curr_table->time_pos = (curr_table->time_pos + 1) % ip_list_tot;		ans = !info->invert;	} else {#ifdef DEBUG		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",				 hash_result,				 addr);#endif		/* Existing item found */		location = hash_table[hash_result];		/* We have a match on address, now to make sure it meets all requirements for a		 * full match. */		if(info->check_set & IPT_RECENT_CHECK || info->check_set & IPT_RECENT_UPDATE) {			if(!info->seconds && !info->hit_count) ans = !info->invert; else ans = info->invert;			if(info->seconds && !info->hit_count) {				if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = !info->invert; else ans = info->invert;			}			if(info->seconds && info->hit_count) {				for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {					if(r_list[location].last_pkts[pkt_count] == 0) break;					if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;				}				if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;			}			if(info->hit_count && !info->seconds) {				for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {					if(r_list[location].last_pkts[pkt_count] == 0) break;					hits_found++;				}				if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;			}		}#ifdef DEBUG		if(debug) {			if(ans)				printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);			else				printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);		}#endif		/* If and only if we have been asked to SET, or to UPDATE (on match) do we add the		 * current timestamp to the last_seen. */		if((info->check_set & IPT_RECENT_SET && (ans = !info->invert)) || (info->check_set & IPT_RECENT_UPDATE && ans)) {#ifdef DEBUG			if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");#endif			/* Have to update our time info */			time_loc = r_list[location].time_pos;			time_info[time_loc].time = now;			time_info[time_loc].position = location;			while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {				time_temp = time_info[time_loc].time;				time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;				time_info[(time_loc+1)%ip_list_tot].time = time_temp;				time_temp = time_info[time_loc].position;				time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;				time_info[(time_loc+1)%ip_list_tot].position = time_temp;				r_list[time_info[time_loc].position].time_pos = time_loc;				r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;				time_loc = (time_loc+1) % ip_list_tot;			}			r_list[location].time_pos = time_loc;			r_list[location].ttl = ttl;			r_list[location].last_pkts[r_list[location].oldest_pkt] = now;			r_list[location].oldest_pkt = ++r_list[location].oldest_pkt % ip_pkt_list_tot;			r_list[location].last_seen = now;		}		/* If we have been asked to remove the entry from the list, just set it to 0 */		if(info->check_set & IPT_RECENT_REMOVE) {#ifdef DEBUG			if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);#endif			/* Check if this is part of a collision chain */			while(hash_table[(orig_hash_result+1) % ip_list_hash_size] != -1) {				orig_hash_result++;				if(hash_func(r_list[hash_table[orig_hash_result]].addr,ip_list_hash_size) == hash_result) {					/* Found collision chain, how deep does this rabbit hole go? */#ifdef DEBUG					if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");#endif					end_collision_chain = orig_hash_result;				}			}			if(end_collision_chain != -1) {#ifdef DEBUG				if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");#endif				/* Part of a collision chain, swap it with the end of the chain				 * before removing. */				r_list[hash_table[end_collision_chain]].hash_entry = hash_result;				temp = hash_table[end_collision_chain];				hash_table[end_collision_chain] = hash_table[hash_result];				hash_table[hash_result] = temp;				time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];				hash_result = end_collision_chain;				r_list[hash_table[hash_result]].hash_entry = hash_result;				time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];			}			location = hash_table[hash_result];			hash_table[r_list[location].hash_entry] = -1;			time_loc = r_list[location].time_pos;			time_info[time_loc].time = 0;			time_info[time_loc].position = location;			while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {				time_temp = time_info[time_loc].time;				time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;				time_info[(time_loc+1)%ip_list_tot].time = time_temp;				time_temp = time_info[time_loc].position;				time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;				time_info[(time_loc+1)%ip_list_tot].position = time_temp;				r_list[time_info[time_loc].position].time_pos = time_loc;				r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;				time_loc = (time_loc+1) % ip_list_tot;			}			r_list[location].time_pos = time_loc;			r_list[location].last_seen = 0;			r_list[location].addr = 0;			r_list[location].ttl = 0;			memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));			r_list[location].oldest_pkt = 0;			ans = !info->invert;		}		spin_unlock_bh(&curr_table->list_lock);		return ans;	}	spin_unlock_bh(&curr_table->list_lock);#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");#endif	return ans;}/* This function is to verify that the rule given during the userspace iptables * command is correct. * If the command is valid then we check if the table name referred to by the * rule exists, if not it is created. */static intcheckentry(const char *tablename,           const struct ipt_ip *ip,           void *matchinfo,           unsigned int matchsize,           unsigned int hook_mask){	int flag = 0, c;	unsigned long *hold;	const struct ipt_recent_info *info = matchinfo;	struct recent_ip_tables *curr_table, *find_table, *last_table;#ifdef DEBUG	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");#endif

⌨️ 快捷键说明

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