From 1129129c4827ae5a00a24ccf8c520b81c731fe88 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 14 Dec 2011 12:42:06 +0000 Subject: [PATCH] yup, and this adds support for sending ipv6 packets --- kernel-module/xt_MEDIAPROXY.c | 88 +++++++++++++++++++++++++++++------ tests/kernel-module-test.pl | 6 ++- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/kernel-module/xt_MEDIAPROXY.c b/kernel-module/xt_MEDIAPROXY.c index ace55ba8b..acf082fec 100644 --- a/kernel-module/xt_MEDIAPROXY.c +++ b/kernel-module/xt_MEDIAPROXY.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include "xt_MEDIAPROXY.h" @@ -150,7 +152,7 @@ static struct seq_operations proc_main_list_seq_ops = { static struct mediaproxy_table *new_table(void) { struct mediaproxy_table *t; - DBG(KERN_DEBUG "Creating new table\n"); + DBG("Creating new table\n"); if (!try_module_get(THIS_MODULE)) return NULL; @@ -269,7 +271,7 @@ static void target_push(struct mediaproxy_target *t) { if (!atomic_dec_and_test(&t->refcnt)) return; - DBG(KERN_DEBUG "Freeing target\n"); + DBG("Freeing target\n"); kfree(t); } @@ -309,7 +311,7 @@ static void table_push(struct mediaproxy_table *t) { if (!atomic_dec_and_test(&t->refcnt)) return; - DBG(KERN_DEBUG "Freeing table\n"); + DBG("Freeing table\n"); for (i = 0; i < 256; i++) { if (!t->target[i]) @@ -347,7 +349,7 @@ static int unlink_table(struct mediaproxy_table *t) { if (t->id >= MAX_ID) return -EINVAL; - DBG(KERN_DEBUG "Unlinking table %u\n", t->id); + DBG("Unlinking table %u\n", t->id); write_lock_irqsave(&table_lock, flags); if (t->id >= MAX_ID || table[t->id] != t) { @@ -737,7 +739,7 @@ static int table_new_target(struct mediaproxy_table *t, struct mediaproxy_target return -EINVAL; } - DBG(KERN_DEBUG "Creating new target\n"); + DBG("Creating new target\n"); err = -ENOMEM; g = kmalloc(sizeof(*g), GFP_KERNEL); @@ -970,7 +972,7 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz switch (msg.cmd) { case MMG_NOOP: - DBG(KERN_DEBUG "noop.\n"); + DBG("noop.\n"); break; case MMG_ADD: @@ -1022,7 +1024,7 @@ static int send_proxy_packet4(struct sk_buff *skb, struct mp_address *src, struc ih = (void *) skb_push(skb, sizeof(*ih)); skb_reset_network_header(skb); - DBG(KERN_DEBUG "datalen=%u network_header=%p transport_header=%p\n", datalen, skb_network_header(skb), skb_transport_header(skb)); + DBG("datalen=%u network_header=%p transport_header=%p\n", datalen, skb_network_header(skb), skb_transport_header(skb)); datalen += sizeof(*uh); *uh = (struct udphdr) { @@ -1031,8 +1033,8 @@ static int send_proxy_packet4(struct sk_buff *skb, struct mp_address *src, struc .len = htons(datalen), }; *ih = (struct iphdr) { - .ihl = 5, .version = 4, + .ihl = 5, .tos = tos, .tot_len = htons(sizeof(*ih) + datalen), .ttl = 64, @@ -1066,6 +1068,60 @@ drop: +static int send_proxy_packet6(struct sk_buff *skb, struct mp_address *src, struct mp_address *dst, unsigned char tos) { + struct ipv6hdr *ih; + struct udphdr *uh; + unsigned int datalen; + + datalen = skb->len; + + uh = (void *) skb_push(skb, sizeof(*uh)); + skb_reset_transport_header(skb); + ih = (void *) skb_push(skb, sizeof(*ih)); + skb_reset_network_header(skb); + + DBG("datalen=%u network_header=%p transport_header=%p\n", datalen, skb_network_header(skb), skb_transport_header(skb)); + + datalen += sizeof(*uh); + *uh = (struct udphdr) { + .source = htons(src->port), + .dest = htons(dst->port), + .len = htons(datalen), + }; + *ih = (struct ipv6hdr) { + .version = 6, + .priority = tos, + .payload_len = htons(datalen), + .nexthdr = IPPROTO_UDP, + .hop_limit = 64, + }; + memcpy(&ih->saddr, src->ipv6, sizeof(ih->saddr)); + memcpy(&ih->daddr, dst->ipv6, sizeof(ih->daddr)); + + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); + uh->check = csum_ipv6_magic(&ih->saddr, &ih->daddr, datalen, IPPROTO_UDP, csum_partial(uh, datalen, 0)); + if (uh->check == 0) + uh->check = CSUM_MANGLED_0; + + skb->protocol = htons(ETH_P_IPV6); + if (ip6_route_me_harder(skb)) + goto drop; + + skb->ip_summed = CHECKSUM_NONE; + + ip6_local_out(skb); + + return 0; + +drop: + kfree_skb(skb); + return -1; +} + + + + static int send_proxy_packet(struct sk_buff *skb, struct mp_address *src, struct mp_address *dst, unsigned char tos) { if (src->family != dst->family) goto drop; @@ -1075,6 +1131,10 @@ static int send_proxy_packet(struct sk_buff *skb, struct mp_address *src, struct return send_proxy_packet4(skb, src, dst, tos); break; + case AF_INET6: + return send_proxy_packet6(skb, src, dst, tos); + break; + default: goto drop; } @@ -1127,17 +1187,17 @@ static unsigned int mediaproxy4(struct sk_buff *oskb, const struct xt_action_par if (datalen < sizeof(*uh)) goto skip2; datalen -= sizeof(*uh); - DBG(KERN_DEBUG "udp payload = %u\n", datalen); + DBG("udp payload = %u\n", datalen); skb_trim(skb, datalen); g = get_target(t, ntohs(uh->dest)); if (!g) goto skip2; - DBG(KERN_DEBUG "target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); + DBG("target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); if (g->target.mirror_addr.family) { - DBG(KERN_DEBUG "sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); + DBG("sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); skb2 = skb_copy(skb, GFP_ATOMIC); err = send_proxy_packet(skb2, &g->target.src_addr, &g->target.mirror_addr, g->target.tos); if (err) { @@ -1212,17 +1272,17 @@ static unsigned int mediaproxy6(struct sk_buff *oskb, const struct xt_action_par if (datalen < sizeof(*uh)) goto skip2; datalen -= sizeof(*uh); - DBG(KERN_DEBUG "udp payload = %u\n", datalen); + DBG("udp payload = %u\n", datalen); skb_trim(skb, datalen); g = get_target(t, ntohs(uh->dest)); if (!g) goto skip2; - DBG(KERN_DEBUG "target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); + DBG("target found, src "MIPF" -> dst "MIPF"\n", MIPP(g->target.src_addr), MIPP(g->target.dst_addr)); if (is_valid_address(&g->target.mirror_addr)) { - DBG(KERN_DEBUG "sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); + DBG("sending mirror packet to dst "MIPF"\n", MIPP(g->target.mirror_addr)); skb2 = skb_copy(skb, GFP_ATOMIC); err = send_proxy_packet(skb2, &g->target.src_addr, &g->target.mirror_addr, g->target.tos); if (err) { diff --git a/tests/kernel-module-test.pl b/tests/kernel-module-test.pl index 419e91160..1ba61a960 100755 --- a/tests/kernel-module-test.pl +++ b/tests/kernel-module-test.pl @@ -47,8 +47,10 @@ sub mediaproxy_message { } my $sleep = 5; -my @src = qw(inet 192.168.1.166); -my @dst = qw(inet 192.168.1.135); +#my @src = qw(inet 10.15.20.61); +#my @dst = qw(inet 10.15.20.58); +my @src = qw(inet6 2a00:4600:1:0:a00:27ff:feb0:f7fe); +my @dst = qw(inet6 2a00:4600:1:0:6884:adff:fe98:6ac5); my @nul = ('', '', ''); print("add 9876 -> 1234/6543\n");