Skip to content

Commit

Permalink
Add basic RTP support (fix netoptimizer#13)
Browse files Browse the repository at this point in the history
Can be configured with the new --format option:
- auto:  strip RTP if detected (default)
- rtp:   require RTP
- raw:   require no RTP

No padded, extended or mixed RTP support yet.
  • Loading branch information
Tilka committed Jun 10, 2014
1 parent e018690 commit 544bce9
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 25 deletions.
47 changes: 43 additions & 4 deletions iptables-module/libxt_mpeg2ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
drop detection stats can be disabled via inverting the parameter
--drop-detect, eg. "! --drop-detect".
Setting the --format parameter to rtp or raw demands a certain format.
*/
static const struct option mpeg2ts_mt_opts[] = {
{.name = "name", .has_arg = true, .val = 'n'},
{.name = "drop-detect", .has_arg = false, .val = 'd'},
{.name = "match-drop", .has_arg = false, .val = 'm'},
{.name = "max-streams", .has_arg = true, .val = 'x'},
{.name = "format", .has_arg = true, .val = 'f'},
{NULL},
};

Expand All @@ -56,10 +58,11 @@ static void mpeg2ts_mt_help(void)
printf(
"mpeg2ts (MPEG2 Transport Stream) match options:\n"
"VERSION %s\n"
" [--name <name>] Name for proc file /proc/net/xt_mpeg2ts/rule_NAME\n"
" [--match-drop] Match on lost TS frames (default: off)\n"
" [--drop-detect] Detect TS frame loss and store stats (default: ON)\n"
" [--max-streams <num>] Track 'max' number of streams (per rule)\n",
" [--name <name>] Name for proc file /proc/net/xt_mpeg2ts/rule_NAME\n"
" [--match-drop] Match on lost TS frames (default: off)\n"
" [--drop-detect] Detect TS frame loss and store stats (default: ON)\n"
" [--max-streams <num>] Track 'max' number of streams (per rule)\n"
" [--format {auto|rtp|raw} Encapsulation format (default: auto)\n",
version
);
}
Expand All @@ -72,6 +75,9 @@ static void mpeg2ts_mt_init(struct xt_entry_match *match)

/* Match on drops is disabled per default */
/* XT_MPEG2TS_MATCH_DROP */

/* Auto-detect format */
info->flags |= XT_MPEG2TS_FORMAT_AUTO;
}

static int mpeg2ts_mt_parse(int c, char **argv, int invert, unsigned int *flags,
Expand Down Expand Up @@ -156,6 +162,22 @@ static int mpeg2ts_mt_parse(int c, char **argv, int invert, unsigned int *flags,

break;

case 'f': /* --format */
if (*flags & XT_MPEG2TS_FORMAT)
xtables_error(PARAMETER_PROBLEM,
"Can't specify --format option twice");
*flags |= XT_MPEG2TS_FORMAT;

if (strcmp(optarg, "auto") == 0)
info->flags = (info->flags & ~XT_MPEG2TS_FORMAT) | XT_MPEG2TS_FORMAT_AUTO;
else if (strcmp(optarg, "rtp") == 0)
info->flags = (info->flags & ~XT_MPEG2TS_FORMAT) | XT_MPEG2TS_FORMAT_RTP;
else if (strcmp(optarg, "raw") == 0)
info->flags = (info->flags & ~XT_MPEG2TS_FORMAT) | XT_MPEG2TS_FORMAT_RAW;
else
xtables_error(PARAMETER_PROBLEM, "bad --format argument: `%s'", optarg);
break;

default:
return false;
}
Expand All @@ -182,6 +204,15 @@ static void mpeg2ts_mt_print(const void *entry,

if (info->flags & XT_MPEG2TS_MAX_STREAMS)
printf(" max-streams:%u", info->cfg.max);

switch (info->flags & XT_MPEG2TS_FORMAT) {
case XT_MPEG2TS_FORMAT_RTP:
printf(" format:rtp");
break;
case XT_MPEG2TS_FORMAT_RAW:
printf(" format:raw");
break;
}
}

static void mpeg2ts_mt_save(const void *entry,
Expand All @@ -202,6 +233,14 @@ static void mpeg2ts_mt_save(const void *entry,
if (info->flags & XT_MPEG2TS_MAX_STREAMS)
printf(" --max-streams %u", info->cfg.max);

switch (info->flags & XT_MPEG2TS_FORMAT) {
case XT_MPEG2TS_FORMAT_RTP:
printf(" --format rtp");
break;
case XT_MPEG2TS_FORMAT_RAW:
printf(" --format raw");
break;
}
}

static struct xtables_match mpeg2ts_mt_reg = {
Expand Down
57 changes: 38 additions & 19 deletions iptables-module/xt_mpeg2ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,14 @@ is_mpeg2ts_packet(const unsigned char *payload_ptr, uint16_t payload_len)
}


static uint16_t
get_rtp_header_length(const unsigned char *payload_ptr, uint16_t payload_len)
{
/* currently, only non-padded, non-extended, non-mixed RTP is supported */
return *payload_ptr == 0x80 ? 12 : 0;
}


static bool
xt_mpeg2ts_match(const struct sk_buff *skb, struct xt_action_param *par)
{
Expand All @@ -1131,7 +1139,9 @@ xt_mpeg2ts_match(const struct sk_buff *skb, struct xt_action_param *par)
struct udphdr _udph;
__be32 saddr, daddr;
uint16_t ulen;
uint16_t hdr_size;
uint16_t format;
uint16_t udp_hdr_size;
uint16_t rtp_hdr_size;
uint16_t payload_len;
const unsigned char *payload_ptr;

Expand Down Expand Up @@ -1187,18 +1197,18 @@ xt_mpeg2ts_match(const struct sk_buff *skb, struct xt_action_param *par)
ulen = ntohs(uh->len);

/* How much do we need to skip to access payload data */
hdr_size = par->thoff + sizeof(struct udphdr);
payload_ptr = skb_network_header(skb) + hdr_size;
/* payload_ptr = skb->data + hdr_size; */
BUG_ON(payload_ptr != (skb->data + hdr_size));
udp_hdr_size = par->thoff + sizeof(struct udphdr);
payload_ptr = skb_network_header(skb) + udp_hdr_size;
/* payload_ptr = skb->data + udp_hdr_size; */
BUG_ON(payload_ptr != (skb->data + udp_hdr_size));

/* Different ways to determine the payload_len. Think the
* safest is to use the skb->len, as we really cannot trust
* the contents of the packet.
payload_len = ntohs(iph->tot_len)- hdr_size;
payload_len = ntohs(iph->tot_len)- udp_hdr_size;
payload_len = ulen - sizeof(struct udphdr);
*/
payload_len = skb->len - hdr_size;
payload_len = skb->len - udp_hdr_size;

/* Not sure if we need to clone packets
if (skb_shared(skb))
Expand All @@ -1208,23 +1218,32 @@ xt_mpeg2ts_match(const struct sk_buff *skb, struct xt_action_param *par)
msg_dbg(RX_STATUS, "skb(0x%p) NOT cloned", skb);
*/

if (is_mpeg2ts_packet(payload_ptr, payload_len)) {
msg_dbg(PKTDATA, "Jubii - its a MPEG2TS packet");

if (!(info->flags & XT_MPEG2TS_DETECT_DROP)) {
/* ! --drop-detect */
/* Don't perform drop detection, just match mpeg2ts */
res = true;
format = info->flags & XT_MPEG2TS_FORMAT;
if (format == XT_MPEG2TS_FORMAT_AUTO || format == XT_MPEG2TS_FORMAT_RTP) {
rtp_hdr_size = get_rtp_header_length(payload_ptr, payload_len);
if (!rtp_hdr_size) {
if (format == XT_MPEG2TS_FORMAT_RTP)
return false;
} else {
skips = dissect_mpeg2ts(payload_ptr, payload_len,
skb, uh, info);
payload_ptr += rtp_hdr_size;
payload_len -= rtp_hdr_size;
}
} else {
msg_dbg(PKTDATA, "Not a MPEG2 TS packet "
"(pkt from:%pI4 to:%pI4)", &saddr, &daddr);
}
if (!is_mpeg2ts_packet(payload_ptr, payload_len)) {
return false;
}

msg_dbg(PKTDATA, "Jubii - its a MPEG2TS packet");

if (!(info->flags & XT_MPEG2TS_DETECT_DROP)) {
/* ! --drop-detect */
/* Don't perform drop detection, just match mpeg2ts */
res = true;
} else {
skips = dissect_mpeg2ts(payload_ptr, payload_len,
skb, uh, info);
}

if (info->flags & XT_MPEG2TS_MATCH_DROP)
res = !!(skips); /* Convert to a bool */

Expand Down
8 changes: 6 additions & 2 deletions iptables-module/xt_mpeg2ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ enum {
XT_MPEG2TS_MAX_STREAMS = 1 << 1,
XT_MPEG2TS_PARAM_NAME = 1 << 2,
XT_MPEG2TS_MATCH_DROP = 1 << 3,
/*Future:*/
XT_MPEG2TS_RECORD_COUNTERS = 1 << 4,
XT_MPEG2TS_RECORD_COUNTERS = 1 << 4, /* Future */
XT_MPEG2TS_FORMAT = 3 << 5,
XT_MPEG2TS_FORMAT_AUTO = 0 << 5,
XT_MPEG2TS_FORMAT_RTP = 1 << 5,
XT_MPEG2TS_FORMAT_RAW = 2 << 5,
};


/* Details of this hash structure is hidden in kernel space xt_mpeg2ts.c */
struct xt_rule_mpeg2ts_conn_htable;

Expand Down

0 comments on commit 544bce9

Please sign in to comment.