Annotation of src/usr.bin/systat/pf.c, Revision 1.14
1.14 ! bluhm 1: /* $OpenBSD: pf.c,v 1.13 2020/09/14 11:15:30 kn Exp $ */
1.1 canacar 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>
1.10 claudio 19: #include <sys/sysctl.h>
1.1 canacar 20: #include <sys/ioctl.h>
21: #include <sys/socket.h>
1.7 deraadt 22: #include <sys/signal.h>
1.1 canacar 23: #include <net/if.h>
24: #include <netinet/in.h>
25: #include <netinet/ip.h>
26: #include <net/pfvar.h>
27:
28: #include <stdio.h>
29: #include <stdlib.h>
30: #include <string.h>
31: #include <ctype.h>
32: #include <errno.h>
33: #include <err.h>
34: #include <unistd.h>
1.2 mcbride 35: #include <syslog.h>
1.1 canacar 36: #include "pfctl_parser.h"
37: #include "systat.h"
38:
39: void print_pf(void);
40: int read_pf(void);
41: int select_pf(void);
1.3 lum 42: void print_fld_double(field_def *, double);
1.1 canacar 43:
44: const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
45: const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
46: const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
1.14 ! bluhm 47: const char *pf_scounters[SCNT_MAX+1] = FCNT_NAMES;
! 48: const char *pf_ncounters[NCNT_MAX+1] = FCNT_NAMES;
1.1 canacar 49:
50: static struct pf_status status;
51: int num_pf = 0;
52:
53: field_def fields_pf[] = {
54: {"TYPE", 13, 16, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
55: {"NAME", 12, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
56: {"VALUE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
57: {"RATE", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 60},
58: };
59:
1.4 jasper 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)
1.1 canacar 64:
65: /* Define views */
66: field_def *view_pf_0[] = {
1.13 kn 67: FLD_PF_TYPE, FLD_PF_NAME, FLD_PF_VALUE, FLD_PF_RATE, NULL
1.1 canacar 68: };
69:
70:
71: /* Define view managers */
72: struct view_manager pf_mgr = {
73: "PF", select_pf, read_pf, NULL, print_header,
74: print_pf, keyboard_callback, NULL, NULL
75: };
76:
77: field_view views_pf[] = {
78: {view_pf_0, "pf", 'P', &pf_mgr},
79: {NULL, NULL, 0, NULL}
80: };
81:
82:
83:
84: int
85: select_pf(void)
86: {
87: return (0);
88: }
89:
90: int
91: read_pf(void)
92: {
1.10 claudio 93: size_t size = sizeof(status);
94: int mib[3] = { CTL_KERN, KERN_PFSTATUS };
1.1 canacar 95:
1.11 deraadt 96: if (sysctl(mib, 2, &status, &size, NULL, 0) == -1) {
1.10 claudio 97: error("sysctl(PFCTL_STATUS): %s", strerror(errno));
1.1 canacar 98: return (-1);
99: }
100:
101: num_disp = 4;
102:
103: if (status.ifname[0] != 0)
104: num_disp += 13;
105:
106: num_disp += FCNT_MAX + 2;
107: num_disp += SCNT_MAX + 2;
1.14 ! bluhm 108: num_disp += NCNT_MAX + 2;
1.1 canacar 109: num_disp += PFRES_MAX + 1;
110: num_disp += LCNT_MAX + 1;
111:
112: return (0);
113: }
114:
115: int
116: initpf(void)
117: {
118: field_view *v;
119:
120: for (v = views_pf; v->name != NULL; v++)
121: add_view(v);
122:
123: return(1);
124: }
125:
126: void
127: print_fld_double(field_def *fld, double val)
128: {
129: int len;
130:
131: if (fld == NULL)
132: return;
133:
134: len = fld->width;
135: if (len < 1)
136: return;
137:
138: tb_start();
139: if (tbprintf("%.2f", val) > len)
140: print_fld_str(fld, "*");
141: else
142: print_fld_tb(fld);
143: tb_end();
144: }
145:
146: #define ADD_LINE_A(t, n, v) \
147: do { \
148: if (cur >= dispstart && cur < end) { \
149: print_fld_str(FLD_PF_TYPE, (t)); \
150: print_fld_str(FLD_PF_NAME, (n)); \
151: print_fld_age(FLD_PF_VALUE, (v)); \
152: end_line(); \
153: } \
154: if (++cur >= end) \
155: return; \
156: } while (0)
157:
158: #define ADD_EMPTY_LINE \
159: do { \
160: if (cur >= dispstart && cur < end) \
161: end_line(); \
162: if (++cur >= end) \
163: return; \
164: } while (0)
165:
166: #define ADD_LINE_S(t, n, v) \
167: do { \
168: if (cur >= dispstart && cur < end) { \
169: print_fld_str(FLD_PF_TYPE, (t)); \
170: print_fld_str(FLD_PF_NAME, (n)); \
171: print_fld_str(FLD_PF_VALUE, (v)); \
172: end_line(); \
173: } \
174: if (++cur >= end) \
175: return; \
176: } while (0)
177:
178: #define ADD_LINE_V(t, n, v) \
179: do { \
180: if (cur >= dispstart && cur < end) { \
181: print_fld_str(FLD_PF_TYPE, (t)); \
182: print_fld_str(FLD_PF_NAME, (n)); \
183: print_fld_size(FLD_PF_VALUE, (v)); \
184: end_line(); \
185: } \
186: if (++cur >= end) \
187: return; \
188: } while (0)
189:
190: #define ADD_LINE_VR(t, n, v, r) \
191: do { \
192: if (cur >= dispstart && cur < end) { \
193: print_fld_str(FLD_PF_TYPE, (t)); \
194: print_fld_str(FLD_PF_NAME, (n)); \
195: print_fld_size(FLD_PF_VALUE, (v)); \
196: print_fld_double(FLD_PF_RATE, (r)); \
197: end_line(); \
198: } \
199: if (++cur >= end) \
200: return; \
201: } while (0)
202:
203:
204: void
205: print_pf(void)
206: {
207: char *debug;
1.9 patrick 208: time_t tm = 0;
209: struct timespec uptime;
1.1 canacar 210: int i;
211: struct pf_status *s = &status;
212:
213: int cur = 0;
214: int end = dispstart + maxprint;
215: if (end > num_disp)
216: end = num_disp;
217:
1.12 cheloha 218: if (!clock_gettime(CLOCK_BOOTTIME, &uptime))
1.9 patrick 219: tm = uptime.tv_sec - s->since;
1.1 canacar 220:
221: ADD_LINE_S("pf", "Status", s->running ? "Enabled" : "Disabled");
222: ADD_LINE_A("pf", "Since", tm);
223:
224: switch (s->debug) {
1.2 mcbride 225: case LOG_EMERG:
226: debug = "emerg";
1.1 canacar 227: break;
1.2 mcbride 228: case LOG_ALERT:
229: debug = "alert";
1.1 canacar 230: break;
1.2 mcbride 231: case LOG_CRIT:
232: debug = "crit";
1.1 canacar 233: break;
1.2 mcbride 234: case LOG_ERR:
235: debug = "err";
236: break;
237: case LOG_WARNING:
238: debug = "warning";
239: break;
240: case LOG_NOTICE:
241: debug = "notice";
242: break;
243: case LOG_INFO:
244: debug = "info";
245: break;
246: case LOG_DEBUG:
247: debug = "debug";
1.1 canacar 248: break;
1.8 benno 249: default:
250: debug = "unknown";
251: break;
1.1 canacar 252: }
253: ADD_LINE_S("pf", "Debug", debug);
254:
255: tb_start();
256: tbprintf("0x%08x\n", ntohl(s->hostid));
257: tb_end();
258:
259: ADD_LINE_S("pf", "Hostid", tmp_buf);
260:
261: if (s->ifname[0] != 0) {
262: ADD_EMPTY_LINE;
1.13 kn 263: ADD_LINE_V(s->ifname, "Bytes In IPv4", s->bcounters[0][0]);
264: ADD_LINE_V(s->ifname, "Bytes In IPv6", s->bcounters[1][0]);
265: ADD_LINE_V(s->ifname, "Bytes Out IPv4", s->bcounters[0][1]);
266: ADD_LINE_V(s->ifname, "Bytes Out IPv6", s->bcounters[1][1]);
267: ADD_LINE_V(s->ifname, "Packets In Passed IPv4", s->pcounters[0][0][PF_PASS]);
268: ADD_LINE_V(s->ifname, "Packets In Passed IPv6", s->pcounters[1][0][PF_PASS]);
269: ADD_LINE_V(s->ifname, "Packets In Blocked IPv4", s->pcounters[0][0][PF_DROP]);
270: ADD_LINE_V(s->ifname, "Packets In Blocked IPv6", s->pcounters[1][0][PF_DROP]);
271: ADD_LINE_V(s->ifname, "Packets Out Passed IPv4", s->pcounters[0][1][PF_PASS]);
272: ADD_LINE_V(s->ifname, "Packets Out Passed IPv6", s->pcounters[1][1][PF_PASS]);
273: ADD_LINE_V(s->ifname, "Packets Out Blocked IPv4", s->pcounters[0][1][PF_DROP]);
274: ADD_LINE_V(s->ifname, "Packets Out Blocked IPv6", s->pcounters[1][1][PF_DROP]);
1.1 canacar 275: }
276:
277:
278: ADD_EMPTY_LINE;
279: ADD_LINE_V("state", "Count", s->states);
280:
281: for (i = 0; i < FCNT_MAX; i++) {
282: if (tm > 0)
283: ADD_LINE_VR("state", pf_fcounters[i], s->fcounters[i],
284: (double)s->fcounters[i] / (double)tm);
285: else
286: ADD_LINE_V("state", pf_fcounters[i], s->fcounters[i]);
287: }
288:
289:
290: ADD_EMPTY_LINE;
291: ADD_LINE_V("src track", "Count", s->src_nodes);
292:
293: for (i = 0; i < SCNT_MAX; i++) {
294: if (tm > 0)
295: ADD_LINE_VR("src track", pf_scounters[i], s->scounters[i],
296: (double)s->scounters[i] / (double)tm);
297: else
298: ADD_LINE_V("src track", pf_scounters[i], s->scounters[i]);
1.14 ! bluhm 299: }
! 300:
! 301: ADD_EMPTY_LINE;
! 302: ADD_LINE_V("fragment", "Count", s->fragments);
! 303:
! 304: for (i = 0; i < NCNT_MAX; i++) {
! 305: if (tm > 0)
! 306: ADD_LINE_VR("fragment", pf_ncounters[i], s->ncounters[i],
! 307: (double)s->ncounters[i] / (double)tm);
! 308: else
! 309: ADD_LINE_V("fragment", pf_ncounters[i], s->ncounters[i]);
1.1 canacar 310: }
311:
312: ADD_EMPTY_LINE;
313: for (i = 0; i < PFRES_MAX; i++) {
314: if (tm > 0)
315: ADD_LINE_VR("counter", pf_reasons[i], s->counters[i],
316: (double)s->counters[i] / (double)tm);
317: else
318: ADD_LINE_V("counter", pf_reasons[i], s->counters[i]);
319: }
320:
321: ADD_EMPTY_LINE;
322: for (i = 0; i < LCNT_MAX; i++) {
323: if (tm > 0)
324: ADD_LINE_VR("limit counter", pf_lcounters[i], s->lcounters[i],
325: (double)s->lcounters[i] / (double)tm);
326: else
327: ADD_LINE_V("limit counter", pf_lcounters[i], s->lcounters[i]);
328: }
329: }