-/* XXX This one should go in sys/mbuf.h. It is used to avoid that
- * a firewall-generated packet loops forever through the firewall.
- */
-#ifndef M_SKIP_FIREWALL
-#define M_SKIP_FIREWALL 0x4000
-#endif
-
-#if CONFIG_MACF_NET
-#include <security/mac_framework.h>
-#endif /* MAC_NET */
-
/* Default values in case CONFIG_ICMP_BANDLIM is not defined in the MASTER file */
#ifndef CONFIG_ICMP_BANDLIM
/* Default values in case CONFIG_ICMP_BANDLIM is not defined in the MASTER file */
#ifndef CONFIG_ICMP_BANDLIM
static int icmplim = CONFIG_ICMP_BANDLIM;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW | CTLFLAG_LOCKED,
&icmplim, 0, "");
static int icmplim = CONFIG_ICMP_BANDLIM;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW | CTLFLAG_LOCKED,
&icmplim, 0, "");
static int icmplim = -1;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD | CTLFLAG_LOCKED,
&icmplim, 0, "");
static int icmplim = -1;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD | CTLFLAG_LOCKED,
&icmplim, 0, "");
+static int icmplim_random_incr = CONFIG_ICMP_BANDLIM;
+SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM_INCR, icmplim_random_incr, CTLFLAG_RW | CTLFLAG_LOCKED,
+ &icmplim_random_incr, 0, "");
+
/* Expect 32-bit aligned data pointer on strict-align platforms */
MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(n);
/* Expect 32-bit aligned data pointer on strict-align platforms */
MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(n);
th = (struct tcphdr *)(void *)((caddr_t)oip + oiphlen);
if (th != ((struct tcphdr *)P2ROUNDDOWN(th,
th = (struct tcphdr *)(void *)((caddr_t)oip + oiphlen);
if (th != ((struct tcphdr *)P2ROUNDDOWN(th,
/*
* Further refine the payload length to the space
* remaining in mbuf after including the IP header and ICMP
* header.
*/
/*
* Further refine the payload length to the space
* remaining in mbuf after including the IP header and ICMP
* header.
*/
- icmplen = min(icmplen, M_TRAILINGSPACE(m) -
- sizeof(struct ip) - ICMP_MINLEN);
+ icmplen = min(icmplen, (u_int)M_TRAILINGSPACE(m) -
+ (u_int)(sizeof(struct ip) - ICMP_MINLEN));
m_align(m, ICMP_MINLEN + icmplen);
m->m_len = ICMP_MINLEN + icmplen; /* for ICMP header and data */
icp = mtod(m, struct icmp *);
icmpstat.icps_outhist[type]++;
m_align(m, ICMP_MINLEN + icmplen);
m->m_len = ICMP_MINLEN + icmplen; /* for ICMP header and data */
icp = mtod(m, struct icmp *);
icmpstat.icps_outhist[type]++;
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
m->m_pkthdr.len = m->m_len;
m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
nip = mtod(m, struct ip *);
bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
m->m_pkthdr.len = m->m_len;
m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
nip = mtod(m, struct ip *);
bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
icp->icmp_rtime = iptime();
icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
#if ICMP_BANDLIM
icp->icmp_rtime = iptime();
icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
#if ICMP_BANDLIM
- *
- * Return 0 if it is ok to send an ICMP error response, -1 if we have
- * hit our bandwidth limit and it is not ok.
- *
- * If icmplim is <= 0, the feature is disabled and 0 is returned.
+ * Returns false when it is ok to send ICMP error and true to limit sending
+ * of ICMP error.
*
* For now we separate the TCP and UDP subsystems w/ different 'which'
* values. We may eventually remove this separation (and simplify the
*
* For now we separate the TCP and UDP subsystems w/ different 'which'
* values. We may eventually remove this separation (and simplify the
badport_bandlim(int which)
{
static uint64_t lticks[BANDLIM_MAX + 1];
static int lpackets[BANDLIM_MAX + 1];
badport_bandlim(int which)
{
static uint64_t lticks[BANDLIM_MAX + 1];
static int lpackets[BANDLIM_MAX + 1];
const char *bandlimittype[] = {
"Limiting icmp unreach response",
"Limiting icmp ping response",
const char *bandlimittype[] = {
"Limiting icmp unreach response",
"Limiting icmp ping response",
-
- if (++lpackets[which] > icmplim) {
- return -1;
+ if (++lpackets[which] > icmplim_random) {
+ /*
+ * After hitting the randomized limit, we further randomize the
+ * behavior of how we apply rate limitation.
+ * We rate limit based on probability that increases with the
+ * increase in lpackets[which] count.
+ */
+ if ((random() % (lpackets[which] - icmplim_random)) != 0) {
+ return true;
+ }
inp = (struct inpcb *)so->so_pcb;
inp->inp_vflag |= INP_IPV4;
inp->inp_ip_p = IPPROTO_ICMP;
inp = (struct inpcb *)so->so_pcb;
inp->inp_vflag |= INP_IPV4;
inp->inp_ip_p = IPPROTO_ICMP;