]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/ip_icmp.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / netinet / ip_icmp.c
index 14aa9c9603881d7397a786546706defab832a727..0fb3d6f75d6daf58a66f945d4ee3abe6111d9384 100644 (file)
@@ -141,7 +141,6 @@ SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect,
 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
@@ -159,15 +158,16 @@ const static int icmp_datalen = 8;
 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
  */
@@ -1074,11 +1074,8 @@ ip_next_mtu(int mtu, int dir)
 
 /*
  * 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
@@ -1098,7 +1095,8 @@ badport_bandlim(int which)
        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",
@@ -1113,6 +1111,14 @@ badport_bandlim(int which)
                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];
 
@@ -1121,11 +1127,11 @@ badport_bandlim(int 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;
@@ -1135,9 +1141,16 @@ badport_bandlim(int which)
        /*
         * 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;
 }