aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat_api_stun.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/nat_api_stun.c')
-rw-r--r--src/nat/nat_api_stun.c155
1 files changed, 76 insertions, 79 deletions
diff --git a/src/nat/nat_api_stun.c b/src/nat/nat_api_stun.c
index a0931a06f..0f8694867 100644
--- a/src/nat/nat_api_stun.c
+++ b/src/nat/nat_api_stun.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20/** 20/**
21 * This code provides some support for doing STUN transactions. 21 * This code provides some support for doing STUN transactions.
22 * We send simplest possible packet ia REQUEST with BIND to a STUN server. 22 * We send simplest possible packet ia REQUEST with BIND to a STUN server.
@@ -43,9 +43,9 @@
43 43
44#include "nat_stun.h" 44#include "nat_stun.h"
45 45
46#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) 46#define LOG(kind, ...) GNUNET_log_from(kind, "stun", __VA_ARGS__)
47 47
48#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 48#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15)
49 49
50 50
51/** 51/**
@@ -53,9 +53,7 @@
53 * the request prior to the timeout or successful execution. Also 53 * the request prior to the timeout or successful execution. Also
54 * used to track our internal state for the request. 54 * used to track our internal state for the request.
55 */ 55 */
56struct GNUNET_NAT_STUN_Handle 56struct GNUNET_NAT_STUN_Handle {
57{
58
59 /** 57 /**
60 * Handle to a pending DNS lookup request. 58 * Handle to a pending DNS lookup request.
61 */ 59 */
@@ -90,7 +88,6 @@ struct GNUNET_NAT_STUN_Handle
90 * STUN port 88 * STUN port
91 */ 89 */
92 uint16_t stun_port; 90 uint16_t stun_port;
93
94}; 91};
95 92
96 93
@@ -102,11 +99,11 @@ struct GNUNET_NAT_STUN_Handle
102 * @return message in a STUN compatible format 99 * @return message in a STUN compatible format
103 */ 100 */
104static int 101static int
105encode_message (enum StunClasses msg_class, 102encode_message(enum StunClasses msg_class,
106 enum StunMethods method) 103 enum StunMethods method)
107{ 104{
108 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | 105 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) |
109 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); 106 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
110} 107}
111 108
112 109
@@ -116,12 +113,12 @@ encode_message (enum StunClasses msg_class,
116 * @param req, stun header to be filled 113 * @param req, stun header to be filled
117 */ 114 */
118static void 115static void
119generate_request_id (struct stun_header *req) 116generate_request_id(struct stun_header *req)
120{ 117{
121 req->magic = htonl(STUN_MAGIC_COOKIE); 118 req->magic = htonl(STUN_MAGIC_COOKIE);
122 for (unsigned int x = 0; x < 3; x++) 119 for (unsigned int x = 0; x < 3; x++)
123 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 120 req->id.id[x] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE,
124 UINT32_MAX); 121 UINT32_MAX);
125} 122}
126 123
127 124
@@ -133,67 +130,67 @@ generate_request_id (struct stun_header *req)
133 * @param addrlen length of @a addr 130 * @param addrlen length of @a addr
134 */ 131 */
135static void 132static void
136stun_dns_callback (void *cls, 133stun_dns_callback(void *cls,
137 const struct sockaddr *addr, 134 const struct sockaddr *addr,
138 socklen_t addrlen) 135 socklen_t addrlen)
139{ 136{
140 struct GNUNET_NAT_STUN_Handle *rh = cls; 137 struct GNUNET_NAT_STUN_Handle *rh = cls;
141 struct stun_header req; 138 struct stun_header req;
142 struct sockaddr_in server; 139 struct sockaddr_in server;
143 140
144 if (NULL == addr) 141 if (NULL == addr)
145 {
146 rh->dns_active = NULL;
147 if (GNUNET_NO == rh->dns_success)
148 {
149 LOG (GNUNET_ERROR_TYPE_INFO,
150 "Error resolving host %s\n",
151 rh->stun_server);
152 rh->cb (rh->cb_cls,
153 GNUNET_NAT_ERROR_NOT_ONLINE);
154 }
155 else if (GNUNET_SYSERR == rh->dns_success)
156 { 142 {
157 rh->cb (rh->cb_cls, 143 rh->dns_active = NULL;
158 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); 144 if (GNUNET_NO == rh->dns_success)
145 {
146 LOG(GNUNET_ERROR_TYPE_INFO,
147 "Error resolving host %s\n",
148 rh->stun_server);
149 rh->cb(rh->cb_cls,
150 GNUNET_NAT_ERROR_NOT_ONLINE);
151 }
152 else if (GNUNET_SYSERR == rh->dns_success)
153 {
154 rh->cb(rh->cb_cls,
155 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
156 }
157 else
158 {
159 rh->cb(rh->cb_cls,
160 GNUNET_NAT_ERROR_SUCCESS);
161 }
162 GNUNET_NAT_stun_make_request_cancel(rh);
163 return;
159 } 164 }
160 else
161 {
162 rh->cb (rh->cb_cls,
163 GNUNET_NAT_ERROR_SUCCESS);
164 }
165 GNUNET_NAT_stun_make_request_cancel (rh);
166 return;
167 }
168 165
169 rh->dns_success = GNUNET_YES; 166 rh->dns_success = GNUNET_YES;
170 memset (&server, 0, sizeof(server)); 167 memset(&server, 0, sizeof(server));
171 server.sin_family = AF_INET; 168 server.sin_family = AF_INET;
172 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; 169 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
173 server.sin_port = htons (rh->stun_port); 170 server.sin_port = htons(rh->stun_port);
174#if HAVE_SOCKADDR_IN_SIN_LEN 171#if HAVE_SOCKADDR_IN_SIN_LEN
175 server.sin_len = (u_char) sizeof (struct sockaddr_in); 172 server.sin_len = (u_char)sizeof(struct sockaddr_in);
176#endif 173#endif
177 174
178 /* Craft the simplest possible STUN packet. A request binding */ 175 /* Craft the simplest possible STUN packet. A request binding */
179 generate_request_id (&req); 176 generate_request_id(&req);
180 req.msglen = htons (0); 177 req.msglen = htons(0);
181 req.msgtype = htons (encode_message (STUN_REQUEST, 178 req.msgtype = htons(encode_message(STUN_REQUEST,
182 STUN_BINDING)); 179 STUN_BINDING));
183 180
184 /* Send the packet */ 181 /* Send the packet */
185 if (-1 == 182 if (-1 ==
186 GNUNET_NETWORK_socket_sendto (rh->sock, 183 GNUNET_NETWORK_socket_sendto(rh->sock,
187 &req, 184 &req,
188 sizeof (req), 185 sizeof(req),
189 (const struct sockaddr *) &server, 186 (const struct sockaddr *)&server,
190 sizeof (server))) 187 sizeof(server)))
191 { 188 {
192 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 189 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR,
193 "sendto"); 190 "sendto");
194 rh->dns_success = GNUNET_SYSERR; 191 rh->dns_success = GNUNET_SYSERR;
195 return; 192 return;
196 } 193 }
197} 194}
198 195
199 196
@@ -209,31 +206,31 @@ stun_dns_callback (void *cls,
209 * @return NULL on error 206 * @return NULL on error
210 */ 207 */
211struct GNUNET_NAT_STUN_Handle * 208struct GNUNET_NAT_STUN_Handle *
212GNUNET_NAT_stun_make_request (const char *server, 209GNUNET_NAT_stun_make_request(const char *server,
213 uint16_t port, 210 uint16_t port,
214 struct GNUNET_NETWORK_Handle *sock, 211 struct GNUNET_NETWORK_Handle *sock,
215 GNUNET_NAT_TestCallback cb, 212 GNUNET_NAT_TestCallback cb,
216 void *cb_cls) 213 void *cb_cls)
217{ 214{
218 struct GNUNET_NAT_STUN_Handle *rh; 215 struct GNUNET_NAT_STUN_Handle *rh;
219 216
220 rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle); 217 rh = GNUNET_new(struct GNUNET_NAT_STUN_Handle);
221 rh->sock = sock; 218 rh->sock = sock;
222 rh->cb = cb; 219 rh->cb = cb;
223 rh->cb_cls = cb_cls; 220 rh->cb_cls = cb_cls;
224 rh->stun_server = GNUNET_strdup (server); 221 rh->stun_server = GNUNET_strdup(server);
225 rh->stun_port = port; 222 rh->stun_port = port;
226 rh->dns_success = GNUNET_NO; 223 rh->dns_success = GNUNET_NO;
227 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, 224 rh->dns_active = GNUNET_RESOLVER_ip_get(rh->stun_server,
228 AF_INET, 225 AF_INET,
229 TIMEOUT, 226 TIMEOUT,
230 &stun_dns_callback, 227 &stun_dns_callback,
231 rh); 228 rh);
232 if (NULL == rh->dns_active) 229 if (NULL == rh->dns_active)
233 { 230 {
234 GNUNET_NAT_stun_make_request_cancel (rh); 231 GNUNET_NAT_stun_make_request_cancel(rh);
235 return NULL; 232 return NULL;
236 } 233 }
237 return rh; 234 return rh;
238} 235}
239 236
@@ -245,15 +242,15 @@ GNUNET_NAT_stun_make_request (const char *server,
245 * @param rh request to cancel 242 * @param rh request to cancel
246 */ 243 */
247void 244void
248GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh) 245GNUNET_NAT_stun_make_request_cancel(struct GNUNET_NAT_STUN_Handle *rh)
249{ 246{
250 if (NULL != rh->dns_active) 247 if (NULL != rh->dns_active)
251 { 248 {
252 GNUNET_RESOLVER_request_cancel (rh->dns_active); 249 GNUNET_RESOLVER_request_cancel(rh->dns_active);
253 rh->dns_active = NULL; 250 rh->dns_active = NULL;
254 } 251 }
255 GNUNET_free (rh->stun_server); 252 GNUNET_free(rh->stun_server);
256 GNUNET_free (rh); 253 GNUNET_free(rh);
257} 254}
258 255
259 256