version 1.3, 2008/06/29 08:42:15 |
version 1.4, 2008/07/16 10:23:39 |
|
|
* |
* |
*/ |
*/ |
|
|
#include "config.h" |
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
|
|
#include <net/pfvar.h> |
#include <net/pfvar.h> |
#include <arpa/inet.h> |
#include <arpa/inet.h> |
|
|
#ifdef HAVE_ALTQ |
|
#include <altq/altq.h> |
#include <altq/altq.h> |
#include <altq/altq_cbq.h> |
#include <altq/altq_cbq.h> |
#include <altq/altq_priq.h> |
#include <altq/altq_priq.h> |
#include <altq/altq_hfsc.h> |
#include <altq/altq_hfsc.h> |
#endif |
|
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <curses.h> |
#include <curses.h> |
|
|
|
|
#define DEFAULT_CACHE_SIZE 10000 |
#define DEFAULT_CACHE_SIZE 10000 |
|
|
#ifndef HAVE_PROTO_NAMES |
|
/* UDP state enumeration */ |
|
#define PFUDPS_NSTATES 3 /* number of state levels */ |
|
|
|
#define PFUDPS_NAMES { \ |
|
"NO TRAFFIC", \ |
|
"SINGLE", \ |
|
"MULTIPLE", \ |
|
NULL \ |
|
} |
|
|
|
/* Other protocol state enumeration */ |
|
#define PFOTHERS_NSTATES 3 /* number of state levels */ |
|
|
|
#define PFOTHERS_NAMES { \ |
|
"NO TRAFFIC", \ |
|
"SINGLE", \ |
|
"MULTIPLE", \ |
|
NULL \ |
|
} |
|
#endif |
|
|
|
#ifdef HAVE_ADDR_WRAP |
|
#ifdef HAVE_ADDR_TYPE |
|
/* XXX must also check type before use */ |
/* XXX must also check type before use */ |
#define PT_ADDR(x) (&(x)->addr.v.a.addr) |
#define PT_ADDR(x) (&(x)->addr.v.a.addr) |
#else |
|
#define PT_ADDR(x) (&(x)->addr.addr) |
|
#endif |
|
#else |
|
#define PT_ADDR(x) (&(x)->addr) |
|
#endif |
|
|
|
#ifdef HAVE_ADDR_MASK |
|
#ifdef HAVE_ADDR_TYPE |
|
/* XXX must also check type before use */ |
/* XXX must also check type before use */ |
#define PT_MASK(x) (&(x)->addr.v.a.mask) |
#define PT_MASK(x) (&(x)->addr.v.a.mask) |
#else |
|
#define PT_MASK(x) (&(x)->addr.mask) |
|
#endif |
|
#else |
|
#define PT_MASK(x) (&(x)->mask) |
|
#endif |
|
|
|
#ifdef HAVE_STATE_NOROUTE |
|
#ifdef HAVE_ADDR_TYPE |
|
#define PT_NOROUTE(x) ((x)->addr.type == PF_ADDR_NOROUTE) |
#define PT_NOROUTE(x) ((x)->addr.type == PF_ADDR_NOROUTE) |
#else |
|
#define PT_NOROUTE(x) ((x)->noroute) |
|
#endif |
|
#else |
|
#define PT_NOROUTE(x) (0) |
|
#endif |
|
|
|
/* view management */ |
/* view management */ |
int select_states(void); |
int select_states(void); |
|
|
int print_header(void); |
int print_header(void); |
int keyboard_callback(int ch); |
int keyboard_callback(int ch); |
|
|
#ifdef HAVE_ALTQ |
|
int select_queues(void); |
int select_queues(void); |
int read_queues(void); |
int read_queues(void); |
void print_queues(void); |
void print_queues(void); |
#endif |
|
|
|
/* qsort callbacks */ |
/* qsort callbacks */ |
int sort_size_callback(const void *s1, const void *s2); |
int sort_size_callback(const void *s1, const void *s2); |
|
|
int pf_dev = -1; |
int pf_dev = -1; |
|
|
struct sc_ent **state_cache = NULL; |
struct sc_ent **state_cache = NULL; |
pf_state_t *state_buf = NULL; |
struct pfsync_state *state_buf = NULL; |
int state_buf_len = 0; |
int state_buf_len = 0; |
u_int32_t *state_ord = NULL; |
u_int32_t *state_ord = NULL; |
u_int32_t num_states = 0; |
u_int32_t num_states = 0; |
|
|
char *filter_string = NULL; |
char *filter_string = NULL; |
int dumpfilter = 0; |
int dumpfilter = 0; |
|
|
#ifndef HAVE_RULE_LABELS |
|
#define PF_RULE_LABEL_SIZE 20 |
|
#endif |
|
|
|
#define MIN_LABEL_SIZE 5 |
#define MIN_LABEL_SIZE 5 |
#define ANCHOR_FLD_SIZE 12 |
#define ANCHOR_FLD_SIZE 12 |
|
|
|
|
{"KS", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"KS", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"IF", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"IF", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"INFO", 40, 80, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"INFO", 40, 80, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"MAX", 3, 5, 2, FLD_ALIGN_RIGHT, -1, 0, FLD_FLAG_HIDDEN, 0}, |
{"MAX", 3, 5, 2, FLD_ALIGN_RIGHT, -1, 0, 0}, |
{"RATE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"RATE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"AVG", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"AVG", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"PEAK", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"PEAK", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"ANCHOR", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, FLD_FLAG_HIDDEN, 0}, |
{"ANCHOR", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0}, |
{"QUEUE", 15, 30, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"QUEUE", 15, 30, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"BW", 4, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"BW", 4, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
{"SCH", 3, 4, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
{"SCH", 3, 4, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
|
|
print_rules, keyboard_callback, NULL, NULL |
print_rules, keyboard_callback, NULL, NULL |
}; |
}; |
|
|
#ifdef HAVE_ALTQ |
|
struct view_manager queue_mgr = { |
struct view_manager queue_mgr = { |
"Queues", select_queues, read_queues, NULL, print_header, |
"Queues", select_queues, read_queues, NULL, print_header, |
print_queues, keyboard_callback, NULL, NULL |
print_queues, keyboard_callback, NULL, NULL |
}; |
}; |
#endif |
|
|
|
field_view views[] = { |
field_view views[] = { |
{view2, "states", '8', &state_mgr}, |
{view2, "states", '8', &state_mgr}, |
|
|
|
|
/* altq structures from pfctl */ |
/* altq structures from pfctl */ |
|
|
#ifdef HAVE_ALTQ |
|
union class_stats { |
union class_stats { |
class_stats_t cbq_stats; |
class_stats_t cbq_stats; |
struct priq_classstats priq_stats; |
struct priq_classstats priq_stats; |
|
|
u_int8_t depth; |
u_int8_t depth; |
u_int8_t visited; |
u_int8_t visited; |
}; |
}; |
#endif /* HAVE_ALTQ */ |
|
|
|
|
|
/* ordering functions */ |
/* ordering functions */ |
|
|
int |
int |
sort_size_callback(const void *s1, const void *s2) |
sort_size_callback(const void *s1, const void *s2) |
{ |
{ |
#ifdef HAVE_INOUT_COUNT |
|
u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes[0]) + |
u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes[0]) + |
COUNTER(state_buf[* (u_int32_t *) s1].bytes[1]); |
COUNTER(state_buf[* (u_int32_t *) s1].bytes[1]); |
u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes[0]) + |
u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes[0]) + |
COUNTER(state_buf[* (u_int32_t *) s2].bytes[1]); |
COUNTER(state_buf[* (u_int32_t *) s2].bytes[1]); |
#else |
|
u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes); |
|
u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes); |
|
#endif |
|
if (b2 > b1) |
if (b2 > b1) |
return sortdir; |
return sortdir; |
if (b2 < b1) |
if (b2 < b1) |
|
|
int |
int |
sort_pkt_callback(const void *s1, const void *s2) |
sort_pkt_callback(const void *s1, const void *s2) |
{ |
{ |
#ifdef HAVE_INOUT_COUNT |
|
u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets[0]) + |
u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets[0]) + |
COUNTER(state_buf[* (u_int32_t *) s1].packets[1]); |
COUNTER(state_buf[* (u_int32_t *) s1].packets[1]); |
u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets[0]) + |
u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets[0]) + |
COUNTER(state_buf[* (u_int32_t *) s2].packets[1]); |
COUNTER(state_buf[* (u_int32_t *) s2].packets[1]); |
#else |
|
u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets); |
|
u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets); |
|
#endif |
|
if (p2 > p1) |
if (p2 > p1) |
return sortdir; |
return sortdir; |
if (p2 < p1) |
if (p2 < p1) |
|
|
return 0; |
return 0; |
} |
} |
|
|
#ifdef HAVE_PFSYNC_KEY |
__inline int |
|
sort_addr_callback(const struct pfsync_state *s1, |
#ifdef __GNUC__ |
const struct pfsync_state *s2, int dir) |
__inline__ |
|
#endif |
|
int |
|
sort_addr_callback(const pf_state_t *s1, |
|
const pf_state_t *s2, int dir) |
|
{ |
{ |
const struct pf_addr *aa, *ab; |
const struct pf_addr *aa, *ab; |
u_int16_t pa, pb; |
u_int16_t pa, pb; |
|
|
return -sortdir; |
return -sortdir; |
} |
} |
|
|
#ifdef __GNUC__ |
__inline int |
__inline__ |
sort_port_callback(const struct pfsync_state *s1, |
#endif |
const struct pfsync_state *s2, int dir) |
int |
|
sort_port_callback(const pf_state_t *s1, |
|
const pf_state_t *s2, int dir) |
|
{ |
{ |
const struct pf_addr *aa, *ab; |
const struct pf_addr *aa, *ab; |
u_int16_t pa, pb; |
u_int16_t pa, pb; |
|
|
return -sortdir; |
return -sortdir; |
} |
} |
|
|
#else /* HAVE_PFSYNC_KEY */ |
|
|
|
#ifdef __GNUC__ |
|
__inline__ |
|
#endif |
|
int |
int |
sort_addr_callback(const pf_state_t *s1, |
sort_sa_callback(const void *p1, const void *p2) |
const pf_state_t *s2, int dir) |
|
{ |
{ |
const pf_state_host_t *a, *b; |
struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1); |
int af, ret; |
struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2); |
|
return sort_addr_callback(s1, s2, PF_OUT); |
af = s1->af; |
|
|
|
if (af > s2->af) |
|
return sortdir; |
|
if (af < s2->af) |
|
return -sortdir; |
|
|
|
if (s1->direction == dir) { |
|
a = &s1->lan; |
|
} else { |
|
a = &s1->ext; |
|
} |
|
|
|
if (s2->direction == dir) { |
|
b = &s2->lan; |
|
} else { |
|
b = &s2->ext; |
|
} |
|
|
|
ret = compare_addr(af, &a->addr, &b->addr); |
|
if (ret) |
|
return ret * sortdir; |
|
|
|
if (ntohs(a->port) > ntohs(b->port)) |
|
return sortdir; |
|
return -sortdir; |
|
} |
} |
|
|
#ifdef __GNUC__ |
|
__inline__ |
|
#endif |
|
int |
int |
sort_port_callback(const pf_state_t *s1, |
sort_da_callback(const void *p1, const void *p2) |
const pf_state_t *s2, int dir) |
|
{ |
{ |
const pf_state_host_t *a, *b; |
struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1); |
int af; |
struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2); |
|
|
af = s1->af; |
|
|
|
if (af > s2->af) |
|
return sortdir; |
|
if (af < s2->af) |
|
return -sortdir; |
|
|
|
if (s1->direction == dir) { |
|
a = &s1->lan; |
|
} else { |
|
a = &s1->ext; |
|
} |
|
|
|
if (s2->direction == dir) { |
|
b = &s2->lan; |
|
} else { |
|
b = &s2->ext; |
|
} |
|
|
|
if (ntohs(a->port) > ntohs(b->port)) |
|
return sortdir; |
|
if (ntohs(a->port) < ntohs(b->port)) |
|
return -sortdir; |
|
|
|
if (compare_addr(af, &a->addr, &b->addr) > 0) |
|
return sortdir; |
|
return -sortdir; |
|
} |
|
#endif /* HAVE_PFSYNC_KEY */ |
|
|
|
int sort_sa_callback(const void *p1, const void *p2) |
|
{ |
|
pf_state_t *s1 = state_buf + (* (u_int32_t *) p1); |
|
pf_state_t *s2 = state_buf + (* (u_int32_t *) p2); |
|
return sort_addr_callback(s1, s2, PF_OUT); |
|
} |
|
|
|
int sort_da_callback(const void *p1, const void *p2) |
|
{ |
|
pf_state_t *s1 = state_buf + (* (u_int32_t *) p1); |
|
pf_state_t *s2 = state_buf + (* (u_int32_t *) p2); |
|
return sort_addr_callback(s1, s2, PF_IN); |
return sort_addr_callback(s1, s2, PF_IN); |
} |
} |
|
|
int |
int |
sort_sp_callback(const void *p1, const void *p2) |
sort_sp_callback(const void *p1, const void *p2) |
{ |
{ |
pf_state_t *s1 = state_buf + (* (u_int32_t *) p1); |
struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1); |
pf_state_t *s2 = state_buf + (* (u_int32_t *) p2); |
struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2); |
return sort_port_callback(s1, s2, PF_OUT); |
return sort_port_callback(s1, s2, PF_OUT); |
} |
} |
|
|
int |
int |
sort_dp_callback(const void *p1, const void *p2) |
sort_dp_callback(const void *p1, const void *p2) |
{ |
{ |
pf_state_t *s1 = state_buf + (* (u_int32_t *) p1); |
struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1); |
pf_state_t *s2 = state_buf + (* (u_int32_t *) p2); |
struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2); |
return sort_port_callback(s1, s2, PF_IN); |
return sort_port_callback(s1, s2, PF_IN); |
} |
} |
|
|
|
|
|
|
if (len >= state_buf_len) { |
if (len >= state_buf_len) { |
len += NUM_STATE_INC; |
len += NUM_STATE_INC; |
state_buf = realloc(state_buf, len * sizeof(pf_state_t)); |
state_buf = realloc(state_buf, len * sizeof(struct pfsync_state)); |
state_ord = realloc(state_ord, len * sizeof(u_int32_t)); |
state_ord = realloc(state_ord, len * sizeof(u_int32_t)); |
state_cache = realloc(state_cache, |
state_cache = realloc(state_cache, |
len * sizeof(struct sc_ent *)); |
len * sizeof(struct sc_ent *)); |
|
|
return -1; |
return -1; |
|
|
for (;;) { |
for (;;) { |
int sbytes = state_buf_len * sizeof(pf_state_t); |
int sbytes = state_buf_len * sizeof(struct pfsync_state); |
|
|
ps.ps_len = sbytes; |
ps.ps_len = sbytes; |
ps.ps_buf = (char *) state_buf; |
ps.ps_buf = (char *) state_buf; |
|
|
if (ioctl(pf_dev, DIOCGETSTATES, &ps) < 0) { |
if (ioctl(pf_dev, DIOCGETSTATES, &ps) < 0) { |
error("DIOCGETSTATES"); |
error("DIOCGETSTATES"); |
} |
} |
num_states_all = ps.ps_len / sizeof(pf_state_t); |
num_states_all = ps.ps_len / sizeof(struct pfsync_state); |
|
|
if (ps.ps_len < sbytes) |
if (ps.ps_len < sbytes) |
break; |
break; |
|
|
tbprintf("/%u", unmask(mask, af)); |
tbprintf("/%u", unmask(mask, af)); |
} |
} |
} |
} |
#ifdef HAVE_PFSYNC_KEY |
|
void |
void |
print_fld_host2(field_def *fld, struct pfsync_state_key *ks, |
print_fld_host2(field_def *fld, struct pfsync_state_key *ks, |
struct pfsync_state_key *kn, int idx, int af) |
struct pfsync_state_key *kn, int idx, int af) |
|
|
} |
} |
|
|
} |
} |
#else |
|
void |
|
print_fld_host(field_def *fld, pf_state_host_t * h, int af) |
|
{ |
|
u_int16_t p = ntohs(h->port); |
|
|
|
if (fld == NULL) |
|
return; |
|
|
|
if (fld->width < 3) { |
|
print_fld_str(fld, "*"); |
|
return; |
|
} |
|
|
|
tb_start(); |
|
tb_print_addr(&h->addr, NULL, af); |
|
|
|
if (af == AF_INET) |
|
tbprintf(":%u", p); |
|
else |
|
tbprintf("[%u]", p); |
|
|
|
print_fld_tb(fld); |
|
} |
|
#endif |
|
|
|
void |
void |
print_fld_state(field_def *fld, unsigned int proto, |
print_fld_state(field_def *fld, unsigned int proto, |
unsigned int s1, unsigned int s2) |
unsigned int s1, unsigned int s2) |
|
|
} |
} |
|
|
int |
int |
print_state(pf_state_t * s, struct sc_ent * ent) |
print_state(struct pfsync_state * s, struct sc_ent * ent) |
{ |
{ |
pf_state_peer_t *src, *dst; |
struct pfsync_state_peer *src, *dst; |
struct protoent *p; |
struct protoent *p; |
|
u_int64_t sz; |
|
|
if (s->direction == PF_OUT) { |
if (s->direction == PF_OUT) { |
src = &s->src; |
src = &s->src; |
|
|
else |
else |
print_fld_uint(FLD_PROTO, s->proto); |
print_fld_uint(FLD_PROTO, s->proto); |
|
|
#ifdef HAVE_PFSYNC_KEY |
|
if (s->direction == PF_OUT) { |
if (s->direction == PF_OUT) { |
print_fld_host2(FLD_SRC, &s->key[PF_SK_WIRE], |
print_fld_host2(FLD_SRC, &s->key[PF_SK_WIRE], |
&s->key[PF_SK_STACK], 1, s->af); |
&s->key[PF_SK_STACK], 1, s->af); |
|
|
print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK], |
print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK], |
&s->key[PF_SK_WIRE], 1, s->af); |
&s->key[PF_SK_WIRE], 1, s->af); |
} |
} |
#else |
|
if (s->direction == PF_OUT) { |
|
print_fld_host(FLD_SRC, &s->lan, s->af); |
|
print_fld_host(FLD_DEST, &s->ext, s->af); |
|
} else { |
|
print_fld_host(FLD_SRC, &s->ext, s->af); |
|
print_fld_host(FLD_DEST, &s->lan, s->af); |
|
} |
|
|
|
if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) || |
|
(s->lan.port != s->gwy.port)) { |
|
print_fld_host(FLD_GW, &s->gwy, s->af); |
|
} |
|
#endif |
|
|
|
if (s->direction == PF_OUT) |
if (s->direction == PF_OUT) |
print_fld_str(FLD_DIR, "Out"); |
print_fld_str(FLD_DIR, "Out"); |
else |
else |
|
|
print_fld_state(FLD_STATE, s->proto, src->state, dst->state); |
print_fld_state(FLD_STATE, s->proto, src->state, dst->state); |
print_fld_age(FLD_AGE, ntohl(s->creation)); |
print_fld_age(FLD_AGE, ntohl(s->creation)); |
print_fld_age(FLD_EXP, ntohl(s->expire)); |
print_fld_age(FLD_EXP, ntohl(s->expire)); |
#ifdef HAVE_INOUT_COUNT |
|
{ |
|
u_int64_t sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]); |
|
|
|
print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) + |
sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]); |
COUNTER(s->packets[1])); |
|
print_fld_size(FLD_BYTES, sz); |
print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) + |
print_fld_rate(FLD_SA, (s->creation) ? |
COUNTER(s->packets[1])); |
((double)sz/ntohl((double)s->creation)) : -1); |
print_fld_size(FLD_BYTES, sz); |
} |
|
#else |
|
print_fld_size(FLD_PKTS, s->packets); |
|
print_fld_size(FLD_BYTES, s->bytes); |
|
print_fld_rate(FLD_SA, (s->creation) ? |
print_fld_rate(FLD_SA, (s->creation) ? |
((double)s->bytes/ntohl((double)s->creation)) : -1); |
((double)sz/ntohl((double)s->creation)) : -1); |
|
|
#endif |
|
#ifdef HAVE_PFSYNC_STATE |
|
print_fld_uint(FLD_RULE, s->rule); |
print_fld_uint(FLD_RULE, s->rule); |
#else |
|
#ifdef HAVE_RULE_NUMBER |
|
print_fld_uint(FLD_RULE, s->rule.nr); |
|
#endif |
|
#endif |
|
if (cachestates && ent != NULL) { |
if (cachestates && ent != NULL) { |
print_fld_rate(FLD_SI, ent->rate); |
print_fld_rate(FLD_SI, ent->rate); |
print_fld_rate(FLD_SP, ent->peak); |
print_fld_rate(FLD_SP, ent->peak); |
|
|
} |
} |
} |
} |
|
|
#ifdef HAVE_RULE_LABELS |
|
int label_length; |
int label_length; |
#endif |
|
|
|
int |
int |
read_anchor_rules(char *anchor) |
read_anchor_rules(char *anchor) |
{ |
{ |
struct pfioc_rule pr; |
struct pfioc_rule pr; |
u_int32_t nr, num, off; |
u_int32_t nr, num, off; |
|
int len; |
|
|
if (pf_dev < 0) |
if (pf_dev < 0) |
return (-1); |
return (-1); |
|
|
memset(&pr, 0, sizeof(pr)); |
memset(&pr, 0, sizeof(pr)); |
#ifdef HAVE_RULESETS |
|
strlcpy(pr.anchor, anchor, sizeof(pr.anchor)); |
strlcpy(pr.anchor, anchor, sizeof(pr.anchor)); |
#endif |
|
if (ioctl(pf_dev, DIOCGETRULES, &pr)) { |
if (ioctl(pf_dev, DIOCGETRULES, &pr)) { |
error("anchor %s: %s", anchor, strerror(errno)); |
error("anchor %s: %s", anchor, strerror(errno)); |
return (-1); |
return (-1); |
|
|
error("DIOCGETRULE: %s", strerror(errno)); |
error("DIOCGETRULE: %s", strerror(errno)); |
return (-1); |
return (-1); |
} |
} |
#ifdef HAVE_RULESETS |
|
/* XXX overload pr.anchor, to store a pointer to |
/* XXX overload pr.anchor, to store a pointer to |
* anchor name */ |
* anchor name */ |
pr.rule.anchor = (struct pf_anchor *) anchor; |
pr.rule.anchor = (struct pf_anchor *) anchor; |
#endif |
len = strlen(pr.rule.label); |
#ifdef HAVE_RULE_LABELS |
if (len > label_length) |
{ |
label_length = len; |
int len = strlen(pr.rule.label); |
|
if (len > label_length) |
|
label_length = len; |
|
} |
|
#endif |
|
rules[off + nr] = pr.rule; |
rules[off + nr] = pr.rule; |
} |
} |
|
|
return (num); |
return (num); |
} |
} |
|
|
#ifdef HAVE_RULESETS |
|
struct anchor_name { |
struct anchor_name { |
char name[MAXPATHLEN]; |
char name[MAXPATHLEN]; |
struct anchor_name *next; |
struct anchor_name *next; |
|
|
need_update = 1; |
need_update = 1; |
} |
} |
} |
} |
#endif |
|
|
|
int |
int |
read_rules(void) |
read_rules(void) |
{ |
{ |
int ret; |
int ret, nw, mw; |
num_rules = 0; |
num_rules = 0; |
|
|
if (pf_dev == -1) |
if (pf_dev == -1) |
return (-1); |
return (-1); |
|
|
#ifdef HAVE_RULE_LABELS |
|
label_length = MIN_LABEL_SIZE; |
label_length = MIN_LABEL_SIZE; |
#endif |
|
|
|
#ifdef HAVE_RULESETS |
|
reset_anchor_names(); |
reset_anchor_names(); |
ret = read_rulesets(NULL); |
ret = read_rulesets(NULL); |
compute_anchor_field(); |
compute_anchor_field(); |
#else |
|
ret = read_anchor_rules(NULL); |
|
#endif |
|
|
|
#ifdef HAVE_RULE_LABELS |
nw = mw = label_length; |
{ |
if (nw > 16) |
int nw, mw; |
nw = 16; |
nw = mw = label_length; |
|
if (nw > 16) |
|
nw = 16; |
|
|
|
if (FLD_LABEL->norm_width != nw || |
if (FLD_LABEL->norm_width != nw || |
FLD_LABEL->max_width != mw) { |
FLD_LABEL->max_width != mw) { |
FLD_LABEL->norm_width = nw; |
FLD_LABEL->norm_width = nw; |
FLD_LABEL->max_width = mw; |
FLD_LABEL->max_width = mw; |
field_setup(); |
field_setup(); |
need_update = 1; |
need_update = 1; |
} |
|
} |
} |
#endif |
|
|
|
num_disp = num_rules; |
num_disp = num_rules; |
return (ret); |
return (ret); |
} |
} |
|
|
#ifdef HAVE_ADDR_WRAP |
|
void |
void |
tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af) |
tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af) |
{ |
{ |
#ifdef HAVE_ADDR_TYPE |
|
switch (addr->type) { |
switch (addr->type) { |
case PF_ADDR_ADDRMASK: |
case PF_ADDR_ADDRMASK: |
tb_print_addr(&addr->v.a.addr, mask, af); |
tb_print_addr(&addr->v.a.addr, mask, af); |
|
|
tbprintf("UNKNOWN"); |
tbprintf("UNKNOWN"); |
break; |
break; |
} |
} |
#else |
|
if (addr->addr_dyn != NULL) |
|
tbprintf("(%s)", addr->addr.pfa.ifname); |
|
else |
|
tb_print_addr(&addr->addr, mask, af); |
|
#endif |
|
} |
} |
#endif |
|
|
|
void |
void |
tb_print_op(u_int8_t op, const char *a1, const char *a2) |
tb_print_op(u_int8_t op, const char *a1, const char *a2) |
|
|
tbprintf("%s >< %s ", a1, a2); |
tbprintf("%s >< %s ", a1, a2); |
else if (op == PF_OP_XRG) |
else if (op == PF_OP_XRG) |
tbprintf("%s <> %s ", a1, a2); |
tbprintf("%s <> %s ", a1, a2); |
#ifdef HAVE_OP_RRG |
|
else if (op == PF_OP_RRG) |
else if (op == PF_OP_RRG) |
tbprintf("%s:%s ", a1, a2); |
tbprintf("%s:%s ", a1, a2); |
#endif |
|
else if (op == PF_OP_EQ) |
else if (op == PF_OP_EQ) |
tbprintf("= %s ", a1); |
tbprintf("= %s ", a1); |
else if (op == PF_OP_NE) |
else if (op == PF_OP_NE) |
|
|
PF_AZERO(PT_MASK(src), AF_INET6)) |
PF_AZERO(PT_MASK(src), AF_INET6)) |
tbprintf("any "); |
tbprintf("any "); |
else { |
else { |
#ifdef HAVE_NEG |
|
if (src->neg) |
if (src->neg) |
#else |
|
if (src->not) |
|
#endif |
|
tbprintf("! "); |
tbprintf("! "); |
#ifdef HAVE_ADDR_WRAP |
|
tb_print_addrw(&src->addr, PT_MASK(src), af); |
tb_print_addrw(&src->addr, PT_MASK(src), af); |
#else |
|
tb_print_addr(&src->addr, PT_MASK(src), af); |
|
#endif |
|
tbprintf(" "); |
tbprintf(" "); |
} |
} |
if (src->port_op) |
if (src->port_op) |
|
|
PF_AZERO(PT_MASK(dst), AF_INET6)) |
PF_AZERO(PT_MASK(dst), AF_INET6)) |
tbprintf("any "); |
tbprintf("any "); |
else { |
else { |
#ifdef HAVE_NEG |
|
if (dst->neg) |
if (dst->neg) |
#else |
|
if (dst->not) |
|
#endif |
|
tbprintf("! "); |
tbprintf("! "); |
#ifdef HAVE_ADDR_WRAP |
|
tb_print_addrw(&dst->addr, PT_MASK(dst), af); |
tb_print_addrw(&dst->addr, PT_MASK(dst), af); |
#else |
|
tb_print_addr(&dst->addr, PT_MASK(dst), af); |
|
#endif |
|
tbprintf(" "); |
tbprintf(" "); |
} |
} |
if (dst->port_op) |
if (dst->port_op) |
|
|
} |
} |
} |
} |
|
|
#ifdef HAVE_RULE_UGID |
|
void |
void |
tb_print_ugid(u_int8_t op, unsigned u1, unsigned u2, |
tb_print_ugid(u_int8_t op, unsigned u1, unsigned u2, |
const char *t, unsigned umax) |
const char *t, unsigned umax) |
|
|
else |
else |
tb_print_op(op, a1, a2); |
tb_print_op(op, a1, a2); |
} |
} |
#endif |
|
|
|
void |
void |
tb_print_flags(u_int8_t f) |
tb_print_flags(u_int8_t f) |
|
|
"no Nat", "Binat", "no Binat", "Rdr", "no Rdr" }; |
"no Nat", "Binat", "no Binat", "Rdr", "no Rdr" }; |
int numact = sizeof(actiontypes) / sizeof(char *); |
int numact = sizeof(actiontypes) / sizeof(char *); |
|
|
#ifdef HAVE_PF_ROUTE |
|
static const char *routetypes[] = { "", "fastroute", "route-to", |
static const char *routetypes[] = { "", "fastroute", "route-to", |
"dup-to", "reply-to" }; |
"dup-to", "reply-to" }; |
|
|
int numroute = sizeof(routetypes) / sizeof(char *); |
int numroute = sizeof(routetypes) / sizeof(char *); |
#endif |
|
|
|
if (pr == NULL) return; |
if (pr == NULL) return; |
|
|
#ifdef HAVE_RULE_LABELS |
|
print_fld_str(FLD_LABEL, pr->label); |
print_fld_str(FLD_LABEL, pr->label); |
#endif |
|
#ifdef HAVE_RULE_STATES |
|
#ifdef HAVE_PFSYNC_KEY |
|
print_fld_size(FLD_STATS, pr->states_tot); |
print_fld_size(FLD_STATS, pr->states_tot); |
#else |
|
print_fld_size(FLD_STATS, pr->states); |
|
#endif |
|
#endif |
|
|
|
#ifdef HAVE_INOUT_COUNT_RULES |
|
print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]); |
print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]); |
print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]); |
print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]); |
#else |
|
print_fld_size(FLD_PKTS, pr->packets); |
|
print_fld_size(FLD_BYTES, pr->bytes); |
|
#endif |
|
print_fld_uint(FLD_RULE, pr->nr); |
print_fld_uint(FLD_RULE, pr->nr); |
print_fld_str(FLD_DIR, pr->direction == PF_OUT ? "Out" : "In"); |
print_fld_str(FLD_DIR, pr->direction == PF_OUT ? "Out" : "In"); |
if (pr->quick) |
if (pr->quick) |
|
|
|
|
if (pr->ifname[0]) { |
if (pr->ifname[0]) { |
tb_start(); |
tb_start(); |
#ifdef HAVE_RULE_IFNOT |
|
if (pr->ifnot) |
if (pr->ifnot) |
tbprintf("!"); |
tbprintf("!"); |
#endif |
|
tbprintf("%s", pr->ifname); |
tbprintf("%s", pr->ifname); |
print_fld_tb(FLD_IF); |
print_fld_tb(FLD_IF); |
} |
} |
#ifdef HAVE_MAX_STATES |
|
if (pr->max_states) |
if (pr->max_states) |
print_fld_uint(FLD_STMAX, pr->max_states); |
print_fld_uint(FLD_STMAX, pr->max_states); |
#endif |
|
/* print info field */ |
/* print info field */ |
|
|
tb_start(); |
tb_start(); |
|
|
#ifdef HAVE_RULE_NATPASS |
|
if (pr->natpass) |
if (pr->natpass) |
tbprintf("pass "); |
tbprintf("pass "); |
#endif |
|
if (pr->action == PF_DROP) { |
if (pr->action == PF_DROP) { |
if (pr->rule_flag & PFRULE_RETURNRST) |
if (pr->rule_flag & PFRULE_RETURNRST) |
tbprintf("return-rst "); |
tbprintf("return-rst "); |
|
|
tbprintf("drop "); |
tbprintf("drop "); |
} |
} |
|
|
#ifdef HAVE_PF_ROUTE |
|
if (pr->rt > 0 && pr->rt < numroute) { |
if (pr->rt > 0 && pr->rt < numroute) { |
tbprintf("%s ", routetypes[pr->rt]); |
tbprintf("%s ", routetypes[pr->rt]); |
if (pr->rt != PF_FASTROUTE) |
if (pr->rt != PF_FASTROUTE) |
tbprintf("... "); |
tbprintf("... "); |
} |
} |
#endif |
|
if (pr->af) { |
if (pr->af) { |
if (pr->af == AF_INET) |
if (pr->af == AF_INET) |
tbprintf("inet "); |
tbprintf("inet "); |
|
|
} |
} |
|
|
tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto); |
tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto); |
#ifdef HAVE_RULE_UGID |
|
if (pr->uid.op) |
if (pr->uid.op) |
tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1], |
tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1], |
"user", UID_MAX); |
"user", UID_MAX); |
if (pr->gid.op) |
if (pr->gid.op) |
tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1], |
tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1], |
"group", GID_MAX); |
"group", GID_MAX); |
#endif |
|
|
|
if (pr->flags || pr->flagset) { |
if (pr->flags || pr->flagset) { |
tbprintf(" flags "); |
tbprintf(" flags "); |
|
|
|
|
tbprintf(" "); |
tbprintf(" "); |
|
|
#ifdef HAVE_RULE_TOS |
|
if (pr->tos) |
if (pr->tos) |
tbprintf("tos 0x%2.2x ", pr->tos); |
tbprintf("tos 0x%2.2x ", pr->tos); |
#endif |
|
#ifdef PFRULE_FRAGMENT |
#ifdef PFRULE_FRAGMENT |
if (pr->rule_flag & PFRULE_FRAGMENT) |
if (pr->rule_flag & PFRULE_FRAGMENT) |
tbprintf("fragment "); |
tbprintf("fragment "); |
|
|
#endif |
#endif |
if (pr->min_ttl) |
if (pr->min_ttl) |
tbprintf("min-ttl %d ", pr->min_ttl); |
tbprintf("min-ttl %d ", pr->min_ttl); |
#ifdef HAVE_MAX_MSS |
|
if (pr->max_mss) |
if (pr->max_mss) |
tbprintf("max-mss %d ", pr->max_mss); |
tbprintf("max-mss %d ", pr->max_mss); |
#endif |
|
if (pr->allow_opts) |
if (pr->allow_opts) |
tbprintf("allow-opts "); |
tbprintf("allow-opts "); |
|
|
|
|
tbprintf("fragment reassemble "); |
tbprintf("fragment reassemble "); |
} |
} |
|
|
#ifdef HAVE_ALTQ |
|
if (pr->qname[0] && pr->pqname[0]) |
if (pr->qname[0] && pr->pqname[0]) |
tbprintf("queue(%s, %s) ", pr->qname, pr->pqname); |
tbprintf("queue(%s, %s) ", pr->qname, pr->pqname); |
else if (pr->qname[0]) |
else if (pr->qname[0]) |
tbprintf("queue %s ", pr->qname); |
tbprintf("queue %s ", pr->qname); |
#endif |
|
#ifdef HAVE_TAGS |
|
if (pr->tagname[0]) |
if (pr->tagname[0]) |
tbprintf("tag %s ", pr->tagname); |
tbprintf("tag %s ", pr->tagname); |
if (pr->match_tagname[0]) { |
if (pr->match_tagname[0]) { |
|
|
tbprintf("! "); |
tbprintf("! "); |
tbprintf("tagged %s ", pr->match_tagname); |
tbprintf("tagged %s ", pr->match_tagname); |
} |
} |
#endif |
|
print_fld_tb(FLD_RINFO); |
print_fld_tb(FLD_RINFO); |
|
|
#ifdef HAVE_RULESETS |
|
/* XXX anchor field overloaded with anchor name */ |
/* XXX anchor field overloaded with anchor name */ |
print_fld_str(FLD_ANCHOR, (char *)pr->anchor); |
print_fld_str(FLD_ANCHOR, (char *)pr->anchor); |
#endif |
|
tb_end(); |
tb_end(); |
|
|
end_line(); |
end_line(); |
|
|
|
|
/* queue display */ |
/* queue display */ |
|
|
#ifdef HAVE_ALTQ |
|
|
|
struct pf_altq_node * |
struct pf_altq_node * |
pfctl_find_altq_node(struct pf_altq_node *root, const char *qname, |
pfctl_find_altq_node(struct pf_altq_node *root, const char *qname, |
const char *ifname) |
const char *ifname) |
|
|
} |
} |
} |
} |
|
|
#endif /* HAVE_ALTQ */ |
|
|
|
/* main program functions */ |
/* main program functions */ |
|
|
void |
void |
|
|
|
|
update_cache(); |
update_cache(); |
|
|
#ifdef HAVE_MAX_STATES |
|
show_field(FLD_STMAX); |
show_field(FLD_STMAX); |
#endif |
|
#ifdef HAVE_RULESETS |
|
show_field(FLD_ANCHOR); |
show_field(FLD_ANCHOR); |
#endif |
|
|
|
} |
} |