GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: pfctl_parser.c,v 1.316 2017/08/14 15:53:04 henning Exp $ */ |
||
2 |
|||
3 |
/* |
||
4 |
* Copyright (c) 2001 Daniel Hartmeier |
||
5 |
* Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org> |
||
6 |
* All rights reserved. |
||
7 |
* |
||
8 |
* Redistribution and use in source and binary forms, with or without |
||
9 |
* modification, are permitted provided that the following conditions |
||
10 |
* are met: |
||
11 |
* |
||
12 |
* - Redistributions of source code must retain the above copyright |
||
13 |
* notice, this list of conditions and the following disclaimer. |
||
14 |
* - Redistributions in binary form must reproduce the above |
||
15 |
* copyright notice, this list of conditions and the following |
||
16 |
* disclaimer in the documentation and/or other materials provided |
||
17 |
* with the distribution. |
||
18 |
* |
||
19 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
20 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
21 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
22 |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||
23 |
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
24 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||
25 |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
26 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||
27 |
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
28 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||
29 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
30 |
* POSSIBILITY OF SUCH DAMAGE. |
||
31 |
* |
||
32 |
*/ |
||
33 |
|||
34 |
#include <sys/types.h> |
||
35 |
#include <sys/ioctl.h> |
||
36 |
#include <sys/socket.h> |
||
37 |
#include <net/if_dl.h> |
||
38 |
#include <net/if.h> |
||
39 |
#include <netinet/in.h> |
||
40 |
#include <netinet/ip.h> |
||
41 |
#include <netinet/ip_icmp.h> |
||
42 |
#include <netinet/icmp6.h> |
||
43 |
#include <net/pfvar.h> |
||
44 |
#include <arpa/inet.h> |
||
45 |
|||
46 |
#include <ctype.h> |
||
47 |
#include <err.h> |
||
48 |
#include <errno.h> |
||
49 |
#include <ifaddrs.h> |
||
50 |
#include <limits.h> |
||
51 |
#include <netdb.h> |
||
52 |
#include <stdarg.h> |
||
53 |
#include <stdio.h> |
||
54 |
#include <stdlib.h> |
||
55 |
#include <string.h> |
||
56 |
#include <time.h> |
||
57 |
#include <unistd.h> |
||
58 |
|||
59 |
#define SYSLOG_NAMES |
||
60 |
#include <syslog.h> |
||
61 |
|||
62 |
#include "pfctl_parser.h" |
||
63 |
#include "pfctl.h" |
||
64 |
|||
65 |
void print_op (u_int8_t, const char *, const char *); |
||
66 |
void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); |
||
67 |
void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); |
||
68 |
void print_flags (u_int8_t); |
||
69 |
void print_fromto(struct pf_rule_addr *, pf_osfp_t, |
||
70 |
struct pf_rule_addr *, u_int8_t, u_int8_t, int); |
||
71 |
void print_bwspec(const char *index, struct pf_queue_bwspec *); |
||
72 |
void print_scspec(const char *, struct pf_queue_scspec *); |
||
73 |
int ifa_skip_if(const char *filter, struct node_host *p); |
||
74 |
|||
75 |
struct node_host *ifa_grouplookup(const char *, int); |
||
76 |
struct node_host *host_if(const char *, int); |
||
77 |
struct node_host *host_v4(const char *, int); |
||
78 |
struct node_host *host_v6(const char *, int); |
||
79 |
struct node_host *host_dns(const char *, int, int, int); |
||
80 |
|||
81 |
const char *tcpflags = "FSRPAUEW"; |
||
82 |
|||
83 |
static const struct icmptypeent icmp_type[] = { |
||
84 |
{ "echoreq", ICMP_ECHO }, |
||
85 |
{ "echorep", ICMP_ECHOREPLY }, |
||
86 |
{ "unreach", ICMP_UNREACH }, |
||
87 |
{ "squench", ICMP_SOURCEQUENCH }, |
||
88 |
{ "redir", ICMP_REDIRECT }, |
||
89 |
{ "althost", ICMP_ALTHOSTADDR }, |
||
90 |
{ "routeradv", ICMP_ROUTERADVERT }, |
||
91 |
{ "routersol", ICMP_ROUTERSOLICIT }, |
||
92 |
{ "timex", ICMP_TIMXCEED }, |
||
93 |
{ "paramprob", ICMP_PARAMPROB }, |
||
94 |
{ "timereq", ICMP_TSTAMP }, |
||
95 |
{ "timerep", ICMP_TSTAMPREPLY }, |
||
96 |
{ "inforeq", ICMP_IREQ }, |
||
97 |
{ "inforep", ICMP_IREQREPLY }, |
||
98 |
{ "maskreq", ICMP_MASKREQ }, |
||
99 |
{ "maskrep", ICMP_MASKREPLY }, |
||
100 |
{ "trace", ICMP_TRACEROUTE }, |
||
101 |
{ "dataconv", ICMP_DATACONVERR }, |
||
102 |
{ "mobredir", ICMP_MOBILE_REDIRECT }, |
||
103 |
{ "ipv6-where", ICMP_IPV6_WHEREAREYOU }, |
||
104 |
{ "ipv6-here", ICMP_IPV6_IAMHERE }, |
||
105 |
{ "mobregreq", ICMP_MOBILE_REGREQUEST }, |
||
106 |
{ "mobregrep", ICMP_MOBILE_REGREPLY }, |
||
107 |
{ "skip", ICMP_SKIP }, |
||
108 |
{ "photuris", ICMP_PHOTURIS } |
||
109 |
}; |
||
110 |
|||
111 |
static const struct icmptypeent icmp6_type[] = { |
||
112 |
{ "unreach", ICMP6_DST_UNREACH }, |
||
113 |
{ "toobig", ICMP6_PACKET_TOO_BIG }, |
||
114 |
{ "timex", ICMP6_TIME_EXCEEDED }, |
||
115 |
{ "paramprob", ICMP6_PARAM_PROB }, |
||
116 |
{ "echoreq", ICMP6_ECHO_REQUEST }, |
||
117 |
{ "echorep", ICMP6_ECHO_REPLY }, |
||
118 |
{ "groupqry", ICMP6_MEMBERSHIP_QUERY }, |
||
119 |
{ "listqry", MLD_LISTENER_QUERY }, |
||
120 |
{ "grouprep", ICMP6_MEMBERSHIP_REPORT }, |
||
121 |
{ "listenrep", MLD_LISTENER_REPORT }, |
||
122 |
{ "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, |
||
123 |
{ "listendone", MLD_LISTENER_DONE }, |
||
124 |
{ "routersol", ND_ROUTER_SOLICIT }, |
||
125 |
{ "routeradv", ND_ROUTER_ADVERT }, |
||
126 |
{ "neighbrsol", ND_NEIGHBOR_SOLICIT }, |
||
127 |
{ "neighbradv", ND_NEIGHBOR_ADVERT }, |
||
128 |
{ "redir", ND_REDIRECT }, |
||
129 |
{ "routrrenum", ICMP6_ROUTER_RENUMBERING }, |
||
130 |
{ "wrureq", ICMP6_WRUREQUEST }, |
||
131 |
{ "wrurep", ICMP6_WRUREPLY }, |
||
132 |
{ "fqdnreq", ICMP6_FQDN_QUERY }, |
||
133 |
{ "fqdnrep", ICMP6_FQDN_REPLY }, |
||
134 |
{ "niqry", ICMP6_NI_QUERY }, |
||
135 |
{ "nirep", ICMP6_NI_REPLY }, |
||
136 |
{ "mtraceresp", MLD_MTRACE_RESP }, |
||
137 |
{ "mtrace", MLD_MTRACE } |
||
138 |
}; |
||
139 |
|||
140 |
static const struct icmpcodeent icmp_code[] = { |
||
141 |
{ "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, |
||
142 |
{ "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, |
||
143 |
{ "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, |
||
144 |
{ "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, |
||
145 |
{ "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, |
||
146 |
{ "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, |
||
147 |
{ "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, |
||
148 |
{ "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, |
||
149 |
{ "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, |
||
150 |
{ "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, |
||
151 |
{ "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, |
||
152 |
{ "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, |
||
153 |
{ "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, |
||
154 |
{ "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, |
||
155 |
{ "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, |
||
156 |
{ "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, |
||
157 |
{ "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, |
||
158 |
{ "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, |
||
159 |
{ "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, |
||
160 |
{ "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, |
||
161 |
{ "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, |
||
162 |
{ "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, |
||
163 |
{ "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, |
||
164 |
{ "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, |
||
165 |
{ "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, |
||
166 |
{ "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, |
||
167 |
{ "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, |
||
168 |
{ "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, |
||
169 |
{ "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, |
||
170 |
{ "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } |
||
171 |
}; |
||
172 |
|||
173 |
static const struct icmpcodeent icmp6_code[] = { |
||
174 |
{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, |
||
175 |
{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, |
||
176 |
{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, |
||
177 |
{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, |
||
178 |
{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, |
||
179 |
{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, |
||
180 |
{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, |
||
181 |
{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, |
||
182 |
{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, |
||
183 |
{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, |
||
184 |
{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } |
||
185 |
}; |
||
186 |
|||
187 |
const struct pf_timeout pf_timeouts[] = { |
||
188 |
{ "tcp.first", PFTM_TCP_FIRST_PACKET }, |
||
189 |
{ "tcp.opening", PFTM_TCP_OPENING }, |
||
190 |
{ "tcp.established", PFTM_TCP_ESTABLISHED }, |
||
191 |
{ "tcp.closing", PFTM_TCP_CLOSING }, |
||
192 |
{ "tcp.finwait", PFTM_TCP_FIN_WAIT }, |
||
193 |
{ "tcp.closed", PFTM_TCP_CLOSED }, |
||
194 |
{ "tcp.tsdiff", PFTM_TS_DIFF }, |
||
195 |
{ "udp.first", PFTM_UDP_FIRST_PACKET }, |
||
196 |
{ "udp.single", PFTM_UDP_SINGLE }, |
||
197 |
{ "udp.multiple", PFTM_UDP_MULTIPLE }, |
||
198 |
{ "icmp.first", PFTM_ICMP_FIRST_PACKET }, |
||
199 |
{ "icmp.error", PFTM_ICMP_ERROR_REPLY }, |
||
200 |
{ "other.first", PFTM_OTHER_FIRST_PACKET }, |
||
201 |
{ "other.single", PFTM_OTHER_SINGLE }, |
||
202 |
{ "other.multiple", PFTM_OTHER_MULTIPLE }, |
||
203 |
{ "frag", PFTM_FRAG }, |
||
204 |
{ "interval", PFTM_INTERVAL }, |
||
205 |
{ "adaptive.start", PFTM_ADAPTIVE_START }, |
||
206 |
{ "adaptive.end", PFTM_ADAPTIVE_END }, |
||
207 |
{ "src.track", PFTM_SRC_NODE }, |
||
208 |
{ NULL, 0 } |
||
209 |
}; |
||
210 |
|||
211 |
enum { PF_POOL_ROUTE, PF_POOL_NAT, PF_POOL_RDR }; |
||
212 |
|||
213 |
const struct icmptypeent * |
||
214 |
geticmptypebynumber(u_int8_t type, sa_family_t af) |
||
215 |
{ |
||
216 |
unsigned int i; |
||
217 |
|||
218 |
✓✓ | 196 |
if (af != AF_INET6) { |
219 |
✓✓ | 988 |
for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); |
220 |
432 |
i++) { |
|
221 |
✓✓ | 478 |
if (type == icmp_type[i].type) |
222 |
46 |
return (&icmp_type[i]); |
|
223 |
} |
||
224 |
} else { |
||
225 |
✓✓ | 920 |
for (i=0; i < (sizeof (icmp6_type) / |
226 |
424 |
sizeof(icmp6_type[0])); i++) { |
|
227 |
✓✓ | 444 |
if (type == icmp6_type[i].type) |
228 |
20 |
return (&icmp6_type[i]); |
|
229 |
} |
||
230 |
} |
||
231 |
32 |
return (NULL); |
|
232 |
98 |
} |
|
233 |
|||
234 |
const struct icmptypeent * |
||
235 |
geticmptypebyname(char *w, sa_family_t af) |
||
236 |
{ |
||
237 |
unsigned int i; |
||
238 |
|||
239 |
✓✓ | 48 |
if (af != AF_INET6) { |
240 |
✓✗ | 60 |
for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); |
241 |
14 |
i++) { |
|
242 |
✓✓ | 30 |
if (!strcmp(w, icmp_type[i].name)) |
243 |
16 |
return (&icmp_type[i]); |
|
244 |
} |
||
245 |
} else { |
||
246 |
✓✗ | 32 |
for (i=0; i < (sizeof (icmp6_type) / |
247 |
8 |
sizeof(icmp6_type[0])); i++) { |
|
248 |
✓✓ | 16 |
if (!strcmp(w, icmp6_type[i].name)) |
249 |
8 |
return (&icmp6_type[i]); |
|
250 |
} |
||
251 |
} |
||
252 |
return (NULL); |
||
253 |
24 |
} |
|
254 |
|||
255 |
const struct icmpcodeent * |
||
256 |
geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) |
||
257 |
{ |
||
258 |
unsigned int i; |
||
259 |
|||
260 |
✓✓ | 500 |
if (af != AF_INET6) { |
261 |
✓✓ | 3544 |
for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); |
262 |
1635 |
i++) { |
|
263 |
✓✓✓✓ |
2264 |
if (type == icmp_code[i].type && |
264 |
532 |
code == icmp_code[i].code) |
|
265 |
97 |
return (&icmp_code[i]); |
|
266 |
} |
||
267 |
} else { |
||
268 |
✓✓ | 1404 |
for (i=0; i < (sizeof (icmp6_code) / |
269 |
589 |
sizeof(icmp6_code[0])); i++) { |
|
270 |
✓✓✓✓ |
961 |
if (type == icmp6_code[i].type && |
271 |
296 |
code == icmp6_code[i].code) |
|
272 |
76 |
return (&icmp6_code[i]); |
|
273 |
} |
||
274 |
} |
||
275 |
77 |
return (NULL); |
|
276 |
250 |
} |
|
277 |
|||
278 |
const struct icmpcodeent * |
||
279 |
geticmpcodebyname(u_long type, char *w, sa_family_t af) |
||
280 |
{ |
||
281 |
unsigned int i; |
||
282 |
|||
283 |
✓✓ | 150 |
if (af != AF_INET6) { |
284 |
✓✗ | 480 |
for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); |
285 |
206 |
i++) { |
|
286 |
✓✗✓✓ |
480 |
if (type == icmp_code[i].type && |
287 |
240 |
!strcmp(w, icmp_code[i].name)) |
|
288 |
34 |
return (&icmp_code[i]); |
|
289 |
} |
||
290 |
} else { |
||
291 |
✓✗ | 270 |
for (i=0; i < (sizeof (icmp6_code) / |
292 |
94 |
sizeof(icmp6_code[0])); i++) { |
|
293 |
✓✓✓✓ |
250 |
if (type == icmp6_code[i].type && |
294 |
115 |
!strcmp(w, icmp6_code[i].name)) |
|
295 |
41 |
return (&icmp6_code[i]); |
|
296 |
} |
||
297 |
} |
||
298 |
return (NULL); |
||
299 |
75 |
} |
|
300 |
|||
301 |
/* |
||
302 |
* Decode a symbolic name to a numeric value. |
||
303 |
* From syslogd. |
||
304 |
*/ |
||
305 |
int |
||
306 |
string_to_loglevel(const char *name) |
||
307 |
{ |
||
308 |
CODE *c; |
||
309 |
char *p, buf[40]; |
||
310 |
|||
311 |
if (isdigit((unsigned char)*name)) { |
||
312 |
const char *errstr; |
||
313 |
int val; |
||
314 |
|||
315 |
val = strtonum(name, 0, LOG_DEBUG, &errstr); |
||
316 |
if (errstr) |
||
317 |
return -1; |
||
318 |
return val; |
||
319 |
} |
||
320 |
|||
321 |
for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) { |
||
322 |
if (isupper((unsigned char)*name)) |
||
323 |
*p = tolower((unsigned char)*name); |
||
324 |
else |
||
325 |
*p = *name; |
||
326 |
} |
||
327 |
*p = '\0'; |
||
328 |
for (c = prioritynames; c->c_name; c++) |
||
329 |
if (!strcmp(buf, c->c_name) && c->c_val != INTERNAL_NOPRI) |
||
330 |
return (c->c_val); |
||
331 |
|||
332 |
return (-1); |
||
333 |
} |
||
334 |
|||
335 |
const char * |
||
336 |
loglevel_to_string(int level) |
||
337 |
{ |
||
338 |
CODE *c; |
||
339 |
|||
340 |
✓✗ | 44 |
for (c = prioritynames; c->c_name; c++) |
341 |
✓✓ | 20 |
if (c->c_val == level) |
342 |
4 |
return (c->c_name); |
|
343 |
|||
344 |
return ("unknown"); |
||
345 |
4 |
} |
|
346 |
|||
347 |
void |
||
348 |
print_op(u_int8_t op, const char *a1, const char *a2) |
||
349 |
{ |
||
350 |
✓✓ | 2048 |
if (op == PF_OP_IRG) |
351 |
7 |
printf(" %s >< %s", a1, a2); |
|
352 |
✓✓ | 1017 |
else if (op == PF_OP_XRG) |
353 |
4 |
printf(" %s <> %s", a1, a2); |
|
354 |
✓✓ | 1013 |
else if (op == PF_OP_EQ) |
355 |
887 |
printf(" = %s", a1); |
|
356 |
✓✓ | 126 |
else if (op == PF_OP_NE) |
357 |
15 |
printf(" != %s", a1); |
|
358 |
✓✓ | 111 |
else if (op == PF_OP_LT) |
359 |
4 |
printf(" < %s", a1); |
|
360 |
✓✓ | 107 |
else if (op == PF_OP_LE) |
361 |
8 |
printf(" <= %s", a1); |
|
362 |
✓✓ | 99 |
else if (op == PF_OP_GT) |
363 |
12 |
printf(" > %s", a1); |
|
364 |
✓✓ | 87 |
else if (op == PF_OP_GE) |
365 |
7 |
printf(" >= %s", a1); |
|
366 |
✓✗ | 80 |
else if (op == PF_OP_RRG) |
367 |
80 |
printf(" %s:%s", a1, a2); |
|
368 |
1024 |
} |
|
369 |
|||
370 |
void |
||
371 |
print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int opts) |
||
372 |
{ |
||
373 |
1922 |
char a1[6], a2[6]; |
|
374 |
struct servent *s = NULL; |
||
375 |
|||
376 |
✗✓ | 961 |
if (opts & PF_OPT_PORTNAMES) |
377 |
s = getservbyport(p1, proto); |
||
378 |
961 |
p1 = ntohs(p1); |
|
379 |
961 |
p2 = ntohs(p2); |
|
380 |
961 |
snprintf(a1, sizeof(a1), "%u", p1); |
|
381 |
961 |
snprintf(a2, sizeof(a2), "%u", p2); |
|
382 |
961 |
printf(" port"); |
|
383 |
✗✓✗✗ ✗✗ |
961 |
if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) |
384 |
print_op(op, s->s_name, a2); |
||
385 |
else |
||
386 |
961 |
print_op(op, a1, a2); |
|
387 |
961 |
} |
|
388 |
|||
389 |
void |
||
390 |
print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) |
||
391 |
{ |
||
392 |
126 |
char a1[11], a2[11]; |
|
393 |
|||
394 |
63 |
snprintf(a1, sizeof(a1), "%u", u1); |
|
395 |
63 |
snprintf(a2, sizeof(a2), "%u", u2); |
|
396 |
63 |
printf(" %s", t); |
|
397 |
✗✓✗✗ ✗✗ |
63 |
if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) |
398 |
print_op(op, "unknown", a2); |
||
399 |
else |
||
400 |
63 |
print_op(op, a1, a2); |
|
401 |
63 |
} |
|
402 |
|||
403 |
void |
||
404 |
print_flags(u_int8_t f) |
||
405 |
{ |
||
406 |
int i; |
||
407 |
|||
408 |
✓✓ | 47196 |
for (i = 0; tcpflags[i]; ++i) |
409 |
✓✓ | 19872 |
if (f & (1 << i)) |
410 |
3786 |
printf("%c", tcpflags[i]); |
|
411 |
2484 |
} |
|
412 |
|||
413 |
void |
||
414 |
print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, |
||
415 |
sa_family_t af, u_int8_t proto, int opts) |
||
416 |
{ |
||
417 |
6682 |
char buf[PF_OSFP_LEN*3]; |
|
418 |
3341 |
int verbose = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); |
|
419 |
✓✓ | 3341 |
if (src->addr.type == PF_ADDR_ADDRMASK && |
420 |
✓✓ | 2900 |
dst->addr.type == PF_ADDR_ADDRMASK && |
421 |
✓✓✓✗ ✓✗✓✓ |
8132 |
PF_AZERO(&src->addr.v.a.addr, AF_INET6) && |
422 |
✓✓✓✗ ✓✗✓✗ |
7032 |
PF_AZERO(&src->addr.v.a.mask, AF_INET6) && |
423 |
✓✓✓✗ ✓✗✓✗ |
6050 |
PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && |
424 |
✓✓✓✗ ✓✗✓✗ |
5692 |
PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && |
425 |
✓✗✓✗ |
2840 |
!src->neg && !dst->neg && |
426 |
✓✓✓✓ |
4058 |
!src->port_op && !dst->port_op && |
427 |
1319 |
osfp == PF_OSFP_ANY) |
|
428 |
1130 |
printf(" all"); |
|
429 |
else { |
||
430 |
2211 |
printf(" from "); |
|
431 |
✓✓ | 2211 |
if (src->neg) |
432 |
77 |
printf("! "); |
|
433 |
2211 |
print_addr(&src->addr, af, verbose); |
|
434 |
✓✓ | 2211 |
if (src->port_op) |
435 |
620 |
print_port(src->port_op, src->port[0], |
|
436 |
310 |
src->port[1], |
|
437 |
310 |
proto == IPPROTO_TCP ? "tcp" : "udp", opts); |
|
438 |
✗✓ | 2211 |
if (osfp != PF_OSFP_ANY) |
439 |
printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, |
||
440 |
sizeof(buf))); |
||
441 |
|||
442 |
2211 |
printf(" to "); |
|
443 |
✓✓ | 2211 |
if (dst->neg) |
444 |
96 |
printf("! "); |
|
445 |
2211 |
print_addr(&dst->addr, af, verbose); |
|
446 |
✓✓ | 2211 |
if (dst->port_op) |
447 |
1302 |
print_port(dst->port_op, dst->port[0], |
|
448 |
651 |
dst->port[1], |
|
449 |
651 |
proto == IPPROTO_TCP ? "tcp" : "udp", opts); |
|
450 |
} |
||
451 |
3341 |
} |
|
452 |
|||
453 |
void |
||
454 |
print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, |
||
455 |
sa_family_t af, int id, int verbose) |
||
456 |
{ |
||
457 |
✓✓ | 1710 |
if (pool->ifname[0]) { |
458 |
✓✓✓✓ ✓✓✓✓ ✓✗✓✗ ✗✓ |
234 |
if (!PF_AZERO(&pool->addr.v.a.addr, af)) { |
459 |
44 |
print_addr(&pool->addr, af, verbose); |
|
460 |
44 |
printf("@"); |
|
461 |
44 |
} |
|
462 |
71 |
printf("%s", pool->ifname); |
|
463 |
71 |
} else |
|
464 |
784 |
print_addr(&pool->addr, af, verbose); |
|
465 |
✓✓✓ | 1631 |
switch (id) { |
466 |
case PF_POOL_NAT: |
||
467 |
✓✓✗✓ |
617 |
if ((p1 != PF_NAT_PROXY_PORT_LOW || |
468 |
✗✓✓✓ |
617 |
p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { |
469 |
✓✓ | 24 |
if (p1 == p2) |
470 |
8 |
printf(" port %u", p1); |
|
471 |
else |
||
472 |
16 |
printf(" port %u:%u", p1, p2); |
|
473 |
} |
||
474 |
break; |
||
475 |
case PF_POOL_RDR: |
||
476 |
✓✓ | 371 |
if (p1) { |
477 |
100 |
printf(" port %u", p1); |
|
478 |
✓✓✓✗ |
108 |
if (p2 && (p2 != p1)) |
479 |
8 |
printf(":%u", p2); |
|
480 |
} |
||
481 |
break; |
||
482 |
default: |
||
483 |
break; |
||
484 |
} |
||
485 |
✓✓✓✓ ✗✓ |
965 |
switch (pool->opts & PF_POOL_TYPEMASK) { |
486 |
case PF_POOL_NONE: |
||
487 |
break; |
||
488 |
case PF_POOL_BITMASK: |
||
489 |
12 |
printf(" bitmask"); |
|
490 |
12 |
break; |
|
491 |
case PF_POOL_RANDOM: |
||
492 |
16 |
printf(" random"); |
|
493 |
16 |
break; |
|
494 |
case PF_POOL_SRCHASH: |
||
495 |
20 |
printf(" source-hash 0x%08x%08x%08x%08x", |
|
496 |
20 |
pool->key.key32[0], pool->key.key32[1], |
|
497 |
20 |
pool->key.key32[2], pool->key.key32[3]); |
|
498 |
20 |
break; |
|
499 |
case PF_POOL_ROUNDROBIN: |
||
500 |
62 |
printf(" round-robin"); |
|
501 |
62 |
break; |
|
502 |
case PF_POOL_LEASTSTATES: |
||
503 |
printf(" least-states"); |
||
504 |
break; |
||
505 |
} |
||
506 |
✓✓ | 855 |
if (pool->opts & PF_POOL_STICKYADDR) |
507 |
12 |
printf(" sticky-address"); |
|
508 |
✓✓✓✓ ✓✗ |
1472 |
if (id == PF_POOL_NAT && p1 == 0 && p2 == 0) |
509 |
212 |
printf(" static-port"); |
|
510 |
855 |
} |
|
511 |
|||
512 |
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; |
||
513 |
const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; |
||
514 |
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; |
||
515 |
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES; |
||
516 |
|||
517 |
void |
||
518 |
print_status(struct pf_status *s, int opts) |
||
519 |
{ |
||
520 |
8 |
char statline[80], *running, *debug; |
|
521 |
time_t runtime = 0; |
||
522 |
4 |
struct timespec uptime; |
|
523 |
int i; |
||
524 |
4 |
char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; |
|
525 |
static const char hex[] = "0123456789abcdef"; |
||
526 |
|||
527 |
✓✗ | 4 |
if (!clock_gettime(CLOCK_UPTIME, &uptime)) |
528 |
4 |
runtime = uptime.tv_sec - s->since; |
|
529 |
4 |
running = s->running ? "Enabled" : "Disabled"; |
|
530 |
|||
531 |
✓✗ | 4 |
if (runtime) { |
532 |
unsigned int sec, min, hrs; |
||
533 |
time_t day = runtime; |
||
534 |
|||
535 |
4 |
sec = day % 60; |
|
536 |
4 |
day /= 60; |
|
537 |
4 |
min = day % 60; |
|
538 |
4 |
day /= 60; |
|
539 |
4 |
hrs = day % 24; |
|
540 |
4 |
day /= 24; |
|
541 |
4 |
snprintf(statline, sizeof(statline), |
|
542 |
"Status: %s for %lld days %.2u:%.2u:%.2u", |
||
543 |
running, (long long)day, hrs, min, sec); |
||
544 |
4 |
} else |
|
545 |
snprintf(statline, sizeof(statline), "Status: %s", running); |
||
546 |
4 |
printf("%-44s", statline); |
|
547 |
✓✗ | 4 |
if (asprintf(&debug, "Debug: %s", loglevel_to_string(s->debug)) != -1) { |
548 |
4 |
printf("%15s\n\n", debug); |
|
549 |
4 |
free(debug); |
|
550 |
4 |
} |
|
551 |
|||
552 |
✗✓ | 4 |
if (opts & PF_OPT_VERBOSE) { |
553 |
printf("Hostid: 0x%08x\n", ntohl(s->hostid)); |
||
554 |
|||
555 |
for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { |
||
556 |
buf[i + i] = hex[s->pf_chksum[i] >> 4]; |
||
557 |
buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; |
||
558 |
} |
||
559 |
buf[i + i] = '\0'; |
||
560 |
printf("Checksum: 0x%s\n\n", buf); |
||
561 |
} |
||
562 |
|||
563 |
✗✓ | 4 |
if (s->ifname[0] != 0) { |
564 |
printf("Interface Stats for %-16s %5s %16s\n", |
||
565 |
s->ifname, "IPv4", "IPv6"); |
||
566 |
printf(" %-25s %14llu %16llu\n", "Bytes In", |
||
567 |
(unsigned long long)s->bcounters[0][0], |
||
568 |
(unsigned long long)s->bcounters[1][0]); |
||
569 |
printf(" %-25s %14llu %16llu\n", "Bytes Out", |
||
570 |
(unsigned long long)s->bcounters[0][1], |
||
571 |
(unsigned long long)s->bcounters[1][1]); |
||
572 |
printf(" Packets In\n"); |
||
573 |
printf(" %-23s %14llu %16llu\n", "Passed", |
||
574 |
(unsigned long long)s->pcounters[0][0][PF_PASS], |
||
575 |
(unsigned long long)s->pcounters[1][0][PF_PASS]); |
||
576 |
printf(" %-23s %14llu %16llu\n", "Blocked", |
||
577 |
(unsigned long long)s->pcounters[0][0][PF_DROP], |
||
578 |
(unsigned long long)s->pcounters[1][0][PF_DROP]); |
||
579 |
printf(" Packets Out\n"); |
||
580 |
printf(" %-23s %14llu %16llu\n", "Passed", |
||
581 |
(unsigned long long)s->pcounters[0][1][PF_PASS], |
||
582 |
(unsigned long long)s->pcounters[1][1][PF_PASS]); |
||
583 |
printf(" %-23s %14llu %16llu\n\n", "Blocked", |
||
584 |
(unsigned long long)s->pcounters[0][1][PF_DROP], |
||
585 |
(unsigned long long)s->pcounters[1][1][PF_DROP]); |
||
586 |
} |
||
587 |
4 |
printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); |
|
588 |
4 |
printf(" %-25s %14u %14s\n", "current entries", s->states, ""); |
|
589 |
4 |
printf(" %-25s %14u %14s\n", "half-open tcp", s->states_halfopen, ""); |
|
590 |
✓✓ | 32 |
for (i = 0; i < FCNT_MAX; i++) { |
591 |
24 |
printf(" %-25s %14llu ", pf_fcounters[i], |
|
592 |
12 |
(unsigned long long)s->fcounters[i]); |
|
593 |
✓✗ | 12 |
if (runtime > 0) |
594 |
12 |
printf("%14.1f/s\n", |
|
595 |
12 |
(double)s->fcounters[i] / (double)runtime); |
|
596 |
else |
||
597 |
printf("%14s\n", ""); |
||
598 |
} |
||
599 |
✗✓ | 4 |
if (opts & PF_OPT_VERBOSE) { |
600 |
printf("Source Tracking Table\n"); |
||
601 |
printf(" %-25s %14u %14s\n", "current entries", |
||
602 |
s->src_nodes, ""); |
||
603 |
for (i = 0; i < SCNT_MAX; i++) { |
||
604 |
printf(" %-25s %14lld ", pf_scounters[i], |
||
605 |
s->scounters[i]); |
||
606 |
if (runtime > 0) |
||
607 |
printf("%14.1f/s\n", |
||
608 |
(double)s->scounters[i] / (double)runtime); |
||
609 |
else |
||
610 |
printf("%14s\n", ""); |
||
611 |
} |
||
612 |
} |
||
613 |
4 |
printf("Counters\n"); |
|
614 |
✓✓ | 144 |
for (i = 0; i < PFRES_MAX; i++) { |
615 |
136 |
printf(" %-25s %14llu ", pf_reasons[i], |
|
616 |
68 |
(unsigned long long)s->counters[i]); |
|
617 |
✓✗ | 68 |
if (runtime > 0) |
618 |
68 |
printf("%14.1f/s\n", |
|
619 |
68 |
(double)s->counters[i] / (double)runtime); |
|
620 |
else |
||
621 |
printf("%14s\n", ""); |
||
622 |
} |
||
623 |
✗✓ | 4 |
if (opts & PF_OPT_VERBOSE) { |
624 |
printf("Limit Counters\n"); |
||
625 |
for (i = 0; i < LCNT_MAX; i++) { |
||
626 |
printf(" %-25s %14lld ", pf_lcounters[i], |
||
627 |
s->lcounters[i]); |
||
628 |
if (runtime > 0) |
||
629 |
printf("%14.1f/s\n", |
||
630 |
(double)s->lcounters[i] / (double)runtime); |
||
631 |
else |
||
632 |
printf("%14s\n", ""); |
||
633 |
} |
||
634 |
} |
||
635 |
4 |
} |
|
636 |
|||
637 |
void |
||
638 |
print_src_node(struct pf_src_node *sn, int opts) |
||
639 |
{ |
||
640 |
struct pf_addr_wrap aw; |
||
641 |
int min, sec; |
||
642 |
|||
643 |
memset(&aw, 0, sizeof(aw)); |
||
644 |
if (sn->af == AF_INET) |
||
645 |
aw.v.a.mask.addr32[0] = 0xffffffff; |
||
646 |
else |
||
647 |
memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); |
||
648 |
|||
649 |
aw.v.a.addr = sn->addr; |
||
650 |
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); |
||
651 |
|||
652 |
if (!PF_AZERO(&sn->raddr, sn->af)) { |
||
653 |
if (sn->type == PF_SN_NAT) |
||
654 |
printf(" nat-to "); |
||
655 |
else if (sn->type == PF_SN_RDR) |
||
656 |
printf(" rdr-to "); |
||
657 |
else if (sn->type == PF_SN_ROUTE) |
||
658 |
printf(" route-to "); |
||
659 |
else |
||
660 |
printf(" ??? (%u) ", sn->type); |
||
661 |
aw.v.a.addr = sn->raddr; |
||
662 |
print_addr(&aw, sn->naf ? sn->naf : sn->af, |
||
663 |
opts & PF_OPT_VERBOSE2); |
||
664 |
} |
||
665 |
|||
666 |
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, |
||
667 |
sn->conn, sn->conn_rate.count / 1000, |
||
668 |
(sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); |
||
669 |
if (opts & PF_OPT_VERBOSE) { |
||
670 |
sec = sn->creation % 60; |
||
671 |
sn->creation /= 60; |
||
672 |
min = sn->creation % 60; |
||
673 |
sn->creation /= 60; |
||
674 |
printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); |
||
675 |
if (sn->states == 0) { |
||
676 |
sec = sn->expire % 60; |
||
677 |
sn->expire /= 60; |
||
678 |
min = sn->expire % 60; |
||
679 |
sn->expire /= 60; |
||
680 |
printf(", expires in %.2u:%.2u:%.2u", |
||
681 |
sn->expire, min, sec); |
||
682 |
} |
||
683 |
printf(", %llu pkts, %llu bytes", |
||
684 |
sn->packets[0] + sn->packets[1], |
||
685 |
sn->bytes[0] + sn->bytes[1]); |
||
686 |
if (sn->rule.nr != -1) |
||
687 |
printf(", rule %u", sn->rule.nr); |
||
688 |
printf("\n"); |
||
689 |
} |
||
690 |
} |
||
691 |
|||
692 |
void |
||
693 |
print_rule(struct pf_rule *r, const char *anchor_call, int opts) |
||
694 |
{ |
||
695 |
static const char *actiontypes[] = { "pass", "block", "scrub", |
||
696 |
"no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr", |
||
697 |
"", "", "match"}; |
||
698 |
static const char *anchortypes[] = { "anchor", "anchor", "anchor", |
||
699 |
"anchor", "nat-anchor", "nat-anchor", "binat-anchor", |
||
700 |
"binat-anchor", "rdr-anchor", "rdr-anchor" }; |
||
701 |
int i, ropts; |
||
702 |
6682 |
int verbose = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); |
|
703 |
char *p; |
||
704 |
|||
705 |
✗✓ | 3341 |
if ((r->rule_flag & PFRULE_EXPIRED) && (!verbose)) |
706 |
return; |
||
707 |
|||
708 |
✓✓ | 3341 |
if (verbose) |
709 |
1476 |
printf("@%d ", r->nr); |
|
710 |
|||
711 |
✗✓ | 3341 |
if (r->action > PF_MATCH) |
712 |
printf("action(%d)", r->action); |
||
713 |
✓✓ | 3341 |
else if (anchor_call[0]) { |
714 |
126 |
p = strrchr(anchor_call, '/'); |
|
715 |
✓✓✗✓ ✓✓ |
252 |
if (p ? p[1] == '_' : anchor_call[0] == '_') |
716 |
60 |
printf("%s", anchortypes[r->action]); |
|
717 |
else |
||
718 |
66 |
printf("%s \"%s\"", anchortypes[r->action], |
|
719 |
anchor_call); |
||
720 |
} else |
||
721 |
3215 |
printf("%s", actiontypes[r->action]); |
|
722 |
✓✓ | 3341 |
if (r->action == PF_DROP) { |
723 |
✓✓ | 701 |
if (r->rule_flag & PFRULE_RETURN) |
724 |
34 |
printf(" return"); |
|
725 |
✓✓ | 667 |
else if (r->rule_flag & PFRULE_RETURNRST) { |
726 |
✓✓ | 36 |
if (!r->return_ttl) |
727 |
28 |
printf(" return-rst"); |
|
728 |
else |
||
729 |
8 |
printf(" return-rst(ttl %d)", r->return_ttl); |
|
730 |
✓✓ | 631 |
} else if (r->rule_flag & PFRULE_RETURNICMP) { |
731 |
const struct icmpcodeent *ic, *ic6; |
||
732 |
|||
733 |
186 |
ic = geticmpcodebynumber(r->return_icmp >> 8, |
|
734 |
93 |
r->return_icmp & 255, AF_INET); |
|
735 |
186 |
ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, |
|
736 |
93 |
r->return_icmp6 & 255, AF_INET6); |
|
737 |
|||
738 |
✓✓✓ | 93 |
switch (r->af) { |
739 |
case AF_INET: |
||
740 |
32 |
printf(" return-icmp"); |
|
741 |
✗✓ | 32 |
if (ic == NULL) |
742 |
printf("(%u)", r->return_icmp & 255); |
||
743 |
else |
||
744 |
32 |
printf("(%s)", ic->name); |
|
745 |
break; |
||
746 |
case AF_INET6: |
||
747 |
38 |
printf(" return-icmp6"); |
|
748 |
✗✓ | 38 |
if (ic6 == NULL) |
749 |
printf("(%u)", r->return_icmp6 & 255); |
||
750 |
else |
||
751 |
38 |
printf("(%s)", ic6->name); |
|
752 |
break; |
||
753 |
default: |
||
754 |
23 |
printf(" return-icmp"); |
|
755 |
✗✓ | 23 |
if (ic == NULL) |
756 |
printf("(%u, ", r->return_icmp & 255); |
||
757 |
else |
||
758 |
23 |
printf("(%s, ", ic->name); |
|
759 |
✗✓ | 23 |
if (ic6 == NULL) |
760 |
printf("%u)", r->return_icmp6 & 255); |
||
761 |
else |
||
762 |
23 |
printf("%s)", ic6->name); |
|
763 |
break; |
||
764 |
} |
||
765 |
93 |
} else |
|
766 |
538 |
printf(" drop"); |
|
767 |
} |
||
768 |
✓✓ | 3341 |
if (r->direction == PF_IN) |
769 |
2135 |
printf(" in"); |
|
770 |
✓✓ | 1206 |
else if (r->direction == PF_OUT) |
771 |
700 |
printf(" out"); |
|
772 |
✓✓ | 3341 |
if (r->log) { |
773 |
287 |
printf(" log"); |
|
774 |
✓✓✓✓ |
530 |
if (r->log & ~PF_LOG || r->logif) { |
775 |
int count = 0; |
||
776 |
|||
777 |
48 |
printf(" ("); |
|
778 |
✓✓ | 48 |
if (r->log & PF_LOG_ALL) |
779 |
36 |
printf("%sall", count++ ? ", " : ""); |
|
780 |
✗✓ | 48 |
if (r->log & PF_LOG_MATCHES) |
781 |
printf("%smatches", count++ ? ", " : ""); |
||
782 |
✓✓ | 48 |
if (r->log & PF_LOG_SOCKET_LOOKUP) |
783 |
12 |
printf("%suser", count++ ? ", " : ""); |
|
784 |
✓✓ | 48 |
if (r->logif) |
785 |
24 |
printf("%sto pflog%u", count++ ? ", " : "", |
|
786 |
12 |
r->logif); |
|
787 |
48 |
printf(")"); |
|
788 |
48 |
} |
|
789 |
} |
||
790 |
✓✓ | 3341 |
if (r->quick) |
791 |
214 |
printf(" quick"); |
|
792 |
✓✓ | 3341 |
if (r->ifname[0]) { |
793 |
✓✓ | 1924 |
if (r->ifnot) |
794 |
52 |
printf(" on ! %s", r->ifname); |
|
795 |
else |
||
796 |
1872 |
printf(" on %s", r->ifname); |
|
797 |
} |
||
798 |
✗✓ | 3341 |
if (r->onrdomain >= 0) { |
799 |
if (r->ifnot) |
||
800 |
printf(" on ! rdomain %d", r->onrdomain); |
||
801 |
else |
||
802 |
printf(" on rdomain %d", r->onrdomain); |
||
803 |
} |
||
804 |
✓✓ | 3341 |
if (r->af) { |
805 |
✓✓ | 2114 |
if (r->af == AF_INET) |
806 |
1589 |
printf(" inet"); |
|
807 |
else |
||
808 |
525 |
printf(" inet6"); |
|
809 |
} |
||
810 |
✓✓ | 3341 |
if (r->proto) { |
811 |
struct protoent *p; |
||
812 |
|||
813 |
✓✓ | 1382 |
if ((p = getprotobynumber(r->proto)) != NULL) |
814 |
1370 |
printf(" proto %s", p->p_name); |
|
815 |
else |
||
816 |
12 |
printf(" proto %u", r->proto); |
|
817 |
1382 |
} |
|
818 |
3341 |
print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, |
|
819 |
opts); |
||
820 |
✗✓ | 3341 |
if (r->rcv_ifname[0]) |
821 |
printf(" %sreceived-on %s", r->rcvifnot ? "!" : "", |
||
822 |
r->rcv_ifname); |
||
823 |
✓✓ | 3341 |
if (r->uid.op) |
824 |
33 |
print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", |
|
825 |
UID_MAX); |
||
826 |
✓✓ | 3341 |
if (r->gid.op) |
827 |
30 |
print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", |
|
828 |
GID_MAX); |
||
829 |
✓✓✓✓ |
5444 |
if (r->flags || r->flagset) { |
830 |
1242 |
printf(" flags "); |
|
831 |
1242 |
print_flags(r->flags); |
|
832 |
1242 |
printf("/"); |
|
833 |
1242 |
print_flags(r->flagset); |
|
834 |
✓✓✓✓ ✓✓ |
6061 |
} else if ((r->action == PF_PASS || r->action == PF_MATCH) && |
835 |
✓✓✓✓ |
2040 |
(!r->proto || r->proto == IPPROTO_TCP) && |
836 |
✓✓ | 1134 |
!(r->rule_flag & PFRULE_FRAGMENT) && |
837 |
✓✓ | 2138 |
!anchor_call[0] && r->keep_state) |
838 |
4 |
printf(" flags any"); |
|
839 |
✓✓ | 3341 |
if (r->type) { |
840 |
const struct icmptypeent *it; |
||
841 |
|||
842 |
98 |
it = geticmptypebynumber(r->type-1, r->af); |
|
843 |
✓✓ | 98 |
if (r->af != AF_INET6) |
844 |
62 |
printf(" icmp-type"); |
|
845 |
else |
||
846 |
36 |
printf(" icmp6-type"); |
|
847 |
✓✓ | 98 |
if (it != NULL) |
848 |
66 |
printf(" %s", it->name); |
|
849 |
else |
||
850 |
32 |
printf(" %u", r->type-1); |
|
851 |
✓✓ | 98 |
if (r->code) { |
852 |
const struct icmpcodeent *ic; |
||
853 |
|||
854 |
64 |
ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); |
|
855 |
✓✓ | 64 |
if (ic != NULL) |
856 |
16 |
printf(" code %s", ic->name); |
|
857 |
else |
||
858 |
48 |
printf(" code %u", r->code-1); |
|
859 |
64 |
} |
|
860 |
98 |
} |
|
861 |
✓✓ | 3341 |
if (r->tos) |
862 |
32 |
printf(" tos 0x%2.2x", r->tos); |
|
863 |
✗✓ | 3341 |
if (r->prio) |
864 |
printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); |
||
865 |
|||
866 |
✓✓✓✓ |
6625 |
if (r->scrub_flags & PFSTATE_SETMASK || r->qname[0]) { |
867 |
char *comma = ""; |
||
868 |
59 |
printf(" set ("); |
|
869 |
✓✓ | 59 |
if (r->scrub_flags & PFSTATE_SETPRIO) { |
870 |
✓✓ | 40 |
if (r->set_prio[0] == r->set_prio[1]) |
871 |
36 |
printf("%s prio %u", comma, r->set_prio[0]); |
|
872 |
else |
||
873 |
4 |
printf("%s prio(%u, %u)", comma, r->set_prio[0], |
|
874 |
r->set_prio[1]); |
||
875 |
comma = ","; |
||
876 |
40 |
} |
|
877 |
✓✓ | 59 |
if (r->qname[0]) { |
878 |
✗✓ | 2 |
if (r->pqname[0]) |
879 |
printf("%s queue(%s, %s)", comma, r->qname, |
||
880 |
r->pqname); |
||
881 |
else |
||
882 |
2 |
printf("%s queue %s", comma, r->qname); |
|
883 |
comma = ","; |
||
884 |
2 |
} |
|
885 |
✓✓ | 59 |
if (r->scrub_flags & PFSTATE_SETTOS) { |
886 |
17 |
printf("%s tos 0x%2.2x", comma, r->set_tos); |
|
887 |
comma = ","; |
||
888 |
17 |
} |
|
889 |
59 |
printf(" )"); |
|
890 |
59 |
} |
|
891 |
|||
892 |
ropts = 0; |
||
893 |
✓✓✓✓ ✓✓ |
10007 |
if (r->max_states || r->max_src_nodes || r->max_src_states) |
894 |
16 |
ropts = 1; |
|
895 |
✓✓ | 3341 |
if (r->rule_flag & PFRULE_NOSYNC) |
896 |
4 |
ropts = 1; |
|
897 |
✓✓ | 3341 |
if (r->rule_flag & PFRULE_SRCTRACK) |
898 |
40 |
ropts = 1; |
|
899 |
✗✓ | 3341 |
if (r->rule_flag & PFRULE_IFBOUND) |
900 |
ropts = 1; |
||
901 |
✗✓ | 3341 |
if (r->rule_flag & PFRULE_STATESLOPPY) |
902 |
ropts = 1; |
||
903 |
✗✓ | 3341 |
if (r->rule_flag & PFRULE_PFLOW) |
904 |
ropts = 1; |
||
905 |
✓✓ | 138426 |
for (i = 0; !ropts && i < PFTM_MAX; ++i) |
906 |
✓✓ | 65872 |
if (r->timeout[i]) |
907 |
4 |
ropts = 1; |
|
908 |
|||
909 |
✓✓✓✓ ✓✓ |
5383 |
if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) |
910 |
33 |
printf(" no state"); |
|
911 |
✓✓ | 3308 |
else if (r->keep_state == PF_STATE_NORMAL && ropts) |
912 |
40 |
printf(" keep state"); |
|
913 |
✓✓ | 3268 |
else if (r->keep_state == PF_STATE_MODULATE) |
914 |
36 |
printf(" modulate state"); |
|
915 |
✓✓ | 3232 |
else if (r->keep_state == PF_STATE_SYNPROXY) |
916 |
16 |
printf(" synproxy state"); |
|
917 |
✓✓ | 3341 |
if (r->prob) { |
918 |
12 |
char buf[20]; |
|
919 |
|||
920 |
12 |
snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); |
|
921 |
✓✗ | 160 |
for (i = strlen(buf)-1; i > 0; i--) { |
922 |
✓✓ | 80 |
if (buf[i] == '0') |
923 |
68 |
buf[i] = '\0'; |
|
924 |
else { |
||
925 |
✓✓ | 12 |
if (buf[i] == '.') |
926 |
8 |
buf[i] = '\0'; |
|
927 |
break; |
||
928 |
} |
||
929 |
} |
||
930 |
12 |
printf(" probability %s%%", buf); |
|
931 |
12 |
} |
|
932 |
✓✓ | 3341 |
if (ropts) { |
933 |
48 |
printf(" ("); |
|
934 |
✓✓ | 48 |
if (r->max_states) { |
935 |
4 |
printf("max %u", r->max_states); |
|
936 |
ropts = 0; |
||
937 |
4 |
} |
|
938 |
✓✓ | 48 |
if (r->rule_flag & PFRULE_NOSYNC) { |
939 |
✓✗ | 4 |
if (!ropts) |
940 |
4 |
printf(", "); |
|
941 |
4 |
printf("no-sync"); |
|
942 |
ropts = 0; |
||
943 |
4 |
} |
|
944 |
✓✓ | 48 |
if (r->rule_flag & PFRULE_SRCTRACK) { |
945 |
✗✓ | 40 |
if (!ropts) |
946 |
printf(", "); |
||
947 |
40 |
printf("source-track"); |
|
948 |
✓✓ | 40 |
if (r->rule_flag & PFRULE_RULESRCTRACK) |
949 |
28 |
printf(" rule"); |
|
950 |
else |
||
951 |
12 |
printf(" global"); |
|
952 |
ropts = 0; |
||
953 |
40 |
} |
|
954 |
✓✓ | 48 |
if (r->max_src_states) { |
955 |
✓✗ | 8 |
if (!ropts) |
956 |
8 |
printf(", "); |
|
957 |
8 |
printf("max-src-states %u", r->max_src_states); |
|
958 |
ropts = 0; |
||
959 |
8 |
} |
|
960 |
✓✓ | 48 |
if (r->max_src_conn) { |
961 |
✓✗ | 16 |
if (!ropts) |
962 |
16 |
printf(", "); |
|
963 |
16 |
printf("max-src-conn %u", r->max_src_conn); |
|
964 |
ropts = 0; |
||
965 |
16 |
} |
|
966 |
✓✓ | 48 |
if (r->max_src_conn_rate.limit) { |
967 |
✓✗ | 16 |
if (!ropts) |
968 |
16 |
printf(", "); |
|
969 |
16 |
printf("max-src-conn-rate %u/%u", |
|
970 |
16 |
r->max_src_conn_rate.limit, |
|
971 |
16 |
r->max_src_conn_rate.seconds); |
|
972 |
ropts = 0; |
||
973 |
16 |
} |
|
974 |
✓✓ | 48 |
if (r->max_src_nodes) { |
975 |
✓✗ | 8 |
if (!ropts) |
976 |
8 |
printf(", "); |
|
977 |
8 |
printf("max-src-nodes %u", r->max_src_nodes); |
|
978 |
ropts = 0; |
||
979 |
8 |
} |
|
980 |
✓✓ | 48 |
if (r->overload_tblname[0]) { |
981 |
✓✗ | 8 |
if (!ropts) |
982 |
8 |
printf(", "); |
|
983 |
8 |
printf("overload <%s>", r->overload_tblname); |
|
984 |
✓✗ | 8 |
if (r->flush) |
985 |
8 |
printf(" flush"); |
|
986 |
✓✓ | 8 |
if (r->flush & PF_FLUSH_GLOBAL) |
987 |
4 |
printf(" global"); |
|
988 |
} |
||
989 |
✗✓ | 48 |
if (r->rule_flag & PFRULE_IFBOUND) { |
990 |
if (!ropts) |
||
991 |
printf(", "); |
||
992 |
printf("if-bound"); |
||
993 |
ropts = 0; |
||
994 |
} |
||
995 |
✗✓ | 48 |
if (r->rule_flag & PFRULE_STATESLOPPY) { |
996 |
if (!ropts) |
||
997 |
printf(", "); |
||
998 |
printf("sloppy"); |
||
999 |
ropts = 0; |
||
1000 |
} |
||
1001 |
✗✓ | 48 |
if (r->rule_flag & PFRULE_PFLOW) { |
1002 |
if (!ropts) |
||
1003 |
printf(", "); |
||
1004 |
printf("pflow"); |
||
1005 |
ropts = 0; |
||
1006 |
} |
||
1007 |
✓✓ | 2016 |
for (i = 0; i < PFTM_MAX; ++i) |
1008 |
✓✓ | 960 |
if (r->timeout[i]) { |
1009 |
int j; |
||
1010 |
|||
1011 |
✓✓ | 32 |
if (!ropts) |
1012 |
28 |
printf(", "); |
|
1013 |
ropts = 0; |
||
1014 |
✓✗ | 968 |
for (j = 0; pf_timeouts[j].name != NULL; |
1015 |
452 |
++j) |
|
1016 |
✓✓ | 484 |
if (pf_timeouts[j].timeout == i) |
1017 |
break; |
||
1018 |
✓✗ | 128 |
printf("%s %u", pf_timeouts[j].name == NULL ? |
1019 |
"inv.timeout" : pf_timeouts[j].name, |
||
1020 |
32 |
r->timeout[i]); |
|
1021 |
32 |
} |
|
1022 |
48 |
printf(")"); |
|
1023 |
48 |
} |
|
1024 |
|||
1025 |
✓✓ | 3341 |
if (r->rule_flag & PFRULE_FRAGMENT) |
1026 |
4 |
printf(" fragment"); |
|
1027 |
|||
1028 |
✓✓✓✓ ✓✓ |
9787 |
if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) { |
1029 |
143 |
printf(" scrub ("); |
|
1030 |
ropts = 1; |
||
1031 |
✓✓ | 143 |
if (r->scrub_flags & PFSTATE_NODF) { |
1032 |
96 |
printf("no-df"); |
|
1033 |
ropts = 0; |
||
1034 |
96 |
} |
|
1035 |
✓✓ | 143 |
if (r->scrub_flags & PFSTATE_RANDOMID) { |
1036 |
✗✓ | 8 |
if (!ropts) |
1037 |
printf(" "); |
||
1038 |
8 |
printf("random-id"); |
|
1039 |
ropts = 0; |
||
1040 |
8 |
} |
|
1041 |
✓✓ | 143 |
if (r->min_ttl) { |
1042 |
✓✓ | 86 |
if (!ropts) |
1043 |
74 |
printf(" "); |
|
1044 |
86 |
printf("min-ttl %d", r->min_ttl); |
|
1045 |
ropts = 0; |
||
1046 |
86 |
} |
|
1047 |
✓✓ | 143 |
if (r->scrub_flags & PFSTATE_SCRUB_TCP) { |
1048 |
✓✓ | 12 |
if (!ropts) |
1049 |
4 |
printf(" "); |
|
1050 |
12 |
printf("reassemble tcp"); |
|
1051 |
ropts = 0; |
||
1052 |
12 |
} |
|
1053 |
✓✓ | 143 |
if (r->max_mss) { |
1054 |
✓✓ | 105 |
if (!ropts) |
1055 |
86 |
printf(" "); |
|
1056 |
105 |
printf("max-mss %d", r->max_mss); |
|
1057 |
ropts = 0; |
||
1058 |
105 |
} |
|
1059 |
143 |
printf(")"); |
|
1060 |
143 |
} |
|
1061 |
|||
1062 |
✓✓ | 3341 |
if (r->allow_opts) |
1063 |
24 |
printf(" allow-opts"); |
|
1064 |
✓✓ | 3341 |
if (r->label[0]) |
1065 |
312 |
printf(" label \"%s\"", r->label); |
|
1066 |
✗✓ | 3341 |
if (r->rule_flag & PFRULE_ONCE) |
1067 |
printf(" once"); |
||
1068 |
✓✓ | 3341 |
if (r->tagname[0]) |
1069 |
26 |
printf(" tag %s", r->tagname); |
|
1070 |
✓✓ | 3341 |
if (r->match_tagname[0]) { |
1071 |
✓✓ | 34 |
if (r->match_tag_not) |
1072 |
4 |
printf(" !"); |
|
1073 |
34 |
printf(" tagged %s", r->match_tagname); |
|
1074 |
34 |
} |
|
1075 |
✓✓ | 3341 |
if (r->rtableid != -1) |
1076 |
2 |
printf(" rtable %u", r->rtableid); |
|
1077 |
✓✓ | 3341 |
if (r->divert.port) { |
1078 |
✓✓✓✗ ✓✗✓✓ |
46 |
if (PF_AZERO(&r->divert.addr, AF_INET6)) { |
1079 |
2 |
printf(" divert-reply"); |
|
1080 |
2 |
} else { |
|
1081 |
/* XXX cut&paste from print_addr */ |
||
1082 |
20 |
char buf[48]; |
|
1083 |
|||
1084 |
20 |
printf(" divert-to "); |
|
1085 |
✗✓ | 40 |
if (inet_ntop(r->af, &r->divert.addr, buf, |
1086 |
20 |
sizeof(buf)) == NULL) |
|
1087 |
printf("?"); |
||
1088 |
else |
||
1089 |
20 |
printf("%s", buf); |
|
1090 |
20 |
printf(" port %u", ntohs(r->divert.port)); |
|
1091 |
20 |
} |
|
1092 |
} |
||
1093 |
✗✓ | 3341 |
if (r->divert_packet.port) |
1094 |
printf(" divert-packet port %u", ntohs(r->divert_packet.port)); |
||
1095 |
|||
1096 |
✓✓✓✓ ✗✓ |
6961 |
if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE && |
1097 |
405 |
r->rule_flag & PFRULE_AFTO) { |
|
1098 |
printf(" af-to %s from ", r->naf == AF_INET ? "inet" : "inet6"); |
||
1099 |
print_pool(&r->nat, r->nat.proxy_port[0], |
||
1100 |
r->nat.proxy_port[1], r->naf ? r->naf : r->af, |
||
1101 |
PF_POOL_NAT, verbose); |
||
1102 |
if (r->rdr.addr.type != PF_ADDR_NONE) { |
||
1103 |
printf(" to "); |
||
1104 |
print_pool(&r->rdr, r->rdr.proxy_port[0], |
||
1105 |
r->rdr.proxy_port[1], r->naf ? r->naf : r->af, |
||
1106 |
PF_POOL_RDR, verbose); |
||
1107 |
} |
||
1108 |
✓✓✓✓ |
6556 |
} else if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE) { |
1109 |
405 |
printf (" nat-to "); |
|
1110 |
810 |
print_pool(&r->nat, r->nat.proxy_port[0], |
|
1111 |
✗✓ | 810 |
r->nat.proxy_port[1], r->naf ? r->naf : r->af, |
1112 |
PF_POOL_NAT, verbose); |
||
1113 |
✓✓✓✓ |
6151 |
} else if (!anchor_call[0] && r->rdr.addr.type != PF_ADDR_NONE) { |
1114 |
371 |
printf (" rdr-to "); |
|
1115 |
742 |
print_pool(&r->rdr, r->rdr.proxy_port[0], |
|
1116 |
371 |
r->rdr.proxy_port[1], r->af, PF_POOL_RDR, verbose); |
|
1117 |
371 |
} |
|
1118 |
✓✓ | 3341 |
if (r->rt) { |
1119 |
✓✓ | 79 |
if (r->rt == PF_ROUTETO) |
1120 |
35 |
printf(" route-to"); |
|
1121 |
✓✓ | 44 |
else if (r->rt == PF_REPLYTO) |
1122 |
20 |
printf(" reply-to"); |
|
1123 |
✓✗ | 24 |
else if (r->rt == PF_DUPTO) |
1124 |
24 |
printf(" dup-to"); |
|
1125 |
79 |
printf(" "); |
|
1126 |
79 |
print_pool(&r->route, 0, 0, r->af, PF_POOL_ROUTE, verbose); |
|
1127 |
79 |
} |
|
1128 |
6682 |
} |
|
1129 |
|||
1130 |
void |
||
1131 |
print_tabledef(const char *name, int flags, int addrs, |
||
1132 |
struct node_tinithead *nodes) |
||
1133 |
{ |
||
1134 |
struct node_tinit *ti, *nti; |
||
1135 |
struct node_host *h; |
||
1136 |
|||
1137 |
68 |
printf("table <%s>", name); |
|
1138 |
✓✓ | 34 |
if (flags & PFR_TFLAG_CONST) |
1139 |
29 |
printf(" const"); |
|
1140 |
✓✓ | 34 |
if (flags & PFR_TFLAG_PERSIST) |
1141 |
2 |
printf(" persist"); |
|
1142 |
✗✓ | 34 |
if (flags & PFR_TFLAG_COUNTERS) |
1143 |
printf(" counters"); |
||
1144 |
✓✓ | 140 |
SIMPLEQ_FOREACH(ti, nodes, entries) { |
1145 |
✓✓ | 36 |
if (ti->file) { |
1146 |
2 |
printf(" file \"%s\"", ti->file); |
|
1147 |
2 |
continue; |
|
1148 |
} |
||
1149 |
34 |
printf(" {"); |
|
1150 |
48 |
for (;;) { |
|
1151 |
✓✓ | 254 |
for (h = ti->host; h != NULL; h = h->next) { |
1152 |
79 |
printf(h->not ? " !" : " "); |
|
1153 |
79 |
print_addr(&h->addr, h->af, 0); |
|
1154 |
✓✓ | 79 |
if (h->ifname) |
1155 |
8 |
printf("@%s", h->ifname); |
|
1156 |
} |
||
1157 |
48 |
nti = SIMPLEQ_NEXT(ti, entries); |
|
1158 |
✓✓✓✓ |
64 |
if (nti != NULL && nti->file == NULL) |
1159 |
ti = nti; /* merge lists */ |
||
1160 |
else |
||
1161 |
break; |
||
1162 |
} |
||
1163 |
34 |
printf(" }"); |
|
1164 |
34 |
} |
|
1165 |
✓✓✗✓ |
66 |
if (addrs && SIMPLEQ_EMPTY(nodes)) |
1166 |
printf(" { }"); |
||
1167 |
34 |
printf("\n"); |
|
1168 |
34 |
} |
|
1169 |
|||
1170 |
void |
||
1171 |
print_bwspec(const char *prefix, struct pf_queue_bwspec *bw) |
||
1172 |
{ |
||
1173 |
u_int rate; |
||
1174 |
int i; |
||
1175 |
static const char unit[] = " KMG"; |
||
1176 |
|||
1177 |
✗✓ | 108 |
if (bw->percent) |
1178 |
printf("%s%u%%", prefix, bw->percent); |
||
1179 |
✓✓ | 54 |
else if (bw->absolute) { |
1180 |
rate = bw->absolute; |
||
1181 |
✓✓✓✗ |
114 |
for (i = 0; rate >= 1000 && i <= 3 && (rate % 1000 == 0); i++) |
1182 |
26 |
rate /= 1000; |
|
1183 |
18 |
printf("%s%u%c", prefix, rate, unit[i]); |
|
1184 |
18 |
} |
|
1185 |
54 |
} |
|
1186 |
|||
1187 |
void |
||
1188 |
print_scspec(const char *prefix, struct pf_queue_scspec *sc) |
||
1189 |
{ |
||
1190 |
108 |
print_bwspec(prefix, &sc->m2); |
|
1191 |
✗✓ | 54 |
if (sc->d) { |
1192 |
printf(" burst "); |
||
1193 |
print_bwspec("", &sc->m1); |
||
1194 |
printf(" for %ums", sc->d); |
||
1195 |
} |
||
1196 |
54 |
} |
|
1197 |
|||
1198 |
void |
||
1199 |
print_queuespec(struct pf_queuespec *q) |
||
1200 |
{ |
||
1201 |
52 |
printf("queue %s", q->qname); |
|
1202 |
✓✓ | 26 |
if (q->parent[0]) |
1203 |
10 |
printf(" parent %s", q->parent); |
|
1204 |
✓✗ | 16 |
else if (q->ifname[0]) |
1205 |
16 |
printf(" on %s", q->ifname); |
|
1206 |
✓✓ | 26 |
if (q->flags & PFQS_FLOWQUEUE) { |
1207 |
14 |
printf(" flows %u", q->flowqueue.flows); |
|
1208 |
✓✓ | 14 |
if (q->flowqueue.quantum > 0) |
1209 |
6 |
printf(" quantum %u", q->flowqueue.quantum); |
|
1210 |
✗✓ | 14 |
if (q->flowqueue.interval > 0) |
1211 |
printf(" interval %ums", |
||
1212 |
q->flowqueue.interval / 1000000); |
||
1213 |
✗✓ | 14 |
if (q->flowqueue.target > 0) |
1214 |
printf(" target %ums", |
||
1215 |
q->flowqueue.target / 1000000); |
||
1216 |
} |
||
1217 |
✓✓✗✓ |
34 |
if (q->linkshare.m1.absolute || q->linkshare.m2.absolute) { |
1218 |
18 |
print_scspec(" bandwidth ", &q->linkshare); |
|
1219 |
18 |
print_scspec(", min ", &q->realtime); |
|
1220 |
18 |
print_scspec(", max ", &q->upperlimit); |
|
1221 |
18 |
} |
|
1222 |
✓✓ | 26 |
if (q->flags & PFQS_DEFAULT) |
1223 |
8 |
printf(" default"); |
|
1224 |
✓✓ | 26 |
if (q->qlimit) |
1225 |
4 |
printf(" qlimit %u", q->qlimit); |
|
1226 |
26 |
printf("\n"); |
|
1227 |
26 |
} |
|
1228 |
|||
1229 |
int |
||
1230 |
parse_flags(char *s) |
||
1231 |
{ |
||
1232 |
char *p, *q; |
||
1233 |
u_int8_t f = 0; |
||
1234 |
|||
1235 |
✓✓ | 16685 |
for (p = s; *p; p++) { |
1236 |
✗✓ | 4219 |
if ((q = strchr(tcpflags, *p)) == NULL) |
1237 |
return -1; |
||
1238 |
else |
||
1239 |
4219 |
f |= 1 << (q - tcpflags); |
|
1240 |
} |
||
1241 |
2749 |
return (f ? f : PF_TH_ALL); |
|
1242 |
2749 |
} |
|
1243 |
|||
1244 |
void |
||
1245 |
set_ipmask(struct node_host *h, u_int8_t b) |
||
1246 |
{ |
||
1247 |
struct pf_addr *m, *n; |
||
1248 |
int i, j = 0; |
||
1249 |
|||
1250 |
6452 |
m = &h->addr.v.a.mask; |
|
1251 |
3226 |
memset(m, 0, sizeof(*m)); |
|
1252 |
|||
1253 |
✓✓ | 17890 |
while (b >= 32) { |
1254 |
5719 |
m->addr32[j++] = 0xffffffff; |
|
1255 |
5719 |
b -= 32; |
|
1256 |
} |
||
1257 |
✓✓ | 30760 |
for (i = 31; i > 31-b; --i) |
1258 |
12154 |
m->addr32[j] |= (1 << i); |
|
1259 |
✓✓ | 3226 |
if (b) |
1260 |
720 |
m->addr32[j] = htonl(m->addr32[j]); |
|
1261 |
|||
1262 |
/* Mask off bits of the address that will never be used. */ |
||
1263 |
3226 |
n = &h->addr.v.a.addr; |
|
1264 |
✓✓ | 3226 |
if (h->addr.type == PF_ADDR_ADDRMASK) |
1265 |
✓✓ | 30360 |
for (i = 0; i < 4; i++) |
1266 |
12144 |
n->addr32[i] = n->addr32[i] & m->addr32[i]; |
|
1267 |
3226 |
} |
|
1268 |
|||
1269 |
int |
||
1270 |
check_netmask(struct node_host *h, sa_family_t af) |
||
1271 |
{ |
||
1272 |
struct node_host *n = NULL; |
||
1273 |
struct pf_addr *m; |
||
1274 |
|||
1275 |
✓✓ | 37194 |
for (n = h; n != NULL; n = n->next) { |
1276 |
✓✓ | 7810 |
if (h->addr.type == PF_ADDR_TABLE) |
1277 |
continue; |
||
1278 |
7465 |
m = &h->addr.v.a.mask; |
|
1279 |
/* netmasks > 32 bit are invalid on v4 */ |
||
1280 |
✓✓✗✓ |
11193 |
if (af == AF_INET && |
1281 |
✓✓✓✗ |
11185 |
(m->addr32[1] || m->addr32[2] || m->addr32[3])) { |
1282 |
1 |
fprintf(stderr, "netmask %u invalid for IPv4 address\n", |
|
1283 |
1 |
unmask(m, AF_INET6)); |
|
1284 |
1 |
return (1); |
|
1285 |
} |
||
1286 |
} |
||
1287 |
7191 |
return (0); |
|
1288 |
7192 |
} |
|
1289 |
|||
1290 |
struct node_host * |
||
1291 |
gen_dynnode(struct node_host *h, sa_family_t af) |
||
1292 |
{ |
||
1293 |
struct node_host *n; |
||
1294 |
struct pf_addr *m; |
||
1295 |
|||
1296 |
✗✓ | 748 |
if (h->addr.type != PF_ADDR_DYNIFTL) |
1297 |
return (NULL); |
||
1298 |
|||
1299 |
✗✓ | 374 |
if ((n = calloc(1, sizeof(*n))) == NULL) |
1300 |
return (NULL); |
||
1301 |
374 |
bcopy(h, n, sizeof(*n)); |
|
1302 |
374 |
n->ifname = NULL; |
|
1303 |
374 |
n->next = NULL; |
|
1304 |
374 |
n->tail = NULL; |
|
1305 |
|||
1306 |
/* fix up netmask */ |
||
1307 |
374 |
m = &n->addr.v.a.mask; |
|
1308 |
✓✓✓✓ |
503 |
if (af == AF_INET && unmask(m, AF_INET6) > 32) |
1309 |
112 |
set_ipmask(n, 32); |
|
1310 |
|||
1311 |
374 |
return (n); |
|
1312 |
374 |
} |
|
1313 |
|||
1314 |
/* interface lookup routines */ |
||
1315 |
|||
1316 |
struct node_host *iftab; |
||
1317 |
|||
1318 |
void |
||
1319 |
ifa_load(void) |
||
1320 |
{ |
||
1321 |
718 |
struct ifaddrs *ifap, *ifa; |
|
1322 |
struct node_host *n = NULL, *h = NULL; |
||
1323 |
|||
1324 |
✗✓ | 359 |
if (getifaddrs(&ifap) < 0) |
1325 |
err(1, "getifaddrs"); |
||
1326 |
|||
1327 |
✓✓ | 11488 |
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
1328 |
✓✓✓✗ |
8975 |
if (!(ifa->ifa_addr->sa_family == AF_INET || |
1329 |
✓✓ | 4308 |
ifa->ifa_addr->sa_family == AF_INET6 || |
1330 |
3590 |
ifa->ifa_addr->sa_family == AF_LINK)) |
|
1331 |
continue; |
||
1332 |
5385 |
n = calloc(1, sizeof(struct node_host)); |
|
1333 |
✗✓ | 5385 |
if (n == NULL) |
1334 |
err(1, "address: calloc"); |
||
1335 |
5385 |
n->af = ifa->ifa_addr->sa_family; |
|
1336 |
5385 |
n->ifa_flags = ifa->ifa_flags; |
|
1337 |
#ifdef __KAME__ |
||
1338 |
✓✓✓✗ |
5744 |
if (n->af == AF_INET6 && |
1339 |
✓✓ | 1077 |
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) |
1340 |
✓✗ | 359 |
ifa->ifa_addr)->sin6_addr) && |
1341 |
359 |
((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == |
|
1342 |
0) { |
||
1343 |
struct sockaddr_in6 *sin6; |
||
1344 |
|||
1345 |
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; |
||
1346 |
718 |
sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | |
|
1347 |
359 |
sin6->sin6_addr.s6_addr[3]; |
|
1348 |
359 |
sin6->sin6_addr.s6_addr[2] = 0; |
|
1349 |
359 |
sin6->sin6_addr.s6_addr[3] = 0; |
|
1350 |
359 |
} |
|
1351 |
#endif |
||
1352 |
5385 |
n->ifindex = 0; |
|
1353 |
✓✓ | 5385 |
if (n->af == AF_INET) { |
1354 |
2154 |
memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) |
|
1355 |
1077 |
ifa->ifa_addr)->sin_addr.s_addr, |
|
1356 |
sizeof(struct in_addr)); |
||
1357 |
2154 |
memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) |
|
1358 |
1077 |
ifa->ifa_netmask)->sin_addr.s_addr, |
|
1359 |
sizeof(struct in_addr)); |
||
1360 |
✓✗ | 1077 |
if (ifa->ifa_broadaddr != NULL) |
1361 |
2154 |
memcpy(&n->bcast, &((struct sockaddr_in *) |
|
1362 |
1077 |
ifa->ifa_broadaddr)->sin_addr.s_addr, |
|
1363 |
sizeof(struct in_addr)); |
||
1364 |
✓✗ | 1077 |
if (ifa->ifa_dstaddr != NULL) |
1365 |
2154 |
memcpy(&n->peer, &((struct sockaddr_in *) |
|
1366 |
1077 |
ifa->ifa_dstaddr)->sin_addr.s_addr, |
|
1367 |
sizeof(struct in_addr)); |
||
1368 |
✓✓ | 4308 |
} else if (n->af == AF_INET6) { |
1369 |
1436 |
memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) |
|
1370 |
718 |
ifa->ifa_addr)->sin6_addr.s6_addr, |
|
1371 |
sizeof(struct in6_addr)); |
||
1372 |
1436 |
memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) |
|
1373 |
718 |
ifa->ifa_netmask)->sin6_addr.s6_addr, |
|
1374 |
sizeof(struct in6_addr)); |
||
1375 |
✓✗ | 718 |
if (ifa->ifa_broadaddr != NULL) |
1376 |
1436 |
memcpy(&n->bcast, &((struct sockaddr_in6 *) |
|
1377 |
718 |
ifa->ifa_broadaddr)->sin6_addr.s6_addr, |
|
1378 |
sizeof(struct in6_addr)); |
||
1379 |
✓✗ | 718 |
if (ifa->ifa_dstaddr != NULL) |
1380 |
1436 |
memcpy(&n->peer, &((struct sockaddr_in6 *) |
|
1381 |
718 |
ifa->ifa_dstaddr)->sin6_addr.s6_addr, |
|
1382 |
sizeof(struct in6_addr)); |
||
1383 |
718 |
n->ifindex = ((struct sockaddr_in6 *) |
|
1384 |
718 |
ifa->ifa_addr)->sin6_scope_id; |
|
1385 |
✓✗ | 4308 |
} else if (n->af == AF_LINK) { |
1386 |
3590 |
n->ifindex = ((struct sockaddr_dl *) |
|
1387 |
3590 |
ifa->ifa_addr)->sdl_index; |
|
1388 |
3590 |
} |
|
1389 |
✗✓ | 5385 |
if ((n->ifname = strdup(ifa->ifa_name)) == NULL) |
1390 |
err(1, "ifa_load: strdup"); |
||
1391 |
5385 |
n->next = NULL; |
|
1392 |
5385 |
n->tail = n; |
|
1393 |
✓✓ | 5385 |
if (h == NULL) |
1394 |
359 |
h = n; |
|
1395 |
else { |
||
1396 |
5026 |
h->tail->next = n; |
|
1397 |
5026 |
h->tail = n; |
|
1398 |
} |
||
1399 |
} |
||
1400 |
|||
1401 |
359 |
iftab = h; |
|
1402 |
359 |
freeifaddrs(ifap); |
|
1403 |
359 |
} |
|
1404 |
|||
1405 |
unsigned int |
||
1406 |
ifa_nametoindex(const char *ifa_name) |
||
1407 |
{ |
||
1408 |
struct node_host *p; |
||
1409 |
|||
1410 |
✓✗ | 63 |
for (p = iftab; p; p = p->next) { |
1411 |
✓✗✓✗ |
42 |
if (p->af == AF_LINK && strcmp(p->ifname, ifa_name) == 0) |
1412 |
21 |
return (p->ifindex); |
|
1413 |
} |
||
1414 |
errno = ENXIO; |
||
1415 |
return (0); |
||
1416 |
21 |
} |
|
1417 |
|||
1418 |
char * |
||
1419 |
ifa_indextoname(unsigned int ifindex, char *ifa_name) |
||
1420 |
{ |
||
1421 |
struct node_host *p; |
||
1422 |
|||
1423 |
✓✓ | 67416 |
for (p = iftab; p; p = p->next) { |
1424 |
✓✓✓✓ |
48228 |
if (p->af == AF_LINK && ifindex == p->ifindex) { |
1425 |
14 |
strlcpy(ifa_name, p->ifname, IFNAMSIZ); |
|
1426 |
14 |
return (ifa_name); |
|
1427 |
} |
||
1428 |
} |
||
1429 |
3178 |
errno = ENXIO; |
|
1430 |
3178 |
return (NULL); |
|
1431 |
3192 |
} |
|
1432 |
|||
1433 |
struct node_host * |
||
1434 |
ifa_exists(const char *ifa_name) |
||
1435 |
{ |
||
1436 |
struct node_host *n; |
||
1437 |
7306 |
struct ifgroupreq ifgr; |
|
1438 |
int s; |
||
1439 |
|||
1440 |
✓✓ | 3653 |
if (iftab == NULL) |
1441 |
359 |
ifa_load(); |
|
1442 |
|||
1443 |
/* check whether this is a group */ |
||
1444 |
✗✓ | 3653 |
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) |
1445 |
err(1, "socket"); |
||
1446 |
3653 |
bzero(&ifgr, sizeof(ifgr)); |
|
1447 |
3653 |
strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); |
|
1448 |
✓✓ | 3653 |
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) { |
1449 |
/* fake a node_host */ |
||
1450 |
✗✓ | 20 |
if ((n = calloc(1, sizeof(*n))) == NULL) |
1451 |
err(1, "calloc"); |
||
1452 |
✗✓ | 20 |
if ((n->ifname = strdup(ifa_name)) == NULL) |
1453 |
err(1, "strdup"); |
||
1454 |
20 |
close(s); |
|
1455 |
20 |
return (n); |
|
1456 |
} |
||
1457 |
3633 |
close(s); |
|
1458 |
|||
1459 |
✓✓ | 74316 |
for (n = iftab; n; n = n->next) { |
1460 |
✓✓✓✓ |
59015 |
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) |
1461 |
1739 |
return (n); |
|
1462 |
} |
||
1463 |
|||
1464 |
1894 |
return (NULL); |
|
1465 |
3653 |
} |
|
1466 |
|||
1467 |
struct node_host * |
||
1468 |
ifa_grouplookup(const char *ifa_name, int flags) |
||
1469 |
{ |
||
1470 |
struct ifg_req *ifg; |
||
1471 |
372 |
struct ifgroupreq ifgr; |
|
1472 |
int s, len; |
||
1473 |
struct node_host *n, *h = NULL; |
||
1474 |
|||
1475 |
✗✓ | 186 |
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) |
1476 |
err(1, "socket"); |
||
1477 |
186 |
bzero(&ifgr, sizeof(ifgr)); |
|
1478 |
186 |
strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); |
|
1479 |
✓✓ | 186 |
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { |
1480 |
176 |
close(s); |
|
1481 |
176 |
return (NULL); |
|
1482 |
} |
||
1483 |
|||
1484 |
10 |
len = ifgr.ifgr_len; |
|
1485 |
✗✓ | 10 |
if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) |
1486 |
err(1, "calloc"); |
||
1487 |
✗✓ | 10 |
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) |
1488 |
err(1, "SIOCGIFGMEMB"); |
||
1489 |
|||
1490 |
✓✓ | 100 |
for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); |
1491 |
40 |
ifg++) { |
|
1492 |
40 |
len -= sizeof(struct ifg_req); |
|
1493 |
✓✓ | 40 |
if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) |
1494 |
continue; |
||
1495 |
✓✗ | 6 |
if (h == NULL) |
1496 |
6 |
h = n; |
|
1497 |
else { |
||
1498 |
h->tail->next = n; |
||
1499 |
h->tail = n->tail; |
||
1500 |
} |
||
1501 |
} |
||
1502 |
10 |
free(ifgr.ifgr_groups); |
|
1503 |
10 |
close(s); |
|
1504 |
|||
1505 |
10 |
return (h); |
|
1506 |
186 |
} |
|
1507 |
|||
1508 |
struct node_host * |
||
1509 |
ifa_lookup(const char *ifa_name, int flags) |
||
1510 |
{ |
||
1511 |
struct node_host *p = NULL, *h = NULL, *n = NULL; |
||
1512 |
int got4 = 0, got6 = 0; |
||
1513 |
const char *last_if = NULL; |
||
1514 |
|||
1515 |
✓✓ | 372 |
if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) |
1516 |
6 |
return (h); |
|
1517 |
|||
1518 |
✓✓ | 180 |
if (!strncmp(ifa_name, "self", IFNAMSIZ)) |
1519 |
11 |
ifa_name = NULL; |
|
1520 |
|||
1521 |
✗✓ | 180 |
if (iftab == NULL) |
1522 |
ifa_load(); |
||
1523 |
|||
1524 |
✓✓ | 5760 |
for (p = iftab; p; p = p->next) { |
1525 |
✓✓ | 2700 |
if (ifa_skip_if(ifa_name, p)) |
1526 |
continue; |
||
1527 |
✓✓✓✓ |
491 |
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) |
1528 |
continue; |
||
1529 |
✓✓✓✓ |
467 |
if ((flags & PFI_AFLAG_BROADCAST) && |
1530 |
10 |
!(p->ifa_flags & IFF_BROADCAST)) |
|
1531 |
continue; |
||
1532 |
✓✓✓✗ |
455 |
if ((flags & PFI_AFLAG_BROADCAST) && p->bcast.v4.s_addr == 0) |
1533 |
continue; |
||
1534 |
✓✓✗✓ |
473 |
if ((flags & PFI_AFLAG_PEER) && |
1535 |
22 |
!(p->ifa_flags & IFF_POINTOPOINT)) |
|
1536 |
continue; |
||
1537 |
✓✓✓✓ |
508 |
if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) |
1538 |
continue; |
||
1539 |
✓✓✓✓ |
669 |
if (last_if == NULL || strcmp(last_if, p->ifname)) |
1540 |
155 |
got4 = got6 = 0; |
|
1541 |
404 |
last_if = p->ifname; |
|
1542 |
✓✓✓✗ |
464 |
if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) |
1543 |
continue; |
||
1544 |
✓✓✓✓ |
464 |
if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) |
1545 |
continue; |
||
1546 |
✓✓ | 388 |
if (p->af == AF_INET) |
1547 |
155 |
got4 = 1; |
|
1548 |
else |
||
1549 |
got6 = 1; |
||
1550 |
388 |
n = calloc(1, sizeof(struct node_host)); |
|
1551 |
✗✓ | 388 |
if (n == NULL) |
1552 |
err(1, "address: calloc"); |
||
1553 |
388 |
n->af = p->af; |
|
1554 |
✓✓ | 388 |
if (flags & PFI_AFLAG_BROADCAST) |
1555 |
4 |
memcpy(&n->addr.v.a.addr, &p->bcast, |
|
1556 |
sizeof(struct pf_addr)); |
||
1557 |
✗✓ | 384 |
else if (flags & PFI_AFLAG_PEER) |
1558 |
memcpy(&n->addr.v.a.addr, &p->peer, |
||
1559 |
sizeof(struct pf_addr)); |
||
1560 |
else |
||
1561 |
384 |
memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, |
|
1562 |
sizeof(struct pf_addr)); |
||
1563 |
✓✓ | 388 |
if (flags & PFI_AFLAG_NETWORK) |
1564 |
54 |
set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); |
|
1565 |
else { |
||
1566 |
✓✓ | 334 |
if (n->af == AF_INET) { |
1567 |
✓✓✗✓ |
238 |
if (p->ifa_flags & IFF_LOOPBACK && |
1568 |
112 |
p->ifa_flags & IFF_LINK1) |
|
1569 |
memcpy(&n->addr.v.a.mask, |
||
1570 |
&p->addr.v.a.mask, |
||
1571 |
sizeof(struct pf_addr)); |
||
1572 |
else |
||
1573 |
126 |
set_ipmask(n, 32); |
|
1574 |
} else |
||
1575 |
208 |
set_ipmask(n, 128); |
|
1576 |
} |
||
1577 |
388 |
n->ifindex = p->ifindex; |
|
1578 |
|||
1579 |
388 |
n->next = NULL; |
|
1580 |
388 |
n->tail = n; |
|
1581 |
✓✓ | 388 |
if (h == NULL) |
1582 |
139 |
h = n; |
|
1583 |
else { |
||
1584 |
249 |
h->tail->next = n; |
|
1585 |
249 |
h->tail = n; |
|
1586 |
} |
||
1587 |
} |
||
1588 |
180 |
return (h); |
|
1589 |
186 |
} |
|
1590 |
|||
1591 |
int |
||
1592 |
ifa_skip_if(const char *filter, struct node_host *p) |
||
1593 |
{ |
||
1594 |
int n; |
||
1595 |
|||
1596 |
✓✓✓✓ |
7560 |
if (p->af != AF_INET && p->af != AF_INET6) |
1597 |
1800 |
return (1); |
|
1598 |
✓✓✗✓ |
1745 |
if (filter == NULL || !*filter) |
1599 |
55 |
return (0); |
|
1600 |
✓✓ | 845 |
if (!strcmp(p->ifname, filter)) |
1601 |
402 |
return (0); /* exact match */ |
|
1602 |
443 |
n = strlen(filter); |
|
1603 |
✗✓ | 443 |
if (n < 1 || n >= IFNAMSIZ) |
1604 |
return (1); /* sanity check */ |
||
1605 |
✓✗✓✓ |
886 |
if (filter[n-1] >= '0' && filter[n-1] <= '9') |
1606 |
423 |
return (1); /* only do exact match in that case */ |
|
1607 |
✓✓ | 20 |
if (strncmp(p->ifname, filter, n)) |
1608 |
8 |
return (1); /* prefix doesn't match */ |
|
1609 |
✓✗ | 36 |
return (p->ifname[n] < '0' || p->ifname[n] > '9'); |
1610 |
2700 |
} |
|
1611 |
|||
1612 |
struct node_host * |
||
1613 |
host(const char *s, int opts) |
||
1614 |
{ |
||
1615 |
struct node_host *h = NULL, *n; |
||
1616 |
int mask = -1, v4mask = 32, v6mask = 128, cont = 1; |
||
1617 |
4712 |
char *p, *q, *r, *ps, *if_name; |
|
1618 |
|||
1619 |
✗✓ | 2356 |
if ((ps = strdup(s)) == NULL) |
1620 |
err(1, "host: strdup"); |
||
1621 |
|||
1622 |
✓✓ | 2356 |
if ((if_name = strrchr(ps, '@')) != NULL) { |
1623 |
15 |
if_name[0] = '\0'; |
|
1624 |
15 |
if_name++; |
|
1625 |
15 |
} |
|
1626 |
|||
1627 |
✓✓ | 2356 |
if ((p = strrchr(ps, '/')) != NULL) { |
1628 |
✗✓ | 675 |
if ((r = strdup(ps)) == NULL) |
1629 |
err(1, "host: strdup"); |
||
1630 |
675 |
mask = strtol(p+1, &q, 0); |
|
1631 |
✓✗✓✓ ✗✓ |
2023 |
if (!q || *q || mask > 128 || q == (p+1)) { |
1632 |
2 |
fprintf(stderr, "invalid netmask '%s'\n", p); |
|
1633 |
2 |
free(r); |
|
1634 |
2 |
free(ps); |
|
1635 |
2 |
return (NULL); |
|
1636 |
} |
||
1637 |
673 |
p[0] = '\0'; |
|
1638 |
v4mask = v6mask = mask; |
||
1639 |
673 |
} else |
|
1640 |
r = ps; |
||
1641 |
|||
1642 |
/* interface with this name exists? */ |
||
1643 |
✓✗✓✓ |
4708 |
if (cont && (h = host_if(ps, mask)) != NULL) |
1644 |
127 |
cont = 0; |
|
1645 |
|||
1646 |
/* IPv4 address? */ |
||
1647 |
✓✓✓✓ |
4581 |
if (cont && (h = host_v4(r, mask)) != NULL) |
1648 |
1751 |
cont = 0; |
|
1649 |
✓✓ | 2354 |
if (r != ps) |
1650 |
673 |
free(r); |
|
1651 |
|||
1652 |
/* IPv6 address? */ |
||
1653 |
✓✓✓✓ |
2830 |
if (cont && (h = host_v6(ps, v6mask)) != NULL) |
1654 |
438 |
cont = 0; |
|
1655 |
|||
1656 |
/* dns lookup */ |
||
1657 |
✓✓✓✓ |
2430 |
if (cont && (h = host_dns(ps, v4mask, v6mask, |
1658 |
76 |
(opts & PF_OPT_NODNS))) != NULL) |
|
1659 |
13 |
cont = 0; |
|
1660 |
|||
1661 |
✓✓✓✗ |
2369 |
if (if_name && if_name[0]) |
1662 |
✓✓ | 60 |
for (n = h; n != NULL; n = n->next) |
1663 |
✗✓ | 15 |
if ((n->ifname = strdup(if_name)) == NULL) |
1664 |
err(1, "host: strdup"); |
||
1665 |
|||
1666 |
2354 |
free(ps); /* after we copy the name out */ |
|
1667 |
✓✓ | 2354 |
if (h == NULL || cont == 1) { |
1668 |
25 |
fprintf(stderr, "no IP address found for %s\n", s); |
|
1669 |
25 |
return (NULL); |
|
1670 |
} |
||
1671 |
✓✓ | 9814 |
for (n = h; n != NULL; n = n->next) { |
1672 |
2578 |
n->addr.type = PF_ADDR_ADDRMASK; |
|
1673 |
2578 |
n->weight = 0; |
|
1674 |
} |
||
1675 |
2329 |
return (h); |
|
1676 |
2356 |
} |
|
1677 |
|||
1678 |
struct node_host * |
||
1679 |
host_if(const char *s, int mask) |
||
1680 |
{ |
||
1681 |
struct node_host *n, *h = NULL; |
||
1682 |
char *p, *ps; |
||
1683 |
int flags = 0; |
||
1684 |
|||
1685 |
✗✓ | 4708 |
if ((ps = strdup(s)) == NULL) |
1686 |
err(1, "host_if: strdup"); |
||
1687 |
✓✓ | 4820 |
while ((p = strrchr(ps, ':')) != NULL) { |
1688 |
✓✓ | 496 |
if (!strcmp(p+1, "network")) |
1689 |
16 |
flags |= PFI_AFLAG_NETWORK; |
|
1690 |
✓✓ | 480 |
else if (!strcmp(p+1, "broadcast")) |
1691 |
6 |
flags |= PFI_AFLAG_BROADCAST; |
|
1692 |
✓✓ | 474 |
else if (!strcmp(p+1, "peer")) |
1693 |
6 |
flags |= PFI_AFLAG_PEER; |
|
1694 |
✓✓ | 468 |
else if (!strcmp(p+1, "0")) |
1695 |
28 |
flags |= PFI_AFLAG_NOALIAS; |
|
1696 |
else { |
||
1697 |
440 |
free(ps); |
|
1698 |
440 |
return (NULL); |
|
1699 |
} |
||
1700 |
56 |
*p = '\0'; |
|
1701 |
} |
||
1702 |
✗✓ | 1914 |
if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ |
1703 |
fprintf(stderr, "illegal combination of interface modifiers\n"); |
||
1704 |
free(ps); |
||
1705 |
return (NULL); |
||
1706 |
} |
||
1707 |
✗✓ | 1914 |
if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { |
1708 |
fprintf(stderr, "network or broadcast lookup, but " |
||
1709 |
"extra netmask given\n"); |
||
1710 |
free(ps); |
||
1711 |
return (NULL); |
||
1712 |
} |
||
1713 |
✓✓✓✓ |
3706 |
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { |
1714 |
/* interface with this name exists */ |
||
1715 |
133 |
h = ifa_lookup(ps, flags); |
|
1716 |
✓✓ | 456 |
for (n = h; n != NULL && mask > -1; n = n->next) |
1717 |
95 |
set_ipmask(n, mask); |
|
1718 |
} |
||
1719 |
|||
1720 |
1914 |
free(ps); |
|
1721 |
1914 |
return (h); |
|
1722 |
2354 |
} |
|
1723 |
|||
1724 |
struct node_host * |
||
1725 |
host_v4(const char *s, int mask) |
||
1726 |
{ |
||
1727 |
struct node_host *h = NULL; |
||
1728 |
4454 |
struct in_addr ina; |
|
1729 |
int bits = 32; |
||
1730 |
|||
1731 |
2227 |
memset(&ina, 0, sizeof(struct in_addr)); |
|
1732 |
✓✓ | 2227 |
if (strrchr(s, '/') != NULL) { |
1733 |
✓✓ | 642 |
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) |
1734 |
50 |
return (NULL); |
|
1735 |
} else { |
||
1736 |
✓✓ | 1585 |
if (inet_pton(AF_INET, s, &ina) != 1) |
1737 |
426 |
return (NULL); |
|
1738 |
} |
||
1739 |
|||
1740 |
1751 |
h = calloc(1, sizeof(struct node_host)); |
|
1741 |
✗✓ | 1751 |
if (h == NULL) |
1742 |
err(1, "address: calloc"); |
||
1743 |
1751 |
h->ifname = NULL; |
|
1744 |
1751 |
h->af = AF_INET; |
|
1745 |
1751 |
h->addr.v.a.addr.addr32[0] = ina.s_addr; |
|
1746 |
1751 |
set_ipmask(h, bits); |
|
1747 |
1751 |
h->next = NULL; |
|
1748 |
1751 |
h->tail = h; |
|
1749 |
|||
1750 |
1751 |
return (h); |
|
1751 |
2227 |
} |
|
1752 |
|||
1753 |
struct node_host * |
||
1754 |
host_v6(const char *s, int mask) |
||
1755 |
{ |
||
1756 |
952 |
struct addrinfo hints, *res; |
|
1757 |
struct node_host *h = NULL; |
||
1758 |
|||
1759 |
476 |
memset(&hints, 0, sizeof(hints)); |
|
1760 |
476 |
hints.ai_family = AF_INET6; |
|
1761 |
476 |
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
|
1762 |
476 |
hints.ai_flags = AI_NUMERICHOST; |
|
1763 |
✓✓ | 476 |
if (getaddrinfo(s, "0", &hints, &res) == 0) { |
1764 |
438 |
h = calloc(1, sizeof(struct node_host)); |
|
1765 |
✗✓ | 438 |
if (h == NULL) |
1766 |
err(1, "address: calloc"); |
||
1767 |
438 |
h->ifname = NULL; |
|
1768 |
438 |
h->af = AF_INET6; |
|
1769 |
876 |
memcpy(&h->addr.v.a.addr, |
|
1770 |
438 |
&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, |
|
1771 |
sizeof(h->addr.v.a.addr)); |
||
1772 |
438 |
h->ifindex = |
|
1773 |
438 |
((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; |
|
1774 |
438 |
set_ipmask(h, mask); |
|
1775 |
438 |
freeaddrinfo(res); |
|
1776 |
438 |
h->next = NULL; |
|
1777 |
438 |
h->tail = h; |
|
1778 |
438 |
} |
|
1779 |
|||
1780 |
476 |
return (h); |
|
1781 |
476 |
} |
|
1782 |
|||
1783 |
struct node_host * |
||
1784 |
host_dns(const char *s, int v4mask, int v6mask, int numeric) |
||
1785 |
{ |
||
1786 |
76 |
struct addrinfo hints, *res0, *res; |
|
1787 |
struct node_host *n, *h = NULL; |
||
1788 |
int error, noalias = 0; |
||
1789 |
int got4 = 0, got6 = 0; |
||
1790 |
char *p, *ps; |
||
1791 |
|||
1792 |
✗✓ | 38 |
if ((ps = strdup(s)) == NULL) |
1793 |
err(1, "host_dns: strdup"); |
||
1794 |
✓✓✓✓ |
55 |
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { |
1795 |
noalias = 1; |
||
1796 |
3 |
*p = '\0'; |
|
1797 |
3 |
} |
|
1798 |
38 |
memset(&hints, 0, sizeof(hints)); |
|
1799 |
38 |
hints.ai_family = PF_UNSPEC; |
|
1800 |
38 |
hints.ai_socktype = SOCK_STREAM; /* DUMMY */ |
|
1801 |
✓✓ | 38 |
if (numeric) |
1802 |
1 |
hints.ai_flags = AI_NUMERICHOST; |
|
1803 |
38 |
error = getaddrinfo(ps, NULL, &hints, &res0); |
|
1804 |
✓✓ | 38 |
if (error) { |
1805 |
25 |
free(ps); |
|
1806 |
25 |
return (h); |
|
1807 |
} |
||
1808 |
|||
1809 |
✓✓ | 76 |
for (res = res0; res; res = res->ai_next) { |
1810 |
✓✓✓✗ |
37 |
if (res->ai_family != AF_INET && |
1811 |
12 |
res->ai_family != AF_INET6) |
|
1812 |
continue; |
||
1813 |
✗✓ | 25 |
if (noalias) { |
1814 |
if (res->ai_family == AF_INET) { |
||
1815 |
if (got4) |
||
1816 |
continue; |
||
1817 |
got4 = 1; |
||
1818 |
} else { |
||
1819 |
if (got6) |
||
1820 |
continue; |
||
1821 |
got6 = 1; |
||
1822 |
} |
||
1823 |
} |
||
1824 |
25 |
n = calloc(1, sizeof(struct node_host)); |
|
1825 |
✗✓ | 25 |
if (n == NULL) |
1826 |
err(1, "host_dns: calloc"); |
||
1827 |
25 |
n->ifname = NULL; |
|
1828 |
25 |
n->af = res->ai_family; |
|
1829 |
✓✓ | 25 |
if (res->ai_family == AF_INET) { |
1830 |
13 |
memcpy(&n->addr.v.a.addr, |
|
1831 |
&((struct sockaddr_in *) |
||
1832 |
13 |
res->ai_addr)->sin_addr.s_addr, |
|
1833 |
sizeof(struct in_addr)); |
||
1834 |
13 |
set_ipmask(n, v4mask); |
|
1835 |
13 |
} else { |
|
1836 |
12 |
memcpy(&n->addr.v.a.addr, |
|
1837 |
&((struct sockaddr_in6 *) |
||
1838 |
12 |
res->ai_addr)->sin6_addr.s6_addr, |
|
1839 |
sizeof(struct in6_addr)); |
||
1840 |
12 |
n->ifindex = |
|
1841 |
((struct sockaddr_in6 *) |
||
1842 |
12 |
res->ai_addr)->sin6_scope_id; |
|
1843 |
12 |
set_ipmask(n, v6mask); |
|
1844 |
} |
||
1845 |
25 |
n->next = NULL; |
|
1846 |
25 |
n->tail = n; |
|
1847 |
✓✓ | 25 |
if (h == NULL) |
1848 |
13 |
h = n; |
|
1849 |
else { |
||
1850 |
12 |
h->tail->next = n; |
|
1851 |
12 |
h->tail = n; |
|
1852 |
} |
||
1853 |
} |
||
1854 |
13 |
freeaddrinfo(res0); |
|
1855 |
13 |
free(ps); |
|
1856 |
|||
1857 |
13 |
return (h); |
|
1858 |
38 |
} |
|
1859 |
|||
1860 |
/* |
||
1861 |
* convert a hostname to a list of addresses and put them in the given buffer. |
||
1862 |
* test: |
||
1863 |
* if set to 1, only simple addresses are accepted (no netblock, no "!"). |
||
1864 |
*/ |
||
1865 |
int |
||
1866 |
append_addr(struct pfr_buffer *b, char *s, int test, int opts) |
||
1867 |
{ |
||
1868 |
static int previous = 0; |
||
1869 |
static int expect = 0; |
||
1870 |
struct pfr_addr *a; |
||
1871 |
struct node_host *h, *n; |
||
1872 |
char *r; |
||
1873 |
const char *errstr; |
||
1874 |
int rv, not = 0, i = 0; |
||
1875 |
u_int16_t weight; |
||
1876 |
|||
1877 |
/* skip weight if given */ |
||
1878 |
if (strcmp(s, "weight") == 0) { |
||
1879 |
expect = 1; |
||
1880 |
return (1); /* expecting further call */ |
||
1881 |
} |
||
1882 |
|||
1883 |
/* check if previous host is set */ |
||
1884 |
if (expect) { |
||
1885 |
/* parse and append load balancing weight */ |
||
1886 |
weight = strtonum(s, 1, USHRT_MAX, &errstr); |
||
1887 |
if (errstr) { |
||
1888 |
fprintf(stderr, "failed to convert weight %s\n", s); |
||
1889 |
return (-1); |
||
1890 |
} |
||
1891 |
if (previous != -1) { |
||
1892 |
PFRB_FOREACH(a, b) { |
||
1893 |
if (++i >= previous) { |
||
1894 |
a->pfra_weight = weight; |
||
1895 |
a->pfra_type = PFRKE_COST; |
||
1896 |
} |
||
1897 |
} |
||
1898 |
} |
||
1899 |
|||
1900 |
expect = 0; |
||
1901 |
return (0); |
||
1902 |
} |
||
1903 |
|||
1904 |
for (r = s; *r == '!'; r++) |
||
1905 |
not = !not; |
||
1906 |
if ((n = host(r, opts)) == NULL) { |
||
1907 |
errno = 0; |
||
1908 |
return (-1); |
||
1909 |
} |
||
1910 |
rv = append_addr_host(b, n, test, not); |
||
1911 |
previous = b->pfrb_size; |
||
1912 |
do { |
||
1913 |
h = n; |
||
1914 |
n = n->next; |
||
1915 |
free(h); |
||
1916 |
} while (n != NULL); |
||
1917 |
return (rv); |
||
1918 |
} |
||
1919 |
|||
1920 |
/* |
||
1921 |
* same as previous function, but with a pre-parsed input and the ability |
||
1922 |
* to "negate" the result. Does not free the node_host list. |
||
1923 |
* not: |
||
1924 |
* setting it to 1 is equivalent to adding "!" in front of parameter s. |
||
1925 |
*/ |
||
1926 |
int |
||
1927 |
append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) |
||
1928 |
{ |
||
1929 |
int bits; |
||
1930 |
352 |
struct pfr_addr addr; |
|
1931 |
|||
1932 |
176 |
do { |
|
1933 |
225 |
bzero(&addr, sizeof(addr)); |
|
1934 |
225 |
addr.pfra_not = n->not ^ not; |
|
1935 |
225 |
addr.pfra_af = n->af; |
|
1936 |
225 |
addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); |
|
1937 |
✓✓ | 225 |
if (n->ifname) { |
1938 |
✗✓ | 32 |
if (strlcpy(addr.pfra_ifname, n->ifname, |
1939 |
16 |
sizeof(addr.pfra_ifname)) >= sizeof(addr.pfra_ifname)) |
|
1940 |
errx(1, "append_addr_host: strlcpy"); |
||
1941 |
16 |
addr.pfra_type = PFRKE_ROUTE; |
|
1942 |
16 |
} |
|
1943 |
✗✓ | 225 |
if (n->weight > 0) { |
1944 |
addr.pfra_weight = n->weight; |
||
1945 |
addr.pfra_type = PFRKE_COST; |
||
1946 |
} |
||
1947 |
✓✓✗ | 225 |
switch (n->af) { |
1948 |
case AF_INET: |
||
1949 |
184 |
addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; |
|
1950 |
bits = 32; |
||
1951 |
184 |
break; |
|
1952 |
case AF_INET6: |
||
1953 |
41 |
memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, |
|
1954 |
sizeof(struct in6_addr)); |
||
1955 |
bits = 128; |
||
1956 |
41 |
break; |
|
1957 |
default: |
||
1958 |
errno = EINVAL; |
||
1959 |
return (-1); |
||
1960 |
} |
||
1961 |
✗✓✗✗ ✗✗✗✓ |
450 |
if ((test && (not || addr.pfra_net != bits)) || |
1962 |
225 |
addr.pfra_net > bits) { |
|
1963 |
errno = EINVAL; |
||
1964 |
return (-1); |
||
1965 |
} |
||
1966 |
✗✓ | 225 |
if (pfr_buf_add(b, &addr)) |
1967 |
return (-1); |
||
1968 |
✓✓ | 225 |
} while ((n = n->next) != NULL); |
1969 |
|||
1970 |
176 |
return (0); |
|
1971 |
176 |
} |
|
1972 |
|||
1973 |
int |
||
1974 |
pfctl_add_trans(struct pfr_buffer *buf, int type, const char *anchor) |
||
1975 |
{ |
||
1976 |
1176 |
struct pfioc_trans_e trans; |
|
1977 |
|||
1978 |
588 |
bzero(&trans, sizeof(trans)); |
|
1979 |
588 |
trans.type = type; |
|
1980 |
✗✓ | 1176 |
if (strlcpy(trans.anchor, anchor, |
1981 |
588 |
sizeof(trans.anchor)) >= sizeof(trans.anchor)) |
|
1982 |
errx(1, "pfctl_add_trans: strlcpy"); |
||
1983 |
|||
1984 |
1176 |
return pfr_buf_add(buf, &trans); |
|
1985 |
588 |
} |
|
1986 |
|||
1987 |
u_int32_t |
||
1988 |
pfctl_get_ticket(struct pfr_buffer *buf, int type, const char *anchor) |
||
1989 |
{ |
||
1990 |
struct pfioc_trans_e *p; |
||
1991 |
|||
1992 |
✓✗ | 6206 |
PFRB_FOREACH(p, buf) |
1993 |
✓✓✓✓ |
4146 |
if (type == p->type && !strcmp(anchor, p->anchor)) |
1994 |
1690 |
return (p->ticket); |
|
1995 |
errx(1, "pfctl_get_ticket: assertion failed"); |
||
1996 |
} |
||
1997 |
|||
1998 |
int |
||
1999 |
pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) |
||
2000 |
{ |
||
2001 |
1448 |
struct pfioc_trans trans; |
|
2002 |
|||
2003 |
724 |
bzero(&trans, sizeof(trans)); |
|
2004 |
724 |
trans.size = buf->pfrb_size - from; |
|
2005 |
724 |
trans.esize = sizeof(struct pfioc_trans_e); |
|
2006 |
724 |
trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; |
|
2007 |
1448 |
return ioctl(dev, cmd, &trans); |
|
2008 |
724 |
} |
Generated by: GCOVR (Version 3.3) |