// File: /workspace/github_c_makefile_star2_O2/open-mesh-mirror[P]batmand/linux/route.c
// Function: add_del_rule
void add_del_rule(uint32_t network, uint8_t netmask, int8_t rt_table, uint32_t prio, const char *iif, int8_t rule_type, int8_t rule_action)
{
	int netlink_sock;
	size_t len;
	char buf[4096], str1[16];
	struct rtattr *rta;
	struct sockaddr_nl nladdr;
	struct iovec iov;
	struct msghdr msg;
	struct nlmsghdr *nh;
	struct req_s {
		struct rtmsg rtm;
		char buff[2 * (sizeof(struct rtattr) + 4)];
	} *req;
	char req_buf[NLMSG_LENGTH(sizeof(struct req_s))] ALIGN_WORD;

	iov.iov_base = buf;
	iov.iov_len  = sizeof(buf);


	inet_ntop(AF_INET, &network, str1, sizeof (str1));

	if (policy_routing_script != NULL) {
		dprintf(policy_routing_pipe, "RULE %s %s %s %i %s %s %u %s %i\n", (rule_action == RULE_DEL ? "del" : "add"), rule_type_to_string[rule_type], str1, netmask, "unused", "unused", prio, iif, rt_table);
		return;
	}


	nh = (struct nlmsghdr *)req_buf;
	req = (struct req_s*)NLMSG_DATA(req_buf);
	memset(&nladdr, 0, sizeof(struct sockaddr_nl));
	memset(req_buf, 0, NLMSG_LENGTH(sizeof(struct req_s)));
	memset(&msg, 0, sizeof(struct msghdr));

	nladdr.nl_family = AF_NETLINK;

	len = sizeof(struct rtmsg) + sizeof(struct rtattr) + 4;

	if (prio != 0)
		len += sizeof(struct rtattr) + 4;

	nh->nlmsg_len = NLMSG_LENGTH(len);
	nh->nlmsg_pid = getpid();
	req->rtm.rtm_family = AF_INET;
	req->rtm.rtm_table = rt_table;


	if (rule_action == RULE_DEL) {

		nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
		nh->nlmsg_type = RTM_DELRULE;
		req->rtm.rtm_scope = RT_SCOPE_NOWHERE;

	} else {

		nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
		nh->nlmsg_type = RTM_NEWRULE;
		req->rtm.rtm_scope = RT_SCOPE_UNIVERSE;
		req->rtm.rtm_protocol = RTPROT_STATIC;
		req->rtm.rtm_type = RTN_UNICAST;

	}

	switch(rule_type) {
	case RULE_TYPE_SRC:
		rta = (struct rtattr *)req->buff;
		rta->rta_type = RTA_SRC;
		req->rtm.rtm_src_len = netmask;
		rta->rta_len = sizeof(struct rtattr) + 4;
		memcpy(((char *)req->buff) + sizeof(struct rtattr), (char *)&network, 4);
		break;
	case RULE_TYPE_DST:
		rta = (struct rtattr *)req->buff;
		rta->rta_type = RTA_DST;
		req->rtm.rtm_dst_len = netmask;
		rta->rta_len = sizeof(struct rtattr) + 4;
		memcpy(((char *)req->buff) + sizeof(struct rtattr), (char *)&network, 4);
		break;
	case RULE_TYPE_IIF:
		rta = (struct rtattr *)req->buff;
		rta->rta_len = sizeof(struct rtattr) + 4;

		if (rule_action == RULE_DEL) {
			rta->rta_type = RTA_SRC;
			memcpy(((char *)req->buff) + sizeof(struct rtattr), (char *)&network, 4);
		} else {
			rta->rta_type = RTA_IIF;
			memcpy(((char *)req->buff) + sizeof(struct rtattr), iif, 4);
		}
		break;
	default:
		debug_output(0, "Error - unknown rule type (add_del_rule): %i\n", rule_type);
		return;
	}

	if (prio != 0) {
		rta = (struct rtattr *)(req->buff + sizeof(struct rtattr) + 4);
		rta->rta_type = RTA_PRIORITY;
		rta->rta_len = sizeof(struct rtattr) + 4;
		memcpy(((char *)req->buff) + 2 * sizeof(struct rtattr) + 4, (char *)&prio, 4);
	}


	if ((netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {

		debug_output(0, "Error - can't create netlink socket for routing rule manipulation: %s\n", strerror(errno));
		return;

	}


	if (sendto(netlink_sock, req_buf, nh->nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(struct sockaddr_nl)) < 0)  {

		debug_output( 0, "Error - can't send message to kernel via netlink socket for routing rule manipulation: %s\n", strerror(errno));
		close(netlink_sock);
		return;

	}


	msg.msg_name = (void *)&nladdr;
	msg.msg_namelen = sizeof(nladdr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;

	len = recvmsg(netlink_sock, &msg, 0);
	nh = (struct nlmsghdr *)buf;

	while (NLMSG_OK(nh, len)) {

		if (nh->nlmsg_type == NLMSG_DONE)
			break;

		if ((nh->nlmsg_type == NLMSG_ERROR) && (((struct nlmsgerr*)NLMSG_DATA(nh))->error != 0)) {

			inet_ntop(AF_INET, &network, str1, sizeof (str1));

			debug_output(0, "Error - can't %s rule %s %s/%i: %s\n", (rule_action == RULE_DEL ? "delete" : "add"), rule_type_to_string_script[rule_type], str1, netmask, strerror(-((struct nlmsgerr*)NLMSG_DATA(nh))->error));

		}

		nh = NLMSG_NEXT(nh, len);

	}

	close(netlink_sock);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x10b8, %rsp           # imm = 0x10B8
movl %r9d, %r15d
movq %r8, %r14
movl %ecx, %r13d
movl %edx, %r12d
movl %esi, %ebp
movq %rsp, %rsi
movl %edi, (%rsi)
leaq 0xb0(%rsp), %rbx
movq %rbx, 0x60(%rsp)
movq $0x1000, 0x68(%rsp)     # imm = 0x1000
pushq $0x2
popq %rdi
leaq 0x50(%rsp), %rdx
pushq $0x10
popq %rcx
callq 0x2030
leaq 0xf82d(%rip), %rax      # 0x172d8
cmpq $0x0, (%rax)
je 0x7b1f
leaq 0xf828(%rip), %rax      # 0x172e0
movl (%rax), %edi
cmpb $0x1, 0x10f0(%rsp)
leaq 0x8402(%rip), %rax      # 0xfecb
leaq 0x83ff(%rip), %rdx      # 0xfecf
cmoveq %rax, %rdx
movsbq %r15b, %rax
leaq 0x83ad(%rip), %rsi      # 0xfe8c
movslq (%rsi,%rax,4), %rcx
addq %rsi, %rcx
movzbl %bpl, %r9d
movsbl %r12b, %r10d
subq $0x8, %rsp
leaq 0x8591(%rip), %r11      # 0x1008a
leaq 0x8569(%rip), %rsi      # 0x10069
leaq 0x58(%rsp), %r8
xorl %eax, %eax
pushq %r10
pushq %r14
pushq %r13
pushq %r11
pushq %r11
callq 0x2200
addq $0x30, %rsp
jmp 0x7dd1
andq $0x0, 0x40(%rsp)
andl $0x0, 0x48(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rsp)
movups %xmm0, 0x20(%rsp)
andl $0x0, 0x30(%rsp)
movaps %xmm0, 0x70(%rsp)
andq $0x0, 0xa0(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
movw $0x10, 0x40(%rsp)
xorl %eax, %eax
movq %r13, 0x38(%rsp)
testl %r13d, %r13d
setne %al
leal 0x24(,%rax,8), %eax
movl %eax, 0x4(%rsp)
movl %eax, 0x8(%rsp)
callq 0x2100
movl %eax, 0x14(%rsp)
movb $0x2, 0x18(%rsp)
movb %r12b, 0x1c(%rsp)
movb 0x10f0(%rsp), %r12b
cmpb $0x1, %r12b
jne 0x7baa
movss 0x827a(%rip), %xmm0     # 0xfe20
movb $-0x1, %al
jmp 0x7bbe
movb $0x4, 0x1d(%rsp)
movb $0x1, 0x1f(%rsp)
movss 0x8274(%rip), %xmm0     # 0xfe30
xorl %eax, %eax
movl %ebp, %r13d
movss %xmm0, 0xc(%rsp)
movb %al, 0x1e(%rsp)
movl %r15d, %ebp
movsbl %bpl, %edx
cmpl $0x2, %edx
je 0x7c02
cmpl $0x1, %edx
je 0x7bf3
testl %edx, %edx
jne 0x7d98
movb %r13b, 0x1a(%rsp)
movl $0x20008, 0x24(%rsp)    # imm = 0x20008
jmp 0x7c1a
movb %r13b, 0x19(%rsp)
movl $0x10008, 0x24(%rsp)    # imm = 0x10008
jmp 0x7c1a
movw $0x8, 0x24(%rsp)
cmpb $0x1, %r12b
jne 0x7de3
movw $0x2, 0x26(%rsp)
movl (%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x38(%rsp), %rax
testl %eax, %eax
je 0x7c36
movl $0x60008, 0x2c(%rsp)    # imm = 0x60008
movl %eax, 0x30(%rsp)
pushq $0x10
popq %rdi
pushq $0x2
popq %rsi
xorl %edx, %edx
callq 0x24e0
testl %eax, %eax
js 0x7d77
movl 0x4(%rsp), %edx
leaq 0x8(%rsp), %rsi
leaq 0x40(%rsp), %r15
pushq $0xc
popq %r9
movl %eax, %r14d
movl %eax, %edi
xorl %ecx, %ecx
movq %r15, %r8
callq 0x21e0
testq %rax, %rax
js 0x7daa
leaq 0x70(%rsp), %rsi
movq %r15, (%rsi)
movl $0xc, 0x8(%rsi)
leaq 0x60(%rsp), %rax
movq %rax, 0x10(%rsi)
movq $0x1, 0x18(%rsi)
andq $0x0, 0x20(%rsi)
movl %r14d, 0x4(%rsp)
movl %r14d, %edi
xorl %edx, %edx
callq 0x2360
movq %rax, %r15
cmpb $0x1, %r12b
leaq 0x83ab(%rip), %rax      # 0x10062
leaq 0x8211(%rip), %r12      # 0xfecf
cmoveq %rax, %r12
movzbl %bpl, %ebp
shll $0x2, %ebp
movzbl %r13b, %eax
movl %eax, 0x38(%rsp)
cmpq $0x10, %r15
jb 0x7d71
movl (%rbx), %eax
cmpq $0x10, %rax
jb 0x7d71
cmpq %rax, %r15
jb 0x7d71
movzwl 0x4(%rbx), %ecx
cmpl $0x2, %ecx
je 0x7d00
cmpl $0x3, %ecx
jne 0x7d60
jmp 0x7d71
cmpl $0x0, 0x10(%rbx)
je 0x7d60
pushq $0x2
popq %rdi
movq %rsp, %rsi
leaq 0x50(%rsp), %r14
movq %r14, %rdx
pushq $0x10
popq %rcx
callq 0x2030
leaq 0x8175(%rip), %rax      # 0xfe98
movslq (%rbp,%rax), %r13
addq %rax, %r13
xorl %edi, %edi
subl 0x10(%rbx), %edi
callq 0x2480
movq %rax, %r10
subq $0x8, %rsp
xorl %edi, %edi
leaq 0x841c(%rip), %rsi      # 0x10161
movq %r12, %rdx
movq %r13, %rcx
movq %r14, %r8
movl 0x40(%rsp), %r9d
xorl %eax, %eax
pushq %r10
callq 0xcb1c
popq %rax
popq %rcx
movl (%rbx), %eax
addl $0x3, %eax
andl $-0x4, %eax
subq %rax, %r15
addq %rax, %rbx
jmp 0x7cd1
movl 0x4(%rsp), %edi
jmp 0x7dcc
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x8335(%rip), %rsi      # 0x100bf
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
jmp 0x7dd1
leaq 0x82f2(%rip), %rsi      # 0x10091
xorl %edi, %edi
xorl %eax, %eax
callq 0xcb1c
jmp 0x7dd1
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x8349(%rip), %rsi      # 0x10106
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xcb1c
movl %r14d, %edi
callq 0x21f0
addq $0x10b8, %rsp           # imm = 0x10B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movw $0x3, 0x26(%rsp)
movl (%r14), %eax
jmp 0x7c1d