@@ -159,13 +159,47 @@ struct gre_header {
159
159
__u16 protocol ;
160
160
};
161
161
162
+ #define GTP_MSG_TPDU 0xFF
163
+
164
+ struct gtp_header {
165
+ #if defined(__LITTLE_ENDIAN_BITFIELD )
166
+ u_int16_t n_pdu :1 ,
167
+ sequence :1 ,
168
+ extension :1 ,
169
+ reserved :1 ,
170
+ protocol :1 ,
171
+ version :3 ,
172
+ type :8 ;
173
+ #elif defined(__BIG_ENDIAN_BITFIELD )
174
+ u_int16_t version :3 ,
175
+ protocol :1 ,
176
+ reserved :1 ,
177
+ extension :1 ,
178
+ sequence :1 ,
179
+ n_pdu :1 ,
180
+ type :8 ;
181
+ #else
182
+ #error "Adjust your <asm/byteorder.h> defines"
183
+ #endif
184
+ u_int16_t total_length ;
185
+ u_int32_t teid ;
186
+ };
187
+
188
+ struct gtp_header_optional {
189
+ u_int16_t sn ;
190
+ u_int8_t n_pdu_nbr ;
191
+ u_int8_t next_hdr ;
192
+ };
193
+
194
+
162
195
struct m_pkt {
163
196
unsigned char * raw_data ;
164
197
struct pcap_pkthdr header ;
165
198
166
199
int l2_offset ;
167
200
int prev_l3_offset ;
168
201
u_int16_t prev_l3_proto ;
202
+ int gtp_offset ;
169
203
int l3_offset ;
170
204
u_int16_t l3_proto ;
171
205
int l4_offset ;
@@ -708,6 +742,136 @@ static int dissect_l4(struct m_pkt *p)
708
742
}
709
743
return 0 ;
710
744
}
745
+ static int is_gtp_u (unsigned char * gtp_buffer , int gtp_buffer_len ,
746
+ const struct m_pkt * p , u_int16_t * l3_proto )
747
+ {
748
+ struct gtp_header * gtp_h ;
749
+ struct udphdr * udp_h ;
750
+ uint16_t new_layer_len = 0 ;
751
+ unsigned char sub_proto ;
752
+
753
+ if (p -> l4_proto != IPPROTO_UDP ||
754
+ gtp_buffer_len < (int )sizeof (struct gtp_header ))
755
+ return 0 ;
756
+
757
+ /* Only default port */
758
+ udp_h = (struct udphdr * )(p -> raw_data + p -> l4_offset );
759
+ if (udp_h -> source != htons (2152 ) &&
760
+ udp_h -> dest != htons (2152 ))
761
+ return 0 ;
762
+
763
+ gtp_h = (struct gtp_header * )gtp_buffer ;
764
+
765
+ if (gtp_h -> version != 1 ||
766
+ gtp_h -> type != GTP_MSG_TPDU ||
767
+ gtp_h -> reserved != 0 ||
768
+ ntohs (gtp_h -> total_length ) > (gtp_buffer_len - sizeof (struct gtp_header ))) {
769
+ ddbg ("Invalid gtp header: %d, 0x%x, 0x%0x, %d vs %d\n" ,
770
+ gtp_h -> version , gtp_h -> type , gtp_h -> reserved ,
771
+ ntohs (gtp_h -> total_length ), gtp_buffer_len );
772
+ return 0 ;
773
+ }
774
+
775
+ new_layer_len = sizeof (struct gtp_header );
776
+
777
+ /* Optional header version 1 */
778
+ if (gtp_h -> extension || gtp_h -> sequence || gtp_h -> n_pdu ) {
779
+ new_layer_len += sizeof (struct gtp_header_optional );
780
+
781
+ if (gtp_buffer_len < new_layer_len )
782
+ return 0 ;
783
+ }
784
+ if (gtp_h -> extension ) {
785
+ unsigned int length = 0 ;
786
+
787
+ while (new_layer_len < (gtp_buffer_len - 1 )) {
788
+ length = gtp_buffer [new_layer_len ] << 2 ;
789
+ new_layer_len += length ;
790
+ if (new_layer_len > gtp_buffer_len ||
791
+ gtp_buffer [new_layer_len - 1 ] == 0 || length == 0 )
792
+ break ;
793
+ }
794
+ if (new_layer_len > gtp_buffer_len ||
795
+ gtp_buffer [new_layer_len - 1 ] != 0 ||
796
+ length == 0 ) {
797
+ return 0 ;
798
+ }
799
+ }
800
+
801
+ /* Trying to detect next proto. Code taken from wireshark */
802
+ if (gtp_buffer_len < new_layer_len + 1 )
803
+ return 0 ;
804
+ sub_proto = gtp_buffer [new_layer_len ];
805
+ if ((sub_proto >= 0x45 ) && (sub_proto <= 0x4e )) {
806
+ /* This is most likely an IPv4 packet
807
+ * we can exclude 0x40 - 0x44 because the minimum header size is 20 octets
808
+ * 0x4f is excluded because PPP protocol type "IPv6 header compression"
809
+ * with protocol field compression is more likely than a plain
810
+ * IPv4 packet with 60 octet header size */
811
+ * l3_proto = ETH_P_IP ;
812
+ } else if ((sub_proto & 0xf0 ) == 0x60 ) {
813
+ /* This is most likely an IPv6 packet */
814
+ * l3_proto = ETH_P_IPV6 ;
815
+ } else {
816
+ /* This seems to be a PPP packet */
817
+ /* TODO: code not back-ported from wireshark yet*/
818
+ return 0 ;
819
+ }
820
+
821
+ return new_layer_len ;
822
+ }
823
+ static int dissect_l4_detunneling (struct m_pkt * p )
824
+ {
825
+ unsigned char * data = p -> raw_data + p -> l5_offset ;
826
+ int data_len = p -> header .caplen - p -> l5_offset ;
827
+ u_int16_t next_l3_proto ;
828
+ int gtp_header_len , rc ;
829
+
830
+ ddbg ("L4(detunel): l4_proto %d data_len %d l5_length %d\n" ,
831
+ p -> l4_proto , data_len , p -> l5_length );
832
+
833
+ if (data_len < 0 || p -> l5_length > data_len )
834
+ return -1 ;
835
+
836
+ /* TODO: try to handle tunnel over fragment */
837
+ if (p -> is_l3_fragment ) {
838
+ ddbg ("Skip L4(detunnel) dissection because it is a fragment\n" );
839
+ return 0 ;
840
+ }
841
+ /* No reasons to detunnel if we skipped L4 dissection */
842
+ if (p -> skip_l4_dissection ) {
843
+ ddbg ("Skip L4 dissection\n" );
844
+ return 0 ;
845
+ }
846
+
847
+ /* GTP detunneling: looking only for MSG T-PDU that carries
848
+ encapsulated data */
849
+ gtp_header_len = is_gtp_u (data , data_len , p , & next_l3_proto );
850
+ if (gtp_header_len > 0 ) {
851
+ ddbg ("Found GTP-U\n" );
852
+ if (p -> prev_l3_proto == 0 ) {
853
+ assert (p -> prev_l3_offset == 0 );
854
+ p -> prev_l3_proto = p -> l3_proto ;
855
+ p -> prev_l3_offset = p -> l3_offset ;
856
+ } else {
857
+ derr ("Multiple tunnels. Unsupported\n" );
858
+ return -1 ;
859
+ }
860
+ assert (p -> gtp_offset == 0 );
861
+ p -> gtp_offset = p -> l5_offset ;
862
+ p -> l3_proto = next_l3_proto ;
863
+ p -> l3_offset = p -> l5_offset + gtp_header_len ;
864
+ rc = dissect_l3 (p );
865
+ if (rc != 0 ) {
866
+ derr ("Error dissect_l3 (after gtp)\n" );
867
+ return -1 ;
868
+ }
869
+ return dissect_l4 (p );
870
+ }
871
+
872
+ /* "Normal" L4 traffic */
873
+ return 0 ;
874
+ }
711
875
static int dissect_do (int datalink_type , struct m_pkt * p )
712
876
{
713
877
int rc ;
@@ -727,6 +891,12 @@ static int dissect_do(int datalink_type, struct m_pkt *p)
727
891
derr ("Error dissect_l4\n" );
728
892
return -1 ;
729
893
}
894
+ /* Some kind of detunneling over L4 (usually over UDP). Example: GTP */
895
+ rc = dissect_l4_detunneling (p );
896
+ if (rc != 0 ) {
897
+ derr ("Error dissect_l5\n" );
898
+ return -1 ;
899
+ }
730
900
return 0 ;
731
901
}
732
902
@@ -792,6 +962,7 @@ static void update_do_l7(struct m_pkt *p)
792
962
{
793
963
struct udphdr * udp_h ;
794
964
struct tcphdr * tcp_h ;
965
+ struct gtp_header * gtp_h ;
795
966
size_t new_l5_len ;
796
967
int l4_header_len = 0 ;
797
968
int l5_len_diff ;
@@ -857,6 +1028,16 @@ static void update_do_l7(struct m_pkt *p)
857
1028
ip6 -> ip6_plen = htons (ntohs (ip6 -> ip6_plen ) + l5_len_diff );
858
1029
}
859
1030
1031
+ /* Update GTP header */
1032
+ if (p -> gtp_offset ) {
1033
+ gtp_h = (struct gtp_header * )(p -> raw_data + p -> gtp_offset );
1034
+ gtp_h -> total_length = htons (ntohs (gtp_h -> total_length ) + l5_len_diff );
1035
+ /* Update previous UDP header */
1036
+ assert (p -> gtp_offset > (int )sizeof (struct udphdr ));
1037
+ udp_h = (struct udphdr * )(p -> raw_data + p -> gtp_offset - sizeof (struct udphdr ));
1038
+ udp_h -> len = htons (ntohs (udp_h -> len ) + l5_len_diff );
1039
+ }
1040
+
860
1041
p -> l5_length = new_l5_len ;
861
1042
ddbg ("cap_len %u->%zu\n" , p -> header .caplen , p -> l5_offset + new_l5_len );
862
1043
p -> header .caplen = p -> l5_offset + new_l5_len ;
@@ -955,6 +1136,7 @@ static struct m_pkt *__dup_pkt(struct m_pkt *p)
955
1136
n -> l2_offset = p -> l2_offset ;
956
1137
n -> prev_l3_offset = p -> prev_l3_offset ;
957
1138
n -> prev_l3_proto = p -> prev_l3_proto ;
1139
+ n -> gtp_offset = p -> gtp_offset ;
958
1140
n -> l4_offset = p -> l4_offset ;
959
1141
n -> l3_offset = p -> l3_offset ;
960
1142
n -> l3_proto = p -> l3_proto ;
0 commit comments