diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -708,6 +708,7 @@ 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 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -137,7 +137,6 @@ 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 @@ * 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 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3056,6 +3056,22 @@ 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) @@ -3064,6 +3080,16 @@ 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)