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