diff --git a/contrib/tcpdump/print-pflog.c b/contrib/tcpdump/print-pflog.c --- a/contrib/tcpdump/print-pflog.c +++ b/contrib/tcpdump/print-pflog.c @@ -88,10 +88,12 @@ static void pflog_print(netdissect_options *ndo, const struct pfloghdr *hdr) { - uint32_t rulenr, subrulenr; + uint32_t rulenr, subrulenr, ridentifier; rulenr = EXTRACT_32BITS(&hdr->rulenr); subrulenr = EXTRACT_32BITS(&hdr->subrulenr); + ridentifier = EXTRACT_32BITS(&hdr->ridentifier); + if (subrulenr == (uint32_t)-1) ND_PRINT((ndo, "rule %u/", rulenr)); else @@ -102,6 +104,9 @@ if (hdr->uid != UID_MAX) ND_PRINT((ndo, " [uid %u]", (unsigned)hdr->uid)); + if (ridentifier != 0) + ND_PRINT((ndo, " [ridentifier %u]", ridentifier)); + ND_PRINT((ndo, ": %s %s on %s: ", tok2str(pf_actions, "unkn(%u)", hdr->action), tok2str(pf_directions, "unkn(%u)", hdr->dir), diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -81,6 +81,7 @@ struct pf_rule_addr dst; union pf_rule_ptr skip[PF_SKIP_COUNT]; char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; + u_int32_t ridentifier; char ifname[IFNAMSIZ]; char qname[PF_QNAME_SIZE]; char pqname[PF_QNAME_SIZE]; diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -455,6 +455,7 @@ assert(labelcount <= PF_RULE_MAX_LABEL_COUNT); for (size_t i = 0; i < labelcount; i++) strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE); + rule->ridentifier = nvlist_get_number(nvl, "ridentifier"); strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE); @@ -569,6 +570,7 @@ r->label[labelcount]); labelcount++; } + nvlist_add_number(nvlr, "ridentifier", r->ridentifier); nvlist_add_string(nvlr, "ifname", r->ifname); nvlist_add_string(nvlr, "qname", r->qname); diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -236,6 +236,7 @@ struct node_icmp *icmpspec; u_int32_t tos; u_int32_t prob; + u_int32_t ridentifier; struct { int action; struct node_state_opt *options; @@ -263,6 +264,7 @@ static struct antispoof_opts { char *label[PF_RULE_MAX_LABEL_COUNT]; int labelcount; + u_int32_t ridentifier; u_int rtableid; } antispoof_opts; @@ -471,7 +473,7 @@ %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL -%token DNPIPE DNQUEUE +%token DNPIPE DNQUEUE RIDENTIFIER %token LOAD RULESET_OPTIMIZATION PRIO %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY @@ -927,6 +929,7 @@ r.af = $6; r.prob = $9.prob; r.rtableid = $9.rtableid; + r.ridentifier = $9.ridentifier; if ($9.tag) if (strlcpy(r.tagname, $9.tag, @@ -1326,6 +1329,7 @@ r.logif = $2.logif; r.quick = $2.quick; r.af = $4; + r.ridentifier = $5.ridentifier; if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; @@ -1378,6 +1382,7 @@ r.logif = $2.logif; r.quick = $2.quick; r.af = $4; + r.ridentifier = $5.ridentifier; if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; @@ -1440,6 +1445,9 @@ } antispoof_opts.label[antispoof_opts.labelcount++] = $1; } + | RIDENTIFIER number { + antispoof_opts.ridentifier = $2; + } | RTABLE NUMBER { if ($2 < 0 || $2 > rt_tableid_max()) { yyerror("invalid rtable id"); @@ -2155,6 +2163,7 @@ YYERROR; for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) free($9.label[i]); + r.ridentifier = $9.ridentifier; r.flags = $9.flags.b1; r.flagset = $9.flags.b2; if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { @@ -2594,6 +2603,9 @@ filter_opts.keep.action = $1.action; filter_opts.keep.options = $1.options; } + | RIDENTIFIER number { + filter_opts.ridentifier = $2; + } | FRAGMENT { filter_opts.fragment = 1; } @@ -5736,6 +5748,7 @@ { "return-icmp", RETURNICMP}, { "return-icmp6", RETURNICMP6}, { "return-rst", RETURNRST}, + { "ridentifier", RIDENTIFIER}, { "round-robin", ROUNDROBIN}, { "route", ROUTE}, { "route-to", ROUTETO}, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1019,6 +1019,8 @@ i = 0; while (r->label[i][0]) printf(" label \"%s\"", r->label[i++]); + if (r->ridentifier) + printf(" ridentifier %u", r->ridentifier); /* Only dnrpipe as we might do (0, 42) to only queue return traffic. */ if (r->dnrpipe) printf(" %s(%d, %d)", diff --git a/share/man/man4/pflog.4 b/share/man/man4/pflog.4 --- a/share/man/man4/pflog.4 +++ b/share/man/man4/pflog.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 18, 2019 +.Dd October 29, 2021 .Dt PFLOG 4 .Os .Sh NAME @@ -84,6 +84,7 @@ pid_t rule_pid; u_int8_t dir; u_int8_t pad[3]; + u_int32_t ridentifier; }; .Ed .Sh EXAMPLES diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -1896,6 +1896,9 @@ The macro expansion for the .Ar label directive occurs only at configuration file parse time, not during runtime. +.It Ar ridentifier Aq Ar number +Add an identifier (number) to the rule, which can be used to correlate the rule +to pflog entries, even after ruleset updates. .It Xo Ar queue Aq Ar queue .No \*(Ba ( Aq Ar queue , .Aq Ar queue ) @@ -3000,7 +3003,8 @@ "queue" ( string | "(" string [ [ "," ] string ] ")" ) | "rtable" number | "probability" number"%" | "prio" number | "dnpipe" ( number | "(" number "," number ")" ) | - "dnqueue" ( number | "(" number "," number ")" ) + "dnqueue" ( number | "(" number "," number ")" ) | + "ridentifier" number nat-rule = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] [ "on" ifspec ] [ af ] @@ -3024,6 +3028,7 @@ antispoof-rule = "antispoof" [ "log" ] [ "quick" ] "for" ifspec [ af ] [ "label" string ] + [ "ridentifier" number ] table-rule = "table" "\*(Lt" string "\*(Gt" [ tableopts-list ] tableopts-list = tableopts-list tableopts | tableopts diff --git a/sys/net/if_pflog.h b/sys/net/if_pflog.h --- a/sys/net/if_pflog.h +++ b/sys/net/if_pflog.h @@ -50,6 +50,7 @@ pid_t rule_pid; u_int8_t dir; u_int8_t pad[3]; + u_int32_t ridentifier; }; #define PFLOG_HDRLEN sizeof(struct pfloghdr) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -578,6 +578,7 @@ struct pf_rule_addr dst; union pf_krule_ptr skip[PF_SKIP_COUNT]; char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; + uint32_t ridentifier; char ifname[IFNAMSIZ]; char qname[PF_QNAME_SIZE]; char pqname[PF_QNAME_SIZE]; diff --git a/sys/netpfil/ipfw/nat64/nat64clat.c b/sys/netpfil/ipfw/nat64/nat64clat.c --- a/sys/netpfil/ipfw/nat64/nat64clat.c +++ b/sys/netpfil/ipfw/nat64/nat64clat.c @@ -71,7 +71,7 @@ static uint32_t pktid = 0; memset(plog, 0, sizeof(*plog)); - plog->length = PFLOG_REAL_HDRLEN; + plog->length = PFLOG_HDRLEN; plog->af = family; plog->action = PF_NAT; plog->dir = PF_IN; diff --git a/sys/netpfil/ipfw/nat64/nat64lsn.c b/sys/netpfil/ipfw/nat64/nat64lsn.c --- a/sys/netpfil/ipfw/nat64/nat64lsn.c +++ b/sys/netpfil/ipfw/nat64/nat64lsn.c @@ -181,7 +181,7 @@ { memset(plog, 0, sizeof(*plog)); - plog->length = PFLOG_REAL_HDRLEN; + plog->length = PFLOG_HDRLEN; plog->af = family; plog->action = PF_NAT; plog->dir = PF_IN; diff --git a/sys/netpfil/ipfw/nat64/nat64stl.c b/sys/netpfil/ipfw/nat64/nat64stl.c --- a/sys/netpfil/ipfw/nat64/nat64stl.c +++ b/sys/netpfil/ipfw/nat64/nat64stl.c @@ -70,7 +70,7 @@ static uint32_t pktid = 0; memset(plog, 0, sizeof(*plog)); - plog->length = PFLOG_REAL_HDRLEN; + plog->length = PFLOG_HDRLEN; plog->af = family; plog->action = PF_NAT; plog->dir = PF_IN; diff --git a/sys/netpfil/pf/if_pflog.c b/sys/netpfil/pf/if_pflog.c --- a/sys/netpfil/pf/if_pflog.c +++ b/sys/netpfil/pf/if_pflog.c @@ -215,7 +215,7 @@ return (0); bzero(&hdr, sizeof(hdr)); - hdr.length = PFLOG_REAL_HDRLEN; + hdr.length = PFLOG_HDRLEN; hdr.af = af; hdr.action = rm->action; hdr.reason = reason; @@ -231,6 +231,7 @@ strlcpy(hdr.ruleset, ruleset->anchor->name, sizeof(hdr.ruleset)); } + hdr.ridentifier = htonl(rm->ridentifier); /* * XXXGL: we avoid pf_socket_lookup() when we are holding * state lock, since this leads to unsafe LOR. diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c --- a/sys/netpfil/pf/pf_nv.c +++ b/sys/netpfil/pf/pf_nv.c @@ -531,6 +531,7 @@ } } + PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0)); PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname, sizeof(rule->ifname))); PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname))); @@ -696,6 +697,7 @@ nvlist_append_string_array(nvl, "labels", rule->label[i]); } nvlist_add_string(nvl, "label", rule->label[0]); + nvlist_add_number(nvl, "ridentifier", rule->ridentifier); nvlist_add_string(nvl, "ifname", rule->ifname); nvlist_add_string(nvl, "qname", rule->qname); nvlist_add_string(nvl, "pqname", rule->pqname);