+ 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;