1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <pthread.h>
#include "spi.h"
#include "tun.h"
static pthread_t read_thd;
static int tun_fd;
static char tun_name[IFNAMSIZ];
static int tun_alloc(char *dev, int flags) {
struct ifreq ifr;
int fd, err;
char *clonedev = "/dev/net/tun";
/* Arguments taken by the function:
*
* char *dev: the name of an interface (or '\0'). MUST have enough
* space to hold the interface name if '\0' is passed
* int flags: interface flags (eg, IFF_TUN etc.)
*/
fd = open(clonedev, O_RDWR);
if (fd < 0) {
return fd;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
if (*dev) {
/* if a device name was specified, put it in the structure; otherwise,
* the kernel will try to allocate the "next" device of the
* specified type */
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
}
/* try to create the device */
err = ioctl(fd, TUNSETIFF, (void *) &ifr);
if (err < 0) {
close(fd);
return err;
}
/* if the operation was successful, write back the name of the
* interface to the variable "dev", so the caller can know
* it. Note that the caller MUST reserve space in *dev (see calling
* code below) */
strcpy(dev, ifr.ifr_name);
/* this is the special file descriptor that the caller will use to talk
* with the virtual interface */
return fd;
}
ssize_t tun_read(unsigned char *buffer, size_t buf_size) {
return read(tun_fd, buffer, buf_size);
}
ssize_t tun_write(unsigned char *buffer, size_t buf_len) {
return write(tun_fd, buffer, buf_len);
}
int tun_init(char *name) {
int rv;
if (strlen(name) >= sizeof(tun_name) - 1) return -1;
strcpy(tun_name, name);
tun_fd = tun_alloc(tun_name, IFF_TUN | IFF_NO_PI);
if (tun_fd < 0) return -1;
return 0;
}
|