Пример #1
0
/*
 *	Should be called AFTER yanking it from the list, so that
 *	any newly inserted entries don't collide with this one.
 */
int fr_packet_list_id_free(fr_packet_list_t *pl,
			     RADIUS_PACKET *request)
{
	fr_packet_socket_t *ps;
	fr_packet_dst2id_t my_pd, *pd;

	if (!pl || !request) return 0;

	ps = fr_socket_find(pl, request->sockfd);
	if (!ps) return 0;

	my_pd.dst_ipaddr = request->dst_ipaddr;
	my_pd.dst_port = request->dst_port;

	pd = fr_hash_table_finddata(pl->dst2id_ht, &my_pd);
	if (!pd) return 0;

	pd->id[request->id] &= ~(1 << ps->offset);
	
	pd->num_outgoing--;
	ps->num_outgoing--;
	pl->num_outgoing--;

	if(pd->num_outgoing == 0) {
		fr_hash_table_delete(pl->dst2id_ht,&my_pd);
	}
	return 1;
}
Пример #2
0
/*
 *	Wait 10 seconds at most for a child to exit, then give up.
 */
pid_t rad_waitpid(pid_t pid, int *status)
{
	int i;
	thread_fork_t mytf, *tf;

	if (!pool_initialized) return waitpid(pid, status, 0);

	if (pid <= 0) return -1;

	mytf.pid = pid;

	pthread_mutex_lock(&thread_pool.wait_mutex);
	tf = fr_hash_table_finddata(thread_pool.waiters, &mytf);
	pthread_mutex_unlock(&thread_pool.wait_mutex);

	if (!tf) return -1;

	for (i = 0; i < 100; i++) {
		reap_children();

		if (tf->exited) {
			*status = tf->status;

			pthread_mutex_lock(&thread_pool.wait_mutex);
			fr_hash_table_delete(thread_pool.waiters, &mytf);
			pthread_mutex_unlock(&thread_pool.wait_mutex);
			return pid;
		}
		usleep(100000);	/* sleep for 1/10 of a second */
	}

	/*
	 *	10 seconds have passed, give up on the child.
	 */
	pthread_mutex_lock(&thread_pool.wait_mutex);
	fr_hash_table_delete(thread_pool.waiters, &mytf);
	pthread_mutex_unlock(&thread_pool.wait_mutex);

	return 0;
}
Пример #3
0
/*
 *	Add an attribute to the dictionary.
 */
int dict_addattr(const char *name, int vendor, int type, int value,
		 ATTR_FLAGS flags)
{
	size_t namelen;
	static int      max_attr = 0;
	DICT_ATTR	*attr;

	namelen = strlen(name);
	if (namelen >= DICT_ATTR_MAX_NAME_LEN) {
		fr_strerror_printf("dict_addattr: attribute name too long");
		return -1;
	}

	/*
	 *	If the value is '-1', that means use a pre-existing
	 *	one (if it already exists).  If one does NOT already exist,
	 *	then create a new attribute, with a non-conflicting value,
	 *	and use that.
	 */
	if (value == -1) {
		if (dict_attrbyname(name)) {
			return 0; /* exists, don't add it again */
		}

		value = ++max_attr;

	} else if (vendor == 0) {
		/*
		 *  Update 'max_attr'
		 */
		if (value > max_attr) {
			max_attr = value;
		}
	}

	if (value < 0) {
		fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (less than zero)");
		return -1;
	}

	if (value >= 65536) {
		fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 65535).");
		return -1;
	}

	if (vendor) {
		DICT_VENDOR *dv;
		static DICT_VENDOR *last_vendor = NULL;

		if (flags.is_tlv && (flags.encrypt != FLAG_ENCRYPT_NONE)) {
			fr_strerror_printf("Sub-TLV's cannot be encrypted");
			return -1;
		}

		if (flags.has_tlv && (flags.encrypt != FLAG_ENCRYPT_NONE)) {
			fr_strerror_printf("TLV's cannot be encrypted");
			return -1;
		}

		if (flags.is_tlv && flags.has_tag) {
			fr_strerror_printf("Sub-TLV's cannot have a tag");
			return -1;
		}

		if (flags.has_tlv && flags.has_tag) {
			fr_strerror_printf("TLV's cannot have a tag");
			return -1;
		}

		/*
		 *	Most ATTRIBUTEs are bunched together by
		 *	VENDOR.  We can save a lot of lookups on
		 *	dictionary initialization by caching the last
		 *	vendor.
		 */
		if (last_vendor && (vendor == last_vendor->vendorpec)) {
			dv = last_vendor;
		} else {
			dv = dict_vendorbyvalue(vendor);
			last_vendor = dv;
		}

		/*
		 *	If the vendor isn't defined, die.
		 */
		if (!dv) {
			fr_strerror_printf("dict_addattr: Unknown vendor");
			return -1;
		}

		/*
		 *	FIXME: Switch over dv->type, and limit things
		 *	properly.
		 */
		if ((dv->type == 1) && (value >= 256) && !flags.is_tlv) {
			fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 255).");
			return -1;
		} /* else 256..65535 are allowed */
	}

	/*
	 *	Create a new attribute for the list
	 */
	if ((attr = fr_pool_alloc(sizeof(*attr) + namelen)) == NULL) {
		fr_strerror_printf("dict_addattr: out of memory");
		return -1;
	}

	memcpy(attr->name, name, namelen);
	attr->name[namelen] = '\0';
	attr->attr = value;
	attr->attr |= (vendor << 16); /* FIXME: hack */
	attr->vendor = vendor;
	attr->type = type;
	attr->flags = flags;
	attr->vendor = vendor;

	/*
	 *	Insert the attribute, only if it's not a duplicate.
	 */
	if (!fr_hash_table_insert(attributes_byname, attr)) {
		DICT_ATTR	*a;

		/*
		 *	If the attribute has identical number, then
		 *	ignore the duplicate.
		 */
		a = fr_hash_table_finddata(attributes_byname, attr);
		if (a && (strcasecmp(a->name, attr->name) == 0)) {
			if (a->attr != attr->attr) {
				fr_strerror_printf("dict_addattr: Duplicate attribute name %s", name);
				fr_pool_free(attr);
				return -1;
			}

			/*
			 *	Same name, same vendor, same attr,
			 *	maybe the flags and/or type is
			 *	different.  Let the new value
			 *	over-ride the old one.
			 */
		}


		fr_hash_table_delete(attributes_byvalue, a);

		if (!fr_hash_table_replace(attributes_byname, attr)) {
			fr_strerror_printf("dict_addattr: Internal error storing attribute %s", name);
			fr_pool_free(attr);
			return -1;
		}
	}

	/*
	 *	Insert the SAME pointer (not free'd when this entry is
	 *	deleted), into another table.
	 *
	 *	We want this behaviour because we want OLD names for
	 *	the attributes to be read from the configuration
	 *	files, but when we're printing them, (and looking up
	 *	by value) we want to use the NEW name.
	 */
	if (!fr_hash_table_replace(attributes_byvalue, attr)) {
		fr_strerror_printf("dict_addattr: Failed inserting attribute name %s", name);
		return -1;
	}

	if (!vendor && (value > 0) && (value < 256)) {
	 	 dict_base_attrs[value] = attr;
	}

	return 0;
}