/* * 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; }
/* * 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; }
/* * 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; }