Coverage Report

Created: 2025-07-11 06:44

/src/open5gs/lib/gtp/context.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
3
 *
4
 * This file is part of Open5GS.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include "ogs-gtp.h"
21
22
int __ogs_gtp_domain;
23
static ogs_gtp_context_t self;
24
static int context_initialized = 0;
25
26
static OGS_POOL(pool, ogs_gtp_node_t);
27
static OGS_POOL(ogs_gtpu_resource_pool, ogs_gtpu_resource_t);
28
29
void ogs_gtp_context_init(int num_of_gtpu_resource)
30
0
{
31
0
    ogs_assert(context_initialized == 0);
32
33
    /* Initialize GTP context */
34
0
    memset(&self, 0, sizeof(ogs_gtp_context_t));
35
36
0
    ogs_log_install_domain(&__ogs_gtp_domain, "gtp", ogs_core()->log.level);
37
38
0
    ogs_pool_init(&pool, ogs_app()->pool.gtp_node);
39
0
    ogs_pool_init(&ogs_gtpu_resource_pool, num_of_gtpu_resource);
40
41
0
    context_initialized = 1;
42
0
}
43
44
void ogs_gtp_context_final(void)
45
0
{
46
0
    ogs_assert(context_initialized == 1);
47
48
0
    ogs_gtpu_resource_remove_all(&self.gtpu_resource_list);
49
0
    ogs_pool_final(&ogs_gtpu_resource_pool);
50
51
0
    ogs_gtp_node_remove_all(&self.gtpu_peer_list);
52
0
    ogs_pool_final(&pool);
53
54
0
    context_initialized = 0;
55
0
}
56
57
ogs_gtp_context_t *ogs_gtp_self(void)
58
0
{
59
0
    return &self;
60
0
}
61
62
static int ogs_gtp_context_prepare(void)
63
0
{
64
0
    self.gtpc_port = OGS_GTPV2_C_UDP_PORT;
65
0
    self.gtpu_port = OGS_GTPV1_U_UDP_PORT;
66
67
0
    return OGS_OK;
68
0
}
69
70
static int ogs_gtp_context_validation(const char *local)
71
0
{
72
0
    return OGS_OK;
73
0
}
74
75
int ogs_gtp_context_parse_config(const char *local, const char *remote)
76
0
{
77
0
    int rv;
78
0
    yaml_document_t *document = NULL;
79
0
    ogs_yaml_iter_t root_iter;
80
0
    int idx = 0;
81
82
0
    document = ogs_app()->document;
83
0
    ogs_assert(document);
84
85
0
    rv = ogs_gtp_context_prepare();
86
0
    if (rv != OGS_OK) return rv;
87
88
0
    ogs_yaml_iter_init(&root_iter, document);
89
0
    while (ogs_yaml_iter_next(&root_iter)) {
90
0
        const char *root_key = ogs_yaml_iter_key(&root_iter);
91
0
        ogs_assert(root_key);
92
0
        if ((!strcmp(root_key, local)) &&
93
0
            (idx++ == ogs_app()->config_section_id)) {
94
0
            ogs_yaml_iter_t local_iter;
95
0
            ogs_yaml_iter_recurse(&root_iter, &local_iter);
96
0
            while (ogs_yaml_iter_next(&local_iter)) {
97
0
                const char *local_key = ogs_yaml_iter_key(&local_iter);
98
0
                ogs_assert(local_key);
99
0
                if (!strcmp(local_key, "gtpc")) {
100
0
                    ogs_yaml_iter_t gtpc_iter;
101
0
                    ogs_yaml_iter_recurse(&local_iter, &gtpc_iter);
102
0
                    while (ogs_yaml_iter_next(&gtpc_iter)) {
103
0
                        const char *gtpc_key = ogs_yaml_iter_key(&gtpc_iter);
104
0
                        ogs_assert(gtpc_key);
105
0
                        if (!strcmp(gtpc_key, "server")) {
106
0
                            ogs_yaml_iter_t server_array, server_iter;
107
0
                            ogs_yaml_iter_recurse(&gtpc_iter, &server_array);
108
0
                            do {
109
0
                                int family = AF_UNSPEC;
110
0
                                int i, num = 0;
111
0
                                const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
112
0
                                uint16_t port = self.gtpc_port;
113
0
                                const char *dev = NULL;
114
0
                                ogs_sockaddr_t *addr = NULL;
115
116
0
                                ogs_sockopt_t option;
117
0
                                bool is_option = false;
118
119
0
                                if (ogs_yaml_iter_type(&server_array) ==
120
0
                                        YAML_MAPPING_NODE) {
121
0
                                    memcpy(&server_iter, &server_array,
122
0
                                            sizeof(ogs_yaml_iter_t));
123
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
124
0
                                    YAML_SEQUENCE_NODE) {
125
0
                                    if (!ogs_yaml_iter_next(&server_array))
126
0
                                        break;
127
0
                                    ogs_yaml_iter_recurse(
128
0
                                            &server_array, &server_iter);
129
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
130
0
                                    YAML_SCALAR_NODE) {
131
0
                                    break;
132
0
                                } else
133
0
                                    ogs_assert_if_reached();
134
135
0
                                while (ogs_yaml_iter_next(&server_iter)) {
136
0
                                    const char *server_key =
137
0
                                        ogs_yaml_iter_key(&server_iter);
138
0
                                    ogs_assert(server_key);
139
0
                                    if (!strcmp(server_key, "family")) {
140
0
                                        const char *v =
141
0
                                            ogs_yaml_iter_value(&server_iter);
142
0
                                        if (v) family = atoi(v);
143
0
                                        if (family != AF_UNSPEC &&
144
0
                                            family != AF_INET &&
145
0
                                            family != AF_INET6) {
146
0
                                            ogs_warn("Ignore family(%d) : "
147
0
                                                "AF_UNSPEC(%d), "
148
0
                                                "AF_INET(%d), AF_INET6(%d) ",
149
0
                                                family,
150
0
                                                AF_UNSPEC, AF_INET, AF_INET6);
151
0
                                            family = AF_UNSPEC;
152
0
                                        }
153
0
                                    } else if (!strcmp(server_key, "address")) {
154
0
                                        ogs_yaml_iter_t hostname_iter;
155
0
                                        ogs_yaml_iter_recurse(&server_iter,
156
0
                                                &hostname_iter);
157
0
                                        ogs_assert(ogs_yaml_iter_type(
158
0
                                                    &hostname_iter) !=
159
0
                                                YAML_MAPPING_NODE);
160
161
0
                                        do {
162
0
                                            if (ogs_yaml_iter_type(
163
0
                                                        &hostname_iter) ==
164
0
                                                    YAML_SEQUENCE_NODE) {
165
0
                                                if (!ogs_yaml_iter_next(
166
0
                                                            &hostname_iter))
167
0
                                                    break;
168
0
                                            }
169
170
0
                                            ogs_assert(num <
171
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
172
0
                                            hostname[num++] =
173
0
                                                ogs_yaml_iter_value(
174
0
                                                        &hostname_iter);
175
0
                                        } while (ogs_yaml_iter_type(
176
0
                                                    &hostname_iter) ==
177
0
                                                YAML_SEQUENCE_NODE);
178
0
                                    } else if (!strcmp(server_key, "port")) {
179
0
                                        const char *v =
180
0
                                            ogs_yaml_iter_value(&server_iter);
181
0
                                        if (v) port = atoi(v);
182
0
                                    } else if (!strcmp(server_key, "dev")) {
183
0
                                        dev = ogs_yaml_iter_value(&server_iter);
184
0
                                    } else if (!strcmp(server_key, "option")) {
185
0
                                        rv = ogs_app_parse_sockopt_config(
186
0
                                                &server_iter, &option);
187
0
                                        if (rv != OGS_OK) {
188
0
                                            ogs_error("ogs_app_parse_sockopt_"
189
0
                                                    "config() failed");
190
0
                                            return rv;
191
0
                                        }
192
0
                                        is_option = true;
193
0
                                    } else if (!strcmp(server_key, "tac")) {
194
                                        /* Nothing */
195
0
                                    } else if (!strcmp(
196
0
                                                server_key, "e_cell_id")) {
197
                                        /* Nothing */
198
0
                                    } else
199
0
                                        ogs_warn("unknown key `%s`",
200
0
                                                server_key);
201
0
                                }
202
203
                                /* Add address information */
204
0
                                addr = NULL;
205
0
                                for (i = 0; i < num; i++) {
206
0
                                    rv = ogs_addaddrinfo(&addr,
207
0
                                            family, hostname[i], port, 0);
208
0
                                    ogs_assert(rv == OGS_OK);
209
0
                                }
210
211
                                /* Add each address as a separate socknode */
212
0
                                if (addr) {
213
0
                                    ogs_sockaddr_t *current = addr;
214
0
                                    while (current) {
215
0
                                        if (current->ogs_sa_family ==
216
0
                                                AF_INET &&
217
0
                                            ogs_global_conf()->
218
0
                                                parameter.no_ipv4 == 0) {
219
0
                                            ogs_socknode_add(&self.gtpc_list,
220
0
                                                             AF_INET, current,
221
0
                                                             is_option ?
222
0
                                                             &option : NULL);
223
0
                                        }
224
0
                                        if (current->ogs_sa_family ==
225
0
                                                AF_INET6 &&
226
0
                                            ogs_global_conf()->
227
0
                                                parameter.no_ipv6 == 0) {
228
0
                                            ogs_socknode_add(&self.gtpc_list6,
229
0
                                                             AF_INET6, current,
230
0
                                                             is_option ?
231
0
                                                             &option : NULL);
232
0
                                        }
233
0
                                        current = current->next;
234
0
                                    }
235
0
                                    ogs_freeaddrinfo(addr);
236
0
                                }
237
238
0
                                if (dev) {
239
0
                                    rv = ogs_socknode_probe(
240
0
                                            ogs_global_conf()->parameter.
241
0
                                            no_ipv4 ?
242
0
                                                NULL : &self.gtpc_list,
243
0
                                            ogs_global_conf()->parameter.
244
0
                                            no_ipv6 ?
245
0
                                                NULL : &self.gtpc_list6,
246
0
                                            dev, port,
247
0
                                            is_option ? &option : NULL);
248
0
                                    ogs_assert(rv == OGS_OK);
249
0
                                }
250
251
0
                            } while (ogs_yaml_iter_type(&server_array) ==
252
0
                                    YAML_SEQUENCE_NODE);
253
254
0
                        } else if (!strcmp(gtpc_key, "client")) {
255
                            /* handle config in application */
256
0
                        } else
257
0
                            ogs_warn("unknown key `%s`", gtpc_key);
258
0
                    }
259
0
                } else if (!strcmp(local_key, "gtpu")) {
260
0
                    ogs_list_t list, list6;
261
0
                    ogs_socknode_t *node = NULL, *node6 = NULL;
262
0
                    ogs_socknode_t *iter = NULL, *next_iter = NULL;
263
264
0
                    ogs_yaml_iter_t gtpu_iter;
265
0
                    ogs_yaml_iter_recurse(&local_iter, &gtpu_iter);
266
0
                    while (ogs_yaml_iter_next(&gtpu_iter)) {
267
0
                        const char *gtpu_key = ogs_yaml_iter_key(&gtpu_iter);
268
0
                        ogs_assert(gtpu_key);
269
0
                        if (!strcmp(gtpu_key, "server")) {
270
0
                            ogs_yaml_iter_t server_array, server_iter;
271
0
                            ogs_yaml_iter_recurse(&gtpu_iter, &server_array);
272
0
                            do {
273
0
                                int family = AF_UNSPEC;
274
0
                                int i, num_of_hostname = 0;
275
0
                                const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
276
0
                                int num_of_advertise = 0;
277
0
                                const char *advertise[OGS_MAX_NUM_OF_HOSTNAME];
278
0
                                uint16_t port = self.gtpu_port;
279
0
                                const char *dev = NULL;
280
0
                                ogs_sockaddr_t *addr = NULL;
281
0
                                ogs_sockaddr_t *adv_addr = NULL;
282
0
                                ogs_sockaddr_t *adv_addr6 = NULL;
283
0
                                const char *teid_range_indication = NULL;
284
0
                                const char *teid_range = NULL;
285
0
                                const char *network_instance = NULL;
286
0
                                const char *source_interface = NULL;
287
288
0
                                ogs_sockopt_t option;
289
0
                                bool is_option = false;
290
291
0
                                if (ogs_yaml_iter_type(&server_array) ==
292
0
                                        YAML_MAPPING_NODE) {
293
0
                                    memcpy(&server_iter, &server_array,
294
0
                                            sizeof(ogs_yaml_iter_t));
295
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
296
0
                                        YAML_SEQUENCE_NODE) {
297
0
                                    if (!ogs_yaml_iter_next(&server_array))
298
0
                                        break;
299
0
                                    ogs_yaml_iter_recurse(
300
0
                                            &server_array, &server_iter);
301
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
302
0
                                    YAML_SCALAR_NODE) {
303
0
                                    break;
304
0
                                } else
305
0
                                    ogs_assert_if_reached();
306
307
0
                                while (ogs_yaml_iter_next(&server_iter)) {
308
0
                                    const char *server_key =
309
0
                                        ogs_yaml_iter_key(&server_iter);
310
0
                                    ogs_assert(server_key);
311
312
0
                                    if (ogs_list_count(
313
0
                                                &self.gtpu_resource_list) >=
314
0
                                        OGS_MAX_NUM_OF_GTPU_RESOURCE) {
315
0
                                        ogs_warn(
316
0
                                            "[Overflow]: Number of User Plane "
317
0
                                            "IP Resource <= %d",
318
0
                                            OGS_MAX_NUM_OF_GTPU_RESOURCE);
319
0
                                        break;
320
0
                                    }
321
322
0
                                    if (!strcmp(server_key, "family")) {
323
0
                                        const char *v =
324
0
                                            ogs_yaml_iter_value(&server_iter);
325
0
                                        if (v) family = atoi(v);
326
0
                                        if (family != AF_UNSPEC &&
327
0
                                            family != AF_INET &&
328
0
                                            family != AF_INET6) {
329
0
                                            ogs_warn("Ignore family(%d)"
330
0
                                                ": AF_UNSPEC(%d), "
331
0
                                                "AF_INET(%d), AF_INET6(%d) ",
332
0
                                                family,
333
0
                                                AF_UNSPEC, AF_INET, AF_INET6);
334
0
                                            family = AF_UNSPEC;
335
0
                                        }
336
0
                                    } else if (!strcmp(server_key, "address")) {
337
0
                                        ogs_yaml_iter_t hostname_iter;
338
0
                                        ogs_yaml_iter_recurse(&server_iter,
339
0
                                                &hostname_iter);
340
0
                                        ogs_assert(ogs_yaml_iter_type(
341
0
                                                    &hostname_iter) !=
342
0
                                                YAML_MAPPING_NODE);
343
344
0
                                        do {
345
0
                                            if (ogs_yaml_iter_type(
346
0
                                                        &hostname_iter) ==
347
0
                                                    YAML_SEQUENCE_NODE) {
348
0
                                                if (!ogs_yaml_iter_next(
349
0
                                                            &hostname_iter))
350
0
                                                    break;
351
0
                                            }
352
353
0
                                            ogs_assert(num_of_hostname <
354
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
355
0
                                            hostname[num_of_hostname++] =
356
0
                                                ogs_yaml_iter_value(
357
0
                                                        &hostname_iter);
358
0
                                        } while (ogs_yaml_iter_type(
359
0
                                                    &hostname_iter) ==
360
0
                                                YAML_SEQUENCE_NODE);
361
0
                                    } else if (!strcmp(server_key,
362
0
                                                "advertise")) {
363
0
                                        ogs_yaml_iter_t advertise_iter;
364
0
                                        ogs_yaml_iter_recurse(
365
0
                                                &server_iter, &advertise_iter);
366
0
                                        ogs_assert(ogs_yaml_iter_type(
367
0
                                                    &advertise_iter) !=
368
0
                                                YAML_MAPPING_NODE);
369
370
0
                                        do {
371
0
                                            if (ogs_yaml_iter_type(
372
0
                                                        &advertise_iter) ==
373
0
                                                    YAML_SEQUENCE_NODE) {
374
0
                                                if (!ogs_yaml_iter_next(
375
0
                                                            &advertise_iter))
376
0
                                                    break;
377
0
                                            }
378
379
0
                                            ogs_assert(num_of_advertise <
380
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
381
0
                                            advertise[num_of_advertise++] =
382
0
                                                ogs_yaml_iter_value(
383
0
                                                        &advertise_iter);
384
0
                                        } while (ogs_yaml_iter_type(
385
0
                                                    &advertise_iter) ==
386
0
                                                YAML_SEQUENCE_NODE);
387
0
                                    } else if (!strcmp(server_key, "port")) {
388
0
                                        const char *v =
389
0
                                            ogs_yaml_iter_value(&server_iter);
390
0
                                        if (v) port = atoi(v);
391
0
                                    } else if (!strcmp(server_key, "dev")) {
392
0
                                        dev = ogs_yaml_iter_value(&server_iter);
393
0
                                    } else if (!strcmp(server_key, "option")) {
394
0
                                        rv = ogs_app_parse_sockopt_config(
395
0
                                                &server_iter, &option);
396
0
                                        if (rv != OGS_OK) {
397
0
                                            ogs_error("ogs_app_parse_sockopt_"
398
0
                                                    "config() failed");
399
0
                                            return rv;
400
0
                                        }
401
0
                                        is_option = true;
402
0
                                    } else if (!strcmp(server_key,
403
0
                                                "teid_range_indication")) {
404
0
                                        teid_range_indication =
405
0
                                            ogs_yaml_iter_value(&server_iter);
406
0
                                    } else if (!strcmp(server_key,
407
0
                                                "teid_range")) {
408
0
                                        teid_range = ogs_yaml_iter_value(
409
0
                                                &server_iter);
410
0
                                    } else if (!strcmp(server_key,
411
0
                                                "network_instance")) {
412
0
                                        network_instance =
413
0
                                            ogs_yaml_iter_value(&server_iter);
414
0
                                    } else if (!strcmp(server_key,
415
0
                                                "source_interface")) {
416
0
                                        source_interface =
417
0
                                            ogs_yaml_iter_value(&server_iter);
418
0
                                    } else
419
0
                                        ogs_warn("unknown key `%s`",
420
0
                                                server_key);
421
0
                                }
422
423
0
                                addr = NULL;
424
0
                                for (i = 0; i < num_of_hostname; i++) {
425
0
                                    rv = ogs_addaddrinfo(&addr,
426
0
                                            family, hostname[i], port, 0);
427
0
                                    ogs_assert(rv == OGS_OK);
428
0
                                }
429
430
0
                                ogs_list_init(&list);
431
0
                                ogs_list_init(&list6);
432
433
0
                                if (addr) {
434
0
                                    ogs_sockaddr_t *current = addr;
435
0
                                    while (current) {
436
0
                                        if (current->ogs_sa_family ==
437
0
                                                AF_INET &&
438
0
                                            ogs_global_conf()->
439
0
                                                parameter.no_ipv4 == 0) {
440
0
                                            ogs_socknode_add(&list,
441
0
                                                             AF_INET, current,
442
0
                                                             is_option ?
443
0
                                                             &option : NULL);
444
0
                                        }
445
0
                                        if (current->ogs_sa_family ==
446
0
                                                AF_INET6 &&
447
0
                                            ogs_global_conf()->
448
0
                                                parameter.no_ipv6 == 0) {
449
0
                                            ogs_socknode_add(&list6,
450
0
                                                             AF_INET6, current,
451
0
                                                             is_option ?
452
0
                                                             &option : NULL);
453
0
                                        }
454
0
                                        current = current->next;
455
0
                                    }
456
0
                                    ogs_freeaddrinfo(addr);
457
0
                                }
458
459
0
                                if (dev) {
460
0
                                    rv = ogs_socknode_probe(
461
0
                                        ogs_global_conf()->parameter.no_ipv4 ?
462
0
                                        NULL : &list,
463
0
                                        ogs_global_conf()->parameter.no_ipv6 ?
464
0
                                        NULL : &list6,
465
0
                                        dev, port,
466
0
                                        is_option ? &option : NULL);
467
0
                                    ogs_assert(rv == OGS_OK);
468
0
                                }
469
470
0
                                adv_addr = NULL;
471
0
                                for (i = 0; i < num_of_advertise; i++) {
472
0
                                    rv = ogs_addaddrinfo(&adv_addr,
473
0
                                            family, advertise[i], port, 0);
474
0
                                    ogs_assert(rv == OGS_OK);
475
0
                                }
476
0
                                rv = ogs_copyaddrinfo(&adv_addr6, adv_addr);
477
0
                                ogs_assert(rv == OGS_OK);
478
479
0
                                rv = ogs_filteraddrinfo(&adv_addr, AF_INET);
480
0
                                ogs_assert(rv == OGS_OK);
481
0
                                rv = ogs_filteraddrinfo(&adv_addr6, AF_INET6);
482
0
                                ogs_assert(rv == OGS_OK);
483
484
0
                                if (adv_addr || adv_addr6) {
485
0
                                    rv = ogs_sockaddr_to_ip(
486
0
                                            adv_addr, adv_addr6,
487
0
                                            &self.gtpu_ip);
488
0
                                    ogs_assert(rv == OGS_OK);
489
0
                                }
490
491
                        /* Find first IPv4/IPv6 address in the list.
492
                         *
493
                         * In the following configuration,
494
                         * 127.0.0.4, 127.0.0.5 and 2001:db8:cafe::1 are ignored
495
                         * on PFCP Association Response message's
496
                         * user plane IP resource information.
497
                         *
498
                         * gtpu:
499
                         *   - addr:
500
                         *     - 127.0.0.3
501
                         *     - ::1
502
                         *     - 127.0.0.4
503
                         *     - 127.0.0.5
504
                         *     - 2001:db8:cafe::1
505
                         *
506
                         * To include all user plane IP resource information,
507
                         * configure as below:
508
                         *
509
                         * gtpu:
510
                         *   - addr:
511
                         *     - 127.0.0.3
512
                         *     - ::1
513
                         *   - addr: 127.0.0.4
514
                         *   - addr
515
                         *     - 127.0.0.5
516
                         *     - 2001:db8:cafe::1
517
                         */
518
0
                                node = ogs_list_first(&list);
519
0
                                node6 = ogs_list_first(&list6);
520
0
                                if (node || node6) {
521
0
                                    ogs_user_plane_ip_resource_info_t info;
522
523
0
                                    memset(&info, 0, sizeof(info));
524
0
                                    ogs_sockaddr_to_user_plane_ip_resource_info(
525
0
                                            adv_addr ? adv_addr :
526
0
                                                node ? node->addr : NULL,
527
0
                                            adv_addr6 ? adv_addr6 :
528
0
                                                node6 ? node6->addr : NULL,
529
0
                                            &info);
530
531
0
                                    if (teid_range_indication) {
532
0
                                        info.teidri = atoi(
533
0
                                                teid_range_indication);
534
0
                                        if (teid_range) {
535
0
                                            info.teid_range = atoi(teid_range);
536
0
                                        }
537
0
                                    }
538
0
                                    if (network_instance) {
539
0
                                        info.assoni = 1;
540
0
                                        ogs_cpystrn(info.network_instance,
541
0
                                            network_instance,
542
0
                                            OGS_MAX_APN_LEN+1);
543
0
                                    }
544
0
                                    if (source_interface) {
545
0
                                        info.assosi = 1;
546
0
                                        info.source_interface =
547
0
                                            atoi(source_interface);
548
0
                                    }
549
550
0
                                    ogs_gtpu_resource_add(
551
0
                                        &self.gtpu_resource_list, &info);
552
0
                                }
553
554
0
                                ogs_list_for_each_safe(&list, next_iter, iter)
555
0
                                    ogs_list_add(&self.gtpu_list, iter);
556
0
                                ogs_list_for_each_safe(&list6, next_iter, iter)
557
0
                                    ogs_list_add(&self.gtpu_list, iter);
558
559
0
                                ogs_freeaddrinfo(adv_addr);
560
0
                                ogs_freeaddrinfo(adv_addr6);
561
562
0
                            } while (ogs_yaml_iter_type(&server_array) ==
563
0
                                    YAML_SEQUENCE_NODE);
564
0
                        } else
565
0
                            ogs_warn("unknown key `%s`", gtpu_key);
566
0
                    }
567
0
                }
568
0
            }
569
0
        }
570
0
    }
571
572
0
    rv = ogs_gtp_context_validation(local);
573
0
    if (rv != OGS_OK) return rv;
574
575
0
    return OGS_OK;
576
0
}
577
578
ogs_gtp_node_t *ogs_gtp_node_new(ogs_sockaddr_t *sa_list)
579
0
{
580
0
    ogs_gtp_node_t *node = NULL;
581
582
0
    ogs_assert(sa_list);
583
584
0
    ogs_pool_alloc(&pool, &node);
585
0
    if (!node) {
586
0
        ogs_error("ogs_pool_alloc() failed");
587
0
        return NULL;
588
0
    }
589
0
    memset(node, 0, sizeof(ogs_gtp_node_t));
590
591
0
    node->sa_list = sa_list;
592
593
0
    ogs_list_init(&node->local_list);
594
0
    ogs_list_init(&node->remote_list);
595
596
0
    return node;
597
0
}
598
599
void ogs_gtp_node_free(ogs_gtp_node_t *node)
600
0
{
601
0
    ogs_assert(node);
602
603
0
    ogs_gtp_xact_delete_all(node);
604
605
0
    ogs_freeaddrinfo(node->sa_list);
606
0
    ogs_pool_free(&pool, node);
607
0
}
608
609
ogs_gtp_node_t *ogs_gtp_node_add_by_f_teid(
610
        ogs_list_t *list, ogs_gtp2_f_teid_t *f_teid, uint16_t port)
611
0
{
612
0
    int rv;
613
0
    ogs_gtp_node_t *node = NULL;
614
0
    ogs_sockaddr_t *addr = NULL;
615
616
0
    ogs_assert(list);
617
0
    ogs_assert(f_teid);
618
0
    ogs_assert(port);
619
620
0
    rv = ogs_gtp2_f_teid_to_sockaddr(f_teid, port, &addr);
621
0
    if (rv != OGS_OK) {
622
0
        ogs_error("ogs_gtp2_f_teid_to_sockaddr() failed");
623
0
        return NULL;
624
0
    }
625
626
0
    rv = ogs_filter_ip_version(
627
0
            &addr,
628
0
            ogs_global_conf()->parameter.no_ipv4,
629
0
            ogs_global_conf()->parameter.no_ipv6,
630
0
            ogs_global_conf()->parameter.prefer_ipv4);
631
0
    if (!addr) {
632
0
        ogs_error("ogs_filter_ip_version() failed");
633
0
        return NULL;
634
0
    }
635
636
#if 0 /* deprecated */
637
    rv = ogs_socknode_fill_scope_id_in_local(addr);
638
    ogs_assert(rv == OGS_OK);
639
#endif
640
641
0
    node = ogs_gtp_node_new(addr);
642
0
    if (!node) {
643
0
        ogs_error("ogs_gtp_node_new() failed");
644
0
        ogs_freeaddrinfo(addr);
645
0
        return NULL;
646
0
    }
647
648
0
    rv = ogs_gtp2_f_teid_to_ip(f_teid, &node->ip);
649
0
    if (rv != OGS_OK) {
650
0
        ogs_error("ogs_gtp2_f_teid_to_ip() failed");
651
0
        ogs_freeaddrinfo(addr);
652
0
        return NULL;
653
0
    }
654
655
0
    ogs_list_add(list, node);
656
657
0
    return node;
658
0
}
659
660
ogs_gtp_node_t *ogs_gtp_node_add_by_addr(ogs_list_t *list, ogs_sockaddr_t *addr)
661
0
{
662
0
    ogs_gtp_node_t *gnode = NULL;
663
0
    ogs_sockaddr_t *new = NULL;
664
665
0
    ogs_assert(list);
666
0
    ogs_assert(addr);
667
668
0
    ogs_assert(OGS_OK == ogs_copyaddrinfo(&new, addr));
669
0
    gnode = ogs_gtp_node_new(new);
670
0
    if (!gnode) {
671
0
        ogs_error("ogs_gtp_node_new() failed");
672
0
        ogs_freeaddrinfo(new);
673
0
        return NULL;
674
0
    }
675
676
0
    memcpy(&gnode->addr, new, sizeof gnode->addr);
677
678
0
    ogs_list_add(list, gnode);
679
680
0
    return gnode;
681
0
}
682
683
void ogs_gtp_node_remove(ogs_list_t *list, ogs_gtp_node_t *node)
684
0
{
685
0
    ogs_assert(node);
686
687
0
    ogs_list_remove(list, node);
688
689
0
    ogs_gtp_node_free(node);
690
0
}
691
692
void ogs_gtp_node_remove_all(ogs_list_t *list)
693
0
{
694
0
    ogs_gtp_node_t *node = NULL, *next_node = NULL;
695
696
0
    ogs_list_for_each_safe(list, next_node, node)
697
0
        ogs_gtp_node_remove(list, node);
698
0
}
699
700
ogs_gtp_node_t *ogs_gtp_node_find_by_addr(
701
        ogs_list_t *list, ogs_sockaddr_t *addr)
702
0
{
703
0
    ogs_gtp_node_t *node = NULL;
704
705
0
    ogs_assert(list);
706
0
    ogs_assert(addr);
707
708
0
    ogs_list_for_each(list, node) {
709
0
        if (ogs_sockaddr_is_equal(&node->addr, addr) == true)
710
0
            break;
711
0
    }
712
713
0
    return node;
714
0
}
715
716
ogs_gtp_node_t *ogs_gtp_node_find_by_f_teid(
717
        ogs_list_t *list, ogs_gtp2_f_teid_t *f_teid)
718
0
{
719
0
    int rv;
720
0
    ogs_gtp_node_t *node = NULL;
721
0
    ogs_ip_t ip;
722
723
0
    ogs_assert(list);
724
0
    ogs_assert(f_teid);
725
726
0
    rv = ogs_gtp2_f_teid_to_ip(f_teid, &ip);
727
0
    ogs_assert(rv == OGS_OK);
728
729
0
    ogs_list_for_each(list, node) {
730
0
        if (memcmp(&node->ip, &ip, sizeof(ip)) == 0)
731
0
            break;
732
0
    }
733
734
0
    return node;
735
0
}
736
737
ogs_gtp_node_t *ogs_gtp_node_add_by_ip(
738
        ogs_list_t *list, ogs_ip_t *ip, uint16_t port)
739
0
{
740
0
    int rv;
741
0
    ogs_gtp_node_t *node = NULL;
742
0
    ogs_sockaddr_t *addr = NULL;
743
744
0
    ogs_assert(list);
745
0
    ogs_assert(ip);
746
0
    ogs_assert(port);
747
748
0
    rv = ogs_ip_to_sockaddr(ip, port, &addr);
749
0
    if (rv != OGS_OK) {
750
0
        ogs_error("ogs_ip_to_sockaddr() failed");
751
0
        return NULL;
752
0
    }
753
754
0
    rv = ogs_filter_ip_version(
755
0
            &addr,
756
0
            ogs_global_conf()->parameter.no_ipv4,
757
0
            ogs_global_conf()->parameter.no_ipv6,
758
0
            ogs_global_conf()->parameter.prefer_ipv4);
759
0
    if (!addr) {
760
0
        ogs_error("ogs_filter_ip_version() failed");
761
0
        return NULL;
762
0
    }
763
764
#if 0 /* deprecated */
765
    rv = ogs_socknode_fill_scope_id_in_local(addr);
766
    ogs_assert(rv == OGS_OK);
767
#endif
768
769
0
    node = ogs_gtp_node_new(addr);
770
0
    if (!node) {
771
0
        ogs_error("ogs_gtp_node_new() failed");
772
0
        ogs_freeaddrinfo(addr);
773
0
        return NULL;
774
0
    }
775
776
0
    memcpy(&node->ip, ip, sizeof(*ip));
777
778
0
    ogs_list_add(list, node);
779
780
0
    return node;
781
0
}
782
783
ogs_gtp_node_t *ogs_gtp_node_find_by_ip(ogs_list_t *list, ogs_ip_t *ip)
784
0
{
785
0
    ogs_gtp_node_t *node = NULL;
786
787
0
    ogs_assert(list);
788
0
    ogs_assert(ip);
789
790
0
    ogs_list_for_each(list, node) {
791
0
        if (memcmp(&node->ip, ip, sizeof(*ip)) == 0)
792
0
            break;
793
0
    }
794
795
0
    return node;
796
0
}
797
798
ogs_gtpu_resource_t *ogs_gtpu_resource_add(ogs_list_t *list,
799
        ogs_user_plane_ip_resource_info_t *info)
800
0
{
801
0
    ogs_gtpu_resource_t *resource = NULL;
802
803
0
    ogs_assert(list);
804
0
    ogs_assert(info);
805
806
0
    ogs_pool_alloc(&ogs_gtpu_resource_pool, &resource);
807
0
    ogs_assert(resource);
808
809
0
    memcpy(&resource->info, info, sizeof(*info));
810
811
0
    ogs_list_add(list, resource);
812
813
0
    return resource;
814
0
}
815
816
void ogs_gtpu_resource_remove(ogs_list_t *list,
817
        ogs_gtpu_resource_t *resource)
818
0
{
819
0
    ogs_assert(list);
820
0
    ogs_assert(resource);
821
822
0
    ogs_list_remove(list, resource);
823
824
0
    ogs_pool_free(&ogs_gtpu_resource_pool, resource);
825
0
}
826
827
void ogs_gtpu_resource_remove_all(ogs_list_t *list)
828
0
{
829
0
    ogs_gtpu_resource_t *resource = NULL, *next_resource = NULL;
830
831
0
    ogs_assert(list);
832
833
0
    ogs_list_for_each_safe(list, next_resource, resource)
834
0
        ogs_gtpu_resource_remove(list, resource);
835
0
}