Coverage Report

Created: 2026-01-09 06:23

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