/src/open5gs/lib/gtp/path.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 | | ogs_sock_t *ogs_gtp_server(ogs_socknode_t *node) |
23 | 0 | { |
24 | 0 | char buf[OGS_ADDRSTRLEN]; |
25 | 0 | ogs_sock_t *gtp; |
26 | 0 | ogs_assert(node); |
27 | | |
28 | 0 | gtp = ogs_udp_server(node->addr, node->option); |
29 | 0 | if (gtp) { |
30 | 0 | ogs_info("gtp_server() [%s]:%d", |
31 | 0 | OGS_ADDR(node->addr, buf), OGS_PORT(node->addr)); |
32 | |
|
33 | 0 | node->sock = gtp; |
34 | 0 | } |
35 | |
|
36 | 0 | return gtp; |
37 | 0 | } |
38 | | |
39 | | int ogs_gtp_connect(ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_gtp_node_t *gnode) |
40 | 0 | { |
41 | 0 | ogs_sockaddr_t *addr; |
42 | 0 | char buf[OGS_ADDRSTRLEN]; |
43 | |
|
44 | 0 | ogs_assert(ipv4 || ipv6); |
45 | 0 | ogs_assert(gnode); |
46 | 0 | ogs_assert(gnode->sa_list); |
47 | | |
48 | 0 | addr = gnode->sa_list; |
49 | 0 | while (addr) { |
50 | 0 | ogs_sock_t *sock = NULL; |
51 | |
|
52 | 0 | if (addr->ogs_sa_family == AF_INET) |
53 | 0 | sock = ipv4; |
54 | 0 | else if (addr->ogs_sa_family == AF_INET6) |
55 | 0 | sock = ipv6; |
56 | 0 | else |
57 | 0 | ogs_assert_if_reached(); |
58 | | |
59 | 0 | if (sock) { |
60 | 0 | ogs_info("gtp_connect() [%s]:%d", |
61 | 0 | OGS_ADDR(addr, buf), OGS_PORT(addr)); |
62 | |
|
63 | 0 | gnode->sock = sock; |
64 | 0 | memcpy(&gnode->addr, addr, sizeof gnode->addr); |
65 | 0 | break; |
66 | 0 | } |
67 | | |
68 | 0 | addr = addr->next; |
69 | 0 | } |
70 | | |
71 | 0 | if (addr == NULL) { |
72 | 0 | ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, |
73 | 0 | "gtp_connect() [%s]:%d failed", |
74 | 0 | OGS_ADDR(gnode->sa_list, buf), OGS_PORT(gnode->sa_list)); |
75 | 0 | return OGS_ERROR; |
76 | 0 | } |
77 | | |
78 | 0 | return OGS_OK; |
79 | 0 | } |
80 | | |
81 | | int ogs_gtp_send(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf) |
82 | 0 | { |
83 | 0 | ssize_t sent; |
84 | 0 | ogs_sock_t *sock = NULL; |
85 | |
|
86 | 0 | ogs_assert(gnode); |
87 | 0 | ogs_assert(pkbuf); |
88 | 0 | sock = gnode->sock; |
89 | 0 | ogs_assert(sock); |
90 | | |
91 | 0 | sent = ogs_send(sock->fd, pkbuf->data, pkbuf->len, 0); |
92 | 0 | if (sent < 0 || sent != pkbuf->len) { |
93 | 0 | if (ogs_socket_errno != OGS_EAGAIN) { |
94 | 0 | ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, |
95 | 0 | "ogs_gtp_send() failed"); |
96 | 0 | } |
97 | 0 | return OGS_ERROR; |
98 | 0 | } |
99 | | |
100 | 0 | return OGS_OK; |
101 | 0 | } |
102 | | |
103 | | int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf) |
104 | 0 | { |
105 | 0 | ssize_t sent; |
106 | 0 | ogs_sock_t *sock = NULL; |
107 | 0 | ogs_sockaddr_t *addr = NULL; |
108 | |
|
109 | 0 | ogs_assert(gnode); |
110 | 0 | ogs_assert(pkbuf); |
111 | 0 | sock = gnode->sock; |
112 | 0 | ogs_assert(sock); |
113 | 0 | addr = &gnode->addr; |
114 | 0 | ogs_assert(addr); |
115 | | |
116 | 0 | sent = ogs_sendto(sock->fd, pkbuf->data, pkbuf->len, 0, addr); |
117 | 0 | if (sent < 0 || sent != pkbuf->len) { |
118 | 0 | if (ogs_socket_errno != OGS_EAGAIN) { |
119 | 0 | char buf[OGS_ADDRSTRLEN]; |
120 | 0 | int err = ogs_socket_errno; |
121 | 0 | ogs_log_message(OGS_LOG_ERROR, err, |
122 | 0 | "ogs_gtp_sendto(%u, %p, %u, 0, %s:%u) failed", |
123 | 0 | sock->fd, pkbuf->data, pkbuf->len, |
124 | 0 | OGS_ADDR(addr, buf), OGS_PORT(addr)); |
125 | 0 | } |
126 | 0 | return OGS_ERROR; |
127 | 0 | } |
128 | | |
129 | 0 | return OGS_OK; |
130 | 0 | } |
131 | | |
132 | | void ogs_gtp_send_error_message( |
133 | | ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value) |
134 | 0 | { |
135 | 0 | switch (xact->gtp_version) { |
136 | 0 | case 1: |
137 | 0 | ogs_gtp1_send_error_message(xact, teid, type, cause_value); |
138 | 0 | break; |
139 | 0 | case 2: |
140 | 0 | ogs_gtp2_send_error_message(xact, teid, type, cause_value); |
141 | 0 | break; |
142 | 0 | } |
143 | 0 | } |