/* Стандартная стратегия для работы с типами в базе данных. Применима для простых типов (не содержащих указателей и сложной логики инициализации).*/
template<typename T>
class StdStrategy {
public:
/* Возвращает размер данных. */
static size_t size(const T& key) { return sizeof(key); }
/* Возвращает данные в виде константного указателя void*. Размер определется вызовом метода size(). */
static const void* data(const T& key) { return &key; }
/* Копирует данные из void* в переменную типа, с которым работает стратегия. */
static void put(T& d, const void* v, size_t size) {
assert(sizeof(d) <= size);
const T c = *(static_cast<const T*>(v));
d = c;
}
};
/* Спецификация стандартной стратегии для класса STL-строк. */
template<>
class StdStrategy<std::string> {
public:
static size_t size(const std::string& key) {
return key.length();
}
static const void* data(const std::string& key) {
return key.c_str();
}
static void put(std::string& s, const void* v, size_t size) {
s = std::string(static_cast<const char*>(v), size);
}
};
Работа с базой данных: контроллер.
/* Шаблон контроллера базы данных. Детали реализации опущены для экономии места, представлен только интерфейс.*/
template<
typename KeyType,
typename DataType,
template <typename> class KeyStrategy = StdStrategy,
template <typename> class DataStrategy = StdStrategy
>
class DBController {
public:
typedef KeyType Key;
typedef DataType Data;
/* Конструктор. Принимает имя файла базы данных. Если такого файла нет, он будет создан. */
DBController(const std::string& dbname) {... }
/* Деструктор. Корректно закрывает базу данных. */
~DBController() {... }
/* Возвращает данные по ключу. Выбрасывает исключение, если такого ключа нет в БД. */
Data get(const Key& key) {... }
/* Записывает пару ключ/значение в БД. Если такой ключ уже существует, старое его значение будет утрачено. */
void put(const Key& key, const Data& data) {... }
/* Проверяет, существует ли ключ в базе данных. */
bool exists(const Key& key) {... }
/* Делает проход по всей базе данных и вызывает oper(key, value) для каждой пары ключ/значение. Тип Т должен быть пригоден для этой цели, иначе возникнет ошибка компиляции. */
template<typename T> void foreach(T& oper) {... }
/* Очищает базу данных, удаляя все имеющиеся в ней пары ключ/значение. */
void truncate() {
impl_->truncate();
}
private:
/*... */
};
Множество пакетов.
/* Интерфейс, описывающий множество пакетов. */
class Set {
public:
/* Вернуть пакет по локальному номеру. */
virtual Packet at(SET_INDEX index) const = 0;
/* Получить размер множества. */
virtual SIZE size() const = 0;
virtual ~Set() {}
};
Правило.
// Интерфейс правила
class Rule {
public:
/* Тип итератора для доступа к подмножествам. SET_INDEX - это псевдоним типа uint32_t */
typedef std::vector<SET_INDEX>::iterator Iterator;
/* Клонирование правила */
virtual Rule* clone() const = 0;
/* Применение правила к переданному множеству. Все остальные методы, которые имеют дело с "текущим делением", не должны вызываться раньше этого. */
virtual SIZE compute(const std::auto_ptr<Set> subset) = 0;
/* Возвращает разницу в весе частей текущего деления. */
virtual SIZE getDiff() const = 0;
/* Возвращают левое и правое дочернее правило для текущего деления. */
virtual Rule* getLeftRule() const = 0;
virtual Rule* getRightRule() const = 0;
/* Возвращает "истину", если правило прошло (см. описание архитектуры генератора). */
virtual bool isPassed() const = 0;
/* Вовзращает "истину", если текущее деление невырожденное. */
virtual bool isDivided() const = 0;
/* Работа с флагом активности правила. */
virtual bool isActive() const = 0;
virtual void setActive(bool active) = 0;
/* Возвращает текущее деление в текстовом виде, пригодном для использования в командах iptables. */
virtual std::string printRule() const = 0;
/* Возвращают итераторы на начало и конец левого и правого подмножества текущего деления. */
virtual Iterator leftBegin() const = 0;
virtual Iterator leftEnd() const = 0;
virtual Iterator rightBegin() const = 0;
virtual Iterator rightEnd() const = 0;
virtual ~Rule() {}
};
Приложение Б.
(обязательное)
Файл описания диапазонов адресов.
Файл описания диапазонов адресов состоит из записей, разделенные пробельными символами. Записи могут быть двух видов:
1. строка «source» или «dest». Обозначает, что все последующие за этой строкой записи (пока не встретится противоположная строка, либо конец файла) относятся к адресам отправителя или получателя соответственно. Для этих двух параметров можно задать разные наборы диапазонов.
2. Все, что не является «source» или «dest», трактуется как пары «диапазон адресов» и «маска диапазона». Оба этих поля также могут быть разделены любыми пробельными символами. Они имеют стандартный формат записи адресов в виде четырех чисел от 0 до 255, разделенных точками (маска тоже записывается таким образом, нотация CIDR не поддерживается). Важна очередность задания параметров, поскольку именно с помощью нее система отличает диапазон от маски. Диапазон может идти вслед за флагом «source/dest», либо вслед за маской. Маска должна идти вслед за диапазоном. Флаг «source/dest» не может идти вслед за диапазоном (так как ожидается маска) — этот случай система отлавливает и сообщает об ошибке.
Пример.
source
10.3.0.0 255.255.0.0
193.124.208.0 255.255.255.0
dest
10.4.16.0 255.255.255.0
193.124.208.0 255.255.255.0
source
10.168.131.0 255.255.255.0
[1] Класс, не хранящий данных, все методы которого — чисто виртуальные.
[2] Имя файла с нужным журналом зависит от настроек демона syslogd. Обычно это /var/log/kern.log.






