mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-05 01:03:55 +08:00
pfctl: Import sources from FreeBSD.
This commit is contained in:
parent
fef6dd1def
commit
084d4db8f4
6083
freebsd/contrib/pf/pfctl/parse.y
Normal file
6083
freebsd/contrib/pf/pfctl/parse.y
Normal file
File diff suppressed because it is too large
Load Diff
382
freebsd/contrib/pf/pfctl/pf_print_state.c
Normal file
382
freebsd/contrib/pf/pfctl/pf_print_state.c
Normal file
@ -0,0 +1,382 @@
|
||||
#include <machine/rtems-bsd-user-space.h>
|
||||
|
||||
/* $OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/bsd/sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#define betoh64 be64toh
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#define TCPSTATES
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pfctl_parser.h"
|
||||
#include "pfctl.h"
|
||||
|
||||
void print_name(struct pf_addr *, sa_family_t);
|
||||
|
||||
void
|
||||
print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
|
||||
{
|
||||
switch (addr->type) {
|
||||
case PF_ADDR_DYNIFTL:
|
||||
printf("(%s", addr->v.ifname);
|
||||
if (addr->iflags & PFI_AFLAG_NETWORK)
|
||||
printf(":network");
|
||||
if (addr->iflags & PFI_AFLAG_BROADCAST)
|
||||
printf(":broadcast");
|
||||
if (addr->iflags & PFI_AFLAG_PEER)
|
||||
printf(":peer");
|
||||
if (addr->iflags & PFI_AFLAG_NOALIAS)
|
||||
printf(":0");
|
||||
if (verbose) {
|
||||
if (addr->p.dyncnt <= 0)
|
||||
printf(":*");
|
||||
else
|
||||
printf(":%d", addr->p.dyncnt);
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
case PF_ADDR_TABLE:
|
||||
if (verbose)
|
||||
if (addr->p.tblcnt == -1)
|
||||
printf("<%s:*>", addr->v.tblname);
|
||||
else
|
||||
printf("<%s:%d>", addr->v.tblname,
|
||||
addr->p.tblcnt);
|
||||
else
|
||||
printf("<%s>", addr->v.tblname);
|
||||
return;
|
||||
case PF_ADDR_RANGE: {
|
||||
char buf[48];
|
||||
|
||||
if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL)
|
||||
printf("?");
|
||||
else
|
||||
printf("%s", buf);
|
||||
if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL)
|
||||
printf(" - ?");
|
||||
else
|
||||
printf(" - %s", buf);
|
||||
break;
|
||||
}
|
||||
case PF_ADDR_ADDRMASK:
|
||||
if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||
PF_AZERO(&addr->v.a.mask, AF_INET6))
|
||||
printf("any");
|
||||
else {
|
||||
char buf[48];
|
||||
|
||||
if (inet_ntop(af, &addr->v.a.addr, buf,
|
||||
sizeof(buf)) == NULL)
|
||||
printf("?");
|
||||
else
|
||||
printf("%s", buf);
|
||||
}
|
||||
break;
|
||||
case PF_ADDR_NOROUTE:
|
||||
printf("no-route");
|
||||
return;
|
||||
case PF_ADDR_URPFFAILED:
|
||||
printf("urpf-failed");
|
||||
return;
|
||||
case PF_ADDR_RTLABEL:
|
||||
printf("route \"%s\"", addr->v.rtlabelname);
|
||||
return;
|
||||
default:
|
||||
printf("?");
|
||||
return;
|
||||
}
|
||||
|
||||
/* mask if not _both_ address and mask are zero */
|
||||
if (addr->type != PF_ADDR_RANGE &&
|
||||
!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
|
||||
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
|
||||
int bits = unmask(&addr->v.a.mask, af);
|
||||
|
||||
if (bits != (af == AF_INET ? 32 : 128))
|
||||
printf("/%d", bits);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_name(struct pf_addr *addr, sa_family_t af)
|
||||
{
|
||||
char host[NI_MAXHOST];
|
||||
|
||||
strlcpy(host, "?", sizeof(host));
|
||||
switch (af) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr = addr->v4;
|
||||
getnameinfo((struct sockaddr *)&sin, sin.sin_len,
|
||||
host, sizeof(host), NULL, 0, NI_NOFQDN);
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = addr->v6;
|
||||
getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
|
||||
host, sizeof(host), NULL, 0, NI_NOFQDN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%s", host);
|
||||
}
|
||||
|
||||
void
|
||||
print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
|
||||
{
|
||||
if (opts & PF_OPT_USEDNS)
|
||||
print_name(addr, af);
|
||||
else {
|
||||
struct pf_addr_wrap aw;
|
||||
|
||||
memset(&aw, 0, sizeof(aw));
|
||||
aw.v.a.addr = *addr;
|
||||
if (af == AF_INET)
|
||||
aw.v.a.mask.addr32[0] = 0xffffffff;
|
||||
else {
|
||||
memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
|
||||
af = AF_INET6;
|
||||
}
|
||||
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
|
||||
}
|
||||
|
||||
if (port) {
|
||||
if (af == AF_INET)
|
||||
printf(":%u", ntohs(port));
|
||||
else
|
||||
printf("[%u]", ntohs(port));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_seq(struct pfsync_state_peer *p)
|
||||
{
|
||||
if (p->seqdiff)
|
||||
printf("[%u + %u](+%u)", ntohl(p->seqlo),
|
||||
ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
|
||||
else
|
||||
printf("[%u + %u]", ntohl(p->seqlo),
|
||||
ntohl(p->seqhi) - ntohl(p->seqlo));
|
||||
}
|
||||
|
||||
void
|
||||
print_state(struct pfsync_state *s, int opts)
|
||||
{
|
||||
struct pfsync_state_peer *src, *dst;
|
||||
struct pfsync_state_key *sk, *nk;
|
||||
struct protoent *p;
|
||||
int min, sec;
|
||||
|
||||
if (s->direction == PF_OUT) {
|
||||
src = &s->src;
|
||||
dst = &s->dst;
|
||||
sk = &s->key[PF_SK_STACK];
|
||||
nk = &s->key[PF_SK_WIRE];
|
||||
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
|
||||
sk->port[0] = nk->port[0];
|
||||
} else {
|
||||
src = &s->dst;
|
||||
dst = &s->src;
|
||||
sk = &s->key[PF_SK_WIRE];
|
||||
nk = &s->key[PF_SK_STACK];
|
||||
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
|
||||
sk->port[1] = nk->port[1];
|
||||
}
|
||||
printf("%s ", s->ifname);
|
||||
if ((p = getprotobynumber(s->proto)) != NULL)
|
||||
printf("%s ", p->p_name);
|
||||
else
|
||||
printf("%u ", s->proto);
|
||||
|
||||
print_host(&nk->addr[1], nk->port[1], s->af, opts);
|
||||
if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
|
||||
nk->port[1] != sk->port[1]) {
|
||||
printf(" (");
|
||||
print_host(&sk->addr[1], sk->port[1], s->af, opts);
|
||||
printf(")");
|
||||
}
|
||||
if (s->direction == PF_OUT)
|
||||
printf(" -> ");
|
||||
else
|
||||
printf(" <- ");
|
||||
print_host(&nk->addr[0], nk->port[0], s->af, opts);
|
||||
if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
|
||||
nk->port[0] != sk->port[0]) {
|
||||
printf(" (");
|
||||
print_host(&sk->addr[0], sk->port[0], s->af, opts);
|
||||
printf(")");
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
if (s->proto == IPPROTO_TCP) {
|
||||
if (src->state <= TCPS_TIME_WAIT &&
|
||||
dst->state <= TCPS_TIME_WAIT)
|
||||
printf(" %s:%s\n", tcpstates[src->state],
|
||||
tcpstates[dst->state]);
|
||||
else if (src->state == PF_TCPS_PROXY_SRC ||
|
||||
dst->state == PF_TCPS_PROXY_SRC)
|
||||
printf(" PROXY:SRC\n");
|
||||
else if (src->state == PF_TCPS_PROXY_DST ||
|
||||
dst->state == PF_TCPS_PROXY_DST)
|
||||
printf(" PROXY:DST\n");
|
||||
else
|
||||
printf(" <BAD STATE LEVELS %u:%u>\n",
|
||||
src->state, dst->state);
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
printf(" ");
|
||||
print_seq(src);
|
||||
if (src->wscale && dst->wscale)
|
||||
printf(" wscale %u",
|
||||
src->wscale & PF_WSCALE_MASK);
|
||||
printf(" ");
|
||||
print_seq(dst);
|
||||
if (src->wscale && dst->wscale)
|
||||
printf(" wscale %u",
|
||||
dst->wscale & PF_WSCALE_MASK);
|
||||
printf("\n");
|
||||
}
|
||||
} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
|
||||
dst->state < PFUDPS_NSTATES) {
|
||||
const char *states[] = PFUDPS_NAMES;
|
||||
|
||||
printf(" %s:%s\n", states[src->state], states[dst->state]);
|
||||
} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
|
||||
dst->state < PFOTHERS_NSTATES) {
|
||||
/* XXX ICMP doesn't really have state levels */
|
||||
const char *states[] = PFOTHERS_NAMES;
|
||||
|
||||
printf(" %s:%s\n", states[src->state], states[dst->state]);
|
||||
} else {
|
||||
printf(" %u:%u\n", src->state, dst->state);
|
||||
}
|
||||
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
u_int64_t packets[2];
|
||||
u_int64_t bytes[2];
|
||||
u_int32_t creation = ntohl(s->creation);
|
||||
u_int32_t expire = ntohl(s->expire);
|
||||
|
||||
sec = creation % 60;
|
||||
creation /= 60;
|
||||
min = creation % 60;
|
||||
creation /= 60;
|
||||
printf(" age %.2u:%.2u:%.2u", creation, min, sec);
|
||||
sec = expire % 60;
|
||||
expire /= 60;
|
||||
min = expire % 60;
|
||||
expire /= 60;
|
||||
printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
|
||||
|
||||
bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
|
||||
bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
|
||||
bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
|
||||
bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
|
||||
printf(", %llu:%llu pkts, %llu:%llu bytes",
|
||||
#ifdef __FreeBSD__
|
||||
(unsigned long long)betoh64(packets[0]),
|
||||
(unsigned long long)betoh64(packets[1]),
|
||||
(unsigned long long)betoh64(bytes[0]),
|
||||
(unsigned long long)betoh64(bytes[1]));
|
||||
#else
|
||||
betoh64(packets[0]),
|
||||
betoh64(packets[1]),
|
||||
betoh64(bytes[0]),
|
||||
betoh64(bytes[1]));
|
||||
#endif
|
||||
if (ntohl(s->anchor) != -1)
|
||||
printf(", anchor %u", ntohl(s->anchor));
|
||||
if (ntohl(s->rule) != -1)
|
||||
printf(", rule %u", ntohl(s->rule));
|
||||
if (s->state_flags & PFSTATE_SLOPPY)
|
||||
printf(", sloppy");
|
||||
if (s->state_flags & PFSTATE_PFLOW)
|
||||
printf(", pflow");
|
||||
if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
|
||||
printf(", source-track");
|
||||
if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
|
||||
printf(", sticky-address");
|
||||
printf("\n");
|
||||
}
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
u_int64_t id;
|
||||
|
||||
bcopy(&s->id, &id, sizeof(u_int64_t));
|
||||
printf(" id: %016llx creatorid: %08x",
|
||||
#ifdef __FreeBSD__
|
||||
(unsigned long long)betoh64(id), ntohl(s->creatorid));
|
||||
#else
|
||||
betoh64(id), ntohl(s->creatorid));
|
||||
#endif
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
unmask(struct pf_addr *m, sa_family_t af)
|
||||
{
|
||||
int i = 31, j = 0, b = 0;
|
||||
u_int32_t tmp;
|
||||
|
||||
while (j < 4 && m->addr32[j] == 0xffffffff) {
|
||||
b += 32;
|
||||
j++;
|
||||
}
|
||||
if (j < 4) {
|
||||
tmp = ntohl(m->addr32[j]);
|
||||
for (i = 31; tmp & (1 << i); --i)
|
||||
b++;
|
||||
}
|
||||
return (b);
|
||||
}
|
2410
freebsd/contrib/pf/pfctl/pfctl.c
Normal file
2410
freebsd/contrib/pf/pfctl/pfctl.c
Normal file
File diff suppressed because it is too large
Load Diff
130
freebsd/contrib/pf/pfctl/pfctl.h
Normal file
130
freebsd/contrib/pf/pfctl/pfctl.h
Normal file
@ -0,0 +1,130 @@
|
||||
/* $OpenBSD: pfctl.h,v 1.42 2007/12/05 12:01:47 chl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PFCTL_H_
|
||||
#define _PFCTL_H_
|
||||
|
||||
enum pfctl_show { PFCTL_SHOW_RULES, PFCTL_SHOW_LABELS, PFCTL_SHOW_NOTHING };
|
||||
|
||||
enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS,
|
||||
PFRB_IFACES, PFRB_TRANS, PFRB_MAX };
|
||||
struct pfr_buffer {
|
||||
int pfrb_type; /* type of content, see enum above */
|
||||
int pfrb_size; /* number of objects in buffer */
|
||||
int pfrb_msize; /* maximum number of objects in buffer */
|
||||
void *pfrb_caddr; /* malloc'ated memory area */
|
||||
};
|
||||
#define PFRB_FOREACH(var, buf) \
|
||||
for ((var) = pfr_buf_next((buf), NULL); \
|
||||
(var) != NULL; \
|
||||
(var) = pfr_buf_next((buf), (var)))
|
||||
|
||||
int pfr_get_fd(void);
|
||||
int pfr_clr_tables(struct pfr_table *, int *, int);
|
||||
int pfr_add_tables(struct pfr_table *, int, int *, int);
|
||||
int pfr_del_tables(struct pfr_table *, int, int *, int);
|
||||
int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int);
|
||||
int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int);
|
||||
int pfr_clr_tstats(struct pfr_table *, int, int *, int);
|
||||
int pfr_clr_addrs(struct pfr_table *, int *, int);
|
||||
int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int *, int *, int *, int);
|
||||
int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
|
||||
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
|
||||
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
|
||||
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int *, int, int);
|
||||
void pfr_buf_clear(struct pfr_buffer *);
|
||||
int pfr_buf_add(struct pfr_buffer *, const void *);
|
||||
void *pfr_buf_next(struct pfr_buffer *, const void *);
|
||||
int pfr_buf_grow(struct pfr_buffer *, int);
|
||||
int pfr_buf_load(struct pfr_buffer *, char *, int,
|
||||
int (*)(struct pfr_buffer *, char *, int));
|
||||
char *pfr_strerror(int);
|
||||
int pfi_get_ifaces(const char *, struct pfi_kif *, int *);
|
||||
int pfi_clr_istats(const char *, int *, int);
|
||||
|
||||
void pfctl_print_title(char *);
|
||||
int pfctl_clear_tables(const char *, int);
|
||||
int pfctl_show_tables(const char *, int);
|
||||
int pfctl_command_tables(int, char *[], char *, const char *, char *,
|
||||
const char *, int);
|
||||
int pfctl_show_altq(int, const char *, int, int);
|
||||
void warn_namespace_collision(const char *);
|
||||
int pfctl_show_ifaces(const char *, int);
|
||||
FILE *pfctl_fopen(const char *, const char *);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
extern int altqsupport;
|
||||
extern int dummynetsupport;
|
||||
#define HTONL(x) (x) = htonl((__uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_PRIORITY
|
||||
#define DEFAULT_PRIORITY 1
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_QLIMIT
|
||||
#define DEFAULT_QLIMIT 50
|
||||
#endif
|
||||
|
||||
/*
|
||||
* generalized service curve used for admission control
|
||||
*/
|
||||
struct segment {
|
||||
LIST_ENTRY(segment) _next;
|
||||
double x, y, d, m;
|
||||
};
|
||||
|
||||
extern int loadopt;
|
||||
|
||||
int check_commit_altq(int, int);
|
||||
void pfaltq_store(struct pf_altq *);
|
||||
struct pf_altq *pfaltq_lookup(const char *);
|
||||
char *rate2str(double);
|
||||
|
||||
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
|
||||
void print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
|
||||
void print_seq(struct pfsync_state_peer *);
|
||||
void print_state(struct pfsync_state *, int);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
|
||||
int pfctl_cmdline_symset(char *);
|
||||
int pfctl_add_trans(struct pfr_buffer *, int, const char *);
|
||||
u_int32_t
|
||||
pfctl_get_ticket(struct pfr_buffer *, int, const char *);
|
||||
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
|
||||
|
||||
#endif /* _PFCTL_H_ */
|
1260
freebsd/contrib/pf/pfctl/pfctl_altq.c
Normal file
1260
freebsd/contrib/pf/pfctl/pfctl_altq.c
Normal file
File diff suppressed because it is too large
Load Diff
1657
freebsd/contrib/pf/pfctl/pfctl_optimize.c
Normal file
1657
freebsd/contrib/pf/pfctl/pfctl_optimize.c
Normal file
File diff suppressed because it is too large
Load Diff
1110
freebsd/contrib/pf/pfctl/pfctl_osfp.c
Normal file
1110
freebsd/contrib/pf/pfctl/pfctl_osfp.c
Normal file
File diff suppressed because it is too large
Load Diff
1754
freebsd/contrib/pf/pfctl/pfctl_parser.c
Normal file
1754
freebsd/contrib/pf/pfctl/pfctl_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
305
freebsd/contrib/pf/pfctl/pfctl_parser.h
Normal file
305
freebsd/contrib/pf/pfctl/pfctl_parser.h
Normal file
@ -0,0 +1,305 @@
|
||||
/* $OpenBSD: pfctl_parser.h,v 1.86 2006/10/31 23:46:25 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PFCTL_PARSER_H_
|
||||
#define _PFCTL_PARSER_H_
|
||||
|
||||
#define PF_OSFP_FILE "/etc/pf.os"
|
||||
|
||||
#define PF_OPT_DISABLE 0x0001
|
||||
#define PF_OPT_ENABLE 0x0002
|
||||
#define PF_OPT_VERBOSE 0x0004
|
||||
#define PF_OPT_NOACTION 0x0008
|
||||
#define PF_OPT_QUIET 0x0010
|
||||
#define PF_OPT_CLRRULECTRS 0x0020
|
||||
#define PF_OPT_USEDNS 0x0040
|
||||
#define PF_OPT_VERBOSE2 0x0080
|
||||
#define PF_OPT_DUMMYACTION 0x0100
|
||||
#define PF_OPT_DEBUG 0x0200
|
||||
#define PF_OPT_SHOWALL 0x0400
|
||||
#define PF_OPT_OPTIMIZE 0x0800
|
||||
#define PF_OPT_NUMERIC 0x1000
|
||||
#define PF_OPT_MERGE 0x2000
|
||||
#define PF_OPT_RECURSE 0x4000
|
||||
|
||||
#define PF_TH_ALL 0xFF
|
||||
|
||||
#define PF_NAT_PROXY_PORT_LOW 50001
|
||||
#define PF_NAT_PROXY_PORT_HIGH 65535
|
||||
|
||||
#define PF_OPTIMIZE_BASIC 0x0001
|
||||
#define PF_OPTIMIZE_PROFILE 0x0002
|
||||
|
||||
#define FCNT_NAMES { \
|
||||
"searches", \
|
||||
"inserts", \
|
||||
"removals", \
|
||||
NULL \
|
||||
}
|
||||
|
||||
struct pfr_buffer; /* forward definition */
|
||||
|
||||
|
||||
struct pfctl {
|
||||
int dev;
|
||||
int opts;
|
||||
int optimize;
|
||||
int loadopt;
|
||||
int asd; /* anchor stack depth */
|
||||
int bn; /* brace number */
|
||||
int brace;
|
||||
int tdirty; /* kernel dirty */
|
||||
#define PFCTL_ANCHOR_STACK_DEPTH 64
|
||||
struct pf_anchor *astack[PFCTL_ANCHOR_STACK_DEPTH];
|
||||
struct pfioc_pooladdr paddr;
|
||||
struct pfioc_altq *paltq;
|
||||
struct pfioc_queue *pqueue;
|
||||
struct pfr_buffer *trans;
|
||||
struct pf_anchor *anchor, *alast;
|
||||
const char *ruleset;
|
||||
|
||||
/* 'set foo' options */
|
||||
u_int32_t timeout[PFTM_MAX];
|
||||
u_int32_t limit[PF_LIMIT_MAX];
|
||||
u_int32_t debug;
|
||||
u_int32_t hostid;
|
||||
char *ifname;
|
||||
|
||||
u_int8_t timeout_set[PFTM_MAX];
|
||||
u_int8_t limit_set[PF_LIMIT_MAX];
|
||||
u_int8_t debug_set;
|
||||
u_int8_t hostid_set;
|
||||
u_int8_t ifname_set;
|
||||
};
|
||||
|
||||
struct node_if {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_int8_t not;
|
||||
u_int8_t dynamic; /* antispoof */
|
||||
u_int ifa_flags;
|
||||
struct node_if *next;
|
||||
struct node_if *tail;
|
||||
};
|
||||
|
||||
struct node_host {
|
||||
struct pf_addr_wrap addr;
|
||||
struct pf_addr bcast;
|
||||
struct pf_addr peer;
|
||||
sa_family_t af;
|
||||
u_int8_t not;
|
||||
u_int32_t ifindex; /* link-local IPv6 addrs */
|
||||
char *ifname;
|
||||
u_int ifa_flags;
|
||||
struct node_host *next;
|
||||
struct node_host *tail;
|
||||
};
|
||||
|
||||
struct node_os {
|
||||
char *os;
|
||||
pf_osfp_t fingerprint;
|
||||
struct node_os *next;
|
||||
struct node_os *tail;
|
||||
};
|
||||
|
||||
struct node_queue_bw {
|
||||
u_int32_t bw_absolute;
|
||||
u_int16_t bw_percent;
|
||||
};
|
||||
|
||||
struct node_hfsc_sc {
|
||||
struct node_queue_bw m1; /* slope of 1st segment; bps */
|
||||
u_int d; /* x-projection of m1; msec */
|
||||
struct node_queue_bw m2; /* slope of 2nd segment; bps */
|
||||
u_int8_t used;
|
||||
};
|
||||
|
||||
struct node_hfsc_opts {
|
||||
struct node_hfsc_sc realtime;
|
||||
struct node_hfsc_sc linkshare;
|
||||
struct node_hfsc_sc upperlimit;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct node_queue_opt {
|
||||
int qtype;
|
||||
union {
|
||||
struct cbq_opts cbq_opts;
|
||||
struct priq_opts priq_opts;
|
||||
struct node_hfsc_opts hfsc_opts;
|
||||
} data;
|
||||
};
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* XXX
|
||||
* Absolutely this is not correct location to define this.
|
||||
* Should we use an another sperate header file?
|
||||
*/
|
||||
#define SIMPLEQ_HEAD STAILQ_HEAD
|
||||
#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER
|
||||
#define SIMPLEQ_ENTRY STAILQ_ENTRY
|
||||
#define SIMPLEQ_FIRST STAILQ_FIRST
|
||||
#define SIMPLEQ_END(head) NULL
|
||||
#define SIMPLEQ_EMPTY STAILQ_EMPTY
|
||||
#define SIMPLEQ_NEXT STAILQ_NEXT
|
||||
/*#define SIMPLEQ_FOREACH STAILQ_FOREACH*/
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for((var) = SIMPLEQ_FIRST(head); \
|
||||
(var) != SIMPLEQ_END(head); \
|
||||
(var) = SIMPLEQ_NEXT(var, field))
|
||||
#define SIMPLEQ_INIT STAILQ_INIT
|
||||
#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
|
||||
#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL
|
||||
#define SIMPLEQ_INSERT_AFTER STAILQ_INSERT_AFTER
|
||||
#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD
|
||||
#endif
|
||||
SIMPLEQ_HEAD(node_tinithead, node_tinit);
|
||||
struct node_tinit { /* table initializer */
|
||||
SIMPLEQ_ENTRY(node_tinit) entries;
|
||||
struct node_host *host;
|
||||
char *file;
|
||||
};
|
||||
|
||||
|
||||
/* optimizer created tables */
|
||||
struct pf_opt_tbl {
|
||||
char pt_name[PF_TABLE_NAME_SIZE];
|
||||
int pt_rulecount;
|
||||
int pt_generated;
|
||||
struct node_tinithead pt_nodes;
|
||||
struct pfr_buffer *pt_buf;
|
||||
};
|
||||
#define PF_OPT_TABLE_PREFIX "__automatic_"
|
||||
|
||||
/* optimizer pf_rule container */
|
||||
struct pf_opt_rule {
|
||||
struct pf_rule por_rule;
|
||||
struct pf_opt_tbl *por_src_tbl;
|
||||
struct pf_opt_tbl *por_dst_tbl;
|
||||
u_int64_t por_profile_count;
|
||||
TAILQ_ENTRY(pf_opt_rule) por_entry;
|
||||
TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
|
||||
};
|
||||
|
||||
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
|
||||
|
||||
int pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *);
|
||||
int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
|
||||
|
||||
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
|
||||
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
|
||||
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
|
||||
void pfctl_move_pool(struct pf_pool *, struct pf_pool *);
|
||||
void pfctl_clear_pool(struct pf_pool *);
|
||||
|
||||
int pfctl_set_timeout(struct pfctl *, const char *, int, int);
|
||||
int pfctl_set_optimization(struct pfctl *, const char *);
|
||||
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||
int pfctl_set_logif(struct pfctl *, char *);
|
||||
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||
int pfctl_set_debug(struct pfctl *, char *);
|
||||
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
|
||||
|
||||
int parse_config(char *, struct pfctl *);
|
||||
int parse_flags(char *);
|
||||
int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
|
||||
|
||||
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
|
||||
void print_src_node(struct pf_src_node *, int);
|
||||
void print_rule(struct pf_rule *, const char *, int, int);
|
||||
void print_tabledef(const char *, int, int, struct node_tinithead *);
|
||||
void print_status(struct pf_status *, int);
|
||||
|
||||
int eval_pfaltq(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
int eval_pfqueue(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
|
||||
void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
struct node_queue_opt *);
|
||||
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
|
||||
int, struct node_queue_opt *);
|
||||
|
||||
int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
|
||||
u_int32_t);
|
||||
|
||||
void pfctl_clear_fingerprints(int, int);
|
||||
int pfctl_file_fingerprints(int, int, const char *);
|
||||
pf_osfp_t pfctl_get_fingerprint(const char *);
|
||||
int pfctl_load_fingerprints(int, int);
|
||||
char *pfctl_lookup_fingerprint(pf_osfp_t, char *, size_t);
|
||||
void pfctl_show_fingerprints(int);
|
||||
|
||||
|
||||
struct icmptypeent {
|
||||
const char *name;
|
||||
u_int8_t type;
|
||||
};
|
||||
|
||||
struct icmpcodeent {
|
||||
const char *name;
|
||||
u_int8_t type;
|
||||
u_int8_t code;
|
||||
};
|
||||
|
||||
const struct icmptypeent *geticmptypebynumber(u_int8_t, u_int8_t);
|
||||
const struct icmptypeent *geticmptypebyname(char *, u_int8_t);
|
||||
const struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t, u_int8_t);
|
||||
const struct icmpcodeent *geticmpcodebyname(u_long, char *, u_int8_t);
|
||||
|
||||
struct pf_timeout {
|
||||
const char *name;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
#define PFCTL_FLAG_FILTER 0x02
|
||||
#define PFCTL_FLAG_NAT 0x04
|
||||
#define PFCTL_FLAG_OPTION 0x08
|
||||
#define PFCTL_FLAG_ALTQ 0x10
|
||||
#define PFCTL_FLAG_TABLE 0x20
|
||||
|
||||
extern const struct pf_timeout pf_timeouts[];
|
||||
|
||||
void set_ipmask(struct node_host *, u_int8_t);
|
||||
int check_netmask(struct node_host *, sa_family_t);
|
||||
int unmask(struct pf_addr *, sa_family_t);
|
||||
void ifa_load(void);
|
||||
struct node_host *ifa_exists(const char *);
|
||||
struct node_host *ifa_lookup(const char *, int);
|
||||
struct node_host *host(const char *);
|
||||
|
||||
int append_addr(struct pfr_buffer *, char *, int);
|
||||
int append_addr_host(struct pfr_buffer *,
|
||||
struct node_host *, int, int);
|
||||
|
||||
#endif /* _PFCTL_PARSER_H_ */
|
451
freebsd/contrib/pf/pfctl/pfctl_qstats.c
Normal file
451
freebsd/contrib/pf/pfctl/pfctl_qstats.c
Normal file
@ -0,0 +1,451 @@
|
||||
#include <machine/rtems-bsd-user-space.h>
|
||||
|
||||
/* $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) Henning Brauer <henning@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/bsd/sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <altq/altq.h>
|
||||
#include <altq/altq_cbq.h>
|
||||
#include <altq/altq_priq.h>
|
||||
#include <altq/altq_hfsc.h>
|
||||
|
||||
#include "pfctl.h"
|
||||
#include "pfctl_parser.h"
|
||||
|
||||
union class_stats {
|
||||
class_stats_t cbq_stats;
|
||||
struct priq_classstats priq_stats;
|
||||
struct hfsc_classstats hfsc_stats;
|
||||
};
|
||||
|
||||
#define AVGN_MAX 8
|
||||
#define STAT_INTERVAL 5
|
||||
|
||||
struct queue_stats {
|
||||
union class_stats data;
|
||||
int avgn;
|
||||
double avg_bytes;
|
||||
double avg_packets;
|
||||
u_int64_t prev_bytes;
|
||||
u_int64_t prev_packets;
|
||||
};
|
||||
|
||||
struct pf_altq_node {
|
||||
struct pf_altq altq;
|
||||
struct pf_altq_node *next;
|
||||
struct pf_altq_node *children;
|
||||
struct queue_stats qstats;
|
||||
};
|
||||
|
||||
int pfctl_update_qstats(int, struct pf_altq_node **);
|
||||
void pfctl_insert_altq_node(struct pf_altq_node **,
|
||||
const struct pf_altq, const struct queue_stats);
|
||||
struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *,
|
||||
const char *, const char *);
|
||||
void pfctl_print_altq_node(int, const struct pf_altq_node *,
|
||||
unsigned, int);
|
||||
void print_cbqstats(struct queue_stats);
|
||||
void print_priqstats(struct queue_stats);
|
||||
void print_hfscstats(struct queue_stats);
|
||||
void pfctl_free_altq_node(struct pf_altq_node *);
|
||||
void pfctl_print_altq_nodestat(int,
|
||||
const struct pf_altq_node *);
|
||||
|
||||
void update_avg(struct pf_altq_node *);
|
||||
|
||||
int
|
||||
pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
|
||||
{
|
||||
struct pf_altq_node *root = NULL, *node;
|
||||
int nodes, dotitle = (opts & PF_OPT_SHOWALL);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (!altqsupport)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
|
||||
return (-1);
|
||||
|
||||
if (nodes == 0)
|
||||
printf("No queue in use\n");
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
continue;
|
||||
if (dotitle) {
|
||||
pfctl_print_title("ALTQ:");
|
||||
dotitle = 0;
|
||||
}
|
||||
pfctl_print_altq_node(dev, node, 0, opts);
|
||||
}
|
||||
|
||||
while (verbose2 && nodes > 0) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
sleep(STAT_INTERVAL);
|
||||
if ((nodes = pfctl_update_qstats(dev, &root)) == -1)
|
||||
return (-1);
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (iface != NULL && strcmp(node->altq.ifname, iface))
|
||||
continue;
|
||||
#ifdef __FreeBSD__
|
||||
if (node->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
|
||||
continue;
|
||||
#endif
|
||||
pfctl_print_altq_node(dev, node, 0, opts);
|
||||
}
|
||||
}
|
||||
pfctl_free_altq_node(root);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_update_qstats(int dev, struct pf_altq_node **root)
|
||||
{
|
||||
struct pf_altq_node *node;
|
||||
struct pfioc_altq pa;
|
||||
struct pfioc_qstats pq;
|
||||
u_int32_t mnr, nr;
|
||||
struct queue_stats qstats;
|
||||
static u_int32_t last_ticket;
|
||||
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
memset(&pq, 0, sizeof(pq));
|
||||
memset(&qstats, 0, sizeof(qstats));
|
||||
if (ioctl(dev, DIOCGETALTQS, &pa)) {
|
||||
warn("DIOCGETALTQS");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* if a new set is found, start over */
|
||||
if (pa.ticket != last_ticket && *root != NULL) {
|
||||
pfctl_free_altq_node(*root);
|
||||
*root = NULL;
|
||||
}
|
||||
last_ticket = pa.ticket;
|
||||
|
||||
mnr = pa.nr;
|
||||
for (nr = 0; nr < mnr; ++nr) {
|
||||
pa.nr = nr;
|
||||
if (ioctl(dev, DIOCGETALTQ, &pa)) {
|
||||
warn("DIOCGETALTQ");
|
||||
return (-1);
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
if (pa.altq.qid > 0 &&
|
||||
!(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) {
|
||||
#else
|
||||
if (pa.altq.qid > 0) {
|
||||
#endif
|
||||
pq.nr = nr;
|
||||
pq.ticket = pa.ticket;
|
||||
pq.buf = &qstats.data;
|
||||
pq.nbytes = sizeof(qstats.data);
|
||||
if (ioctl(dev, DIOCGETQSTATS, &pq)) {
|
||||
warn("DIOCGETQSTATS");
|
||||
return (-1);
|
||||
}
|
||||
if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
|
||||
pa.altq.ifname)) != NULL) {
|
||||
memcpy(&node->qstats.data, &qstats.data,
|
||||
sizeof(qstats.data));
|
||||
update_avg(node);
|
||||
} else {
|
||||
pfctl_insert_altq_node(root, pa.altq, qstats);
|
||||
}
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
|
||||
memset(&qstats.data, 0, sizeof(qstats.data));
|
||||
if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
|
||||
pa.altq.ifname)) != NULL) {
|
||||
memcpy(&node->qstats.data, &qstats.data,
|
||||
sizeof(qstats.data));
|
||||
update_avg(node);
|
||||
} else {
|
||||
pfctl_insert_altq_node(root, pa.altq, qstats);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return (mnr);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_insert_altq_node(struct pf_altq_node **root,
|
||||
const struct pf_altq altq, const struct queue_stats qstats)
|
||||
{
|
||||
struct pf_altq_node *node;
|
||||
|
||||
node = calloc(1, sizeof(struct pf_altq_node));
|
||||
if (node == NULL)
|
||||
err(1, "pfctl_insert_altq_node: calloc");
|
||||
memcpy(&node->altq, &altq, sizeof(struct pf_altq));
|
||||
memcpy(&node->qstats, &qstats, sizeof(qstats));
|
||||
node->next = node->children = NULL;
|
||||
|
||||
if (*root == NULL)
|
||||
*root = node;
|
||||
else if (!altq.parent[0]) {
|
||||
struct pf_altq_node *prev = *root;
|
||||
|
||||
while (prev->next != NULL)
|
||||
prev = prev->next;
|
||||
prev->next = node;
|
||||
} else {
|
||||
struct pf_altq_node *parent;
|
||||
|
||||
parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname);
|
||||
if (parent == NULL)
|
||||
errx(1, "parent %s not found", altq.parent);
|
||||
if (parent->children == NULL)
|
||||
parent->children = node;
|
||||
else {
|
||||
struct pf_altq_node *prev = parent->children;
|
||||
|
||||
while (prev->next != NULL)
|
||||
prev = prev->next;
|
||||
prev->next = node;
|
||||
}
|
||||
}
|
||||
update_avg(node);
|
||||
}
|
||||
|
||||
struct pf_altq_node *
|
||||
pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
|
||||
const char *ifname)
|
||||
{
|
||||
struct pf_altq_node *node, *child;
|
||||
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
if (!strcmp(node->altq.qname, qname)
|
||||
&& !(strcmp(node->altq.ifname, ifname)))
|
||||
return (node);
|
||||
if (node->children != NULL) {
|
||||
child = pfctl_find_altq_node(node->children, qname,
|
||||
ifname);
|
||||
if (child != NULL)
|
||||
return (child);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
|
||||
unsigned int level, int opts)
|
||||
{
|
||||
const struct pf_altq_node *child;
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
print_altq(&node->altq, level, NULL, NULL);
|
||||
|
||||
if (node->children != NULL) {
|
||||
printf("{");
|
||||
for (child = node->children; child != NULL;
|
||||
child = child->next) {
|
||||
printf("%s", child->altq.qname);
|
||||
if (child->next != NULL)
|
||||
printf(", ");
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
pfctl_print_altq_nodestat(dev, node);
|
||||
|
||||
if (opts & PF_OPT_DEBUG)
|
||||
printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n",
|
||||
node->altq.qid, node->altq.ifname,
|
||||
rate2str((double)(node->altq.ifbandwidth)));
|
||||
|
||||
for (child = node->children; child != NULL;
|
||||
child = child->next)
|
||||
pfctl_print_altq_node(dev, child, level + 1, opts);
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
|
||||
{
|
||||
if (a->altq.qid == 0)
|
||||
return;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
|
||||
return;
|
||||
#endif
|
||||
switch (a->altq.scheduler) {
|
||||
case ALTQT_CBQ:
|
||||
print_cbqstats(a->qstats);
|
||||
break;
|
||||
case ALTQT_PRIQ:
|
||||
print_priqstats(a->qstats);
|
||||
break;
|
||||
case ALTQT_HFSC:
|
||||
print_hfscstats(a->qstats);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_cbqstats(struct queue_stats cur)
|
||||
{
|
||||
printf(" [ pkts: %10llu bytes: %10llu "
|
||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||
(unsigned long long)cur.data.cbq_stats.xmit_cnt.packets,
|
||||
(unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes,
|
||||
(unsigned long long)cur.data.cbq_stats.drop_cnt.packets,
|
||||
(unsigned long long)cur.data.cbq_stats.drop_cnt.bytes);
|
||||
printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n",
|
||||
cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax,
|
||||
cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays);
|
||||
|
||||
if (cur.avgn < 2)
|
||||
return;
|
||||
|
||||
printf(" [ measured: %7.1f packets/s, %s/s ]\n",
|
||||
cur.avg_packets / STAT_INTERVAL,
|
||||
rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
|
||||
}
|
||||
|
||||
void
|
||||
print_priqstats(struct queue_stats cur)
|
||||
{
|
||||
printf(" [ pkts: %10llu bytes: %10llu "
|
||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||
(unsigned long long)cur.data.priq_stats.xmitcnt.packets,
|
||||
(unsigned long long)cur.data.priq_stats.xmitcnt.bytes,
|
||||
(unsigned long long)cur.data.priq_stats.dropcnt.packets,
|
||||
(unsigned long long)cur.data.priq_stats.dropcnt.bytes);
|
||||
printf(" [ qlength: %3d/%3d ]\n",
|
||||
cur.data.priq_stats.qlength, cur.data.priq_stats.qlimit);
|
||||
|
||||
if (cur.avgn < 2)
|
||||
return;
|
||||
|
||||
printf(" [ measured: %7.1f packets/s, %s/s ]\n",
|
||||
cur.avg_packets / STAT_INTERVAL,
|
||||
rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
|
||||
}
|
||||
|
||||
void
|
||||
print_hfscstats(struct queue_stats cur)
|
||||
{
|
||||
printf(" [ pkts: %10llu bytes: %10llu "
|
||||
"dropped pkts: %6llu bytes: %6llu ]\n",
|
||||
(unsigned long long)cur.data.hfsc_stats.xmit_cnt.packets,
|
||||
(unsigned long long)cur.data.hfsc_stats.xmit_cnt.bytes,
|
||||
(unsigned long long)cur.data.hfsc_stats.drop_cnt.packets,
|
||||
(unsigned long long)cur.data.hfsc_stats.drop_cnt.bytes);
|
||||
printf(" [ qlength: %3d/%3d ]\n",
|
||||
cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit);
|
||||
|
||||
if (cur.avgn < 2)
|
||||
return;
|
||||
|
||||
printf(" [ measured: %7.1f packets/s, %s/s ]\n",
|
||||
cur.avg_packets / STAT_INTERVAL,
|
||||
rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
|
||||
}
|
||||
|
||||
void
|
||||
pfctl_free_altq_node(struct pf_altq_node *node)
|
||||
{
|
||||
while (node != NULL) {
|
||||
struct pf_altq_node *prev;
|
||||
|
||||
if (node->children != NULL)
|
||||
pfctl_free_altq_node(node->children);
|
||||
prev = node;
|
||||
node = node->next;
|
||||
free(prev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
update_avg(struct pf_altq_node *a)
|
||||
{
|
||||
struct queue_stats *qs;
|
||||
u_int64_t b, p;
|
||||
int n;
|
||||
|
||||
if (a->altq.qid == 0)
|
||||
return;
|
||||
|
||||
qs = &a->qstats;
|
||||
n = qs->avgn;
|
||||
|
||||
switch (a->altq.scheduler) {
|
||||
case ALTQT_CBQ:
|
||||
b = qs->data.cbq_stats.xmit_cnt.bytes;
|
||||
p = qs->data.cbq_stats.xmit_cnt.packets;
|
||||
break;
|
||||
case ALTQT_PRIQ:
|
||||
b = qs->data.priq_stats.xmitcnt.bytes;
|
||||
p = qs->data.priq_stats.xmitcnt.packets;
|
||||
break;
|
||||
case ALTQT_HFSC:
|
||||
b = qs->data.hfsc_stats.xmit_cnt.bytes;
|
||||
p = qs->data.hfsc_stats.xmit_cnt.packets;
|
||||
break;
|
||||
default:
|
||||
b = 0;
|
||||
p = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
qs->prev_bytes = b;
|
||||
qs->prev_packets = p;
|
||||
qs->avgn++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (b >= qs->prev_bytes)
|
||||
qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
|
||||
(b - qs->prev_bytes)) / n;
|
||||
|
||||
if (p >= qs->prev_packets)
|
||||
qs->avg_packets = ((qs->avg_packets * (n - 1)) +
|
||||
(p - qs->prev_packets)) / n;
|
||||
|
||||
qs->prev_bytes = b;
|
||||
qs->prev_packets = p;
|
||||
if (n < AVGN_MAX)
|
||||
qs->avgn++;
|
||||
}
|
587
freebsd/contrib/pf/pfctl/pfctl_radix.c
Normal file
587
freebsd/contrib/pf/pfctl/pfctl_radix.c
Normal file
@ -0,0 +1,587 @@
|
||||
#include <machine/rtems-bsd-user-space.h>
|
||||
|
||||
/* $OpenBSD: pfctl_radix.c,v 1.27 2005/05/21 21:03:58 henning Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/bsd/sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "pfctl.h"
|
||||
|
||||
#define BUF_SIZE 256
|
||||
|
||||
extern int dev;
|
||||
|
||||
static int pfr_next_token(char buf[], FILE *);
|
||||
|
||||
|
||||
int
|
||||
pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
if (filter != NULL)
|
||||
io.pfrio_table = *filter;
|
||||
if (ioctl(dev, DIOCRCLRTABLES, &io))
|
||||
return (-1);
|
||||
if (ndel != NULL)
|
||||
*ndel = io.pfrio_ndel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && tbl == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRADDTABLES, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && tbl == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRDELTABLES, &io))
|
||||
return (-1);
|
||||
if (ndel != NULL)
|
||||
*ndel = io.pfrio_ndel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
|
||||
int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
if (filter != NULL)
|
||||
io.pfrio_table = *filter;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = *size;
|
||||
if (ioctl(dev, DIOCRGETTABLES, &io))
|
||||
return (-1);
|
||||
*size = io.pfrio_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
|
||||
int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
if (filter != NULL)
|
||||
io.pfrio_table = *filter;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = *size;
|
||||
if (ioctl(dev, DIOCRGETTSTATS, &io))
|
||||
return (-1);
|
||||
*size = io.pfrio_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
if (ioctl(dev, DIOCRCLRADDRS, &io))
|
||||
return (-1);
|
||||
if (ndel != NULL)
|
||||
*ndel = io.pfrio_ndel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *nadd, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRADDADDRS, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *ndel, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRDELADDRS, &io))
|
||||
return (-1);
|
||||
if (ndel != NULL)
|
||||
*ndel = io.pfrio_ndel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *size2, int *nadd, int *ndel, int *nchange, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
|
||||
if (ioctl(dev, DIOCRSETADDRS, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
if (ndel != NULL)
|
||||
*ndel = io.pfrio_ndel;
|
||||
if (nchange != NULL)
|
||||
*nchange = io.pfrio_nchange;
|
||||
if (size2 != NULL)
|
||||
*size2 = io.pfrio_size2;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
|
||||
int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size == NULL || *size < 0 ||
|
||||
(*size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = *size;
|
||||
if (ioctl(dev, DIOCRGETADDRS, &io))
|
||||
return (-1);
|
||||
*size = io.pfrio_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
|
||||
int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size == NULL || *size < 0 ||
|
||||
(*size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = *size;
|
||||
if (ioctl(dev, DIOCRGETASTATS, &io))
|
||||
return (-1);
|
||||
*size = io.pfrio_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && !tbl)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRCLRTSTATS, &io))
|
||||
return (-1);
|
||||
if (nzero)
|
||||
*nzero = io.pfrio_nzero;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *nmatch, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRTSTADDRS, &io))
|
||||
return (-1);
|
||||
if (nmatch)
|
||||
*nmatch = io.pfrio_nmatch;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
int *nadd, int *naddr, int ticket, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_table = *tbl;
|
||||
io.pfrio_buffer = addr;
|
||||
io.pfrio_esize = sizeof(*addr);
|
||||
io.pfrio_size = size;
|
||||
io.pfrio_ticket = ticket;
|
||||
if (ioctl(dev, DIOCRINADEFINE, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
if (naddr != NULL)
|
||||
*naddr = io.pfrio_naddr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* interface management code */
|
||||
|
||||
int
|
||||
pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size)
|
||||
{
|
||||
struct pfioc_iface io;
|
||||
|
||||
if (size == NULL || *size < 0 || (*size && buf == NULL)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
if (filter != NULL)
|
||||
if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
|
||||
sizeof(io.pfiio_name)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
io.pfiio_buffer = buf;
|
||||
io.pfiio_esize = sizeof(*buf);
|
||||
io.pfiio_size = *size;
|
||||
if (ioctl(dev, DIOCIGETIFACES, &io))
|
||||
return (-1);
|
||||
*size = io.pfiio_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* buffer management code */
|
||||
|
||||
size_t buf_esize[PFRB_MAX] = { 0,
|
||||
sizeof(struct pfr_table), sizeof(struct pfr_tstats),
|
||||
sizeof(struct pfr_addr), sizeof(struct pfr_astats),
|
||||
sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
|
||||
};
|
||||
|
||||
/*
|
||||
* add one element to the buffer
|
||||
*/
|
||||
int
|
||||
pfr_buf_add(struct pfr_buffer *b, const void *e)
|
||||
{
|
||||
size_t bs;
|
||||
|
||||
if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
|
||||
e == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bs = buf_esize[b->pfrb_type];
|
||||
if (b->pfrb_size == b->pfrb_msize)
|
||||
if (pfr_buf_grow(b, 0))
|
||||
return (-1);
|
||||
memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
|
||||
b->pfrb_size++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* return next element of the buffer (or first one if prev is NULL)
|
||||
* see PFRB_FOREACH macro
|
||||
*/
|
||||
void *
|
||||
pfr_buf_next(struct pfr_buffer *b, const void *prev)
|
||||
{
|
||||
size_t bs;
|
||||
|
||||
if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX)
|
||||
return (NULL);
|
||||
if (b->pfrb_size == 0)
|
||||
return (NULL);
|
||||
if (prev == NULL)
|
||||
return (b->pfrb_caddr);
|
||||
bs = buf_esize[b->pfrb_type];
|
||||
if ((((caddr_t)prev)-((caddr_t)b->pfrb_caddr)) / bs >= b->pfrb_size-1)
|
||||
return (NULL);
|
||||
return (((caddr_t)prev) + bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* minsize:
|
||||
* 0: make the buffer somewhat bigger
|
||||
* n: make room for "n" entries in the buffer
|
||||
*/
|
||||
int
|
||||
pfr_buf_grow(struct pfr_buffer *b, int minsize)
|
||||
{
|
||||
caddr_t p;
|
||||
size_t bs;
|
||||
|
||||
if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (minsize != 0 && minsize <= b->pfrb_msize)
|
||||
return (0);
|
||||
bs = buf_esize[b->pfrb_type];
|
||||
if (!b->pfrb_msize) {
|
||||
if (minsize < 64)
|
||||
minsize = 64;
|
||||
b->pfrb_caddr = calloc(bs, minsize);
|
||||
if (b->pfrb_caddr == NULL)
|
||||
return (-1);
|
||||
b->pfrb_msize = minsize;
|
||||
} else {
|
||||
if (minsize == 0)
|
||||
minsize = b->pfrb_msize * 2;
|
||||
if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
|
||||
/* msize overflow */
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
p = realloc(b->pfrb_caddr, minsize * bs);
|
||||
if (p == NULL)
|
||||
return (-1);
|
||||
bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
|
||||
b->pfrb_caddr = p;
|
||||
b->pfrb_msize = minsize;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* reset buffer and free memory.
|
||||
*/
|
||||
void
|
||||
pfr_buf_clear(struct pfr_buffer *b)
|
||||
{
|
||||
if (b == NULL)
|
||||
return;
|
||||
if (b->pfrb_caddr != NULL)
|
||||
free(b->pfrb_caddr);
|
||||
b->pfrb_caddr = NULL;
|
||||
b->pfrb_size = b->pfrb_msize = 0;
|
||||
}
|
||||
|
||||
int
|
||||
pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
|
||||
int (*append_addr)(struct pfr_buffer *, char *, int))
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[BUF_SIZE];
|
||||
int rv;
|
||||
|
||||
if (file == NULL)
|
||||
return (0);
|
||||
if (!strcmp(file, "-"))
|
||||
fp = stdin;
|
||||
else {
|
||||
fp = pfctl_fopen(file, "r");
|
||||
if (fp == NULL)
|
||||
return (-1);
|
||||
}
|
||||
while ((rv = pfr_next_token(buf, fp)) == 1)
|
||||
if (append_addr(b, buf, nonetwork)) {
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if (fp != stdin)
|
||||
fclose(fp);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_next_token(char buf[BUF_SIZE], FILE *fp)
|
||||
{
|
||||
static char next_ch = ' ';
|
||||
int i = 0;
|
||||
|
||||
for (;;) {
|
||||
/* skip spaces */
|
||||
while (isspace(next_ch) && !feof(fp))
|
||||
next_ch = fgetc(fp);
|
||||
/* remove from '#' until end of line */
|
||||
if (next_ch == '#')
|
||||
while (!feof(fp)) {
|
||||
next_ch = fgetc(fp);
|
||||
if (next_ch == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (feof(fp)) {
|
||||
next_ch = ' ';
|
||||
return (0);
|
||||
}
|
||||
do {
|
||||
if (i < BUF_SIZE)
|
||||
buf[i++] = next_ch;
|
||||
next_ch = fgetc(fp);
|
||||
} while (!feof(fp) && !isspace(next_ch));
|
||||
if (i >= BUF_SIZE) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return (1);
|
||||
}
|
||||
|
||||
char *
|
||||
pfr_strerror(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
case ESRCH:
|
||||
return "Table does not exist";
|
||||
case ENOENT:
|
||||
return "Anchor or Ruleset does not exist";
|
||||
default:
|
||||
return strerror(errnum);
|
||||
}
|
||||
}
|
637
freebsd/contrib/pf/pfctl/pfctl_table.c
Normal file
637
freebsd/contrib/pf/pfctl/pfctl_table.c
Normal file
@ -0,0 +1,637 @@
|
||||
#include <machine/rtems-bsd-user-space.h>
|
||||
|
||||
/* $OpenBSD: pfctl_table.c,v 1.67 2008/06/10 20:55:02 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/bsd/sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "pfctl_parser.h"
|
||||
#include "pfctl.h"
|
||||
|
||||
extern void usage(void);
|
||||
static int pfctl_table(int, char *[], char *, const char *, char *,
|
||||
const char *, int);
|
||||
static void print_table(struct pfr_table *, int, int);
|
||||
static void print_tstats(struct pfr_tstats *, int);
|
||||
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
|
||||
static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
|
||||
static void print_astats(struct pfr_astats *, int);
|
||||
static void radix_perror(void);
|
||||
static void xprintf(int, const char *, ...);
|
||||
static void print_iface(struct pfi_kif *, int);
|
||||
|
||||
static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
|
||||
{ "In/Block:", "In/Pass:", "In/XPass:" },
|
||||
{ "Out/Block:", "Out/Pass:", "Out/XPass:" }
|
||||
};
|
||||
|
||||
static const char *istats_text[2][2][2] = {
|
||||
{ { "In4/Pass:", "In4/Block:" }, { "Out4/Pass:", "Out4/Block:" } },
|
||||
{ { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } }
|
||||
};
|
||||
|
||||
#define RVTEST(fct) do { \
|
||||
if ((!(opts & PF_OPT_NOACTION) || \
|
||||
(opts & PF_OPT_DUMMYACTION)) && \
|
||||
(fct)) { \
|
||||
radix_perror(); \
|
||||
goto _error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CREATE_TABLE do { \
|
||||
table.pfrt_flags |= PFR_TFLAG_PERSIST; \
|
||||
if ((!(opts & PF_OPT_NOACTION) || \
|
||||
(opts & PF_OPT_DUMMYACTION)) && \
|
||||
(pfr_add_tables(&table, 1, &nadd, flags)) && \
|
||||
(errno != EPERM)) { \
|
||||
radix_perror(); \
|
||||
goto _error; \
|
||||
} \
|
||||
if (nadd) { \
|
||||
warn_namespace_collision(table.pfrt_name); \
|
||||
xprintf(opts, "%d table created", nadd); \
|
||||
if (opts & PF_OPT_NOACTION) \
|
||||
return (0); \
|
||||
} \
|
||||
table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
pfctl_clear_tables(const char *anchor, int opts)
|
||||
{
|
||||
return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_show_tables(const char *anchor, int opts)
|
||||
{
|
||||
return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_command_tables(int argc, char *argv[], char *tname,
|
||||
const char *command, char *file, const char *anchor, int opts)
|
||||
{
|
||||
if (tname == NULL || command == NULL)
|
||||
usage();
|
||||
return pfctl_table(argc, argv, tname, command, file, anchor, opts);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_table(int argc, char *argv[], char *tname, const char *command,
|
||||
char *file, const char *anchor, int opts)
|
||||
{
|
||||
struct pfr_table table;
|
||||
struct pfr_buffer b, b2;
|
||||
struct pfr_addr *a, *a2;
|
||||
int nadd = 0, ndel = 0, nchange = 0, nzero = 0;
|
||||
int rv = 0, flags = 0, nmatch = 0;
|
||||
void *p;
|
||||
|
||||
if (command == NULL)
|
||||
usage();
|
||||
if (opts & PF_OPT_NOACTION)
|
||||
flags |= PFR_FLAG_DUMMY;
|
||||
|
||||
bzero(&b, sizeof(b));
|
||||
bzero(&b2, sizeof(b2));
|
||||
bzero(&table, sizeof(table));
|
||||
if (tname != NULL) {
|
||||
if (strlen(tname) >= PF_TABLE_NAME_SIZE)
|
||||
usage();
|
||||
if (strlcpy(table.pfrt_name, tname,
|
||||
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
|
||||
errx(1, "pfctl_table: strlcpy");
|
||||
}
|
||||
if (strlcpy(table.pfrt_anchor, anchor,
|
||||
sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor))
|
||||
errx(1, "pfctl_table: strlcpy");
|
||||
|
||||
if (!strcmp(command, "-F")) {
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
RVTEST(pfr_clr_tables(&table, &ndel, flags));
|
||||
xprintf(opts, "%d tables deleted", ndel);
|
||||
} else if (!strcmp(command, "-s")) {
|
||||
b.pfrb_type = (opts & PF_OPT_VERBOSE2) ?
|
||||
PFRB_TSTATS : PFRB_TABLES;
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (opts & PF_OPT_VERBOSE2)
|
||||
RVTEST(pfr_get_tstats(&table,
|
||||
b.pfrb_caddr, &b.pfrb_size, flags));
|
||||
else
|
||||
RVTEST(pfr_get_tables(&table,
|
||||
b.pfrb_caddr, &b.pfrb_size, flags));
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
|
||||
pfctl_print_title("TABLES:");
|
||||
|
||||
PFRB_FOREACH(p, &b)
|
||||
if (opts & PF_OPT_VERBOSE2)
|
||||
print_tstats(p, opts & PF_OPT_DEBUG);
|
||||
else
|
||||
print_table(p, opts & PF_OPT_VERBOSE,
|
||||
opts & PF_OPT_DEBUG);
|
||||
} else if (!strcmp(command, "kill")) {
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
RVTEST(pfr_del_tables(&table, 1, &ndel, flags));
|
||||
xprintf(opts, "%d table deleted", ndel);
|
||||
} else if (!strcmp(command, "flush")) {
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
RVTEST(pfr_clr_addrs(&table, &ndel, flags));
|
||||
xprintf(opts, "%d addresses deleted", ndel);
|
||||
} else if (!strcmp(command, "add")) {
|
||||
b.pfrb_type = PFRB_ADDRS;
|
||||
if (load_addr(&b, argc, argv, file, 0))
|
||||
goto _error;
|
||||
CREATE_TABLE;
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
flags |= PFR_FLAG_FEEDBACK;
|
||||
RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
||||
&nadd, flags));
|
||||
xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size);
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
PFRB_FOREACH(a, &b)
|
||||
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||
print_addrx(a, NULL,
|
||||
opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "delete")) {
|
||||
b.pfrb_type = PFRB_ADDRS;
|
||||
if (load_addr(&b, argc, argv, file, 0))
|
||||
goto _error;
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
flags |= PFR_FLAG_FEEDBACK;
|
||||
RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
||||
&ndel, flags));
|
||||
xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size);
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
PFRB_FOREACH(a, &b)
|
||||
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||
print_addrx(a, NULL,
|
||||
opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "replace")) {
|
||||
b.pfrb_type = PFRB_ADDRS;
|
||||
if (load_addr(&b, argc, argv, file, 0))
|
||||
goto _error;
|
||||
CREATE_TABLE;
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
flags |= PFR_FLAG_FEEDBACK;
|
||||
for (;;) {
|
||||
int sz2 = b.pfrb_msize;
|
||||
|
||||
RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
||||
&sz2, &nadd, &ndel, &nchange, flags));
|
||||
if (sz2 <= b.pfrb_msize) {
|
||||
b.pfrb_size = sz2;
|
||||
break;
|
||||
} else
|
||||
pfr_buf_grow(&b, sz2);
|
||||
}
|
||||
if (nadd)
|
||||
xprintf(opts, "%d addresses added", nadd);
|
||||
if (ndel)
|
||||
xprintf(opts, "%d addresses deleted", ndel);
|
||||
if (nchange)
|
||||
xprintf(opts, "%d addresses changed", nchange);
|
||||
if (!nadd && !ndel && !nchange)
|
||||
xprintf(opts, "no changes");
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
PFRB_FOREACH(a, &b)
|
||||
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||
print_addrx(a, NULL,
|
||||
opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "expire")) {
|
||||
const char *errstr;
|
||||
u_int lifetime;
|
||||
|
||||
b.pfrb_type = PFRB_ASTATS;
|
||||
b2.pfrb_type = PFRB_ADDRS;
|
||||
if (argc != 1 || file != NULL)
|
||||
usage();
|
||||
lifetime = strtonum(*argv, 0, UINT_MAX, &errstr);
|
||||
if (errstr)
|
||||
errx(1, "expiry time: %s", errstr);
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
|
||||
&b.pfrb_size, flags));
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(p, &b) {
|
||||
((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
|
||||
if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
|
||||
lifetime)
|
||||
if (pfr_buf_add(&b2,
|
||||
&((struct pfr_astats *)p)->pfras_a))
|
||||
err(1, "duplicate buffer");
|
||||
}
|
||||
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
flags |= PFR_FLAG_FEEDBACK;
|
||||
RVTEST(pfr_del_addrs(&table, b2.pfrb_caddr, b2.pfrb_size,
|
||||
&ndel, flags));
|
||||
xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size);
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
PFRB_FOREACH(a, &b2)
|
||||
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
|
||||
print_addrx(a, NULL,
|
||||
opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "show")) {
|
||||
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
|
||||
PFRB_ASTATS : PFRB_ADDRS;
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
|
||||
&b.pfrb_size, flags));
|
||||
else
|
||||
RVTEST(pfr_get_addrs(&table, b.pfrb_caddr,
|
||||
&b.pfrb_size, flags));
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(p, &b)
|
||||
if (opts & PF_OPT_VERBOSE)
|
||||
print_astats(p, opts & PF_OPT_USEDNS);
|
||||
else
|
||||
print_addrx(p, NULL, opts & PF_OPT_USEDNS);
|
||||
} else if (!strcmp(command, "test")) {
|
||||
b.pfrb_type = PFRB_ADDRS;
|
||||
b2.pfrb_type = PFRB_ADDRS;
|
||||
|
||||
if (load_addr(&b, argc, argv, file, 1))
|
||||
goto _error;
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
flags |= PFR_FLAG_REPLACE;
|
||||
PFRB_FOREACH(a, &b)
|
||||
if (pfr_buf_add(&b2, a))
|
||||
err(1, "duplicate buffer");
|
||||
}
|
||||
RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size,
|
||||
&nmatch, flags));
|
||||
xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size);
|
||||
if ((opts & PF_OPT_VERBOSE) && !(opts & PF_OPT_VERBOSE2))
|
||||
PFRB_FOREACH(a, &b)
|
||||
if (a->pfra_fback == PFR_FB_MATCH)
|
||||
print_addrx(a, NULL,
|
||||
opts & PF_OPT_USEDNS);
|
||||
if (opts & PF_OPT_VERBOSE2) {
|
||||
a2 = NULL;
|
||||
PFRB_FOREACH(a, &b) {
|
||||
a2 = pfr_buf_next(&b2, a2);
|
||||
print_addrx(a2, a, opts & PF_OPT_USEDNS);
|
||||
}
|
||||
}
|
||||
if (nmatch < b.pfrb_size)
|
||||
rv = 2;
|
||||
} else if (!strcmp(command, "zero")) {
|
||||
if (argc || file != NULL)
|
||||
usage();
|
||||
flags |= PFR_FLAG_ADDRSTOO;
|
||||
RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags));
|
||||
xprintf(opts, "%d table/stats cleared", nzero);
|
||||
} else
|
||||
warnx("pfctl_table: unknown command '%s'", command);
|
||||
goto _cleanup;
|
||||
|
||||
_error:
|
||||
rv = -1;
|
||||
_cleanup:
|
||||
pfr_buf_clear(&b);
|
||||
pfr_buf_clear(&b2);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
void
|
||||
print_table(struct pfr_table *ta, int verbose, int debug)
|
||||
{
|
||||
if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
|
||||
return;
|
||||
if (verbose) {
|
||||
printf("%c%c%c%c%c%c%c\t%s",
|
||||
(ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
|
||||
(ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
|
||||
ta->pfrt_name);
|
||||
if (ta->pfrt_anchor[0])
|
||||
printf("\t%s", ta->pfrt_anchor);
|
||||
puts("");
|
||||
} else
|
||||
puts(ta->pfrt_name);
|
||||
}
|
||||
|
||||
void
|
||||
print_tstats(struct pfr_tstats *ts, int debug)
|
||||
{
|
||||
time_t time = ts->pfrts_tzero;
|
||||
int dir, op;
|
||||
|
||||
if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE))
|
||||
return;
|
||||
print_table(&ts->pfrts_t, 1, debug);
|
||||
printf("\tAddresses: %d\n", ts->pfrts_cnt);
|
||||
printf("\tCleared: %s", ctime(&time));
|
||||
printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n",
|
||||
ts->pfrts_refcnt[PFR_REFCNT_ANCHOR],
|
||||
ts->pfrts_refcnt[PFR_REFCNT_RULE]);
|
||||
printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n",
|
||||
(unsigned long long)ts->pfrts_nomatch,
|
||||
(unsigned long long)ts->pfrts_match);
|
||||
for (dir = 0; dir < PFR_DIR_MAX; dir++)
|
||||
for (op = 0; op < PFR_OP_TABLE_MAX; op++)
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
stats_text[dir][op],
|
||||
(unsigned long long)ts->pfrts_packets[dir][op],
|
||||
(unsigned long long)ts->pfrts_bytes[dir][op]);
|
||||
}
|
||||
|
||||
int
|
||||
load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file,
|
||||
int nonetwork)
|
||||
{
|
||||
while (argc--)
|
||||
if (append_addr(b, *argv++, nonetwork)) {
|
||||
if (errno)
|
||||
warn("cannot decode %s", argv[-1]);
|
||||
return (-1);
|
||||
}
|
||||
if (pfr_buf_load(b, file, nonetwork, append_addr)) {
|
||||
warn("cannot load %s", file);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
|
||||
{
|
||||
char ch, buf[256] = "{error}";
|
||||
char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' };
|
||||
unsigned int fback, hostnet;
|
||||
|
||||
fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback;
|
||||
ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?';
|
||||
hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32;
|
||||
inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf));
|
||||
printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf);
|
||||
if (ad->pfra_net < hostnet)
|
||||
printf("/%d", ad->pfra_net);
|
||||
if (rad != NULL && fback != PFR_FB_NONE) {
|
||||
if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf))
|
||||
errx(1, "print_addrx: strlcpy");
|
||||
inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf));
|
||||
printf("\t%c%s", (rad->pfra_not?'!':' '), buf);
|
||||
if (rad->pfra_net < hostnet)
|
||||
printf("/%d", rad->pfra_net);
|
||||
}
|
||||
if (rad != NULL && fback == PFR_FB_NONE)
|
||||
printf("\t nomatch");
|
||||
if (dns && ad->pfra_net == hostnet) {
|
||||
char host[NI_MAXHOST];
|
||||
union sockaddr_union sa;
|
||||
|
||||
strlcpy(host, "?", sizeof(host));
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa.sa_family = ad->pfra_af;
|
||||
if (sa.sa.sa_family == AF_INET) {
|
||||
sa.sa.sa_len = sizeof(sa.sin);
|
||||
sa.sin.sin_addr = ad->pfra_ip4addr;
|
||||
} else {
|
||||
sa.sa.sa_len = sizeof(sa.sin6);
|
||||
sa.sin6.sin6_addr = ad->pfra_ip6addr;
|
||||
}
|
||||
if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host),
|
||||
NULL, 0, NI_NAMEREQD) == 0)
|
||||
printf("\t(%s)", host);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
print_astats(struct pfr_astats *as, int dns)
|
||||
{
|
||||
time_t time = as->pfras_tzero;
|
||||
int dir, op;
|
||||
|
||||
print_addrx(&as->pfras_a, NULL, dns);
|
||||
printf("\tCleared: %s", ctime(&time));
|
||||
if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
|
||||
return;
|
||||
for (dir = 0; dir < PFR_DIR_MAX; dir++)
|
||||
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
stats_text[dir][op],
|
||||
(unsigned long long)as->pfras_packets[dir][op],
|
||||
(unsigned long long)as->pfras_bytes[dir][op]);
|
||||
}
|
||||
|
||||
void
|
||||
radix_perror(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno));
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
|
||||
struct pfr_buffer *ab, u_int32_t ticket)
|
||||
{
|
||||
struct pfr_table tbl;
|
||||
|
||||
bzero(&tbl, sizeof(tbl));
|
||||
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
|
||||
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
|
||||
sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
|
||||
errx(1, "pfctl_define_table: strlcpy");
|
||||
tbl.pfrt_flags = flags;
|
||||
|
||||
return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL,
|
||||
NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0);
|
||||
}
|
||||
|
||||
void
|
||||
warn_namespace_collision(const char *filter)
|
||||
{
|
||||
struct pfr_buffer b;
|
||||
struct pfr_table *t;
|
||||
const char *name = NULL, *lastcoll;
|
||||
int coll = 0;
|
||||
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_TABLES;
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfr_get_tables(NULL, b.pfrb_caddr,
|
||||
&b.pfrb_size, PFR_FLAG_ALLRSETS))
|
||||
err(1, "pfr_get_tables");
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
}
|
||||
PFRB_FOREACH(t, &b) {
|
||||
if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE))
|
||||
continue;
|
||||
if (filter != NULL && strcmp(filter, t->pfrt_name))
|
||||
continue;
|
||||
if (!t->pfrt_anchor[0])
|
||||
name = t->pfrt_name;
|
||||
else if (name != NULL && !strcmp(name, t->pfrt_name)) {
|
||||
coll++;
|
||||
lastcoll = name;
|
||||
name = NULL;
|
||||
}
|
||||
}
|
||||
if (coll == 1)
|
||||
warnx("warning: namespace collision with <%s> global table.",
|
||||
lastcoll);
|
||||
else if (coll > 1)
|
||||
warnx("warning: namespace collisions with %d global tables.",
|
||||
coll);
|
||||
pfr_buf_clear(&b);
|
||||
}
|
||||
|
||||
void
|
||||
xprintf(int opts, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (opts & PF_OPT_QUIET)
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (opts & PF_OPT_DUMMYACTION)
|
||||
fprintf(stderr, " (dummy).\n");
|
||||
else if (opts & PF_OPT_NOACTION)
|
||||
fprintf(stderr, " (syntax only).\n");
|
||||
else
|
||||
fprintf(stderr, ".\n");
|
||||
}
|
||||
|
||||
|
||||
/* interface stuff */
|
||||
|
||||
int
|
||||
pfctl_show_ifaces(const char *filter, int opts)
|
||||
{
|
||||
struct pfr_buffer b;
|
||||
struct pfi_kif *p;
|
||||
int i = 0;
|
||||
|
||||
bzero(&b, sizeof(b));
|
||||
b.pfrb_type = PFRB_IFACES;
|
||||
for (;;) {
|
||||
pfr_buf_grow(&b, b.pfrb_size);
|
||||
b.pfrb_size = b.pfrb_msize;
|
||||
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
|
||||
radix_perror();
|
||||
return (1);
|
||||
}
|
||||
if (b.pfrb_size <= b.pfrb_msize)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("INTERFACES:");
|
||||
PFRB_FOREACH(p, &b)
|
||||
print_iface(p, opts);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
print_iface(struct pfi_kif *p, int opts)
|
||||
{
|
||||
time_t tzero = p->pfik_tzero;
|
||||
int i, af, dir, act;
|
||||
|
||||
printf("%s", p->pfik_name);
|
||||
if (opts & PF_OPT_VERBOSE) {
|
||||
if (p->pfik_flags & PFI_IFLAG_SKIP)
|
||||
printf(" (skip)");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (!(opts & PF_OPT_VERBOSE2))
|
||||
return;
|
||||
printf("\tCleared: %s", ctime(&tzero));
|
||||
printf("\tReferences: [ States: %-18d Rules: %-18d ]\n",
|
||||
p->pfik_states, p->pfik_rules);
|
||||
for (i = 0; i < 8; i++) {
|
||||
af = (i>>2) & 1;
|
||||
dir = (i>>1) &1;
|
||||
act = i & 1;
|
||||
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
|
||||
istats_text[af][dir][act],
|
||||
(unsigned long long)p->pfik_packets[af][dir][act],
|
||||
(unsigned long long)p->pfik_bytes[af][dir][act]);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user