git: a974702e274c - main - pf: apply the network stack's ICMP rate limiting to ICMP errors sent by pf

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Fri, 14 Oct 2022 09:25:19 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=a974702e274cbed52ae9ad9ecef8501e267b822d

commit a974702e274cbed52ae9ad9ecef8501e267b822d
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-10-07 14:22:57 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-10-14 08:36:16 +0000

    pf: apply the network stack's ICMP rate limiting to ICMP errors sent by pf
    
    PR:             266477
    Event:          Aberdeen Hackathon 2022
    Differential Revision:  https://reviews.freebsd.org/D36903
---
 sys/netinet/icmp6.h  |  1 +
 sys/netinet6/icmp6.c |  3 +--
 sys/netpfil/pf/pf.c  | 26 ++++++++++++++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 7429b8173b6a..45a8b8ec0ce8 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -708,6 +708,7 @@ int	icmp6_input(struct mbuf **, int *, int);
 void	icmp6_prepare(struct mbuf *);
 void	icmp6_redirect_input(struct mbuf *, int);
 void	icmp6_redirect_output(struct mbuf *, struct nhop_object *);
+int	icmp6_ratelimit(const struct in6_addr *, const int, const int);
 
 struct	ip6ctlparam;
 void	icmp6_mtudisc_update(struct ip6ctlparam *, int);
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 4497041f0330..2cd54abbb76e 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -137,7 +137,6 @@ VNET_DECLARE(int, icmp6_nodeinfo);
 static void icmp6_errcount(int, int);
 static int icmp6_rip6_input(struct mbuf **, int);
 static void icmp6_reflect(struct mbuf *, size_t);
-static int icmp6_ratelimit(const struct in6_addr *, const int, const int);
 static const char *icmp6_redirect_diag(struct in6_addr *,
 	struct in6_addr *, struct in6_addr *);
 static struct mbuf *ni6_input(struct mbuf *, int, struct prison *);
@@ -2727,7 +2726,7 @@ icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
  * type - not used at this moment
  * code - not used at this moment
  */
-static int
+int
 icmp6_ratelimit(const struct in6_addr *dst, const int type,
     const int code)
 {
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 2a6efbfe6e7d..d0139dc6bd15 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -3048,6 +3048,22 @@ pf_match_ieee8021q_pcp(u_int8_t prio, struct mbuf *m)
 	return (mpcp == prio);
 }
 
+static int
+pf_icmp_to_bandlim(uint8_t type)
+{
+	switch (type) {
+		case ICMP_ECHO:
+		case ICMP_ECHOREPLY:
+			return (BANDLIM_ICMP_ECHO);
+		case ICMP_TSTAMP:
+		case ICMP_TSTAMPREPLY:
+			return (BANDLIM_ICMP_TSTAMP);
+		case ICMP_UNREACH:
+		default:
+			return (BANDLIM_ICMP_UNREACH);
+	}
+}
+
 static void
 pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
     struct pf_krule *r)
@@ -3056,6 +3072,16 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
 	struct mbuf *m0;
 	struct pf_mtag *pf_mtag;
 
+	/* ICMP packet rate limitation. */
+	if (af == AF_INET6) {
+		if (icmp6_ratelimit(NULL, type, code))
+			return;
+	} else {
+		MPASS(af == AF_INET);
+		if (badport_bandlim(pf_icmp_to_bandlim(type)) != 0)
+			return;
+	}
+
 	/* Allocate outgoing queue entry, mbuf and mbuf tag. */
 	pfse = malloc(sizeof(*pfse), M_PFTEMP, M_NOWAIT);
 	if (pfse == NULL)