1 /****************************************************************************
2  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3  * Copyright (C) 2011-2013 Sourcefire, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License Version 2 as
7  * published by the Free Software Foundation.  You may not use, modify or
8  * distribute this program under any other version of the GNU General
9  * Public License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  *
20  ****************************************************************************
21  * Provides convenience functions for parsing and querying configuration.
22  *
23  * 7/17/2011 - Initial implementation ... Hui Cao <hcao@sourcefire.com>
24  *
25  ****************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 #include <ctype.h>
31 #include <errno.h>
32 #include "sf_types.h"
33 #include "sf_snort_packet.h"
34 #include "sfPolicy.h"
35 #include "sfPolicyUserData.h"
36 #include "gtp_config.h"
37 #include "spp_gtp.h"
38 #include "gtp_debug.h"
39 
40 #define METHOD_NOT_FOUND (-1)
41 /*
42  * Default GTP port
43  */
44 #define GTP_C_PORT	    (2123)
45 #define GTP_C_PORT_V0	(3386)
46 
47 /*
48  * Keyword strings for parsing configuration options.
49  */
50 #define GTP_PORTS_KEYWORD			     "ports"
51 
52 #define GTP_CONFIG_SECTION_SEPERATORS     ",;"
53 #define GTP_CONFIG_VALUE_SEPERATORS       " "
54 
55 /*
56  * Message type defined
57  */
58 
59 static GTP_MsgType GTPv0_MsgTypes[] =
60 {
61         {1, 1, "echo_request"},
62         {2, 1, "echo_response"},
63         {3, 1, "version_not_supported"},
64         {4, 1, "node_alive_request"},
65         {5, 1, "node_alive_response"},
66         {6, 1, "redirection_request"},
67         {7, 1, "redirection_response"},
68 
69         {16, 1,"create_pdp_context_request"},
70         {17, 1,"create_pdp_context_response"},
71         {18, 1,"update_pdp_context_request"},
72         {19, 1,"update_pdp_context_response"},
73         {20, 1,"delete_pdp_context_request"},
74         {21, 1,"delete_pdp_context_response"},
75         {22, 1,"create_aa_pdp_context_request"},
76         {23, 1,"create_aa_pdp_context_response"},
77         {24, 1,"delete_aa_pdp_context_request"},
78         {25, 1,"delete_aa_pdp_context_response"},
79         {26, 1,"error_indication"},
80         {27, 1,"pdu_notification_request"},
81         {28, 1,"pdu_notification_response"},
82         {29, 1,"pdu_notification_reject_request"},
83         {30, 1,"pdu_notification_reject_response"},
84 
85         {32, 1,"send_routing_info_request"},
86         {33, 1,"send_routing_info_response"},
87         {34, 1,"failure_report_request"},
88         {35, 1,"failure_report_response"},
89         {36, 1,"note_ms_present_request"},
90         {37, 1,"note_ms_present_response"},
91 
92         {48, 1,"identification_request"},
93         {49, 1,"identification_response"},
94         {50, 1,"sgsn_context_request"},
95         {51, 1,"sgsn_context_response"},
96         {52, 1,"sgsn_context_ack"},
97 
98         {240, 1,"data_record_transfer_request"},
99         {241, 1,"data_record_transfer_response"},
100 
101         {255, 1,"pdu"},
102         {0, 0, NULL}
103 };
104 
105 static GTP_MsgType GTPv1_MsgTypes[] =
106 {
107         {1, 1, "echo_request"},
108         {2, 1, "echo_response"},
109         {3, 1, "version_not_supported"},
110         {4, 1, "node_alive_request"},
111         {5, 1, "node_alive_response"},
112         {6, 1, "redirection_request"},
113         {7, 1, "redirection_response"},
114 
115         {16, 1,"create_pdp_context_request"},
116         {17, 1,"create_pdp_context_response"},
117         {18, 1,"update_pdp_context_request"},
118         {19, 1,"update_pdp_context_response"},
119         {20, 1,"delete_pdp_context_request"},
120         {21, 1,"delete_pdp_context_response"},
121         {22, 1,"init_pdp_context_activation_request"},
122         {23, 1,"init_pdp_context_activation_response"},
123 
124         {26, 1,"error_indication"},
125         {27, 1,"pdu_notification_request"},
126         {28, 1,"pdu_notification_response"},
127         {29, 1,"pdu_notification_reject_request"},
128         {30, 1,"pdu_notification_reject_response"},
129         {31, 1,"supported_ext_header_notification"},
130         {32, 1,"send_routing_info_request"},
131         {33, 1,"send_routing_info_response"},
132         {34, 1,"failure_report_request"},
133         {35, 1,"failure_report_response"},
134         {36, 1,"note_ms_present_request"},
135         {37, 1,"note_ms_present_response"},
136 
137         {48, 1,"identification_request"},
138         {49, 1,"identification_response"},
139         {50, 1,"sgsn_context_request"},
140         {51, 1,"sgsn_context_response"},
141         {52, 1,"sgsn_context_ack"},
142         {53, 1,"forward_relocation_request"},
143         {54, 1,"forward_relocation_response"},
144         {55, 1,"forward_relocation_complete"},
145         {56, 1,"relocation_cancel_request"},
146         {57, 1,"relocation_cancel_response"},
147         {58, 1,"forward_srns_contex"},
148         {59, 1,"forward_relocation_complete_ack"},
149         {60, 1,"forward_srns_contex_ack"},
150 
151         {70, 1,"ran_info_relay"},
152 
153         {96, 1,"mbms_notification_request"},
154         {97, 1,"mbms_notification_response"},
155         {98, 1,"mbms_notification_reject_request"},
156         {99, 1,"mbms_notification_reject_response"},
157         {100,1,"create_mbms_context_request"},
158         {101,1,"create_mbms_context_response"},
159         {102,1,"update_mbms_context_request"},
160         {103,1,"update_mbms_context_response"},
161         {104,1,"delete_mbms_context_request"},
162         {105,1,"delete_mbms_context_response"},
163 
164         {112,1,"mbms_register_request"},
165         {113,1,"mbms_register_response"},
166         {114,1,"mbms_deregister_request"},
167         {115,1,"mbms_deregister_response"},
168         {116,1,"mbms_session_start_request"},
169         {117,1,"mbms_session_start_response"},
170         {118,1,"mbms_session_stop_request"},
171         {119,1,"mbms_session_stop_response"},
172         {120,1,"mbms_session_update_request"},
173         {121,1,"mbms_session_update_response"},
174 
175         {128, 1,"ms_info_change_request"},
176         {129, 1,"ms_info_change_response"},
177 
178         {240, 1,"data_record_transfer_request"},
179         {241, 1,"data_record_transfer_response"},
180 
181         {254, 1,"end_marker"},
182         {255, 1,"pdu"},
183         {0, 0, NULL}
184 };
185 
186 static GTP_MsgType GTPv2_MsgTypes[] =
187 {
188         {1, 1, "echo_request"},
189         {2, 1, "echo_response"},
190         {3, 1, "version_not_supported"},
191 
192         {32, 1,"create_session_request"},
193         {33, 1,"create_session_response"},
194         {34, 1,"modify_bearer_request"},
195         {35, 1,"modify_bearer_response"},
196         {36, 1,"delete_session_request"},
197         {37, 1,"delete_session_response"},
198         {38, 1,"change_notification_request"},
199         {39, 1,"change_notification_response"},
200 
201         {64, 1,"modify_bearer_command"},
202         {65, 1,"modify_bearer_failure_indication"},
203         {66, 1,"delete_bearer_command"},
204         {67, 1,"delete_bearer_failure_indication"},
205         {68, 1,"bearer_resource_command"},
206         {69, 1,"bearer_resource_failure_indication"},
207         {70, 1,"downlink_failure_indication"},
208         {71, 1,"trace_session_activation"},
209         {72, 1,"trace_session_deactivation"},
210         {73, 1,"stop_paging_indication"},
211 
212         {95, 1,"create_bearer_request"},
213         {96, 1,"create_bearer_response"},
214         {97, 1,"update_bearer_request"},
215         {98, 1,"update_bearer_response"},
216         {99, 1,"delete_bearer_request"},
217         {100,1,"delete_bearer_response"},
218         {101,1,"delete_pdn_request"},
219         {102,1,"delete_pdn_response"},
220 
221         {128, 1,"identification_request"},
222         {129, 1,"identification_response"},
223         {130, 1,"sgsn_context_request"},
224         {131, 1,"sgsn_context_response"},
225         {132, 1,"sgsn_context_ack"},
226         {133, 1,"forward_relocation_request"},
227         {134, 1,"forward_relocation_response"},
228         {135, 1,"forward_relocation_complete"},
229         {136, 1,"forward_relocation_complete_ack"},
230         {137, 1,"forward_access"},
231         {138, 1,"forward_access_ack"},
232         {139, 1,"relocation_cancel_request"},
233         {140, 1,"relocation_cancel_response"},
234         {141, 1,"configuration_transfer_tunnel"},
235 
236         {149, 1,"detach"},
237         {150, 1,"detach_ack"},
238         {151, 1,"cs_paging"},
239         {152, 1,"ran_info_relay"},
240         {153, 1,"alert_mme"},
241         {154, 1,"alert_mme_ack"},
242         {155, 1,"ue_activity"},
243         {156, 1,"ue_activity_ack"},
244 
245         {160,1,"create_forward_tunnel_request"},
246         {161,1,"create_forward_tunnel_response"},
247         {162, 1,"suspend"},
248         {163, 1,"suspend_ack"},
249         {164, 1,"resume"},
250         {165, 1,"resume_ack"},
251         {166,1,"create_indirect_forward_tunnel_request"},
252         {167,1,"create_indirect_forward_tunnel_response"},
253         {168,1,"delete_indirect_forward_tunnel_request"},
254         {169,1,"delete_indirect_forward_tunnel_response"},
255         {170,1,"release_access_bearer_request"},
256         {171,1,"release_access_bearer_response"},
257 
258         {176,1,"downlink_data"},
259         {177,1,"downlink_data_ack"},
260 
261         {179,1,"pgw_restart"},
262         {180,1,"pgw_restart_ack"},
263 
264         {200,1,"update_pdn_request"},
265         {201,1,"update_pdn_response"},
266 
267         {211,1,"modify_access_bearer_request"},
268         {212,1,"modify_access_bearer_response"},
269 
270         {231,1,"mbms_session_start_request"},
271         {232,1,"mbms_session_start_response"},
272         {233,1,"mbms_session_update_request"},
273         {234,1,"mbms_session_update_response"},
274         {235,1,"mbms_session_stop_request"},
275         {236,1,"mbms_session_stop_response"},
276 
277         {0, 0, NULL}
278 };
279 
280 /*
281  * Information elements defined
282  */
283 
284 static GTP_InfoElement GTPv0_InfoElements[] =
285 {
286         {1, 1, "cause", 2},
287         {2, 1, "imsi", 9},
288         {3, 1, "rai", 7},
289         {4, 1, "tlli", 5},
290         {5, 1, "p_tmsi", 5},
291         {6, 1, "qos", 4},
292 
293         {8, 1, "recording_required", 2},
294         {9, 1, "authentication", 29},
295 
296         {11, 1, "map_cause", 2},
297         {12, 1, "p_tmsi_sig", 4},
298         {13, 1, "ms_validated", 2},
299         {14, 1, "recovery", 2},
300         {15, 1, "selection_mode", 2},
301         {16, 1, "flow_label_data_1", 3},
302         {17, 1, "flow_label_signalling", 3},
303         {18, 1, "flow_label_data_2", 4},
304         {19, 1, "ms_unreachable", 2},
305 
306         {127, 1, "charge_id", 5},
307         {128, 1, "end_user_address", 0},
308         {129, 1, "mm_context", 0},
309         {130, 1, "pdp_context", 0},
310         {131, 1, "apn", 0},
311         {132, 1, "protocol_config", 0},
312         {133, 1, "gsn", 0},
313         {134, 1, "msisdn", 0},
314 
315         {251, 1, "charging_gateway_addr", 0},
316 
317         {255, 1, "private_extension", 0},
318 
319         {0, 0, NULL, 0},
320 };
321 
322 static GTP_InfoElement GTPv1_InfoElements[] =
323 {
324         {1, 1, "cause", 2},
325         {2, 1, "imsi", 9},
326         {3, 1, "rai", 7},
327         {4, 1, "tlli", 5},
328         {5, 1, "p_tmsi", 5},
329 
330         {8, 1, "recording_required", 2},
331         {9, 1, "authentication", 29},
332 
333         {11, 1, "map_cause", 2},
334         {12, 1, "p_tmsi_sig", 4},
335         {13, 1, "ms_validated", 2},
336         {14, 1, "recovery", 2},
337         {15, 1, "selection_mode", 2},
338         {16, 1, "teid_1", 5},
339         {17, 1, "teid_control", 5},
340         {18, 1, "teid_2", 6},
341         {19, 1, "teardown_ind", 2},
342         {20, 1, "nsapi", 2},
343         {21, 1, "ranap", 2},
344         {22, 1, "rab_context", 10},
345         {23, 1, "radio_priority_sms", 2},
346         {24, 1, "radio_priority", 2},
347         {25, 1, "packet_flow_id", 3},
348         {26, 1, "charging_char", 3},
349         {27, 1, "trace_ref", 3},
350         {28, 1, "trace_type", 3},
351         {29, 1, "ms_unreachable", 2},
352 
353         {127, 1, "charge_id", 5},
354         {128, 1, "end_user_address", 0},
355         {129, 1, "mm_context", 0},
356         {130, 1, "pdp_context", 0},
357         {131, 1, "apn", 0},
358         {132, 1, "protocol_config", 0},
359         {133, 1, "gsn", 0},
360         {134, 1, "msisdn", 0},
361         {135, 1, "qos", 0},
362         {136, 1, "authentication_qu", 0},
363         {137, 1, "tft", 0},
364         {138, 1, "target_id", 0},
365         {139, 1, "utran_trans", 0},
366         {140, 1, "rab_setup", 0},
367         {141, 1, "ext_header", 0},
368         {142, 1, "trigger_id", 0},
369         {143, 1, "omc_id", 0},
370         {144, 1, "ran_trans", 0},
371         {145, 1, "pdp_context_pri", 0},
372         {146, 1, "addi_rab_setup", 0},
373         {147, 1, "sgsn_number", 0},
374         {148, 1, "common_flag", 0},
375         {149, 1, "apn_restriction", 0},
376         {150, 1, "radio_priority_lcs", 4},
377         {151, 1, "rat_type", 0},
378         {152, 1, "user_loc_info", 0},
379         {153, 1, "ms_time_zone", 0},
380         {154, 1, "imei_sv", 0},
381         {155, 1, "camel", 0},
382         {156, 1, "mbms_ue_context", 0},
383         {157, 1, "tmp_mobile_group_id", 0},
384         {158, 1, "rim_routing_addr", 0},
385         {159, 1, "mbms_config", 0},
386         {160, 1, "mbms_service_area", 0},
387         {161, 1, "src_rnc_pdcp", 0},
388         {162, 1, "addi_trace_info", 0},
389         {163, 1, "hop_counter", 0},
390         {164, 1, "plmn_id", 0},
391         {165, 1, "mbms_session_id", 0},
392         {166, 1, "mbms_2g3g_indicator", 0},
393         {167, 1, "enhanced_nsapi", 0},
394         {168, 1, "mbms_session_duration", 0},
395         {169, 1, "addi_mbms_trace_info", 0},
396         {170, 1, "mbms_session_repetition_num", 0},
397         {171, 1, "mbms_time_to_data", 0},
398 
399         {173, 1, "bss", 0},
400         {174, 1, "cell_id", 0},
401         {175, 1, "pdu_num", 0},
402         {177, 1, "mbms_bearer_capab", 0},
403         {178, 1, "rim_routing_disc", 0},
404         {179, 1, "list_pfc", 0},
405         {180, 1, "ps_xid", 0},
406         {181, 1, "ms_info_change_report", 4},
407         {182, 1, "direct_tunnel_flags", 0},
408         {183, 1, "correlation_id", 0},
409         {184, 1, "bearer_control_mode", 0},
410         {185, 1, "mbms_flow_id", 0},
411         {186, 1, "mbms_ip_multicast", 0},
412         {187, 1, "mbms_distribution_ack", 4},
413         {188, 1, "reliable_inter_rat_handover", 0},
414         {189, 1, "rfsp_index", 0},
415         {190, 1, "fqdn", 0},
416         {191, 1, "evolved_allocation1", 0},
417         {192, 1, "evolved_allocation2", 0},
418         {193, 1, "extended_flags", 0},
419         {194, 1, "uci", 0},
420         {195, 1, "csg_info", 0},
421         {196, 1, "csg_id", 0},
422         {197, 1, "cmi", 4},
423         {198, 1, "apn_ambr", 0},
424         {199, 1, "ue_network", 0},
425         {200, 1, "ue_ambr", 0},
426         {201, 1, "apn_ambr_nsapi", 0},
427         {202, 1, "ggsn_backoff_timer", 0},
428         {203, 1, "signalling_priority_indication", 0},
429         {204, 1, "signalling_priority_indication_nsapi", 0},
430         {205, 1, "high_bitrate", 4},
431         {206, 1, "max_mbr", 0},
432 
433         {251, 1, "charging_gateway_addr", 0},
434 
435         {255, 1, "private_extension", 0},
436 
437         {0, 0, NULL, 0},
438 };
439 
440 static GTP_InfoElement GTPv2_InfoElements[] =
441 {
442         {1, 1, "imsi", 0},
443         {2, 1, "cause", 0},
444         {3, 1, "recovery", 0},
445 
446         {71, 1, "apn", 0},
447         {72, 1, "ambr", 0},
448         {73, 1, "ebi", 0},
449         {74, 1, "ip_addr", 0},
450         {75, 1, "mei", 0},
451         {76, 1, "msisdn", 0},
452         {77, 1, "indication", 0},
453         {78, 1, "pco", 0},
454         {79, 1, "paa", 0},
455         {80, 1, "bearer_qos", 0},
456         {81, 1, "flow_qos", 0},
457         {82, 1, "rat_type", 0},
458         {83, 1, "serving_network", 0},
459         {84, 1, "bearer_tft", 0},
460         {85, 1, "tad", 0},
461         {86, 1, "uli", 0},
462         {87, 1, "f_teid", 0},
463         {88, 1, "tmsi", 0},
464         {89, 1, "cn_id", 0},
465         {90, 1, "s103pdf", 0},
466         {91, 1, "s1udf", 0},
467         {92, 1, "delay_value", 0},
468         {93, 1, "bearer_context", 0},
469         {94, 1, "charging_id", 0},
470         {95, 1, "charging_char", 0},
471         {96, 1, "trace_info", 0},
472         {97, 1, "bearer_flag", 0},
473 
474         {99,  1, "pdn_type", 0},
475         {100, 1, "pti", 0},
476         {101, 1, "drx_parameter", 0},
477 
478         {103, 1, "gsm_key_tri", 0},
479         {104, 1, "umts_key_cipher_quin", 0},
480         {105, 1, "gsm_key_cipher_quin", 0},
481         {106, 1, "umts_key_quin", 0},
482         {107, 1, "eps_quad", 0},
483         {108, 1, "umts_key_quad_quin", 0},
484         {109, 1, "pdn_connection", 0},
485         {110, 1, "pdn_number", 0},
486         {111, 1, "p_tmsi", 0},
487         {112, 1, "p_tmsi_sig", 0},
488         {113, 1, "hop_counter", 0},
489         {114, 1, "ue_time_zone", 0},
490         {115, 1, "trace_ref", 0},
491         {116, 1, "complete_request_msg", 0},
492         {117, 1, "guti", 0},
493         {118, 1, "f_container", 0},
494         {119, 1, "f_cause", 0},
495         {120, 1, "plmn_id", 0},
496         {121, 1, "target_id", 0},
497 
498         {123, 1, "packet_flow_id", 0},
499         {124, 1, "rab_contex", 0},
500         {125, 1, "src_rnc_pdcp", 0},
501         {126, 1, "udp_src_port", 0},
502         {127, 1, "apn_restriction", 0},
503         {128, 1, "selection_mode", 0},
504         {129, 1, "src_id", 0},
505 
506         {131, 1, "change_report_action", 0},
507         {132, 1, "fq_csid", 0},
508         {133, 1, "channel", 0},
509         {134, 1, "emlpp_pri", 0},
510         {135, 1, "node_type", 0},
511         {136, 1, "fqdn", 0},
512         {137, 1, "ti", 0},
513         {138, 1, "mbms_session_duration", 0},
514         {139, 1, "mbms_service_area", 0},
515         {140, 1, "mbms_session_id", 0},
516         {141, 1, "mbms_flow_id", 0},
517         {142, 1, "mbms_ip_multicast", 0},
518         {143, 1, "mbms_distribution_ack", 0},
519         {144, 1, "rfsp_index", 0},
520         {145, 1, "uci", 0},
521         {146, 1, "csg_info", 0},
522         {147, 1, "csg_id", 0},
523         {148, 1, "cmi", 0},
524         {149, 1, "service_indicator", 0},
525         {150, 1, "detach_type", 0},
526         {151, 1, "ldn", 0},
527         {152, 1, "node_feature", 0},
528         {153, 1, "mbms_time_to_transfer", 0},
529         {154, 1, "throttling", 0},
530         {155, 1, "arp", 0},
531         {156, 1, "epc_timer", 0},
532         {157, 1, "signalling_priority_indication", 0},
533         {158, 1, "tmgi", 0},
534         {159, 1, "mm_srvcc", 0},
535         {160, 1, "flags_srvcc", 0},
536         {161, 1, "mmbr", 0},
537 
538         {255, 1, "private_extension", 0},
539 
540         {0, 0, NULL, 0},
541 };
542 
543 
544 /*
545  * Function prototype(s)
546  */
547 static void InitGTPInfoElementTable(GTPConfig *);
548 static void DisplayGTPConfig(GTPConfig *);
549 static void GTP_ParsePortList(char **, uint8_t *);
550 
551 /* Update the information elements table for one GTP version.
552  *
553  * PARAMETERS:
554  *
555  * GTPConfig *config: GTP preprocessor configuration.
556  * GTP_InfoElement *: Information elements
557  * uint8_t: version number for information elements
558  *
559  * RETURNS: Nothing.
560  */
561 
UpdateGTPInfoElementTable(GTPConfig * config,GTP_InfoElement * InfoElements,uint8_t version)562 static void UpdateGTPInfoElementTable(GTPConfig *config, GTP_InfoElement *InfoElements, uint8_t version)
563 {
564     int i = 0;
565 
566     while(NULL != InfoElements[i].name)
567     {
568         config->infoElementTable[version][InfoElements[i].type] =  &InfoElements[i];
569         i++;
570     }
571 }
572 
573 /* Update the information elements table for the GTP preprocessor.
574  *
575  * PARAMETERS:
576  *
577  * GTPConfig *config: GTP preprocessor configuration.
578  *
579  * RETURNS: Nothing.
580  */
581 
InitGTPInfoElementTable(GTPConfig * config)582 static void InitGTPInfoElementTable(GTPConfig *config)
583 {
584 
585     GTP_InfoElement *InfoElements;
586 
587 
588     InfoElements =  GTPv0_InfoElements;
589     UpdateGTPInfoElementTable(config,InfoElements, 0);
590 
591     InfoElements =  GTPv1_InfoElements;
592     UpdateGTPInfoElementTable(config,InfoElements, 1);
593 
594     InfoElements =  GTPv2_InfoElements;
595     UpdateGTPInfoElementTable(config,InfoElements, 2);
596 
597 }
598 
599 /* Update the message types table for one GTP version.
600  *
601  * PARAMETERS:
602  *
603  * GTPConfig *config: GTP preprocessor configuration.
604  * GTP_MsgType *: message types
605  * uint8_t: version number for message types
606  *
607  * RETURNS: Nothing.
608  */
609 
UpdateGTPMsgTypeTable(GTPConfig * config,GTP_MsgType * MsgTypes,uint8_t version)610 static void UpdateGTPMsgTypeTable(GTPConfig *config, GTP_MsgType *MsgTypes, uint8_t version)
611 {
612     int i = 0;
613 
614     while(NULL != MsgTypes[i].name)
615     {
616         config->msgTypeTable[version][MsgTypes[i].type] =  &MsgTypes[i];
617         gtp_stats.msgTypeTable[version][MsgTypes[i].type] =  &MsgTypes[i];
618         i++;
619     }
620 }
621 
622 /* Update the message types table for the GTP preprocessor.
623  *
624  * PARAMETERS:
625  *
626  * GTPConfig *config: GTP preprocessor configuration.
627  *
628  * RETURNS: Nothing.
629  */
630 
InitGTPMsgTypeTable(GTPConfig * config)631 static void InitGTPMsgTypeTable(GTPConfig *config)
632 {
633 
634     GTP_MsgType *MsgTypes;
635 
636 
637     MsgTypes =  GTPv0_MsgTypes;
638     UpdateGTPMsgTypeTable(config,MsgTypes, 0);
639 
640     MsgTypes =  GTPv1_MsgTypes;
641     UpdateGTPMsgTypeTable(config,MsgTypes, 1);
642 
643     MsgTypes =  GTPv2_MsgTypes;
644     UpdateGTPMsgTypeTable(config,MsgTypes, 2);
645 
646 }
647 
648 #ifdef DEBUG_MSGS
649 /* Display the message types for the GTP preprocessor.
650  *
651  * PARAMETERS:
652  *
653  * GTPConfig *config: GTP preprocessor configuration.
654  *
655  * RETURNS: Nothing.
656  */
DisplayMsgTypes(GTPConfig * config)657 static void DisplayMsgTypes(GTPConfig *config)
658 {
659     int i, j;
660 
661     _dpd.logMsg("    Supported message types:\n");
662 
663     for(i = 0; i < MAX_GTP_TYPE_CODE + 1; i++)
664     {
665         _dpd.logMsg("\t%3d ", i);
666         for (j = 0; j < MAX_GTP_VERSION_CODE + 1; j++)
667         {
668             if (config->msgTypeTable[j][i])
669             {
670                 _dpd.logMsg("%40s ", config->msgTypeTable[j][i]->name);
671             }
672             else
673                 _dpd.logMsg("%40s ", "N/A");
674 
675         }
676         _dpd.logMsg("\n");
677     }
678 }
679 /* Display the information element for the GTP preprocessor.
680  *
681  * PARAMETERS:
682  *
683  * GTPConfig *config: GTP preprocessor configuration.
684  *
685  * RETURNS: Nothing.
686  */
DisplayInfoElements(GTPConfig * config)687 static void DisplayInfoElements(GTPConfig *config)
688 {
689     int i, j;
690 
691     _dpd.logMsg("    Supported information elements:\n");
692 
693     for(i = 0; i < MAX_GTP_IE_CODE + 1; i++)
694     {
695         _dpd.logMsg("\t%3d ", i);
696         for (j = 0; j < MAX_GTP_VERSION_CODE + 1 ; j++)
697         {
698             if (config->infoElementTable[j][i])
699                 _dpd.logMsg(" %40s ", config->infoElementTable[j][i]->name);
700             else
701                 _dpd.logMsg(" %40s ", "N/A");
702 
703         }
704         _dpd.logMsg("\n");
705     }
706 }
707 #endif
708 
709 /* Display the configuration for the GTP preprocessor.
710  *
711  * PARAMETERS:
712  *
713  * GTPConfig *config: GTP preprocessor configuration.
714  *
715  * RETURNS: Nothing.
716  */
DisplayGTPConfig(GTPConfig * config)717 static void DisplayGTPConfig(GTPConfig *config)
718 {
719     int index;
720     int newline;
721 
722     if (config == NULL)
723         return;
724 
725     _dpd.logMsg("GTP config: \n");
726 
727     /* Traverse list, printing ports, 5 per line */
728     newline = 1;
729     _dpd.logMsg("    Ports:\n");
730     for(index = 0; index < MAXPORTS; index++)
731     {
732         if( config->ports[ PORT_INDEX(index) ] & CONV_PORT(index) )
733         {
734             _dpd.logMsg("\t%d", index);
735             if ( !((newline++)% 5) )
736                 _dpd.logMsg("\n");
737         }
738     }
739     _dpd.logMsg("\n");
740     DEBUG_WRAP(DisplayMsgTypes(config));
741     DEBUG_WRAP(DisplayInfoElements(config));
742 
743 }
744 
745 
746 /********************************************************************
747  * Function: GTP_ParsePortList()
748  *
749  * Parses a port list and adds bits associated with the ports
750  * parsed to a bit array.
751  *
752  * Arguments:
753  *  char **
754  *      Pointer to the pointer to the current position in the
755  *      configuration line.  This is updated to the current position
756  *      after parsing the IP list.
757  *  uint8_t *
758  *      Pointer to the port array mask to set bits for the ports
759  *      parsed.
760  *
761  * Returns:
762  *  GTP_Ret
763  *      GTP_SUCCESS if we were able to successfully parse the
764  *          port list.
765  *      GTP_FAILURE if an error occured in parsing the port list.
766  *
767  ********************************************************************/
GTP_ParsePortList(char ** ptr,uint8_t * port_array)768 static void GTP_ParsePortList(char **ptr, uint8_t *port_array)
769 {
770     long int port = -1;
771     char* cur_tokenp = *ptr;
772     /* If the user specified ports, remove GTP_C_PORT for now since
773      * it now needs to be set explicitly. */
774     port_array[ PORT_INDEX( GTP_C_PORT ) ] = 0;
775     port_array[ PORT_INDEX( GTP_C_PORT_V0 ) ] = 0;
776 
777     DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Port configurations: %s\n",*ptr ););
778 
779     /* Eat the open brace. */
780     cur_tokenp = strtok( NULL, GTP_CONFIG_VALUE_SEPERATORS);
781 
782     DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Port token: %s\n",cur_tokenp ););
783 
784     /* Check the space after '{'*/
785     if (( !cur_tokenp ) || ( 0 != strncmp (cur_tokenp,  "{", 2 )))
786     {
787         DynamicPreprocessorFatalMessage(" %s(%d) => Bad value specified for %s, make sure space before and after '{'.\n",
788                 *(_dpd.config_file), *(_dpd.config_line), GTP_PORTS_KEYWORD);
789     }
790 
791     cur_tokenp = strtok( NULL, GTP_CONFIG_VALUE_SEPERATORS);
792     while (( cur_tokenp ) && (  0 != strncmp (cur_tokenp,  "}", 2 )))
793     {
794         char *endStr = NULL;
795 
796         DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Port token: %s\n",cur_tokenp ););
797 
798         if ( !cur_tokenp )
799         {
800             DynamicPreprocessorFatalMessage(" %s(%d) => No option to '%s'.\n",
801                     *(_dpd.config_file), *(_dpd.config_line), GTP_PORTS_KEYWORD);
802         }
803 
804         port = _dpd.SnortStrtol( cur_tokenp, &endStr, 10);
805 
806         if (*endStr)
807         {
808             DynamicPreprocessorFatalMessage(" %s(%d) => Bad value specified for %s. "
809                     "Please specify an integer between %d and %d.\n",
810                     *(_dpd.config_file), *(_dpd.config_line),
811                     GTP_PORTS_KEYWORD, 1, MAXPORTS-1);
812         }
813 
814         if ((port < 0 || port > MAXPORTS-1) || (errno == ERANGE))
815         {
816             DynamicPreprocessorFatalMessage(" %s(%d) => Value specified for %s is out of "
817                     "bounds.  Please specify an integer between %d and %d.\n",
818                     *(_dpd.config_file), *(_dpd.config_line),
819                     GTP_PORTS_KEYWORD, 1, MAXPORTS-1);
820         }
821         port_array[ PORT_INDEX( port ) ] |= CONV_PORT(port);
822 
823         cur_tokenp = strtok( NULL, GTP_CONFIG_VALUE_SEPERATORS);
824     }
825     if ( NULL == cur_tokenp )
826     {
827         DynamicPreprocessorFatalMessage(" %s(%d) => Bad value specified for %s, missing '}'.\n",
828                 *(_dpd.config_file), *(_dpd.config_line), GTP_PORTS_KEYWORD);
829     }
830     if ( -1 == port)
831     {
832         DynamicPreprocessorFatalMessage(" %s(%d) => No ports specified.\n",
833                         *(_dpd.config_file), *(_dpd.config_line), GTP_PORTS_KEYWORD);
834     }
835     *ptr = cur_tokenp;
836 }
837 
838 /* Parses and processes the configuration arguments
839  * supplied in the GTP preprocessor rule.
840  *
841  * PARAMETERS:
842  *
843  * GTPConfig *config: GTP preprocessor configuration.
844  * argp:              Pointer to string containing the config arguments.
845  *
846  * RETURNS:     Nothing.
847  */
ParseGTPArgs(GTPConfig * config,u_char * argp)848 void ParseGTPArgs(GTPConfig *config, u_char* argp)
849 {
850     char* cur_sectionp = NULL;
851     char* next_sectionp = NULL;
852     char* argcpyp = NULL;
853 
854     if (NULL == config)
855         return;
856 
857     /* Set up default port to listen on */
858     config->ports[ PORT_INDEX( GTP_C_PORT ) ] |= CONV_PORT(GTP_C_PORT);
859     config->ports[ PORT_INDEX( GTP_C_PORT_V0 ) ] |= CONV_PORT(GTP_C_PORT_V0);
860 
861     InitGTPInfoElementTable(config);
862     InitGTPMsgTypeTable(config);
863 
864     /* Sanity check(s) */
865     if (NULL == argp)
866     {
867         DisplayGTPConfig(config);
868         return;
869     }
870 
871     argcpyp = strdup( (char*) argp );
872 
873     if ( !argcpyp )
874     {
875         DynamicPreprocessorFatalMessage("Could not allocate memory to parse GTP options.\n");
876         return;
877     }
878 
879     DEBUG_WRAP(DebugMessage(DEBUG_GTP, "GTP configurations: %s\n",argcpyp ););
880 
881     cur_sectionp = strtok_r( argcpyp, GTP_CONFIG_SECTION_SEPERATORS, &next_sectionp);
882     DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Arguments token: %s\n",cur_sectionp ););
883 
884     while ( cur_sectionp )
885     {
886 
887         char* cur_config;
888         char* cur_tokenp = 	strtok( cur_sectionp, GTP_CONFIG_VALUE_SEPERATORS);
889 
890         if (!cur_tokenp)
891         {
892             cur_sectionp = strtok_r( next_sectionp, GTP_CONFIG_SECTION_SEPERATORS, &next_sectionp);
893             continue;
894         }
895 
896         cur_config = cur_tokenp;
897 
898         if ( !strcmp( cur_tokenp, GTP_PORTS_KEYWORD ))
899         {
900             GTP_ParsePortList(&cur_tokenp, config->ports);
901 
902         }
903         else
904         {
905             DynamicPreprocessorFatalMessage(" %s(%d) => Invalid argument: %s\n",
906                     *(_dpd.config_file), *(_dpd.config_line), cur_tokenp);
907             return;
908         }
909         /*Check whether too many parameters*/
910         if (NULL != strtok( NULL, GTP_CONFIG_VALUE_SEPERATORS))
911         {
912             DynamicPreprocessorFatalMessage("%s(%d) => To many arguments: %s\n",
913                     *(_dpd.config_file), *(_dpd.config_line), cur_config);
914 
915         }
916         cur_sectionp = strtok_r( next_sectionp, GTP_CONFIG_SECTION_SEPERATORS, &next_sectionp);
917         DEBUG_WRAP(DebugMessage(DEBUG_GTP, "Arguments token: %s\n",cur_sectionp ););
918     }
919 
920     DisplayGTPConfig(config);
921     free(argcpyp);
922 }
923 
924 /* Search the message type information
925  *
926  * PARAMETERS:
927  *
928  * uint8_t: version number for the message type
929  * char* the message type name
930  *
931  * RETURNS:
932  *
933  * GTP_MsgType*: the message type, NULL if not found
934  */
935 
GetMsgTypeByName(uint8_t version,char * name)936 GTP_MsgType*  GetMsgTypeByName(uint8_t version, char *name)
937 {
938     int i = 0;
939     GTP_MsgType *MsgTypes;
940 
941     switch (version)
942     {
943     case 0:
944         MsgTypes =  GTPv0_MsgTypes;
945         break;
946     case 1:
947         MsgTypes =  GTPv1_MsgTypes;
948         break;
949     case 2:
950         MsgTypes =  GTPv2_MsgTypes;
951         break;
952     default:
953         return NULL;
954     }
955 
956     while(NULL != MsgTypes[i].name)
957     {
958         if ( MsgTypes[i].isKeyword
959                 &&(strlen(MsgTypes[i].name) == strlen(name))
960                 && (0 == strncmp(MsgTypes[i].name, name, strlen(name))))
961             return (&(MsgTypes[i]));
962         i++;
963     }
964 
965     return NULL;
966 }
967 
968 
969 /* Search the information element information
970  *
971  * PARAMETERS:
972  *
973  * uint8_t: version number for information elements
974  * char* the information element name
975  *
976  * RETURNS:
977  *
978  * GTP_InfoElement*: the information element, NULL if not found
979  */
GetInfoElementByName(uint8_t version,char * name)980 GTP_InfoElement*  GetInfoElementByName(uint8_t version, char *name)
981 {
982     int i = 0;
983     GTP_InfoElement *InfoElements;
984 
985     switch (version)
986     {
987     case 0:
988         InfoElements =  GTPv0_InfoElements;
989         break;
990     case 1:
991         InfoElements =  GTPv1_InfoElements;
992         break;
993     case 2:
994         InfoElements =  GTPv2_InfoElements;
995         break;
996     default:
997         return NULL;
998     }
999 
1000     while(NULL != InfoElements[i].name)
1001     {
1002         if (InfoElements[i].isKeyword
1003                 && (strlen(InfoElements[i].name) == strlen(name))
1004                 && (0 == strncmp(InfoElements[i].name, name, strlen(name))))
1005             return (&InfoElements[i]);
1006         i++;
1007     }
1008 
1009     return NULL;
1010 }
1011