// File: /workspace/github_c_makefile_star2_O2/open-mesh-mirror[P]batmand/linux/tun.c
// Function: add_dev_tun
int8_t add_dev_tun( struct batman_if *batman_if, uint32_t tun_addr, char *tun_dev, size_t tun_dev_size, int32_t *fd, int32_t *ifi ) {

	int32_t tmp_fd, sock_opts;
	struct ifreq ifr_tun, ifr_if;
	struct sockaddr_in addr;

	/* set up tunnel device */
	memset( &ifr_tun, 0, sizeof(ifr_tun) );
	memset( &ifr_if, 0, sizeof(ifr_if) );

	ifr_tun.ifr_flags = IFF_TUN | IFF_NO_PI;
	strncpy( ifr_tun.ifr_name, "gate%d", IFNAMSIZ );

	if ( ( *fd = open( "/dev/net/tun", O_RDWR ) ) < 0 ) {

		debug_output( 0, "Error - can't create tun device (/dev/net/tun): %s\n", strerror(errno) );
		return -1;

	}

	if ( ( ioctl( *fd, TUNSETIFF, (void *)&ifr_tun ) ) < 0 ) {

		debug_output( 0, "Error - can't create tun device (TUNSETIFF): %s\n", strerror(errno) );
		close(*fd);
		return -1;

	}

	if ( ioctl( *fd, TUNSETPERSIST, 1 ) < 0 ) {

		debug_output( 0, "Error - can't create tun device (TUNSETPERSIST): %s\n", strerror(errno) );
		close(*fd);
		return -1;

	}


	tmp_fd = socket( AF_INET, SOCK_DGRAM, 0 );

	if ( tmp_fd < 0 ) {
		debug_output( 0, "Error - can't create tun device (udp socket): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		return -1;
	}


	/* set ip of this end point of tunnel */
	memset( &addr, 0, sizeof(addr) );
	addr.sin_addr.s_addr = tun_addr;
	addr.sin_family = AF_INET;
	memcpy( &ifr_tun.ifr_addr, &addr, sizeof(struct sockaddr) );


	if ( ioctl( tmp_fd, SIOCSIFADDR, &ifr_tun) < 0 ) {

		debug_output( 0, "Error - can't create tun device (SIOCSIFADDR): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		close( tmp_fd );
		return -1;

	}


	if ( ioctl( tmp_fd, SIOCGIFINDEX, &ifr_tun ) < 0 ) {

		debug_output( 0, "Error - can't create tun device (SIOCGIFINDEX): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		close( tmp_fd );
		return -1;

	}

	*ifi = ifr_tun.ifr_ifindex;

	if ( ioctl( tmp_fd, SIOCGIFFLAGS, &ifr_tun) < 0 ) {

		debug_output( 0, "Error - can't create tun device (SIOCGIFFLAGS): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		close( tmp_fd );
		return -1;

	}

	ifr_tun.ifr_flags |= IFF_UP;
	ifr_tun.ifr_flags |= IFF_RUNNING;

	if ( ioctl( tmp_fd, SIOCSIFFLAGS, &ifr_tun) < 0 ) {

		debug_output( 0, "Error - can't create tun device (SIOCSIFFLAGS): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		close( tmp_fd );
		return -1;

	}

	/* get MTU from real interface */
	strncpy( ifr_if.ifr_name, batman_if->dev, IFNAMSIZ - 1 );

	if ( ioctl( tmp_fd, SIOCGIFMTU, &ifr_if ) < 0 ) {

		debug_output( 0, "Error - can't create tun device (SIOCGIFMTU): %s\n", strerror(errno) );
		del_dev_tun( *fd );
		close( tmp_fd );
		return -1;

	}

	/* set MTU of tun interface: real MTU - 29 */
	if ( ifr_if.ifr_mtu < 100 ) {

		debug_output( 0, "Warning - MTU smaller than 100 -> can't reduce MTU anymore\n" );

	} else {

		ifr_tun.ifr_mtu = ifr_if.ifr_mtu - 29;

		if ( ioctl( tmp_fd, SIOCSIFMTU, &ifr_tun ) < 0 ) {

			debug_output( 0, "Error - can't create tun device (SIOCSIFMTU): %s\n", strerror(errno) );
			del_dev_tun( *fd );
			close( tmp_fd );
			return -1;

		}

	}


	/* make tun socket non blocking */
	sock_opts = fcntl( *fd, F_GETFL, 0 );
	fcntl( *fd, F_SETFL, sock_opts | O_NONBLOCK );


	strncpy( tun_dev, ifr_tun.ifr_name, tun_dev_size - 1 );
	close( tmp_fd );

	return 1;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r9, %r13
movq %r8, %rbx
movq %rcx, %r14
movq %rdx, %rbp
movl %esi, %r15d
movq %rdi, %r12
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
andq $0x0, 0x20(%rsp)
movaps %xmm0, 0x30(%rsp)
andq $0x0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movw $0x1001, 0x10(%rsp)     # imm = 0x1001
movups 0x7fb9(%rip), %xmm0     # 0x1092a
movaps %xmm0, (%rsp)
leaq 0x7bee(%rip), %rdi      # 0x1056a
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0x23a0
movl %eax, (%rbx)
testl %eax, %eax
js 0x8aac
movq %rsp, %rdx
movl $0x400454ca, %esi       # imm = 0x400454CA
movl %eax, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8ad0
movl (%rbx), %edi
pushq $0x1
popq %rdx
movl $0x400454cb, %esi       # imm = 0x400454CB
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8ae5
movq %rbp, 0x28(%rsp)
pushq $0x2
popq %rdi
movl %edi, %esi
xorl %edx, %edx
callq 0x24e0
testl %eax, %eax
js 0x8b0b
movl %eax, %ebp
movq %rsp, %rdx
movl $0x2, 0x10(%rdx)
movl %r15d, 0x14(%rdx)
andq $0x0, 0x18(%rdx)
movl $0x8916, %esi           # imm = 0x8916
movl %eax, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8b36
movq %rsp, %rdx
movl $0x8933, %esi           # imm = 0x8933
movl %ebp, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8b4e
movq %rsp, %rdx
movl 0x10(%rdx), %eax
movl %eax, (%r13)
movl $0x8913, %esi           # imm = 0x8913
movl %ebp, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8b66
movq %rsp, %rdx
orb $0x41, 0x10(%rdx)
movl $0x8914, %esi           # imm = 0x8914
movl %ebp, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8b7e
movq 0x8(%r12), %rsi
leaq 0x30(%rsp), %r12
pushq $0xf
popq %rdx
movq %r12, %rdi
callq 0x2090
movl $0x8921, %esi           # imm = 0x8921
movl %ebp, %edi
movq %r12, %rdx
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8b96
movl 0x40(%rsp), %eax
cmpl $0x63, %eax
jg 0x8bab
leaq 0x7d16(%rip), %rsi      # 0x107b4
xorl %edi, %edi
xorl %eax, %eax
callq 0xcb1c
jmp 0x8bc6
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b28(%rip), %rsi      # 0x105e7
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
jmp 0x8c32
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b38(%rip), %rsi      # 0x1061b
jmp 0x8af8
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b54(%rip), %rsi      # 0x1064c
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
movl (%rbx), %edi
jmp 0x8c2d
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b63(%rip), %rsi      # 0x10681
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
movl (%rbx), %edi
callq 0x88e2
jmp 0x8c32
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b6a(%rip), %rsi      # 0x106b3
jmp 0x8c18
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7b85(%rip), %rsi      # 0x106e6
jmp 0x8c18
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7ba1(%rip), %rsi      # 0x1071a
jmp 0x8c18
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7bbd(%rip), %rsi      # 0x1074e
jmp 0x8c18
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7bd9(%rip), %rsi      # 0x10782
jmp 0x8c18
addl $-0x1d, %eax
movq %rsp, %rdx
movl %eax, 0x10(%rdx)
movl $0x8922, %esi           # imm = 0x8922
movl %ebp, %edi
xorl %eax, %eax
callq 0x21d0
testl %eax, %eax
js 0x8c05
movl (%rbx), %edi
pushq $0x3
popq %rsi
xorl %edx, %edx
xorl %eax, %eax
callq 0x20e0
movl (%rbx), %edi
orl $0x800, %eax            # imm = 0x800
pushq $0x4
popq %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x20e0
decq %r14
movq %rsp, %rsi
movq 0x28(%rsp), %rdi
movq %r14, %rdx
callq 0x2090
movl %ebp, %edi
callq 0x21f0
movb $0x1, %al
jmp 0x8c34
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x7bd8(%rip), %rsi      # 0x107f0
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
movl (%rbx), %edi
callq 0x88e2
movl %ebp, %edi
callq 0x21f0
movb $-0x1, %al
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq