|
|
|
@ -684,6 +684,32 @@ int is_local_endpoint(const struct intf_address *addr, unsigned int port) {
|
|
|
|
|
|
|
|
|
|
static void release_reserved_port(struct port_pool *pp, ports_q *);
|
|
|
|
|
|
|
|
|
|
static void reserve_additional_port_links(ports_q *ret, struct port_pool *pp, unsigned int port) {
|
|
|
|
|
for (__auto_type l = pp->overlaps.head; l; l = l->next) {
|
|
|
|
|
__auto_type opp = l->data;
|
|
|
|
|
|
|
|
|
|
if (port < opp->min || port > opp->max)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
LOCK(&opp->free_list_lock);
|
|
|
|
|
__auto_type link = free_ports_link(opp, port);
|
|
|
|
|
if (!link)
|
|
|
|
|
goto bail;
|
|
|
|
|
// move link from free list to output
|
|
|
|
|
t_queue_unlink(&opp->free_ports_q, link);
|
|
|
|
|
free_ports_link(opp, port) = NULL;
|
|
|
|
|
t_queue_push_tail_link(ret, link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
// Oops. Some spec didn't have the port available. Probably a race condition.
|
|
|
|
|
// Return everything to its place and report failure by resetting the output
|
|
|
|
|
// list to empty.
|
|
|
|
|
release_reserved_port(pp, ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function just (globally) reserves a port number, it doesn't provide any binding/unbinding.
|
|
|
|
|
* Returns linked list if successful, or NULL if failed.
|
|
|
|
@ -692,41 +718,22 @@ static ports_q reserve_port(struct port_pool *pp, unsigned int port) {
|
|
|
|
|
ports_q ret = TYPED_GQUEUE_INIT;
|
|
|
|
|
|
|
|
|
|
if (port < pp->min || port > pp->max)
|
|
|
|
|
return ret;
|
|
|
|
|
return ret; // empty result
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
LOCK(&pp->free_list_lock);
|
|
|
|
|
__auto_type link = free_ports_link(pp, port);
|
|
|
|
|
if (!link)
|
|
|
|
|
return ret;
|
|
|
|
|
return ret; // empty result
|
|
|
|
|
// move link from free list to output
|
|
|
|
|
t_queue_unlink(&pp->free_ports_q, link);
|
|
|
|
|
free_ports_link(pp, port) = NULL;
|
|
|
|
|
t_queue_push_tail_link(&ret, link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (__auto_type l = pp->overlaps.head; l; l = l->next) {
|
|
|
|
|
__auto_type opp = l->data;
|
|
|
|
|
|
|
|
|
|
if (port < opp->min || port > opp->max)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
LOCK(&opp->free_list_lock);
|
|
|
|
|
__auto_type link = free_ports_link(opp, port);
|
|
|
|
|
if (!link)
|
|
|
|
|
goto bail;
|
|
|
|
|
// move link from free list to output
|
|
|
|
|
t_queue_unlink(&opp->free_ports_q, link);
|
|
|
|
|
free_ports_link(opp, port) = NULL;
|
|
|
|
|
t_queue_push_tail_link(&ret, link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
reserve_additional_port_links(&ret, pp, port);
|
|
|
|
|
// reverts `ret` to empty result on failure
|
|
|
|
|
|
|
|
|
|
bail:
|
|
|
|
|
// Oops. Some spec didn't have the port available. Probably a race condition.
|
|
|
|
|
// Return everything to its place and report failure.
|
|
|
|
|
release_reserved_port(pp, &ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|