summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/helper/conntrackd.conf8
-rw-r--r--doc/manual/conntrack-tools.tmpl1
-rw-r--r--src/helpers/Makefile.am7
-rw-r--r--src/helpers/ssdp.c134
4 files changed, 149 insertions, 1 deletions
diff --git a/doc/helper/conntrackd.conf b/doc/helper/conntrackd.conf
index 358ad10..d2d94a9 100644
--- a/doc/helper/conntrackd.conf
+++ b/doc/helper/conntrackd.conf
@@ -70,6 +70,14 @@ Helper {
ExpectTimeout 300
}
}
+ Type ssdp inet udp {
+ QueueNum 5
+ QueueLen 10240
+ Policy ssdp {
+ ExpectMax 1
+ ExpectTimeout 300
+ }
+ }
}
#
diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl
index f21a4ff..d23dec5 100644
--- a/doc/manual/conntrack-tools.tmpl
+++ b/doc/manual/conntrack-tools.tmpl
@@ -890,6 +890,7 @@ maintainance.</para></listitem>
<listitem><para>Oracle*TNS, to support its special <emphasis>Redirect</emphasis> message.</para></listitem>
<listitem><para>NFSv3, mind that version 4 does not require this helper.</para></listitem>
<listitem><para>FTP (this helper is also available in kernel-space).</para></listitem>
+<listitem><para>SSDP.</para></listitem>
</itemizedlist>
<para>The following steps describe how to enable the RPC portmapper helper for NFSv3 (this is similar for other helpers):</para>
diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am
index fe28e83..78ef7aa 100644
--- a/src/helpers/Makefile.am
+++ b/src/helpers/Makefile.am
@@ -6,7 +6,8 @@ pkglib_LTLIBRARIES = ct_helper_amanda.la \
ct_helper_rpc.la \
ct_helper_tftp.la \
ct_helper_tns.la \
- ct_helper_sane.la
+ ct_helper_sane.la \
+ ct_helper_ssdp.la
ct_helper_amanda_la_SOURCES = amanda.c
ct_helper_amanda_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS)
@@ -35,3 +36,7 @@ ct_helper_tns_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS)
ct_helper_sane_la_SOURCES = sane.c
ct_helper_sane_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS)
ct_helper_sane_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS)
+
+ct_helper_ssdp_la_SOURCES = ssdp.c
+ct_helper_ssdp_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS)
+ct_helper_ssdp_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS)
diff --git a/src/helpers/ssdp.c b/src/helpers/ssdp.c
new file mode 100644
index 0000000..2713f23
--- /dev/null
+++ b/src/helpers/ssdp.c
@@ -0,0 +1,134 @@
+/*
+ * SSDP connection tracking helper
+ * (SSDP = Simple Service Discovery Protocol)
+ * For documentation about SSDP see
+ * http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol
+ *
+ * Copyright (C) 2014 Ashley Hughes <ashley.hughes@blueyonder.co.uk>
+ * Based on the SSDP conntrack helper (nf_conntrack_ssdp.c),
+ * :http://marc.info/?t=132945775100001&r=1&w=2
+ * (C) 2012 Ian Pilcher <arequipeno@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "conntrackd.h"
+#include "helper.h"
+#include "myct.h"
+#include "log.h"
+#include <errno.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <libmnl/libmnl.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+#include <libnetfilter_queue/libnetfilter_queue.h>
+#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
+#include <libnetfilter_queue/pktbuff.h>
+#include <linux/netfilter.h>
+
+#define SSDP_MCAST_ADDR "239.255.255.250"
+#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
+#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
+
+#define SSDP_M_SEARCH "M-SEARCH"
+#define SSDP_M_SEARCH_SIZE (sizeof SSDP_M_SEARCH - 1)
+
+static int ssdp_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
+ struct myct *myct, uint32_t ctinfo)
+{
+ int ret = NF_ACCEPT;
+ union nfct_attr_grp_addr daddr, saddr, taddr;
+ struct iphdr *net_hdr = (struct iphdr *)pktb_network_header(pkt);
+ int good_packet = 0;
+ struct nf_expect *exp;
+ u_int16_t port;
+ unsigned int dataoff;
+ void *sb_ptr;
+
+ cthelper_get_addr_dst(myct->ct, MYCT_DIR_ORIG, &daddr);
+ switch (nfct_get_attr_u8(myct->ct, ATTR_L3PROTO)) {
+ case AF_INET:
+ inet_pton(AF_INET, SSDP_MCAST_ADDR, &(taddr.ip));
+ if (daddr.ip == taddr.ip)
+ good_packet = 1;
+ break;
+ case AF_INET6:
+ inet_pton(AF_INET6, UPNP_MCAST_LL_ADDR, &(taddr.ip6));
+ if (daddr.ip6[0] == taddr.ip6[0] &&
+ daddr.ip6[1] == taddr.ip6[1] &&
+ daddr.ip6[2] == taddr.ip6[2] &&
+ daddr.ip6[3] == taddr.ip6[3]) {
+ good_packet = 1;
+ break;
+ }
+ inet_pton(AF_INET6, UPNP_MCAST_SL_ADDR, &(taddr.ip6));
+ if (daddr.ip6[0] == taddr.ip6[0] &&
+ daddr.ip6[1] == taddr.ip6[1] &&
+ daddr.ip6[2] == taddr.ip6[2] &&
+ daddr.ip6[3] == taddr.ip6[3]) {
+ good_packet = 1;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!good_packet) {
+ pr_debug("ssdp_help: destination address not multicast; ignoring\n");
+ return NF_ACCEPT;
+ }
+
+ /* No data? Ignore */
+ dataoff = net_hdr->ihl*4 + sizeof(struct udphdr);
+ if (dataoff >= pktb_len(pkt)) {
+ pr_debug("ssdp_help: UDP payload too small for M-SEARCH; ignoring\n");
+ return NF_ACCEPT;
+ }
+
+ sb_ptr = pktb_network_header(pkt) + dataoff;
+
+ if (memcmp(sb_ptr, SSDP_M_SEARCH, SSDP_M_SEARCH_SIZE) != 0) {
+ pr_debug("ssdp_help: UDP payload does not begin with 'M-SEARCH'; ignoring\n");
+ return NF_ACCEPT;
+ }
+
+ cthelper_get_addr_src(myct->ct, MYCT_DIR_ORIG, &saddr);
+ cthelper_get_port_src(myct->ct, MYCT_DIR_ORIG, &port);
+
+ exp = nfexp_new();
+ if (exp == NULL)
+ return NF_DROP;
+
+ if (cthelper_expect_init(exp, myct->ct, 0, NULL, &saddr,
+ IPPROTO_UDP, NULL, &port,
+ NF_CT_EXPECT_PERMANENT)) {
+ nfexp_destroy(exp);
+ return NF_DROP;
+ }
+ myct->exp = exp;
+
+ return ret;
+}
+
+static struct ctd_helper ssdp_helper = {
+ .name = "ssdp",
+ .l4proto = IPPROTO_UDP,
+ .priv_data_len = 0,
+ .cb = ssdp_helper_cb,
+ .policy = {
+ [0] = {
+ .name = "ssdp",
+ .expect_max = 1,
+ .expect_timeout = 5 * 60,
+ },
+ },
+};
+
+static void __attribute__ ((constructor)) ssdp_init(void)
+{
+ helper_register(&ssdp_helper);
+}