aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-10-31 21:02:30 +0000
committerChristian Grothoff <christian@grothoff.org>2016-10-31 21:02:30 +0000
commitdb0bbaa1293f15ca825c69addfaa76beab40829e (patch)
tree5080d930bbe7a79934955c79e2a754f1988a742e
parent331e0e66df283db2d305bd6b80ac2b1896271d4f (diff)
downloadgnunet-db0bbaa1293f15ca825c69addfaa76beab40829e.tar.gz
gnunet-db0bbaa1293f15ca825c69addfaa76beab40829e.zip
-more work towards NAT service
-rw-r--r--src/nat/gnunet-service-nat.c550
-rw-r--r--src/nat/nat.c2
-rw-r--r--src/nat/nat_api.c29
3 files changed, 568 insertions, 13 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 607797081..c3e134b35 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -39,6 +39,13 @@
39 39
40 40
41/** 41/**
42 * How often should we ask the OS about a list of active
43 * network interfaces?
44 */
45#define SCAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
46
47
48/**
42 * Internal data structure we track for each of our clients. 49 * Internal data structure we track for each of our clients.
43 */ 50 */
44struct ClientHandle 51struct ClientHandle
@@ -63,16 +70,16 @@ struct ClientHandle
63 * Message queue for communicating with the client. 70 * Message queue for communicating with the client.
64 */ 71 */
65 struct GNUNET_MQ_Handle *mq; 72 struct GNUNET_MQ_Handle *mq;
66 73
67 /** 74 /**
68 * What does this client care about? 75 * Array of addresses used by the service.
69 */ 76 */
70 enum GNUNET_NAT_RegisterFlags flags; 77 struct sockaddr **addrs;
71 78
72 /** 79 /**
73 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP. 80 * What does this client care about?
74 */ 81 */
75 uint8_t proto; 82 enum GNUNET_NAT_RegisterFlags flags;
76 83
77 /** 84 /**
78 * Port we would like as we are configured to use this one for 85 * Port we would like as we are configured to use this one for
@@ -84,15 +91,47 @@ struct ClientHandle
84 * Number of addresses that this service is bound to. 91 * Number of addresses that this service is bound to.
85 */ 92 */
86 uint16_t num_addrs; 93 uint16_t num_addrs;
94
95 /**
96 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
97 */
98 uint8_t proto;
99
100};
101
102
103/**
104 * List of local addresses this system has.
105 */
106struct LocalAddressList
107{
108 /**
109 * This is a linked list.
110 */
111 struct LocalAddressList *next;
87 112
88 /** 113 /**
89 * Array of addresses used by the service. 114 * Previous entry.
90 */ 115 */
91 struct sockaddr **addrs; 116 struct LocalAddressList *prev;
117
118 /**
119 * The address itself (i.e. `struct in_addr` or `struct in6_addr`,
120 * in the respective byte order). Allocated at the end of this
121 * struct.
122 */
123 const void *addr;
124
125 /**
126 * Address family.
127 */
128 int af;
92 129
93}; 130};
94 131
95 132
133
134
96/** 135/**
97 * Handle to our current configuration. 136 * Handle to our current configuration.
98 */ 137 */
@@ -118,20 +157,85 @@ static struct ClientHandle *ch_head;
118 */ 157 */
119static struct ClientHandle *ch_tail; 158static struct ClientHandle *ch_tail;
120 159
160/**
161 * Head of DLL of local addresses.
162 */
163static struct LocalAddressList *lal_head;
121 164
122/** 165/**
123 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. 166 * Tail of DLL of local addresses.
124 * We remember the client for updates upon future NAT events. 167 */
168static struct LocalAddressList *lal_tail;
169
170
171/**
172 * Free the DLL starting at #lal_head.
173 */
174static void
175destroy_lal ()
176{
177 struct LocalAddressList *lal;
178
179 while (NULL != (lal = lal_head))
180 {
181 GNUNET_CONTAINER_DLL_remove (lal_head,
182 lal_tail,
183 lal);
184 GNUNET_free (lal);
185 }
186}
187
188
189/**
190 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from
191 * client.
125 * 192 *
126 * @param cls client who sent the message 193 * @param cls client who sent the message
127 * @param message the message received 194 * @param message the message received
195 * @return #GNUNET_OK if message is well-formed
128 */ 196 */
129static int 197static int
130check_register (void *cls, 198check_register (void *cls,
131 const struct GNUNET_NAT_RegisterMessage *message) 199 const struct GNUNET_NAT_RegisterMessage *message)
132{ 200{
133 GNUNET_break (0); // not implemented 201 uint16_t num_addrs = ntohs (message->num_addrs);
134 return GNUNET_SYSERR; 202 const char *off = (const char *) &message[1];
203 size_t left = ntohs (message->header.size) - sizeof (*message);
204
205 for (unsigned int i=0;i<num_addrs;i++)
206 {
207 size_t alen;
208 const struct sockaddr *sa = (const struct sockaddr *) off;
209
210 if (sizeof (sa_family_t) > left)
211 {
212 GNUNET_break (0);
213 return GNUNET_SYSERR;
214 }
215 switch (sa->sa_family)
216 {
217 case AF_INET:
218 alen = sizeof (struct sockaddr_in);
219 break;
220 case AF_INET6:
221 alen = sizeof (struct sockaddr_in6);
222 break;
223#if AF_UNIX
224 case AF_UNIX:
225 alen = sizeof (struct sockaddr_un);
226 break;
227#endif
228 default:
229 GNUNET_break (0);
230 return GNUNET_SYSERR;
231 }
232 if (alen > left)
233 {
234 GNUNET_break (0);
235 return GNUNET_SYSERR;
236 }
237 }
238 return GNUNET_OK;
135} 239}
136 240
137 241
@@ -147,10 +251,307 @@ handle_register (void *cls,
147 const struct GNUNET_NAT_RegisterMessage *message) 251 const struct GNUNET_NAT_RegisterMessage *message)
148{ 252{
149 struct ClientHandle *ch = cls; 253 struct ClientHandle *ch = cls;
150 // struct GNUNET_MQ_Handle *mq; 254 const char *off;
255 size_t left;
151 256
257 if ( (0 != ch->proto) ||
258 (NULL != ch->addrs) )
259 {
260 /* double registration not allowed */
261 GNUNET_break (0);
262 GNUNET_SERVICE_client_drop (ch->client);
263 return;
264 }
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153 "Received REGISTER message from client\n"); 266 "Received REGISTER message from client\n");
267 ch->flags = message->flags;
268 ch->proto = message->proto;
269 ch->adv_port = ntohs (message->adv_port);
270 ch->num_addrs = ntohs (message->adv_port);
271 ch->addrs = GNUNET_new_array (ch->num_addrs,
272 struct sockaddr *);
273 left = ntohs (message->header.size) - sizeof (*message);
274 off = (const char *) &message[1];
275 for (unsigned int i=0;i<ch->num_addrs;i++)
276 {
277 size_t alen;
278 const struct sockaddr *sa = (const struct sockaddr *) off;
279
280 if (sizeof (sa_family_t) > left)
281 {
282 GNUNET_break (0);
283 GNUNET_SERVICE_client_drop (ch->client);
284 return;
285 }
286 switch (sa->sa_family)
287 {
288 case AF_INET:
289 alen = sizeof (struct sockaddr_in);
290 break;
291 case AF_INET6:
292 alen = sizeof (struct sockaddr_in6);
293 break;
294#if AF_UNIX
295 case AF_UNIX:
296 alen = sizeof (struct sockaddr_un);
297 break;
298#endif
299 default:
300 GNUNET_break (0);
301 GNUNET_SERVICE_client_drop (ch->client);
302 return;
303 }
304 GNUNET_assert (alen <= left);
305 ch->addrs[i] = GNUNET_malloc (alen);
306 GNUNET_memcpy (ch->addrs[i],
307 sa,
308 alen);
309 off += alen;
310 }
311 GNUNET_SERVICE_client_continue (ch->client);
312}
313
314
315/**
316 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
317 * client.
318 *
319 * @param cls client who sent the message
320 * @param message the message received
321 * @return #GNUNET_OK if message is well-formed
322 */
323static int
324check_stun (void *cls,
325 const struct GNUNET_NAT_HandleStunMessage *message)
326{
327 size_t sa_len = ntohs (message->sender_addr_size);
328 size_t expect = sa_len + ntohs (message->payload_size);
329
330 if (ntohs (message->header.size) - sizeof (*message) != expect)
331 {
332 GNUNET_break (0);
333 return GNUNET_SYSERR;
334 }
335 if (sa_len < sizeof (sa_family_t))
336 {
337 GNUNET_break (0);
338 return GNUNET_SYSERR;
339 }
340 return GNUNET_OK;
341}
342
343
344/**
345 * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
346 * client.
347 *
348 * @param cls client who sent the message
349 * @param message the message received
350 */
351static void
352handle_stun (void *cls,
353 const struct GNUNET_NAT_HandleStunMessage *message)
354{
355 struct ClientHandle *ch = cls;
356 const char *buf = (const char *) &message[1];
357 const struct sockaddr *sa;
358 const void *payload;
359 size_t sa_len;
360 size_t payload_size;
361
362 sa_len = ntohs (message->sender_addr_size);
363 payload_size = ntohs (message->payload_size);
364 sa = (const struct sockaddr *) &buf[0];
365 payload = (const struct sockaddr *) &buf[sa_len];
366 switch (sa->sa_family)
367 {
368 case AF_INET:
369 if (sa_len != sizeof (struct sockaddr_in))
370 {
371 GNUNET_break (0);
372 GNUNET_SERVICE_client_drop (ch->client);
373 return;
374 }
375 break;
376 case AF_INET6:
377 if (sa_len != sizeof (struct sockaddr_in6))
378 {
379 GNUNET_break (0);
380 GNUNET_SERVICE_client_drop (ch->client);
381 return;
382 }
383 break;
384 }
385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
386 "Received HANDLE_STUN message from client\n");
387 // FIXME: actually handle STUN request!
388 GNUNET_SERVICE_client_continue (ch->client);
389}
390
391
392/**
393 * Check validity of
394 * #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from
395 * client.
396 *
397 * @param cls client who sent the message
398 * @param message the message received
399 * @return #GNUNET_OK if message is well-formed
400 */
401static int
402check_request_connection_reversal (void *cls,
403 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
404{
405 size_t expect;
406
407 expect = ntohs (message->local_addr_size)
408 + ntohs (message->remote_addr_size);
409 if (ntohs (message->header.size) - sizeof (*message) != expect)
410 {
411 GNUNET_break (0);
412 return GNUNET_SYSERR;
413 }
414 return GNUNET_OK;
415}
416
417
418/**
419 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL
420 * message from client.
421 *
422 * @param cls client who sent the message
423 * @param message the message received
424 */
425static void
426handle_request_connection_reversal (void *cls,
427 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
428{
429 struct ClientHandle *ch = cls;
430 const char *buf = (const char *) &message[1];
431 size_t local_sa_len = ntohs (message->local_addr_size);
432 size_t remote_sa_len = ntohs (message->remote_addr_size);
433 const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0];
434 const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len];
435
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
437 "Received REQUEST CONNECTION REVERSAL message from client\n");
438 switch (local_sa->sa_family)
439 {
440 case AF_INET:
441 if (local_sa_len != sizeof (struct sockaddr_in))
442 {
443 GNUNET_break (0);
444 GNUNET_SERVICE_client_drop (ch->client);
445 return;
446 }
447 break;
448 case AF_INET6:
449 if (local_sa_len != sizeof (struct sockaddr_in6))
450 {
451 GNUNET_break (0);
452 GNUNET_SERVICE_client_drop (ch->client);
453 return;
454 }
455 break;
456 default:
457 GNUNET_break (0);
458 GNUNET_SERVICE_client_drop (ch->client);
459 return;
460 }
461 switch (remote_sa->sa_family)
462 {
463 case AF_INET:
464 if (remote_sa_len != sizeof (struct sockaddr_in))
465 {
466 GNUNET_break (0);
467 GNUNET_SERVICE_client_drop (ch->client);
468 return;
469 }
470 break;
471 case AF_INET6:
472 if (remote_sa_len != sizeof (struct sockaddr_in6))
473 {
474 GNUNET_break (0);
475 GNUNET_SERVICE_client_drop (ch->client);
476 return;
477 }
478 break;
479 default:
480 GNUNET_break (0);
481 GNUNET_SERVICE_client_drop (ch->client);
482 return;
483 }
484 /* FIXME: actually run the logic! */
485
486 GNUNET_SERVICE_client_continue (ch->client);
487}
488
489
490/**
491 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_TEST message from
492 * client.
493 *
494 * @param cls client who sent the message
495 * @param message the message received
496 */
497static void
498handle_test (void *cls,
499 const struct GNUNET_NAT_RequestTestMessage *message)
500{
501 struct ClientHandle *ch = cls;
502
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
504 "Received REQUEST_TEST message from client\n");
505 GNUNET_SERVICE_client_continue (ch->client);
506}
507
508
509/**
510 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
511 * from client.
512 *
513 * @param cls client who sent the message
514 * @param message the message received
515 * @return #GNUNET_OK if message is well-formed
516 */
517static int
518check_autoconfig_request (void *cls,
519 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
520{
521 return GNUNET_OK; /* checked later */
522}
523
524
525/**
526 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
527 * client.
528 *
529 * @param cls client who sent the message
530 * @param message the message received
531 */
532static void
533handle_autoconfig_request (void *cls,
534 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
535{
536 struct ClientHandle *ch = cls;
537 size_t left = ntohs (message->header.size);
538 struct GNUNET_CONFIGURATION_Handle *c;
539
540 c = GNUNET_CONFIGURATION_create ();
541 if (GNUNET_OK !=
542 GNUNET_CONFIGURATION_deserialize (c,
543 (const char *) &message[1],
544 left,
545 GNUNET_NO))
546 {
547 GNUNET_break (0);
548 GNUNET_SERVICE_client_drop (ch->client);
549 return;
550 }
551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
552 "Received REQUEST_AUTO_CONFIG message from client\n");
553 // FIXME: actually handle request...
554 GNUNET_CONFIGURATION_destroy (c);
154 GNUNET_SERVICE_client_continue (ch->client); 555 GNUNET_SERVICE_client_continue (ch->client);
155} 556}
156 557
@@ -173,6 +574,110 @@ shutdown_task (void *cls)
173 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 574 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
174 stats = NULL; 575 stats = NULL;
175 } 576 }
577 destroy_lal ();
578}
579
580
581/**
582 * Closure for #ifc_proc.
583 */
584struct IfcProcContext
585{
586
587 /**
588 * Head of DLL of local addresses.
589 */
590 struct LocalAddressList *lal_head;
591
592 /**
593 * Tail of DLL of local addresses.
594 */
595 struct LocalAddressList *lal_tail;
596
597};
598
599
600/**
601 * Callback function invoked for each interface found. Adds them
602 * to our new address list.
603 *
604 * @param cls a `struct IfcProcContext *`
605 * @param name name of the interface (can be NULL for unknown)
606 * @param isDefault is this presumably the default interface
607 * @param addr address of this interface (can be NULL for unknown or unassigned)
608 * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
609 * @param netmask the network mask (can be NULL for unknown or unassigned)
610 * @param addrlen length of the address
611 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
612 */
613static int
614ifc_proc (void *cls,
615 const char *name,
616 int isDefault,
617 const struct sockaddr *addr,
618 const struct sockaddr *broadcast_addr,
619 const struct sockaddr *netmask,
620 socklen_t addrlen)
621{
622 struct IfcProcContext *ifc_ctx = cls;
623 struct LocalAddressList *lal;
624 size_t alen;
625 const void *ip;
626
627 switch (addr->sa_family)
628 {
629 case AF_INET:
630 alen = sizeof (struct in_addr);
631 ip = &((const struct sockaddr_in *) addr)->sin_addr;
632 break;
633 case AF_INET6:
634 alen = sizeof (struct in6_addr);
635 ip = &((const struct sockaddr_in6 *) addr)->sin6_addr;
636 break;
637#if AF_UNIX
638 case AF_UNIX:
639 GNUNET_break (0);
640 return GNUNET_OK;
641#endif
642 default:
643 GNUNET_break (0);
644 return GNUNET_OK;
645 }
646 lal = GNUNET_malloc (sizeof (*lal) + alen);
647 lal->af = addr->sa_family;
648 lal->addr = &lal[1];
649 GNUNET_memcpy (&lal[1],
650 ip,
651 alen);
652 GNUNET_CONTAINER_DLL_insert (ifc_ctx->lal_head,
653 ifc_ctx->lal_tail,
654 lal);
655 return GNUNET_OK;
656}
657
658
659/**
660 * Task we run periodically to scan for network interfaces.
661 *
662 * @param cls NULL
663 */
664static void
665run_scan (void *cls)
666{
667 struct IfcProcContext ifc_ctx;
668
669 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
670 &run_scan,
671 NULL);
672 memset (&ifc_ctx,
673 0,
674 sizeof (ifc_ctx));
675 GNUNET_OS_network_interfaces_list (&ifc_proc,
676 &ifc_ctx);
677 /* FIXME: notify clients of changes in lal-DLL */
678 destroy_lal ();
679 lal_head = ifc_ctx.lal_head;
680 lal_tail = ifc_ctx.lal_tail;
176} 681}
177 682
178 683
@@ -193,6 +698,8 @@ run (void *cls,
193 NULL); 698 NULL);
194 stats = GNUNET_STATISTICS_create ("nat", 699 stats = GNUNET_STATISTICS_create ("nat",
195 cfg); 700 cfg);
701 scan_task = GNUNET_SCHEDULER_add_now (&run_scan,
702 NULL);
196} 703}
197 704
198 705
@@ -238,6 +745,9 @@ client_disconnect_cb (void *cls,
238 GNUNET_CONTAINER_DLL_remove (ch_head, 745 GNUNET_CONTAINER_DLL_remove (ch_head,
239 ch_tail, 746 ch_tail,
240 ch); 747 ch);
748 for (unsigned int i=0;i<ch->num_addrs;i++)
749 GNUNET_free_non_null (ch->addrs[i]);
750 GNUNET_free_non_null (ch->addrs);
241 GNUNET_free (ch); 751 GNUNET_free (ch);
242} 752}
243 753
@@ -256,6 +766,22 @@ GNUNET_SERVICE_MAIN
256 GNUNET_MESSAGE_TYPE_NAT_REGISTER, 766 GNUNET_MESSAGE_TYPE_NAT_REGISTER,
257 struct GNUNET_NAT_RegisterMessage, 767 struct GNUNET_NAT_RegisterMessage,
258 NULL), 768 NULL),
769 GNUNET_MQ_hd_var_size (stun,
770 GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN,
771 struct GNUNET_NAT_HandleStunMessage,
772 NULL),
773 GNUNET_MQ_hd_var_size (request_connection_reversal,
774 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
775 struct GNUNET_NAT_RequestConnectionReversalMessage,
776 NULL),
777 GNUNET_MQ_hd_fixed_size (test,
778 GNUNET_MESSAGE_TYPE_NAT_REQUEST_TEST,
779 struct GNUNET_NAT_RequestTestMessage,
780 NULL),
781 GNUNET_MQ_hd_var_size (autoconfig_request,
782 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
783 struct GNUNET_NAT_AutoconfigRequestMessage,
784 NULL),
259 GNUNET_MQ_handler_end ()); 785 GNUNET_MQ_handler_end ());
260 786
261 787
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 9a9ae18ac..08dd5dd1e 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -76,7 +76,7 @@ enum LocalAddressSource
76 */ 76 */
77 LAL_EXTERNAL_IP, 77 LAL_EXTERNAL_IP,
78 78
79 /** 79 /**
80 * Address was obtained by an external STUN server 80 * Address was obtained by an external STUN server
81 */ 81 */
82 LAL_EXTERNAL_STUN_IP, 82 LAL_EXTERNAL_STUN_IP,
diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c
index e567368d2..421befab3 100644
--- a/src/nat/nat_api.c
+++ b/src/nat/nat_api.c
@@ -403,6 +403,35 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
403 off = (char *) &rm[1]; 403 off = (char *) &rm[1];
404 for (unsigned int i=0;i<num_addrs;i++) 404 for (unsigned int i=0;i<num_addrs;i++)
405 { 405 {
406 switch (addrs[i]->sa_family)
407 {
408 case AF_INET:
409 if (sizeof (struct sockaddr_in) != addrlens[i])
410 {
411 GNUNET_break (0);
412 return NULL;
413 }
414 break;
415 case AF_INET6:
416 if (sizeof (struct sockaddr_in6) != addrlens[i])
417 {
418 GNUNET_break (0);
419 return NULL;
420 }
421 break;
422#if AF_UNIX
423 case AF_UNIX:
424 if (sizeof (struct sockaddr_un) != addrlens[i])
425 {
426 GNUNET_break (0);
427 return NULL;
428 }
429 break;
430#endif
431 default:
432 GNUNET_break (0);
433 return NULL;
434 }
406 GNUNET_memcpy (off, 435 GNUNET_memcpy (off,
407 addrs[i], 436 addrs[i],
408 addrlens[i]); 437 addrlens[i]);