pf

Псевдоустройство фильтрации пакетов

Синтаксис:

/dev/pf

Платформы:

ЗОСРВ «Нейтрино»

Целевые архитектуры:

aarch64, arm, armv7, e2k, mips, ppc, x86

Описание:

Фильтрация пакетов выполняется в io-pkt-*. Псевдоустройство /dev/pf позволяет управлять поведением фильтра пакетов через интерфейс ioctl(). Существуют команды, с помощью которых можно активировать или деактивировать фильтр, загружать наборы правил, добавлять или удалять отдельные правила или записи таблицы состояний и собирать статистику. Утилита pfctl обеспечивает наиболее часто используемые функции.


Note: Несмотря на то, что в документации по NetBSD описывается ioctl(), в коде фильтрации пакетов следует использовать ioctl_socket(). В архитектуре передачи сообщений микроядра вызовы команды ioctl() с встроенными указателями должны обрабатываться по специальной схеме. В случае если специальная обработка не требуется функции ioctl_socket() по умолчанию представляет собой функцию ioctl().

Для таких операций манипулирования, как загрузка набора правил, предполагающая неоднократный вызов ioctl_socket(), требуется мандат, предотвращающий выполнение нескольких противоречивых операций.


Поля структур параметра ioctl_socket(), относящиеся к пакетным данным (например, адреса и порты), обычно располагаются в сетевом порядке байтов.

Правила и таблицы адресов содержатся в закладках. Если поле закладки структуры аргумента не заполнено, то при обслуживании запроса ioctl_socket()) администратор io-pkt-* использует для выполнения операций закладку по умолчанию (т.е. основной набор правил). Закладки определяются по имени и могут быть вложенными, при этом компоненты разделяются символами косой черты, аналогично иерархиям файловой системы. Конечный компонент пути к закладке – собственно закладка, в соответствии с которой выполняются операции.

Интерфейс ioctl_socket()

Псевдоустройство /dev/pf поддерживает следующие команды ioctl_socket(), которые описаны в заголовочном файле <net/pfvar.h>:

DIOCSTART
Запустить фильтр пакетов.
DIOCSTOP
Завершить работу фильтра пакетов.
DIOCSTARTALTQ
Запустить систему управления пропускной способностью ALTQ (см. описание altq в документации по NetBSD).
DIOCSTOPALTQ
Завершить работу системы управления пропускной способностью ALTQ.
DIOCBEGINADDRS struct pfioc_pooladdr *pp
Очистить пул адресов в буфере и получить мандат для последующего вызова команд DIOCADDADDR, DIOCADDRULE и DIOCCHANGERULE. Структура pfioc_pooladdr определена следующимобразом:

struct pfioc_pooladdr {
u_int32_t action;
u_int32_t ticket;
u_int32_t nr;
u_int32_t r_num;
u_int8_t r_action;
u_int8_t r_last;
u_int8_t af;
char anchor[MAXPATHLEN];
struct pf_pooladdr addr;
};

DIOCADDADDR struct pfioc_pooladdr *pp
Добавить адрес пула addr в пул адресов в буфере для использования при следующем вызове команды DIOCADDRULE или DIOCCHANGERULE. Все остальные элементы структуры игнорируются.
DIOCADDRULE struct pfioc_rule *pr
Добавить данное правило в конец неактивного набора правил. Структура pfioc_rule определена следующим образом:

struct pfioc_rule {
u_int32_t action;
u_int32_t ticket;
u_int32_t pool_ticket;
u_int32_t nr;
char anchor[MAXPATHLEN];
char anchor_call[MAXPATHLEN];
struct pf_rule rule;
};

Для выполнения этого вызова необходимо наличие мандата ticket, полученного в результате предварительного вызова команды DIOCXBEGIN, и мандата пула pool_ticket, полученного в результате вызова DIOCBEGINADDRS. Кроме того, если требуются адреса пулов, следует вызвать команду DIOCADDADDR. Дополнительное имя закладки указывает на закладку, к которой требуется добавить правило. Элементы nr и action игнорируются.

DIOCADDALTQ struct pfioc_altq *pa
Добавить дисциплину ALTQ или очередь. Структура pfioc_altq определена следующим образом:

struct pfioc_altq {
u_int32_t action;
u_int32_t ticket;
u_int32_t nr;
struct pf_altq altq;
};

DIOCGETRULES struct pfioc_rule *pr
Получить мандат для последующих вызовов команды DIOCGETRULE и число nr правил в активном наборе правил.
DIOCGETRULE struct pfioc_rule *pr
Получить правило по его номеру nr с использованием мандата, полученного в результате предварительного вызова DIOCGETRULES.
DIOCGETADDRS struct pfioc_pooladdr *pp
Получить мандат для последующих вызовов DIOCGETADDR и число nr адресов пулов в правиле, определенном элементами r_action, r_num и anchor.
DIOCGETADDR struct pfioc_pooladdr *pp
Получить адрес пула addr по его номеру nr из правила, определенного элементами r_action, r_num и anchor, с использованием мандата, полученного в результате предварительного вызова DIOCGETADDRS.
DIOCGETALTQS struct pfioc_altq *pa
Получить мандат для последующих вызовов DIOCGETALTQ и число nr очередей в активном списке.
DIOCGETALTQ struct pfioc_altq *pa
Получить дисциплину очереди altq по номеру nr с использованием мандата, полученного в результате предварительного вызова DIOCGETALTQS.
DIOCGETQSTATS struct pfioc_qstats *pq
Получить статистику для очереди. Структура pfioc_qstats определена следующим образом:

struct pfioc_qstats {
u_int32_t ticket;
u_int32_t nr;
void *buf;
int nbytes;
u_int8_t scheduler;
};

При вызове этой команды заполняется указатель на буфер статистики buf длиной nbytes для очереди с номером nr.

DIOCGETRULESETS struct pfioc_ruleset *pr
Получить число nr наборов правил (т.е. закладок), напрямую присоединенных к закладке с именем path для использования при последующих вызовах DIOCGETRULESET. Структура pfioc_ruleset определена следующим образом:

struct pfioc_ruleset {
u_int32_t nr;
char path[MAXPATHLEN];
char name[PF_ANCHOR_NAME_SIZE];
};

Вложенные закладки игнорируются, поскольку они напрямую не присоединены к данной закладке. Если эта закладка отсутствует, команда ioctl_socket() возвращает EINVAL.

DIOCGETRULESET struct pfioc_ruleset *pr
Получить имя набора правил (т.е. закладки) по номеру nr, на основе заданного пути к закладке; максимальное значение номера определяется предварительным вызовом команды DIOCGETRULESETS. Если эта закладка не существует, команда ioctl_socket() возвращает EINVAL, а если набор правил одновременно обновляется другим процессом – EBUSY.
DIOCADDSTATE struct pfioc_state *ps
Добавить запись состояния. Структура pfioc_state определена следующим образом:

struct pfioc_state {
u_int32_t nr;
struct pf_state state;
};

DIOCGETSTATE struct pfioc_state *ps
Извлечь из таблицы состояний запись с номером nr.
DIOCKILLSTATES struct pfioc_state_kill *psk
Удалить соответствующие записи из таблицы состояний. Команда ioctl_socket() возвращает количество уничтоженных состояний в psk_af. Структура pfioc_state_kill определена следующим образом:

struct pfioc_state_kill {
sa_family_t psk_af;
int psk_proto;
struct pf_rule_addr psk_src;
struct pf_rule_addr psk_dst;
char psk_ifname[IFNAMSIZ];
};

DIOCCLRSTATES struct pfioc_state_kill *psk
Удалить все состояния. Эта команда аналогична DIOCKILLSTATES, однако при ее выполнении игнорируются поля psk_af, psk_proto, psk_src и psk_dst структуры pfioc_state_kill.
DIOCSETSTATUSIF struct pfioc_if *pi
Определить интерфейс, по которому требуется собрать статистику. Структура pfioc_if определена следующим образом:

struct pfioc_if {
char ifname[IFNAMSIZ];
};

DIOCGETSTATUS struct pf_status *s
Получить статистику внутреннего фильтра пакетов. Структура pf_status определена следующим образом:

struct pf_status {
u_int64_t counters[PFRES_MAX];
u_int64_t lcounters[LCNT_MAX];
u_int64_t fcounters[FCNT_MAX];
u_int64_t scounters[SCNT_MAX];
u_int64_t pcounters[2][2][3];
u_int64_t bcounters[2][2];
u_int64_t stateid;
u_int32_t running;
u_int32_t states;
u_int32_t src_nodes;
u_int32_t since;
u_int32_t debug;
u_int32_t hostid;
char ifname[IFNAMSIZ];
};

DIOCCLRSTATUS
Удалить внутреннюю статистику фильтра пакетов.
DIOCNATLOOK struct pfioc_natlook *pnl
Выполнить поиск записи в таблице состояний по адресам и портам источника и назначения. Структура pfioc_natlook определена следующим образом:

struct pfioc_natlook {
struct pf_addr saddr;
struct pf_addr daddr;
struct pf_addr rsaddr;
struct pf_addr rdaddr;
u_int16_t sport;
u_int16_t dport;
u_int16_t rsport;
u_int16_t rdport;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
};

DIOCSETDEBUG u_int32_t *level
Установить одно из значений уровня отладки:
PF_DEBUG_NONE
PF_DEBUG_URGENT
PF_DEBUG_MISC
PF_DEBUG_NOISY.
DIOCGETSTATES struct pfioc_states *ps
Получить записи таблицы состояний. Структура pfioc_states определена следующим образом:

struct pfioc_states {
int ps_len;
union {
caddr_t psu_buf;
struct pf_state *psu_states;
} ps_u;
#define ps_buf ps_u.psu_buf
#define ps_states ps_u.psu_states
};

Если значение ps_len равно нулю, то все состояния суммируются в элементе pf_states, а ps_len принимает значение, соответствующее объему памяти, который они занимают (т.е. sizeof( struct pf_state ) * nr). Если значение ps_len отлично от нуля, то максимальное количество состояний суммируется в элементе ps_len, а значение ps_len обновляется в соответствии с объемом памяти, который занимают правила.

DIOCCHANGERULE struct pfioc_rule *pcr
Добавить правило в набор правил, определяемый элементом rule.action, или удалить это правило. Тип выполняемой операции определяется элементом action, который может принимать следующие значения:
PF_CHANGE_NONE
PF_CHANGE_ADD_HEAD
PF_CHANGE_ADD_TAIL
PF_CHANGE_ADD_BEFORE
PF_CHANGE_ADD_AFTER
PF_CHANGE_REMOVE
PF_CHANGE_GET_TICKET

Для всех действий, за исключением PF_CHANGE_GET_TICKET, для ticket следует установить значение, полученное в результате вызова команды PF_CHANGE_GET_TICKET. Для всех действий, за исключением PF_CHANGE_REMOVE и PF_CHANGE_GET_TICKET, для pool_ticket следует установить значение, полученное в результате вызова команды DIOCBEGINADDRS. Значение anchor определяет, для какой закладки выполняется операция. Элемент nr определяет номер правила, к которому применяются действия PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER или PF_CHANGE_REMOVE.
DIOCCHANGEADDR struct pfioc_pooladdr *pca
Добавить адрес пула addr в правило, определяемое элементами r_action, r_num, и anchor, или удалить этот адрес.
DIOCSETTIMEOUT struct pfioc_tm *pt
Установить для таймаута состояния timeout значение seconds. Структура pfioc_tm определена следующим образом:

struct pfioc_tm {
int timeout;
int seconds;
};

Предыдущее значение указывается в поле seconds. Возможные значения элемента timeout приведены в списке значений PFTM_* в заголовочном файле <net/pfvar.h>.

DIOCGETTIMEOUT struct pfioc_tm *pt
Получить значение таймаута состояния timeout. Это значение указывается в поле seconds.
DIOCCLRRULECTRS
Очистить статистику по каждому правилу.
DIOCSETLIMIT struct pfioc_limit *pl
Установить жесткие ограничения для пулов памяти, используемых фильтром пакетов. Структура pfioc_limit определена следующим образом:

struct pfioc_limit {
int index;
unsigned limit;
};
enum {
PF_LIMIT_STATES,
PF_LIMIT_SRC_NODES,
PF_LIMIT_FRAGS
};

DIOCGETLIMIT struct pfioc_limit *pl
Получить жесткие ограничения для пула памяти, определенного элементом index.
DIOCRCLRTABLES struct pfioc_table *io
Удалить все таблицы. Все команды ioctl_socket() для манипулирования разрядными таблицами имеют одинаковую структуру, описанную далее. После завершения выполнения команды DIOCRCLRTABLES в поле pfrio_ndel содержится количество удаленных таблиц. Структура pfioc_table определена следующим образом:

struct pfioc_table {
struct pfr_table pfrio_table;
void *pfrio_buffer;
int pfrio_esize;
int pfrio_size;
int pfrio_size2;
int pfrio_nadd;
int pfrio_ndel;
int pfrio_nchange;
int pfrio_flags;
u_int32_t pfrio_ticket;
};
#define pfrio_exists pfrio_nadd
#define pfrio_nzero pfrio_nadd
#define pfrio_nmatch pfrio_nadd
#define pfrio_naddr pfrio_size2
#define pfrio_setflag pfrio_size2
#define pfrio_clrflag pfrio_nadd

DIOCRADDTABLES struct pfioc_table *io
Создать одну или несколько таблиц. При запуске команды поле pfrio_buffer[pfrio_size] содержит таблицу структур pfr_table. После завершения выполнения команды в поле pfrio_nadd указывается количество успешно созданных таблиц. Структура pfr_table определена следующим образом:

struct pfr_table {
char pfrt_anchor[MAXPATHLEN];
char pfrt_name[PF_TABLE_NAME_SIZE];
u_int32_t pfrt_flags;
u_int8_t pfrt_fback;
};

DIOCRDELTABLES struct pfioc_table *io
Удалить одну или несколько таблиц. При запуске команды поле pfrio_buffer[pfrio_size] содержит таблицу структур pfr_table. После завершения выполнения команды в поле pfrio_nadd указывается количество успешно удаленных таблиц.
DIOCRGETTABLES struct pfioc_table *io
Получить список всех таблиц. При запуске команды поле pfrio_buffer[pfrio_size] содержит действительный буфер, доступный для записи, для структур pfr_table. После завершения выполнения команды в поле pfrio_size содержится количество таблиц, записанных в буфер. Если размер буфера не достаточен, то io-pkt-* не сохраняет данные, но возвращает требуемый размер буфера, сообщение об ошибке не выводится.
DIOCRGETTSTATS struct pfioc_table *io
Вызов этой команды аналогичен DIOCRGETTABLES, но она используется для получения массива структур pfr_tstats. Структура pfr_tstats определена следующим образом:

struct pfr_tstats {
struct pfr_table pfrts_t;
u_int64_t pfrts_packets[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
u_int64_t pfrts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
u_int64_t pfrts_match;
u_int64_t pfrts_nomatch;
long pfrts_tzero;
int pfrts_cnt;
int pfrts_refcnt[PFR_REFCNT_MAX];
};
#define pfrts_name pfrts_t.pfrt_name
#define pfrts_flags pfrts_t.pfrt_flags

DIOCRCLRTSTATS struct pfioc_table *io
Удалить статистику в одной или нескольких таблицах. При запуске команды поле pfrio_buffer[pfrio_size] содержит таблицу структур pfr_table. После завершения выполнения команды в поле pfrio_nzero указывается количество таблиц, статистика в которых успешно удалена.
DIOCRCLRADDRS struct pfioc_table *io
Удалить все адреса в таблице. При запуске команды поле pfrio_table содержит таблицу, которую требуется очистить. После завершения выполнения команды в поле pfrio_ndel указывается количество удаленных адресов.
DIOCRADDADDRS struct pfioc_table *io
Добавить в таблицу один или несколько адресов. При запуске программы поле pfrio_table содержит идентификатор таблицы, а поле pfrio_buffer[pfrio_size] – список структур pfr_addr, которые требуется добавить. После завершения выполнения команды поле pfrio_nadd содержит количество успешно добавленных адресов. Структура pfr_addr определена следующим образом:

struct pfr_addr {
union {
struct in_addr _pfra_ip4addr;
struct in6_addr _pfra_ip6addr;
} pfra_u;
u_int8_t pfra_af;
u_int8_t pfra_net;
u_int8_t pfra_not;
u_int8_t pfra_fback;
};
#define pfra_ip4addr pfra_u._pfra_ip4addr
#define pfra_ip6addr pfra_u._pfra_ip6addr

DIOCRDELADDRS struct pfioc_table *io
Удалить один или несколько адресов из таблицы. При запуске команды поле pfrio_table содержит идентификатор таблицы, а поле pfrio_buffer[pfrio_size] – список структур pfr_addr, которые требуется удалить. После завершения команды поле pfrio_ndel содержит количество успешно удаленных адресов.
DIOCRSETADDRS struct pfioc_table *io
Заменить содержимое таблицы новым списком адресов. Это наиболее сложная команда, в которой используются все элементы структуры.

При запуске команды поле pfrio_table содержит идентификатор таблицы, а поле pfrio_buffer[pfrio_size] – новый список структур pfr_addr. Кроме того, если значение в поле pfrio_size2 отлично от нуля, то pfrio_buffer[pfrio_size..pfrio_size2] используется в качестве буфера для записи, в который io-pkt-* может копировать адреса, удаленные в процессе замены.

После завершения выполнения команды в полях pfrio_ndel, pfrio_nadd и pfrio_nchange содержится количество адресов, удаленных, добавленных и измененных администратором io-pkt-*. Если при запуске команды установлено значение pfrio_size2, то в поле pfrio_size2 указывается размер используемого буфера, так же, как и для команды DIOCRGETADDRS.
DIOCRGETADDRS struct pfioc_table *io
Получить все адреса из таблицы. При запуске команды в поле pfrio_table содержится идентификатор таблицы, а в поле pfrio_buffer[pfrio_size] – действительный буфер для записи для структур pfr_addr. После завершения выполнения команды в поле pfrio_size содержится количество адресов, записанных в буфер. Если размер буфера не достаточен, то io-pkt-* не выполняет сохранение и только возвращает требуемый размер буфера, сообщение об ошибке не выводится.
DIOCRGETASTATS struct pfioc_table *io
Эта команда вызывается аналогично DIOCRGETADDRS, но используется для извлечения массива структур pfr_astats:

struct pfr_astats {
struct pfr_addr pfras_a;
u_int64_t pfras_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
u_int64_t pfras_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
long pfras_tzero;
};

DIOCRCLRASTATS struct pfioc_table *io
Удалить статистику по одному или нескольким адресам. При вызове команды в поле pfrio_table содержится идентификатор таблицы, а в поле pfrio_buffer[pfrio_size] – таблица структур pfr_addr, которую требуется очистить. После завершения выполнения команды поле pfrio_nzero содержит количество адресов, статистика по которым успешно удалена.
DIOCRTSTADDRS struct pfioc_table *io
Проверить соответствие адресов значениям в таблице. При запуске команды поле pfrio_table содержит идентификатор таблицы, а поле pfrio_buffer[pfrio_size] – таблицу структур pfr_addr, которые требуется проверить. После завершения выполнения команды io-pkt-* обновляет таблицу pfr_addr путем установки соответствующего значения для элемента pfra_fback.
DIOCRSETTFLAGS struct pfioc_table *io
Изменить флаги таблицы PFR_TFLAG_CONST или PFR_TFLAG_PERSIST. При запуске команды в поле pfrio_buffer[pfrio_size] содержится таблица структур pfr_table, в поле pfrio_setflag – флаги, которые требуется добавить, а в поле pfrio_clrflag – флаги, которые требуется удалить. После завершения выполнения команды в полях pfrio_nchange и pfrio_ndel содержится количество таблиц, измененных или удаленных администратором io-pkt-*.

Note: Таблицы можно удалить путем удаления флага PFR_TFLAG_PERSIST таблицы, ссылка на которую отсутствует.

DIOCRINADEFINE struct pfioc_table *io
Определить таблицу в неактивном наборе. При запуске команды поле pfrio_table содержит идентификатор таблицы, а pfrio_buffer[pfrio_size] – список структур pfr_addr, которые требуется добавить в таблицу. В поле pfrio_ticket также требуется указать действительный мандат. После завершения выполнения команды в поле pfrio_nadd содержится значение 0, если таблица уже определена в неактивном списке, или значение 1, если создана новая таблица. Элемент pfrio_naddr содержит количество адресов, успешно добавленных в таблицу.
DIOCXBEGIN struct pfioc_trans *io
Удалить все неактивные наборы правил, определенные в массиве pfioc_trans_e. Структура pfioc_trans определена следующим образом:

struct pfioc_trans {
int size; /* количество элементов */
int esize; /* размер каждого элемента в байтах */
struct pfioc_trans_e {
int rs_num;
char anchor[MAXPATHLEN];
u_int32_t ticket;
} *array;
};

Для каждого набора правил возвращается мандат для последующего выполнения команд "добавления правила" ioctl_socket(), а также для вызова команд DIOCXCOMMIT и DIOCXROLLBACK. Имеются следующие типы наборов правил, определяемые элементом rs_num:

PF_RULESET_SCRUB
правила очистки (нормализации пакетов).
PF_RULESET_FILTER
правила фильтрации.
PF_RULESET_NAT
правила NAT (Network Address Translation – трансляция сетевых адресов).
PF_RULESET_BINAT
правила двунаправленной трансляции NAT.
PF_RULESET_RDR
правила переадресации.
PF_RULESET_ALTQ
дисциплины ALTQ.
PF_RULESET_TABLE
таблицы адресов.
DIOCXCOMMIT struct pfioc_trans *io
Атомарно переключать вектор неактивных наборов правил на активные наборы правил. Вызов представляет собой стандартную двухфазную фиксацию, которая завершается либо успешно, либо неуспешно для всех наборов правил. Все мандаты должны быть действительными. При одновременном обновлении некоторых наборов правил другим процессом команда ioctl_socket() возвращает EBUSY.
DIOCXROLLBACK struct pfioc_trans *io
Очистить io-pkt-* путем отмены всех изменений, внесенных в неактивные наборы правил с момента последнего вызова команды DIOCXBEGIN. DIOCXROLLBACK игнорирует наборы правил, для которых мандант недействителен, без оповещения.
DIOCSETHOSTID u_int32_t *hostid
Указать идентификатор хоста, используемый pfsync для идентификации хоста, создавшего записи в таблице состояний.
DIOCOSFPFLUSH
Очистить таблицу пассивного отпечатка ОС.
DIOCOSFPADD struct pf_osfp_ioctl *io
Добавить пассивный отпечаток ОС в таблицу. Структура pf_osfp_ioctl определена следующим образом:

struct pf_osfp_ioctl {
struct pf_osfp_entry {
SLIST_ENTRY( pf_osfp_entry ) fp_entry;
pf_osfp_t fp_os;
char fp_class_nm[PF_OSFP_LEN];
char fp_version_nm[PF_OSFP_LEN];
char fp_subtype_nm[PF_OSFP_LEN];
} fp_os;
pf_tcpopts_t fp_tcpopts;
u_int16_t fp_wsize;
u_int16_t fp_psize;
u_int16_t fp_mss;
u_int16_t fp_flags;
u_int8_t fp_optcnt;
u_int8_t fp_wscale;
u_int8_t fp_ttl;
int fp_getnum;
};

В поле fp_os.fp_os указывается упакованный отпечаток, в поле fp_os.fp_class_nm – имя класса (Linux, Windows и т.д.), в поле fp_os.fp_version_nm – имя версии (NT, 95, 98), а в поле fp_os.fp_subtype_nm – имя подтипа или уровня исправлений. Элементы fp_mss, fp_wsize, fp_psize, fp_ttl, fp_optcnt и fp_wscale определяют соответственно максимальный размер сегмента TCP, размер окна TCP, длину IP-пакетов, предельное время существования IP-пакетов, количество опций TCP и константу масштабирования окна TCP для TCP- пакета SYN.

Значения в элемент fp_flags подставляются в соответствии с определением PF_OSFP_* в заголовочном файле <net/pfvar.h>. Элемент fp_tcpopts содержит упакованные опции TCP. Каждая опция использует упакованное значение битов PF_OSFP_TCPOPT_BITS. Варианты опций:

PF_OSFP_TCPOPT_NOP
PF_OSFP_TCPOPT_SACK
PF_OSFP_TCPOPT_WSCALE
PF_OSFP_TCPOPT_MSS
PF_OSFP_TCPOPT_TS


Эта команда ioctl_socket() не использует элемент fp_getnum.

Note: Для корректного выполнения операции необходимо заполнить нулями неиспользуемое пространство структуры; перед определением и отправкой в io-pkt-* следует заполнить нулями всю структуру с помощью memset().

DIOCOSFPGET struct pf_osfp_ioctl *io
Получить номер пассивного отпечатка ОС fp_getnum из списка отпечатков io-pkt-*. Для остальных элементов структуры значения подставляются автоматически. Получить весь список можно путем постепенного увеличения номера fp_getnum до тех пор, пока ioctl_socket() не выдаст ошибку EBUSY.
DIOCGETSRCNODES struct pfioc_src_nodes *psn
Получить список узлов-источников на основе закрепленных адресов и отслеживания источника. Структура pfioc_src_nodes определена следующим образом:

struct pfioc_src_nodes {
int psn_len;
union {
caddr_t psu_buf;
struct pf_src_node *psu_src_nodes;
} psn_u;
#define psn_buf psn_u.psu_buf
#define psn_src_nodes psn_u.psu_src_nodes
};

Необходимо один раз вызвать функцию ioctl_socket() с нулевым значением psn_len. Если ioctl_socket() не возвращает ошибки, в качестве значения psn_len устанавливается размер буфера, необходимого для сохранения всех структур из таблицы pf_src_node. Затем требуется выделить буфер этого размера и установить указатель на этот буфер в psn_buf. Затем необходимо повторно вызвать ioctl_socket() для заполнения буфера актуальными данными из узла-источника. После этого вызова в поле psn_len указывается фактически используемый размер буфера.

DIOCCLRSRCNODES
Удалить дерево узлов отслеживания источника.
DIOCIGETIFACES struct pfioc_iface *io
Получить список интерфейсов и драйверов интерфейсов, известных /dev/pf. Все команды ioctl_socket() для манипулирования интерфейсами имеют следующую структуру:

struct pfioc_iface {
char pfiio_name[IFNAMSIZ];
void *pfiio_buffer;
int pfiio_esize;
int pfiio_size;
int pfiio_nzero;
int pfiio_flags;
};
#define PFI_FLAG_GROUP 0x0001 /* получение групп интерфейсов */
#define PFI_FLAG_INSTANCE 0x0002 /* получение отдельных интерфейсов */
#define PFI_FLAG_ALLMASK 0x0003

Для ограничения поиска определенным интерфейсом или драйвером можно использовать аргумент pfiio_name, если его значение определено. Элемент pfiio_buffer[pfiio_size] представляет собой пользовательский буфер для возврата данных. При запуске команды в поле pfiio_size указывается количество записей pfi_if, вмещаемых буфером. Менеджер io-pkt-* заменяет это значение фактическим количеством возвращаемых записей.

В поле pfiio_esize следует установить значение sizeof( struct pfi_if ). Для возврата администратором io-pkt-* группы интерфейсов (драйверов, например fxp), реальных экземпляров интерфейсов (например, fxp1), или группы интерфейсов и экземпляров для элемента pfiio_flags следует установить значение PFI_FLAG_GROUP, PFI_FLAG_INSTANCE или оба эти значения. Данные, возвращаемые pfi_if, имеют следующую структуру:

struct pfi_if {
char pfif_name[IFNAMSIZ];
u_int64_t pfif_packets[2][2][2];
u_int64_t pfif_bytes[2][2][2];
u_int64_t pfif_addcnt;
u_int64_t pfif_delcnt;
long pfif_tzero;
int pfif_states;
int pfif_rules;
int pfif_flags;
};
#define PFI_IFLAG_GROUP 0x0001 /* группа интерфейсов */
#define PFI_IFLAG_INSTANCE 0x0002 /* один экземпляр */
#define PFI_IFLAG_CLONABLE 0x0010 /* клонируемая группа */
#define PFI_IFLAG_DYNAMIC 0x0020 /* динамическая группа */
#define PFI_IFLAG_ATTACHED 0x0040 /* связанный интерфейс */

DIOCICLRISTATS struct pfioc_iface *io
Удалить счетчики статистики в одном или нескольких интерфейсах. Для выбора интерфейсов, в которых требуется удалить счетчики статистики, используются элементы pfiio_name и pfiio_flags. Процесс фильтрации аналогичен процессу для команды DIOCIGETIFACES. Для элемента pfiio_nzero администратор io-pkt-* устанавливает значение количества интерфейсов и драйверов, для которых удалены счетчики статистики.
DIOCSETIFFLAG struct pfioc_iface *io
Установить пользовательские флаги в описании внутреннего интерфейса /dev/pf:
PFI_IFLAG_SKIP
пропустить интерфейс.

Процесс фильтрации аналогичен процессу для команды DIOCIGETIFACES.
DIOCCLRIFFLAG struct pfioc_iface *io
Аналогично DIOCSETIFFLAG, но удалить флаги.

Примеры:

Пример использования команды DIOCNATLOOK для поиска внутреннего хоста/порта соединения NAT:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
u_int32_t read_address( const char *s )
{
int a, b, c, d;
sscanf( s, "%i.%i.%i.%i", &a, &b, &c, &d );
return htonl( a << 24 | b << 16 | c << 8 | d );
}
void print_address( u_int32_t a )
{
a = ntohl( a );
printf( "%d.%d.%d.%d", a >> 24 & 255, a >> 16 & 255, a >> 8 & 255, a & 255 );
}
int main( int argc, char *argv[] )
{
struct pfioc_natlook nl;
int dev;
if ( argc != 5 )
{
printf( "%s \n", argv[0] );
return (1);
}
dev = open( "/dev/pf", O_RDWR );
if ( dev == -1 )
err( 1, "open(\"/dev/pf\") failed" );
memset( &nl, 0, sizeof( struct pfioc_natlook ) );
nl.saddr.v4.s_addr = read_address( argv[1] );
nl.sport = htons( atoi( argv[2] ) );
nl.daddr.v4.s_addr = read_address( argv[3] );
nl.dport = htons( atoi( argv[4] ) );
nl.af = AF_INET;
nl.proto = IPPROTO_TCP;
nl.direction = PF_IN;
if ( ioctl_socket( dev, DIOCNATLOOK, &nl ) )
err( 1, "DIOCNATLOOK" );
printf( "internal host" );
print_address( nl.rsaddr.v4.s_addr );
printf( ":%u\n", ntohs( nl.rsport ) );
return (0);
}

Предостережения:

В данной версии NetBSD отсутствуют следующие функциональные возможности /dev/pf:

Классификация:

Базовые подсистемы ЗОСРВ «Нейтрино», NetBSD

Тематические ссылки:

io-pkt-*, pfctl

ioctl(), ioctl_socket()




Предыдущий раздел: Сервисы