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
2952b0f0
Commit
2952b0f0
authored
Dec 16, 2014
by
Lionel Gauthier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
git-svn-id:
http://svn.eurecom.fr/openair4G/trunk@6273
818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent
032b6164
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
265 additions
and
442 deletions
+265
-442
openair-cn/GTPV1-U/GTPURH/libxt_GTPURH.c
openair-cn/GTPV1-U/GTPURH/libxt_GTPURH.c
+106
-17
openair-cn/GTPV1-U/GTPURH/xt_GTPURH.c
openair-cn/GTPV1-U/GTPURH/xt_GTPURH.c
+159
-425
No files found.
openair-cn/GTPV1-U/GTPURH/libxt_GTPURH.c
View file @
2952b0f0
...
@@ -50,14 +50,22 @@
...
@@ -50,14 +50,22 @@
#endif
#endif
enum
{
enum
{
PARAM_ACTION
=
1
<<
0
,
PARAM_LADDR
=
1
<<
0
,
PARAM_LTUN
=
1
<<
1
,
PARAM_RADDR
=
1
<<
2
,
PARAM_RTUN
=
1
<<
3
,
PARAM_ACTION
=
1
<<
4
,
};
};
static
void
GTPURH_help
(
void
)
static
void
GTPURH_help
(
void
)
{
{
printf
(
printf
(
"GTPURH target options
\n
"
"GTPUAH target options
\n
"
" --action value Set action <value: remove>
\n
"
);
" --action value Set action <value: remove>
\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)
#if (IPTVERSION <= 135)
...
@@ -97,17 +105,63 @@ void gtpurh_param_act(unsigned int status, const char *p1, ...)
...
@@ -97,17 +105,63 @@ void gtpurh_param_act(unsigned int status, const char *p1, ...)
#endif
#endif
static
void
parse_gtpurh_addr
(
const
char
*
s
,
struct
xt_gtpurh_target_info
*
info
,
int
flag
)
{
in_addr_t
addr
;
if
((
addr
=
inet_addr
(
s
))
==
-
1
)
{
switch
(
flag
)
{
case
PARAM_LADDR
:
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--own-ip"
,
s
);
break
;
case
PARAM_RADDR
:
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--peer-ip"
,
s
);
break
;
}
}
switch
(
flag
)
{
case
PARAM_LADDR
:
info
->
laddr
=
addr
;
break
;
case
PARAM_RADDR
:
info
->
raddr
=
addr
;
break
;
}
}
static
void
parse_gtpurh_tunid
(
char
*
s
,
struct
xt_gtpurh_target_info
*
info
,
int
flag
)
{
unsigned
int
value
;
if
(
!
gtpurh_strtoui
(
s
,
&
value
,
0
,
UINT32_MAX
))
{
switch
(
flag
)
{
case
PARAM_LTUN
:
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--own-tun"
,
s
);
break
;
case
PARAM_RTUN
:
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--peer-tun"
,
s
);
break
;
}
}
switch
(
flag
)
{
case
PARAM_LTUN
:
info
->
ltun
=
value
;
break
;
case
PARAM_RTUN
:
info
->
rtun
=
value
;
break
;
}
}
static
void
parse_gtpurh_action
(
char
*
s
,
struct
xt_gtpurh_target_info
*
info
,
unsigned
int
*
flags
)
static
void
parse_gtpurh_action
(
char
*
s
,
struct
xt_gtpurh_target_info
*
info
,
unsigned
int
*
flags
)
{
{
if
(
!
strcmp
(
s
,
"remove"
))
if
(
!
strcmp
(
s
,
"remove"
))
{
{
info
->
action
=
PARAM_GTPURH_ACTION_REM
;
info
->
action
=
PARAM_GTPURH_ACTION_REM
;
*
flags
|=
PARAM_GTPURH_ACTION_REM
;
*
flags
|=
PARAM_GTPURH_ACTION_REM
;
}
}
else
{
else
{
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--action"
,
s
);
gtpurh_param_act
(
GTPURH_PARAM_BAD_VALUE
,
"GTPURH"
,
"--action"
,
s
);
}
}
}
}
...
@@ -128,10 +182,30 @@ GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
...
@@ -128,10 +182,30 @@ GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
switch
(
c
)
switch
(
c
)
{
{
case
'1'
:
case
'1'
:
gtpurh_param_act
(
GTPURH_PARAM_ONLY_ONCE
,
"GTPURH"
,
"--action"
,
*
flags
&
PARAM_ACTION
);
gtpurh_param_act
(
GTPURH_PARAM_ONLY_ONCE
,
"GTPURH"
,
"--own-ip"
,
*
flags
&
PARAM_LADDR
);
parse_gtpurh_action
(
optarg
,
info
,
flags
);
parse_gtpurh_addr
(
optarg
,
info
,
PARAM_LADDR
);
*
flags
|=
PARAM_ACTION
;
*
flags
|=
PARAM_LADDR
;
return
1
;
return
1
;
case
'2'
:
gtpurh_param_act
(
GTPURH_PARAM_ONLY_ONCE
,
"GTPURH"
,
"--own-tun"
,
*
flags
&
PARAM_LTUN
);
parse_gtpurh_tunid
(
optarg
,
info
,
PARAM_LTUN
);
*
flags
|=
PARAM_LTUN
;
return
1
;
case
'3'
:
gtpurh_param_act
(
GTPURH_PARAM_ONLY_ONCE
,
"GTPURH"
,
"--peer-ip"
,
*
flags
&
PARAM_RADDR
);
parse_gtpurh_addr
(
optarg
,
info
,
PARAM_RADDR
);
*
flags
|=
PARAM_RADDR
;
return
1
;
case
'4'
:
gtpurh_param_act
(
GTPURH_PARAM_ONLY_ONCE
,
"GTPURH"
,
"--peer-tun"
,
*
flags
&
PARAM_RTUN
);
parse_gtpurh_tunid
(
optarg
,
info
,
PARAM_RTUN
);
*
flags
|=
PARAM_RTUN
;
return
1
;
case
'5'
:
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
;
return
1
;
...
@@ -143,10 +217,21 @@ static void GTPURH_check(unsigned int flags)
...
@@ -143,10 +217,21 @@ static void GTPURH_check(unsigned int flags)
{
{
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify action"
);
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify action"
);
}
}
if
(
!
(
flags
&
PARAM_LADDR
))
if
(
flags
&
PARAM_GTPURH_ACTION_REM
)
{
{
return
;
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify local addr"
);
}
if
(
!
(
flags
&
PARAM_LTUN
))
{
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify local tunnel id"
);
}
if
(
!
(
flags
&
PARAM_RADDR
))
{
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify remote addr"
);
}
if
(
!
(
flags
&
PARAM_RTUN
))
{
gtpurh_exit_error
(
PARAMETER_PROBLEM
,
"GTPURH: You must specify remote tunnel id"
);
}
}
}
}
...
@@ -191,8 +276,12 @@ GTPURH_print(const void *ip,
...
@@ -191,8 +276,12 @@ GTPURH_print(const void *ip,
}
}
static
struct
option
GTPURH_opts
[]
=
{
static
struct
option
GTPURH_opts
[]
=
{
{
"action"
,
1
,
NULL
,
'1'
},
{
"own-ip"
,
1
,
NULL
,
'1'
},
{
.
name
=
NULL
}
{
"own-tun"
,
1
,
NULL
,
'2'
},
{
"peer-ip"
,
1
,
NULL
,
'3'
},
{
"peer-tun"
,
1
,
NULL
,
'4'
},
{
"action"
,
1
,
NULL
,
'5'
},
{
.
name
=
NULL
}
};
};
#if (IPTVERSION <= 135)
#if (IPTVERSION <= 135)
...
...
openair-cn/GTPV1-U/GTPURH/xt_GTPURH.c
View file @
2952b0f0
/*
/*
* GTPu klm for Linux/iptables
* GTPu klm for Linux/iptables
*
*
...
@@ -28,6 +27,9 @@
...
@@ -28,6 +27,9 @@
#if 0
#if 0
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
#endif
#endif
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif
//#define ROUTE_PACKET 1
//#define ROUTE_PACKET 1
...
@@ -39,220 +41,50 @@
...
@@ -39,220 +41,50 @@
#error "Kernel version is not defined!!!! Exiting."
#error "Kernel version is not defined!!!! Exiting."
#endif
#endif
#define NIPADDR(addr) \
(
uint8_t
)(
addr
&
0x000000FF
),
\
(
uint8_t
)((
addr
&
0x0000FF00
)
>>
8
),
\
(
uint8_t
)((
addr
&
0x00FF0000
)
>>
16
),
\
(
uint8_t
)((
addr
&
0xFF000000
)
>>
24
)
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Pradip Biswas <pradip_biswas@polarisnetworks.net>"
);
MODULE_AUTHOR
(
"Pradip Biswas <pradip_biswas@polarisnetworks.net>"
);
MODULE_DESCRIPTION
(
"GTPu Data Path extension on netfilter"
);
MODULE_DESCRIPTION
(
"GTPu Data Path extension on netfilter"
);
static
char
*
_gtpurh_nf_inet_hook_2_string
(
int
nf_inet_hookP
);
static
inline
bool
_gtpurh_ip_is_fragment
(
const
struct
iphdr
*
iph_p
);
static
void
_gtpurh_print_hex_octets
(
unsigned
char
*
data_pP
,
unsigned
short
sizeP
);
static
unsigned
int
_gtpurh_tg4_rem
(
struct
sk_buff
*
orig_skb_pP
,
const
struct
xt_action_param
*
par_pP
);
#if defined(WITH_IPV6)
static
unsigned
int
gtpurh_tg6
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
);
#endif
static
unsigned
int
gtpurh_tg4
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
);
/*
static
struct
xt_target
gtpurh_tg_reg
[]
__read_mostly
=
{
* Statically sized hash table implementation
{
* (C) 2012 Sasha Levin <levinsasha928@gmail.com>
.
name
=
"GTPURH"
,
*/
.
revision
=
0
,
.
family
=
NFPROTO_IPV4
,
#ifndef _LINUX_HASHTABLE_H
.
hooks
=
(
1
<<
NF_INET_PRE_ROUTING
)
|
#define _LINUX_HASHTABLE_H
(
1
<<
NF_INET_LOCAL_OUT
),
.
proto
=
IPPROTO_UDP
,
#include <linux/list.h>
.
table
=
"raw"
,
#include <linux/types.h>
.
target
=
gtpurh_tg4
,
#include <linux/kernel.h>
.
targetsize
=
sizeof
(
struct
xt_gtpurh_target_info
),
#include <linux/hash.h>
.
me
=
THIS_MODULE
,
#include <linux/rculist.h>
},
#if defined(WITH_IPV6)
#define DEFINE_HASHTABLE(name, bits) \
{
struct
hlist_head
name
[
1
<<
(
bits
)]
=
\
.
name
=
"GTPURH"
,
{
[
0
...
((
1
<<
(
bits
))
-
1
)]
=
HLIST_HEAD_INIT
}
.
revision
=
0
,
.
family
=
NFPROTO_IPV6
,
#define DECLARE_HASHTABLE(name, bits) \
.
proto
=
IPPROTO_UDP
,
struct
hlist_head
name
[
1
<<
(
bits
)]
.
table
=
"raw"
,
.
target
=
gtpurh_tg6
,
#define HASH_SIZE(name) (ARRAY_SIZE(name))
.
me
=
THIS_MODULE
,
#define HASH_BITS(name) ilog2(HASH_SIZE(name))
},
/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
#define hash_min(val, bits) \
(
sizeof
(
val
)
<=
4
?
hash_32
(
val
,
bits
)
:
hash_long
(
val
,
bits
))
static
inline
void
__hash_init
(
struct
hlist_head
*
ht
,
unsigned
int
sz
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
sz
;
i
++
)
INIT_HLIST_HEAD
(
&
ht
[
i
]);
}
/**
* hash_init - initialize a hash table
* @hashtable: hashtable to be initialized
*
* Calculates the size of the hashtable from the given parameter, otherwise
* same as hash_init_size.
*
* This has to be a macro since HASH_BITS() will not work on pointers since
* it calculates the size during preprocessing.
*/
#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
/**
* hash_add - add an object to a hashtable
* @hashtable: hashtable to add to
* @node: the &struct hlist_node of the object to be added
* @key: the key of the object to be added
*/
#define hash_add(hashtable, node, key) \
hlist_add_head
(
node
,
&
hashtable
[
hash_min
(
key
,
HASH_BITS
(
hashtable
))])
/**
* hash_add_rcu - add an object to a rcu enabled hashtable
* @hashtable: hashtable to add to
* @node: the &struct hlist_node of the object to be added
* @key: the key of the object to be added
*/
#define hash_add_rcu(hashtable, node, key) \
hlist_add_head_rcu
(
node
,
&
hashtable
[
hash_min
(
key
,
HASH_BITS
(
hashtable
))])
/**
* hash_hashed - check whether an object is in any hashtable
* @node: the &struct hlist_node of the object to be checked
*/
static
inline
bool
hash_hashed
(
struct
hlist_node
*
node
)
{
return
!
hlist_unhashed
(
node
);
}
static
inline
bool
__hash_empty
(
struct
hlist_head
*
ht
,
unsigned
int
sz
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
sz
;
i
++
)
if
(
!
hlist_empty
(
&
ht
[
i
]))
return
false
;
return
true
;
}
/**
* hash_empty - check whether a hashtable is empty
* @hashtable: hashtable to check
*
* This has to be a macro since HASH_BITS() will not work on pointers since
* it calculates the size during preprocessing.
*/
#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
/**
* hash_del - remove an object from a hashtable
* @node: &struct hlist_node of the object to remove
*/
static
inline
void
hash_del
(
struct
hlist_node
*
node
)
{
hlist_del_init
(
node
);
}
/**
* hash_del_rcu - remove an object from a rcu enabled hashtable
* @node: &struct hlist_node of the object to remove
*/
static
inline
void
hash_del_rcu
(
struct
hlist_node
*
node
)
{
hlist_del_init_rcu
(
node
);
}
/**
* hash_for_each - iterate over a hashtable
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each(name, bkt, obj, pos, member) \
for
((
bkt
)
=
0
,
obj
=
NULL
;
obj
==
NULL
&&
(
bkt
)
<
HASH_SIZE
(
name
);
\
(
bkt
)
++
)
\
hlist_for_each_entry
(
obj
,
pos
,
&
name
[
bkt
],
member
)
/**
* hash_for_each_rcu - iterate over a rcu enabled hashtable
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each_rcu(name, bkt, obj, member) \
for
((
bkt
)
=
0
,
obj
=
NULL
;
obj
==
NULL
&&
(
bkt
)
<
HASH_SIZE
(
name
);
\
(
bkt
)
++
)
\
hlist_for_each_entry_rcu
(
obj
,
&
name
[
bkt
],
member
)
/**
* hash_for_each_safe - iterate over a hashtable safe against removal of
* hash entry
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @tmp: a &struct used for temporary storage
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each_safe(name, bkt, tmp, obj, member) \
for
((
bkt
)
=
0
,
obj
=
NULL
;
obj
==
NULL
&&
(
bkt
)
<
HASH_SIZE
(
name
);
\
(
bkt
)
++
)
\
hlist_for_each_entry_safe
(
obj
,
tmp
,
&
name
[
bkt
],
member
)
/**
* hash_for_each_possible - iterate over all possible objects hashing to the
* same bucket
* @name: hashtable to iterate
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible(name, tpos, pos, member, key) \
hlist_for_each_entry
(
tpos
,
pos
,
&
name
[
hash_min
(
key
,
HASH_BITS
(
name
))],
member
)
/**
* hash_for_each_possible_rcu - iterate over all possible objects hashing to the
* same bucket in an rcu enabled hashtable
* in a rcu enabled hashtable
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible_rcu(name, obj, member, key) \
hlist_for_each_entry_rcu
(
obj
,
&
name
[
hash_min
(
key
,
HASH_BITS
(
name
))],
\
member
)
/**
* hash_for_each_possible_rcu_notrace - iterate over all possible objects hashing
* to the same bucket in an rcu enabled hashtable in a rcu enabled hashtable
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*
* This is the same as hash_for_each_possible_rcu() except that it does
* not do any RCU debugging or tracing.
*/
#define hash_for_each_possible_rcu_notrace(name, obj, member, key) \
hlist_for_each_entry_rcu_notrace
(
obj
,
\
&
name
[
hash_min
(
key
,
HASH_BITS
(
name
))],
member
)
/**
* hash_for_each_possible_safe - iterate over all possible objects hashing to the
* same bucket safe against removals
* @name: hashtable to iterate
* @obj: the type * to use as a loop cursor for each entry
* @tmp: a &struct used for temporary storage
* @member: the name of the hlist_node within the struct
* @key: the key of the objects to iterate over
*/
#define hash_for_each_possible_safe(name, obj, tmp, member, key) \
hlist_for_each_entry_safe
(
obj
,
tmp
,
\
&
name
[
hash_min
(
key
,
HASH_BITS
(
name
))],
member
)
#endif
#endif
};
struct
gtpuhdr
struct
gtpuhdr
{
{
...
@@ -276,28 +108,26 @@ struct gtpuhdr
...
@@ -276,28 +108,26 @@ struct gtpuhdr
static
char
_gtpurh_print_buffer
[
GTPURH_2_PRINT_BUFFER_LEN
];
static
char
_gtpurh_print_buffer
[
GTPURH_2_PRINT_BUFFER_LEN
];
/*typedef struct ip_fragment_entry_s {
//-----------------------------------------------------------------------------
struct sk_buff *skb_p;
static
char
*
//struct timeval first_ts; // TO DO WITH IP_FRAG_TIME
_gtpurh_nf_inet_hook_2_string
(
int
nf_inet_hookP
)
{
int flags; //ip header field
//-----------------------------------------------------------------------------
int offset; //ip header field
switch
(
nf_inet_hookP
)
{
int end;
case
NF_INET_PRE_ROUTING
:
return
"NF_INET_PRE_ROUTING"
;
break
;
struct hlist_node node;
case
NF_INET_LOCAL_IN
:
return
"NF_INET_LOCAL_IN"
;
break
;
}ip_fragment_entry_t;
case
NF_INET_FORWARD
:
return
"NF_INET_FORWARD"
;
break
;
case
NF_INET_LOCAL_OUT
:
return
"NF_INET_LOCAL_OUT"
;
break
;
typedef struct ip_reassembly_entry_s {
case
NF_INET_POST_ROUTING
:
return
"NF_INET_POST_ROUTING"
;
break
;
}ip_reassembly_entry_t;
default:
return
"NF_INET_UNKNOWN"
;
*/
}
}
static
inline
bool
_gtpurh_ip_is_fragment
(
const
struct
iphdr
*
iph_p
)
//-----------------------------------------------------------------------------
{
static
inline
bool
_gtpurh_ip_is_fragment
(
const
struct
iphdr
*
iph_p
)
{
//-----------------------------------------------------------------------------
return
(
iph_p
->
frag_off
&
htons
(
IP_MF
|
IP_OFFSET
))
!=
0
;
return
(
iph_p
->
frag_off
&
htons
(
IP_MF
|
IP_OFFSET
))
!=
0
;
}
}
#define MAX_IP_FRAGMENTS 16
#define GTPURH_HASHTABLE_BITS 7
DEFINE_HASHTABLE
(
ip_fragments
,
GTPURH_HASHTABLE_BITS
);
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void
_gtpurh_print_hex_octets
(
unsigned
char
*
data_pP
,
unsigned
short
sizeP
)
void
_gtpurh_print_hex_octets
(
unsigned
char
*
data_pP
,
unsigned
short
sizeP
)
...
@@ -356,7 +186,9 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
...
@@ -356,7 +186,9 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
#if defined(ROUTE_PACKET)
#if defined(ROUTE_PACKET)
//-----------------------------------------------------------------------------
static
bool
_gtpurh_route_packet
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_gtpurh_target_info
*
info_pP
)
static
bool
_gtpurh_route_packet
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_gtpurh_target_info
*
info_pP
)
//-----------------------------------------------------------------------------
{
{
int
err
=
0
;
int
err
=
0
;
struct
rtable
*
rt
=
NULL
;
struct
rtable
*
rt
=
NULL
;
...
@@ -408,7 +240,7 @@ static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_
...
@@ -408,7 +240,7 @@ static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_
skb_dst_set
(
skb_pP
,
&
rt
->
dst
);
skb_dst_set
(
skb_pP
,
&
rt
->
dst
);
skb_pP
->
dev
=
skb_dst
(
skb_pP
)
->
dev
;
skb_pP
->
dev
=
skb_dst
(
skb_pP
)
->
dev
;
/
* Send the GTPu message out */
/
/ Send the GTPu message out
ip_local_out
(
skb_pP
);
ip_local_out
(
skb_pP
);
if
(
err
==
0
)
{
if
(
err
==
0
)
{
...
@@ -418,140 +250,12 @@ static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_
...
@@ -418,140 +250,12 @@ static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_
}
}
}
}
#endif
#endif
/*
static void
_gtpurh_delete_collection_ip_fragments(void)
{
int bucket_loop_cursor = 0;
struct ip_fragment_entry_s *ip_fragment_p = NULL;
struct hlist_node *pos_p = NULL;
hash_for_each(ip_fragments, bucket_loop_cursor, ip_fragment_p, pos_p, node) {
pr_info("GTPURH: %s struct ip_fragment_entry_s* %p, struct hlist_node* %p\n",
__FUNCTION__,
ip_fragment_p,
pos_p);
}
}
static int
_gtpurh_target_reassembly(struct sk_buff *orig_skb_pP, const struct xt_gtpurh_target_info *tgi_pP)
{
struct iphdr *iph_p = ip_hdr(orig_skb_pP);
struct sk_buff *skb_p = NULL;
struct sk_buff *new_skb_p = NULL;
uint16_t key = 0;
int flags, offset, last_frag_offset;
int ihl, end;
struct ip_fragment_entry_s *ip_fragment_p = NULL;
struct hlist_node *pos_p = NULL;
int all_segments_availables = 1;
if ((orig_skb_pP) && (tgi_pP)) {
offset = ntohs(iph_p->frag_off);
flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET; // offset is in 8-byte chunks
offset <<= 3;
ihl = ip_hdrlen(orig_skb_pP);
end = offset + orig_skb_pP->len - ihl;
key = iph_p->id;
pr_info("---------------GTPURH: Dump fragment:------------------------------------------------\n");
_gtpurh_print_hex_octets((unsigned char*)iph_p, orig_skb_pP->len);
// Is this the final fragment?
if ((flags & IP_MF) == 0) {
pr_info("GTPURH: try reassembly last segment id %u len %u offset %u end %u\n",
key,orig_skb_pP->len, offset, end);
// may be the last segment received
// normally iterator gives elements from head to tail, but elements
// have been inserted at the head, so iterator should retrieve fragments
// in reverse order.
last_frag_offset = offset;
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) {
pr_info("GTPURH: try reassembly segment id %u len %u offset %u end %u\n",
key,ip_fragment_p->skb_p->len, ip_fragment_p->offset, ip_fragment_p->end);
if (ip_fragment_p->end == offset) {
offset = ip_fragment_p->offset;
} else {
pr_info("GTPURH: try reassembly segment id %u failed\n",
key);
all_segments_availables = 0;
break;
}
}
if (all_segments_availables) {
// not optimal, but optimize later
new_skb_p = skb_copy_expand(orig_skb_pP,
last_frag_offset + skb_headroom(orig_skb_pP),
skb_tailroom(orig_skb_pP),
GFP_ATOMIC);
if (new_skb_p != NULL)
{
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) {
skb_p = ip_fragment_p->skb_p;
skb_pull(new_skb_p, ihl);
pr_info("GTPURH: reassembly segment id %u len %u offset %u end %u\n",
key, skb_p->len, ip_fragment_p->offset, ip_fragment_p->end);
iph_p = (struct iphdr*)skb_push(new_skb_p, skb_p->len);
ihl = ip_hdrlen(skb_p);
memcpy(iph_p, skb_network_header(skb_p), skb_p->len);
}
skb_set_network_header(new_skb_p, 0);
if (_gtpurh_route_packet(new_skb_p, tgi_pP) != GTPURH_SUCCESS)
{
kfree_skb(new_skb_p);
}
} else {
pr_info("GTPURH: Failed in skb_p allocation (%u bytes)\n",
last_frag_offset + skb_headroom(orig_skb_pP));
}
}
if (1) {
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) {
kfree_skb(ip_fragment_p->skb_p);
hash_del(pos_p);
kfree(ip_fragment_p);
}
}
} else {
pr_info("GTPURH: but in buffer not last segment id %u len %u offset %u end %u\n",
key,orig_skb_pP->len, offset, end);
// not the last fragment received
// assuming no out of order
ip_fragment_p = kmalloc(sizeof(struct ip_fragment_entry_s), GFP_KERNEL);
if (NULL != ip_fragment_p) {
ip_fragment_p->skb_p = skb_copy(orig_skb_pP, GFP_ATOMIC); // may use skb_clone(), TODO
ip_fragment_p->flags = flags;
ip_fragment_p->offset = offset;
ip_fragment_p->end = end;
pr_info("GTPURH: adding in hashtable key %04x ip_fragment %p skbuff %p\n",
key, ip_fragment_p, ip_fragment_p->skb_p);
INIT_HLIST_NODE(&ip_fragment_p->node);
hash_add(ip_fragments, &ip_fragment_p->node, key);
return 0;
} else {
pr_info("GTPURH: ERROR could not allocate memory for buffering IP fragment\n");
}
}
} else {
pr_info("%s(skb_p=%p,tgi_pP=%p) parameter skb_p or tgi_pP is NULL\n",
__FUNCTION__, orig_skb_pP, tgi_pP);
}
return -1;
}*/
//-----------------------------------------------------------------------------
static
unsigned
int
static
unsigned
int
_gtpurh_tg4_rem
(
struct
sk_buff
*
orig_skb_pP
,
const
struct
xt_action_param
*
par_pP
)
_gtpurh_tg4_rem
(
struct
sk_buff
*
orig_skb_pP
,
const
struct
xt_action_param
*
par_pP
)
{
{
//-----------------------------------------------------------------------------
struct
iphdr
*
iph_p
=
ip_hdr
(
orig_skb_pP
);
struct
iphdr
*
iph_p
=
ip_hdr
(
orig_skb_pP
);
struct
iphdr
*
iph2_p
=
NULL
;
struct
iphdr
*
iph2_p
=
NULL
;
struct
udphdr
*
udph_p
=
NULL
;
struct
udphdr
*
udph_p
=
NULL
;
...
@@ -560,7 +264,6 @@ _gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_p
...
@@ -560,7 +264,6 @@ _gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_p
#if defined(NEW_SKB)
#if defined(NEW_SKB)
struct
sk_buff
*
new_skb_p
=
NULL
;
struct
sk_buff
*
new_skb_p
=
NULL
;
struct
iphdr
*
new_ip_p
=
NULL
;
struct
iphdr
*
new_ip_p
=
NULL
;
unsigned
int
addr_type
=
0
;
#endif
#endif
uint16_t
gtp_payload_size
=
0
;
uint16_t
gtp_payload_size
=
0
;
...
@@ -730,57 +433,78 @@ _gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_p
...
@@ -730,57 +433,78 @@ _gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_p
skb_p
->
priority
=
rt_tos2priority
(
iph2_p
->
tos
);
skb_p
->
priority
=
rt_tos2priority
(
iph2_p
->
tos
);
skb_p
->
pkt_type
=
PACKET_OTHERHOST
;
skb_p
->
pkt_type
=
PACKET_OTHERHOST
;
skb_dst_drop
(
skb_p
);
skb_dst_drop
(
skb_p
);
skb_dst_set
(
skb_p
,
&
rt
->
dst
);
skb_dst_set
(
skb_p
,
dst_clone
(
&
rt
->
dst
)
);
skb_p
->
dev
=
skb_dst
(
skb_p
)
->
dev
;
skb_p
->
dev
=
skb_dst
(
skb_p
)
->
dev
;
}
#if defined(NEW_SKB)
#if defined(NEW_SKB)
new_skb_p
=
alloc_skb
(
LL_MAX_HEADER
+
ntohs
(
iph2_p
->
tot_len
),
GFP_ATOMIC
);
new_skb_p
=
alloc_skb
(
LL_MAX_HEADER
+
ntohs
(
iph2_p
->
tot_len
),
GFP_ATOMIC
);
if
(
new_skb_p
==
NULL
)
{
if
(
new_skb_p
==
NULL
)
{
return
NF_DROP
;
return
NF_DROP
;
}
}
skb_reserve
(
new_skb_p
,
LL_MAX_HEADER
);
skb_reserve
(
new_skb_p
,
LL_MAX_HEADER
);
new_skb_p
->
protocol
=
skb_p
->
protocol
;
new_skb_p
->
protocol
=
skb_p
->
protocol
;
skb_reset_network_header
(
new_skb_p
);
skb_reset_network_header
(
new_skb_p
);
new_ip_p
=
(
void
*
)
skb_put
(
new_skb_p
,
iph2_p
->
ihl
<<
2
);
new_ip_p
=
(
void
*
)
skb_put
(
new_skb_p
,
iph2_p
->
ihl
<<
2
);
skb_reset_transport_header
(
new_skb_p
);
skb_reset_transport_header
(
new_skb_p
);
skb_put
(
new_skb_p
,
ntohs
(
iph2_p
->
tot_len
)
-
(
iph2_p
->
ihl
<<
2
));
skb_put
(
new_skb_p
,
ntohs
(
iph2_p
->
tot_len
)
-
(
iph2_p
->
ihl
<<
2
));
memcpy
(
new_ip_p
,
iph2_p
,
ntohs
(
iph2_p
->
tot_len
));
memcpy
(
new_ip_p
,
iph2_p
,
ntohs
(
iph2_p
->
tot_len
));
new_skb_p
->
mark
=
ntohl
(
gtpuh_p
->
tunid
);
new_skb_p
->
mark
=
ntohl
(
gtpuh_p
->
tunid
);
//new_skb_p->mark = skb_p->mark;
//new_skb_p->mark = skb_p->mark;
/* ip_route_me_harder expects skb->dst to be set */
/* ip_route_me_harder expects skb->dst to be set */
skb_dst_set
(
new_skb_p
,
dst_clone
(
skb_dst
(
skb_p
)));
skb_dst_set
(
new_skb_p
,
dst_clone
(
skb_dst
(
skb_p
)));
if
(
ip_route_me_harder
(
new_skb_p
,
RTN_UNSPEC
)
<
0
)
/*if (ip_route_me_harder(new_skb_p, RTN_UNSPEC) < 0) {
goto
free_new_skb
;
pr_info("GTPURH: cannot route harder dest 0x%x\n", daddr);
goto free_skb;
}*/
new_ip_p
->
ttl
=
ip4_dst_hoplimit
(
skb_dst
(
new_skb_p
));
new_ip_p
->
ttl
=
new_ip_p
->
ttl
-
1
;
//
ip4_dst_hoplimit(skb_dst(new_skb_p));
new_skb_p
->
ip_summed
=
CHECKSUM_NONE
;
new_skb_p
->
ip_summed
=
CHECKSUM_NONE
;
/* "Never happens" (?) */
if
(
new_skb_p
->
len
>
dst_mtu
(
skb_dst
(
new_skb_p
)))
{
if
(
new_skb_p
->
len
>
dst_mtu
(
skb_dst
(
new_skb_p
)))
pr_info
(
"GTPURH: bad length
\n
"
);
goto
free_new_skb
;
goto
free_skb
;
}
nf_ct_attach
(
new_skb_p
,
skb_p
);
nf_ct_attach
(
new_skb_p
,
skb_p
);
ip_local_out
(
new_skb_p
);
pr_info
(
"GTPURH: ip_local_out %s/%s dev %s src %u.%u.%u.%u dst %u.%u.%u.%u
\n
"
,
return
NF_DROP
;
_gtpurh_nf_inet_hook_2_string
(
par_pP
->
hooknum
),
gtpurh_tg_reg
[
0
].
table
,
(
new_skb_p
->
dev
==
NULL
)
?
"NULL"
:
new_skb_p
->
dev
->
name
,
NIPADDR
(
new_ip_p
->
saddr
),
NIPADDR
(
new_ip_p
->
daddr
));
ip_local_out
(
new_skb_p
);
return
NF_DROP
;
free_skb:
pr_info
(
"GTPURH: Dropped skb ip_local_out %s/%s
\n
"
,
_gtpurh_nf_inet_hook_2_string
(
par_pP
->
hooknum
),
gtpurh_tg_reg
[
0
].
table
);
kfree_skb
(
new_skb_p
);
return
NF_DROP
;
free_new_skb:
kfree_skb
(
new_skb_p
);
return
NF_DROP
;
#else
#else
return
NF_ACCEPT
;
return
NF_ACCEPT
;
free_skb:
pr_info
(
"GTPURH: Dropped skb
\n
"
);
kfree_skb
(
skb_p
);
return
NF_DROP
;
#endif
#endif
}
#endif
#endif
}
}
#if defined(WITH_IPV6)
//-----------------------------------------------------------------------------
static
unsigned
int
static
unsigned
int
gtpurh_tg6
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
gtpurh_tg6
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
//-----------------------------------------------------------------------------
{
{
const
struct
xt_gtpurh_target_info
*
tgi_p
=
par_pP
->
targinfo
;
const
struct
xt_gtpurh_target_info
*
tgi_p
=
par_pP
->
targinfo
;
int
result
=
NF_DROP
;
int
result
=
NF_DROP
;
...
@@ -794,60 +518,70 @@ gtpurh_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
...
@@ -794,60 +518,70 @@ gtpurh_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
}
}
return
result
;
return
result
;
}
}
#endif
//-----------------------------------------------------------------------------
static
unsigned
int
static
unsigned
int
gtpurh_tg4
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
gtpurh_tg4
(
struct
sk_buff
*
skb_pP
,
const
struct
xt_action_param
*
par_pP
)
//-----------------------------------------------------------------------------
{
{
const
struct
iphdr
*
iph_p
=
ip_hdr
(
skb_pP
);
const
struct
rtable
*
rt_p
=
skb_rtable
(
skb_pP
);
const
struct
xt_gtpurh_target_info
*
tgi_p
=
par_pP
->
targinfo
;
const
struct
xt_gtpurh_target_info
*
tgi_p
=
par_pP
->
targinfo
;
int
result
=
NF_ACCEPT
;
if
(
tgi_p
==
NULL
)
{
if
(
tgi_p
==
NULL
)
{
return
result
;
return
NF_ACCEPT
;
}
if
((
tgi_p
->
raddr
!=
iph_p
->
saddr
)
||
(
tgi_p
->
laddr
!=
iph_p
->
daddr
))
{
pr_info
(
"GTPURH: Not processed because of not matching saddr %d.%d.%d.%d raddr %d.%d.%d.%d laddr %d.%d.%d.%d daddr %d.%d.%d.%d
\n
"
,
NIPADDR
(
tgi_p
->
raddr
),
NIPADDR
(
iph_p
->
saddr
),
NIPADDR
(
tgi_p
->
laddr
),
NIPADDR
(
iph_p
->
daddr
));
return
NF_ACCEPT
;
}
if
(
ip_hdrlen
(
skb_pP
)
!=
sizeof
(
struct
iphdr
))
{
pr_info
(
"GTPURH: Dropped because IP options
\n
"
);
return
NF_DROP
;
}
// Drop fragments
if
(
iph_p
->
frag_off
&
htons
(
IP_OFFSET
))
{
pr_info
(
"GTPURH: Dropped because is fragment
\n
"
);
return
NF_DROP
;
}
}
if
(
tgi_p
->
action
==
PARAM_GTPURH_ACTION_REM
)
{
if
(
tgi_p
->
action
==
PARAM_GTPURH_ACTION_REM
)
{
re
sult
=
_gtpurh_tg4_rem
(
skb_pP
,
par_pP
);
re
turn
_gtpurh_tg4_rem
(
skb_pP
,
par_pP
);
}
}
return
result
;
return
NF_DROP
;
}
}
static
struct
xt_target
gtpurh_tg_reg
[]
__read_mostly
=
{
{
.
name
=
"GTPURH"
,
.
revision
=
0
,
.
family
=
NFPROTO_IPV6
,
.
proto
=
IPPROTO_UDP
,
.
table
=
"raw"
,
.
target
=
gtpurh_tg6
,
.
me
=
THIS_MODULE
,
},
{
.
name
=
"GTPURH"
,
.
revision
=
0
,
.
family
=
NFPROTO_IPV4
,
.
hooks
=
(
1
<<
NF_INET_PRE_ROUTING
)
|
(
1
<<
NF_INET_LOCAL_OUT
),
.
proto
=
IPPROTO_UDP
,
.
table
=
"raw"
,
.
target
=
gtpurh_tg4
,
.
targetsize
=
sizeof
(
struct
xt_gtpurh_target_info
),
.
me
=
THIS_MODULE
,
},
};
static
int
__init
gtpurh_tg_init
(
void
)
//-----------------------------------------------------------------------------
{
static
int
__init
gtpurh_tg_init
(
void
)
{
//-----------------------------------------------------------------------------
pr_info
(
"GTPURH: Initializing module (KVersion: %d)
\n
"
,
KVERSION
);
pr_info
(
"GTPURH: Initializing module (KVersion: %d)
\n
"
,
KVERSION
);
pr_info
(
"GTPURH: Copyright Polaris Networks 2010-2011
\n
"
);
pr_info
(
"GTPURH: Copyright Polaris Networks 2010-2011
\n
"
);
pr_info
(
"GTPURH: Modified by EURECOM Lionel GAUTHIER 2014
\n
"
);
pr_info
(
"GTPURH: Modified by EURECOM Lionel GAUTHIER 2014
\n
"
);
//hash_init(ip_fragments);
#if defined(WITH_IPV6)
pr_info
(
"GTPURH: IPv4/IPv6 enabled
\n
"
);
#else
pr_info
(
"GTPURH: IPv4 only enabled
\n
"
);
#endif
return
xt_register_targets
(
gtpurh_tg_reg
,
ARRAY_SIZE
(
gtpurh_tg_reg
));
return
xt_register_targets
(
gtpurh_tg_reg
,
ARRAY_SIZE
(
gtpurh_tg_reg
));
}
}
static
void
__exit
gtpurh_tg_exit
(
void
)
//-----------------------------------------------------------------------------
{
static
void
__exit
gtpurh_tg_exit
(
void
)
{
//-----------------------------------------------------------------------------
xt_unregister_targets
(
gtpurh_tg_reg
,
ARRAY_SIZE
(
gtpurh_tg_reg
));
xt_unregister_targets
(
gtpurh_tg_reg
,
ARRAY_SIZE
(
gtpurh_tg_reg
));
//_gtpurh_delete_collection_ip_fragments();
pr_info
(
"GTPURH: Unloading module
\n
"
);
pr_info
(
"GTPURH: Unloading module
\n
"
);
}
}
...
...
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