I have checked the old NAT implementation and found that it had some
problems which I shall summarize below:
- It interfaces directly between the low level interfaces and the lwIP
stack and therefore you will come into problems if you have different
interfaces (PPP and Ethernet)
- It does not work with the recent version of lwIP and the previous
people working on this are not reachable.
I have therefore decided working on this and I would like to go the
following way.
- The first hook in lwIP would be in the general ip processing right
before the ip_forward code. If the paket is taken by the NAT no other
processing is necessary. Right now it looks like:
/* packet not for us? */
if (netif == NULL) {
/* packet not for us, route or discard */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not
for us.\n"));
#if NAT_SUPPORT
/* check if we want to perform NAT with this paket. */
if ( ip_nat_out(p, iphdr,inp) ) {
} else
#endif
#if IP_FORWARD
/* non-broadcast packet? */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
/* try to forward IP packet on (other) interfaces */
ip_forward(p, iphdr, inp);
} else
- The second hook is before the IP input processing when the paket has
a destination for the local host. In this case a check on the internal
NAT tables is made. Right now it looks like:
#if NAT_SUPPORT
if (ip_nat_input(p, inp) != 0 )
{
LWIP_DEBUGF(IP_DEBUG, ("ip_input: paket consumed by nat layer\n"));
} else
#endif
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0)
#endif /* LWIP_RAW */
- Configuration of the NAT layer would look like:
new_nat_entry.out_if = ( struct netif * )arg;
new_nat_entry.in_if = ( struct netif * )&EMAC_if;
IP4_ADDR( &new_nat_entry.source_net, 213, 129, 231, 168 );
IP4_ADDR( &new_nat_entry.source_netmask, 255, 255, 255, 248 );
IP4_ADDR( &new_nat_entry.dest_net, 10, 0, 0, 0 );
IP4_ADDR( &new_nat_entry.source_netmask, 255, 0, 0, 0 );
ip_nat_init( &new_nat_entry );
I need the source and destination interfaces on the NAT interface to
get the IP address which should be used for outgoing "nated" paket. The
input interface is required for the same reasons. I think we could also
use IP addresses to specifiy this but this would not be any better for
the users in my opinion.
Questions/Poblems so far.
- I am currently forwarding pakets between PPP and ethernet over NAT.
This works right now but I had some problems with space for the headers
because PPP and ethernet headers have different sizes and if forwarding
from PPP to ethernet the ethernet header does not fit. I am using a code
like below for this:
/* Since we are forwarding we must assure that there are enough
* paket headers for the link level layer.
*/
q = pbuf_alloc( PBUF_LINK, sizeof( struct eth_hdr ), PBUF_RAM );
if( NULL != q )
{
pbuf_cat( q, p );
pbuf_header( q, -sizeof( struct eth_hdr ) );
if( ERR_OK != ( err = ip_nat_icmp_table[ i ].cfg->in_if->output(
ip_nat_icmp_table[ i ].cfg->in_if, q, ( struct ip_addr * )&( iphdr->dest
) ) ) )
{
LWIP_DEBUGF( NAT_DEBUG, ("ip_nat_in: failed to send
rewritten paket. link layer returned %d\r\n", err ) );
}
My question is now how I can find the size of the headers depending on
the interface type. Otherwise I would always need to allocate the
maximum size.
- The normal forwarding code can not handle PPP/Ethernet pakets due to
the header problem I have mentioned. Would a patch similar than the code
above be useful?
Still we would miss the following for a fullimplementation
- We would need some defragmentation code to handle fragmented UDP and
TCP pakets correctly. This is the most difficult one but is not need by
my customer right now. Still I would like to have the opportunity to add
this later. Are there some design issues I should take care of right now?
- We would need a more user friendly configuration interface for the NAT.
- We should have the possiblity to add application specific hooks -
For example for FTP forwarding or something like this.
My status right now is that I have a basic version already working where
I can forward and nat pakets between a PPP link and an ethernet link.
Thanks for any comments and feedback on this,
Christian
--
+--------------------------------------+-----------------------------------+
Embedded Solutions | DI Christian Walter
Lorenz Böhler Gasse 4/4, A-1200 Wien | cwa...@embedded-solutions.at
http://www.embedded-solutions.at | +43-676-7278851
_______________________________________________
lwip-users mailing list
lwip-...@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users
Would using PBUF_LINK as the layer type and size of zero as arguments to
pbuf_alloc() do what you need? Probably not, as it just uses a constant
to determine the link header size. This would be the right place to make
it dynamic though if you wanted to improve things. That might requiring
passing a netif to pbuf_alloc though, which would be a bit of pain to
change. Perhaps we could add a "pbuf_alloc_for_netif()" function which
would wrap pbuf_alloc(), and leave the current behaviour when
pbuf_alloc() is called directly.
> - The normal forwarding code can not handle PPP/Ethernet pakets due to
> the header problem I have mentioned. Would a patch similar than the code
> above be useful?
Yes.
> Still we would miss the following for a fullimplementation
>
> - We would need some defragmentation code to handle fragmented UDP and
> TCP pakets correctly. This is the most difficult one but is not need by
> my customer right now. Still I would like to have the opportunity to add
> this later. Are there some design issues I should take care of right now?
Couldn't we just forward the fragments?
> - We would need a more user friendly configuration interface for the NAT.
>
> - We should have the possiblity to add application specific hooks -
> For example for FTP forwarding or something like this.
Happy to leave those two to the port or application to sort out.
Thanks for your work on this.
Kieran
> On Sun, 2009-08-16 at 12:21 +0200, Christian Walter wrote:
>> My question is now how I can find the size of the headers depending on
>> the interface type. Otherwise I would always need to allocate the
>> maximum size.
>
> Would using PBUF_LINK as the layer type and size of zero as arguments to
> pbuf_alloc() do what you need? Probably not, as it just uses a constant
> to determine the link header size. This would be the right place to make
> it dynamic though if you wanted to improve things. That might requiring
> passing a netif to pbuf_alloc though, which would be a bit of pain to
> change. Perhaps we could add a "pbuf_alloc_for_netif()" function which
> would wrap pbuf_alloc(), and leave the current behaviour when
> pbuf_alloc() is called directly.
Thanks - I will think about this.
>> Still we would miss the following for a fullimplementation
>>
>> - We would need some defragmentation code to handle fragmented UDP and
>> TCP pakets correctly. This is the most difficult one but is not need by
>> my customer right now. Still I would like to have the opportunity to add
>> this later. Are there some design issues I should take care of right now?
>
> Couldn't we just forward the fragments?
The problem with this is that I can not track the state anymore since
I need the TCP and UDP headers for this. When I receive back an packet
I am currently checking if the tcp port belongs to a connection with
NAT. I only have the TCP header in the first paket of the fragment.
>
>> - We would need a more user friendly configuration interface for the NAT.
>>
>> - We should have the possiblity to add application specific hooks -
>> For example for FTP forwarding or something like this.
>
> Happy to leave those two to the port or application to sort out.
Okay. Thanks for your valuable feedback,
Christian
--
+--------------------------------------+-----------------------------------+
Embedded Solutions | DI Christian Walter
Lorenz B?hler Gasse 4/4, A-1200 Wien | cwa...@embedded-solutions.at
http://www.embedded-solutions.at | +43-676-7278851
_______________________________________________
Simon