Changeset View
Changeset View
Standalone View
Standalone View
sbin/pfctl/pfctl.c
Show First 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
int pfctl_load_options(struct pfctl *); | int pfctl_load_options(struct pfctl *); | ||||
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); | int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); | ||||
int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); | int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); | ||||
int pfctl_load_debug(struct pfctl *, unsigned int); | int pfctl_load_debug(struct pfctl *, unsigned int); | ||||
int pfctl_load_logif(struct pfctl *, char *); | int pfctl_load_logif(struct pfctl *, char *); | ||||
int pfctl_load_hostid(struct pfctl *, u_int32_t); | int pfctl_load_hostid(struct pfctl *, u_int32_t); | ||||
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, | int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, | ||||
char *); | char *); | ||||
void pfctl_print_rule_counters(struct pf_rule *, int); | void pfctl_print_rule_counters(struct pfctl_rule *, int); | ||||
int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); | int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); | ||||
int pfctl_show_nat(int, int, char *); | int pfctl_show_nat(int, int, char *); | ||||
int pfctl_show_src_nodes(int, int); | int pfctl_show_src_nodes(int, int); | ||||
int pfctl_show_states(int, const char *, int); | int pfctl_show_states(int, const char *, int); | ||||
int pfctl_show_status(int, int); | int pfctl_show_status(int, int); | ||||
int pfctl_show_running(int); | int pfctl_show_running(int); | ||||
int pfctl_show_timeouts(int, int); | int pfctl_show_timeouts(int, int); | ||||
int pfctl_show_limits(int, int); | int pfctl_show_limits(int, int); | ||||
void pfctl_debug(int, u_int32_t, int); | void pfctl_debug(int, u_int32_t, int); | ||||
int pfctl_test_altqsupport(int, int); | int pfctl_test_altqsupport(int, int); | ||||
int pfctl_show_anchors(int, int, char *); | int pfctl_show_anchors(int, int, char *); | ||||
int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); | int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *); | ||||
int pfctl_load_ruleset(struct pfctl *, char *, | int pfctl_load_ruleset(struct pfctl *, char *, | ||||
struct pf_ruleset *, int, int); | struct pfctl_ruleset *, int, int); | ||||
int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); | int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); | ||||
const char *pfctl_lookup_option(char *, const char * const *); | const char *pfctl_lookup_option(char *, const char * const *); | ||||
static struct pf_anchor_global pf_anchors; | static struct pfctl_anchor_global pf_anchors; | ||||
static struct pf_anchor pf_main_anchor; | static struct pfctl_anchor pf_main_anchor; | ||||
static struct pfr_buffer skip_b; | static struct pfr_buffer skip_b; | ||||
static const char *clearopt; | static const char *clearopt; | ||||
static char *rulesopt; | static char *rulesopt; | ||||
static const char *showopt; | static const char *showopt; | ||||
static const char *debugopt; | static const char *debugopt; | ||||
static char *anchoropt; | static char *anchoropt; | ||||
static const char *optiopt = NULL; | static const char *optiopt = NULL; | ||||
▲ Show 20 Lines • Show All 732 Lines • ▼ Show 20 Lines | pfctl_clear_pool(struct pf_pool *pool) | ||||
while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { | while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { | ||||
TAILQ_REMOVE(&pool->list, pa, entries); | TAILQ_REMOVE(&pool->list, pa, entries); | ||||
free(pa); | free(pa); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
pfctl_print_rule_counters(struct pf_rule *rule, int opts) | pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) | ||||
{ | { | ||||
if (opts & PF_OPT_DEBUG) { | if (opts & PF_OPT_DEBUG) { | ||||
const char *t[PF_SKIP_COUNT] = { "i", "d", "f", | const char *t[PF_SKIP_COUNT] = { "i", "d", "f", | ||||
"p", "sa", "sp", "da", "dp" }; | "p", "sa", "sp", "da", "dp" }; | ||||
int i; | int i; | ||||
printf(" [ Skip steps: "); | printf(" [ Skip steps: "); | ||||
for (i = 0; i < PF_SKIP_COUNT; ++i) { | for (i = 0; i < PF_SKIP_COUNT; ++i) { | ||||
Show All 35 Lines | pfctl_print_title(char *title) | ||||
printf("%s\n", title); | printf("%s\n", title); | ||||
} | } | ||||
int | int | ||||
pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, | pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, | ||||
char *anchorname, int depth) | char *anchorname, int depth) | ||||
{ | { | ||||
struct pfioc_rule pr; | struct pfioc_rule pr; | ||||
struct pfctl_rule rule; | |||||
u_int32_t nr, mnr, header = 0; | u_int32_t nr, mnr, header = 0; | ||||
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); | int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); | ||||
int numeric = opts & PF_OPT_NUMERIC; | int numeric = opts & PF_OPT_NUMERIC; | ||||
int len = strlen(path); | int len = strlen(path); | ||||
int brace; | int brace; | ||||
char *p; | char *p; | ||||
if (path[0]) | if (path[0]) | ||||
Show All 24 Lines | pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, | ||||
} | } | ||||
mnr = pr.nr; | mnr = pr.nr; | ||||
if (opts & PF_OPT_CLRRULECTRS) | if (opts & PF_OPT_CLRRULECTRS) | ||||
pr.action = PF_GET_CLR_CNTR; | pr.action = PF_GET_CLR_CNTR; | ||||
for (nr = 0; nr < mnr; ++nr) { | for (nr = 0; nr < mnr; ++nr) { | ||||
pr.nr = nr; | pr.nr = nr; | ||||
if (libpfctl_get_rule(dev, nr, pr.ticket, path, PF_SCRUB, | if (libpfctl_get_rule(dev, nr, pr.ticket, path, PF_SCRUB, | ||||
&pr.rule, pr.anchor_call)) { | &rule, pr.anchor_call)) { | ||||
warn("DIOCGETRULENV"); | warn("DIOCGETRULENV"); | ||||
goto error; | goto error; | ||||
} | } | ||||
if (pfctl_get_pool(dev, &pr.rule.rpool, | if (pfctl_get_pool(dev, &rule.rpool, | ||||
nr, pr.ticket, PF_SCRUB, path) != 0) | nr, pr.ticket, PF_SCRUB, path) != 0) | ||||
goto error; | goto error; | ||||
switch (format) { | switch (format) { | ||||
case PFCTL_SHOW_LABELS: | case PFCTL_SHOW_LABELS: | ||||
break; | break; | ||||
case PFCTL_SHOW_RULES: | case PFCTL_SHOW_RULES: | ||||
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) | if (rule.label[0] && (opts & PF_OPT_SHOWALL)) | ||||
labels = 1; | labels = 1; | ||||
print_rule(&pr.rule, pr.anchor_call, rule_numbers, numeric); | print_rule(&rule, pr.anchor_call, rule_numbers, numeric); | ||||
printf("\n"); | printf("\n"); | ||||
pfctl_print_rule_counters(&pr.rule, opts); | pfctl_print_rule_counters(&rule, opts); | ||||
break; | break; | ||||
case PFCTL_SHOW_NOTHING: | case PFCTL_SHOW_NOTHING: | ||||
break; | break; | ||||
} | } | ||||
pfctl_clear_pool(&pr.rule.rpool); | pfctl_clear_pool(&rule.rpool); | ||||
} | } | ||||
pr.rule.action = PF_PASS; | pr.rule.action = PF_PASS; | ||||
if (ioctl(dev, DIOCGETRULES, &pr)) { | if (ioctl(dev, DIOCGETRULES, &pr)) { | ||||
warn("DIOCGETRULES"); | warn("DIOCGETRULES"); | ||||
goto error; | goto error; | ||||
} | } | ||||
mnr = pr.nr; | mnr = pr.nr; | ||||
for (nr = 0; nr < mnr; ++nr) { | for (nr = 0; nr < mnr; ++nr) { | ||||
pr.nr = nr; | pr.nr = nr; | ||||
if (libpfctl_get_rule(dev, nr, pr.ticket, path, PF_PASS, | if (libpfctl_get_rule(dev, nr, pr.ticket, path, PF_PASS, | ||||
&pr.rule, pr.anchor_call)) { | &rule, pr.anchor_call)) { | ||||
warn("DIOCGETRULE"); | warn("DIOCGETRULE"); | ||||
goto error; | goto error; | ||||
} | } | ||||
if (pfctl_get_pool(dev, &pr.rule.rpool, | if (pfctl_get_pool(dev, &rule.rpool, | ||||
nr, pr.ticket, PF_PASS, path) != 0) | nr, pr.ticket, PF_PASS, path) != 0) | ||||
goto error; | goto error; | ||||
switch (format) { | switch (format) { | ||||
case PFCTL_SHOW_LABELS: | case PFCTL_SHOW_LABELS: | ||||
if (pr.rule.label[0]) { | if (rule.label[0]) { | ||||
printf("%s %llu %llu %llu %llu" | printf("%s %llu %llu %llu %llu" | ||||
" %llu %llu %llu %ju\n", | " %llu %llu %llu %ju\n", | ||||
pr.rule.label, | rule.label, | ||||
(unsigned long long)pr.rule.evaluations, | (unsigned long long)rule.evaluations, | ||||
(unsigned long long)(pr.rule.packets[0] + | (unsigned long long)(rule.packets[0] + | ||||
pr.rule.packets[1]), | rule.packets[1]), | ||||
(unsigned long long)(pr.rule.bytes[0] + | (unsigned long long)(rule.bytes[0] + | ||||
pr.rule.bytes[1]), | rule.bytes[1]), | ||||
(unsigned long long)pr.rule.packets[0], | (unsigned long long)rule.packets[0], | ||||
(unsigned long long)pr.rule.bytes[0], | (unsigned long long)rule.bytes[0], | ||||
(unsigned long long)pr.rule.packets[1], | (unsigned long long)rule.packets[1], | ||||
(unsigned long long)pr.rule.bytes[1], | (unsigned long long)rule.bytes[1], | ||||
(uintmax_t)pr.rule.u_states_tot); | (uintmax_t)rule.u_states_tot); | ||||
} | } | ||||
break; | break; | ||||
case PFCTL_SHOW_RULES: | case PFCTL_SHOW_RULES: | ||||
brace = 0; | brace = 0; | ||||
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) | if (rule.label[0] && (opts & PF_OPT_SHOWALL)) | ||||
labels = 1; | labels = 1; | ||||
INDENT(depth, !(opts & PF_OPT_VERBOSE)); | INDENT(depth, !(opts & PF_OPT_VERBOSE)); | ||||
if (pr.anchor_call[0] && | if (pr.anchor_call[0] && | ||||
((((p = strrchr(pr.anchor_call, '_')) != NULL) && | ((((p = strrchr(pr.anchor_call, '_')) != NULL) && | ||||
((void *)p == (void *)pr.anchor_call || | ((void *)p == (void *)pr.anchor_call || | ||||
*(--p) == '/')) || (opts & PF_OPT_RECURSE))) { | *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { | ||||
brace++; | brace++; | ||||
if ((p = strrchr(pr.anchor_call, '/')) != | if ((p = strrchr(pr.anchor_call, '/')) != | ||||
NULL) | NULL) | ||||
p++; | p++; | ||||
else | else | ||||
p = &pr.anchor_call[0]; | p = &pr.anchor_call[0]; | ||||
} else | } else | ||||
p = &pr.anchor_call[0]; | p = &pr.anchor_call[0]; | ||||
print_rule(&pr.rule, p, rule_numbers, numeric); | print_rule(&rule, p, rule_numbers, numeric); | ||||
if (brace) | if (brace) | ||||
printf(" {\n"); | printf(" {\n"); | ||||
else | else | ||||
printf("\n"); | printf("\n"); | ||||
pfctl_print_rule_counters(&pr.rule, opts); | pfctl_print_rule_counters(&rule, opts); | ||||
if (brace) { | if (brace) { | ||||
pfctl_show_rules(dev, path, opts, format, | pfctl_show_rules(dev, path, opts, format, | ||||
p, depth + 1); | p, depth + 1); | ||||
INDENT(depth, !(opts & PF_OPT_VERBOSE)); | INDENT(depth, !(opts & PF_OPT_VERBOSE)); | ||||
printf("}\n"); | printf("}\n"); | ||||
} | } | ||||
break; | break; | ||||
case PFCTL_SHOW_NOTHING: | case PFCTL_SHOW_NOTHING: | ||||
break; | break; | ||||
} | } | ||||
pfctl_clear_pool(&pr.rule.rpool); | pfctl_clear_pool(&rule.rpool); | ||||
} | } | ||||
path[len] = '\0'; | path[len] = '\0'; | ||||
return (0); | return (0); | ||||
error: | error: | ||||
path[len] = '\0'; | path[len] = '\0'; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
int | int | ||||
pfctl_show_nat(int dev, int opts, char *anchorname) | pfctl_show_nat(int dev, int opts, char *anchorname) | ||||
{ | { | ||||
struct pfioc_rule pr; | struct pfioc_rule pr; | ||||
struct pfctl_rule rule; | |||||
u_int32_t mnr, nr; | u_int32_t mnr, nr; | ||||
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; | static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; | ||||
int i, dotitle = opts & PF_OPT_SHOWALL; | int i, dotitle = opts & PF_OPT_SHOWALL; | ||||
memset(&pr, 0, sizeof(pr)); | memset(&pr, 0, sizeof(pr)); | ||||
memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); | memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); | ||||
for (i = 0; i < 3; i++) { | for (i = 0; i < 3; i++) { | ||||
pr.rule.action = nattype[i]; | pr.rule.action = nattype[i]; | ||||
if (ioctl(dev, DIOCGETRULES, &pr)) { | if (ioctl(dev, DIOCGETRULES, &pr)) { | ||||
warn("DIOCGETRULES"); | warn("DIOCGETRULES"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
mnr = pr.nr; | mnr = pr.nr; | ||||
for (nr = 0; nr < mnr; ++nr) { | for (nr = 0; nr < mnr; ++nr) { | ||||
pr.nr = nr; | pr.nr = nr; | ||||
if (libpfctl_get_rule(dev, nr, pr.ticket, anchorname, | if (libpfctl_get_rule(dev, nr, pr.ticket, anchorname, | ||||
nattype[i], &pr.rule, pr.anchor_call)) { | nattype[i], &rule, pr.anchor_call)) { | ||||
warn("DIOCGETRULE"); | warn("DIOCGETRULE"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (pfctl_get_pool(dev, &pr.rule.rpool, nr, | if (pfctl_get_pool(dev, &rule.rpool, nr, | ||||
pr.ticket, nattype[i], anchorname) != 0) | pr.ticket, nattype[i], anchorname) != 0) | ||||
return (-1); | return (-1); | ||||
if (dotitle) { | if (dotitle) { | ||||
pfctl_print_title("TRANSLATION RULES:"); | pfctl_print_title("TRANSLATION RULES:"); | ||||
dotitle = 0; | dotitle = 0; | ||||
} | } | ||||
print_rule(&pr.rule, pr.anchor_call, | print_rule(&rule, pr.anchor_call, | ||||
opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); | opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); | ||||
printf("\n"); | printf("\n"); | ||||
pfctl_print_rule_counters(&pr.rule, opts); | pfctl_print_rule_counters(&rule, opts); | ||||
pfctl_clear_pool(&pr.rule.rpool); | pfctl_clear_pool(&rule.rpool); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pfctl_show_src_nodes(int dev, int opts) | pfctl_show_src_nodes(int dev, int opts) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | if ((pf->opts & PF_OPT_NOACTION) == 0) { | ||||
if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) | if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) | ||||
err(1, "DIOCADDADDR"); | err(1, "DIOCADDADDR"); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) | pfctl_add_rule(struct pfctl *pf, struct pfctl_rule *r, const char *anchor_call) | ||||
{ | { | ||||
u_int8_t rs_num; | u_int8_t rs_num; | ||||
struct pf_rule *rule; | struct pfctl_rule *rule; | ||||
struct pf_ruleset *rs; | struct pfctl_ruleset *rs; | ||||
char *p; | char *p; | ||||
rs_num = pf_get_ruleset_number(r->action); | rs_num = pf_get_ruleset_number(r->action); | ||||
if (rs_num == PF_RULESET_MAX) | if (rs_num == PF_RULESET_MAX) | ||||
errx(1, "Invalid rule type %d", r->action); | errx(1, "Invalid rule type %d", r->action); | ||||
rs = &pf->anchor->ruleset; | rs = &pf->anchor->ruleset; | ||||
Show All 26 Lines | pfctl_add_rule(struct pfctl *pf, struct pfctl_rule *r, const char *anchor_call) | ||||
TAILQ_INIT(&rule->rpool.list); | TAILQ_INIT(&rule->rpool.list); | ||||
pfctl_move_pool(&r->rpool, &rule->rpool); | pfctl_move_pool(&r->rpool, &rule->rpool); | ||||
TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); | TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) | pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a) | ||||
{ | { | ||||
int osize = pf->trans->pfrb_size; | int osize = pf->trans->pfrb_size; | ||||
if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { | if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { | ||||
if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || | if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || | ||||
pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || | pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || | ||||
pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) | pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) | ||||
return (1); | return (1); | ||||
Show All 13 Lines | if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) | ||||
return (4); | return (4); | ||||
if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) | if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) | ||||
return (5); | return (5); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, | pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, | ||||
int rs_num, int depth) | int rs_num, int depth) | ||||
{ | { | ||||
struct pf_rule *r; | struct pfctl_rule *r; | ||||
int error, len = strlen(path); | int error, len = strlen(path); | ||||
int brace = 0; | int brace = 0; | ||||
pf->anchor = rs->anchor; | pf->anchor = rs->anchor; | ||||
if (path[0]) | if (path[0]) | ||||
snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); | snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); | ||||
else | else | ||||
Show All 40 Lines | |||||
error: | error: | ||||
path[len] = '\0'; | path[len] = '\0'; | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) | pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) | ||||
{ | { | ||||
u_int8_t rs_num = pf_get_ruleset_number(r->action); | u_int8_t rs_num = pf_get_ruleset_number(r->action); | ||||
char *name; | char *name; | ||||
u_int32_t ticket; | u_int32_t ticket; | ||||
char anchor[PF_ANCHOR_NAME_SIZE]; | char anchor[PF_ANCHOR_NAME_SIZE]; | ||||
int len = strlen(path); | int len = strlen(path); | ||||
/* set up anchor before adding to path for anchor_call */ | /* set up anchor before adding to path for anchor_call */ | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | pfctl_rules(int dev, char *filename, int opts, int optimize, | ||||
char *anchorname, struct pfr_buffer *trans) | char *anchorname, struct pfr_buffer *trans) | ||||
{ | { | ||||
#define ERR(x) do { warn(x); goto _error; } while(0) | #define ERR(x) do { warn(x); goto _error; } while(0) | ||||
#define ERRX(x) do { warnx(x); goto _error; } while(0) | #define ERRX(x) do { warnx(x); goto _error; } while(0) | ||||
struct pfr_buffer *t, buf; | struct pfr_buffer *t, buf; | ||||
struct pfioc_altq pa; | struct pfioc_altq pa; | ||||
struct pfctl pf; | struct pfctl pf; | ||||
struct pf_ruleset *rs; | struct pfctl_ruleset *rs; | ||||
struct pfr_table trs; | struct pfr_table trs; | ||||
char *path; | char *path; | ||||
int osize; | int osize; | ||||
RB_INIT(&pf_anchors); | RB_INIT(&pf_anchors); | ||||
memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); | memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); | ||||
pf_init_ruleset(&pf_main_anchor.ruleset); | pf_init_ruleset(&pf_main_anchor.ruleset); | ||||
pf_main_anchor.ruleset.anchor = &pf_main_anchor; | pf_main_anchor.ruleset.anchor = &pf_main_anchor; | ||||
▲ Show 20 Lines • Show All 994 Lines • Show Last 20 Lines |