Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG UE
Commits
61d34160
Commit
61d34160
authored
Dec 17, 2014
by
Lionel Gauthier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
git-svn-id:
http://svn.eurecom.fr/openair4G/trunk@6276
818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent
9b1daf46
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
247 additions
and
304 deletions
+247
-304
openair-cn/GTPV1-U/GTPUAH/xt_GTPUAH.c
openair-cn/GTPV1-U/GTPUAH/xt_GTPUAH.c
+247
-304
No files found.
openair-cn/GTPV1-U/GTPUAH/xt_GTPUAH.c
View file @
61d34160
/*
* GTPu klm for Linux/iptables
*
...
...
@@ -23,21 +22,60 @@
#include <net/udp.h>
#include <net/inet_sock.h>
#include <net/route.h>
#include <net/addrconf.h>
#include <net/ip6_checksum.h>
#include <net/ip6_route.h>
#include <net/ipv6.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#if 0
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#ifdef CONFIG_BRIDGE_NETFILTER
# include <linux/netfilter_bridge.h>
#endif
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#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"
);
//-----------------------------------------------------------------------------
static
char
*
_gtpuah_nf_inet_hook_2_string
(
int
nf_inet_hookP
);
static
void
_gtpuah_tg4_add
(
struct
sk_buff
*
old_skb_pP
,
const
struct
xt_action_param
*
par_pP
);
static
unsigned
int
gtpuah_tg4
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
);
static
unsigned
int
gtpuah_tg6
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
);
static
int
__init
gtpuah_tg_init
(
void
);
static
void
__exit
gtpuah_tg_exit
(
void
);
//-----------------------------------------------------------------------------
static
struct
xt_target
gtpuah_tg_reg
[]
__read_mostly
=
{
{
.
name
=
"GTPUAH"
,
.
revision
=
0
,
.
family
=
NFPROTO_IPV4
,
.
hooks
=
(
1
<<
NF_INET_POST_ROUTING
)
|
(
1
<<
NF_INET_LOCAL_IN
)
,
.
table
=
"mangle"
,
.
target
=
gtpuah_tg4
,
.
targetsize
=
sizeof
(
struct
xt_gtpuah_target_info
),
.
me
=
THIS_MODULE
,
},
#ifdef WITH_IPV6
{
.
name
=
"GTPUAH"
,
.
revision
=
0
,
.
family
=
NFPROTO_IPV6
,
.
hooks
=
(
1
<<
NF_INET_POST_ROUTING
)
|
(
1
<<
NF_INET_LOCAL_IN
)
,
.
table
=
"mangle"
,
.
target
=
gtpuah_tg6
,
.
targetsize
=
sizeof
(
struct
xt_gtpuah_target_info
),
.
me
=
THIS_MODULE
,
},
#endif
};
struct
gtpuhdr
{
...
...
@@ -46,7 +84,7 @@ struct gtpuhdr
u_int16_t
length
;
u_int32_t
tunid
;
};
//-----------------------------------------------------------------------------
#define MTU 1564
#define GTPU_HDR_PNBIT 1
#define GTPU_HDR_SBIT 1 << 1
...
...
@@ -55,347 +93,252 @@ struct gtpuhdr
#define GTPU_FAILURE 1
#define GTPU_SUCCESS !GTPU_FAILURE
#define GTPU_PORT 2152
#define IP_MORE_FRAGMENTS 0x2000
static
bool
_gtpuah_route_packet
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_gtpuah_target_info
*
info_pP
,
char
*
in_dev_pP
)
{
int
err
=
0
;
struct
rtable
*
rt
=
NULL
;
struct
iphdr
*
iph
=
ip_hdr
(
skb_pP
);
int
daddr
=
iph
->
daddr
;
struct
flowi
fl
=
{
.
u
=
{
.
ip4
=
{
.
daddr
=
daddr
,
.
flowi4_tos
=
RT_TOS
(
iph
->
tos
),
.
flowi4_scope
=
RT_SCOPE_UNIVERSE
,
}
}
};
#if 1
int
flags
,
offset
;
offset
=
ntohs
(
iph
->
frag_off
);
flags
=
offset
&
~
IP_OFFSET
;
offset
&=
IP_OFFSET
;
/* offset is in 8-byte chunks */
offset
<<=
3
;
pr_info
(
"GTPUAH(%d): Routing %s packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %05u, Id %04X, Offset %u, Flags %04X, Mark: %u
\n
"
,
info_pP
->
action
,
(
ip_is_fragment
(
iph
)
==
0
)
?
""
:
"fragmented"
,
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
),
ntohs
(
iph
->
id
),
offset
,
flags
,
skb_pP
->
mark
);
#endif
if
(
in_dev_pP
)
{
if
(
strcasecmp
(
in_dev_pP
,
"lo"
)
==
0
)
{
struct
inet_sock
*
inet
=
inet_sk
(
skb_pP
->
sk
);
ip_queue_xmit
(
&
inet
->
sk
,
skb_pP
,
&
fl
);
}
else
{
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 1
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_pP->action == PARAM_GTPUAH_ACTION_ADD) //LG was commented
{
skb_dst_drop
(
skb_pP
);
skb_dst_set
(
skb_pP
,
&
rt
->
dst
);
skb_pP
->
dev
=
skb_dst
(
skb_pP
)
->
dev
;
}
skb_pP
->
protocol
=
htons
(
ETH_P_IP
);
/* Send the GTPu message out...gggH */
err
=
dst_output
(
skb_pP
);
}
}
if
(
err
==
0
)
{
return
GTPU_SUCCESS
;
}
else
{
return
GTPU_FAILURE
;
#define NIPADDR(addr) \
(
uint8_t
)(
addr
&
0x000000FF
),
\
(
uint8_t
)((
addr
&
0x0000FF00
)
>>
8
),
\
(
uint8_t
)((
addr
&
0x00FF0000
)
>>
16
),
\
(
uint8_t
)((
addr
&
0xFF000000
)
>>
24
)
//-----------------------------------------------------------------------------
static
char
*
_gtpuah_nf_inet_hook_2_string
(
int
nf_inet_hookP
)
{
//-----------------------------------------------------------------------------
switch
(
nf_inet_hookP
)
{
case
NF_INET_PRE_ROUTING
:
return
"NF_INET_PRE_ROUTING"
;
break
;
case
NF_INET_LOCAL_IN
:
return
"NF_INET_LOCAL_IN"
;
break
;
case
NF_INET_FORWARD
:
return
"NF_INET_FORWARD"
;
break
;
case
NF_INET_LOCAL_OUT
:
return
"NF_INET_LOCAL_OUT"
;
break
;
case
NF_INET_POST_ROUTING
:
return
"NF_INET_POST_ROUTING"
;
break
;
default:
return
"NF_INET_UNKNOWN"
;
}
}
static
unsigned
int
_gtpuah_t
arget_add
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_gtpuah_target_info
*
tgi_pP
,
char
*
in_dev_pP
)
{
struct
iphdr
*
iph
=
ip_hdr
(
skb_pP
)
;
struct
iphdr
*
iph2
=
NULL
;
struct
udphdr
*
udph
=
NULL
;
struct
gtpuhdr
*
gtpuh
=
NULL
;
struct
sk_buff
*
new_skb
=
NULL
;
struct
sk_buff
*
new_skb
2
=
NULL
;
uint16_t
headroom_reqd
=
sizeof
(
struct
iphdr
)
+
sizeof
(
struct
udphdr
)
+
sizeof
(
struct
gtpuhdr
);
//-----------------------------------------------------------------------------
static
void
_gtpuah_t
g4_add
(
struct
sk_buff
*
old_skb_pP
,
const
struct
xt_action_param
*
par_pP
)
{
//-----------------------------------------------------------------------------
struct
rtable
*
rt
=
NULL
;
struct
iphdr
*
old_iph_p
=
ip_hdr
(
old_skb_pP
)
;
struct
iphdr
*
new_iph_p
=
NULL
;
struct
udphdr
*
udph_p
=
NULL
;
struct
gtpuhdr
*
gtpuh_p
=
NULL
;
struct
sk_buff
*
new_skb
_p
=
NULL
;
uint16_t
headroom_reqd
=
LL_MAX_HEADER
+
sizeof
(
struct
iphdr
)
+
sizeof
(
struct
udphdr
)
+
sizeof
(
struct
gtpuhdr
);
uint16_t
orig_iplen
=
0
,
udp_len
=
0
,
ip_len
=
0
;
int16_t
remaining_bytes_to_send
=
0
,
remaining_payload_to_send
=
0
,
payload_to_send
=
0
,
bytes_to_remove
=
0
,
bytes_to_send
=
0
;
int
flags
=
0
,
offset
=
0
,
offset2
=
0
;
if
(
skb_pP
->
mark
==
0
)
{
pr_info
(
"GTPUAH: _gtpuah_target_add force info_pP mark %u to skb_pP mark %u"
,
skb_pP
->
mark
,
tgi_pP
->
rtun
);
skb_pP
->
mark
=
tgi_pP
->
rtun
;
int
flags
=
0
,
offset
=
0
;
unsigned
int
addr_type
=
RTN_UNSPEC
;
if
(
old_skb_pP
->
mark
==
0
)
{
pr_info
(
"GTPUAH: _gtpuah_target_add force info_pP mark %u to skb_pP mark %u"
,
old_skb_pP
->
mark
,
((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
rtun
);
old_skb_pP
->
mark
=
((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
rtun
;
}
/* Keep the length of the source IP packet */
orig_iplen
=
ntohs
(
iph
->
tot_len
);
offset
=
ntohs
(
iph
->
frag_off
);
orig_iplen
=
ntohs
(
old_iph_p
->
tot_len
);
offset
=
ntohs
(
old_iph_p
->
frag_off
);
flags
=
offset
&
~
IP_OFFSET
;
/* Create a new copy of the original skb...can't avoid :-( */
if
((
(
orig_iplen
+
headroom_reqd
)
<=
MTU
)
||
(
flags
&
IP_DF
)
)
{
if
((
orig_iplen
+
headroom_reqd
)
<=
MTU
)
{
#if 1
if
(
flags
&
IP_DF
)
{
pr_info
(
"GTPUAH: DONT FRAGMENT id %04X"
,
ntohs
(
iph
->
id
));
}
#endif
new_skb
=
skb_copy_expand
(
skb_pP
,
headroom_reqd
+
skb_headroom
(
skb_pP
),
skb_tailroom
(
skb_pP
),
GFP_ATOMIC
);
if
(
new_skb
==
NULL
)
{
return
NF_ACCEPT
;
new_skb_p
=
skb_copy_expand
(
old_skb_pP
,
headroom_reqd
+
skb_headroom
(
old_skb_pP
),
skb_tailroom
(
old_skb_pP
),
GFP_ATOMIC
);
if
(
new_skb_p
==
NULL
)
{
pr_info
(
"GTPUAH: skb_copy_expand returned NULL"
);
return
;
}
nf_reset
(
new_skb_p
);
//skb_nfmark(new_skb_p) = 0;
skb_init_secmark
(
new_skb_p
);
skb_shinfo
(
new_skb_p
)
->
gso_size
=
0
;
skb_shinfo
(
new_skb_p
)
->
gso_segs
=
0
;
skb_shinfo
(
new_skb_p
)
->
gso_type
=
0
;
/* 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_pP
->
mark
);
gtpuh
_p
=
(
struct
gtpuhdr
*
)
skb_push
(
new_skb_p
,
sizeof
(
struct
gtpuhdr
));
gtpuh
_p
->
flags
=
0x30
;
/* v1 and Protocol-type=GTP */
gtpuh
_p
->
msgtype
=
0xff
;
/* T-PDU */
gtpuh
_p
->
length
=
htons
(
orig_iplen
);
gtpuh
_p
->
tunid
=
htonl
(
old_
skb_pP
->
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_pP
->
laddr
,
tgi_pP
->
raddr
,
udp_len
,
IPPROTO_UDP
,
csum_partial
((
char
*
)
udph
,
udp_len
,
0
));
skb_set_transport_header
(
new_skb
,
0
);
udp_len
=
sizeof
(
struct
udphdr
)
+
sizeof
(
struct
gtpuhdr
)
+
orig_iplen
;
udph
_p
=
(
struct
udphdr
*
)
skb_push
(
new_skb_p
,
sizeof
(
struct
udphdr
));
udph
_p
->
source
=
htons
(
GTPU_PORT
);
udph
_p
->
dest
=
htons
(
GTPU_PORT
);
udph
_p
->
len
=
htons
(
udp_len
);
udph
_p
->
check
=
0
;
udph
_p
->
check
=
csum_tcpudp_magic
(((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
laddr
,
((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
raddr
,
udp_len
,
IPPROTO_UDP
,
csum_partial
((
char
*
)
udph_p
,
udp_len
,
0
));
skb_set_transport_header
(
new_skb
_p
,
0
);
/* Add IP header */
ip_len
=
sizeof
(
struct
iphdr
)
+
sizeof
(
struct
udphdr
)
+
sizeof
(
struct
gtpuhdr
)
+
orig_iplen
;
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
=
(
uint16_t
)(((
uint64_t
)
new_skb
)
>>
8
);
iph
->
frag_off
=
0
;
iph
->
ttl
=
64
;
iph
->
protocol
=
IPPROTO_UDP
;
iph
->
saddr
=
(
tgi_pP
->
laddr
);
iph
->
daddr
=
(
tgi_pP
->
raddr
);
iph
->
check
=
0
;
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_pP
,
in_dev_pP
)
==
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 */
}
}
else
{
new_skb
=
skb_copy_expand
(
skb_pP
,
headroom_reqd
+
skb_headroom
(
skb_pP
),
0
,
GFP_ATOMIC
);
if
(
new_skb
==
NULL
)
{
return
NF_ACCEPT
;
}
// must segment if added headers (IP, UDP, GTP) + original data + original headers > MTU
pr_info
(
"GTPUAH: Fragmentation Id %04X payload size %u (IP Head inc), total ip packet size %u"
,
htons
((
uint16_t
)(((
uint64_t
)
new_skb
)
>>
8
)),
MTU
-
headroom_reqd
,
MTU
);
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_pP
->
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_pP
->
laddr
,
tgi_pP
->
raddr
,
udp_len
,
IPPROTO_UDP
,
csum_partial
((
char
*
)
udph
,
udp_len
,
0
));
skb_set_transport_header
(
new_skb
,
0
);
/* Add IP header */
ip_len
=
MTU
;
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
=
(
uint16_t
)(((
uint64_t
)
new_skb
)
>>
8
);
iph
->
frag_off
=
htons
(
IP_MORE_FRAGMENTS
);
iph
->
ttl
=
64
;
iph
->
protocol
=
IPPROTO_UDP
;
iph
->
saddr
=
(
tgi_pP
->
laddr
);
iph
->
daddr
=
(
tgi_pP
->
raddr
);
iph
->
check
=
0
;
iph
->
check
=
ip_fast_csum
((
unsigned
char
*
)
iph
,
iph
->
ihl
);
skb_set_network_header
(
new_skb
,
0
);
skb_trim
(
new_skb
,
MTU
-
headroom_reqd
);
/* Route the packet */
if
(
_gtpuah_route_packet
(
new_skb
,
tgi_pP
,
in_dev_pP
)
==
GTPU_SUCCESS
)
{
remaining_payload_to_send
=
orig_iplen
-
MTU
+
headroom_reqd
;
remaining_bytes_to_send
=
remaining_payload_to_send
+
sizeof
(
struct
iphdr
);
bytes_to_remove
=
MTU
-
headroom_reqd
;
offset2
=
MTU
-
headroom_reqd
-
sizeof
(
struct
iphdr
);
// the localhost generated traffic can have len > MTU
// but can cause problem at UE rx side
while
(
remaining_payload_to_send
>
0
)
{
if
((
remaining_payload_to_send
+
sizeof
(
struct
iphdr
))
>
MTU
)
{
bytes_to_send
=
MTU
;
payload_to_send
=
MTU
-
sizeof
(
struct
iphdr
);
new_iph_p
=
(
struct
iphdr
*
)
skb_push
(
new_skb_p
,
sizeof
(
struct
iphdr
));
new_iph_p
->
ihl
=
5
;
new_iph_p
->
version
=
4
;
new_iph_p
->
tos
=
0
;
new_iph_p
->
tot_len
=
htons
(
ip_len
);
new_iph_p
->
id
=
(
uint16_t
)(((
uint64_t
)
new_skb_p
)
>>
8
);
new_iph_p
->
frag_off
=
0
;
new_iph_p
->
ttl
=
64
;
new_iph_p
->
protocol
=
IPPROTO_UDP
;
new_iph_p
->
saddr
=
((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
laddr
;
new_iph_p
->
daddr
=
((
const
struct
xt_gtpuah_target_info
*
)(
par_pP
->
targinfo
))
->
raddr
;
new_iph_p
->
check
=
0
;
new_iph_p
->
check
=
ip_fast_csum
((
unsigned
char
*
)
new_iph_p
,
new_iph_p
->
ihl
);
skb_set_network_header
(
new_skb_p
,
0
);
new_skb_p
->
ip_summed
=
CHECKSUM_COMPLETE
;
new_skb_p
->
csum
=
new_iph_p
->
check
;
new_skb_p
->
mark
=
old_skb_pP
->
mark
;
switch
(
par_pP
->
hooknum
)
{
case
NF_INET_POST_ROUTING
:
{
struct
flowi
fl
=
{
.
u
=
{
.
ip4
=
{
.
daddr
=
new_iph_p
->
daddr
,
.
flowi4_tos
=
RT_TOS
(
new_iph_p
->
tos
),
.
flowi4_scope
=
RT_SCOPE_UNIVERSE
,
}
}
};
pr_info
(
"GTPUAH: PACKET -> NF_HOOK NF_INET_POST_ROUTING/%s encapsulated src: %u.%u.%u.%u dst: %u.%u.%u.%u"
,
gtpuah_tg_reg
[
0
].
table
,
NIPADDR
(
old_iph_p
->
saddr
),
NIPADDR
(
old_iph_p
->
daddr
));
new_skb_p
->
pkt_type
=
PACKET_OTHERHOST
;
// PACKET_OUTGOING
#ifdef CONFIG_BRIDGE_NETFILTER
if
(
new_skb_p
->
nf_bridge
!=
NULL
&&
new_skb_p
->
nf_bridge
->
mask
&
BRNF_BRIDGED
)
{
addr_type
=
RTN_LOCAL
;
new_skb_p
->
pkt_type
=
PACKET_HOST
;
}
#endif
rt
=
ip_route_output_key
(
&
init_net
,
&
fl
.
u
.
ip4
);
if
(
rt
==
NULL
)
{
pr_info
(
"GTPURH: Failed to route packet to dst 0x%x."
,
fl
.
u
.
ip4
.
daddr
);
goto
free_new_skb
;
}
new_skb_p
->
priority
=
rt_tos2priority
(
new_iph_p
->
tos
);
skb_dst_drop
(
new_skb_p
);
if
(
rt
->
dst
.
dev
)
{
pr_info
(
"GTPURH: dst dev name %s
\n
"
,
rt
->
dst
.
dev
->
name
);
skb_dst_set
(
new_skb_p
,
dst_clone
(
&
rt
->
dst
));
new_skb_p
->
dev
=
skb_dst
(
new_skb_p
)
->
dev
;
if
(
new_skb_p
->
len
>
dst_mtu
(
skb_dst
(
new_skb_p
)))
{
goto
free_new_skb
;
}
nf_ct_attach
(
new_skb_p
,
old_skb_pP
);
ip_local_out
(
new_skb_p
);
}
else
{
bytes_to_send
=
remaining_payload_to_send
+
sizeof
(
struct
iphdr
);
payload_to_send
=
remaining_payload_to_send
;
pr_info
(
"GTPURH: rt->dst.dev == NULL
\n
"
);
goto
free_new_skb
;
}
pr_info
(
"GTPUAH: Fragmentation Id %04X payload size %u, total ip packet size %u"
,
htons
((
uint16_t
)(((
uint64_t
)
new_skb
)
>>
8
)),
payload_to_send
,
bytes_to_send
);
// Not optimal, TO OPTIMIZE copies
new_skb2
=
skb_copy
(
skb_pP
,
GFP_ATOMIC
);
skb_pull
(
new_skb2
,
bytes_to_remove
);
/* Add IP header */
iph2
=
(
struct
iphdr
*
)
skb_push
(
new_skb2
,
sizeof
(
struct
iphdr
));
iph2
->
ihl
=
5
;
iph2
->
version
=
4
;
iph2
->
tos
=
0
;
iph2
->
tot_len
=
htons
(
bytes_to_send
);
iph2
->
id
=
(
uint16_t
)(((
uint64_t
)
new_skb
)
>>
8
);
iph2
->
frag_off
=
htons
(
offset2
/
8
);
iph2
->
ttl
=
64
;
iph2
->
protocol
=
IPPROTO_UDP
;
iph2
->
saddr
=
(
tgi_pP
->
laddr
);
iph2
->
daddr
=
(
tgi_pP
->
raddr
);
iph2
->
check
=
0
;
iph2
->
check
=
ip_fast_csum
((
unsigned
char
*
)
iph2
,
iph2
->
ihl
);
skb_set_network_header
(
new_skb2
,
0
);
skb_trim
(
new_skb2
,
MTU
);
_gtpuah_route_packet
(
new_skb2
,
tgi_pP
,
in_dev_pP
);
remaining_payload_to_send
=
remaining_payload_to_send
-
payload_to_send
;
bytes_to_remove
=
bytes_to_remove
+
payload_to_send
;
offset2
=
offset2
+
payload_to_send
;
}
return
NF_DROP
;
}
else
{
kfree_skb
(
new_skb
);
return
NF_ACCEPT
;
/* What should we do here ??? ACCEPT seems to be the best option */
break
;
case
NF_INET_LOCAL_IN
:
addr_type
=
RTN_LOCAL
;
pr_info
(
"GTPUAH: PACKET -> NF_HOOK NF_INET_LOCAL_IN/%s src: %u.%u.%u.%u dst: %u.%u.%u.%u NOT PROCESSED"
,
gtpuah_tg_reg
[
0
].
table
,
NIPADDR
(
old_iph_p
->
saddr
),
NIPADDR
(
old_iph_p
->
daddr
));
//NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, new_skb_p, NULL,
// skb_dst(new_skb_p)->dev, ip_local_deliver_finish);
goto
free_new_skb
;
break
;
default:
pr_info
(
"GTPUAH: NF_HOOK %u not processed"
,
par_pP
->
hooknum
);
goto
free_new_skb
;
}
}
return
;
}
free_new_skb:
pr_info
(
"GTPUAH: PACKET DROPPED"
);
kfree_skb
(
new_skb_p
);
return
;
}
#ifdef WITH_IPV6
//-----------------------------------------------------------------------------
static
unsigned
int
gtpuah_tg6
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
{
//-----------------------------------------------------------------------------
const
struct
xt_gtpuah_target_info
*
tgi_p
=
par_pP
->
targinfo
;
if
(
tgi_p
==
NULL
)
{
return
NF_ACCEPT
;
}
if
(
tgi_p
->
action
==
PARAM_GTPUAH_ACTION_ADD
)
{
return
NF_DROP
;
// TODO
}
return
NF_ACCEPT
;
}
#endif
//-----------------------------------------------------------------------------
static
unsigned
int
xt_gtpuah_target
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
{
gtpuah_tg4
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
{
//-----------------------------------------------------------------------------
const
struct
iphdr
*
iph_p
=
ip_hdr
(
skb_pP
);
const
struct
xt_gtpuah_target_info
*
tgi_p
=
par_pP
->
targinfo
;
int
result
=
NF_ACCEPT
;
if
(
tgi_p
==
NULL
)
{
return
result
;
if
(
tgi_p
==
NULL
)
{
return
NF_ACCEPT
;
}
if
(
tgi_p
->
action
==
PARAM_GTPUAH_ACTION_ADD
)
{
result
=
_gtpuah_target_add
(
skb_pP
,
tgi_p
,
par_pP
->
in
->
name
);
if
(
tgi_p
->
action
==
PARAM_GTPUAH_ACTION_ADD
)
{
pr_info
(
"GTPUAH: PACKET -> NF_HOOK %s/%s src: %u.%u.%u.%u dst: %u.%u.%u.%u NOT PROCESSED"
,
_gtpuah_nf_inet_hook_2_string
(
par_pP
->
hooknum
),
NIPADDR
(
iph_p
->
saddr
),
NIPADDR
(
iph_p
->
daddr
));
//_gtpuah_tg4_add(skb_pP, par_pP);
return
NF_DROP
;
}
return
result
;
return
NF_ACCEPT
;
}
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
)
|
(
1
<<
NF_INET_LOCAL_OUT
),
.
table
=
"mangle"
,
.
target
=
xt_gtpuah_target
,
.
targetsize
=
sizeof
(
struct
xt_gtpuah_target_info
),
.
me
=
THIS_MODULE
,
};
//-----------------------------------------------------------------------------
static
int
__init
gtpuah_tg_init
(
void
)
{
//-----------------------------------------------------------------------------
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
"
);
pr_info
(
"GTPUAH: Modified by EURECOM Lionel GAUTHIER 2014
\n
"
);
return
xt_register_target
(
&
xt_gtpuah_reg
);
#if defined(WITH_IPV6)
pr_info
(
"GTPURH: IPv4/IPv6 enabled
\n
"
);
#else
pr_info
(
"GTPURH: IPv4 only enabled
\n
"
);
#endif
return
xt_register_targets
(
gtpuah_tg_reg
,
ARRAY_SIZE
(
gtpuah_tg_reg
));
}
static
void
__exit
xt_gtpuah
_exit
(
void
)
static
void
__exit
gtpuah_tg
_exit
(
void
)
{
xt_unregister_target
(
&
xt_gtpuah_reg
);
xt_unregister_targets
(
gtpuah_tg_reg
,
ARRAY_SIZE
(
gtpuah_tg_reg
));
#if defined(WITH_IPV6)
pr_info
(
"GTPURH: IPv4/IPv6 enabled
\n
"
);
#else
pr_info
(
"GTPURH: IPv4 only enabled
\n
"
);
#endif
pr_info
(
"GTPUAH: Unloading module
\n
"
);
}
module_init
(
xt_gtpuah_init
);
module_exit
(
xt_gtpuah_exit
);
module_init
(
gtpuah_tg_init
);
module_exit
(
gtpuah_tg_exit
);
MODULE_ALIAS
(
"ipt6_GTPUAH"
);
MODULE_ALIAS
(
"ipt_GTPUAH"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment