Coverage Report

Created: 2026-03-16 06:53

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