Coverage Report

Created: 2025-07-23 07:05

/src/open5gs/lib/gtp/xact.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
3
 * Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
4
 *
5
 * This file is part of Open5GS.
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include "ogs-gtp.h"
22
#include "ogs-app.h"
23
24
typedef enum {
25
    GTP_XACT_UNKNOWN_STAGE,
26
    GTP_XACT_INITIAL_STAGE,
27
    GTP_XACT_INTERMEDIATE_STAGE,
28
    GTP_XACT_FINAL_STAGE,
29
} ogs_gtp_xact_stage_t;
30
31
static int ogs_gtp_xact_initialized = 0;
32
static uint32_t g_xact_id = 0;
33
34
static OGS_POOL(pool, ogs_gtp_xact_t);
35
36
static ogs_gtp_xact_t *ogs_gtp_xact_remote_create(ogs_gtp_node_t *gnode, uint8_t gtp_version, uint32_t sqn);
37
static ogs_gtp_xact_stage_t ogs_gtp2_xact_get_stage(uint8_t type, uint32_t xid);
38
static ogs_gtp_xact_stage_t ogs_gtp1_xact_get_stage(uint8_t type, uint32_t xid);
39
static int ogs_gtp_xact_delete(ogs_gtp_xact_t *xact);
40
static int ogs_gtp_xact_update_rx(ogs_gtp_xact_t *xact, uint8_t type);
41
42
static void response_timeout(void *data);
43
static void holding_timeout(void *data);
44
static void peer_timeout(void *data);
45
46
int ogs_gtp_xact_init(void)
47
0
{
48
0
    ogs_assert(ogs_gtp_xact_initialized == 0);
49
50
0
    ogs_pool_init(&pool, ogs_app()->pool.xact);
51
52
0
    g_xact_id = 0;
53
54
0
    ogs_gtp_xact_initialized = 1;
55
56
0
    return OGS_OK;
57
0
}
58
59
void ogs_gtp_xact_final(void)
60
0
{
61
0
    ogs_assert(ogs_gtp_xact_initialized == 1);
62
63
0
    ogs_pool_final(&pool);
64
65
0
    ogs_gtp_xact_initialized = 0;
66
0
}
67
68
ogs_gtp_xact_t *ogs_gtp1_xact_local_create(ogs_gtp_node_t *gnode,
69
        ogs_gtp1_header_t *hdesc, ogs_pkbuf_t *pkbuf,
70
        void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data)
71
0
{
72
0
    int rv;
73
0
    char buf[OGS_ADDRSTRLEN];
74
0
    ogs_gtp_xact_t *xact = NULL;
75
76
0
    ogs_assert(gnode);
77
0
    ogs_assert(hdesc);
78
79
0
    ogs_pool_id_calloc(&pool, &xact);
80
0
    ogs_assert(xact);
81
0
    xact->index = ogs_pool_index(&pool, xact);
82
83
0
    xact->gtp_version = 1;
84
0
    xact->org = OGS_GTP_LOCAL_ORIGINATOR;
85
0
    xact->xid = OGS_NEXT_ID(g_xact_id,
86
0
            OGS_GTP1_MIN_XACT_ID, OGS_GTP1_MAX_XACT_ID);
87
0
    xact->gnode = gnode;
88
0
    xact->cb = cb;
89
0
    xact->data = data;
90
91
    /* 7.6 "The T3-RESPONSE timer shall be started when a signalling request
92
     * message (for which a response has been defined) is sent." */
93
0
    if (hdesc->type != OGS_GTP1_RAN_INFORMATION_RELAY_TYPE) {
94
0
        xact->tm_response = ogs_timer_add(
95
0
                ogs_app()->timer_mgr, response_timeout,
96
0
                OGS_UINT_TO_POINTER(xact->id));
97
0
        ogs_assert(xact->tm_response);
98
0
        xact->response_rcount =
99
0
            ogs_local_conf()->time.message.gtp.n3_response_rcount;
100
0
    }
101
102
0
    xact->tm_holding = ogs_timer_add(
103
0
            ogs_app()->timer_mgr, holding_timeout,
104
0
            OGS_UINT_TO_POINTER(xact->id));
105
0
    ogs_assert(xact->tm_holding);
106
0
    xact->holding_rcount = ogs_local_conf()->time.message.gtp.n3_holding_rcount;
107
108
0
    ogs_list_add(&xact->gnode->local_list, xact);
109
110
0
    rv = ogs_gtp1_xact_update_tx(xact, hdesc, pkbuf);
111
0
    if (rv != OGS_OK) {
112
0
        ogs_error("ogs_gtp_xact_update_tx(rv=%d) failed", (int)rv);
113
0
        ogs_gtp_xact_delete(xact);
114
0
        return NULL;
115
0
    }
116
117
0
    ogs_debug("[%d] LOCAL Create  peer [%s]:%d",
118
0
            xact->xid,
119
0
            OGS_ADDR(&gnode->addr, buf),
120
0
            OGS_PORT(&gnode->addr));
121
122
0
    return xact;
123
0
}
124
125
ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode,
126
        ogs_gtp2_header_t *hdesc, ogs_pkbuf_t *pkbuf,
127
        void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data)
128
0
{
129
0
    int rv;
130
0
    char buf[OGS_ADDRSTRLEN];
131
0
    ogs_gtp_xact_t *xact = NULL;
132
133
0
    ogs_assert(gnode);
134
0
    ogs_assert(hdesc);
135
136
0
    ogs_pool_id_calloc(&pool, &xact);
137
0
    ogs_assert(xact);
138
0
    xact->index = ogs_pool_index(&pool, xact);
139
140
0
    xact->gtp_version = 2;
141
0
    xact->org = OGS_GTP_LOCAL_ORIGINATOR;
142
0
    xact->xid = OGS_NEXT_ID(g_xact_id,
143
0
            OGS_GTP_MIN_XACT_ID, OGS_GTP_CMD_XACT_ID);
144
0
    if (hdesc->type == OGS_GTP2_MODIFY_BEARER_COMMAND_TYPE ||
145
0
        hdesc->type == OGS_GTP2_DELETE_BEARER_COMMAND_TYPE ||
146
0
        hdesc->type == OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE) {
147
0
        xact->xid |= OGS_GTP_CMD_XACT_ID;
148
0
    }
149
0
    xact->gnode = gnode;
150
0
    xact->cb = cb;
151
0
    xact->data = data;
152
153
0
    xact->tm_response = ogs_timer_add(
154
0
            ogs_app()->timer_mgr, response_timeout,
155
0
            OGS_UINT_TO_POINTER(xact->id));
156
0
    ogs_assert(xact->tm_response);
157
0
    xact->response_rcount =
158
0
        ogs_local_conf()->time.message.gtp.n3_response_rcount,
159
160
0
    xact->tm_holding = ogs_timer_add(
161
0
            ogs_app()->timer_mgr, holding_timeout,
162
0
            OGS_UINT_TO_POINTER(xact->id));
163
0
    ogs_assert(xact->tm_holding);
164
0
    xact->holding_rcount = ogs_local_conf()->time.message.gtp.n3_holding_rcount,
165
166
0
    xact->tm_peer = ogs_timer_add(ogs_app()->timer_mgr, peer_timeout,
167
0
            OGS_UINT_TO_POINTER(xact->id));
168
0
    ogs_assert(xact->tm_peer);
169
170
0
    ogs_list_add(&xact->gnode->local_list, xact);
171
172
0
    rv = ogs_gtp_xact_update_tx(xact, hdesc, pkbuf);
173
0
    if (rv != OGS_OK) {
174
0
        ogs_error("ogs_gtp_xact_update_tx(rv=%d) failed", (int)rv);
175
0
        ogs_gtp_xact_delete(xact);
176
0
        return NULL;
177
0
    }
178
179
0
    ogs_debug("[%d] LOCAL Create  peer [%s]:%d",
180
0
            xact->xid,
181
0
            OGS_ADDR(&gnode->addr, buf),
182
0
            OGS_PORT(&gnode->addr));
183
184
0
    return xact;
185
0
}
186
187
static ogs_gtp_xact_t *ogs_gtp_xact_remote_create(ogs_gtp_node_t *gnode, uint8_t gtp_version, uint32_t sqn)
188
0
{
189
0
    char buf[OGS_ADDRSTRLEN];
190
0
    ogs_gtp_xact_t *xact = NULL;
191
192
0
    ogs_assert(gnode);
193
194
0
    ogs_pool_id_calloc(&pool, &xact);
195
0
    ogs_assert(xact);
196
0
    xact->index = ogs_pool_index(&pool, xact);
197
198
0
    xact->gtp_version = gtp_version;
199
0
    xact->org = OGS_GTP_REMOTE_ORIGINATOR;
200
0
    xact->xid = (gtp_version == 1) ?
201
0
            OGS_GTP1_SQN_TO_XID(sqn) : OGS_GTP2_SQN_TO_XID(sqn);
202
0
    xact->gnode = gnode;
203
204
0
    xact->tm_response = ogs_timer_add(
205
0
            ogs_app()->timer_mgr, response_timeout,
206
0
            OGS_UINT_TO_POINTER(xact->id));
207
0
    ogs_assert(xact->tm_response);
208
0
    xact->response_rcount =
209
0
        ogs_local_conf()->time.message.gtp.n3_response_rcount,
210
211
0
    xact->tm_holding = ogs_timer_add(
212
0
            ogs_app()->timer_mgr, holding_timeout,
213
0
            OGS_UINT_TO_POINTER(xact->id));
214
0
    ogs_assert(xact->tm_holding);
215
0
    xact->holding_rcount = ogs_local_conf()->time.message.gtp.n3_holding_rcount,
216
217
0
    xact->tm_peer = ogs_timer_add(ogs_app()->timer_mgr, peer_timeout,
218
0
            OGS_UINT_TO_POINTER(xact->id));
219
0
    ogs_assert(xact->tm_peer);
220
221
0
    ogs_list_add(&xact->gnode->remote_list, xact);
222
223
0
    ogs_debug("[%d] REMOTE Create  peer [%s]:%d",
224
0
            xact->xid,
225
0
            OGS_ADDR(&gnode->addr, buf),
226
0
            OGS_PORT(&gnode->addr));
227
228
0
    return xact;
229
0
}
230
231
ogs_gtp_xact_t *ogs_gtp_xact_find_by_id(ogs_pool_id_t id)
232
0
{
233
0
    return ogs_pool_find_by_id(&pool, id);
234
0
}
235
236
void ogs_gtp_xact_delete_all(ogs_gtp_node_t *gnode)
237
0
{
238
0
    ogs_gtp_xact_t *xact = NULL, *next_xact = NULL;
239
240
0
    ogs_list_for_each_safe(&gnode->local_list, next_xact, xact)
241
0
        ogs_gtp_xact_delete(xact);
242
0
    ogs_list_for_each_safe(&gnode->remote_list, next_xact, xact)
243
0
        ogs_gtp_xact_delete(xact);
244
0
}
245
246
int ogs_gtp1_xact_update_tx(ogs_gtp_xact_t *xact,
247
        ogs_gtp1_header_t *hdesc, ogs_pkbuf_t *pkbuf)
248
0
{
249
0
    char buf[OGS_ADDRSTRLEN];
250
0
    ogs_gtp_xact_stage_t stage;
251
0
    ogs_gtp1_header_t *h = NULL;
252
0
    int gtp_hlen = 0;
253
254
0
    ogs_assert(xact);
255
0
    ogs_assert(xact->gnode);
256
0
    ogs_assert(hdesc);
257
0
    ogs_assert(pkbuf);
258
259
0
    ogs_debug("[%d] %s UPD TX-%d  peer [%s]:%d",
260
0
            xact->xid,
261
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
262
0
            hdesc->type,
263
0
            OGS_ADDR(&xact->gnode->addr, buf),
264
0
            OGS_PORT(&xact->gnode->addr));
265
266
0
    stage = ogs_gtp1_xact_get_stage(hdesc->type, xact->xid);
267
0
    if (xact->org == OGS_GTP_LOCAL_ORIGINATOR) {
268
0
        switch (stage) {
269
0
        case GTP_XACT_INITIAL_STAGE:
270
0
            if (xact->step != 0) {
271
0
                ogs_error("invalid step[%d]", xact->step);
272
0
                ogs_pkbuf_free(pkbuf);
273
0
                return OGS_ERROR;
274
0
            }
275
0
            break;
276
277
0
        case GTP_XACT_INTERMEDIATE_STAGE:
278
0
            ogs_expect(0);
279
0
            ogs_pkbuf_free(pkbuf);
280
0
            return OGS_ERROR;
281
282
0
        case GTP_XACT_FINAL_STAGE:
283
0
            if (xact->step != 2 && xact->step != 3) {
284
0
                ogs_error("invalid step[%d]", xact->step);
285
0
                ogs_pkbuf_free(pkbuf);
286
0
                return OGS_ERROR;
287
0
            }
288
0
            break;
289
290
0
        default:
291
0
            ogs_assert_if_reached();
292
0
            break;
293
0
        }
294
0
    } else if (xact->org == OGS_GTP_REMOTE_ORIGINATOR) {
295
0
        switch (stage) {
296
0
        case GTP_XACT_INITIAL_STAGE:
297
0
            ogs_expect(0);
298
0
            ogs_pkbuf_free(pkbuf);
299
0
            return OGS_ERROR;
300
301
0
        case GTP_XACT_INTERMEDIATE_STAGE:
302
0
        case GTP_XACT_FINAL_STAGE:
303
0
            if (xact->step != 1) {
304
0
                ogs_error("invalid step[%d]", xact->step);
305
0
                ogs_pkbuf_free(pkbuf);
306
0
                return OGS_ERROR;
307
0
            }
308
0
            break;
309
310
0
        default:
311
0
            ogs_error("invalid stage[%d]", stage);
312
0
            ogs_pkbuf_free(pkbuf);
313
0
            return OGS_ERROR;
314
0
        }
315
0
    } else {
316
0
        ogs_error("invalid org[%d]", xact->org);
317
0
        ogs_pkbuf_free(pkbuf);
318
0
        return OGS_ERROR;
319
0
    }
320
321
0
    gtp_hlen = OGS_GTPV1C_HEADER_LEN;
322
323
324
0
    ogs_pkbuf_push(pkbuf, gtp_hlen);
325
0
    h = (ogs_gtp1_header_t *)pkbuf->data;
326
0
    memset(h, 0, gtp_hlen);
327
328
0
    h->version = 1;
329
0
    h->type = hdesc->type;
330
0
    h->pt = 1; /* GTP */
331
0
    h->teid = htobe32(hdesc->teid);
332
333
0
    h->s = 1;
334
0
    h->sqn = OGS_GTP1_XID_TO_SQN(xact->xid);
335
0
    h->length = htobe16(pkbuf->len - 8);
336
337
    /* Save Message type and packet of this step */
338
0
    xact->seq[xact->step].type = h->type;
339
0
    xact->seq[xact->step].pkbuf = pkbuf;
340
341
    /* Step */
342
0
    xact->step++;
343
344
0
    return OGS_OK;
345
0
}
346
347
int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact,
348
        ogs_gtp2_header_t *hdesc, ogs_pkbuf_t *pkbuf)
349
0
{
350
0
    char buf[OGS_ADDRSTRLEN];
351
0
    ogs_gtp_xact_stage_t stage;
352
0
    ogs_gtp2_header_t *h = NULL;
353
0
    int gtp_hlen = 0;
354
355
0
    ogs_assert(xact);
356
0
    ogs_assert(xact->gnode);
357
0
    ogs_assert(hdesc);
358
0
    ogs_assert(pkbuf);
359
360
0
    ogs_debug("[%d] %s UPD TX-%d  peer [%s]:%d",
361
0
            xact->xid,
362
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
363
0
            hdesc->type,
364
0
            OGS_ADDR(&xact->gnode->addr, buf),
365
0
            OGS_PORT(&xact->gnode->addr));
366
367
0
    stage = ogs_gtp2_xact_get_stage(hdesc->type, xact->xid);
368
0
    if (xact->org == OGS_GTP_LOCAL_ORIGINATOR) {
369
0
        switch (stage) {
370
0
        case GTP_XACT_INITIAL_STAGE:
371
0
            if (xact->step != 0) {
372
0
                ogs_error("invalid step[%d]", xact->step);
373
0
                ogs_pkbuf_free(pkbuf);
374
0
                return OGS_ERROR;
375
0
            }
376
0
            break;
377
378
0
        case GTP_XACT_INTERMEDIATE_STAGE:
379
0
            ogs_expect(0);
380
0
            ogs_pkbuf_free(pkbuf);
381
0
            return OGS_ERROR;
382
383
0
        case GTP_XACT_FINAL_STAGE:
384
0
            if (xact->step != 2) {
385
0
                ogs_error("invalid step[%d]", xact->step);
386
0
                ogs_pkbuf_free(pkbuf);
387
0
                return OGS_ERROR;
388
0
            }
389
0
            break;
390
391
0
        default:
392
0
            ogs_assert_if_reached();
393
0
            break;
394
0
        }
395
0
    } else if (xact->org == OGS_GTP_REMOTE_ORIGINATOR) {
396
0
        switch (stage) {
397
0
        case GTP_XACT_INITIAL_STAGE:
398
0
            ogs_expect(0);
399
0
            ogs_pkbuf_free(pkbuf);
400
0
            return OGS_ERROR;
401
402
0
        case GTP_XACT_INTERMEDIATE_STAGE:
403
0
        case GTP_XACT_FINAL_STAGE:
404
0
            if (xact->step != 1) {
405
0
                ogs_error("invalid step[%d]", xact->step);
406
0
                ogs_pkbuf_free(pkbuf);
407
0
                return OGS_ERROR;
408
0
            }
409
0
            break;
410
411
0
        default:
412
0
            ogs_error("invalid stage[%d]", stage);
413
0
            ogs_pkbuf_free(pkbuf);
414
0
            return OGS_ERROR;
415
0
        }
416
0
    } else {
417
0
        ogs_error("invalid org[%d]", xact->org);
418
0
        ogs_pkbuf_free(pkbuf);
419
0
        return OGS_ERROR;
420
0
    }
421
422
0
    if (hdesc->type > OGS_GTP2_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
423
0
        gtp_hlen = OGS_GTPV2C_HEADER_LEN;
424
0
    } else {
425
0
        gtp_hlen = OGS_GTPV2C_HEADER_LEN - OGS_GTP2_TEID_LEN;
426
0
    }
427
428
0
    ogs_pkbuf_push(pkbuf, gtp_hlen);
429
0
    h = (ogs_gtp2_header_t *)pkbuf->data;
430
0
    memset(h, 0, gtp_hlen);
431
432
0
    h->version = 2;
433
0
    h->type = hdesc->type;
434
435
0
    if (hdesc->type > OGS_GTP2_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
436
0
        h->teid_presence = 1;
437
0
        h->teid = htobe32(hdesc->teid);
438
0
        h->sqn = OGS_GTP2_XID_TO_SQN(xact->xid);
439
0
    } else {
440
0
        h->teid_presence = 0;
441
0
        h->sqn_only = OGS_GTP2_XID_TO_SQN(xact->xid);
442
0
    }
443
0
    h->length = htobe16(pkbuf->len - 4);
444
445
    /* Save Message type and packet of this step */
446
0
    xact->seq[xact->step].type = h->type;
447
0
    xact->seq[xact->step].pkbuf = pkbuf;
448
449
    /* Step */
450
0
    xact->step++;
451
452
0
    return OGS_OK;
453
0
}
454
455
static int ogs_gtp_xact_update_rx(ogs_gtp_xact_t *xact, uint8_t type)
456
0
{
457
0
    char buf[OGS_ADDRSTRLEN];
458
0
    ogs_gtp_xact_stage_t stage;
459
460
0
    ogs_debug("[%d] %s UPD RX-%d  peer [%s]:%d",
461
0
            xact->xid,
462
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
463
0
            type,
464
0
            OGS_ADDR(&xact->gnode->addr, buf),
465
0
            OGS_PORT(&xact->gnode->addr));
466
467
0
    if (xact->gtp_version == 1)
468
0
        stage = ogs_gtp1_xact_get_stage(type, xact->xid);
469
0
    else
470
0
        stage = ogs_gtp2_xact_get_stage(type, xact->xid);
471
472
0
    if (xact->org == OGS_GTP_LOCAL_ORIGINATOR) {
473
0
        switch (stage) {
474
0
        case GTP_XACT_INITIAL_STAGE:
475
0
            ogs_expect(0);
476
0
            return OGS_ERROR;
477
478
0
        case GTP_XACT_INTERMEDIATE_STAGE:
479
0
            if (xact->seq[1].type == type) {
480
0
                ogs_pkbuf_t *pkbuf = NULL;
481
482
0
                if (xact->step != 2 && xact->step != 3) {
483
0
                    ogs_error("invalid step[%d]", xact->step);
484
0
                    ogs_pkbuf_free(pkbuf);
485
0
                    return OGS_ERROR;
486
0
                }
487
488
0
                pkbuf = xact->seq[2].pkbuf;
489
0
                if (pkbuf) {
490
0
                    if (xact->tm_holding)
491
0
                        ogs_timer_start(xact->tm_holding,
492
0
                                ogs_local_conf()->time.message.
493
0
                                    gtp.t3_holding_duration);
494
495
0
                    ogs_warn("[%d] %s Request Duplicated. Retransmit!"
496
0
                            " for step %d type %d peer [%s]:%d",
497
0
                            xact->xid,
498
0
                            xact->org == OGS_GTP_LOCAL_ORIGINATOR ?
499
0
                                "LOCAL " : "REMOTE",
500
0
                            xact->step, type,
501
0
                            OGS_ADDR(&xact->gnode->addr,
502
0
                                buf),
503
0
                            OGS_PORT(&xact->gnode->addr));
504
0
                    ogs_expect(OGS_OK == ogs_gtp_sendto(xact->gnode, pkbuf));
505
0
                } else {
506
0
                    ogs_warn("[%d] %s Request Duplicated. Discard!"
507
0
                            " for step %d type %d peer [%s]:%d",
508
0
                            xact->xid,
509
0
                            xact->org == OGS_GTP_LOCAL_ORIGINATOR ?
510
0
                                "LOCAL " : "REMOTE",
511
0
                            xact->step, type,
512
0
                            OGS_ADDR(&xact->gnode->addr,
513
0
                                buf),
514
0
                            OGS_PORT(&xact->gnode->addr));
515
0
                }
516
517
0
                return OGS_RETRY;
518
0
            }
519
520
0
            if (xact->step != 1) {
521
0
                ogs_error("invalid step[%d]", xact->step);
522
0
                return OGS_ERROR;
523
0
            }
524
525
0
            if (xact->tm_holding)
526
0
                ogs_timer_start(xact->tm_holding,
527
0
                        ogs_local_conf()->time.message.gtp.t3_holding_duration);
528
529
0
            break;
530
531
0
        case GTP_XACT_FINAL_STAGE:
532
0
            if (xact->step != 1) {
533
0
                ogs_error("invalid step[%d]", xact->step);
534
0
                return OGS_ERROR;
535
0
            }
536
0
            break;
537
538
0
        default:
539
0
            ogs_error("invalid stage[%d]", stage);
540
0
            return OGS_ERROR;
541
0
        }
542
0
    } else if (xact->org == OGS_GTP_REMOTE_ORIGINATOR) {
543
0
        switch (stage) {
544
0
        case GTP_XACT_INITIAL_STAGE:
545
0
            if (xact->seq[0].type == type) {
546
0
                ogs_pkbuf_t *pkbuf = NULL;
547
548
0
                if (xact->step != 1 && xact->step != 2) {
549
0
                    ogs_error("invalid step[%d]", xact->step);
550
0
                    return OGS_ERROR;
551
0
                }
552
553
0
                pkbuf = xact->seq[1].pkbuf;
554
0
                if (pkbuf) {
555
0
                    if (xact->tm_holding)
556
0
                        ogs_timer_start(xact->tm_holding,
557
0
                                ogs_local_conf()->time.message.
558
0
                                    gtp.t3_holding_duration);
559
560
0
                    ogs_warn("[%d] %s Request Duplicated. Retransmit!"
561
0
                            " for step %d type %d peer [%s]:%d",
562
0
                            xact->xid,
563
0
                            xact->org == OGS_GTP_LOCAL_ORIGINATOR ?
564
0
                                "LOCAL " : "REMOTE",
565
0
                            xact->step, type,
566
0
                            OGS_ADDR(&xact->gnode->addr,
567
0
                                buf),
568
0
                            OGS_PORT(&xact->gnode->addr));
569
0
                    ogs_expect(OGS_OK == ogs_gtp_sendto(xact->gnode, pkbuf));
570
0
                } else {
571
0
                    ogs_warn("[%d] %s Request Duplicated. Discard!"
572
0
                            " for step %d type %d peer [%s]:%d",
573
0
                            xact->xid,
574
0
                            xact->org == OGS_GTP_LOCAL_ORIGINATOR ?
575
0
                                "LOCAL " : "REMOTE",
576
0
                            xact->step, type,
577
0
                            OGS_ADDR(&xact->gnode->addr,
578
0
                                buf),
579
0
                            OGS_PORT(&xact->gnode->addr));
580
0
                }
581
582
0
                return OGS_RETRY;
583
0
            }
584
585
0
            if (xact->step != 0) {
586
0
                ogs_error("invalid step[%d]", xact->step);
587
0
                return OGS_ERROR;
588
0
            }
589
0
            if (xact->tm_holding)
590
0
                ogs_timer_start(xact->tm_holding,
591
0
                        ogs_local_conf()->time.message.gtp.t3_holding_duration);
592
593
0
            break;
594
595
0
        case GTP_XACT_INTERMEDIATE_STAGE:
596
0
            ogs_expect(0);
597
0
            return OGS_ERROR;
598
599
0
        case GTP_XACT_FINAL_STAGE:
600
0
            if (xact->step != 2) {
601
0
                ogs_error("invalid step[%d]", xact->step);
602
0
                return OGS_ERROR;
603
0
            }
604
605
            /* continue */
606
0
            break;
607
608
0
        default:
609
0
            ogs_error("invalid stage[%d]", stage);
610
0
            return OGS_ERROR;
611
0
        }
612
0
    } else {
613
0
        ogs_error("invalid org[%d]", xact->org);
614
0
        return OGS_ERROR;
615
0
    }
616
617
0
    if (xact->tm_response)
618
0
        ogs_timer_stop(xact->tm_response);
619
620
    /* Save Message type of this step */
621
0
    xact->seq[xact->step].type = type;
622
623
    /* Step */
624
0
    xact->step++;
625
626
0
    return OGS_OK;
627
0
}
628
629
630
int ogs_gtp_xact_commit(ogs_gtp_xact_t *xact)
631
0
{
632
0
    char buf[OGS_ADDRSTRLEN];
633
634
0
    uint8_t type;
635
0
    ogs_pkbuf_t *pkbuf = NULL;
636
0
    ogs_gtp_xact_stage_t stage;
637
638
0
    ogs_assert(xact);
639
0
    ogs_assert(xact->gnode);
640
641
0
    ogs_debug("[%d] %s Commit  peer [%s]:%d",
642
0
            xact->xid,
643
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
644
0
            OGS_ADDR(&xact->gnode->addr, buf),
645
0
            OGS_PORT(&xact->gnode->addr));
646
647
0
    type = xact->seq[xact->step-1].type;
648
0
    if (xact->gtp_version == 1)
649
0
        stage = ogs_gtp1_xact_get_stage(type, xact->xid);
650
0
    else
651
0
        stage = ogs_gtp2_xact_get_stage(type, xact->xid);
652
653
0
    if (xact->org == OGS_GTP_LOCAL_ORIGINATOR) {
654
0
        switch (stage) {
655
0
        case GTP_XACT_INITIAL_STAGE:
656
0
            if (xact->step != 1) {
657
0
                ogs_error("invalid step[%d]", xact->step);
658
0
                ogs_gtp_xact_delete(xact);
659
0
                return OGS_ERROR;
660
0
            }
661
662
0
            if (xact->tm_response)
663
0
                ogs_timer_start(xact->tm_response,
664
0
                        ogs_local_conf()->time.message.gtp.
665
0
                        t3_response_duration);
666
667
0
            break;
668
669
0
        case GTP_XACT_INTERMEDIATE_STAGE:
670
0
            if (xact->step != 2) {
671
0
                ogs_error("invalid step[%d]", xact->step);
672
0
                ogs_gtp_xact_delete(xact);
673
0
                return OGS_ERROR;
674
0
            }
675
0
            return OGS_OK;
676
677
0
        case GTP_XACT_FINAL_STAGE:
678
0
            if (xact->step != 2 && xact->step != 3) {
679
0
                ogs_error("invalid step[%d]", xact->step);
680
0
                ogs_gtp_xact_delete(xact);
681
0
                return OGS_ERROR;
682
0
            }
683
0
            if (xact->step == 2) {
684
0
                ogs_gtp_xact_delete(xact);
685
0
                return OGS_OK;
686
0
            }
687
688
0
            break;
689
690
0
        default:
691
0
            ogs_error("invalid stage[%d]", stage);
692
0
            ogs_gtp_xact_delete(xact);
693
0
            return OGS_ERROR;
694
0
        }
695
0
    } else if (xact->org == OGS_GTP_REMOTE_ORIGINATOR) {
696
0
        switch (stage) {
697
0
        case GTP_XACT_INITIAL_STAGE:
698
0
            ogs_expect(0);
699
0
            ogs_gtp_xact_delete(xact);
700
0
            return OGS_ERROR;
701
702
0
        case GTP_XACT_INTERMEDIATE_STAGE:
703
0
            if (xact->step != 2) {
704
0
                ogs_error("invalid step[%d]", xact->step);
705
0
                ogs_gtp_xact_delete(xact);
706
0
                return OGS_ERROR;
707
0
            }
708
0
            if (xact->tm_response)
709
0
                ogs_timer_start(xact->tm_response,
710
0
                        ogs_local_conf()->time.message.gtp.
711
0
                        t3_response_duration);
712
713
0
            break;
714
715
0
        case GTP_XACT_FINAL_STAGE:
716
0
            if (xact->step != 2 && xact->step != 3) {
717
0
                ogs_error("invalid step[%d]", xact->step);
718
0
                ogs_gtp_xact_delete(xact);
719
0
                return OGS_ERROR;
720
0
            }
721
0
            if (xact->step == 3) {
722
0
                ogs_gtp_xact_delete(xact);
723
0
                return OGS_OK;
724
0
            }
725
726
0
            break;
727
728
0
        default:
729
0
            ogs_error("invalid stage[%d]", stage);
730
0
            ogs_gtp_xact_delete(xact);
731
0
            return OGS_ERROR;
732
0
        }
733
0
    } else {
734
0
        ogs_error("invalid org[%d]", xact->org);
735
0
        ogs_gtp_xact_delete(xact);
736
0
        return OGS_ERROR;
737
0
    }
738
739
0
    pkbuf = xact->seq[xact->step-1].pkbuf;
740
0
    ogs_assert(pkbuf);
741
742
0
    ogs_expect(OGS_OK == ogs_gtp_sendto(xact->gnode, pkbuf));
743
744
0
    return OGS_OK;
745
0
}
746
747
static void response_timeout(void *data)
748
0
{
749
0
    char buf[OGS_ADDRSTRLEN];
750
0
    ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
751
0
    ogs_gtp_xact_t *xact = NULL;
752
753
0
    ogs_assert(data);
754
0
    xact_id = OGS_POINTER_TO_UINT(data);
755
0
    ogs_assert(xact_id >= OGS_MIN_POOL_ID && xact_id <= OGS_MAX_POOL_ID);
756
757
0
    xact = ogs_gtp_xact_find_by_id(xact_id);
758
0
    if (!xact) {
759
0
        ogs_error("GTP Transaction has already been removed [%d]", xact_id);
760
0
        return;;
761
0
    }
762
0
    ogs_assert(xact->gnode);
763
764
0
    ogs_debug("[%d] %s Response Timeout "
765
0
            "for step %d type %d peer [%s]:%d",
766
0
            xact->xid,
767
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
768
0
            xact->step, xact->seq[xact->step-1].type,
769
0
            OGS_ADDR(&xact->gnode->addr, buf),
770
0
            OGS_PORT(&xact->gnode->addr));
771
772
0
    if (--xact->response_rcount > 0) {
773
0
        ogs_pkbuf_t *pkbuf = NULL;
774
775
0
        if (xact->tm_response)
776
0
            ogs_timer_start(xact->tm_response,
777
0
                    ogs_local_conf()->time.message.gtp.t3_response_duration);
778
779
0
        pkbuf = xact->seq[xact->step-1].pkbuf;
780
0
        ogs_assert(pkbuf);
781
782
0
        ogs_expect(OGS_OK == ogs_gtp_sendto(xact->gnode, pkbuf));
783
0
    } else {
784
0
        ogs_warn("[%d] %s No Reponse. Give up! "
785
0
                "for step %d type %d peer [%s]:%d",
786
0
                xact->xid,
787
0
                xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
788
0
                xact->step, xact->seq[xact->step-1].type,
789
0
                OGS_ADDR(&xact->gnode->addr, buf),
790
0
                OGS_PORT(&xact->gnode->addr));
791
792
0
        if (xact->cb)
793
0
            xact->cb(xact, xact->data);
794
795
0
        ogs_gtp_xact_delete(xact);
796
0
    }
797
0
}
798
799
static void holding_timeout(void *data)
800
0
{
801
0
    char buf[OGS_ADDRSTRLEN];
802
0
    ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
803
0
    ogs_gtp_xact_t *xact = NULL;
804
805
0
    ogs_assert(data);
806
0
    xact_id = OGS_POINTER_TO_UINT(data);
807
0
    ogs_assert(xact_id >= OGS_MIN_POOL_ID && xact_id <= OGS_MAX_POOL_ID);
808
809
0
    xact = ogs_gtp_xact_find_by_id(xact_id);
810
0
    if (!xact) {
811
0
        ogs_error("GTP Transaction has already been removed [%d]", xact_id);
812
0
        return;;
813
0
    }
814
0
    ogs_assert(xact->gnode);
815
816
0
    ogs_debug("[%d] %s Holding Timeout "
817
0
            "for step %d type %d peer [%s]:%d",
818
0
            xact->xid,
819
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
820
0
            xact->step, xact->seq[xact->step-1].type,
821
0
            OGS_ADDR(&xact->gnode->addr, buf),
822
0
            OGS_PORT(&xact->gnode->addr));
823
824
0
    if (--xact->holding_rcount > 0) {
825
0
        if (xact->tm_holding)
826
0
            ogs_timer_start(xact->tm_holding,
827
0
                    ogs_local_conf()->time.message.gtp.t3_holding_duration);
828
0
    } else {
829
0
        ogs_debug("[%d] %s Delete Transaction "
830
0
                "for step %d type %d peer [%s]:%d",
831
0
                xact->xid,
832
0
                xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
833
0
                xact->step, xact->seq[xact->step-1].type,
834
0
                OGS_ADDR(&xact->gnode->addr, buf),
835
0
                OGS_PORT(&xact->gnode->addr));
836
0
        ogs_gtp_xact_delete(xact);
837
0
    }
838
0
}
839
840
static void peer_timeout(void *data)
841
0
{
842
0
    char buf[OGS_ADDRSTRLEN];
843
0
    ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
844
0
    ogs_gtp_xact_t *xact = NULL;
845
846
0
    ogs_assert(data);
847
0
    xact_id = OGS_POINTER_TO_UINT(data);
848
0
    ogs_assert(xact_id >= OGS_MIN_POOL_ID && xact_id <= OGS_MAX_POOL_ID);
849
850
0
    xact = ogs_gtp_xact_find_by_id(xact_id);
851
0
    if (!xact) {
852
0
        ogs_error("GTP Transaction has already been removed [%d]", xact_id);
853
0
        return;;
854
0
    }
855
0
    ogs_assert(xact->gnode);
856
857
0
    ogs_error("[%d] %s Peer Timeout "
858
0
            "for step %d type %d peer [%s]:%d",
859
0
            xact->xid,
860
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
861
0
            xact->step, xact->seq[xact->step-1].type,
862
0
            OGS_ADDR(&xact->gnode->addr, buf),
863
0
            OGS_PORT(&xact->gnode->addr));
864
865
0
    if (xact->peer_cb)
866
0
        xact->peer_cb(xact, xact->peer_data);
867
0
}
868
869
int ogs_gtp1_xact_receive(
870
        ogs_gtp_node_t *gnode, ogs_gtp1_header_t *h, ogs_gtp_xact_t **xact)
871
0
{
872
0
    int rv;
873
0
    char buf[OGS_ADDRSTRLEN];
874
875
0
    uint8_t type;
876
0
    uint32_t sqn, xid;
877
0
    ogs_gtp_xact_stage_t stage;
878
0
    ogs_list_t *list = NULL;
879
0
    ogs_gtp_xact_t *new = NULL;
880
881
0
    ogs_assert(gnode);
882
0
    ogs_assert(h);
883
884
0
    type = h->type;
885
886
0
    if (!h->s) {
887
0
        ogs_error("ogs_gtp_xact_update_rx() failed, pkt has no SQN");
888
0
        return OGS_ERROR;
889
0
    }
890
0
    sqn = h->sqn;
891
892
0
    xid = OGS_GTP1_SQN_TO_XID(sqn);
893
0
    stage = ogs_gtp1_xact_get_stage(type, xid);
894
895
0
    switch (stage) {
896
0
    case GTP_XACT_INITIAL_STAGE:
897
0
        list = &gnode->remote_list;
898
0
        break;
899
0
    case GTP_XACT_INTERMEDIATE_STAGE:
900
0
        list = &gnode->local_list;
901
0
        break;
902
0
    case GTP_XACT_FINAL_STAGE:
903
        /* For types which are replies to replies, the xact is never locally
904
         * created during transmit, but actually during rx of the initial req, hence
905
         * it is never placed in the local_list, but in the remote_list. */
906
0
        if (type == OGS_GTP1_SGSN_CONTEXT_ACKNOWLEDGE_TYPE)
907
0
            list = &gnode->remote_list;
908
0
        else
909
0
            list = &gnode->local_list;
910
0
        break;
911
0
    default:
912
0
        ogs_error("[%d] Unexpected type %u from GTPv1 peer [%s]:%d",
913
0
                xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
914
0
        return OGS_ERROR;
915
0
    }
916
917
0
    ogs_assert(list);
918
0
    ogs_list_for_each(list, new) {
919
0
        if (new->gtp_version == 1 && new->xid == xid) {
920
0
            ogs_debug("[%d] %s Find GTPv%u peer [%s]:%d",
921
0
                    new->xid,
922
0
                    new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
923
0
                    new->gtp_version,
924
0
                    OGS_ADDR(&gnode->addr, buf),
925
0
                    OGS_PORT(&gnode->addr));
926
0
            break;
927
0
        }
928
0
    }
929
930
0
    if (!new) {
931
0
        ogs_debug("[%d] Cannot find xact type %u from GTPv1 peer [%s]:%d",
932
0
                  xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
933
0
        new = ogs_gtp_xact_remote_create(gnode, 1, sqn);
934
0
    }
935
0
    ogs_assert(new);
936
937
0
    ogs_debug("[%d] %s Receive peer [%s]:%d",
938
0
            new->xid,
939
0
            new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
940
0
            OGS_ADDR(&gnode->addr, buf),
941
0
            OGS_PORT(&gnode->addr));
942
943
0
    rv = ogs_gtp_xact_update_rx(new, type);
944
0
    if (rv == OGS_ERROR) {
945
0
        ogs_error("ogs_gtp_xact_update_rx() failed");
946
0
        ogs_gtp_xact_delete(new);
947
0
        return rv;
948
0
    } else if (rv == OGS_RETRY) {
949
0
        return rv;
950
0
    }
951
952
0
    *xact = new;
953
0
    return rv;
954
0
}
955
956
int ogs_gtp_xact_receive(
957
        ogs_gtp_node_t *gnode, ogs_gtp2_header_t *h, ogs_gtp_xact_t **xact)
958
0
{
959
0
    int rv;
960
0
    char buf[OGS_ADDRSTRLEN];
961
962
0
    uint8_t type;
963
0
    uint32_t sqn, xid;
964
0
    ogs_gtp_xact_stage_t stage;
965
0
    ogs_list_t *list = NULL;
966
0
    ogs_gtp_xact_t *new = NULL;
967
968
0
    ogs_assert(gnode);
969
0
    ogs_assert(h);
970
971
0
    type = h->type;
972
973
0
    if (h->teid_presence) sqn = h->sqn;
974
0
    else sqn = h->sqn_only;
975
976
0
    xid = OGS_GTP2_SQN_TO_XID(sqn);
977
0
    stage = ogs_gtp2_xact_get_stage(type, xid);
978
979
0
    switch (stage) {
980
0
    case GTP_XACT_INITIAL_STAGE:
981
0
        list = &gnode->remote_list;
982
0
        break;
983
0
    case GTP_XACT_INTERMEDIATE_STAGE:
984
0
        list = &gnode->local_list;
985
0
        break;
986
0
    case GTP_XACT_FINAL_STAGE:
987
0
        if (xid & OGS_GTP_CMD_XACT_ID) {
988
0
            if (type == OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE ||
989
0
                type == OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE ||
990
0
                type == OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE) {
991
0
                list = &gnode->local_list;
992
0
            } else {
993
0
                list = &gnode->remote_list;
994
0
            }
995
0
        } else {
996
0
            list = &gnode->local_list;
997
0
        }
998
0
        break;
999
0
    default:
1000
0
        ogs_error("[%d] Unexpected type %u from GTPv2 peer [%s]:%d",
1001
0
                xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
1002
0
        return OGS_ERROR;
1003
0
    }
1004
1005
0
    ogs_assert(list);
1006
0
    ogs_list_for_each(list, new) {
1007
0
        if (new->gtp_version == 2 && new->xid == xid) {
1008
0
            ogs_debug("[%d] %s Find GTPv%u peer [%s]:%d",
1009
0
                    new->xid,
1010
0
                    new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
1011
0
                    new->gtp_version,
1012
0
                    OGS_ADDR(&gnode->addr, buf),
1013
0
                    OGS_PORT(&gnode->addr));
1014
0
            break;
1015
0
        }
1016
0
    }
1017
1018
0
    if (!new) {
1019
0
        ogs_debug("[%d] Cannot find xact type %u from GTPv2 peer [%s]:%d",
1020
0
                  xid, type, OGS_ADDR(&gnode->addr, buf), OGS_PORT(&gnode->addr));
1021
0
        new = ogs_gtp_xact_remote_create(gnode, 2, sqn);
1022
0
    }
1023
0
    ogs_assert(new);
1024
1025
0
    ogs_debug("[%d] %s Receive peer [%s]:%d",
1026
0
            new->xid,
1027
0
            new->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
1028
0
            OGS_ADDR(&gnode->addr, buf),
1029
0
            OGS_PORT(&gnode->addr));
1030
1031
0
    rv = ogs_gtp_xact_update_rx(new, type);
1032
0
    if (rv == OGS_ERROR) {
1033
0
        ogs_error("ogs_gtp_xact_update_rx() failed");
1034
0
        ogs_gtp_xact_delete(new);
1035
0
        return rv;
1036
0
    } else if (rv == OGS_RETRY) {
1037
0
        return rv;
1038
0
    }
1039
1040
0
    *xact = new;
1041
0
    return rv;
1042
0
}
1043
1044
static ogs_gtp_xact_stage_t ogs_gtp1_xact_get_stage(uint8_t type, uint32_t xid)
1045
0
{
1046
0
    ogs_gtp_xact_stage_t stage = GTP_XACT_UNKNOWN_STAGE;
1047
1048
0
    switch (type) {
1049
0
    case OGS_GTP1_ECHO_REQUEST_TYPE:
1050
0
    case OGS_GTP1_NODE_ALIVE_REQUEST_TYPE:
1051
0
    case OGS_GTP1_REDIRECTION_REQUEST_TYPE:
1052
0
    case OGS_GTP1_CREATE_PDP_CONTEXT_REQUEST_TYPE:
1053
0
    case OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE:
1054
0
    case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE:
1055
0
    case OGS_GTP1_INITIATE_PDP_CONTEXT_ACTIVATION_REQUEST_TYPE:
1056
0
    case OGS_GTP1_PDU_NOTIFICATION_REQUEST_TYPE:
1057
0
    case OGS_GTP1_PDU_NOTIFICATION_REJECT_REQUEST_TYPE:
1058
0
    case OGS_GTP1_SEND_ROUTEING_INFORMATION_FOR_GPRS_REQUEST_TYPE:
1059
0
    case OGS_GTP1_FAILURE_REPORT_REQUEST_TYPE:
1060
0
    case OGS_GTP1_NOTE_MS_GPRS_PRESENT_REQUEST_TYPE:
1061
0
    case OGS_GTP1_IDENTIFICATION_REQUEST_TYPE:
1062
0
    case OGS_GTP1_SGSN_CONTEXT_REQUEST_TYPE:
1063
0
    case OGS_GTP1_FORWARD_RELOCATION_REQUEST_TYPE:
1064
0
    case OGS_GTP1_RELOCATION_CANCEL_REQUEST_TYPE:
1065
0
    case OGS_GTP1_UE_REGISTRATION_QUERY_REQUEST_TYPE:
1066
0
    case OGS_GTP1_RAN_INFORMATION_RELAY_TYPE:
1067
0
        stage = GTP_XACT_INITIAL_STAGE;
1068
0
        break;
1069
0
    case OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE:
1070
0
        stage = GTP_XACT_INTERMEDIATE_STAGE;
1071
0
        break;
1072
0
    case OGS_GTP1_ECHO_RESPONSE_TYPE:
1073
0
    case OGS_GTP1_NODE_ALIVE_RESPONSE_TYPE:
1074
0
    case OGS_GTP1_REDIRECTION_RESPONSE_TYPE:
1075
0
    case OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE:
1076
0
    case OGS_GTP1_UPDATE_PDP_CONTEXT_RESPONSE_TYPE:
1077
0
    case OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE:
1078
0
    case OGS_GTP1_INITIATE_PDP_CONTEXT_ACTIVATION_RESPONSE_TYPE:
1079
0
    case OGS_GTP1_PDU_NOTIFICATION_RESPONSE_TYPE:
1080
0
    case OGS_GTP1_PDU_NOTIFICATION_REJECT_RESPONSE_TYPE:
1081
0
    case OGS_GTP1_SEND_ROUTEING_INFORMATION_FOR_GPRS_RESPONSE_TYPE:
1082
0
    case OGS_GTP1_FAILURE_REPORT_RESPONSE_TYPE:
1083
0
    case OGS_GTP1_NOTE_MS_GPRS_PRESENT_RESPONSE_TYPE:
1084
0
    case OGS_GTP1_IDENTIFICATION_RESPONSE_TYPE:
1085
0
    case OGS_GTP1_SGSN_CONTEXT_ACKNOWLEDGE_TYPE:
1086
0
    case OGS_GTP1_FORWARD_RELOCATION_RESPONSE_TYPE:
1087
0
    case OGS_GTP1_RELOCATION_CANCEL_RESPONSE_TYPE:
1088
0
    case OGS_GTP1_UE_REGISTRATION_QUERY_RESPONSE_TYPE:
1089
0
        stage = GTP_XACT_FINAL_STAGE;
1090
0
        break;
1091
1092
0
    default:
1093
0
        ogs_error("Not implemented GTPv1 Message Type(%d)", type);
1094
0
        break;
1095
0
    }
1096
1097
0
    return stage;
1098
0
}
1099
1100
/* TS 29.274 Table 6.1-1 */
1101
static ogs_gtp_xact_stage_t ogs_gtp2_xact_get_stage(uint8_t type, uint32_t xid)
1102
0
{
1103
0
    ogs_gtp_xact_stage_t stage = GTP_XACT_UNKNOWN_STAGE;
1104
1105
0
    switch (type) {
1106
0
    case OGS_GTP2_ECHO_REQUEST_TYPE:
1107
0
    case OGS_GTP2_CREATE_SESSION_REQUEST_TYPE:
1108
0
    case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE:
1109
0
    case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE:
1110
0
    case OGS_GTP2_CHANGE_NOTIFICATION_REQUEST_TYPE:
1111
0
    case OGS_GTP2_REMOTE_UE_REPORT_NOTIFICATION_TYPE:
1112
0
    case OGS_GTP2_MODIFY_BEARER_COMMAND_TYPE:
1113
0
    case OGS_GTP2_DELETE_BEARER_COMMAND_TYPE:
1114
0
    case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE:
1115
0
    case OGS_GTP2_TRACE_SESSION_ACTIVATION_TYPE:
1116
0
    case OGS_GTP2_TRACE_SESSION_DEACTIVATION_TYPE:
1117
0
    case OGS_GTP2_STOP_PAGING_INDICATION_TYPE:
1118
0
    case OGS_GTP2_DELETE_PDN_CONNECTION_SET_REQUEST_TYPE:
1119
0
    case OGS_GTP2_PGW_DOWNLINK_TRIGGERING_NOTIFICATION_TYPE:
1120
0
    case OGS_GTP2_CREATE_FORWARDING_TUNNEL_REQUEST_TYPE:
1121
0
    case OGS_GTP2_SUSPEND_NOTIFICATION_TYPE:
1122
0
    case OGS_GTP2_RESUME_NOTIFICATION_TYPE:
1123
0
    case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
1124
0
    case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
1125
0
    case OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE:
1126
0
    case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE:
1127
0
    case OGS_GTP2_PGW_RESTART_NOTIFICATION_TYPE:
1128
0
    case OGS_GTP2_UPDATE_PDN_CONNECTION_SET_REQUEST_TYPE:
1129
0
    case OGS_GTP2_MODIFY_ACCESS_BEARERS_REQUEST_TYPE:
1130
0
        stage = GTP_XACT_INITIAL_STAGE;
1131
0
        break;
1132
0
    case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE:
1133
0
    case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE:
1134
0
    case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE:
1135
0
        if (xid & OGS_GTP_CMD_XACT_ID)
1136
0
            stage = GTP_XACT_INTERMEDIATE_STAGE;
1137
0
        else
1138
0
            stage = GTP_XACT_INITIAL_STAGE;
1139
0
        break;
1140
0
    case OGS_GTP2_ECHO_RESPONSE_TYPE:
1141
0
    case OGS_GTP2_VERSION_NOT_SUPPORTED_INDICATION_TYPE:
1142
0
    case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE:
1143
0
    case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE:
1144
0
    case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE:
1145
0
    case OGS_GTP2_CHANGE_NOTIFICATION_RESPONSE_TYPE:
1146
0
    case OGS_GTP2_REMOTE_UE_REPORT_ACKNOWLEDGE_TYPE:
1147
0
    case OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE:
1148
0
    case OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE:
1149
0
    case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
1150
0
    case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION_TYPE:
1151
0
    case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE:
1152
0
    case OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE:
1153
0
    case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE:
1154
0
    case OGS_GTP2_DELETE_PDN_CONNECTION_SET_RESPONSE_TYPE:
1155
0
    case OGS_GTP2_PGW_DOWNLINK_TRIGGERING_ACKNOWLEDGE_TYPE:
1156
0
    case OGS_GTP2_CREATE_FORWARDING_TUNNEL_RESPONSE_TYPE:
1157
0
    case OGS_GTP2_SUSPEND_ACKNOWLEDGE_TYPE:
1158
0
    case OGS_GTP2_RESUME_ACKNOWLEDGE_TYPE:
1159
0
    case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
1160
0
    case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
1161
0
    case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
1162
0
    case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE:
1163
0
    case OGS_GTP2_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE_TYPE:
1164
0
    case OGS_GTP2_UPDATE_PDN_CONNECTION_SET_RESPONSE_TYPE:
1165
0
    case OGS_GTP2_MODIFY_ACCESS_BEARERS_RESPONSE_TYPE:
1166
0
        stage = GTP_XACT_FINAL_STAGE;
1167
0
        break;
1168
1169
0
    default:
1170
0
        ogs_error("Not implemented GTPv2 Message Type(%d)", type);
1171
0
        break;
1172
0
    }
1173
1174
0
    return stage;
1175
0
}
1176
1177
void ogs_gtp_xact_associate(ogs_gtp_xact_t *xact1, ogs_gtp_xact_t *xact2)
1178
0
{
1179
0
    ogs_assert(xact1);
1180
0
    ogs_assert(xact2);
1181
1182
0
    ogs_assert(xact1->assoc_xact_id == OGS_INVALID_POOL_ID);
1183
0
    ogs_assert(xact2->assoc_xact_id == OGS_INVALID_POOL_ID);
1184
1185
0
    xact1->assoc_xact_id = xact2->id;
1186
0
    xact2->assoc_xact_id = xact1->id;
1187
0
}
1188
1189
void ogs_gtp_xact_deassociate(ogs_gtp_xact_t *xact1, ogs_gtp_xact_t *xact2)
1190
0
{
1191
0
    ogs_assert(xact1);
1192
0
    ogs_assert(xact2);
1193
1194
0
    ogs_assert(xact1->assoc_xact_id != OGS_INVALID_POOL_ID);
1195
0
    ogs_assert(xact2->assoc_xact_id != OGS_INVALID_POOL_ID);
1196
1197
0
    xact1->assoc_xact_id = OGS_INVALID_POOL_ID;
1198
0
    xact2->assoc_xact_id = OGS_INVALID_POOL_ID;
1199
0
}
1200
1201
static int ogs_gtp_xact_delete(ogs_gtp_xact_t *xact)
1202
0
{
1203
0
    char buf[OGS_ADDRSTRLEN];
1204
0
    ogs_gtp_xact_t *assoc_xact = NULL;
1205
1206
0
    ogs_assert(xact);
1207
0
    ogs_assert(xact->gnode);
1208
1209
0
    ogs_debug("[%d] %s Delete  peer [%s]:%d",
1210
0
            xact->xid,
1211
0
            xact->org == OGS_GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
1212
0
            OGS_ADDR(&xact->gnode->addr, buf),
1213
0
            OGS_PORT(&xact->gnode->addr));
1214
1215
0
    if (xact->seq[0].pkbuf)
1216
0
        ogs_pkbuf_free(xact->seq[0].pkbuf);
1217
0
    if (xact->seq[1].pkbuf)
1218
0
        ogs_pkbuf_free(xact->seq[1].pkbuf);
1219
0
    if (xact->seq[2].pkbuf)
1220
0
        ogs_pkbuf_free(xact->seq[2].pkbuf);
1221
1222
0
    if (xact->tm_response)
1223
0
        ogs_timer_delete(xact->tm_response);
1224
0
    if (xact->tm_holding)
1225
0
        ogs_timer_delete(xact->tm_holding);
1226
0
    if (xact->tm_peer)
1227
0
        ogs_timer_delete(xact->tm_peer);
1228
1229
0
    assoc_xact = ogs_gtp_xact_find_by_id(xact->assoc_xact_id);
1230
0
    if (assoc_xact)
1231
0
        ogs_gtp_xact_deassociate(xact, assoc_xact);
1232
1233
0
    ogs_list_remove(xact->org == OGS_GTP_LOCAL_ORIGINATOR ?
1234
0
            &xact->gnode->local_list : &xact->gnode->remote_list, xact);
1235
0
    ogs_pool_id_free(&pool, xact);
1236
1237
0
    return OGS_OK;
1238
0
}