From patchwork Sat Mar 8 15:59:47 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ash Hughes X-Patchwork-Id: 328213 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 6494B2C00B0 for ; Sun, 9 Mar 2014 03:05:32 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751440AbaCHQFb (ORCPT ); Sat, 8 Mar 2014 11:05:31 -0500 Received: from know-smtprelay-omc-2.server.virginmedia.net ([80.0.253.66]:56204 "EHLO know-smtprelay-omc-2.server.virginmedia.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751130AbaCHQFa (ORCPT ); Sat, 8 Mar 2014 11:05:30 -0500 X-Greylist: delayed 341 seconds by postgrey-1.27 at vger.kernel.org; Sat, 08 Mar 2014 11:05:29 EST Received: from [192.168.0.20] ([78.86.124.99]) by know-smtprelay-2-imp with bizsmtp id b3zn1n00C28nGvi013znX7; Sat, 08 Mar 2014 15:59:47 +0000 X-Originating-IP: [78.86.124.99] X-Spam: 0 X-Authority: v=2.1 cv=B5U30YdM c=1 sm=1 tr=0 a=RpN67Ftul3/ugb9A7s2Uuw==:117 a=RpN67Ftul3/ugb9A7s2Uuw==:17 a=_KO4s6dtIjIA:10 a=nG-ott2hxY4A:10 a=3NElcqgl2aoA:10 a=8nJEP1OIZ-IA:10 a=a5Gf7U6LAAAA:8 a=gu6fZOg2AAAA:8 a=3HDBlxybAAAA:8 a=8pif782wAAAA:8 a=pGLkceISAAAA:8 a=_DM9lqFHeuM_IdtA4-0A:9 a=_O5jMroA8OIjTr_Y:21 a=pvWTFvrqZC9S0eN3:21 a=wPNLvfGTeEIA:10 a=qmu8fGOOOCMA:10 a=yHIqe9kG5mgA:10 a=MSl-tDqOz04A:10 a=GC8p-B92FUEA:10 a=NWVoK91CQyQA:10 Message-ID: <531B3E73.3080801@blueyonder.co.uk> Date: Sat, 08 Mar 2014 15:59:47 +0000 From: Ash Hughes User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0 MIME-Version: 1.0 To: netfilter-devel@vger.kernel.org Subject: [PATCH] userspace SSDP conntrack helper X-Enigmail-Version: 1.6 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Hi, Here is a patch which adds a userspace conntrack helper for the SSDP protocol. This is based on the code found at: http://marc.info/?t=132945775100001&r=1&w=2 I'm not sure how to get my laptop to play at IPv6, so I've not tested this part, but I've tested the IPv4 section and it works. What more needs to be done to get this merged in? :) To get this to work, I've followed the instructions here: http://conntrack-tools.netfilter.org/manual.html#helpers That is: nfct helper add ssdp inet udp iptables --verbose -I OUTPUT 1 -t raw -p udp --dport 1900 -j CT --helper ssdp And the following in conntrackd.conf: Type ssdp inet udp { # # Set NFQUEUE number you want to use to receive traffic from # the kernel. # QueueNum 0 # # Maximum number of packets waiting in the queue to receive # a verdict from user-space. Default is 1024. # # Rise value if you hit the following error message: # "nf_queue: full at X entries, dropping packets(s)" # QueueLen 10240 # # Set the Expectation policy for this helper. # Policy ssdp { # # Maximum number of simultaneous expectations # ExpectMax 1 # # Maximum living time for one expectation (in seconds). # ExpectTimeout 300 } } Thanks, Ash --- -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index fe28e83..947e58b 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..0011f51 --- /dev/null +++ b/src/helpers/ssdp.c @@ -0,0 +1,135 @@ +/* + * 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 + * Based on the SSDP conntrack helper (nf_conntrack_ssdp.c), + * :http://marc.info/?t=132945775100001&r=1&w=2 + * (C) 2012 Ian Pilcher + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, 0)) { + 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); +} +