From a39bfdf98e1819751e179135063cc982274256ae Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 13 Mar 2008 01:07:35 +0100 Subject: [PATCH] Add xt_ECHO sample target --- extensions/Kbuild | 1 + extensions/libxt_ECHO.c | 34 +++++++++++ extensions/xt_ECHO.c | 130 ++++++++++++++++++++++++++++++++++++++++ mconfig | 1 + 4 files changed, 166 insertions(+) create mode 100644 extensions/libxt_ECHO.c create mode 100644 extensions/xt_ECHO.c diff --git a/extensions/Kbuild b/extensions/Kbuild index 7155e3e..3c25fa2 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -7,6 +7,7 @@ obj-m += compat_xtables.o obj-${build_CHAOS} += xt_CHAOS.o obj-${build_DELUDE} += xt_DELUDE.o +obj-${build_ECHO} += xt_ECHO.o obj-${build_LOGMARK} += xt_LOGMARK.o obj-${build_TARPIT} += xt_TARPIT.o obj-${build_TEE} += xt_TEE.o diff --git a/extensions/libxt_ECHO.c b/extensions/libxt_ECHO.c new file mode 100644 index 0000000..f03df06 --- /dev/null +++ b/extensions/libxt_ECHO.c @@ -0,0 +1,34 @@ +#include +#include +#include + +static void echo_tg_help(void) +{ + printf("ECHO takes no options\n\n"); +} + +static int echo_tg_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + return 0; +} + +static void echo_tg_check(unsigned int flags) +{ +} + +static struct xtables_target echo_tg_reg = { + .version = XTABLES_VERSION, + .name = "ECHO", + .family = AF_UNSPEC, + .size = XT_ALIGN(0), + .userspacesize = XT_ALIGN(0), + .help = echo_tg_help, + .parse = echo_tg_parse, + .final_check = echo_tg_check, +}; + +static void _init(void) +{ + xtables_register_target(&echo_tg_reg); +} diff --git a/extensions/xt_ECHO.c b/extensions/xt_ECHO.c new file mode 100644 index 0000000..f1483f7 --- /dev/null +++ b/extensions/xt_ECHO.c @@ -0,0 +1,130 @@ +/* + * ECHO target (RFC 862) + * Copyright © CC Computer Consultants GmbH, 2008 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 or 3 as published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#ifdef CONFIG_BRIDGE_NETFILTER +# include +#endif +#include +#include "compat_xtables.h" + +static unsigned int echo_tg4(struct sk_buff *oldskb, + const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const struct xt_target *target, const void *targinfo) +{ + const struct udphdr *oldudp; + const struct iphdr *oldip; + struct udphdr *newudp, oldudp_buf; + struct iphdr *newip; + struct sk_buff *newskb; + unsigned int addr_type, data_len; + void *payload; + + /* This allows us to do the copy operation in fewer lines of code. */ + skb_linearize(oldskb); + + oldip = ip_hdr(oldskb); + oldudp = skb_header_pointer(oldskb, ip_hdrlen(oldskb), + sizeof(struct udphdr), &oldudp_buf); + if (oldudp == NULL) + return NF_DROP; + if (ntohs(oldudp->len) <= sizeof(struct udphdr)) + return NF_DROP; + + newskb = alloc_skb(LL_MAX_HEADER + sizeof(struct iphdr) + + ntohs(oldudp->len), GFP_ATOMIC); + if (newskb == NULL) + return NF_DROP; + + skb_reserve(newskb, LL_MAX_HEADER); + skb_reset_network_header(newskb); + newip = (void *)skb_put(newskb, sizeof(struct iphdr)); + newip->version = 4; + newip->ihl = sizeof(struct iphdr) / 4; + newip->tos = oldip->tos; + newip->id = 0; + newip->frag_off = htons(IP_DF); + newip->protocol = oldip->protocol; + newip->check = 0; + newip->saddr = oldip->daddr; + newip->daddr = oldip->saddr; + + newudp = (void *)skb_put(newskb, sizeof(struct udphdr)); + newudp->source = oldudp->dest; + newudp->dest = oldudp->source; + newudp->len = oldudp->len; + newudp->check = 0; + + data_len = htons(oldudp->len) - sizeof(*oldudp); + payload = skb_header_pointer(oldskb, ip_hdrlen(oldskb) + + sizeof(*oldudp), data_len, NULL); + memcpy(skb_put(newskb, data_len), payload, data_len); + + addr_type = RTN_UNSPEC; +#ifdef CONFIG_BRIDGE_NETFILTER + if (hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL && + newskb->nf_bridge->mask & BRNF_BRIDGED)) +#else + if (hooknum != NF_INET_FORWARD) +#endif + addr_type = RTN_LOCAL; + + /* ip_route_me_harder expects skb->dst to be set */ + dst_hold(oldskb->dst); + newskb->dst = oldskb->dst; + + if (ip_route_me_harder(newskb, addr_type) < 0) + goto free_nskb; + + newip->ttl = dst_metric(newskb->dst, RTAX_HOPLIMIT); + newskb->ip_summed = CHECKSUM_NONE; + + /* "Never happens" (?) */ + if (newskb->len > dst_mtu(newskb->dst)) + goto free_nskb; + + nf_ct_attach(newskb, oldskb); + ip_local_out(newskb); + return NF_DROP; + + free_nskb: + kfree_skb(newskb); + return NF_DROP; +} + +static struct xt_target echo_tg_reg __read_mostly = { + .name = "ECHO", + .revision = 0, + .family = AF_INET, + .proto = IPPROTO_UDP, + .table = "filter", + .target = echo_tg4, + .targetsize = XT_ALIGN(0), + .me = THIS_MODULE, +}; + +static int __init echo_tg_init(void) +{ + return xt_register_target(&echo_tg_reg); +} + +static void __exit echo_tg_exit(void) +{ + return xt_unregister_target(&echo_tg_reg); +} + +module_init(echo_tg_init); +module_exit(echo_tg_exit); +MODULE_AUTHOR("Jan Engelhardt "); +MODULE_DESCRIPTION("Xtables: ECHO diagnosis target"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_ECHO"); diff --git a/mconfig b/mconfig index afbe701..d881610 100644 --- a/mconfig +++ b/mconfig @@ -5,6 +5,7 @@ # build_CHAOS=m build_DELUDE=m +build_ECHO= build_LOGMARK=m build_TARPIT=m build_TEE=m