// File: /workspace/github_c_makefile_star2_O3/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 $0x10c8, %rsp           # imm = 0x10C8
movl %r9d, %r15d
movq %r8, %r14
movl %ecx, %r13d
movl %edx, %r12d
movl %esi, %ebp
leaq 0xc(%rsp), %rsi
movl %edi, (%rsi)
leaq 0xc0(%rsp), %rbx
movq %rbx, 0x70(%rsp)
movq $0x1000, 0x78(%rsp)     # imm = 0x1000
leaq 0x60(%rsp), %rdx
movl $0x2, %edi
movl $0x10, %ecx
callq 0x2030
leaq 0xef88(%rip), %rax      # 0x172d8
cmpq $0x0, (%rax)
je 0x83c4
leaq 0xef83(%rip), %rax      # 0x172e0
movl (%rax), %edi
cmpb $0x1, 0x1100(%rsp)
leaq 0x8b7d(%rip), %rax      # 0x10eeb
leaq 0x8b7a(%rip), %rdx      # 0x10eef
cmoveq %rax, %rdx
movsbq %r15b, %rax
leaq 0x8b28(%rip), %rsi      # 0x10eac
movslq (%rsi,%rax,4), %rcx
addq %rsi, %rcx
movzbl %bpl, %r9d
movsbl %r12b, %r10d
subq $0x8, %rsp
leaq 0x8d0c(%rip), %r11      # 0x110aa
leaq 0x8ce4(%rip), %rsi      # 0x11089
leaq 0x68(%rsp), %r8
xorl %eax, %eax
pushq %r10
pushq %r14
pushq %r13
pushq %r11
pushq %r11
callq 0x2200
addq $0x30, %rsp
jmp 0x8691
xorl %eax, %eax
movq %rax, 0x48(%rsp)
movl %eax, 0x50(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rsp)
movups %xmm0, 0x28(%rsp)
movl %eax, 0x38(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0xa0(%rsp)
movq %rax, 0xb0(%rsp)
movw $0x10, 0x48(%rsp)
xorl %eax, %eax
movq %r13, 0x40(%rsp)
testl %r13d, %r13d
setne %al
leal 0x24(,%rax,8), %eax
movl %eax, %r13d
movl %eax, 0x10(%rsp)
callq 0x2100
movl %eax, 0x1c(%rsp)
movb $0x2, 0x20(%rsp)
movb %r12b, 0x24(%rsp)
movb 0x1100(%rsp), %cl
cmpb $0x1, %cl
jne 0x844d
movss 0x89f7(%rip), %xmm0     # 0x10e40
movb $-0x1, %al
jmp 0x8461
movb $0x4, 0x25(%rsp)
movb $0x1, 0x27(%rsp)
movss 0x89f1(%rip), %xmm0     # 0x10e50
xorl %eax, %eax
movl %ebp, %r12d
movss %xmm0, 0x14(%rsp)
movb %al, 0x26(%rsp)
movl %r15d, %ebp
movsbl %bpl, %edx
cmpl $0x2, %edx
je 0x84a5
cmpl $0x1, %edx
je 0x8496
testl %edx, %edx
jne 0x8658
movb %r12b, 0x22(%rsp)
movl $0x20008, 0x2c(%rsp)    # imm = 0x20008
jmp 0x84bc
movb %r12b, 0x21(%rsp)
movl $0x10008, 0x2c(%rsp)    # imm = 0x10008
jmp 0x84bc
movw $0x8, 0x2c(%rsp)
cmpb $0x1, %cl
jne 0x86a3
movw $0x2, 0x2e(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x30(%rsp)
movq 0x40(%rsp), %rax
testl %eax, %eax
je 0x84d9
movl $0x60008, 0x34(%rsp)    # imm = 0x60008
movl %eax, 0x38(%rsp)
movl $0x10, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x24e0
testl %eax, %eax
js 0x8637
movl %eax, %r14d
movl %r13d, %edx
leaq 0x10(%rsp), %rsi
leaq 0x48(%rsp), %r15
movl %eax, %edi
xorl %ecx, %ecx
movq %r15, %r8
movl $0xc, %r9d
callq 0x21e0
testq %rax, %rax
js 0x866a
leaq 0x80(%rsp), %rsi
movq %r15, (%rsi)
movl $0xc, 0x8(%rsi)
leaq 0x70(%rsp), %rax
movq %rax, 0x10(%rsi)
movq $0x1, 0x18(%rsi)
movq $0x0, 0x20(%rsi)
movl %r14d, %edi
xorl %edx, %edx
callq 0x2360
cmpq $0x10, %rax
jb 0x8689
movq %rax, %r15
cmpb $0x1, 0x1100(%rsp)
leaq 0x8b14(%rip), %rax      # 0x11082
leaq 0x897a(%rip), %rcx      # 0x10eef
cmoveq %rax, %rcx
movq %rcx, 0x58(%rsp)
movzbl %bpl, %ebp
shll $0x2, %ebp
movzbl %r12b, %eax
movl %eax, 0x40(%rsp)
movl (%rbx), %eax
cmpq $0x10, %rax
jb 0x8689
cmpq %rax, %r15
jb 0x8689
movzwl 0x4(%rbx), %ecx
cmpl $0x2, %ecx
je 0x85b5
cmpl $0x3, %ecx
jne 0x861f
jmp 0x8689
cmpl $0x0, 0x10(%rbx)
je 0x861f
movl $0x2, %edi
leaq 0xc(%rsp), %rsi
leaq 0x60(%rsp), %r12
movq %r12, %rdx
movl $0x10, %ecx
callq 0x2030
leaq 0x88da(%rip), %rax      # 0x10eb8
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 0x8b81(%rip), %rsi      # 0x11181
movq 0x60(%rsp), %rdx
movq %r13, %rcx
movq %r12, %r8
movl 0x48(%rsp), %r9d
xorl %eax, %eax
pushq %r10
callq 0xd88c
addq $0x10, %rsp
movl (%rbx), %eax
addl $0x3, %eax
andl $-0x4, %eax
subq %rax, %r15
addq %rax, %rbx
cmpq $0xf, %r15
ja 0x858d
jmp 0x8689
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x8a95(%rip), %rsi      # 0x110df
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xd88c
jmp 0x8691
leaq 0x8a52(%rip), %rsi      # 0x110b1
xorl %edi, %edi
xorl %eax, %eax
callq 0xd88c
jmp 0x8691
callq 0x2070
movl (%rax), %edi
callq 0x2480
leaq 0x8aa9(%rip), %rsi      # 0x11126
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0xd88c
movl %r14d, %edi
callq 0x21f0
addq $0x10c8, %rsp           # imm = 0x10C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movw $0x3, 0x2e(%rsp)
movl (%r14), %eax
jmp 0x84c0