From: Andrea Crotti on
>
> One way it can be used is by implementing something like a select()
> loop on the tun descriptor, to be woken up when there is something to read
> or write. When will that be? Again, it depends. You will have data
> available for reading on the tun descriptor when the kernel decides that
> some packet has to be sent out the tun interface. When will that be? It
> depends. For example, when the kernel has to route a packet and sees
> that the route for the destination IP points out the tun interface.

Now in this toy example I was not using it, but in the program we ARE
using a select.

We have a select on the tun device and the usb port and, looking at what
status they have, we behave accordingly.
Is this than supposed to work?

The thing that puzzled me is that if I get a successful return value
from write I expected to be able to read something, but then apparently
is not so simple as I thought.

And also another question, is sniffing traffic on a tun device
exactly as sniffing it on a "normal" network device?

Thanks a lot
From: pk on
On Sun, 25 Jul 2010 16:13:34 +0200 Andrea Crotti
<andrea.crotti.0(a)gmail.com> wrote:

> >
> > One way it can be used is by implementing something like a select()
> > loop on the tun descriptor, to be woken up when there is something to
> > read or write. When will that be? Again, it depends. You will have data
> > available for reading on the tun descriptor when the kernel decides that
> > some packet has to be sent out the tun interface. When will that be? It
> > depends. For example, when the kernel has to route a packet and sees
> > that the route for the destination IP points out the tun interface.
>
> Now in this toy example I was not using it, but in the program we ARE
> using a select.
>
> We have a select on the tun device and the usb port and, looking at what
> status they have, we behave accordingly.
> Is this than supposed to work?
>
> The thing that puzzled me is that if I get a successful return value
> from write I expected to be able to read something, but then apparently
> is not so simple as I thought.

Why do you think so? At the IP level (which is what tun is about), there's
no implicit or explicit concept of "request" or "reply". All you see is
"traffic", which can be of many different types (ICMP, TCP, UDP, and the
application protocols riding on top of them). But unless you peek past the
IP header, all you see when working with tun are IP packets. Period.

Again, let's use eth0. Let's imagine you are *on the wire* (this is
important to make the analogy with tun closer) capturing all the traffic
going to/from eth0.

You capture a packet coming from the Internet, destined to eth0. Good. Does
that give you any clue about what the next packet you'll get in the
other direction will be, or even that there will be one at all? No, it
doesn't. At the IP level there's absolutely nothing that provides that
information.

Of course, if the payload is an HTTP request for the local box, and you know
that (which requires looking past the IP and TCP header), you *might* expect
the server's reply after a while, but again, this is not granted at all,
because

- the return route used by the server may be through a different
path/interface
- depending on what the box does, there may be lots of other outgoing
packets from eth0 before the reply you're looking for
- perhaps the incoming packet was malformed, had a bad checksum or
whatever, and was discarded by the kernel
- the web server may have crashed, in which case the kernel sends back an
ICMP error
- etc.etc.

In short, there's no reason to expect the traffic in the two directions to
be related. It's very well possible that you'll get hundreds of packets in
one direction before even seeing one in the other.

> And also another question, is sniffing traffic on a tun device
> exactly as sniffing it on a "normal" network device?

It's exactly the same (except you don't see the datalink header if you're
in tun mode).
From: Andrea Crotti on

> Why do you think so? At the IP level (which is what tun is about), there's
> no implicit or explicit concept of "request" or "reply". All you see is
> "traffic", which can be of many different types (ICMP, TCP, UDP, and the
> application protocols riding on top of them). But unless you peek past the
> IP header, all you see when working with tun are IP packets. Period.
>

Yes I never meant that I want an automatic correlation between ingoing
and outgoing traffic, I just mean that if I know there's something going
on tun, I would also like to read from it...
>
> It's exactly the same (except you don't see the datalink header if you're
> in tun mode).

So what am I doing wrong?
Now I onlys start this program below, that open a file descriptor to a
tun device in read-only mode.

Then in another shell I run
ifconfig tun2 10.0.0.1

then I try to ping 10.0.0.1 and it works perfectly.

BUT my program doesn't read anything, and even worse, ALSO tcpdump is
completely silent.
It should not be so hard, there must be some stupid mistake then..

--8<---------------cut here---------------start------------->8---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>

char msg[] = "hallo hallo\n";
#define TUN_DEV "/dev/net/tun"

int create_tun(char *dev) {
struct ifreq ifr;
int err;
char *clonedev = TUN_DEV;

// open the tun device rw mode
int fd = open(clonedev , O_RDONLY);
if (fd < 0) {
perror("Opening /dev/net/tun");
exit(1);
}

// prepare ifr
memset(&ifr, 0, sizeof(ifr));
// Set the flags
ifr.ifr_flags = IFF_TUN;

// If a device name was specified it is put to ifr
if (*dev) {
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
}

// Try to create the device
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
close(fd);
perror("Creating the device");
return err;
}

// Write the name of the new interface to device
strcpy(dev, ifr.ifr_name);
printf("successfully created %s\n", dev);
return fd;
}

int write_tun_write(int fd) {
return write(fd, msg, strlen(msg));
}

int read_from(int fd, char *buf, int len) {
return read(fd, buf, len);
}

int main() {
char name[IFNAMSIZ];
name[0] = 0;
int fd = create_tun(name);

/* int wrote = write_tun_write(fd); */
/* printf("wrote %d bytes on the tun device, now check iptables log\n", wrote); */

char buf[strlen(msg) + 1];
// read is blocking here
read_from(fd, buf, strlen(msg));
printf("reading from the device string\n");
return 0;
}
--8<---------------cut here---------------end--------------->8---
From: pk on
On Sun, 25 Jul 2010 19:13:31 +0200 Andrea Crotti
<andrea.crotti.0(a)gmail.com> wrote:

> > It's exactly the same (except you don't see the datalink header if
> > you're in tun mode).
>
> So what am I doing wrong?
> Now I onlys start this program below, that open a file descriptor to a
> tun device in read-only mode.
>
> Then in another shell I run
> ifconfig tun2 10.0.0.1
>
> then I try to ping 10.0.0.1 and it works perfectly.
>
> BUT my program doesn't read anything, and even worse, ALSO tcpdump is
> completely silent.
> It should not be so hard, there must be some stupid mistake then..

Ok, I told you already. Last time:

try this:

# ifconfig eth0 10.0.0.1 netmask 255.255.255.0 up
# tcpdump -i eth0

# ping 10.0.0.1


Does tcpdump get you anything? No, right? So why do you expect a different
result when doing it on tun2?

From: Andrea Crotti on

> Ok, I told you already. Last time:
>
> try this:
>
> # ifconfig eth0 10.0.0.1 netmask 255.255.255.0 up
> # tcpdump -i eth0
>
> # ping 10.0.0.1
>
>
> Does tcpdump get you anything? No, right? So why do you expect a different
> result when doing it on tun2?

Mm actually I get something, I see all the arp request looking for
10.0.0.1 in this case...

I see your point, but I still don't see a solution.

Probably tun is not what we need, but it would be very strange since is
what our professor told us to use for this purpose.

And if it's not what else should we use to do such a thing then?

Maybe just a simple file (socket/fifo) and read/write from it then...