<p>Kevin Harwell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15592">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_rtp_asterisk: Add a DEVMODE RTP drop packets CLI command<br><br>This patch makes it so when Asterisk is compiled in DEVMODE a CLI<br>command is available that allows someone to drop incoming RTP<br>packets. The command allows for dropping of packets once, or on a<br>timed interval (e.g. drop 10 packets every 5 seconds). A user can<br>also specify to drop packets by IP address.<br><br>Change-Id: I25fa7ae9bad6ed68e273bbcccf0ee51cae6e7024<br>---<br>M res/res_rtp_asterisk.c<br>1 file changed, 171 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/15592/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c</span><br><span>index a962d70..8d89a53 100644</span><br><span>--- a/res/res_rtp_asterisk.c</span><br><span>+++ b/res/res_rtp_asterisk.c</span><br><span>@@ -63,6 +63,7 @@</span><br><span> #include <ifaddrs.h></span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/conversions.h"</span><br><span> #include "asterisk/options.h"</span><br><span> #include "asterisk/logger_category.h"</span><br><span> #include "asterisk/stun.h"</span><br><span>@@ -7489,6 +7490,55 @@</span><br><span>    return AST_LIST_FIRST(&frames);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef AST_DEVMODE</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct rtp_drop_packets_data {</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int num_to_drop;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int num_dropped;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct timeval interval;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct timeval next;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_sockaddr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int port;</span><br><span style="color: hsl(120, 100%, 40%);">+} drop_packets_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int should_drop_packets(struct ast_sockaddr *addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct timeval tv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!drop_packets_data.num_to_drop) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ast_sockaddr_isnull(&drop_packets_data.addr) &&</span><br><span style="color: hsl(120, 100%, 40%);">+              (drop_packets_data.port ?</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_sockaddr_cmp(&drop_packets_data.addr, addr) :</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_sockaddr_cmp_addr(&drop_packets_data.addr, addr)) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (drop_packets_data.num_dropped < drop_packets_data.num_to_drop) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ++drop_packets_data.num_dropped;</span><br><span style="color: hsl(120, 100%, 40%);">+              return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_tvzero(drop_packets_data.interval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* If no interval then drop specified number of packets and be done */</span><br><span style="color: hsl(120, 100%, 40%);">+                drop_packets_data.num_to_drop = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   tv = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_tvcmp(tv, drop_packets_data.next) == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   drop_packets_data.num_dropped = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    drop_packets_data.next = ast_tvadd(tv, drop_packets_data.interval);</span><br><span style="color: hsl(120, 100%, 40%);">+   return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \pre instance is locked */</span><br><span> static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)</span><br><span> {</span><br><span>@@ -7783,6 +7833,14 @@</span><br><span>       seqno &= 0xffff;</span><br><span>         timestamp = ntohl(rtpheader[1]);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef AST_DEVMODE</span><br><span style="color: hsl(120, 100%, 40%);">+      if (should_drop_packets(&addr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_debug(0, "(%p) RTP: drop received packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   instance, ast_sockaddr_stringify(&addr), payloadtype, seqno, timestamp, res - hdrlen);</span><br><span style="color: hsl(120, 100%, 40%);">+            return &ast_null_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (rtp_debug_test_addr(&addr)) {</span><br><span>                ast_verbose("Got  RTP packet from    %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",</span><br><span>                           ast_sockaddr_stringify(&addr),</span><br><span>@@ -9070,11 +9128,124 @@</span><br><span>    return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef AST_DEVMODE</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *handle_cli_rtp_drop_packets(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     static const char * const completions_2[] = { "stop", "<N>", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+        static const char * const completions_3[] = { "incoming packets", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+   static const char * const completions_5[] = { "every", "on", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+      static const char * const completions_units[] = { "usec", "msec", "sec", "min", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int num_to_drop = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int interval = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *interval_s = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *unit_s = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_sockaddr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *addr_s = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+                e->command = "rtp drop";</span><br><span style="color: hsl(120, 100%, 40%);">+         e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Usage: rtp drop [stop|[<N> incoming packets[ every <N> {usec|msec|sec|min}]][ on <ip[:port]>]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                 "       Drop RTP packets.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (a->pos) {</span><br><span style="color: hsl(120, 100%, 40%);">+          case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+                       return ast_cli_complete(a->word, completions_2, a->n);</span><br><span style="color: hsl(120, 100%, 40%);">+          case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+                       return ast_cli_complete(a->word, completions_3, a->n);</span><br><span style="color: hsl(120, 100%, 40%);">+          case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+                       return ast_cli_complete(a->word, completions_5, a->n);</span><br><span style="color: hsl(120, 100%, 40%);">+          case 7:</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (!strcasecmp(a->argv[a->pos - 2], "on")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_cli_completion_add(ast_strdup("every"));</span><br><span style="color: hsl(120, 100%, 40%);">+                                break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             case 9:</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (!strcasecmp(a->argv[a->pos - 2], "every")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              return ast_cli_complete(a->word, completions_units, a->n);</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (strcasecmp(a->argv[a->pos - 1], "every")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ast_cli_completion_add(ast_strdup("on"));</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (a->argc < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!strcasecmp(a->argv[2], "stop")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /* rtp drop stop */</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (a->argc < 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_str_to_uint(a->argv[2], &num_to_drop)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, "%s is not a valid number of packets to drop\n", a->argv[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+          return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (a->argc == 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* rtp drop <N> incoming packets */</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (a->argc >= 7 && !strcasecmp(a->argv[5], "on")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* rtp drop <N> incoming packets on <ip[:port]> */</span><br><span style="color: hsl(120, 100%, 40%);">+                addr_s = a->argv[6];</span><br><span style="color: hsl(120, 100%, 40%);">+               if (a->argc == 10 && !strcasecmp(a->argv[7], "every")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* rtp drop <N> incoming packets on <ip[:port]> every <N> {usec|msec|sec|min}*/</span><br><span style="color: hsl(120, 100%, 40%);">+                     interval_s = a->argv[8];</span><br><span style="color: hsl(120, 100%, 40%);">+                   unit_s = a->argv[9];</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (a->argc >= 8 && !strcasecmp(a->argv[5], "every")) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* rtp drop <N> incoming packets every <N> {usec|msec|sec|min}*/</span><br><span style="color: hsl(120, 100%, 40%);">+          interval_s = a->argv[6];</span><br><span style="color: hsl(120, 100%, 40%);">+           unit_s = a->argv[7];</span><br><span style="color: hsl(120, 100%, 40%);">+               if (a->argc == 10 && !strcasecmp(a->argv[8], "on")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* rtp drop <N> incoming packets every <N> {usec|msec|sec|min} on <ip[:port]>*/</span><br><span style="color: hsl(120, 100%, 40%);">+                     addr_s = a->argv[9];</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (a->argc == 8 || a->argc == 9 || (a->argc >= 10 && (!interval_s || !addr_s))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (interval_s && ast_str_to_uint(interval_s, &interval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_cli(a->fd, "%s is not a valid interval number\n", interval_s);</span><br><span style="color: hsl(120, 100%, 40%);">+               return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&addr, 0, sizeof(addr));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (addr_s && !ast_sockaddr_parse(&addr, addr_s, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_cli(a->fd, "%s is not a valid hostname[:port]\n", addr_s);</span><br><span style="color: hsl(120, 100%, 40%);">+           return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   drop_packets_data.num_to_drop = num_to_drop;</span><br><span style="color: hsl(120, 100%, 40%);">+  drop_packets_data.num_dropped = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    drop_packets_data.interval = ast_time_create_by_unit_str(interval, unit_s);</span><br><span style="color: hsl(120, 100%, 40%);">+   drop_packets_data.next = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sockaddr_copy(&drop_packets_data.addr, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+    drop_packets_data.port = ast_sockaddr_port(&addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_cli_entry cli_rtp[] = {</span><br><span>        AST_CLI_DEFINE(handle_cli_rtp_set_debug,  "Enable/Disable RTP debugging"),</span><br><span>         AST_CLI_DEFINE(handle_cli_rtp_settings,   "Display RTP settings"),</span><br><span>         AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),</span><br><span>        AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef AST_DEVMODE</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(handle_cli_rtp_drop_packets, "Drop RTP packets"),</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> };</span><br><span> </span><br><span> static int rtp_reload(int reload, int by_external_config)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15592">change 15592</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/15592"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I25fa7ae9bad6ed68e273bbcccf0ee51cae6e7024 </div>
<div style="display:none"> Gerrit-Change-Number: 15592 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>