1 /* fd_tuntap.c: VSYS script to allocate slice-local tuntap interfaces.
2 * Thom Haddow - 06/09/09
4 * Reads interface type from local control unix socket, replies with fd for new
5 * (unconfigured) tuntap interface. VSYS client can get interface name with
16 #include <sys/ioctl.h>
17 #include <sys/socket.h>
18 #include <sys/types.h>
20 #include <linux/if_tun.h>
22 int send_vif_fd(int sock_fd, int vif_fd, char *vif_name)
26 struct cmsghdr *p_cmsg;
28 size_t cmsgbuf[CMSG_SPACE(sizeof(vif_fd)) / sizeof(size_t)];
32 msg.msg_control = cmsgbuf;
33 msg.msg_controllen = sizeof(cmsgbuf);
34 p_cmsg = CMSG_FIRSTHDR(&msg);
35 p_cmsg->cmsg_level = SOL_SOCKET;
36 p_cmsg->cmsg_type = SCM_RIGHTS;
37 p_cmsg->cmsg_len = CMSG_LEN(sizeof(vif_fd));
38 p_fds = (int *) CMSG_DATA(p_cmsg);
40 msg.msg_controllen = p_cmsg->cmsg_len;
47 /* Send the interface name as the iov */
48 vec.iov_base = vif_name;
49 vec.iov_len = strlen(vif_name)+1;
51 while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
53 perror("sending file descriptor");
61 int main(int argc, char *argv[])
63 int control_channel_fd;
66 char if_name[IFNAMSIZ];
72 printf("This script is called by vsys.\n");
77 /* Get slice UID and control channel fd from VSYS args */
78 pwd = getpwnam(argv[1]);
80 perror("Failed to lookup UID");
83 slice_uid = pwd->pw_uid;
84 sscanf(argv[2],"%d", &control_channel_fd);
88 /* Get type param from control channel. */
89 if(recv(control_channel_fd, &if_type, sizeof(int), 0) != sizeof(int)) {
90 perror("fd_tuntap: Failed to read from control channel");
95 /* Generate basename for interface */
96 if(if_type==IFF_TUN) {
97 sprintf(if_name, "tun%d-%%d", slice_uid);
99 else if(if_type==IFF_TAP) {
100 sprintf(if_name, "tap%d-%%d", slice_uid);
102 else { /* TODO: Might also want to allow the other types? */
103 fprintf(stderr, "fd_tuntap: %d is not a valid interface type",if_type);
107 /* Open tun device */
108 if( (tap_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
109 system("modprobe tun");
110 system("ln -sf /dev/net/tun /dev/stdtun");
111 if( (tap_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
112 perror("ERROR: tun_alloc():open(/dev/net/tun)");
118 /* Set interface type */
119 memset(&ifr, 0, sizeof(ifr));
120 ifr.ifr_flags = if_type;
121 strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
123 if( ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0 ) {
125 perror("fd_tuntap: Failed to set tun type");
128 /* Read initialised interface name */
129 strcpy(if_name, ifr.ifr_name);
132 /* Send tap_fd to slice */
133 send_vif_fd(control_channel_fd, tap_fd, if_name);