Below is the c program for sending receiving packets using TUN device. You should comment out either the dump_packet() or send_packet(). Otherwise, the program will be sending and receiving packets of its own.
void dump_packet(int fd, int count, char* buffer)
{
printf("the fd is %d. read %d bytes!\n", fd, count);
int i;
for (i=0; i
Wireshark shows the packet are exchanged as below. It's working!
1 0.000000000 203.0.113.2 203.0.113.1 ICMP 86 Echo (ping) request id=0x0019, seq=7/1792, ttl=64 (reply in 2)
2 0.000082333 203.0.113.1 203.0.113.2 ICMP 84 Echo (ping) reply id=0x0019, seq=7/1792, ttl=64 (request in 1)
I added the below code to the previous post to receive ICMP packets.
char *buffer = (char *) calloc(150, sizeof(char));
ssize_t count = read(fd, buffer, 100);
Below is how read() can be used.
The read() function shall attempt to read nbyte bytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf.
In the absence of errors, or if error detection is not performed, the read() function shall return zero and have no other results. reference
Below is the received packet in hex.
00 00 08 00 45 00 00 54 89 4b 40 00 40 01 39 59 cb 00 71 01 cb 00 71 02 08 00 2a c7 00 19 00 07 c8 b6 8c 63 00 00 00 00 af 2b 0a 00 00 00 00 00 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37
The above shows that the source address is "cb 00 71 01->203.0.113.1" and the destination address is "cb 00 71 02->203.0.113.290". I'll try to send packets next time! I'm curious simply switching the source and destination address will be enough to send back the packet?
I created a TUN interface with the below c program.
int main(int argc, char** argv)
{
if (argc != 2)
return 1;
const char* device_name = argv[1];
if (strlen(device_name) + 1 > IFNAMSIZ)
{
return 1;
}
int fd = open("/dev/net/tun", O_RDWR);
if (fd == -1)
{
return 1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, device_name, IFNAMSIZ);
int res = ioctl(fd, TUNSETIFF, &ifr);
if (res == -1)
{
return 1;
}
printf("the created device is only available during this program\n");
while (1) {
}
return 0;
}
The important part in the above code is below. You can provide the name of the interface to "ifr.ifr_name" and spcify whether you want the interface to be TUN or TAP with "ifr.ifr_flags".
int fd = open("/dev/net/tun", O_RDWR);
int res = ioctl(fd, TUNSETIFF, &ifr);
There is another way of creating TUN device using ip command which is shown below.
$ sudo ip tuntap add dev tun0 mode tun
My next attempt is to receive and read packets using read() and send(). I also want to see how packets are being exchanged using Wireshark.
You can check the file descriptor and associated device files with the below command.
$ lsof
cat 307 ryo 1w REG 8, 32 0 106248 /home/ryo/ctf/kernel/file1.txt
Above shows that device files have major and minor numbers to identify the associated device drivers. You can see that 8, 32 are the major and minor number in the above case. You can check which device number has 8, 32 by the below command.
/dev$ ls -la
brw------- 1 root root 8, 32 Nov 23 11:51 sdc
Maybe I should start looking into device drivers used for networking?