aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat_mini.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-08 11:30:01 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-08 11:30:01 +0000
commitceefc6de0ed40c33a644c571422d0b558aa851ca (patch)
treebb2da9ec2e03367377cf8d9da7a7e566716e01ea /src/nat/nat_mini.c
parentf2e1a736377f59b2f7f12b0dcfc8c73e6e80e897 (diff)
downloadgnunet-ceefc6de0ed40c33a644c571422d0b558aa851ca.tar.gz
gnunet-ceefc6de0ed40c33a644c571422d0b558aa851ca.zip
mini works
Diffstat (limited to 'src/nat/nat_mini.c')
-rw-r--r--src/nat/nat_mini.c140
1 files changed, 121 insertions, 19 deletions
diff --git a/src/nat/nat_mini.c b/src/nat/nat_mini.c
index 2e4dd1a38..38dcfcd1f 100644
--- a/src/nat/nat_mini.c
+++ b/src/nat/nat_mini.c
@@ -20,7 +20,7 @@
20 20
21/** 21/**
22 * @file nat/nat_mini.c 22 * @file nat/nat_mini.c
23 * @brief functions for interaction with miniupnp 23 * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
@@ -33,7 +33,6 @@
33 */ 33 */
34#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 34#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
35 35
36
37/** 36/**
38 * How long do we give upnpc to remove a mapping? 37 * How long do we give upnpc to remove a mapping?
39 */ 38 */
@@ -42,7 +41,7 @@
42/** 41/**
43 * How often do we check for changes in the mapping? 42 * How often do we check for changes in the mapping?
44 */ 43 */
45#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 44#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
46 45
47 46
48/** 47/**
@@ -158,6 +157,11 @@ struct GNUNET_NAT_MiniHandle
158 int did_map; 157 int did_map;
159 158
160 /** 159 /**
160 * Did we find our mapping during refresh scan?
161 */
162 int found;
163
164 /**
161 * Which port are we mapping? 165 * Which port are we mapping?
162 */ 166 */
163 uint16_t port; 167 uint16_t port;
@@ -177,6 +181,17 @@ do_refresh (void *cls,
177 181
178 182
179/** 183/**
184 * Process the output from the 'upnpc -r' command.
185 *
186 * @param cls the 'struct GNUNET_NAT_MiniHandle'
187 * @param line line of output, NULL at the end
188 */
189static void
190process_map_output (void *cls,
191 const char *line);
192
193
194/**
180 * Process the output from 'upnpc -l' to see if our 195 * Process the output from 'upnpc -l' to see if our
181 * external mapping changed. If so, do the notifications. 196 * external mapping changed. If so, do the notifications.
182 * 197 *
@@ -188,20 +203,105 @@ process_refresh_output (void *cls,
188 const char *line) 203 const char *line)
189{ 204{
190 struct GNUNET_NAT_MiniHandle *mini = cls; 205 struct GNUNET_NAT_MiniHandle *mini = cls;
206 char pstr[9];
207 const char *s;
208 unsigned int nport;
209 struct in_addr exip;
191 210
192 if (NULL == line) 211 if (NULL == line)
193 { 212 {
194 GNUNET_OS_command_stop (mini->refresh_cmd); 213 GNUNET_OS_command_stop (mini->refresh_cmd);
195 mini->refresh_cmd = NULL; 214 mini->refresh_cmd = NULL;
215 if (mini->found == GNUNET_NO)
216 {
217 /* mapping disappeared, try to re-create */
218 if (mini->did_map)
219 {
220 mini->ac (mini->ac_cls, GNUNET_NO,
221 (const struct sockaddr*) &mini->current_addr,
222 sizeof (mini->current_addr));
223 mini->did_map = GNUNET_NO;
224 }
225 GNUNET_snprintf (pstr, sizeof (pstr),
226 "%u",
227 (unsigned int) mini->port);
228 mini->map_cmd = GNUNET_OS_command_run (&process_map_output,
229 mini,
230 MAP_TIMEOUT,
231 "upnpc",
232 "upnpc",
233 "-r", pstr,
234 mini->is_tcp ? "tcp" : "udp",
235 NULL);
236 if (NULL != mini->map_cmd)
237 return;
238 }
196 mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, 239 mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
197 &do_refresh, 240 &do_refresh,
198 mini); 241 mini);
199 return; 242 return;
200 } 243 }
201 /* FIXME: parse 'line' */ 244 if (! mini->did_map)
202 fprintf (stderr, 245 return; /* never mapped, won't find our mapping anyway */
203 "Refresh output: `%s'\n", 246
204 line); 247 /* we're looking for output of the form:
248 "ExternalIPAddress = 12.134.41.124" */
249
250 s = strstr (line, "ExternalIPAddress = ");
251 if (NULL != s)
252 {
253 s += strlen ("ExternalIPAddress = ");
254 if (1 != inet_pton (AF_INET,
255 s, &exip))
256 return; /* skip */
257 if (exip.s_addr == mini->current_addr.sin_addr.s_addr)
258 return; /* no change */
259 /* update mapping */
260 mini->ac (mini->ac_cls, GNUNET_NO,
261 (const struct sockaddr*) &mini->current_addr,
262 sizeof (mini->current_addr));
263 mini->current_addr.sin_addr = exip;
264 mini->ac (mini->ac_cls, GNUNET_YES,
265 (const struct sockaddr*) &mini->current_addr,
266 sizeof (mini->current_addr));
267 return;
268 }
269 /*
270 we're looking for output of the form:
271
272 "0 TCP 3000->192.168.2.150:3000 'libminiupnpc' ''"
273 "1 UDP 3001->192.168.2.150:3001 'libminiupnpc' ''"
274
275 the pattern we look for is:
276
277 "%s TCP PORT->STRING:OURPORT *" or
278 "%s UDP PORT->STRING:OURPORT *"
279 */
280 GNUNET_snprintf (pstr, sizeof (pstr),
281 ":%u ",
282 mini->port);
283 if (NULL == (s = strstr (line, "->")))
284 return; /* skip */
285 if (NULL == (s = strstr (s, pstr)))
286 return; /* skip */
287 if (1 != sscanf (line,
288 (mini->is_tcp)
289 ? "%*u TCP %u->%*s:%*u %*s"
290 : "%*u UDP %u->%*s:%*u %*s",
291 &nport))
292 return; /* skip */
293 mini->found = GNUNET_YES;
294 if (nport == ntohs (mini->current_addr.sin_port))
295 return; /* no change */
296
297 /* external port changed, update mapping */
298 mini->ac (mini->ac_cls, GNUNET_NO,
299 (const struct sockaddr*) &mini->current_addr,
300 sizeof (mini->current_addr));
301 mini->current_addr.sin_port = htons ((uint16_t) nport);
302 mini->ac (mini->ac_cls, GNUNET_YES,
303 (const struct sockaddr*) &mini->current_addr,
304 sizeof (mini->current_addr));
205} 305}
206 306
207 307
@@ -218,6 +318,7 @@ do_refresh (void *cls,
218 struct GNUNET_NAT_MiniHandle *mini = cls; 318 struct GNUNET_NAT_MiniHandle *mini = cls;
219 319
220 mini->refresh_task = GNUNET_SCHEDULER_NO_TASK; 320 mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
321 mini->found = GNUNET_NO;
221 mini->refresh_cmd = GNUNET_OS_command_run (&process_refresh_output, 322 mini->refresh_cmd = GNUNET_OS_command_run (&process_refresh_output,
222 mini, 323 mini,
223 MAP_TIMEOUT, 324 MAP_TIMEOUT,
@@ -248,10 +349,9 @@ process_map_output (void *cls,
248 { 349 {
249 GNUNET_OS_command_stop (mini->map_cmd); 350 GNUNET_OS_command_stop (mini->map_cmd);
250 mini->map_cmd = NULL; 351 mini->map_cmd = NULL;
251 if (mini->did_map == GNUNET_YES) 352 mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
252 mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, 353 &do_refresh,
253 &do_refresh, 354 mini);
254 mini);
255 return; 355 return;
256 } 356 }
257 /* 357 /*
@@ -263,9 +363,6 @@ process_map_output (void *cls,
263 (NULL == (pstr = strstr (ipaddr, ":"))) || 363 (NULL == (pstr = strstr (ipaddr, ":"))) ||
264 (1 != sscanf (pstr + 1, "%u", &port)) ) 364 (1 != sscanf (pstr + 1, "%u", &port)) )
265 { 365 {
266 fprintf (stderr,
267 "Skipping output `%s'\n",
268 line);
269 return; /* skip line */ 366 return; /* skip line */
270 } 367 }
271 ipa = GNUNET_strdup (ipaddr + 1); 368 ipa = GNUNET_strdup (ipaddr + 1);
@@ -275,9 +372,6 @@ process_map_output (void *cls,
275 &mini->current_addr.sin_addr)) 372 &mini->current_addr.sin_addr))
276 { 373 {
277 GNUNET_free (ipa); 374 GNUNET_free (ipa);
278 fprintf (stderr,
279 "Skipping output `%s'\n",
280 line);
281 return; /* skip line */ 375 return; /* skip line */
282 } 376 }
283 GNUNET_free (ipa); 377 GNUNET_free (ipa);
@@ -332,7 +426,12 @@ GNUNET_NAT_mini_map_start (uint16_t port,
332 "-r", pstr, 426 "-r", pstr,
333 is_tcp ? "tcp" : "udp", 427 is_tcp ? "tcp" : "udp",
334 NULL); 428 NULL);
335 429 if (NULL != ret->map_cmd)
430 return ret;
431 ret->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
432 &do_refresh,
433 ret);
434
336 return ret; 435 return ret;
337} 436}
338 437
@@ -396,9 +495,12 @@ GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
396 mini->ac (mini->ac_cls, GNUNET_NO, 495 mini->ac (mini->ac_cls, GNUNET_NO,
397 (const struct sockaddr*) &mini->current_addr, 496 (const struct sockaddr*) &mini->current_addr,
398 sizeof (mini->current_addr)); 497 sizeof (mini->current_addr));
498 /* Note: oddly enough, deletion uses the external port whereas
499 addition uses the internal port; this rarely matters since they
500 often are the same, but it might... */
399 GNUNET_snprintf (pstr, sizeof (pstr), 501 GNUNET_snprintf (pstr, sizeof (pstr),
400 "%u", 502 "%u",
401 (unsigned int) mini->port); 503 (unsigned int) mini->current_addr.sin_port);
402 mini->unmap_cmd = GNUNET_OS_command_run (&process_unmap_output, 504 mini->unmap_cmd = GNUNET_OS_command_run (&process_unmap_output,
403 mini, 505 mini,
404 UNMAP_TIMEOUT, 506 UNMAP_TIMEOUT,