This file is indexed.

/usr/src/xtables-addons-3.0/extensions/xt_fuzzy.c is in xtables-addons-dkms 3.0-0.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 *	This module implements a simple TSK FLC (Takagi-Sugeno-Kang Fuzzy Logic
 *	Controller) that aims to limit, in an adaptive and flexible way, the
 *	packet rate crossing a given stream. It serves as an initial and very
 *	simple (but effective) example of how Fuzzy Logic techniques can be
 *	applied to defeat DoS attacks.
 *
 *	As a matter of fact, Fuzzy Logic can help us to insert any "behavior"
 *	into our code in a precise, adaptive and efficient manner.
 *
 *	The goal is very similar to that of "limit" match, but using techniques
 *	of Fuzzy Control, that allow us to shape the transfer functions
 *	precisely, avoiding over and undershoots - and stuff like that.
 *
 * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
 * 2002-08-17  : Changed to eliminate floating point operations .
 * 2002-08-23  : Coding style changes .
 * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
 */

#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/random.h>
#include <net/tcp.h>
#include <linux/netfilter/x_tables.h>
#include "xt_fuzzy.h"
#include "compat_xtables.h"

/*
 * Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
 * Expressed in percentage.
 */

#define PAR_LOW		1/100
#define PAR_HIGH	1

MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
MODULE_DESCRIPTION("Xtables: Fuzzy Logic Controller match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_fuzzy");
MODULE_ALIAS("ip6t_fuzzy");

static uint8_t mf_high(uint32_t tx, uint32_t mini, uint32_t maxi)
{
	if (tx >= maxi)
		return 100;
	if (tx <= mini)
		return 0;
	return 100 * (tx - mini) / (maxi - mini);
}

static uint8_t mf_low(uint32_t tx, uint32_t mini, uint32_t maxi)
{
	if (tx <= mini)
		return 100;
	if (tx >= maxi)
		return 0;
	return 100 * (maxi - tx) / (maxi - mini);

}

static bool
fuzzy_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	struct xt_fuzzy_mtinfo *info = (void *)par->matchinfo;
	unsigned long amount;
	uint8_t howhigh, howlow, random_number;

	info->bytes_total += skb->len;
	++info->packets_total;
	info->present_time = jiffies;

	if (info->present_time >= info->previous_time) {
		amount = info->present_time - info->previous_time;
	} else {
		/*
		 * There was a transition: I choose to re-sample
		 * and keep the old acceptance rate...
	         */
		amount = 0;
		info->previous_time = info->present_time;
		info->bytes_total = info->packets_total = 0;
	}

	if (amount > HZ / 10) {
		/* More than 100 ms elapsed ... */

		info->mean_rate     = HZ * info->packets_total / amount;
		info->previous_time = info->present_time;
		info->bytes_total   = info->packets_total = 0;

		howhigh = mf_high(info->mean_rate, info->minimum_rate,
		          info->maximum_rate);
		howlow  = mf_low(info->mean_rate, info->minimum_rate,
		          info->maximum_rate);

		info->acceptance_rate = howhigh * PAR_LOW + PAR_HIGH * howlow;

		/*
		 * In fact, the above defuzzification would require a
		 * denominator proportional to (howhigh+howlow) but, in this
		 * particular case, that expression is constant.
		 *
		 * An imediate consequence is that it is not necessary to call
		 * both mf_high and mf_low - but to keep things understandable,
		 * I did so.
		 */
	}

	if (info->acceptance_rate < 100) {
		get_random_bytes(&random_number, sizeof(random_number));

		if (random_number <= 255 * info->acceptance_rate / 100)
			/*
			 * If within the acceptance, it can pass
			 * => do not match.
			 */
			return false;
		else
			/* It cannot pass (it matches) */
			return true;
	};

	/* acceptance_rate == 100 % => Everything passes ... */
	return false;
}

static int fuzzy_mt_check(const struct xt_mtchk_param *par)
{
	const struct xt_fuzzy_mtinfo *info = par->matchinfo;

	if (info->minimum_rate < FUZZY_MIN_RATE ||
	    info->maximum_rate > FUZZY_MAX_RATE ||
	    info->minimum_rate >= info->maximum_rate) {
		printk(KERN_INFO KBUILD_MODNAME ": bad values, please check.\n");
		return -EDOM;
	}

	return 0;
}

static struct xt_match fuzzy_mt_reg[] __read_mostly = {
	{
		.name       = "fuzzy",
		.revision   = 1,
		.family     = NFPROTO_IPV4,
		.match      = fuzzy_mt,
		.checkentry = fuzzy_mt_check,
		.matchsize  = sizeof(struct xt_fuzzy_mtinfo),
		.me         = THIS_MODULE,
	},
	{
		.name       = "fuzzy",
		.revision   = 1,
		.family     = NFPROTO_IPV6,
		.match      = fuzzy_mt,
		.checkentry = fuzzy_mt_check,
		.matchsize  = sizeof(struct xt_fuzzy_mtinfo),
		.me         = THIS_MODULE,
	},
};

static int __init fuzzy_mt_init(void)
{
	return xt_register_matches(fuzzy_mt_reg, ARRAY_SIZE(fuzzy_mt_reg));
}

static void __exit fuzzy_mt_exit(void)
{
	xt_unregister_matches(fuzzy_mt_reg, ARRAY_SIZE(fuzzy_mt_reg));
}

module_init(fuzzy_mt_init);
module_exit(fuzzy_mt_exit);