Beispiel #1
0
int registry_init() {

	if (pom_mutex_init_type(&registry_global_lock, PTHREAD_MUTEX_RECURSIVE) != POM_OK)
		return POM_ERR;


	// Init random numbers for UIDs
	registry_uid_seedp = (unsigned int) time(NULL) + (unsigned int) pthread_self();
		

	return POM_OK;
}
Beispiel #2
0
int conntrack_get_unique_from_parent(struct proto_process_stack *stack, unsigned int stack_index) {

	struct conntrack_node_list *child = NULL;
	struct conntrack_list *lst = NULL;

	struct proto_process_stack *s = &stack[stack_index];
	struct proto_process_stack *s_prev = &stack[stack_index - 1];

	struct conntrack_entry *parent = s_prev->ce;

	if (!s->proto) {
		pomlog(POMLOG_ERR "Cannot allocate conntrack for NULL proto");
		return POM_ERR;
	}

	if (!parent) {
		pomlog(POMLOG_ERR "Cannot allocate unique conntrack without a parent");
		return POM_ERR;
	}


	if (s->ce) { // This should only occur in the case that an expectation matched
		// Make sure the conntrack is locked
		int res = pthread_mutex_trylock(&s->ce->lock);
		if (res && res != EBUSY && res == EDEADLK) {
			pomlog(POMLOG_ERR "Error while locking the conntrack : %s", pom_strerror(res));
			return POM_ERR;
		}
		return POM_OK;
	}

	conntrack_lock(parent);

	struct conntrack_tables *ct = s->proto->ct;
	struct conntrack_entry *res = NULL;

	// Look for the conntrack
	
	if (parent->children) {
		struct conntrack_node_list *child = parent->children;
		for (child = parent->children; child && child->ce->proto != s->proto; child = child->next);
		if (child)
			res = child->ce;
	} 

	if (!res) {

		// Alloc the conntrack
		res = malloc(sizeof(struct conntrack_entry));
		if (!res) {
			pom_oom(sizeof(struct conntrack_entry));
			goto err;
		}

		memset(res, 0, sizeof(struct conntrack_entry));
		res->proto = s->proto;

		if (pom_mutex_init_type(&res->lock, PTHREAD_MUTEX_ERRORCHECK) != POM_OK)
			goto err;

		// Alloc the child list
		child = malloc(sizeof(struct conntrack_node_list));
		if (!child) 
			goto err;
		
		memset(child, 0, sizeof(struct conntrack_node_list));
		child->ce = res;
		child->ct = ct;

		// Alloc the parent node
		res->parent = malloc(sizeof(struct conntrack_node_list));
		if (!res->parent) {
			free(child);
			goto err;
		}
		memset(res->parent, 0, sizeof(struct conntrack_node_list));
		res->parent->ce = parent;
		res->parent->ct = parent->proto->ct;
		res->parent->hash = parent->hash;

		// Alloc the list node
		lst = malloc(sizeof(struct conntrack_list));
		if (!lst) {
			pom_oom(sizeof(struct conntrack_list));
			goto err;
		}
		memset(lst, 0, sizeof(struct conntrack_list));
		lst->ce = res;

		// Add the child to the parent
		child->next = parent->children;
		if (child->next)
			child->next->prev = child;
		parent->children = child;

		// Add the conntrack to the table
		pom_mutex_lock(&ct->locks[0]);
		lst->next = ct->table[0];
		if (lst->next)
			lst->next->prev = lst;
		ct->table[0] = lst;
		pom_mutex_unlock(&ct->locks[0]);
		debug_conntrack("Allocated conntrack %p with parent %p (uniq child)", res, parent);

		registry_perf_inc(s->proto->perf_conn_cur, 1);
		registry_perf_inc(s->proto->perf_conn_tot, 1);

	}

	conntrack_unlock(parent);

	conntrack_lock(res);
	res->refcount++;
	s->ce = res;
	s->direction = s_prev->direction;

	struct proto_process_stack *s_next = &stack[stack_index + 1];
	s_next->direction = s->direction;

	return POM_OK;

err:
	if (res) {
		pthread_mutex_destroy(&res->lock);
		free(res);
	}

	if (child)
		free(child);
	conntrack_unlock(parent);

	return POM_ERR;
}
Beispiel #3
0
int conntrack_get(struct proto_process_stack *stack, unsigned int stack_index) {

	struct proto_process_stack *s = &stack[stack_index];
	struct proto_process_stack *s_prev = &stack[stack_index - 1];
	struct proto_process_stack *s_next = &stack[stack_index + 1];

	if (s->ce)
		return POM_OK;
		
	if (!s->proto || !s->proto->info->ct_info)
		return POM_ERR;

	struct ptype *fwd_value = s->pkt_info->fields_value[s->proto->info->ct_info->fwd_pkt_field_id];
	if (!fwd_value)
		return POM_ERR;

	struct ptype *rev_value = NULL;
	if (s->proto->info->ct_info->rev_pkt_field_id != CONNTRACK_PKT_FIELD_NONE) {
		rev_value = s->pkt_info->fields_value[s->proto->info->ct_info->rev_pkt_field_id];
		if (!rev_value)
			return POM_ERR;
	}

	struct conntrack_tables *ct = s->proto->ct;

	uint32_t hash = conntrack_hash(fwd_value, rev_value, s_prev->ce) % ct->table_size;

	// Lock the specific hash while browsing for a conntrack
	pom_mutex_lock(&ct->locks[hash]);

	// Try to find the conntrack in the forward table

	// Check if we can find this entry in the forward way
	if (ct->table[hash]) {
		s->ce = conntrack_find(ct->table[hash], fwd_value, rev_value, s_prev->ce);
		if (s->ce) {
			s->direction = POM_DIR_FWD;
			s_next->direction = POM_DIR_FWD;
			pom_mutex_lock(&s->ce->lock);
			s->ce->refcount++;
			pom_mutex_unlock(&ct->locks[hash]);
			return POM_OK;;
		}
	}


	// It wasn't found in the forward way, maybe in the reverse direction ?
	if (rev_value) {
		s->ce = conntrack_find(ct->table[hash], rev_value, fwd_value, s_prev->ce);
		if (s->ce) {
			s->direction = POM_DIR_REV;
			s_next->direction = POM_DIR_REV;
			pom_mutex_lock(&s->ce->lock);
			s->ce->refcount++;
			pom_mutex_unlock(&ct->locks[hash]);
			return POM_OK;
		}

	}

	// It's not found in the reverse direction either, let's create it then

	if (s_prev->direction == POM_DIR_REV && rev_value) {
		// This indicates that the parent conntrack matched in a reverse direction
		// Let's keep directions consistent and swap fwd and rev values
		struct ptype *tmp = rev_value;
		rev_value = fwd_value;
		fwd_value = tmp;
	}


	// Alloc the conntrack entry
	struct conntrack_entry *ce = malloc(sizeof(struct conntrack_entry));
	if (!ce) {
		pom_mutex_unlock(&ct->locks[hash]);
		pom_oom(sizeof(struct conntrack_entry));
		return POM_ERR;
	}
	memset(ce, 0, sizeof(struct conntrack_entry));

	if (pom_mutex_init_type(&ce->lock, PTHREAD_MUTEX_ERRORCHECK) != POM_OK) {
		pom_mutex_unlock(&ct->locks[hash]);
		free(ce);
		return POM_ERR;
	}

	struct conntrack_node_list *child = NULL;

	// We shouldn't have to check if the parent still exists as it
	// is supposed to have a refcount since conntrack_get is called after
	// the parent's conntrack_get was called and before conntrack_refcount_dec
	// was called by core_process_stack.
	if (s_prev->ce) {

		child = malloc(sizeof(struct conntrack_node_list));
		if (!child) {
			pthread_mutex_destroy(&ce->lock);
			pom_mutex_unlock(&ct->locks[hash]);
			free(ce);
			pom_oom(sizeof(struct conntrack_node_list));
			return POM_ERR;
		}
		memset(child, 0, sizeof(struct conntrack_node_list));

		child->ce = ce;
		child->ct = s->proto->ct;
		child->hash = hash;

		ce->parent = malloc(sizeof(struct conntrack_node_list));
		if (!ce->parent) {
			pthread_mutex_destroy(&ce->lock);
			pom_mutex_unlock(&ct->locks[hash]);
			free(child);
			free(ce);
			pom_oom(sizeof(struct conntrack_node_list));
			return POM_ERR;
		}
		ce->parent->ce = s_prev->ce;
		ce->parent->ct = s_prev->ce->proto->ct;
		ce->parent->hash = s_prev->ce->hash;

	}

	ce->proto = s->proto;

	ce->hash = hash;

	struct conntrack_list *lst = NULL;

	ce->fwd_value = ptype_alloc_from(fwd_value);
	if (!ce->fwd_value)
		goto err;

	if (rev_value) {
		ce->rev_value = ptype_alloc_from(rev_value);
		if (!ce->rev_value)
			goto err;
	}
	// Alloc the list node
	lst = malloc(sizeof(struct conntrack_list));
	if (!lst) {
		ptype_cleanup(ce->fwd_value);
		pom_oom(sizeof(struct conntrack_list));
		goto err;
	}
	memset(lst, 0, sizeof(struct conntrack_list));
	lst->ce = ce;

	// Insert in the conntrack table
	lst->next = ct->table[hash];
	if (lst->next) {
		lst->next->prev = lst;
		registry_perf_inc(s->proto->perf_conn_hash_col, 1);
	}
	ct->table[hash] = lst;

	// Add the child to the parent if any
	if (child) {
		pom_mutex_lock(&s_prev->ce->lock);
		if (!s_prev->ce->refcount)
			pomlog(POMLOG_WARN "Internal error, the parent is supposed to have a refcount > 0");
		child->next = s_prev->ce->children;
		if (child->next)
			child->next->prev = child;
		s_prev->ce->children = child;
		pom_mutex_unlock(&s_prev->ce->lock);
	}

	// Unlock the table
	if (s_prev->ce) {
		debug_conntrack("Allocated conntrack %p with parent %p", ce, s_prev->ce);
	} else {
		debug_conntrack("Allocated conntrack %p with no parent", ce);
	}
	pom_mutex_lock(&ce->lock);
	ce->refcount++;
	pom_mutex_unlock(&ct->locks[hash]);

	s->ce = ce;
	s->direction = s_prev->direction;

	// Propagate the direction to the payload as well
	s_next->direction = s->direction;
	
	registry_perf_inc(ce->proto->perf_conn_cur, 1);
	registry_perf_inc(ce->proto->perf_conn_tot, 1);

	return POM_OK;

err:
	pom_mutex_unlock(&ct->locks[hash]);

	pthread_mutex_destroy(&ce->lock);
	if (child)
		free(child);

	if (lst)
		free(lst);

	if (ce->parent)
		free(ce->parent);
	
	if (ce->fwd_value)
		ptype_cleanup(ce->fwd_value);

	if (ce->rev_value)
		ptype_cleanup(ce->rev_value);

	free(ce);

	return POM_ERR;
}
Beispiel #4
0
int conntrack_get_unique(struct proto_process_stack *stack, unsigned int stack_index) {

	struct proto_process_stack *s = &stack[stack_index];
	struct proto_process_stack *s_prev = &stack[stack_index - 1];
	if (s_prev->ce) {
		pomlog(POMLOG_ERR "conntrack_get_unique() can only be used for link protocols");
		return POM_ERR;
	}

	if (s->ce) { // This should only occur in the case that an expectation matched
		// Make sure the conntrack is locked
		int res = pthread_mutex_trylock(&s->ce->lock);
		if (res && res != EBUSY && res == EDEADLK) {
			pomlog(POMLOG_ERR "Error while locking the conntrack : %s", pom_strerror(res));
			return POM_ERR;
		}
		return POM_OK;
	}

	struct conntrack_tables *ct = s->proto->ct;
	pom_mutex_lock(&ct->locks[0]);

	struct conntrack_list *lst = ct->table[0];

	for (lst = ct->table[0]; lst && lst->ce->parent; lst = lst->next);

	if (lst) {
		// Conntrack found
		s->ce = lst->ce;
		pom_mutex_unlock(&ct->locks[0]);
	} else {
		// Alloc the conntrack
		struct conntrack_entry *res = NULL;
		res = malloc(sizeof(struct conntrack_entry));
		if (!res) {
			pom_oom(sizeof(struct conntrack_entry));
			pom_mutex_unlock(&ct->locks[0]);
			return POM_ERR;
		}

		memset(res, 0, sizeof(struct conntrack_entry));
		res->proto = s->proto;

		if (pom_mutex_init_type(&res->lock, PTHREAD_MUTEX_ERRORCHECK) != POM_OK) {
			pom_mutex_unlock(&ct->locks[0]);
			return POM_ERR;
		}

		// Alloc the list node
		lst = malloc(sizeof(struct conntrack_list));
		if (!lst) {
			pom_oom(sizeof(struct conntrack_list));
			pom_mutex_unlock(&ct->locks[0]);
			return POM_ERR;
		}
		memset(lst, 0, sizeof(struct conntrack_list));
		lst->ce = res;

		// Add the conntrack to the table
		lst->next = ct->table[0];
		if (lst->next)
			lst->next->prev = lst;
		ct->table[0] = lst;
		pom_mutex_unlock(&ct->locks[0]);
		debug_conntrack("Allocated unique conntrack %p", res);

		registry_perf_inc(s->proto->perf_conn_cur, 1);
		registry_perf_inc(s->proto->perf_conn_tot, 1);
		s->ce = res;
	}

	conntrack_lock(s->ce);
	s->ce->refcount++;

	struct proto_process_stack *s_next = &stack[stack_index + 1];
	s_next->direction = s->direction;

	return POM_OK;

}