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
|
/*
* The rule engine, shared by both halves of fw: request filtering (the
* ctl layer) and packet filtering (the wire). One rule language, two enforcement points: a rule says what
* may happen, and the caller decides where it is enforced.
*/
typedef struct Rule Rule;
/*
* Direction, not layer. A "connect" written to a ctl file and an
* egress packet are the same intent seen from two places, so they are
* the same verb and one rule file serves both enforcement points.
*/
enum
{
Vin, /* inbound: announce, or a packet arriving */
Vout, /* outbound: connect, or a packet leaving */
Vany,
};
struct Rule
{
int allow;
int verb;
char *proto; /* nil: any */
int anyip;
uchar ip[IPaddrlen]; /* the peer, whichever end that is */
uchar mask[IPaddrlen];
int port; /* peer port, -1: any */
int lport; /* local port, -1: any */
int log; /* note matches in /sys/log/fw */
long hits; /* how often it has decided something */
int nr;
Rule *next;
};
/*
* Rules are swapped wholesale, never mutated in place, so no packet is
* ever judged against a half-applied rule set. rulechanged, if set, is
* called after a swap - the wire half uses it to re-check live flows.
*/
extern Rule *rules;
extern void (*rulechanged)(void);
void readrules(char*); /* parse and install, fatal on error */
Rule* parserules(char*, char**); /* parse only; nil + reason on error */
void installrules(Rule*); /* swap in, then call rulechanged */
void freerules(Rule*);
char* rulestext(void); /* current set as ndb; free it */
char* hitstext(void); /* the same, with hit counts */
void dumprules(void);
void checklogging(void);
/*
* One question for the rule list, and its answer, in the caller's
* frame.
*
* matchrule used to hand back a Rule* and a pointer into a static
* buffer, and callers read both after it had let go of the lock. A
* rule set installed in between freed the Rule under them, and two
* procs deciding at once overwrote each other's reason - in a program
* whose entire output is the reason. Nothing here outlives the Match,
* and the Match belongs to whoever asked.
*
* count says to charge the decision to the rule's tally. Re-checking
* live flows after a rule change is not traffic and must not be
* counted, or "how often has this rule decided something" answers a
* different question every time the rules are edited.
*/
typedef struct Match Match;
struct Match
{
int verb; /* in */
char *proto; /* nil: any */
uchar *ip; /* the peer; unread if anyip */
int anyip;
int port; /* peer port, -1: any */
int lport; /* local port, -1: any */
int count; /* charge this to the rule */
int nr; /* out: the rule that decided, 0 if none */
int log; /* it asked to be logged */
char err[128]; /* why not, if it said no */
};
int matchrule(Match*); /* 1 to permit, 0 to refuse */
int protoname2num(char*);
char* protonum2name(int);
void* emalloc(ulong);
char* estrdup(char*);
|