diff options
Diffstat (limited to 'src/nat/nat_api_stun.c')
-rw-r--r-- | src/nat/nat_api_stun.c | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/src/nat/nat_api_stun.c b/src/nat/nat_api_stun.c deleted file mode 100644 index 0bc2c5fbd..000000000 --- a/src/nat/nat_api_stun.c +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2015, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * This code provides some support for doing STUN transactions. | ||
22 | * We send simplest possible packet ia REQUEST with BIND to a STUN server. | ||
23 | * | ||
24 | * All STUN packets start with a simple header made of a type, | ||
25 | * length (excluding the header) and a 16-byte random transaction id. | ||
26 | * Following the header we may have zero or more attributes, each | ||
27 | * structured as a type, length and a value (whose format depends | ||
28 | * on the type, but often contains addresses). | ||
29 | * Of course all fields are in network format. | ||
30 | * | ||
31 | * This code was based on ministun.c. | ||
32 | * | ||
33 | * @file nat/nat_api_stun.c | ||
34 | * @brief Functions for STUN functionality | ||
35 | * @author Bruno Souza Cabral | ||
36 | */ | ||
37 | |||
38 | #include "platform.h" | ||
39 | #include "gnunet_util_lib.h" | ||
40 | #include "gnunet_resolver_service.h" | ||
41 | #include "gnunet_nat_service.h" | ||
42 | |||
43 | |||
44 | #include "nat_stun.h" | ||
45 | |||
46 | #define LOG(kind, ...) GNUNET_log_from (kind, "stun", __VA_ARGS__) | ||
47 | |||
48 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Handle to a request given to the resolver. Can be used to cancel | ||
53 | * the request prior to the timeout or successful execution. Also | ||
54 | * used to track our internal state for the request. | ||
55 | */ | ||
56 | struct GNUNET_NAT_STUN_Handle | ||
57 | { | ||
58 | /** | ||
59 | * Handle to a pending DNS lookup request. | ||
60 | */ | ||
61 | struct GNUNET_RESOLVER_RequestHandle *dns_active; | ||
62 | |||
63 | /** | ||
64 | * Handle to the listen socket | ||
65 | */ | ||
66 | struct GNUNET_NETWORK_Handle *sock; | ||
67 | |||
68 | /** | ||
69 | * Stun server address | ||
70 | */ | ||
71 | char *stun_server; | ||
72 | |||
73 | /** | ||
74 | * Function to call when a error occurs | ||
75 | */ | ||
76 | GNUNET_NAT_TestCallback cb; | ||
77 | |||
78 | /** | ||
79 | * Closure for @e cb. | ||
80 | */ | ||
81 | void *cb_cls; | ||
82 | |||
83 | /** | ||
84 | * Do we got a DNS resolution successfully? | ||
85 | */ | ||
86 | int dns_success; | ||
87 | |||
88 | /** | ||
89 | * STUN port | ||
90 | */ | ||
91 | uint16_t stun_port; | ||
92 | }; | ||
93 | |||
94 | |||
95 | /** | ||
96 | * Encode a class and method to a compatible STUN format | ||
97 | * | ||
98 | * @param msg_class class to be converted | ||
99 | * @param method method to be converted | ||
100 | * @return message in a STUN compatible format | ||
101 | */ | ||
102 | static int | ||
103 | encode_message (enum StunClasses msg_class, | ||
104 | enum StunMethods method) | ||
105 | { | ||
106 | return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | ||
107 | | (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) | ||
108 | << 2); | ||
109 | } | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Fill the stun_header with a random request_id | ||
114 | * | ||
115 | * @param req, stun header to be filled | ||
116 | */ | ||
117 | static void | ||
118 | generate_request_id (struct stun_header *req) | ||
119 | { | ||
120 | req->magic = htonl (STUN_MAGIC_COOKIE); | ||
121 | for (unsigned int x = 0; x < 3; x++) | ||
122 | req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | ||
123 | UINT32_MAX); | ||
124 | } | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Try to establish a connection given the specified address. | ||
129 | * | ||
130 | * @param cls our `struct GNUNET_NAT_STUN_Handle *` | ||
131 | * @param addr address to try, NULL for "last call" | ||
132 | * @param addrlen length of @a addr | ||
133 | */ | ||
134 | static void | ||
135 | stun_dns_callback (void *cls, | ||
136 | const struct sockaddr *addr, | ||
137 | socklen_t addrlen) | ||
138 | { | ||
139 | struct GNUNET_NAT_STUN_Handle *rh = cls; | ||
140 | struct stun_header req; | ||
141 | struct sockaddr_in server; | ||
142 | |||
143 | if (NULL == addr) | ||
144 | { | ||
145 | rh->dns_active = NULL; | ||
146 | if (GNUNET_NO == rh->dns_success) | ||
147 | { | ||
148 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
149 | "Error resolving host %s\n", | ||
150 | rh->stun_server); | ||
151 | rh->cb (rh->cb_cls, | ||
152 | GNUNET_NAT_ERROR_NOT_ONLINE); | ||
153 | } | ||
154 | else if (GNUNET_SYSERR == rh->dns_success) | ||
155 | { | ||
156 | rh->cb (rh->cb_cls, | ||
157 | GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | rh->cb (rh->cb_cls, | ||
162 | GNUNET_NAT_ERROR_SUCCESS); | ||
163 | } | ||
164 | GNUNET_NAT_stun_make_request_cancel (rh); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | rh->dns_success = GNUNET_YES; | ||
169 | memset (&server, 0, sizeof(server)); | ||
170 | server.sin_family = AF_INET; | ||
171 | server.sin_addr = ((struct sockaddr_in *) addr)->sin_addr; | ||
172 | server.sin_port = htons (rh->stun_port); | ||
173 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
174 | server.sin_len = (u_char) sizeof(struct sockaddr_in); | ||
175 | #endif | ||
176 | |||
177 | /* Craft the simplest possible STUN packet. A request binding */ | ||
178 | generate_request_id (&req); | ||
179 | req.msglen = htons (0); | ||
180 | req.msgtype = htons (encode_message (STUN_REQUEST, | ||
181 | STUN_BINDING)); | ||
182 | |||
183 | /* Send the packet */ | ||
184 | if (-1 == | ||
185 | GNUNET_NETWORK_socket_sendto (rh->sock, | ||
186 | &req, | ||
187 | sizeof(req), | ||
188 | (const struct sockaddr *) &server, | ||
189 | sizeof(server))) | ||
190 | { | ||
191 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
192 | "sendto"); | ||
193 | rh->dns_success = GNUNET_SYSERR; | ||
194 | return; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Make Generic STUN request. Sends a generic stun request to the | ||
201 | * server specified using the specified socket. | ||
202 | * | ||
203 | * @param server the address of the stun server | ||
204 | * @param port port of the stun server, in host byte order | ||
205 | * @param sock the socket used to send the request | ||
206 | * @param cb callback in case of error | ||
207 | * @param cb_cls closure for @a cb | ||
208 | * @return NULL on error | ||
209 | */ | ||
210 | struct GNUNET_NAT_STUN_Handle * | ||
211 | GNUNET_NAT_stun_make_request (const char *server, | ||
212 | uint16_t port, | ||
213 | struct GNUNET_NETWORK_Handle *sock, | ||
214 | GNUNET_NAT_TestCallback cb, | ||
215 | void *cb_cls) | ||
216 | { | ||
217 | struct GNUNET_NAT_STUN_Handle *rh; | ||
218 | |||
219 | rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle); | ||
220 | rh->sock = sock; | ||
221 | rh->cb = cb; | ||
222 | rh->cb_cls = cb_cls; | ||
223 | rh->stun_server = GNUNET_strdup (server); | ||
224 | rh->stun_port = port; | ||
225 | rh->dns_success = GNUNET_NO; | ||
226 | rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, | ||
227 | AF_INET, | ||
228 | TIMEOUT, | ||
229 | &stun_dns_callback, | ||
230 | rh); | ||
231 | if (NULL == rh->dns_active) | ||
232 | { | ||
233 | GNUNET_NAT_stun_make_request_cancel (rh); | ||
234 | return NULL; | ||
235 | } | ||
236 | return rh; | ||
237 | } | ||
238 | |||
239 | |||
240 | /** | ||
241 | * Cancel active STUN request. Frees associated resources | ||
242 | * and ensures that the callback is no longer invoked. | ||
243 | * | ||
244 | * @param rh request to cancel | ||
245 | */ | ||
246 | void | ||
247 | GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh) | ||
248 | { | ||
249 | if (NULL != rh->dns_active) | ||
250 | { | ||
251 | GNUNET_RESOLVER_request_cancel (rh->dns_active); | ||
252 | rh->dns_active = NULL; | ||
253 | } | ||
254 | GNUNET_free (rh->stun_server); | ||
255 | GNUNET_free (rh); | ||
256 | } | ||
257 | |||
258 | |||
259 | /* end of nat_stun.c */ | ||