// File: /workspace/github_c_makefile_star2_O3/open-mesh-mirror[P]batmand/hna.c
// Function: hna_global_update
void hna_global_update(struct orig_node *orig_node, unsigned char *new_hna,
				int16_t new_hna_len, struct neigh_node *old_router)
{
	struct hna_element *e, *buff;
	struct hna_global_entry *hna_global_entry;
	int i, num_elements, old_hna_len;
	unsigned char *old_hna;

	/* orig node stopped announcing any networks */
	if ((orig_node->hna_buff) && ((new_hna == NULL) || (new_hna_len == 0))) {
		hna_global_del(orig_node);
		return;
	}

	/* orig node started to announce networks */
	if ((!orig_node->hna_buff) && ((new_hna != NULL) || (new_hna_len != 0))) {
		hna_global_add(orig_node, new_hna, new_hna_len);
		return;
	}

	/**
	 * next hop router changed - no need to change the global hna hash
	 * we just have to make sure that the best orig node is still in place
	 * NOTE: we may miss a changed HNA here which we will update with the next packet
	 */
	if (old_router != orig_node->router) {
		num_elements = orig_node->hna_buff_len / sizeof(struct hna_element);
		buff = (struct hna_element *)orig_node->hna_buff;

		for (i = 0; i < num_elements; i++) {
			e = &buff[i];

			if ((e->netmask < 1) || (e->netmask > 32))
				continue;

			hna_global_entry = ((struct hna_global_entry *)hash_find(hna_global_hash, e));

			if (!hna_global_entry)
				continue;

			/* if the given orig node is not in use no routes need to change */
			if (hna_global_entry->curr_orig_node != orig_node)
				continue;

			add_del_route(e->addr, e->netmask, orig_node->router->addr,
					orig_node->router->if_incoming->addr.sin_addr.s_addr,
					orig_node->router->if_incoming->if_index,
					orig_node->router->if_incoming->dev,
					BATMAN_RT_TABLE_NETWORKS, ROUTE_TYPE_UNICAST, ROUTE_ADD);

			add_del_route(e->addr, e->netmask, old_router->addr,
				old_router->if_incoming->addr.sin_addr.s_addr,
				old_router->if_incoming->if_index,
				old_router->if_incoming->dev,
				BATMAN_RT_TABLE_NETWORKS, ROUTE_TYPE_UNICAST, ROUTE_DEL);
		}

		return;
	}

	/**
	 * check if the buffers even changed. if its still the same, there is no need to
	 * update the routes. if the router changed, then we have to update all the routes
	 * NOTE: no NULL pointer checking here because memcmp() just returns if n == 0
	 */
	if ((orig_node->hna_buff_len == new_hna_len) && (memcmp(orig_node->hna_buff, new_hna, new_hna_len) == 0))
		return;	/* nothing to do */

	/* changed HNA */
	old_hna = orig_node->hna_buff;
	old_hna_len = orig_node->hna_buff_len;

	orig_node->hna_buff = debugMalloc(new_hna_len, 706);
	orig_node->hna_buff_len = new_hna_len;
	memcpy(orig_node->hna_buff, new_hna, new_hna_len);

	/* add new routes and keep old routes */
	num_elements = orig_node->hna_buff_len / sizeof(struct hna_element);
	buff = (struct hna_element *)orig_node->hna_buff;

	for (i = 0; i < num_elements; i++) {
		e = &buff[i];

		/**
		 * if the router is the same, and the announcement was already in the old
		 * buffer, we can keep the route.
		 */
		if (hna_buff_delete((struct hna_element *)old_hna, &old_hna_len, e) == 0) {
			/* not found / deleted, need to add this new route */
			if ((e->netmask > 0) && (e->netmask <= 32))
				_hna_global_add(orig_node, e);
		}
	}

	/* old routes which are not to be kept are deleted now. */
	num_elements = old_hna_len / sizeof(struct hna_element);
	buff = (struct hna_element *)old_hna;

	for (i = 0; i < num_elements; i++) {
		e = &buff[i];

		if ((e->netmask > 0) && (e->netmask <= 32))
			_hna_global_del(orig_node, e);
	}

	/* dispose old hna buffer now. */
	if (old_hna != NULL)
		debugFree(old_hna, 1704);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rcx, %r12
movl %edx, %ebp
movq %rsi, %r13
movq %rdi, %rbx
movq 0x38(%rdi), %r14
testq %r14, %r14
je 0x768e
testq %r13, %r13
setne %al
testw %bp, %bp
setne %cl
testb %cl, %al
jne 0x76ba
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x78ff
testq %r13, %r13
sete %al
testw %bp, %bp
sete %cl
testb %cl, %al
jne 0x76ba
movswl %bp, %edx
movq %rbx, %rdi
movq %r13, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x7383
movswq 0x40(%rbx), %r15
cmpq %r12, 0x8(%rbx)
je 0x7797
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
movq %r15, %rax
mulq %rcx
movq %rdx, %r15
shrq $0x2, %r15
testl %r15d, %r15d
jle 0x7788
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
xorl %r13d, %r13d
movl $0x41, %ebp
movb 0x4(%r14), %al
addb $-0x21, %al
cmpb $-0x20, %al
jb 0x777b
movq 0xff6f(%rip), %rdi      # 0x17678
movq %r14, %rsi
callq 0x69d3
testq %rax, %rax
je 0x777b
cmpq %rbx, 0x8(%rax)
jne 0x777b
movl (%r14), %edi
movzbl 0x4(%r14), %esi
movq 0x8(%rbx), %rax
movl 0x8(%rax), %edx
movq 0x30(%rax), %rax
movl 0x34(%rax), %ecx
movl 0x20(%rax), %r8d
movq 0x8(%rax), %r9
subq $0x8, %rsp
pushq %r13
pushq %r13
pushq %rbp
callq 0x7cd4
addq $0x20, %rsp
movl (%r14), %edi
movzbl 0x4(%r14), %esi
movl 0x8(%r12), %edx
movq 0x30(%r12), %rax
movl 0x34(%rax), %ecx
movl 0x20(%rax), %r8d
movq 0x8(%rax), %r9
subq $0x8, %rsp
pushq $0x1
pushq %r13
pushq %rbp
callq 0x7cd4
addq $0x20, %rsp
addq $0x5, %r14
decq %r15
jne 0x76f8
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movswq %bp, %r12
cmpw %bp, %r15w
jne 0x77b3
movq %r14, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x2340
testl %eax, %eax
je 0x7788
movswl %bp, %edi
movl $0x2c2, %esi            # imm = 0x2C2
callq 0x5d52
movq %rax, 0x38(%rbx)
movw %bp, 0x40(%rbx)
movq %rax, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x2290
movswq 0x40(%rbx), %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
mulq %rcx
movq %rdx, %r12
shrq $0x2, %r12
testl %r12d, %r12d
jle 0x7894
movq 0x38(%rbx), %rbp
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
xorl %r13d, %r13d
leaq (,%r13,4), %rsi
addq %r13, %rsi
addq %rbp, %rsi
testq %r14, %r14
je 0x785a
movslq %r15d, %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
mulq %rcx
shrq $0x2, %rdx
testl %edx, %edx
jle 0x785a
movl %edx, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
movq %r14, %rax
movl (%rax), %edi
xorl (%rsi), %edi
movb 0x4(%rax), %r8b
xorb 0x4(%rsi), %r8b
movzbl %r8b, %r8d
orl %edi, %r8d
je 0x786d
addq $0x5, %rax
decq %rcx
jne 0x783c
movb 0x4(%rsi), %al
decb %al
cmpb $0x1f, %al
ja 0x7888
movq %rbx, %rdi
callq 0x74a3
jmp 0x7888
decl %edx
movslq %edx, %rcx
leaq (%rcx,%rcx,4), %rcx
movl (%r14,%rcx), %edx
movb 0x4(%r14,%rcx), %cl
movb %cl, 0x4(%rax)
movl %edx, (%rax)
addl $-0x5, %r15d
incq %r13
cmpq %r12, %r13
jne 0x7806
movslq %r15d, %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
mulq %rcx
movq %rdx, %r15
shrq $0x2, %r15
testl %r15d, %r15d
jle 0x78db
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
movq %r14, %r12
movb 0x4(%r12), %al
decb %al
cmpb $0x1f, %al
ja 0x78d0
movq %rbx, %rdi
movq %r12, %rsi
callq 0x797d
addq $0x5, %r12
decq %r15
jne 0x78ba
jmp 0x78e4
testq %r14, %r14
je 0x7788
movq %r14, %rdi
movl $0x6a8, %esi            # imm = 0x6A8
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x628b