Commit 5109cd00 authored by Lionel Gauthier's avatar Lionel Gauthier

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6117 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent ff1913f8
...@@ -157,12 +157,14 @@ static inline void hash_del_rcu(struct hlist_node *node) ...@@ -157,12 +157,14 @@ static inline void hash_del_rcu(struct hlist_node *node)
* @name: hashtable to iterate * @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor * @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry * @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 * @member: the name of the hlist_node within the struct
*/ */
#define hash_for_each(name, bkt, obj, member) \ #define hash_for_each(name, bkt, obj, pos, member) \
for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\ for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
(bkt)++)\ (bkt)++)\
hlist_for_each_entry(obj, &name[bkt], member) hlist_for_each_entry(obj, pos, &name[bkt], member)
/** /**
* hash_for_each_rcu - iterate over a rcu enabled hashtable * hash_for_each_rcu - iterate over a rcu enabled hashtable
...@@ -247,12 +249,6 @@ static inline void hash_del_rcu(struct hlist_node *node) ...@@ -247,12 +249,6 @@ static inline void hash_del_rcu(struct hlist_node *node)
#endif #endif
struct gtpuhdr struct gtpuhdr
{ {
char flags; char flags;
...@@ -275,8 +271,8 @@ struct gtpuhdr ...@@ -275,8 +271,8 @@ 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 { /*typedef struct ip_fragment_entry_s {
struct sk_buff *skb; struct sk_buff *skb_p;
//struct timeval first_ts; // TO DO WITH IP_FRAG_TIME //struct timeval first_ts; // TO DO WITH IP_FRAG_TIME
int flags; //ip header field int flags; //ip header field
int offset; //ip header field int offset; //ip header field
...@@ -286,17 +282,20 @@ typedef struct ip_fragment_entry_s { ...@@ -286,17 +282,20 @@ typedef struct ip_fragment_entry_s {
typedef struct ip_reassembly_entry_s { typedef struct ip_reassembly_entry_s {
}ip_reassembly_entry_t; }ip_reassembly_entry_t;
*/
static inline bool _gtpurh_ip_is_fragment(const struct iphdr *iph_p)
{
#define MAX_IP_FRAGMENTS 16; return (iph_p->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
}
#define MAX_IP_FRAGMENTS 16
#define GTPURH_HASHTABLE_BITS 7 #define GTPURH_HASHTABLE_BITS 7
DEFINE_HASHTABLE(ip_fragments, GTPURH_HASHTABLE_BITS); DEFINE_HASHTABLE(ip_fragments, GTPURH_HASHTABLE_BITS);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP) void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
unsigned long octet_index = 0; unsigned long octet_index = 0;
...@@ -306,7 +305,10 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP) ...@@ -306,7 +305,10 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP)
char timeofday[64]; char timeofday[64];
unsigned int h,m,s; unsigned int h,m,s;
if (dataP == NULL) { if (data_pP == NULL) {
return;
}
if (sizeP > 2000) {
return; return;
} }
...@@ -319,17 +321,19 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP) ...@@ -319,17 +321,19 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP)
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday);
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
pr_info("%s",_gtpurh_print_buffer);buffer_marker = 0;
for (octet_index = 0; octet_index < sizeP; octet_index++) { for (octet_index = 0; octet_index < sizeP; octet_index++) {
if ((octet_index % 16) == 0){ if ((octet_index % 16) == 0){
if (octet_index != 0) { if (octet_index != 0) {
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
pr_info("%s",_gtpurh_print_buffer);buffer_marker = 0;
} }
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index);
} }
/* /*
* Print every single octet in hexadecimal form * Print every single octet in hexadecimal form
*/ */
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " %02x", dataP[octet_index]); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " %02x", data_pP[octet_index]);
/* /*
* Align newline and pipes according to the octets in groups of 2 * Align newline and pipes according to the octets in groups of 2
*/ */
...@@ -346,17 +350,18 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP) ...@@ -346,17 +350,18 @@ void _gtpurh_print_hex_octets(unsigned char* dataP, unsigned short sizeP)
} }
static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_target_info *info) #if defined(ROUTE_PACKET)
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;
struct iphdr *iph = ip_hdr(skb); struct iphdr *iph_p = ip_hdr(skb_pP);
int daddr = iph->daddr; int daddr = iph_p->daddr;
struct flowi fl = { struct flowi fl = {
.u = { .u = {
.ip4 = { .ip4 = {
.daddr = daddr, .daddr = daddr,
.flowi4_tos = RT_TOS(iph->tos), .flowi4_tos = RT_TOS(iph_p->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE, .flowi4_scope = RT_SCOPE_UNIVERSE,
} }
} }
...@@ -364,18 +369,18 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar ...@@ -364,18 +369,18 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar
#if 0 #if 0
pr_info("GTPURH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u\n", pr_info("GTPURH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u\n",
info->action, info_pP->action,
iph->saddr & 0xFF, iph_p->saddr & 0xFF,
(iph->saddr & 0x0000FF00) >> 8, (iph_p->saddr & 0x0000FF00) >> 8,
(iph->saddr & 0x00FF0000) >> 16, (iph_p->saddr & 0x00FF0000) >> 16,
iph->saddr >> 24, iph_p->saddr >> 24,
iph->daddr & 0xFF, iph_p->daddr & 0xFF,
(iph->daddr & 0x0000FF00) >> 8, (iph_p->daddr & 0x0000FF00) >> 8,
(iph->daddr & 0x00FF0000) >> 16, (iph_p->daddr & 0x00FF0000) >> 16,
iph->daddr >> 24, iph_p->daddr >> 24,
iph->protocol, iph_p->protocol,
ntohs(iph->tot_len), ntohs(iph_p->tot_len),
skb->mark); skb_pP->mark);
#endif #endif
rt = ip_route_output_key(&init_net, &fl.u.ip4); rt = ip_route_output_key(&init_net, &fl.u.ip4);
...@@ -396,17 +401,17 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar ...@@ -396,17 +401,17 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar
} }
#endif #endif
//if (info->action == PARAM_GTPURH_ACTION_ADD) //LG was commented //if (info_pP->action == PARAM_GTPURH_ACTION_ADD) //LG was commented
{ {
skb_dst_drop(skb); skb_dst_drop(skb_pP);
skb_dst_set(skb, &rt->dst); skb_dst_set(skb_pP, &rt->dst);
skb->dev = skb_dst(skb)->dev; skb_pP->dev = skb_dst(skb_pP)->dev;
} }
skb->protocol = htons(ETH_P_IP); skb_pP->protocol = htons(ETH_P_IP);
/* Send the GTPu message out...gggH */ /* Send the GTPu message out...gggH */
err = dst_output(skb); err = dst_output(skb_pP);
if (err == 0) if (err == 0)
{ {
...@@ -417,14 +422,30 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar ...@@ -417,14 +422,30 @@ static bool _gtpurh_route_packet(struct sk_buff *skb, const struct xt_gtpurh_tar
return GTPURH_FAILURE; return GTPURH_FAILURE;
} }
} }
#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 void static int
_gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_target_info *tgi) _gtpurh_target_reassembly(struct sk_buff *orig_skb_pP, const struct xt_gtpurh_target_info *tgi_pP)
{ {
struct iphdr *iph = ip_hdr(orig_skb); struct iphdr *iph_p = ip_hdr(orig_skb_pP);
struct sk_buff *skb = NULL; struct sk_buff *skb_p = NULL;
struct sk_buff *new_skb = NULL; struct sk_buff *new_skb_p = NULL;
uint16_t key = 0; uint16_t key = 0;
int flags, offset, last_frag_offset; int flags, offset, last_frag_offset;
int ihl, end; int ihl, end;
...@@ -432,19 +453,22 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe ...@@ -432,19 +453,22 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe
struct hlist_node *pos_p = NULL; struct hlist_node *pos_p = NULL;
int all_segments_availables = 1; int all_segments_availables = 1;
offset = ntohs(iph->frag_off); if ((orig_skb_pP) && (tgi_pP)) {
offset = ntohs(iph_p->frag_off);
flags = offset & ~IP_OFFSET; flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET; /* offset is in 8-byte chunks */ offset &= IP_OFFSET; // offset is in 8-byte chunks
offset <<= 3; offset <<= 3;
ihl = ip_hdrlen(skb); ihl = ip_hdrlen(orig_skb_pP);
end = offset + skb->len - ihl; end = offset + orig_skb_pP->len - ihl;
key = iph->id; key = iph_p->id;
/* Is this the final fragment? */ 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) { if ((flags & IP_MF) == 0) {
pr_info("GTPURH: try reassembly last segment id %u len %u offset %u end %u\n", pr_info("GTPURH: try reassembly last segment id %u len %u offset %u end %u\n",
key,orig_skb->len, offset, end); key,orig_skb_pP->len, offset, end);
// may be the last segment received // may be the last segment received
// normally iterator gives elements from head to tail, but elements // normally iterator gives elements from head to tail, but elements
// have been inserted at the head, so iterator should retrieve fragments // have been inserted at the head, so iterator should retrieve fragments
...@@ -452,7 +476,7 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe ...@@ -452,7 +476,7 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe
last_frag_offset = offset; last_frag_offset = offset;
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) { 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", pr_info("GTPURH: try reassembly segment id %u len %u offset %u end %u\n",
key,ip_fragment_p->skb->len, ip_fragment_p->offset, ip_fragment_p->end); key,ip_fragment_p->skb_p->len, ip_fragment_p->offset, ip_fragment_p->end);
if (ip_fragment_p->end == offset) { if (ip_fragment_p->end == offset) {
offset = ip_fragment_p->offset; offset = ip_fragment_p->offset;
} else { } else {
...@@ -464,175 +488,213 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe ...@@ -464,175 +488,213 @@ _gtpurh_target_reassembly(struct sk_buff *orig_skb, const struct xt_gtpurh_targe
} }
if (all_segments_availables) { if (all_segments_availables) {
// not optimal, but optimize later // not optimal, but optimize later
new_skb = skb_copy_expand(orig_skb, new_skb_p = skb_copy_expand(orig_skb_pP,
last_frag_offset + skb_headroom(orig_skb), last_frag_offset + skb_headroom(orig_skb_pP),
skb_tailroom(orig_skb), skb_tailroom(orig_skb_pP),
GFP_ATOMIC); GFP_ATOMIC);
if (new_skb != NULL) if (new_skb_p != NULL)
{ {
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) { hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) {
skb = ip_fragment_p->skb; skb_p = ip_fragment_p->skb_p;
skb_pull(new_skb, ihl); skb_pull(new_skb_p, ihl);
pr_info("GTPURH: reassembly segment id %u len %u offset %u end %u\n", pr_info("GTPURH: reassembly segment id %u len %u offset %u end %u\n",
key, skb->len, ip_fragment_p->offset, ip_fragment_p->end); key, skb_p->len, ip_fragment_p->offset, ip_fragment_p->end);
iph = (struct iphdr*)skb_push(new_skb, skb->len); iph_p = (struct iphdr*)skb_push(new_skb_p, skb_p->len);
ihl = ip_hdrlen(skb); ihl = ip_hdrlen(skb_p);
memcpy(iph, skb_network_header(skb), skb->len); memcpy(iph_p, skb_network_header(skb_p), skb_p->len);
} }
skb_set_network_header(new_skb, 0); skb_set_network_header(new_skb_p, 0);
if (_gtpurh_route_packet(new_skb, tgi) != GTPURH_SUCCESS) if (_gtpurh_route_packet(new_skb_p, tgi_pP) != GTPURH_SUCCESS)
{ {
kfree_skb(new_skb); kfree_skb(new_skb_p);
} }
} else { } else {
pr_info("GTPURH: Failed in skb allocation (%u bytes)\n", pr_info("GTPURH: Failed in skb_p allocation (%u bytes)\n",
last_frag_offset + skb_headroom(orig_skb)); last_frag_offset + skb_headroom(orig_skb_pP));
} }
} }
if (1) { if (1) {
hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) { hash_for_each_possible(ip_fragments, ip_fragment_p, pos_p, node, key) {
kfree_skb(ip_fragment_p->skb); kfree_skb(ip_fragment_p->skb_p);
hash_del(pos_p); hash_del(pos_p);
kfree(ip_fragment_p); kfree(ip_fragment_p);
} }
} }
} else { } else {
pr_info("GTPURH: but in buffer not last segment id %u len %u offset %u end %u\n", pr_info("GTPURH: but in buffer not last segment id %u len %u offset %u end %u\n",
key,orig_skb->len, offset, end); key,orig_skb_pP->len, offset, end);
// not the last fragment received // not the last fragment received
// assuming no out of order // assuming no out of order
ip_fragment_p = kmalloc(sizeof(struct ip_fragment_entry_s), GFP_KERNEL); ip_fragment_p = kmalloc(sizeof(struct ip_fragment_entry_s), GFP_KERNEL);
if (NULL != ip_fragment_p) { if (NULL != ip_fragment_p) {
#if defined(ROUTE_PACKET) ip_fragment_p->skb_p = skb_copy(orig_skb_pP, GFP_ATOMIC); // may use skb_clone(), TODO
ip_fragment_p->skb = orig_skb;
#else
ip_fragment_p->skb = skb_copy(orig_skb, GFP_ATOMIC); // may use skb_clone(), TODO
#endif
ip_fragment_p->flags = flags; ip_fragment_p->flags = flags;
ip_fragment_p->offset = offset; ip_fragment_p->offset = offset;
ip_fragment_p->end = end; 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); INIT_HLIST_NODE(&ip_fragment_p->node);
hash_add(ip_fragments, &ip_fragment_p->node, key); hash_add(ip_fragments, &ip_fragment_p->node, key);
return 0;
} else { } else {
pr_info("GTPURH: ERROR could not allocate memory for buffering IP fragment\n"); 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_target_rem(struct sk_buff *orig_skb, const struct xt_gtpurh_target_info *tgi) _gtpurh_target_rem(struct sk_buff *orig_skb_pP, const struct xt_gtpurh_target_info *tgi_pP)
{ {
struct iphdr *iph = ip_hdr(orig_skb); struct iphdr *iph_p = ip_hdr(orig_skb_pP);
struct iphdr *iph2 = NULL; struct iphdr *iph2_p = NULL;
struct udphdr *udph = NULL; struct udphdr *udph_p = NULL;
struct gtpuhdr *gtpuh = NULL; struct gtpuhdr *gtpuh_p = NULL;
struct sk_buff *skb = NULL; struct sk_buff *skb_p = NULL;
uint16_t gtp_payload_size = 0; uint16_t gtp_payload_size = 0;
/* Create a new copy of the original skb...can't avoid :-( LG: WHY???*/ /* Create a new copy of the original skb_p...can't avoid :-( LG: WHY???*/
#if defined(ROUTE_PACKET) #if defined(ROUTE_PACKET)
skb = skb_copy(orig_skb, GFP_ATOMIC); skb_p = skb_copy(orig_skb_pP, GFP_ATOMIC);
if (skb == NULL) if (skb_p == NULL)
{ {
return NF_ACCEPT; return NF_ACCEPT;
} }
skb->skb_iif = orig_skb->skb_iif; skb_p->skb_iif = orig_skb_pP->skb_iif;
skb->protocol = orig_skb->protocol; skb_p->protocol = orig_skb_pP->protocol;
#else #else
skb = orig_skb; skb_p = orig_skb_pP;
#endif #endif
//---------------------------
if (ip_is_fragment(iph)) { // check if is GTPU TUNNEL
_gtpurh_target_reassembly(skb, tgi); if (iph_p->protocol != IPPROTO_UDP) {
return NF_DROP; // orig_skb is copied, original can be destroyed. pr_info("GTPURH(%d): Not GTPV1U packet (not UDP)\n",tgi_pP->action);
return NF_ACCEPT;
} }
//---------------------------
// check if is fragment
// but should not happen since MTU should have been set bigger than 1500 + GTP encap.
// TO DO later segment, but did not succeed in getting in this target all framents of an ip packet!
if (_gtpurh_ip_is_fragment(iph_p)) {
pr_info("GTPURH(%d): ip_is_fragment YES, FLAGS %04X & %04X = %04X\n",
tgi_pP->action,
iph_p->frag_off,
htons(IP_MF | IP_OFFSET),
iph_p->frag_off & htons(IP_MF | IP_OFFSET));
/*if ((rc = _gtpurh_target_reassembly(skb_p, tgi_pP)) == 0) {
return NF_DROP; // orig_skb_pP is copied, original can be destroyed.
} else {*/
return NF_ACCEPT;
//}
} /*else {
pr_info("GTPURH(%d): ip_is_fragment NO, FLAGS %04X & %04X = %04X\n",
tgi_pP->action,
iph_p->frag_off,
htons(IP_MF | IP_OFFSET),
iph_p->frag_off & htons(IP_MF | IP_OFFSET));
}*/
if (skb_p->len <= sizeof (struct udphdr) + sizeof (struct gtpuhdr) + sizeof (struct iphdr)) {
pr_info("GTPURH(%d): Thought was GTPV1U packet but too short length\n",tgi_pP->action);
return NF_ACCEPT;
}
/* Remove IP header */ /* Remove IP header */
udph = (struct udphdr*)skb_pull(skb, (iph->ihl << 2)); udph_p = (struct udphdr*)skb_pull(skb_p, (iph_p->ihl << 2));
if (iph->protocol != IPPROTO_UDP) { if (udph_p->dest != htons(GTPURH_PORT)) {
pr_info("GTPURH(%d): ERROR in decapsulating packet: %d.%d.%d.%d --> %d.%d.%d.%d Bad Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n", pr_info("GTPURH(%d): Not GTPV1U packet (bad UDP dest port)\n",tgi_pP->action);
tgi->action, skb_push(skb_p, (iph_p->ihl << 2));
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(iph2->tot_len),
skb->mark,
ntohs(iph->frag_off) & 0x1FFFFFFF,
ntohs(iph->frag_off) >> 13);
return NF_ACCEPT; return NF_ACCEPT;
} }
/* if (iph_p->protocol != IPPROTO_UDP) {
pr_info("GTPURH(%d): ERROR in decapsulating packet: %d.%d.%d.%d --> %d.%d.%d.%d Bad Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n",
tgi_pP->action,
iph_p->saddr & 0xFF,
(iph_p->saddr & 0x0000FF00) >> 8,
(iph_p->saddr & 0x00FF0000) >> 16,
iph_p->saddr >> 24,
iph_p->daddr & 0xFF,
(iph_p->daddr & 0x0000FF00) >> 8,
(iph_p->daddr & 0x00FF0000) >> 16,
iph_p->daddr >> 24,
iph_p->protocol,
ntohs(iph2_p->tot_len),
skb_p->mark,
ntohs(iph_p->frag_off) & 0x1FFFFFFF,
ntohs(iph_p->frag_off) >> 13);
return NF_ACCEPT;
}*/
/* Remove UDP header */ /* Remove UDP header */
gtpuh = (struct gtpuhdr*)skb_pull(skb, sizeof(struct udphdr)); gtpuh_p = (struct gtpuhdr*)skb_pull(skb_p, sizeof(struct udphdr));
gtp_payload_size = ntohs(gtpuh->length); gtp_payload_size = ntohs(gtpuh_p->length);
skb->mark = ntohl(gtpuh->tunid); skb_p->mark = ntohl(gtpuh_p->tunid);
/* Remove GTPu header */ /* Remove GTPu header */
skb_pull(skb, sizeof(struct gtpuhdr)); skb_pull(skb_p, sizeof(struct gtpuhdr));
/* If additional fields are present in header, remove them also */ /* If additional fields are present in header, remove them also */
if (gtpuh->flags & GTPURH_ANY_EXT_HDR_BIT) if (gtpuh_p->flags & GTPURH_ANY_EXT_HDR_BIT)
{ {
skb_pull(skb, sizeof(short) + sizeof(char) + sizeof(char)); /* #Seq, #N-PDU, #ExtHdr Type */ skb_pull(skb_p, sizeof(short) + sizeof(char) + sizeof(char)); /* #Seq, #N-PDU, #ExtHdr Type */
gtp_payload_size = gtp_payload_size - sizeof(short) - sizeof(char) - sizeof(char); gtp_payload_size = gtp_payload_size - sizeof(short) - sizeof(char) - sizeof(char);
} }
//skb->mac_len = 0; //skb_p->mac_len = 0;
//skb_set_mac_header(skb, 0); //skb_set_mac_header(skb_p, 0);
skb_set_network_header(skb, 0); skb_set_network_header(skb_p, 0);
iph2 = ip_hdr(skb); iph2_p = ip_hdr(skb_p);
skb_set_transport_header(skb, iph2->ihl << 2); skb_set_transport_header(skb_p, iph2_p->ihl << 2);
if ((iph2->version != 4 ) && (iph2->version != 6)) { if ((iph2_p->version != 4 ) && (iph2_p->version != 6)) {
pr_info("\nGTPURH: Decapsulated packet dropped because not IPvx protocol see all GTPU packet here:\n"); pr_info("\nGTPURH: Decapsulated packet dropped because not IPvx protocol see all GTPU packet here:\n");
_gtpurh_print_hex_octets((unsigned char*)iph, ntohs(iph->tot_len)); _gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
return NF_DROP; return NF_DROP;
} }
//#if 0 //#if 0
if ((skb->mark == 0) || (gtp_payload_size != ntohs(iph2->tot_len))) { if ((skb_p->mark == 0) || (gtp_payload_size != ntohs(iph2_p->tot_len))) {
pr_info("\nGTPURH(%d): Decapsulated packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n", pr_info("\nGTPURH(%d): Decapsulated 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, tgi_pP->action,
iph2->saddr & 0xFF, iph2_p->saddr & 0xFF,
(iph2->saddr & 0x0000FF00) >> 8, (iph2_p->saddr & 0x0000FF00) >> 8,
(iph2->saddr & 0x00FF0000) >> 16, (iph2_p->saddr & 0x00FF0000) >> 16,
iph2->saddr >> 24, iph2_p->saddr >> 24,
iph2->daddr & 0xFF, iph2_p->daddr & 0xFF,
(iph2->daddr & 0x0000FF00) >> 8, (iph2_p->daddr & 0x0000FF00) >> 8,
(iph2->daddr & 0x00FF0000) >> 16, (iph2_p->daddr & 0x00FF0000) >> 16,
iph2->daddr >> 24, iph2_p->daddr >> 24,
iph2->protocol, iph2_p->protocol,
ntohs(iph2->tot_len), ntohs(iph2_p->tot_len),
skb->mark, skb_p->mark,
ntohs(iph->frag_off) & 0x1FFFFFFF, ntohs(iph_p->frag_off) & 0x1FFFFFFF,
ntohs(iph->frag_off) >> 13); ntohs(iph_p->frag_off) >> 13);
if (gtp_payload_size != ntohs(iph2->tot_len)) { if (gtp_payload_size != ntohs(iph2_p->tot_len)) {
pr_info("GTPURH(%d): Mismatch in lengths GTPU length: %u -> %u, IP length %u\n", pr_info("GTPURH(%d): Mismatch in lengths GTPU length: %u -> %u, IP length %u\n",
tgi->action, tgi_pP->action,
ntohs(gtpuh->length), ntohs(gtpuh_p->length),
gtp_payload_size, gtp_payload_size,
ntohs(iph2->tot_len)); ntohs(iph2_p->tot_len));
_gtpurh_print_hex_octets((unsigned char*)iph, ntohs(iph->tot_len)); _gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
} }
} }
//#endif //#endif
/* Route the packet */ /* Route the packet */
#if defined(ROUTE_PACKET) #if defined(ROUTE_PACKET)
_gtpurh_route_packet(skb, tgi); _gtpurh_route_packet(skb_p, tgi_pP);
return NF_DROP; return NF_DROP;
#else #else
return NF_ACCEPT; return NF_ACCEPT;
...@@ -641,19 +703,19 @@ _gtpurh_target_rem(struct sk_buff *orig_skb, const struct xt_gtpurh_target_info ...@@ -641,19 +703,19 @@ _gtpurh_target_rem(struct sk_buff *orig_skb, const struct xt_gtpurh_target_info
static unsigned int static unsigned int
xt_gtpurh_target(struct sk_buff *skb, const struct xt_action_param *par) xt_gtpurh_target(struct sk_buff *skb_pP, const struct xt_action_param *par)
{ {
const struct xt_gtpurh_target_info *tgi = par->targinfo; const struct xt_gtpurh_target_info *tgi_p = par->targinfo;
int result = NF_ACCEPT; int result = NF_ACCEPT;
if (tgi == NULL) if (tgi_p == NULL)
{ {
return result; return result;
} }
if (tgi->action == PARAM_GTPURH_ACTION_REM) if (tgi_p->action == PARAM_GTPURH_ACTION_REM)
{ {
result = _gtpurh_target_rem(skb, tgi); result = _gtpurh_target_rem(skb_pP, tgi_p);
} }
return result; return result;
} }
...@@ -674,13 +736,15 @@ static int __init xt_gtpurh_init(void) ...@@ -674,13 +736,15 @@ static int __init xt_gtpurh_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");
hash_init(ip_fragments); pr_info("GTPURH: Modified by EURECOM Lionel GAUTHIER 2014\n");
//hash_init(ip_fragments);
return xt_register_target(&xt_gtpurh_reg); return xt_register_target(&xt_gtpurh_reg);
} }
static void __exit xt_gtpurh_exit(void) static void __exit xt_gtpurh_exit(void)
{ {
xt_unregister_target(&xt_gtpurh_reg); xt_unregister_target(&xt_gtpurh_reg);
//_gtpurh_delete_collection_ip_fragments();
pr_info("GTPURH: Unloading module\n"); pr_info("GTPURH: Unloading module\n");
} }
......
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