open questions for libnetng

Frédéric Raynal <[email protected]> Sun, 1 Aug 2004 10:06:37 +0200
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
Hi guys

As I have time to spend on libnet, I've started coding "libnetng"
which is only the next generation for libnet (development name).

That is done mostly from what I described here:
http://www.security-labs.org/index.php3?page=libnetng

Lots of work has already be done, but more left to do. However, I need
to have you opinion on some points.

Remember I'd like to keep the next API (almost) fully compatible with
the current one. However, there are cases where a change can be a real
benefit.

Question 1 : ptag
=================
pblock have been replaced by pbuf. A pbuf is only a pointer to a given
position in a buffer. Each pbuf is bound to a packet (the buffer). So,
now, when we use ptag (the int referring to a pbuf), it means in fact
the pbuf contained in a given packet.
Thus we can have 2 ptags with the same value as they don't refer to the
same packet.

My problem is that I dint know if it can be source of confusion or not.

Example #1: building a single packet
  l = libnet_init(LIBNET_RAW4, NULL, err_buf);
  ptag = libnet_build_foo(..., l, 0);
  libnet_write(l);

Example #2: building several packets
  l = libnet_init(LIBNET_RAW4, NULL, err_buf);
  // for the first packet, don't change anything
  ptag = libnet_build_foo(..., l, 0);
  printf("ptag=%d\n", ptag);
  ptag = libnet_build_bar(..., l, 0);
  printf("ptag=%d\n", ptag);

  // build the second packet: we need to use the libnet_build_pbuf_*()
  // functions to specify the packet
  pkt = libnet_new_packet();
  ptag = libnet_build_pbuf_foo(..., pkt, l, 0);
  printf("ptag=%d\n", ptag);
  ptag = libnet_build_pbuf_bar(..., pkt, l, 0);
  printf("ptag=%d\n", ptag);

  libnet_write(l);

Output:
  new packet 0: data=0x40177fc0
  ptag=1
  ptag=2
  new packet 1: data=0x40183fee
  ptag=1
  ptag=2
  
As you can see, ptags are currently the same. So the management of the
ptags is let to the user.

Here comes (at least ;-) the question : should I let that that way ?

What's the alternative? I can use a global variable, shared by all the
packets, and each time a ptag is needed, it is increased.

  [ ] use ptag relative to each packet
  [ ] use a global var to handle ptag


Question 2 : changing API of the libnet_auto_build_*()
======================================================
I have added payload and ptag as a user may want to re-use its
previous ptag and put its own data in there. So there are 3 more
arguments.

Should we keep it the old way or not ?
  [ ] Yes, keep the old way
  [ ] No, update to the new API

Question 3 : IPv4 and IPv4 options, API change ?
================================================
Handling separately IPv4 header and options is a real pain in the ass.
We always need to update the header size when changing options, move
payload around, and so on.  That is a huge source of bugs.

To be compatible with the current API, we can keep
libnet_build_ipv4(), and that function will not provide access to
options.
Then, I can add libnet_build_ipv4_with_options(), which builds the
IPv4 header and the options in one shot.
	    
Should we keep it the old way or not ?
  [ ] Yes, keep the old way and have many bugs in libnet ;-)
  [ ] No, update to the new API

Question 4 : TCP/UDP checksums
==============================
Everybody knows, TCP/UDP checksums are opposite to the OSI network
model as it needs inputs that are at IP layer to be computed.

In libnetng, I'd like to have checksums computed at the same time as
when you build the pbuf, that is when you require for a foo header,
you got it fully filled.

However, when such a pbuf requires inputs that are not yet available,
that is impossible :-(

I don't know how to solve that. I have some ideas, but I don't like
them.

Bad idea #1: change the API for TCP and UDP builder so that it also
includes IPv4 needed addresses. That way, you can compute checksums
with whatever addresses you want, and then later build the IP header
with other addresses.
That is a bad idea because it breaks the current API.
What I like with that bad idea is that you have a full control on TCP
and UDP header, which is currently not true.

Bad idea #2: don't change the API and delay the computation of the
checksums until we have the needed inputs.
That is a bad idea because :
  - that behavior will not be coherent in regard of the others
    checksummed headers
  - it is not that simple to do, and thus source of bug
What I like is that it does not break the API.

I don't have other bad idea (at least on that topic ;-)

Which of these bad ideas is the less worst?
  [ ] I prefer bad idea #1
  [ ] I prefer bad idea #2
  [ ] I have other bad ideas:




That's all folks ... for now :-)

I hope to have something sharable the next week. I may also need halo
to perform some testing on each architecture and link types.

	Fred Raynal