// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
pushq %rbx
subq $0x1138, %rsp           # imm = 0x1138
movb %r9b, %al
movb 0x10(%rbp), %r9b
movl %edi, -0xc(%rbp)
movb %sil, -0xd(%rbp)
movb %dl, -0xe(%rbp)
movl %ecx, -0x14(%rbp)
movq %r8, -0x20(%rbp)
movb %al, -0x21(%rbp)
leaq -0x1030(%rbp), %rax
movq %rax, -0x1068(%rbp)
movq $0x1000, -0x1060(%rbp) # imm = 0x1000
leaq -0x1040(%rbp), %rdx
movl $0x2, %edi
leaq -0xc(%rbp), %rsi
movl $0x10, %ecx
callq 0x2030
leaq 0x10647(%rip), %rax     # 0x1b378
cmpq $0x0, (%rax)
je 0xadb2
leaq 0x10642(%rip), %rax     # 0x1b380
movl (%rax), %edi
movsbl 0x10(%rbp), %ecx
leaq 0xb134(%rip), %rdx      # 0x15e7f
leaq 0xb129(%rip), %rax      # 0x15e7b
cmpl $0x1, %ecx
cmoveq %rax, %rdx
movsbq -0x21(%rbp), %rcx
leaq 0x1059b(%rip), %rax     # 0x1b300
movq (%rax,%rcx,8), %rcx
leaq -0x1040(%rbp), %r8
movzbl -0xd(%rbp), %r9d
movl -0x14(%rbp), %r11d
movq -0x20(%rbp), %r10
movsbl -0xe(%rbp), %eax
leaq 0xb291(%rip), %rsi      # 0x16019
leaq 0xb2ab(%rip), %rbx      # 0x1603a
movq %rbx, (%rsp)
movq %rbx, 0x8(%rsp)
movl %r11d, 0x10(%rsp)
movq %r10, 0x18(%rsp)
movl %eax, 0x20(%rsp)
movb $0x0, %al
callq 0x2220
jmp 0xb2e0
leaq -0x10e0(%rbp), %rax
movq %rax, -0x10a8(%rbp)
leaq -0x10e0(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x10b0(%rbp)
leaq -0x1054(%rbp), %rdi
xorl %esi, %esi
movl $0xc, %edx
callq 0x21e0
leaq -0x10e0(%rbp), %rdi
xorl %esi, %esi
movl $0x2c, %edx
callq 0x21e0
leaq -0x10a0(%rbp), %rdi
xorl %esi, %esi
movl $0x38, %edx
callq 0x21e0
movw $0x10, -0x1054(%rbp)
movq $0x14, -0x30(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0xae2e
movq -0x30(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
addq $0x10, %rax
movl %eax, %ecx
movq -0x10a8(%rbp), %rax
movl %ecx, (%rax)
callq 0x2100
movl %eax, %ecx
movq -0x10a8(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x10b0(%rbp), %rax
movb $0x2, (%rax)
movb -0xe(%rbp), %cl
movq -0x10b0(%rbp), %rax
movb %cl, 0x4(%rax)
movsbl 0x10(%rbp), %eax
cmpl $0x1, %eax
jne 0xae99
movq -0x10a8(%rbp), %rax
movw $0x5, 0x6(%rax)
movq -0x10a8(%rbp), %rax
movw $0x21, 0x4(%rax)
movq -0x10b0(%rbp), %rax
movb $-0x1, 0x6(%rax)
jmp 0xaed4
movq -0x10a8(%rbp), %rax
movw $0x605, 0x6(%rax)       # imm = 0x605
movq -0x10a8(%rbp), %rax
movw $0x20, 0x4(%rax)
movq -0x10b0(%rbp), %rax
movb $0x0, 0x6(%rax)
movq -0x10b0(%rbp), %rax
movb $0x4, 0x5(%rax)
movq -0x10b0(%rbp), %rax
movb $0x1, 0x7(%rax)
movsbl -0x21(%rbp), %eax
movl %eax, -0x10ec(%rbp)
testl %eax, %eax
je 0xaf05
jmp 0xaee4
movl -0x10ec(%rbp), %eax
subl $0x1, %eax
je 0xaf4f
jmp 0xaef1
movl -0x10ec(%rbp), %eax
subl $0x2, %eax
je 0xaf96
jmp 0xaff8
movq -0x10b0(%rbp), %rax
addq $0xc, %rax
movq %rax, -0x1048(%rbp)
movq -0x1048(%rbp), %rax
movw $0x2, 0x2(%rax)
movb -0xd(%rbp), %cl
movq -0x10b0(%rbp), %rax
movb %cl, 0x2(%rax)
movq -0x1048(%rbp), %rax
movw $0x8, (%rax)
movq -0x10b0(%rbp), %rax
movl -0xc(%rbp), %ecx
movl %ecx, 0x10(%rax)
jmp 0xb011
movq -0x10b0(%rbp), %rax
addq $0xc, %rax
movq %rax, -0x1048(%rbp)
movq -0x1048(%rbp), %rax
movw $0x1, 0x2(%rax)
movb -0xd(%rbp), %cl
movq -0x10b0(%rbp), %rax
movb %cl, 0x1(%rax)
movq -0x1048(%rbp), %rax
movw $0x8, (%rax)
movq -0x10b0(%rbp), %rax
movl -0xc(%rbp), %ecx
movl %ecx, 0x10(%rax)
jmp 0xb011
movq -0x10b0(%rbp), %rax
addq $0xc, %rax
movq %rax, -0x1048(%rbp)
movq -0x1048(%rbp), %rax
movw $0x8, (%rax)
movsbl 0x10(%rbp), %eax
cmpl $0x1, %eax
jne 0xafd9
movq -0x1048(%rbp), %rax
movw $0x2, 0x2(%rax)
movq -0x10b0(%rbp), %rax
movl -0xc(%rbp), %ecx
movl %ecx, 0x10(%rax)
jmp 0xaff6
movq -0x1048(%rbp), %rax
movw $0x3, 0x2(%rax)
movq -0x10b0(%rbp), %rax
movq -0x20(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x10(%rax)
jmp 0xb011
movsbl -0x21(%rbp), %edx
xorl %edi, %edi
leaq 0xb03c(%rip), %rsi      # 0x16041
movb $0x0, %al
callq 0x123f0
jmp 0xb2e0
cmpl $0x0, -0x14(%rbp)
je 0xb057
movq -0x10b0(%rbp), %rax
addq $0xc, %rax
addq $0x4, %rax
addq $0x4, %rax
movq %rax, -0x1048(%rbp)
movq -0x1048(%rbp), %rax
movw $0x6, 0x2(%rax)
movq -0x1048(%rbp), %rax
movw $0x8, (%rax)
movq -0x10b0(%rbp), %rax
movl -0x14(%rbp), %ecx
movl %ecx, 0x18(%rax)
movl $0x10, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x2500
movl %eax, -0x28(%rbp)
cmpl $0x0, %eax
jge 0xb094
callq 0x2070
movl (%rax), %edi
callq 0x24a0
movq %rax, %rdx
xorl %edi, %edi
leaq 0xafe7(%rip), %rsi      # 0x1606f
movb $0x0, %al
callq 0x123f0
jmp 0xb2e0
movl -0x28(%rbp), %edi
leaq -0x10e0(%rbp), %rsi
movq -0x10a8(%rbp), %rax
movl (%rax), %eax
movl %eax, %edx
leaq -0x1054(%rbp), %rax
movq %rax, -0x10e8(%rbp)
movq -0x10e8(%rbp), %r8
xorl %ecx, %ecx
movl $0xc, %r9d
callq 0x2200
cmpq $0x0, %rax
jge 0xb0fd
callq 0x2070
movl (%rax), %edi
callq 0x24a0
movq %rax, %rdx
xorl %edi, %edi
leaq 0xafcd(%rip), %rsi      # 0x160b6
movb $0x0, %al
callq 0x123f0
movl -0x28(%rbp), %edi
callq 0x2210
jmp 0xb2e0
leaq -0x1054(%rbp), %rax
movq %rax, -0x10a0(%rbp)
movl $0xc, -0x1098(%rbp)
leaq -0x1068(%rbp), %rax
movq %rax, -0x1090(%rbp)
movq $0x1, -0x1088(%rbp)
movq $0x0, -0x1080(%rbp)
movl -0x28(%rbp), %edi
leaq -0x10a0(%rbp), %rsi
xorl %edx, %edx
callq 0x2380
movq %rax, -0x30(%rbp)
leaq -0x1030(%rbp), %rax
movq %rax, -0x10a8(%rbp)
xorl %eax, %eax
cmpq $0x10, -0x30(%rbp)
movb %al, -0x10ed(%rbp)
jb 0xb19a
movq -0x10a8(%rbp), %rax
movl (%rax), %eax
movl %eax, %ecx
xorl %eax, %eax
cmpq $0x10, %rcx
movb %al, -0x10ed(%rbp)
jb 0xb19a
movq -0x10a8(%rbp), %rax
movl (%rax), %eax
cmpq -0x30(%rbp), %rax
setbe %al
movb %al, -0x10ed(%rbp)
movb -0x10ed(%rbp), %al
testb $0x1, %al
jne 0xb1a9
jmp 0xb2d8
movq -0x10a8(%rbp), %rax
movzwl 0x4(%rax), %eax
cmpl $0x3, %eax
jne 0xb1be
jmp 0xb2d8
movq -0x10a8(%rbp), %rax
movzwl 0x4(%rax), %eax
cmpl $0x2, %eax
jne 0xb28d
movq -0x10a8(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0xb28d
leaq -0x1040(%rbp), %rdx
movl $0x2, %edi
leaq -0xc(%rbp), %rsi
movl $0x10, %ecx
callq 0x2030
movsbl 0x10(%rbp), %edx
leaq 0xac77(%rip), %rax      # 0x15e7f
leaq 0xae03(%rip), %rcx      # 0x16012
cmpl $0x1, %edx
cmoveq %rcx, %rax
movq %rax, -0x1110(%rbp)
movsbq -0x21(%rbp), %rcx
leaq 0x100f7(%rip), %rax     # 0x1b320
movq (%rax,%rcx,8), %rax
movq %rax, -0x1108(%rbp)
leaq -0x1040(%rbp), %rax
movq %rax, -0x1100(%rbp)
movzbl -0xd(%rbp), %eax
movl %eax, -0x10f4(%rbp)
movq -0x10a8(%rbp), %rax
xorl %edi, %edi
subl 0x10(%rax), %edi
callq 0x24a0
movq -0x1110(%rbp), %rdx
movq -0x1108(%rbp), %rcx
movq -0x1100(%rbp), %r8
movl -0x10f4(%rbp), %r9d
xorl %edi, %edi
leaq 0xae8f(%rip), %rsi      # 0x16111
movq %rax, (%rsp)
movb $0x0, %al
callq 0x123f0
movq -0x10a8(%rbp), %rax
movl (%rax), %eax
addl $0x4, %eax
subl $0x1, %eax
andl $-0x4, %eax
movl %eax, %eax
movl %eax, %ecx
movq -0x30(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x10a8(%rbp), %rax
movq -0x10a8(%rbp), %rcx
movl (%rcx), %ecx
addl $0x4, %ecx
subl $0x1, %ecx
andl $-0x4, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x10a8(%rbp)
jmp 0xb15c
movl -0x28(%rbp), %edi
callq 0x2210
addq $0x1138, %rsp           # imm = 0x1138
popq %rbx
popq %rbp
retq
nopw (%rax,%rax)