const static int icmp_datalen = 8;
#if ICMP_BANDLIM
-
/* Default values in case CONFIG_ICMP_BANDLIM is not defined in the MASTER file */
#ifndef CONFIG_ICMP_BANDLIM
#if XNU_TARGET_OS_OSX
static int icmplim = CONFIG_ICMP_BANDLIM;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW | CTLFLAG_LOCKED,
&icmplim, 0, "");
-
#else /* ICMP_BANDLIM */
-
static int icmplim = -1;
SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD | CTLFLAG_LOCKED,
&icmplim, 0, "");
-
#endif /* ICMP_BANDLIM */
+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, "");
+
/*
* ICMP broadcast echo sysctl
*/
/*
* badport_bandlim() - check for ICMP bandwidth limit
- *
- * 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
static int lpackets[BANDLIM_MAX + 1];
uint64_t time;
uint64_t secs;
-
+ static boolean_t is_initialized = FALSE;
+ static int icmplim_random;
const char *bandlimittype[] = {
"Limiting icmp unreach response",
"Limiting icmp ping response",
return false;
}
+ if (is_initialized == FALSE) {
+ if (icmplim_random_incr > 0 &&
+ icmplim <= INT32_MAX - (icmplim_random_incr + 1)) {
+ icmplim_random = icmplim + (random() % icmplim_random_incr) + 1;
+ }
+ is_initialized = TRUE;
+ }
+
time = net_uptime();
secs = time - lticks[which];
*/
if (secs > 1) {
- if (lpackets[which] > icmplim) {
+ if (lpackets[which] > icmplim_random) {
printf("%s from %d to %d packets per second\n",
bandlimittype[which],
lpackets[which],
- icmplim
+ icmplim_random
);
}
lticks[which] = time;
/*
* bump packet count
*/
-
- if (++lpackets[which] > icmplim) {
- return true;
+ 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;
+ }
}
return false;
}