GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/pf.c Lines: 0 87 0.0 %
Date: 2017-11-07 Branches: 0 231 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pf.c,v 1.9 2017/06/01 14:38:28 patrick Exp $ */
2
/*
3
 * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/types.h>
19
#include <sys/ioctl.h>
20
#include <sys/socket.h>
21
#include <sys/signal.h>
22
#include <net/if.h>
23
#include <netinet/in.h>
24
#include <netinet/ip.h>
25
#include <net/pfvar.h>
26
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <ctype.h>
31
#include <errno.h>
32
#include <err.h>
33
#include <unistd.h>
34
#include <syslog.h>
35
#include "pfctl_parser.h"
36
#include "systat.h"
37
38
void print_pf(void);
39
int read_pf(void);
40
int select_pf(void);
41
void print_fld_double(field_def *, double);
42
43
const char	*pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
44
const char	*pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
45
const char	*pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
46
const char	*pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
47
48
static struct pf_status status;
49
extern int pf_dev;
50
int num_pf = 0;
51
52
field_def fields_pf[] = {
53
	{"TYPE", 13, 16, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
54
	{"NAME", 12, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
55
	{"VALUE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
56
	{"RATE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 60},
57
	{"NOTES", 10, 20, 1, FLD_ALIGN_LEFT, -1, 0, 0, 60},
58
};
59
60
#define FLD_PF_TYPE	FIELD_ADDR(fields_pf,0)
61
#define FLD_PF_NAME	FIELD_ADDR(fields_pf,1)
62
#define FLD_PF_VALUE	FIELD_ADDR(fields_pf,2)
63
#define FLD_PF_RATE	FIELD_ADDR(fields_pf,3)
64
#define FLD_PF_DESC	FIELD_ADDR(fields_pf,4)
65
66
/* Define views */
67
field_def *view_pf_0[] = {
68
	FLD_PF_TYPE, FLD_PF_NAME, FLD_PF_VALUE, FLD_PF_RATE, FLD_PF_DESC, NULL
69
};
70
71
72
/* Define view managers */
73
struct view_manager pf_mgr = {
74
	"PF", select_pf, read_pf, NULL, print_header,
75
	print_pf, keyboard_callback, NULL, NULL
76
};
77
78
field_view views_pf[] = {
79
	{view_pf_0, "pf", 'P', &pf_mgr},
80
	{NULL, NULL, 0, NULL}
81
};
82
83
84
85
int
86
select_pf(void)
87
{
88
	return (0);
89
}
90
91
int
92
read_pf(void)
93
{
94
	if (pf_dev < 0) {
95
		num_disp = 0;
96
		return 0;
97
	}
98
99
	if (ioctl(pf_dev, DIOCGETSTATUS, &status)) {
100
		error("DIOCGETSTATUS: %s", strerror(errno));
101
		return (-1);
102
	}
103
104
	num_disp = 4;
105
106
	if (status.ifname[0] != 0)
107
		num_disp += 13;
108
109
	num_disp += FCNT_MAX + 2;
110
	num_disp += SCNT_MAX + 2;
111
	num_disp += PFRES_MAX + 1;
112
	num_disp += LCNT_MAX + 1;
113
114
	return (0);
115
}
116
117
int
118
initpf(void)
119
{
120
	field_view *v;
121
122
	for (v = views_pf; v->name != NULL; v++)
123
		add_view(v);
124
125
	return(1);
126
}
127
128
void
129
print_fld_double(field_def *fld, double val)
130
{
131
	int len;
132
133
	if (fld == NULL)
134
		return;
135
136
	len = fld->width;
137
	if (len < 1)
138
		return;
139
140
	tb_start();
141
	if (tbprintf("%.2f", val) > len)
142
		print_fld_str(fld, "*");
143
	else
144
		print_fld_tb(fld);
145
	tb_end();
146
}
147
148
#define ADD_LINE_A(t, n, v) \
149
	do {							\
150
		if (cur >= dispstart && cur < end) { 		\
151
			print_fld_str(FLD_PF_TYPE, (t));	\
152
			print_fld_str(FLD_PF_NAME, (n));	\
153
			print_fld_age(FLD_PF_VALUE, (v));	\
154
			end_line();				\
155
		}						\
156
		if (++cur >= end)				\
157
			return;					\
158
	} while (0)
159
160
#define ADD_EMPTY_LINE \
161
	do {							\
162
		if (cur >= dispstart && cur < end) 		\
163
			end_line();				\
164
		if (++cur >= end)				\
165
			return;					\
166
	} while (0)
167
168
#define ADD_LINE_S(t, n, v) \
169
	do {							\
170
		if (cur >= dispstart && cur < end) { 		\
171
			print_fld_str(FLD_PF_TYPE, (t));	\
172
			print_fld_str(FLD_PF_NAME, (n));	\
173
			print_fld_str(FLD_PF_VALUE, (v));	\
174
			end_line();				\
175
		}						\
176
		if (++cur >= end)				\
177
			return;					\
178
	} while (0)
179
180
#define ADD_LINE_V(t, n, v) \
181
	do {							\
182
		if (cur >= dispstart && cur < end) { 		\
183
			print_fld_str(FLD_PF_TYPE, (t));	\
184
			print_fld_str(FLD_PF_NAME, (n));	\
185
			print_fld_size(FLD_PF_VALUE, (v));	\
186
			end_line();				\
187
		}						\
188
		if (++cur >= end)				\
189
			return;					\
190
	} while (0)
191
192
#define ADD_LINE_VD(t, n, v, d) \
193
	do {							\
194
		if (cur >= dispstart && cur < end) { 		\
195
			print_fld_str(FLD_PF_TYPE, (t));	\
196
			print_fld_str(FLD_PF_NAME, (n));	\
197
			print_fld_size(FLD_PF_VALUE, (v));	\
198
			print_fld_str(FLD_PF_DESC, (d));	\
199
			end_line();				\
200
		}						\
201
		if (++cur >= end)				\
202
			return;					\
203
	} while (0)
204
205
#define ADD_LINE_VR(t, n, v, r) \
206
	do {							\
207
		if (cur >= dispstart && cur < end) { 		\
208
			print_fld_str(FLD_PF_TYPE, (t));	\
209
			print_fld_str(FLD_PF_NAME, (n));	\
210
			print_fld_size(FLD_PF_VALUE, (v));	\
211
			print_fld_double(FLD_PF_RATE, (r));	\
212
			end_line();				\
213
		}						\
214
		if (++cur >= end)				\
215
			return;					\
216
	} while (0)
217
218
219
void
220
print_pf(void)
221
{
222
	char		*debug;
223
	time_t		tm = 0;
224
	struct timespec	uptime;
225
	int		i;
226
	struct pf_status *s = &status;
227
228
	int cur = 0;
229
	int end = dispstart + maxprint;
230
	if (end > num_disp)
231
		end = num_disp;
232
233
	if (!clock_gettime(CLOCK_UPTIME, &uptime))
234
		tm = uptime.tv_sec - s->since;
235
236
	ADD_LINE_S("pf", "Status", s->running ? "Enabled" : "Disabled");
237
	ADD_LINE_A("pf", "Since", tm);
238
239
	switch (s->debug) {
240
	case LOG_EMERG:
241
		debug = "emerg";
242
		break;
243
	case LOG_ALERT:
244
		debug = "alert";
245
		break;
246
	case LOG_CRIT:
247
		debug = "crit";
248
		break;
249
	case LOG_ERR:
250
		debug = "err";
251
		break;
252
	case LOG_WARNING:
253
		debug = "warning";
254
		break;
255
	case LOG_NOTICE:
256
		debug = "notice";
257
		break;
258
	case LOG_INFO:
259
		debug = "info";
260
		break;
261
	case LOG_DEBUG:
262
		debug = "debug";
263
		break;
264
	default:
265
		debug = "unknown";
266
		break;
267
	}
268
	ADD_LINE_S("pf", "Debug", debug);
269
270
	tb_start();
271
	tbprintf("0x%08x\n", ntohl(s->hostid));
272
	tb_end();
273
274
	ADD_LINE_S("pf", "Hostid", tmp_buf);
275
276
	if (s->ifname[0] != 0) {
277
		ADD_EMPTY_LINE;
278
		ADD_LINE_VD(s->ifname, "Bytes In", s->bcounters[0][0], "IPv4");
279
		ADD_LINE_VD(s->ifname, "Bytes In", s->bcounters[1][0], "IPv6");
280
		ADD_LINE_VD(s->ifname, "Bytes Out", s->bcounters[0][1], "IPv4");
281
		ADD_LINE_VD(s->ifname, "Bytes Out", s->bcounters[1][1], "IPv6");
282
		ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[0][0][PF_PASS], "IPv4, Passed");
283
		ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[1][0][PF_PASS], "IPv6, Passed");
284
		ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[0][0][PF_DROP], "IPv4, Blocked");
285
		ADD_LINE_VD(s->ifname, "Packets In", s->pcounters[1][0][PF_DROP], "IPv6, Blocked");
286
		ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[0][1][PF_PASS], "IPv4, Passed");
287
		ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[1][1][PF_PASS], "IPv6, Passed");
288
		ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[0][1][PF_DROP], "IPv4, Blocked");
289
		ADD_LINE_VD(s->ifname, "Packets Out", s->pcounters[1][1][PF_DROP], "IPv6, Blocked");
290
	}
291
292
293
	ADD_EMPTY_LINE;
294
	ADD_LINE_V("state", "Count", s->states);
295
296
	for (i = 0; i < FCNT_MAX; i++) {
297
		if (tm > 0)
298
			ADD_LINE_VR("state", pf_fcounters[i], s->fcounters[i],
299
				    (double)s->fcounters[i] / (double)tm);
300
		else
301
			ADD_LINE_V("state", pf_fcounters[i], s->fcounters[i]);
302
	}
303
304
305
	ADD_EMPTY_LINE;
306
	ADD_LINE_V("src track", "Count", s->src_nodes);
307
308
	for (i = 0; i < SCNT_MAX; i++) {
309
		if (tm > 0)
310
			ADD_LINE_VR("src track", pf_scounters[i], s->scounters[i],
311
				    (double)s->scounters[i] / (double)tm);
312
		else
313
			ADD_LINE_V("src track", pf_scounters[i], s->scounters[i]);
314
	}
315
316
	ADD_EMPTY_LINE;
317
	for (i = 0; i < PFRES_MAX; i++) {
318
		if (tm > 0)
319
			ADD_LINE_VR("counter", pf_reasons[i], s->counters[i],
320
				    (double)s->counters[i] / (double)tm);
321
		else
322
			ADD_LINE_V("counter", pf_reasons[i], s->counters[i]);
323
	}
324
325
	ADD_EMPTY_LINE;
326
	for (i = 0; i < LCNT_MAX; i++) {
327
		if (tm > 0)
328
			ADD_LINE_VR("limit counter", pf_lcounters[i], s->lcounters[i],
329
				    (double)s->lcounters[i] / (double)tm);
330
		else
331
			ADD_LINE_V("limit counter", pf_lcounters[i], s->lcounters[i]);
332
	}
333
}