gnunet-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [GNUnet-developers] NAT library (Was: towards gnunet 0.9.x)


From: Christian Grothoff
Subject: Re: [GNUnet-developers] NAT library (Was: towards gnunet 0.9.x)
Date: Fri, 11 Sep 2009 09:56:17 +0200
User-agent: KMail/1.12.1 (Linux/2.6.28-grml64; KDE/4.3.1; x86_64; ; )

On Thursday 10 September 2009 19:22:26 Milan Bouchet-Valat wrote:
> Hi!
> 
> I've worked a little on the NAT front, and I've come to something that
> basically builds. Now, I need to rework most of the generic code around
> UPnP and NAT-PMP actual implementations, since Transmission was working
> on a very different basis than ours. But there are a few things that I
> don't really understand (see below).

I'll try to answer below.
 
> Le dimanche 31 mai 2009 à 12:31 -0600, Christian Grothoff a écrit :
> > No, we don't need that type of centralization: we now support having
> > *multiple* IP addresses.  This is required for proper IPv6 support
> > anyway.  So all that will really happen is that the UPnP/PMP library
> > should allow us to register a callback which will be called whenever
> > there is an external IP address to be added to (or removed from) our IP
> > list.  I've thought about it a bit more and here is what I'm thinking of
> > for the API right now:
> >
> > // add_remove: YES: add, NO: remove
> > // addr: see man 2 bind
> > void (*GNUNET_NAT_AddressCallback)(void *cls, int add_remove,
> >                                     const struct sockaddr *addr,
> >                                     socklen_t addrlen)
> >
> > struct GNUNET_NAT_Handle;
> >
> > struct GNUNET_NAT_Handle *
> > GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
> >                                 struct GNUNET_CONFIGURATION_Handle *cfg,
> >                                const struct sockaddr *addr, socklen_t
> > addrlen, GNUNET_NAT_AddressCallback callback, void *callback_cls);
> > void
> > GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h);
> >
> >
> > Calling "register" is asking for the given IP address (which can be v4 or
> > v6) to be made available "more globally" (mapped by the NAT box).  If
> > such a "more global" address becomes available, the callback should be
> > invoked with the address other peers should bind to.  If the mapping
> > changes, the callback would be called with "NO" (on the old address) and
> > then "YES" on the updated address.
>
> From what I know of UPnP and NAT-PMP, I understand that you cannot
> choose the addresses (nor internal nor external) for which the
> redirection is performed: the internal address we used to send the
> request will be used for internal redirection, and the external address
> is chosen by the NAT box. So we can't take a sockaddr, but merely a port
> number. Moreover, isn't NAT kind of obsolete on IPv6? My knowledge in
> this realm is very limited, though.

Yes, you are right in that the NAT box has little choice as far as the 
internal address goes.  However, imagine you have a PC with two Ethernet 
cards, both connected to a NAT box:

                                     PC
            eth0 (10.1.0.1)          eth1( 10.2.0.1)
                     |                                   |
          NAT (global: 1.2.3.4)       NAT (global: 5.6.7.8)

With the above API, you can specifically ask either NAT to create a port 
mapping.  You may ask for "10.1.0.1:42" and are told "1.2.3.4:401", and then 
you could ask for "10.2.0.1:55" and are told "5.6.7.8:421".  Naturally, in 
most cases the system will only have one IP address (or the caller could leave 
it at all-zeros for "unknown") and then the given struct sockaddr is really 
effectively only a port number.  And as long as your implementation doesn't 
support multiple network interfaces, you may just choose to only take the port 
anyway.

As far as IPv6 goes, yes, sane people think that it should eliminate NAT but 
there are people that try to combine NAT with IPv6.  So in case that insanity 
prevails, our API would at least be prepared.  Not to mention that you may 
have IPv6 between you and the NAT box and then have an IPv4 address from NAT 
to the outside world (imagine your internal network moved entirely to IPv6, 
not dual-stack, and your NAT box did 6over4 magic and stuff like that).  So 
multiple scenarios are conceivable where IPv6 support can make sense.  

And of course an implementation (of my proposed API) is always allowed to just 
return NULL to say "couldn't do that" / "not yet supported".

Final remark: we may need to add an additinal argument to specify a protocol 
type (UDP, TCP, etc.) in the "GNUNET_NAT_register" call, I forgot about that 
last time.
 
> > Note that "register" could be called on a range of IP addresses
> > (127.0.0.1,
> >
> >  ::1, 192.168.1.42) and ports (2086, 1080, ...).  The NAT could would
> >  :: have to
> >
> > decide if that address was somehow "mappable" (and do nothing if not) and
> > for those that are do the right thing.
> 
> You mean called several times, once for each address/port? That means we
> need a GNUNET_NAT_Handler_Init() function, and then pass the struct to
> register(). But I can't see how we could pass addresses, as I said
> above.

Yes, the intend was that we would call it as often as needed (once for each 
mapping).  I don't see why you would need some kind of "init" function; I'd 
just do the full handshake with the NAT box (or PMP-box) for each mapping that 
is being installed.  I don't think efficiency is a concern here to the point 
that doing this once for each port (and keeping state for each mapping) would 
be an issue.

> Other than that, I could not find the cron jobs API that was in GNUnet
> 0.8. I'd need some kind of timers to regularly check that the NAT is
> still working. I'd also need a basic list support if we want to use
> several ports, though I can use a custom singly-linked list if nothing
> exists.

Cron-ish stuff *is* there.  GNUNET_SCHEDULER_add_delayed replaces "cron". The 
only major difference is that at the end of your "cron" function (or its 
continuation) you have to (explicitly / manually) schedule your cron-task 
*again* (each time).  

As for list support, you can obviously write your own custom singly-linked 
lists in C easily.  However, I still think the answer here is to have one NAT 
handle per port and to have each NAT handle have its own "cron" task with the 
scheduler (also helps keep each individual task short).  Tasks with the 
scheduler should be considered "cheap" -- they are not threads! -- but they 
also are expected to run "quickly".

I hope this clarifies things.

Happy hacking!

Christian
-- 
http://grothoff.org/christian/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]