Coverage Report

Created: 2024-02-11 06:14

/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
81
0
    document = ogs_app()->document;
82
0
    ogs_assert(document);
83
84
0
    rv = ogs_gtp_context_prepare();
85
0
    if (rv != OGS_OK) return rv;
86
87
0
    ogs_yaml_iter_init(&root_iter, document);
88
0
    while (ogs_yaml_iter_next(&root_iter)) {
89
0
        const char *root_key = ogs_yaml_iter_key(&root_iter);
90
0
        ogs_assert(root_key);
91
0
        if (!strcmp(root_key, local)) {
92
0
            ogs_yaml_iter_t local_iter;
93
0
            ogs_yaml_iter_recurse(&root_iter, &local_iter);
94
0
            while (ogs_yaml_iter_next(&local_iter)) {
95
0
                const char *local_key = ogs_yaml_iter_key(&local_iter);
96
0
                ogs_assert(local_key);
97
0
                if (!strcmp(local_key, "gtpc")) {
98
0
                    ogs_yaml_iter_t gtpc_iter;
99
0
                    ogs_yaml_iter_recurse(&local_iter, &gtpc_iter);
100
0
                    while (ogs_yaml_iter_next(&gtpc_iter)) {
101
0
                        const char *gtpc_key = ogs_yaml_iter_key(&gtpc_iter);
102
0
                        ogs_assert(gtpc_key);
103
0
                        if (!strcmp(gtpc_key, "server")) {
104
0
                            ogs_yaml_iter_t server_array, server_iter;
105
0
                            ogs_yaml_iter_recurse(&gtpc_iter, &server_array);
106
0
                            do {
107
0
                                int family = AF_UNSPEC;
108
0
                                int i, num = 0;
109
0
                                const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
110
0
                                uint16_t port = self.gtpc_port;
111
0
                                const char *dev = NULL;
112
0
                                ogs_sockaddr_t *addr = NULL;
113
114
0
                                ogs_sockopt_t option;
115
0
                                bool is_option = false;
116
117
0
                                if (ogs_yaml_iter_type(&server_array) ==
118
0
                                        YAML_MAPPING_NODE) {
119
0
                                    memcpy(&server_iter, &server_array,
120
0
                                            sizeof(ogs_yaml_iter_t));
121
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
122
0
                                    YAML_SEQUENCE_NODE) {
123
0
                                    if (!ogs_yaml_iter_next(&server_array))
124
0
                                        break;
125
0
                                    ogs_yaml_iter_recurse(
126
0
                                            &server_array, &server_iter);
127
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
128
0
                                    YAML_SCALAR_NODE) {
129
0
                                    break;
130
0
                                } else
131
0
                                    ogs_assert_if_reached();
132
133
0
                                while (ogs_yaml_iter_next(&server_iter)) {
134
0
                                    const char *server_key =
135
0
                                        ogs_yaml_iter_key(&server_iter);
136
0
                                    ogs_assert(server_key);
137
0
                                    if (!strcmp(server_key, "family")) {
138
0
                                        const char *v =
139
0
                                            ogs_yaml_iter_value(&server_iter);
140
0
                                        if (v) family = atoi(v);
141
0
                                        if (family != AF_UNSPEC &&
142
0
                                            family != AF_INET &&
143
0
                                            family != AF_INET6) {
144
0
                                            ogs_warn("Ignore family(%d) : "
145
0
                                                "AF_UNSPEC(%d), "
146
0
                                                "AF_INET(%d), AF_INET6(%d) ",
147
0
                                                family,
148
0
                                                AF_UNSPEC, AF_INET, AF_INET6);
149
0
                                            family = AF_UNSPEC;
150
0
                                        }
151
0
                                    } else if (!strcmp(server_key, "address")) {
152
0
                                        ogs_yaml_iter_t hostname_iter;
153
0
                                        ogs_yaml_iter_recurse(&server_iter,
154
0
                                                &hostname_iter);
155
0
                                        ogs_assert(ogs_yaml_iter_type(
156
0
                                                    &hostname_iter) !=
157
0
                                                YAML_MAPPING_NODE);
158
159
0
                                        do {
160
0
                                            if (ogs_yaml_iter_type(
161
0
                                                        &hostname_iter) ==
162
0
                                                    YAML_SEQUENCE_NODE) {
163
0
                                                if (!ogs_yaml_iter_next(
164
0
                                                            &hostname_iter))
165
0
                                                    break;
166
0
                                            }
167
168
0
                                            ogs_assert(num <
169
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
170
0
                                            hostname[num++] =
171
0
                                                ogs_yaml_iter_value(
172
0
                                                        &hostname_iter);
173
0
                                        } while (ogs_yaml_iter_type(
174
0
                                                    &hostname_iter) ==
175
0
                                                YAML_SEQUENCE_NODE);
176
0
                                    } else if (!strcmp(server_key, "port")) {
177
0
                                        const char *v =
178
0
                                            ogs_yaml_iter_value(&server_iter);
179
0
                                        if (v) port = atoi(v);
180
0
                                    } else if (!strcmp(server_key, "dev")) {
181
0
                                        dev = ogs_yaml_iter_value(&server_iter);
182
0
                                    } else if (!strcmp(server_key, "option")) {
183
0
                                        rv = ogs_app_parse_sockopt_config(
184
0
                                                &server_iter, &option);
185
0
                                        if (rv != OGS_OK) {
186
0
                                            ogs_error("ogs_app_parse_sockopt_"
187
0
                                                    "config() failed");
188
0
                                            return rv;
189
0
                                        }
190
0
                                        is_option = true;
191
0
                                    } else if (!strcmp(server_key, "tac")) {
192
                                        /* Nothing */
193
0
                                    } else if (!strcmp(
194
0
                                                server_key, "e_cell_id")) {
195
                                        /* Nothing */
196
0
                                    } else
197
0
                                        ogs_warn("unknown key `%s`",
198
0
                                                server_key);
199
0
                                }
200
201
0
                                addr = NULL;
202
0
                                for (i = 0; i < num; i++) {
203
0
                                    rv = ogs_addaddrinfo(&addr,
204
0
                                            family, hostname[i], port, 0);
205
0
                                    ogs_assert(rv == OGS_OK);
206
0
                                }
207
208
0
                                if (addr) {
209
0
                                    if (ogs_global_conf()->parameter.
210
0
                                            no_ipv4 == 0)
211
0
                                        ogs_socknode_add(
212
0
                                            &self.gtpc_list, AF_INET, addr,
213
0
                                            is_option ? &option : NULL);
214
0
                                    if (ogs_global_conf()->parameter.
215
0
                                            no_ipv6 == 0)
216
0
                                        ogs_socknode_add(
217
0
                                            &self.gtpc_list6, AF_INET6, addr,
218
0
                                            is_option ? &option : NULL);
219
0
                                    ogs_freeaddrinfo(addr);
220
0
                                }
221
222
0
                                if (dev) {
223
0
                                    rv = ogs_socknode_probe(
224
0
                                            ogs_global_conf()->parameter.
225
0
                                            no_ipv4 ?
226
0
                                                NULL : &self.gtpc_list,
227
0
                                            ogs_global_conf()->parameter.
228
0
                                            no_ipv6 ?
229
0
                                                NULL : &self.gtpc_list6,
230
0
                                            dev, port,
231
0
                                            is_option ? &option : NULL);
232
0
                                    ogs_assert(rv == OGS_OK);
233
0
                                }
234
235
0
                            } while (ogs_yaml_iter_type(&server_array) ==
236
0
                                    YAML_SEQUENCE_NODE);
237
238
0
                        } else if (!strcmp(gtpc_key, "client")) {
239
                            /* handle config in application */
240
0
                        } else
241
0
                            ogs_warn("unknown key `%s`", gtpc_key);
242
0
                    }
243
0
                } else if (!strcmp(local_key, "gtpu")) {
244
0
                    ogs_list_t list, list6;
245
0
                    ogs_socknode_t *node = NULL, *node6 = NULL;
246
0
                    ogs_socknode_t *iter = NULL, *next_iter = NULL;
247
248
0
                    ogs_yaml_iter_t gtpu_iter;
249
0
                    ogs_yaml_iter_recurse(&local_iter, &gtpu_iter);
250
0
                    while (ogs_yaml_iter_next(&gtpu_iter)) {
251
0
                        const char *gtpu_key = ogs_yaml_iter_key(&gtpu_iter);
252
0
                        ogs_assert(gtpu_key);
253
0
                        if (!strcmp(gtpu_key, "server")) {
254
0
                            ogs_yaml_iter_t server_array, server_iter;
255
0
                            ogs_yaml_iter_recurse(&gtpu_iter, &server_array);
256
0
                            do {
257
0
                                int family = AF_UNSPEC;
258
0
                                int i, num_of_hostname = 0;
259
0
                                const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
260
0
                                int num_of_advertise = 0;
261
0
                                const char *advertise[OGS_MAX_NUM_OF_HOSTNAME];
262
0
                                uint16_t port = self.gtpu_port;
263
0
                                const char *dev = NULL;
264
0
                                ogs_sockaddr_t *addr = NULL;
265
0
                                ogs_sockaddr_t *adv_addr = NULL;
266
0
                                ogs_sockaddr_t *adv_addr6 = NULL;
267
0
                                const char *teid_range_indication = NULL;
268
0
                                const char *teid_range = NULL;
269
0
                                const char *network_instance = NULL;
270
0
                                const char *source_interface = NULL;
271
272
0
                                ogs_sockopt_t option;
273
0
                                bool is_option = false;
274
275
0
                                if (ogs_yaml_iter_type(&server_array) ==
276
0
                                        YAML_MAPPING_NODE) {
277
0
                                    memcpy(&server_iter, &server_array,
278
0
                                            sizeof(ogs_yaml_iter_t));
279
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
280
0
                                        YAML_SEQUENCE_NODE) {
281
0
                                    if (!ogs_yaml_iter_next(&server_array))
282
0
                                        break;
283
0
                                    ogs_yaml_iter_recurse(
284
0
                                            &server_array, &server_iter);
285
0
                                } else if (ogs_yaml_iter_type(&server_array) ==
286
0
                                    YAML_SCALAR_NODE) {
287
0
                                    break;
288
0
                                } else
289
0
                                    ogs_assert_if_reached();
290
291
0
                                while (ogs_yaml_iter_next(&server_iter)) {
292
0
                                    const char *server_key =
293
0
                                        ogs_yaml_iter_key(&server_iter);
294
0
                                    ogs_assert(server_key);
295
296
0
                                    if (ogs_list_count(
297
0
                                                &self.gtpu_resource_list) >=
298
0
                                        OGS_MAX_NUM_OF_GTPU_RESOURCE) {
299
0
                                        ogs_warn(
300
0
                                            "[Overflow]: Number of User Plane "
301
0
                                            "IP Resource <= %d",
302
0
                                            OGS_MAX_NUM_OF_GTPU_RESOURCE);
303
0
                                        break;
304
0
                                    }
305
306
0
                                    if (!strcmp(server_key, "family")) {
307
0
                                        const char *v =
308
0
                                            ogs_yaml_iter_value(&server_iter);
309
0
                                        if (v) family = atoi(v);
310
0
                                        if (family != AF_UNSPEC &&
311
0
                                            family != AF_INET &&
312
0
                                            family != AF_INET6) {
313
0
                                            ogs_warn("Ignore family(%d)"
314
0
                                                ": AF_UNSPEC(%d), "
315
0
                                                "AF_INET(%d), AF_INET6(%d) ",
316
0
                                                family,
317
0
                                                AF_UNSPEC, AF_INET, AF_INET6);
318
0
                                            family = AF_UNSPEC;
319
0
                                        }
320
0
                                    } else if (!strcmp(server_key, "address")) {
321
0
                                        ogs_yaml_iter_t hostname_iter;
322
0
                                        ogs_yaml_iter_recurse(&server_iter,
323
0
                                                &hostname_iter);
324
0
                                        ogs_assert(ogs_yaml_iter_type(
325
0
                                                    &hostname_iter) !=
326
0
                                                YAML_MAPPING_NODE);
327
328
0
                                        do {
329
0
                                            if (ogs_yaml_iter_type(
330
0
                                                        &hostname_iter) ==
331
0
                                                    YAML_SEQUENCE_NODE) {
332
0
                                                if (!ogs_yaml_iter_next(
333
0
                                                            &hostname_iter))
334
0
                                                    break;
335
0
                                            }
336
337
0
                                            ogs_assert(num_of_hostname <
338
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
339
0
                                            hostname[num_of_hostname++] =
340
0
                                                ogs_yaml_iter_value(
341
0
                                                        &hostname_iter);
342
0
                                        } while (ogs_yaml_iter_type(
343
0
                                                    &hostname_iter) ==
344
0
                                                YAML_SEQUENCE_NODE);
345
0
                                    } else if (!strcmp(server_key,
346
0
                                                "advertise")) {
347
0
                                        ogs_yaml_iter_t advertise_iter;
348
0
                                        ogs_yaml_iter_recurse(
349
0
                                                &server_iter, &advertise_iter);
350
0
                                        ogs_assert(ogs_yaml_iter_type(
351
0
                                                    &advertise_iter) !=
352
0
                                                YAML_MAPPING_NODE);
353
354
0
                                        do {
355
0
                                            if (ogs_yaml_iter_type(
356
0
                                                        &advertise_iter) ==
357
0
                                                    YAML_SEQUENCE_NODE) {
358
0
                                                if (!ogs_yaml_iter_next(
359
0
                                                            &advertise_iter))
360
0
                                                    break;
361
0
                                            }
362
363
0
                                            ogs_assert(num_of_advertise <
364
0
                                                    OGS_MAX_NUM_OF_HOSTNAME);
365
0
                                            advertise[num_of_advertise++] =
366
0
                                                ogs_yaml_iter_value(
367
0
                                                        &advertise_iter);
368
0
                                        } while (ogs_yaml_iter_type(
369
0
                                                    &advertise_iter) ==
370
0
                                                YAML_SEQUENCE_NODE);
371
0
                                    } else if (!strcmp(server_key, "port")) {
372
0
                                        const char *v =
373
0
                                            ogs_yaml_iter_value(&server_iter);
374
0
                                        if (v) port = atoi(v);
375
0
                                    } else if (!strcmp(server_key, "dev")) {
376
0
                                        dev = ogs_yaml_iter_value(&server_iter);
377
0
                                    } else if (!strcmp(server_key, "option")) {
378
0
                                        rv = ogs_app_parse_sockopt_config(
379
0
                                                &server_iter, &option);
380
0
                                        if (rv != OGS_OK) {
381
0
                                            ogs_error("ogs_app_parse_sockopt_"
382
0
                                                    "config() failed");
383
0
                                            return rv;
384
0
                                        }
385
0
                                        is_option = true;
386
0
                                    } else if (!strcmp(server_key,
387
0
                                                "teid_range_indication")) {
388
0
                                        teid_range_indication =
389
0
                                            ogs_yaml_iter_value(&server_iter);
390
0
                                    } else if (!strcmp(server_key,
391
0
                                                "teid_range")) {
392
0
                                        teid_range = ogs_yaml_iter_value(
393
0
                                                &server_iter);
394
0
                                    } else if (!strcmp(server_key,
395
0
                                                "network_instance")) {
396
0
                                        network_instance =
397
0
                                            ogs_yaml_iter_value(&server_iter);
398
0
                                    } else if (!strcmp(server_key,
399
0
                                                "source_interface")) {
400
0
                                        source_interface =
401
0
                                            ogs_yaml_iter_value(&server_iter);
402
0
                                    } else
403
0
                                        ogs_warn("unknown key `%s`",
404
0
                                                server_key);
405
0
                                }
406
407
0
                                addr = NULL;
408
0
                                for (i = 0; i < num_of_hostname; i++) {
409
0
                                    rv = ogs_addaddrinfo(&addr,
410
0
                                            family, hostname[i], port, 0);
411
0
                                    ogs_assert(rv == OGS_OK);
412
0
                                }
413
414
0
                                ogs_list_init(&list);
415
0
                                ogs_list_init(&list6);
416
417
0
                                if (addr) {
418
0
                                    if (ogs_global_conf()->parameter.
419
0
                                            no_ipv4 == 0)
420
0
                                        ogs_socknode_add(
421
0
                                            &list, AF_INET, addr,
422
0
                                            is_option ? &option : NULL);
423
0
                                    if (ogs_global_conf()->parameter.
424
0
                                            no_ipv6 == 0)
425
0
                                        ogs_socknode_add(
426
0
                                            &list6, AF_INET6, addr,
427
0
                                            is_option ? &option : NULL);
428
0
                                    ogs_freeaddrinfo(addr);
429
0
                                }
430
431
0
                                if (dev) {
432
0
                                    rv = ogs_socknode_probe(
433
0
                                        ogs_global_conf()->parameter.no_ipv4 ?
434
0
                                        NULL : &list,
435
0
                                        ogs_global_conf()->parameter.no_ipv6 ?
436
0
                                        NULL : &list6,
437
0
                                        dev, port,
438
0
                                        is_option ? &option : NULL);
439
0
                                    ogs_assert(rv == OGS_OK);
440
0
                                }
441
442
0
                                adv_addr = NULL;
443
0
                                for (i = 0; i < num_of_advertise; i++) {
444
0
                                    rv = ogs_addaddrinfo(&adv_addr,
445
0
                                            family, advertise[i], port, 0);
446
0
                                    ogs_assert(rv == OGS_OK);
447
0
                                }
448
0
                                rv = ogs_copyaddrinfo(&adv_addr6, adv_addr);
449
0
                                ogs_assert(rv == OGS_OK);
450
451
0
                                rv = ogs_filteraddrinfo(&adv_addr, AF_INET);
452
0
                                ogs_assert(rv == OGS_OK);
453
0
                                rv = ogs_filteraddrinfo(&adv_addr6, AF_INET6);
454
0
                                ogs_assert(rv == OGS_OK);
455
456
                        /* Find first IPv4/IPv6 address in the list.
457
                         *
458
                         * In the following configuration,
459
                         * 127.0.0.4, 127.0.0.5 and 2001:db8:cafe::1 are ignored
460
                         * on PFCP Assocation Response message's
461
                         * user plane IP resource information.
462
                         *
463
                         * gtpu:
464
                         *   - addr:
465
                         *     - 127.0.0.3
466
                         *     - ::1
467
                         *     - 127.0.0.4
468
                         *     - 127.0.0.5
469
                         *     - 2001:db8:cafe::1
470
                         *
471
                         * To include all user plane IP resource information,
472
                         * configure as below:
473
                         *
474
                         * gtpu:
475
                         *   - addr:
476
                         *     - 127.0.0.3
477
                         *     - ::1
478
                         *   - addr: 127.0.0.4
479
                         *   - addr
480
                         *     - 127.0.0.5
481
                         *     - 2001:db8:cafe::1
482
                         */
483
0
                                node = ogs_list_first(&list);
484
0
                                node6 = ogs_list_first(&list6);
485
0
                                if (node || node6) {
486
0
                                    ogs_user_plane_ip_resource_info_t info;
487
488
0
                                    memset(&info, 0, sizeof(info));
489
0
                                    ogs_sockaddr_to_user_plane_ip_resource_info(
490
0
                                            adv_addr ? adv_addr :
491
0
                                                node ? node->addr : NULL,
492
0
                                            adv_addr6 ? adv_addr6 :
493
0
                                                node6 ? node6->addr : NULL,
494
0
                                            &info);
495
496
0
                                    if (teid_range_indication) {
497
0
                                        info.teidri = atoi(
498
0
                                                teid_range_indication);
499
0
                                        if (teid_range) {
500
0
                                            info.teid_range = atoi(teid_range);
501
0
                                        }
502
0
                                    }
503
0
                                    if (network_instance) {
504
0
                                        info.assoni = 1;
505
0
                                        ogs_cpystrn(info.network_instance,
506
0
                                            network_instance,
507
0
                                            OGS_MAX_APN_LEN+1);
508
0
                                    }
509
0
                                    if (source_interface) {
510
0
                                        info.assosi = 1;
511
0
                                        info.source_interface =
512
0
                                            atoi(source_interface);
513
0
                                    }
514
515
0
                                    ogs_gtpu_resource_add(
516
0
                                        &self.gtpu_resource_list, &info);
517
0
                                }
518
519
0
                                ogs_list_for_each_safe(&list, next_iter, iter)
520
0
                                    ogs_list_add(&self.gtpu_list, iter);
521
0
                                ogs_list_for_each_safe(&list6, next_iter, iter)
522
0
                                    ogs_list_add(&self.gtpu_list, iter);
523
524
0
                                ogs_freeaddrinfo(adv_addr);
525
0
                                ogs_freeaddrinfo(adv_addr6);
526
527
0
                            } while (ogs_yaml_iter_type(&server_array) ==
528
0
                                    YAML_SEQUENCE_NODE);
529
0
                        } else
530
0
                            ogs_warn("unknown key `%s`", gtpu_key);
531
0
                    }
532
0
                }
533
0
            }
534
0
        }
535
0
    }
536
537
0
    rv = ogs_gtp_context_validation(local);
538
0
    if (rv != OGS_OK) return rv;
539
540
0
    return OGS_OK;
541
0
}
542
543
ogs_gtp_node_t *ogs_gtp_node_new(ogs_sockaddr_t *sa_list)
544
0
{
545
0
    ogs_gtp_node_t *node = NULL;
546
547
0
    ogs_assert(sa_list);
548
549
0
    ogs_pool_alloc(&pool, &node);
550
0
    if (!node) {
551
0
        ogs_error("ogs_pool_alloc() failed");
552
0
        return NULL;
553
0
    }
554
0
    memset(node, 0, sizeof(ogs_gtp_node_t));
555
556
0
    node->sa_list = sa_list;
557
558
0
    ogs_list_init(&node->local_list);
559
0
    ogs_list_init(&node->remote_list);
560
561
0
    return node;
562
0
}
563
564
void ogs_gtp_node_free(ogs_gtp_node_t *node)
565
0
{
566
0
    ogs_assert(node);
567
568
0
    ogs_gtp_xact_delete_all(node);
569
570
0
    ogs_freeaddrinfo(node->sa_list);
571
0
    ogs_pool_free(&pool, node);
572
0
}
573
574
ogs_gtp_node_t *ogs_gtp_node_add_by_f_teid(
575
        ogs_list_t *list, ogs_gtp2_f_teid_t *f_teid, uint16_t port)
576
0
{
577
0
    int rv;
578
0
    ogs_gtp_node_t *node = NULL;
579
0
    ogs_sockaddr_t *addr = NULL;
580
581
0
    ogs_assert(list);
582
0
    ogs_assert(f_teid);
583
0
    ogs_assert(port);
584
585
0
    rv = ogs_gtp2_f_teid_to_sockaddr(f_teid, port, &addr);
586
0
    if (rv != OGS_OK) {
587
0
        ogs_error("ogs_gtp2_f_teid_to_sockaddr() failed");
588
0
        return NULL;
589
0
    }
590
591
0
    rv = ogs_filter_ip_version(
592
0
            &addr,
593
0
            ogs_global_conf()->parameter.no_ipv4,
594
0
            ogs_global_conf()->parameter.no_ipv6,
595
0
            ogs_global_conf()->parameter.prefer_ipv4);
596
0
    if (!addr) {
597
0
        ogs_error("ogs_filter_ip_version() failed");
598
0
        return NULL;
599
0
    }
600
601
#if 0 /* deprecated */
602
    rv = ogs_socknode_fill_scope_id_in_local(addr);
603
    ogs_assert(rv == OGS_OK);
604
#endif
605
606
0
    node = ogs_gtp_node_new(addr);
607
0
    if (!node) {
608
0
        ogs_error("ogs_gtp_node_new() failed");
609
0
        ogs_freeaddrinfo(addr);
610
0
        return NULL;
611
0
    }
612
613
0
    rv = ogs_gtp2_f_teid_to_ip(f_teid, &node->ip);
614
0
    if (rv != OGS_OK) {
615
0
        ogs_error("ogs_gtp2_f_teid_to_ip() failed");
616
0
        ogs_freeaddrinfo(addr);
617
0
        return NULL;
618
0
    }
619
620
0
    ogs_list_add(list, node);
621
622
0
    return node;
623
0
}
624
625
ogs_gtp_node_t *ogs_gtp_node_add_by_addr(ogs_list_t *list, ogs_sockaddr_t *addr)
626
0
{
627
0
    ogs_gtp_node_t *gnode = NULL;
628
0
    ogs_sockaddr_t *new = NULL;
629
630
0
    ogs_assert(list);
631
0
    ogs_assert(addr);
632
633
0
    ogs_assert(OGS_OK == ogs_copyaddrinfo(&new, addr));
634
0
    gnode = ogs_gtp_node_new(new);
635
0
    if (!gnode) {
636
0
        ogs_error("ogs_gtp_node_new() failed");
637
0
        ogs_freeaddrinfo(new);
638
0
        return NULL;
639
0
    }
640
641
0
    memcpy(&gnode->addr, new, sizeof gnode->addr);
642
643
0
    ogs_list_add(list, gnode);
644
645
0
    return gnode;
646
0
}
647
648
void ogs_gtp_node_remove(ogs_list_t *list, ogs_gtp_node_t *node)
649
0
{
650
0
    ogs_assert(node);
651
652
0
    ogs_list_remove(list, node);
653
654
0
    ogs_gtp_node_free(node);
655
0
}
656
657
void ogs_gtp_node_remove_all(ogs_list_t *list)
658
0
{
659
0
    ogs_gtp_node_t *node = NULL, *next_node = NULL;
660
661
0
    ogs_list_for_each_safe(list, next_node, node)
662
0
        ogs_gtp_node_remove(list, node);
663
0
}
664
665
ogs_gtp_node_t *ogs_gtp_node_find_by_addr(
666
        ogs_list_t *list, ogs_sockaddr_t *addr)
667
0
{
668
0
    ogs_gtp_node_t *node = NULL;
669
670
0
    ogs_assert(list);
671
0
    ogs_assert(addr);
672
673
0
    ogs_list_for_each(list, node) {
674
0
        if (ogs_sockaddr_is_equal(&node->addr, addr) == true)
675
0
            break;
676
0
    }
677
678
0
    return node;
679
0
}
680
681
ogs_gtp_node_t *ogs_gtp_node_find_by_f_teid(
682
        ogs_list_t *list, ogs_gtp2_f_teid_t *f_teid)
683
0
{
684
0
    int rv;
685
0
    ogs_gtp_node_t *node = NULL;
686
0
    ogs_ip_t ip;
687
688
0
    ogs_assert(list);
689
0
    ogs_assert(f_teid);
690
691
0
    rv = ogs_gtp2_f_teid_to_ip(f_teid, &ip);
692
0
    ogs_assert(rv == OGS_OK);
693
694
0
    ogs_list_for_each(list, node) {
695
0
        if (memcmp(&node->ip, &ip, sizeof(ip)) == 0)
696
0
            break;
697
0
    }
698
699
0
    return node;
700
0
}
701
702
ogs_gtp_node_t *ogs_gtp_node_add_by_ip(
703
        ogs_list_t *list, ogs_ip_t *ip, uint16_t port)
704
0
{
705
0
    int rv;
706
0
    ogs_gtp_node_t *node = NULL;
707
0
    ogs_sockaddr_t *addr = NULL;
708
709
0
    ogs_assert(list);
710
0
    ogs_assert(ip);
711
0
    ogs_assert(port);
712
713
0
    rv = ogs_ip_to_sockaddr(ip, port, &addr);
714
0
    if (rv != OGS_OK) {
715
0
        ogs_error("ogs_ip_to_sockaddr() failed");
716
0
        return NULL;
717
0
    }
718
719
0
    rv = ogs_filter_ip_version(
720
0
            &addr,
721
0
            ogs_global_conf()->parameter.no_ipv4,
722
0
            ogs_global_conf()->parameter.no_ipv6,
723
0
            ogs_global_conf()->parameter.prefer_ipv4);
724
0
    if (!addr) {
725
0
        ogs_error("ogs_filter_ip_version() failed");
726
0
        return NULL;
727
0
    }
728
729
#if 0 /* deprecated */
730
    rv = ogs_socknode_fill_scope_id_in_local(addr);
731
    ogs_assert(rv == OGS_OK);
732
#endif
733
734
0
    node = ogs_gtp_node_new(addr);
735
0
    if (!node) {
736
0
        ogs_error("ogs_gtp_node_new() failed");
737
0
        ogs_freeaddrinfo(addr);
738
0
        return NULL;
739
0
    }
740
741
0
    memcpy(&node->ip, ip, sizeof(*ip));
742
743
0
    ogs_list_add(list, node);
744
745
0
    return node;
746
0
}
747
748
ogs_gtp_node_t *ogs_gtp_node_find_by_ip(ogs_list_t *list, ogs_ip_t *ip)
749
0
{
750
0
    ogs_gtp_node_t *node = NULL;
751
752
0
    ogs_assert(list);
753
0
    ogs_assert(ip);
754
755
0
    ogs_list_for_each(list, node) {
756
0
        if (memcmp(&node->ip, ip, sizeof(*ip)) == 0)
757
0
            break;
758
0
    }
759
760
0
    return node;
761
0
}
762
763
ogs_gtpu_resource_t *ogs_gtpu_resource_add(ogs_list_t *list,
764
        ogs_user_plane_ip_resource_info_t *info)
765
0
{
766
0
    ogs_gtpu_resource_t *resource = NULL;
767
768
0
    ogs_assert(list);
769
0
    ogs_assert(info);
770
771
0
    ogs_pool_alloc(&ogs_gtpu_resource_pool, &resource);
772
0
    ogs_assert(resource);
773
774
0
    memcpy(&resource->info, info, sizeof(*info));
775
776
0
    ogs_list_add(list, resource);
777
778
0
    return resource;
779
0
}
780
781
void ogs_gtpu_resource_remove(ogs_list_t *list,
782
        ogs_gtpu_resource_t *resource)
783
0
{
784
0
    ogs_assert(list);
785
0
    ogs_assert(resource);
786
787
0
    ogs_list_remove(list, resource);
788
789
0
    ogs_pool_free(&ogs_gtpu_resource_pool, resource);
790
0
}
791
792
void ogs_gtpu_resource_remove_all(ogs_list_t *list)
793
0
{
794
0
    ogs_gtpu_resource_t *resource = NULL, *next_resource = NULL;
795
796
0
    ogs_assert(list);
797
798
0
    ogs_list_for_each_safe(list, next_resource, resource)
799
0
        ogs_gtpu_resource_remove(list, resource);
800
0
}