Commit 64304658 authored by Lionel Gauthier's avatar Lionel Gauthier

Initial release to be continued (echo, frag reassembly, etc)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6052 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent a11d605f
This diff is collapsed.
How to build
------------
1. Extract the files in a location of your choice. The
Files will be extracted in a directory called gtpu.
2. cd <gtpu_dir>/gtpu.
3. make
If make is successful, the binary files (libxt_GTPU.so and xt_GTPU.ko)
will be created in the Bin folder.
How to install
--------------
There is no "make install" as that will be difficult to support all
possible Linux distro. The cmd.sh file demonstrates how to install
the two binary files in the system.
In case of problem:
- check you got the last release of the library (see README),
- contact the mailing list (see README),
- check the bugtracker for known bugs (see README).
Documentation
-------------
Please have a look at the "Architecture" section in the README.
####################################################################################
# Makefile for iptables extension for the GTPUAH target and GTPUAH klm
#
# Copyright (c) 2010-2011 Polaris Networks
# Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
#
# 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.
#
####################################################################################
export BIN_DIR ?= $(shell pwd)/Bin
KVERSION = $(shell uname -r)
KVERSION_LAST_DIGIT = $(shell echo ${KVERSION} | cut -d "." -f 3 | cut -d "-" -f 1)
obj-m = xt_GTPUAH.o
EXTRA_CFLAGS += -DKVERSION=$(KVERSION_LAST_DIGIT)
all: xtlib
echo "Building for Kernel Version: $(KVERSION_LAST_DIGIT)"
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
mv xt_GTPUAH.ko $(BIN_DIR)/
clean: libclean
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
################################################################################
# The next section is used by libxt_GTPUAH
################################################################################
XT_IPTABLES_VERSION = $(shell /sbin/iptables -V | cut -d " " -f 2 | cut -b 2-)
IPT_FIRST_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 1 | cut -d "-" -f 1)
IPT_SECOND_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 2 | cut -d "-" -f 1)
IPT_THIRD_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 3 | cut -d "-" -f 1)
IPTVERSION = $(IPT_FIRST_NUM)$(IPT_SECOND_NUM)$(IPT_THIRD_NUM)
IPTABLES_VERSION_STRING = \"$(IPT_FIRST_NUM).$(IPT_SECOND_NUM).$(IPT_THIRD_NUM)\"
LIB_CC := gcc
ifeq ($(IPTVERSION), 135)
LIB_LD := ld
else
LIB_LD := gcc
endif
LIB_CFLAGS := -fPIC -Wall -MMD -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 \
-D_REENTRANT -pipe -DXTABLES_LIBDIR=\"/usr/local/libexec/xtables\" -DXTABLES_INTERNAL \
-D_INIT=libxt_GTPUAH_init -DPIC -fPIC -O2 \
-DIPTVERSION=$(IPTVERSION) \
-DIPTABLES_VERSION_STRING=$(IPTABLES_VERSION_STRING)
XT_TARGET := xt_GTPUAH
XT_LIBNAME := lib$(XT_TARGET).so
XT_BUILD_DIR = $(BIN_DIR)/$(XT_TARGET)
# Get the system distribution type
IsDebian=$(shell /bin/cat /proc/version | grep -i -e ubuntu -e debian)
IsRedHat=$(shell /bin/cat /proc/version | grep -i -e centos -e "red hat" -e suse -e fedora)
# Change the ipq library name for 64-bit Debian-based distributions
ifeq ($(X86_64),x86_64)
ifneq ($(strip $(IsDebian)),)
LIB_IPQ=_pic
endif
endif
INCLUDE_DIR = -I. \
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include \
-I/usr/lib64/glib-2.0/include
XT_SOURCES = libxt_GTPUAH.c
XT_OBJECTS := $(addprefix $(XT_BUILD_DIR)/, $(notdir $(XT_SOURCES:.c=.o)))
xtlib: XT
XT: DF = $(XT_BUILD_DIR)/$(*F)
XT: $(XT_BUILD_DIR) $(BIN_DIR)/$(XT_LIBNAME)
-include $(addprefix $(XT_BUILD_DIR)/, $(notdir $(XT_SOURCES:.c=.P)))
$(XT_BUILD_DIR):
@echo Build Directory is $@
@if [ ! -d $(BIN_DIR) ]; then mkdir $(BIN_DIR); fi
@if [ ! -d $@ ]; then mkdir $@; fi
$(BIN_DIR)/$(XT_LIBNAME): $(XT_OBJECTS)
@echo Linking $@
@$(LIB_LD) -shared $(XT_OBJECTS) -o $@
$(XT_BUILD_DIR)/%.o : %.c
@echo "Building GTPUAH ext for version $(IPTVERSION) $(IPTABLES_VERSION_STRING)"
@echo Compiling $<
@$(LIB_CC) $(LIB_CFLAGS) -MF $(DF).d $(INCLUDE_DIR) -o $@ -c $<
@cp $(DF).d $(DF).P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(DF).d >> $(DF).P; \
rm -f $(DF).d
libclean:
@rm -rf $(BIN_DIR)/$(XT_LIBNAME) $(XT_BUILD_DIR)
Introduction
------------
This piece of software implementes GPRS Tunneling Protocol (GTP) for user plane.
The software has two components - one is the extension of iptables that
run in user-space. The other is the counterpart of the iptables extension
that runs in kernel space.
License
-------
The project is licensed under GPL2+, see the COPYING and AUTHORS files for more
details.
Architecture
------------
The GTPu tunneling is handled in two parts. The first part is the user-space
iptables target extension library (let's call it libxt). The second
part is the GTPu kernel loadable module (let's call it gtpu). The way it
is, once the user configures a GTPu tunnel attributes using iptables, the klm
is loaded by the kernel automatically and handles the IP packets according to
the GTPu tunnel attributes set by the user.
The user can set the action to be taken on a matching IP packet. The action can be
either of "add", "remove" or "transport" .
A GTPu tunnel has the following attributes:
- own IP address
- own GTPu tunnel id
- peer's IP address
- peer's GTPu tunnel id
The GTPU target is designed to work only on mangle table. Also, the user is
expected to add GTPU target to the PREROUTING chain, as the GTPU target will
modify the original IP packet before it is routed.
Once the user creates the rule in iptables, the matching IP packets go through
the gtpu klm, which acts upon the IP packet according to the action set by the
user. The action "Add" means the klm will add a GTPu header to the IP packet.
"Remove" will remove the GTPu header from the IP packet and "Transport" will
do a Remove first followed by an "Add" on the IP packet.
For example, consider the following command:
iptables -t mangle -A PREROUTING -d 10.10.10.1 -j GTPU --own-ip 192.168.0.98 --own-tun 100 --peer-ip 192.168.0.109 --peer-tun 101 --action add
This command will configure the system to add a GTPu header to any IP packet destined to 10.10.10.1.
The source IP address outer IP will be 192.168.0.109, the dest IP will be 192.168.0.98 and
the destination GTP tunnel id will be 101.
Similarly, consider the following command:
iptables -t mangle -A PREROUTING -s 192.168.0.109 -d 192.168.0.98 -p udp --dport 2152 -j GTPU --action remove
This command will process all the GTPu packets coming from 192.168.0.109 to 192.168.0.98 to
strip the GTPu header and forward the inner IP packet to the kernel's routing engine.
Files
---------
There are two source C files and one header file:
- libxt_GTPU.c : source file for iptables GTPU extension library (libxt)
- xt_GTPU.c : source file for gtpu kernel loadable module (klm)
- xt_GTPU.h : common header file, shared between the libxt and the klm
- Makefile : Makefile to build both the libxt and the klm
- cmd.sh : sample cmd file to show how the binaries can be used
See the INSTALL file to learn how to build the binaries.
References
----------
3GPP TS 29.281 General Packet Radio System (GPRS)
Tunnelling Protocol User Plane (GTP-u)
Authors
-------
Pradip Biswas <pradip_biswas@polarisnetworks.net>
Known issues in GTPU v1.0
-------------------------
1. Does not implement the "Transport" action.
2. Does not handle segmented GTPu packets.
# Clear the iptables mangle table
iptables -t mangle -F
# Remove GTPU KLM
rmmod xt_GTPUAH
# Insert the GTPUAH KLM
insmod ./Bin/xt_GTPUAH.ko
# Copy the userland iptables extenstion library
if [ -d /lib/xtables ]; then
/bin/cp -f ./Bin/libxt_GTPUAH.so /lib/xtables/
fi
if [ -d /lib/iptables ]; then
/bin/cp -f ./Bin/libxt_GTPUAH.so /lib/iptables/libipt_GTPUAH.so
fi
/* Shared library add-on to iptables for the GTPUAH target
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/netfilter.h>
#include "xt_GTPUAH.h"
#if (IPTVERSION <= 135)
#include <iptables.h>
#elif (IPTVERSION > 135)
#include <xtables.h>
#endif
#if (IPTVERSION <= 135)
#define GTPUAH_PARAM_BAD_VALUE 0
#define GTPUAH_PARAM_ONLY_ONCE 1
#define XT_GTPUAH_VERSION IPTABLES_VERSION_STRING
#define gtpuah_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpuah_exit_error exit_error
#elif (IPTVERSION > 135) && (IPTVERSION <= 141)
#define GTPUAH_PARAM_BAD_VALUE P_BAD_VALUE
#define GTPUAH_PARAM_ONLY_ONCE P_ONLY_ONCE
#define XT_GTPUAH_VERSION XTABLES_VERSION
#define gtpuah_param_act param_act
#define gtpuah_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpuah_exit_error exit_error
#elif (IPTVERSION > 141)
#define GTPUAH_PARAM_BAD_VALUE XTF_BAD_VALUE
#define GTPUAH_PARAM_ONLY_ONCE XTF_ONLY_ONCE
#define XT_GTPUAH_VERSION XTABLES_VERSION
#define gtpuah_param_act xtables_param_act
#define gtpuah_strtoui(s,v,m,M) xtables_strtoui(s,NULL,v,m,M)
#define gtpuah_exit_error xtables_error
#endif
enum {
PARAM_LADDR = 1 << 0,
PARAM_LTUN = 1 << 1,
PARAM_RADDR = 1 << 2,
PARAM_RTUN = 1 << 3,
PARAM_ACTION = 1 << 4,
};
static void GTPUAH_help(void)
{
printf(
"GTPUAH target options\n"
" --action value Set action <value: add>\n"
" --own-ip value Set own IP address\n"
" --own-tun value Set own tunnel id <value: 1-2^31>\n"
" --peer-ip value Set peer IP address\n"
" --peer-tun value Set peer tunnel id <value: 1-2^31>\n");
}
#if (IPTVERSION <= 135)
/* Stolen from iptables v1.4.7 code */
void gtpuah_param_act(unsigned int status, const char *p1, ...)
{
const char *p2, *p3;
va_list args;
int b;
va_start(args, p1);
switch (status) {
case GTPUAH_PARAM_ONLY_ONCE:
p2 = va_arg(args, const char *);
b = va_arg(args, unsigned int);
if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPUAH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args);
}
#endif
static void parse_gtpuah_addr(const char *s, struct xt_gtpuah_target_info *info, int flag)
{
in_addr_t addr;
if ((addr = inet_addr(s)) == -1)
{
switch (flag)
{
case PARAM_LADDR:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-ip", s);
break;
case PARAM_RADDR:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-ip", s);
break;
}
}
switch (flag)
{
case PARAM_LADDR:
info->laddr = addr;
break;
case PARAM_RADDR:
info->raddr = addr;
break;
}
}
static void parse_gtpuah_tunid(char *s, struct xt_gtpuah_target_info *info, int flag)
{
unsigned int value;
if (!gtpuah_strtoui(s, &value, 0, UINT32_MAX))
{
switch (flag)
{
case PARAM_LTUN:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-tun", s);
break;
case PARAM_RTUN:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-tun", s);
break;
}
}
switch (flag)
{
case PARAM_LTUN:
info->ltun = value;
break;
case PARAM_RTUN:
info->rtun = value;
break;
}
}
static void parse_gtpuah_action(char *s, struct xt_gtpuah_target_info *info, unsigned int *flags)
{
if (!strcmp(s, "add"))
{
info->action = PARAM_GTPUAH_ACTION_ADD;
*flags |= PARAM_GTPUAH_ACTION_ADD;
}
else
{
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--action", s);
}
}
#if (IPTVERSION <= 135)
static int
GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry,
struct ipt_entry_target **target)
#else
static int
GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
#endif
{
struct xt_gtpuah_target_info *info = (struct xt_gtpuah_target_info *) (*target)->data;
switch (c)
{
case '1':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-ip", *flags & PARAM_LADDR);
parse_gtpuah_addr(optarg, info, PARAM_LADDR);
*flags |= PARAM_LADDR;
return 1;
case '2':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-tun", *flags & PARAM_LTUN);
parse_gtpuah_tunid(optarg, info, PARAM_LTUN);
*flags |= PARAM_LTUN;
return 1;
case '3':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-ip", *flags & PARAM_RADDR);
parse_gtpuah_addr(optarg, info, PARAM_RADDR);
*flags |= PARAM_RADDR;
return 1;
case '4':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-tun", *flags & PARAM_RTUN);
parse_gtpuah_tunid(optarg, info, PARAM_RTUN);
*flags |= PARAM_RTUN;
return 1;
case '5':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--action", *flags & PARAM_ACTION);
parse_gtpuah_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
return 1;
}
static void GTPUAH_check(unsigned int flags)
{
if (!(flags & PARAM_ACTION))
{
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify action");
}
if (!(flags & PARAM_LADDR))
{
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local addr");
}
if (!(flags & PARAM_LTUN))
{
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local tunnel id");
}
if (!(flags & PARAM_RADDR))
{
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote addr");
}
if (!(flags & PARAM_RTUN))
{
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote tunnel id");
}
}
static void convert_action_to_string(int action, char *actionstr)
{
switch(action)
{
case PARAM_GTPUAH_ACTION_ADD:
sprintf (actionstr, "add");
break;
default :
sprintf (actionstr, "unspecified!!!");
break;
}
}
#if (IPTVERSION <= 135)
static void
GTPUAH_print(const struct ipt_ip *ip,
const struct ipt_entry_target *target,
int numeric)
#else
static void
GTPUAH_print(const void *ip,
const struct xt_entry_target *target,
int numeric)
#endif
{
const struct xt_gtpuah_target_info *info =
(struct xt_gtpuah_target_info *) target->data;
char laddr[64], raddr[64], actionstr[32];
convert_action_to_string(info->action, actionstr);
sprintf (laddr, "%s", inet_ntoa(*(struct in_addr*)&info->laddr));
sprintf (raddr, "%s", inet_ntoa(*(struct in_addr*)&info->raddr));
printf("GTPUAH self: %s tunnel: 0x%x / peer: %s tunnel: 0x%x / action: %s",
laddr, info->ltun, raddr, info->rtun, actionstr);
}
static struct option GTPUAH_opts[] = {
{ "own-ip", 1, NULL, '1' },
{ "own-tun", 1, NULL, '2' },
{ "peer-ip", 1, NULL, '3' },
{ "peer-tun", 1, NULL, '4' },
{ "action", 1, NULL, '5' },
{ .name = NULL }
};
#if (IPTVERSION <= 135)
static struct iptables_target gtpuah_tg_reg = {
#else
static struct xtables_target gtpuah_tg_reg = {
#endif
.name = "GTPUAH",
.version = XT_GTPUAH_VERSION,
#if (IPTVERSION > 135)
.family = NFPROTO_IPV4,
#endif
.size = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)),
.help = GTPUAH_help,
.parse = GTPUAH_parse,
.final_check = GTPUAH_check,
.print = GTPUAH_print,
.extra_opts = GTPUAH_opts,
};
void _init(void)
{
#if (IPTVERSION <= 135)
register_target(&gtpuah_tg_reg);
#else
xtables_register_target(&gtpuah_tg_reg);
#endif
}
/*
* GTPu klm for Linux/iptables
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/route.h>
#include <net/checksum.h>
#include <net/udp.h>
#include <net/inet_sock.h>
#include <net/ip.h>
#include <net/route.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#if 0
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#endif
#include "xt_GTPUAH.h"
#if !(defined KVERSION)
#error "Kernel version is not defined!!!! Exiting."
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pradip Biswas <pradip_biswas@polarisnetworks.net>");
MODULE_DESCRIPTION("GTPu Data Path extension on netfilter");
struct gtpuhdr
{
char flags;
char msgtype;
u_int16_t length;
u_int32_t tunid;
};
#define GTPU_HDR_PNBIT 1
#define GTPU_HDR_SBIT 1 << 1
#define GTPU_HDR_EBIT 1 << 2
#define GTPU_ANY_EXT_HDR_BIT (GTPU_HDR_PNBIT | GTPU_HDR_SBIT | GTPU_HDR_EBIT)
#define GTPU_FAILURE 1
#define GTPU_SUCCESS !GTPU_FAILURE
#define GTPU_PORT 2152
static bool _gtpuah_route_packet(struct sk_buff *skb, const struct xt_gtpuah_target_info *info)
{
int err = 0;
struct rtable *rt = NULL;
struct iphdr *iph = ip_hdr(skb);
int daddr = iph->daddr;
struct flowi fl = {
.u = {
.ip4 = {
.daddr = daddr,
.flowi4_tos = RT_TOS(iph->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE,
}
}
};
#if 0
pr_info("GTPUAH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u\n",
info->action,
iph->saddr & 0xFF,
(iph->saddr & 0x0000FF00) >> 8,
(iph->saddr & 0x00FF0000) >> 16,
iph->saddr >> 24,
iph->daddr & 0xFF,
(iph->daddr & 0x0000FF00) >> 8,
(iph->daddr & 0x00FF0000) >> 16,
iph->daddr >> 24,
iph->protocol,
ntohs(iph->tot_len),
skb->mark);
#endif
rt = ip_route_output_key(&init_net, &fl.u.ip4);
if (err != 0)
{
pr_info("GTPU: Failed to route packet to dst 0x%x. Error: (%d)", fl.u.ip4.daddr, err);
return GTPU_FAILURE;
}
#if 0
if (rt->dst.dev)
{
pr_info("GTPU: dst dev name %s\n", rt->dst.dev->name);
}
else
{
pr_info("GTPU: dst dev NULL\n");
}
#endif
//if (info->action == PARAM_GTPUAH_ACTION_ADD) //LG was commented
{
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
skb->dev = skb_dst(skb)->dev;
}
skb->protocol = htons(ETH_P_IP);
/* Send the GTPu message out...gggH */
err = dst_output(skb);
if (err == 0)
{
return GTPU_SUCCESS;
}
else
{
return GTPU_FAILURE;
}
}
static unsigned int
_gtpuah_target_add(struct sk_buff *skb, const struct xt_gtpuah_target_info *tgi)
{
struct iphdr *iph = ip_hdr(skb);
struct udphdr *udph = NULL;
struct gtpuhdr *gtpuh = NULL;
struct sk_buff *new_skb = NULL;
int headroom_reqd = sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtpuhdr);
int orig_iplen = 0, udp_len = 0, ip_len = 0;
if (skb->mark == 0) {
pr_info("GTPUAH: _gtpuah_target_add skb mark %u tgi mark %u", skb->mark, tgi->rtun);
}
/* Keep the length of the source IP packet */
orig_iplen = ntohs(iph->tot_len);
/* Create a new copy of the original skb...can't avoid :-( */
new_skb = skb_copy_expand(skb, headroom_reqd + skb_headroom(skb), skb_tailroom(skb), GFP_ATOMIC);
if (new_skb == NULL)
{
return NF_ACCEPT;
}
/* Add GTPu header */
gtpuh = (struct gtpuhdr*)skb_push(new_skb, sizeof(struct gtpuhdr));
gtpuh->flags = 0x30; /* v1 and Protocol-type=GTP */
gtpuh->msgtype = 0xff; /* T-PDU */
gtpuh->length = htons(orig_iplen);
gtpuh->tunid = htonl(skb->mark);
/* Add UDP header */
udp_len = sizeof(struct udphdr) + sizeof(struct gtpuhdr) + orig_iplen;
udph = (struct udphdr*)skb_push(new_skb, sizeof(struct udphdr));
udph->source = htons(GTPU_PORT);
udph->dest = htons(GTPU_PORT);
udph->len = htons(udp_len);
udph->check = 0;
udph->check = csum_tcpudp_magic(tgi->laddr,
tgi->raddr,
udp_len,
IPPROTO_UDP,
csum_partial((char*)udph, udp_len, 0));
skb_set_transport_header(new_skb, 0);
/* Add IP header */
ip_len = udp_len + sizeof(struct iphdr);
iph = (struct iphdr*)skb_push(new_skb, sizeof(struct iphdr));
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = htons(ip_len);
iph->id = 0;
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;
iph->check = 0;
iph->saddr = (tgi->laddr);
iph->daddr = (tgi->raddr);
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
skb_set_network_header(new_skb, 0);
/* Route the packet */
if (_gtpuah_route_packet(new_skb, tgi) == GTPU_SUCCESS)
{
/* Succeeded. Drop the original packet */
return NF_DROP;
}
else
{
kfree_skb(new_skb);
return NF_ACCEPT; /* What should we do here ??? ACCEPT seems to be the best option */
}
}
static unsigned int
xt_gtpuah_target(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_gtpuah_target_info *tgi = par->targinfo;
int result = NF_ACCEPT;
if (tgi == NULL)
{
return result;
}
if (tgi->action == PARAM_GTPUAH_ACTION_ADD)
{
result = _gtpuah_target_add(skb, tgi);
}
return result;
}
static struct xt_target xt_gtpuah_reg __read_mostly =
{
.name = "GTPUAH",
.revision = 0,
.family = AF_INET,
.hooks = (1 << NF_INET_FORWARD) |
(1 << NF_INET_POST_ROUTING),
.table = "mangle",
.target = xt_gtpuah_target,
.targetsize = sizeof(struct xt_gtpuah_target_info),
.me = THIS_MODULE,
};
static int __init xt_gtpuah_init(void)
{
pr_info("GTPUAH: Initializing module (KVersion: %d)\n", KVERSION);
pr_info("GTPUAH: Copyright Polaris Networks 2010-2011\n");
return xt_register_target(&xt_gtpuah_reg);
}
static void __exit xt_gtpuah_exit(void)
{
xt_unregister_target(&xt_gtpuah_reg);
pr_info("GTPUAH: Unloading module\n");
}
module_init(xt_gtpuah_init);
module_exit(xt_gtpuah_exit);
/* Shared header file for iptables extension for the GTPU target and GTPu KLM
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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.
*
*/
enum xt_gtpuah_mode_
{
PARAM_GTPUAH_ACTION_ADD = 1 << 8,
};
struct xt_gtpuah_target_info
{
u_int32_t laddr;
u_int32_t raddr;
u_int32_t ltun;
u_int32_t rtun;
u_int32_t action;
};
This diff is collapsed.
How to build
------------
1. Extract the files in a location of your choice. The
Files will be extracted in a directory called gtpu.
2. cd <gtpu_dir>/gtpu.
3. make
If make is successful, the binary files (libxt_GTPU.so and xt_GTPU.ko)
will be created in the Bin folder.
How to install
--------------
There is no "make install" as that will be difficult to support all
possible Linux distro. The cmd.sh file demonstrates how to install
the two binary files in the system.
In case of problem:
- check you got the last release of the library (see README),
- contact the mailing list (see README),
- check the bugtracker for known bugs (see README).
Documentation
-------------
Please have a look at the "Architecture" section in the README.
####################################################################################
# Makefile for iptables extension for the GTPU target and GTPu klm
#
# Copyright (c) 2010-2011 Polaris Networks
# Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
#
# 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.
#
####################################################################################
export BIN_DIR ?= $(shell pwd)/Bin
KVERSION = $(shell uname -r)
KVERSION_LAST_DIGIT = $(shell echo ${KVERSION} | cut -d "." -f 3 | cut -d "-" -f 1)
obj-m = xt_GTPURH.o
EXTRA_CFLAGS += -DKVERSION=$(KVERSION_LAST_DIGIT)
all: xtlib
echo "Building for Kernel Version: $(KVERSION_LAST_DIGIT)"
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
mv xt_GTPURH.ko $(BIN_DIR)/
clean: libclean
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
################################################################################
# The next section is used by libxt_GTPURH
################################################################################
XT_IPTABLES_VERSION = $(shell /sbin/iptables -V | cut -d " " -f 2 | cut -b 2-)
IPT_FIRST_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 1 | cut -d "-" -f 1)
IPT_SECOND_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 2 | cut -d "-" -f 1)
IPT_THIRD_NUM = $(shell echo ${XT_IPTABLES_VERSION} | cut -d "." -f 3 | cut -d "-" -f 1)
IPTVERSION = $(IPT_FIRST_NUM)$(IPT_SECOND_NUM)$(IPT_THIRD_NUM)
IPTABLES_VERSION_STRING = \"$(IPT_FIRST_NUM).$(IPT_SECOND_NUM).$(IPT_THIRD_NUM)\"
LIB_CC := gcc
ifeq ($(IPTVERSION), 135)
LIB_LD := ld
else
LIB_LD := gcc
endif
LIB_CFLAGS := -fPIC -Wall -MMD -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 \
-D_REENTRANT -pipe -DXTABLES_LIBDIR=\"/usr/local/libexec/xtables\" -DXTABLES_INTERNAL \
-D_INIT=libxt_GTPURH_init -DPIC -fPIC -O2 \
-DIPTVERSION=$(IPTVERSION) \
-DIPTABLES_VERSION_STRING=$(IPTABLES_VERSION_STRING)
XT_TARGET := xt_GTPURH
XT_LIBNAME := lib$(XT_TARGET).so
XT_BUILD_DIR = $(BIN_DIR)/$(XT_TARGET)
# Get the system distribution type
IsDebian=$(shell /bin/cat /proc/version | grep -i -e ubuntu -e debian)
IsRedHat=$(shell /bin/cat /proc/version | grep -i -e centos -e "red hat" -e suse -e fedora)
# Change the ipq library name for 64-bit Debian-based distributions
ifeq ($(X86_64),x86_64)
ifneq ($(strip $(IsDebian)),)
LIB_IPQ=_pic
endif
endif
INCLUDE_DIR = -I. \
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include \
-I/usr/lib64/glib-2.0/include
XT_SOURCES = libxt_GTPURH.c
XT_OBJECTS := $(addprefix $(XT_BUILD_DIR)/, $(notdir $(XT_SOURCES:.c=.o)))
xtlib: XT
XT: DF = $(XT_BUILD_DIR)/$(*F)
XT: $(XT_BUILD_DIR) $(BIN_DIR)/$(XT_LIBNAME)
-include $(addprefix $(XT_BUILD_DIR)/, $(notdir $(XT_SOURCES:.c=.P)))
$(XT_BUILD_DIR):
@echo Build Directory is $@
@if [ ! -d $(BIN_DIR) ]; then mkdir $(BIN_DIR); fi
@if [ ! -d $@ ]; then mkdir $@; fi
$(BIN_DIR)/$(XT_LIBNAME): $(XT_OBJECTS)
@echo Linking $@
@$(LIB_LD) -shared $(XT_OBJECTS) -o $@
$(XT_BUILD_DIR)/%.o : %.c
@echo "Building GTPuRH ext for version $(IPTVERSION) $(IPTABLES_VERSION_STRING)"
@echo Compiling $<
@$(LIB_CC) $(LIB_CFLAGS) -MF $(DF).d $(INCLUDE_DIR) -o $@ -c $<
@cp $(DF).d $(DF).P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(DF).d >> $(DF).P; \
rm -f $(DF).d
libclean:
@rm -rf $(BIN_DIR)/$(XT_LIBNAME) $(XT_BUILD_DIR)
Introduction
------------
This piece of software implementes GPRS Tunneling Protocol (GTP) for user plane.
The software has two components - one is the extension of iptables that
run in user-space. The other is the counterpart of the iptables extension
that runs in kernel space.
License
-------
The project is licensed under GPL2+, see the COPYING and AUTHORS files for more
details.
Architecture
------------
The GTPu tunneling is handled in two parts. The first part is the user-space
iptables target extension library (let's call it libxt). The second
part is the GTPu kernel loadable module (let's call it gtpu). The way it
is, once the user configures a GTPu tunnel attributes using iptables, the klm
is loaded by the kernel automatically and handles the IP packets according to
the GTPu tunnel attributes set by the user.
The user can set the action to be taken on a matching IP packet. The action can be
either of "add", "remove" or "transport" .
A GTPu tunnel has the following attributes:
- own IP address
- own GTPu tunnel id
- peer's IP address
- peer's GTPu tunnel id
The GTPU target is designed to work only on mangle table. Also, the user is
expected to add GTPU target to the PREROUTING chain, as the GTPU target will
modify the original IP packet before it is routed.
Once the user creates the rule in iptables, the matching IP packets go through
the gtpu klm, which acts upon the IP packet according to the action set by the
user. The action "Add" means the klm will add a GTPu header to the IP packet.
"Remove" will remove the GTPu header from the IP packet and "Transport" will
do a Remove first followed by an "Add" on the IP packet.
For example, consider the following command:
iptables -t mangle -A PREROUTING -d 10.10.10.1 -j GTPU --own-ip 192.168.0.98 --own-tun 100 --peer-ip 192.168.0.109 --peer-tun 101 --action add
This command will configure the system to add a GTPu header to any IP packet destined to 10.10.10.1.
The source IP address outer IP will be 192.168.0.109, the dest IP will be 192.168.0.98 and
the destination GTP tunnel id will be 101.
Similarly, consider the following command:
iptables -t mangle -A PREROUTING -s 192.168.0.109 -d 192.168.0.98 -p udp --dport 2152 -j GTPU --action remove
This command will process all the GTPu packets coming from 192.168.0.109 to 192.168.0.98 to
strip the GTPu header and forward the inner IP packet to the kernel's routing engine.
Files
---------
There are two source C files and one header file:
- libxt_GTPU.c : source file for iptables GTPU extension library (libxt)
- xt_GTPU.c : source file for gtpu kernel loadable module (klm)
- xt_GTPU.h : common header file, shared between the libxt and the klm
- Makefile : Makefile to build both the libxt and the klm
- cmd.sh : sample cmd file to show how the binaries can be used
See the INSTALL file to learn how to build the binaries.
References
----------
3GPP TS 29.281 General Packet Radio System (GPRS)
Tunnelling Protocol User Plane (GTP-u)
Authors
-------
Pradip Biswas <pradip_biswas@polarisnetworks.net>
Known issues in GTPU v1.0
-------------------------
1. Does not implement the "Transport" action.
2. Does not handle segmented GTPu packets.
# Clear the iptables mangle table
iptables -t mangle -F
# Remove GTPU KLM
rmmod xt_GTPU
# Insert the GTPU KLM
insmod ./Bin/xt_GTPU.ko
# Copy the userland iptables extenstion library
if [ -d /lib/xtables ]; then
/bin/cp -f ./Bin/libxt_GTPU.so /lib/xtables/
fi
if [ -d /lib/iptables ]; then
/bin/cp -f ./Bin/libxt_GTPU.so /lib/iptables/libipt_GTPU.so
fi
# Some sample commands for demonstration
iptables -t mangle -A PREROUTING -d 10.10.10.1 -j GTPU --own-ip 192.168.0.98 --own-tun 100 --peer-ip 192.168.0.109 --peer-tun 101 --action add
iptables -t mangle -A PREROUTING -s 192.168.0.109 -d 192.168.0.98 -p udp --dport 2152 -j GTPU --action remove
/* Shared library add-on to iptables for the GTPURH target
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/netfilter.h>
#include "xt_GTPURH.h"
#if (IPTVERSION <= 135)
#include <iptables.h>
#elif (IPTVERSION > 135)
#include <xtables.h>
#endif
#if (IPTVERSION <= 135)
#define GTPURH_PARAM_BAD_VALUE 0
#define GTPURH_PARAM_ONLY_ONCE 1
#define XT_GTPURH_VERSION IPTABLES_VERSION_STRING
#define gtpurh_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpurh_exit_error exit_error
#elif (IPTVERSION > 135) && (IPTVERSION <= 141)
#define GTPURH_PARAM_BAD_VALUE P_BAD_VALUE
#define GTPURH_PARAM_ONLY_ONCE P_ONLY_ONCE
#define XT_GTPURH_VERSION XTABLES_VERSION
#define gtpurh_param_act param_act
#define gtpurh_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpurh_exit_error exit_error
#elif (IPTVERSION > 141)
#define GTPURH_PARAM_BAD_VALUE XTF_BAD_VALUE
#define GTPURH_PARAM_ONLY_ONCE XTF_ONLY_ONCE
#define XT_GTPURH_VERSION XTABLES_VERSION
#define gtpurh_param_act xtables_param_act
#define gtpurh_strtoui(s,v,m,M) xtables_strtoui(s,NULL,v,m,M)
#define gtpurh_exit_error xtables_error
#endif
enum {
PARAM_ACTION = 1 << 0,
};
static void GTPURH_help(void)
{
printf(
"GTPURH target options\n"
" --action value Set action <value: remove>\n");
}
#if (IPTVERSION <= 135)
/* Stolen from iptables v1.4.7 code */
void gtpurh_param_act(unsigned int status, const char *p1, ...)
{
const char *p2, *p3;
va_list args;
int b;
va_start(args, p1);
switch (status) {
case GTPURH_PARAM_ONLY_ONCE:
p2 = va_arg(args, const char *);
b = va_arg(args, unsigned int);
if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPURH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args);
}
#endif
static void parse_gtpurh_action(char *s, struct xt_gtpurh_target_info *info, unsigned int *flags)
{
if (!strcmp(s, "remove"))
{
info->action = PARAM_GTPURH_ACTION_REM;
*flags |= PARAM_GTPURH_ACTION_REM;
}
else
{
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--action", s);
}
}
#if (IPTVERSION <= 135)
static int
GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry,
struct ipt_entry_target **target)
#else
static int
GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
#endif
{
struct xt_gtpurh_target_info *info = (struct xt_gtpurh_target_info *) (*target)->data;
switch (c)
{
case '1':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--action", *flags & PARAM_ACTION);
parse_gtpurh_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
return 1;
}
static void GTPURH_check(unsigned int flags)
{
if (!(flags & PARAM_ACTION))
{
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify action");
}
if (flags & PARAM_GTPURH_ACTION_REM)
{
return;
}
}
static void convert_action_to_string(int action, char *actionstr)
{
switch(action)
{
case PARAM_GTPURH_ACTION_REM:
sprintf (actionstr, "remove");
break;
default :
sprintf (actionstr, "unspecified!!!");
break;
}
}
#if (IPTVERSION <= 135)
static void
GTPURH_print(const struct ipt_ip *ip,
const struct ipt_entry_target *target,
int numeric)
#else
static void
GTPURH_print(const void *ip,
const struct xt_entry_target *target,
int numeric)
#endif
{
const struct xt_gtpurh_target_info *info =
(struct xt_gtpurh_target_info *) target->data;
char laddr[64], raddr[64], actionstr[32];
convert_action_to_string(info->action, actionstr);
if (info->action == PARAM_GTPURH_ACTION_REM)
{
printf("GTPURH action: %s", actionstr);
return;
}
}
static struct option GTPURH_opts[] = {
{ "action", 1, NULL, '1' },
{ .name = NULL }
};
#if (IPTVERSION <= 135)
static struct iptables_target gtpurh_tg_reg = {
#else
static struct xtables_target gtpurh_tg_reg = {
#endif
.name = "GTPURH",
.version = XT_GTPURH_VERSION,
#if (IPTVERSION > 135)
.family = NFPROTO_IPV4,
#endif
.size = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)),
.help = GTPURH_help,
.parse = GTPURH_parse,
.final_check = GTPURH_check,
.print = GTPURH_print,
.extra_opts = GTPURH_opts,
};
void _init(void)
{
#if (IPTVERSION <= 135)
register_target(&gtpurh_tg_reg);
#else
xtables_register_target(&gtpurh_tg_reg);
#endif
}
/*
* GTPu klm for Linux/iptables
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/route.h>
#include <net/checksum.h>
#include <net/udp.h>
#include <net/inet_sock.h>
#include <net/ip.h>
#include <net/route.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#if 0
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#endif
#include "xt_GTPURH.h"
#if !(defined KVERSION)
#error "Kernel version is not defined!!!! Exiting."
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pradip Biswas <pradip_biswas@polarisnetworks.net>");
MODULE_DESCRIPTION("GTPu Data Path extension on netfilter");
struct gtpuhdr
{
char flags;
char msgtype;
u_int16_t length;
u_int32_t tunid;
};
#define GTPURH_HDR_PNBIT 1
#define GTPURH_HDR_SBIT 1 << 1
#define GTPURH_HDR_EBIT 1 << 2
#define GTPURH_ANY_EXT_HDR_BIT (GTPURH_HDR_PNBIT | GTPURH_HDR_SBIT | GTPURH_HDR_EBIT)
#define GTPURH_FAILURE 1
#define GTPURH_SUCCESS !GTPURH_FAILURE
#define GTPURH_PORT 2152
static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_target_info *info)
{
int err = 0;
struct rtable *rt = NULL;
struct iphdr *iph = ip_hdr(skb);
int daddr = iph->daddr;
struct flowi fl = {
.u = {
.ip4 = {
.daddr = daddr,
.flowi4_tos = RT_TOS(iph->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE,
}
}
};
#if 0
pr_info("GTPURH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u\n",
info->action,
iph->saddr & 0xFF,
(iph->saddr & 0x0000FF00) >> 8,
(iph->saddr & 0x00FF0000) >> 16,
iph->saddr >> 24,
iph->daddr & 0xFF,
(iph->daddr & 0x0000FF00) >> 8,
(iph->daddr & 0x00FF0000) >> 16,
iph->daddr >> 24,
iph->protocol,
ntohs(iph->tot_len),
skb->mark);
#endif
rt = ip_route_output_key(&init_net, &fl.u.ip4);
if (err != 0)
{
pr_info("GTPURH: Failed to route packet to dst 0x%x. Error: (%d)", fl.u.ip4.daddr, err);
return GTPURH_FAILURE;
}
#if 0
if (rt->dst.dev)
{
pr_info("GTPURH: dst dev name %s\n", rt->dst.dev->name);
}
else
{
pr_info("GTPURH: dst dev NULL\n");
}
#endif
//if (info->action == PARAM_GTPURH_ACTION_ADD) //LG was commented
{
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
skb->dev = skb_dst(skb)->dev;
}
skb->protocol = htons(ETH_P_IP);
/* Send the GTPu message out...gggH */
err = dst_output(skb);
if (err == 0)
{
return GTPURH_SUCCESS;
}
else
{
return GTPURH_FAILURE;
}
}
static unsigned int
_gtpurh_target_rem(struct sk_buff *orig_skb, const struct xt_gtpurh_target_info *tgi)
{
struct iphdr *iph = ip_hdr(orig_skb);
struct iphdr *iph2 = NULL;
struct gtpuhdr *gtpuh = NULL;
struct sk_buff *skb = NULL;
uint16_t gtp_payload_size = 0;
/* Create a new copy of the original skb...can't avoid :-( LG: WHY???*/
#if defined(ROUTE_PACKET)
skb = skb_copy(orig_skb, GFP_ATOMIC);
if (skb == NULL)
{
return NF_ACCEPT;
}
skb->skb_iif = orig_skb->skb_iif;
skb->protocol = orig_skb->protocol;
#else
skb = orig_skb;
#endif
/* Remove IP header */
skb_pull(skb, (iph->ihl << 2));
/* Remove UDP header */
gtpuh = (struct gtpuhdr*)skb_pull(skb, sizeof(struct udphdr));
gtp_payload_size = ntohs(gtpuh->length);
skb->mark = ntohl(gtpuh->tunid);
/* Remove GTPu header */
skb_pull(skb, sizeof(struct gtpuhdr));
/* If additional fields are present in header, remove them also */
if (gtpuh->flags & GTPURH_ANY_EXT_HDR_BIT)
{
skb_pull(skb, sizeof(short) + sizeof(char) + sizeof(char)); /* #Seq, #N-PDU, #ExtHdr Type */
gtp_payload_size = gtp_payload_size - sizeof(short) - sizeof(char) - sizeof(char);
}
//skb->mac_len = 0;
//skb_set_mac_header(skb, 0);
skb_set_network_header(skb, 0);
iph2 = ip_hdr(skb);
skb_set_transport_header(skb, iph2->ihl << 2);
//#if 0
if ((skb->mark == 0) || (gtp_payload_size != ntohs(iph2->tot_len))) {
pr_info("GTPURH(%d): Decapsulating packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n",
tgi->action,
iph2->saddr & 0xFF,
(iph2->saddr & 0x0000FF00) >> 8,
(iph2->saddr & 0x00FF0000) >> 16,
iph2->saddr >> 24,
iph2->daddr & 0xFF,
(iph2->daddr & 0x0000FF00) >> 8,
(iph2->daddr & 0x00FF0000) >> 16,
iph2->daddr >> 24,
iph2->protocol,
ntohs(iph2->tot_len),
skb->mark,
ntohs(iph->frag_off) & 0x1FFFFFFF,
ntohs(iph->frag_off) >> 13);
if (gtp_payload_size != ntohs(iph2->tot_len)) {
pr_info("\nGTPURH(%d): Mismatch in lengths GTPU length: %u -> %u, IP length %u\n\n",
ntohs(gtpuh->length), gtp_payload_size, ntohs(iph->tot_len));
}
}
//#endif
/* Route the packet */
#if defined(ROUTE_PACKET)
_gtpurh_route_packet(skb, tgi);
return NF_DROP;
#else
return NF_ACCEPT;
#endif
}
static unsigned int
xt_gtpurh_target(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_gtpurh_target_info *tgi = par->targinfo;
int result = NF_ACCEPT;
if (tgi == NULL)
{
return result;
}
if (tgi->action == PARAM_GTPURH_ACTION_REM)
{
result = _gtpurh_target_rem(skb, tgi);
}
return result;
}
static struct xt_target xt_gtpurh_reg __read_mostly =
{
.name = "GTPURH",
.revision = 0,
.family = AF_INET,
.hooks = (1 << NF_INET_PRE_ROUTING),
.table = "raw",
.target = xt_gtpurh_target,
.targetsize = sizeof(struct xt_gtpurh_target_info),
.me = THIS_MODULE,
};
static int __init xt_gtpurh_init(void)
{
pr_info("GTPURH: Initializing module (KVersion: %d)\n", KVERSION);
pr_info("GTPURH: Copyright Polaris Networks 2010-2011\n");
return xt_register_target(&xt_gtpurh_reg);
}
static void __exit xt_gtpurh_exit(void)
{
xt_unregister_target(&xt_gtpurh_reg);
pr_info("GTPURH: Unloading module\n");
}
module_init(xt_gtpurh_init);
module_exit(xt_gtpurh_exit);
/* Shared header file for iptables extension for the GTPU target and GTPu KLM
*
* Copyright (c) 2010-2011 Polaris Networks
* Author: Pradip Biswas <pradip_biswas@polarisnetworks.net>
*
* 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.
*
*/
enum xt_gtpurh_mode_
{
PARAM_GTPURH_ACTION_REM = 1 << 9,
};
struct xt_gtpurh_target_info
{
u_int32_t laddr;
u_int32_t raddr;
u_int32_t ltun;
u_int32_t rtun;
u_int32_t action;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment