/** @brief Frees a TCP session **/ inline static void __tcp_free_session ( pntoh_tcp_session_t session ) { pntoh_tcp_session_t ptr = 0; pntoh_tcp_stream_t item = 0; ntoh_tcp_key_t first = 0; if ( params.sessions_list == session ) params.sessions_list = session->next; else{ for ( ptr = params.sessions_list ; ptr != 0 && ptr->next != session ; ptr = ptr->next ); if ( ptr != 0 ) ptr->next = session->next; } lock_access( &session->lock ); while ( ( first = htable_first ( session->timewait ) ) != 0 ) { item = (pntoh_tcp_stream_t)htable_remove(session->timewait,first,0); lock_access ( &item->lock ); __tcp_free_stream ( session , &item , NTOH_REASON_SYNC , NTOH_REASON_EXIT ); } while ( ( first = htable_first ( session->streams ) ) != 0 ) { item = (pntoh_tcp_stream_t)htable_remove(session->streams,first, 0); lock_access ( &item->lock ); __tcp_free_stream ( session , &item , NTOH_REASON_SYNC , NTOH_REASON_EXIT ); } unlock_access( &session->lock ); pthread_cancel ( session->tID ); pthread_join ( session->tID , 0 ); sem_destroy ( &session->max_streams ); sem_destroy ( &session->max_timewait ); free_lockaccess ( &session->lock ); htable_destroy ( &session->streams ); htable_destroy ( &session->timewait ); free ( session ); return; }
void expire_tls_sessions(main_server_st * s) { tls_cache_st *cache; struct htable_iter iter; time_t now, exp; now = time(0); cache = htable_first(s->tls_db.ht, &iter); while (cache != NULL) { gnutls_datum_t d; d.data = (void *)cache->session_data; d.size = cache->session_data_size; exp = gnutls_db_check_entry_time(&d); if (now - exp > TLS_SESSION_EXPIRATION_TIME(s->config)) { cache->session_id_size = 0; htable_delval(s->tls_db.ht, &iter); safe_memset(cache->session_data, 0, cache->session_data_size); talloc_free(cache); s->tls_db.entries--; } cache = htable_next(s->tls_db.ht, &iter); } return; }
void faup_snapshot_output(faup_handler_t *fh, faup_snapshot_t *snapshot, FILE *fd) { size_t counter; size_t values_count; faup_snapshot_value_count_t *vc; struct htable_iter iter; char first_timebuf[200]; char last_timebuf[200]; fprintf(fd, "{\n"); fprintf(fd,"\t\"snapshot name\": \"%s\",\n", snapshot->name); if (!snapshot->length) { fprintf(fd,"\t\"snapshot length\": %ld\n", snapshot->length); } else { fprintf(fd,"\t\"snapshot length\": %ld,\n", snapshot->length); fprintf(fd,"\t\"items\":["); for (counter = 0; counter < snapshot->length; counter++) { faup_snapshot_item_t *item = snapshot->items[counter]; fprintf(fd,"\t\t{\n"); fprintf(fd,"\t\t\"key\": \"%s\",\n", item->key); fprintf(fd,"\t\t\"length\": %ld,\n", item->length); fprintf(fd,"\t\t\"values\": [\n"); if (item->length) { values_count = 1; vc = htable_first(&item->values, &iter); while (vc) { strftime(first_timebuf, sizeof(first_timebuf), "%Y-%m-%d %H:%M:%S %z", localtime(&vc->first_time_seen)); strftime(last_timebuf, sizeof(last_timebuf), "%Y-%m-%d %H:%M:%S %z", localtime(&vc->last_time_seen)); fprintf(fd,"\t\t\t{\"value\": \"%s\", \"count\": %ld, \"first seen\": \"%s\", \"last seen\": \"%s\"}", vc->value, vc->count, first_timebuf, last_timebuf); if (values_count == item->length) { fprintf(fd,"\n"); } else { fprintf(fd,",\n"); } values_count++; vc = htable_next(&item->values, &iter); } } fprintf(fd,"\t\t]\n\t}"); if (counter == snapshot->length - 1) { fprintf(fd,"\n"); fprintf(fd, "\t]\n"); } else { fprintf(fd,",\n"); } } } fprintf(fd, "\n}\n"); }
void ip_lease_deinit(struct ip_lease_db_st* db) { struct ip_lease_st * cache; struct htable_iter iter; cache = htable_first(&db->ht, &iter); while(cache != NULL) { free(cache); cache = htable_next(&db->ht, &iter); } htable_clear(&db->ht); return; }
void ip_lease_deinit(struct ip_lease_db_st* db) { struct ip_lease_st * cache; struct htable_iter iter; cache = htable_first(&db->ht, &iter); while(cache != NULL) { /* disable the destructor */ cache->db = NULL; talloc_free(cache); cache = htable_next(&db->ht, &iter); } htable_clear(&db->ht); return; }
void faup_snapshot_item_free(faup_snapshot_item_t *item) { struct htable_iter iter; faup_snapshot_value_count_t *vc; vc = htable_first(&item->values, &iter); while (vc) { htable_del(&item->values, hash_string(vc->value), vc); faup_snapshot_value_count_free(vc); vc = htable_next(&item->values, &iter); } htable_clear(&item->values); free(item->key); free(item); }
void cleanup_client_entries(sec_mod_st *sec) { struct htable *db = sec->client_db; client_entry_st *t; struct htable_iter iter; time_t now = time(0); t = htable_first(db, &iter); while (t != NULL) { if (t->time != -1 && (now - t->time) > (sec->config->cookie_timeout + AUTH_SLACK_TIME) && t->in_use == 0) { htable_delval(db, &iter); clean_entry(sec, t); } t = htable_next(db, &iter); } }
static void dump_firsttouch(void) { debug_print("%s", "Dump firsttouch.map\n"); char path[MAX_PATH]; snprintf(path, sizeof(path), "%s/%s", dump_path, firsttouch_suffix); FILE *ft_map = fopen(path, "w"); if (!ft_map) errx(EXIT_FAILURE, "Could not create %s file : %s\n", firsttouch_suffix, strerror(errno)); struct htable_iter iter; ft_entry * t; for (t = htable_first(&firsttouch, &iter); t; t = htable_next(&firsttouch, &iter)) { fprintf(ft_map, "%d %lx\n", t->tid, (unsigned long)t->start_of_page); } fclose(ft_map); }
void kmscon_hashtable_free(struct kmscon_hashtable *tbl) { struct htable_iter i; struct kmscon_hashentry *entry; if (!tbl) return; for (entry = htable_first(&tbl->tbl, &i); entry; entry = htable_next(&tbl->tbl, &i)) { htable_delval(&tbl->tbl, &i); if (tbl->free_key) tbl->free_key(entry->key); if (tbl->free_value) tbl->free_value(entry->value); free(entry); } htable_clear(&tbl->tbl); free(tbl); }
void faup_snapshot_item_debug(faup_snapshot_item_t *item) { struct htable_iter iter; faup_snapshot_value_count_t *vc; if (!item) { printf("** item empty, cannot debug!\n"); return; } printf("** \titem\n"); printf("** \tkey:%s\n", item->key); printf("** \tlength:%ld\n", item->length); if (item->length) { vc = htable_first(&item->values, &iter); while (vc) { faup_snapshot_value_count_debug(vc); vc = htable_next(&item->values, &iter); } } }
const char *likely_stats(unsigned int min_hits, unsigned int percent) { struct get_stats_info info; struct htable_iter i; char *ret; struct trace *trace; if (!htable) return NULL; info.min_hits = min_hits; info.worst = NULL; info.worst_ratio = 2; /* This is O(n), but it's not likely called that often. */ for (trace = htable_first(htable, &i); trace; trace = htable_next(htable,&i)) { get_stats(trace, &info); } if (info.worst_ratio * 100 > percent) return NULL; ret = malloc(strlen(info.worst->condstr) + strlen(info.worst->file) + sizeof(long int) * 8 + sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)")); sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)", info.worst->file, info.worst->line, info.worst->expect ? "" : "un", info.worst->condstr, (unsigned)(info.worst_ratio * 100), info.worst->right, info.worst->count); htable_del(htable, hash_trace(info.worst), info.worst); free(info.worst); return ret; }
static void plain_group_list(void *pool, void *additional, char ***groupname, unsigned *groupname_size) { FILE *fp; char line[512]; ssize_t ll; char *p, *sp; unsigned i; size_t hval; struct htable_iter iter; char *tgroup[MAX_GROUPS]; unsigned tgroup_size; struct htable hash; struct plain_cfg_st *config = additional; htable_init(&hash, rehash, NULL); pool = talloc_init("plain"); fp = fopen(config->passwd, "r"); if (fp == NULL) { syslog(LOG_AUTH, "error in plain authentication; cannot open: %s", (char*)config->passwd); return; } line[sizeof(line)-1] = 0; while ((p=fgets(line, sizeof(line)-1, fp)) != NULL) { ll = strlen(p); if (ll <= 4) continue; if (line[ll - 1] == '\n') { ll--; line[ll] = 0; } if (line[ll - 1] == '\r') { ll--; line[ll] = 0; } #ifdef HAVE_STRSEP sp = line; p = strsep(&sp, ":"); if (p != NULL) { p = strsep(&sp, ":"); #else p = strtok_r(line, ":", &sp); if (p != NULL) { p = strtok_r(NULL, ":", &sp); #endif if (p != NULL) { break_group_list(pool, p, tgroup, &tgroup_size); for (i=0; i<tgroup_size; i++) { hval = rehash(tgroup[i], NULL); if (htable_get(&hash, hval, str_cmp, tgroup[i]) == NULL) { if (strlen(tgroup[i]) > 1) htable_add(&hash, hval, tgroup[i]); } } } } } *groupname_size = 0; *groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS); if (*groupname == NULL) { goto exit; } p = htable_first(&hash, &iter); while (p != NULL && (*groupname_size) < MAX_GROUPS) { (*groupname)[(*groupname_size)] = talloc_strdup(*groupname, p); p = htable_next(&hash, &iter); (*groupname_size)++; } /* always succeed */ exit: htable_clear(&hash); safe_memset(line, 0, sizeof(line)); fclose(fp); return; } const struct auth_mod_st plain_auth_funcs = { .type = AUTH_TYPE_PLAIN | AUTH_TYPE_USERNAME_PASS, .allows_retries = 1, .global_init = plain_global_init, .auth_init = plain_auth_init, .auth_deinit = plain_auth_deinit, .auth_msg = plain_auth_msg, .auth_pass = plain_auth_pass, .auth_user = plain_auth_user, .auth_group = plain_auth_group, .group_list = plain_group_list };
int main(int argc, char *argv[]) { unsigned int i; uintptr_t perfect_bit; struct htable ht; uint64_t val[NUM_VALS]; uint64_t dne; void *p; struct htable_iter iter; plan_tests(29); for (i = 0; i < NUM_VALS; i++) val[i] = i; dne = i; htable_init(&ht, hash, NULL); ok1(ht.max == 0); ok1(ht.bits == 0); /* We cannot find an entry which doesn't exist. */ ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* This should increase it once. */ add_vals(&ht, val, 0, 1); ok1(ht.bits == 1); ok1(ht.max == 1); ok1(ht.common_mask == -1); /* Mask should be set. */ ok1(check_mask(&ht, val, 1)); /* This should increase it again. */ add_vals(&ht, val, 1, 1); ok1(ht.bits == 2); ok1(ht.max == 3); /* Mask should be set. */ ok1(ht.common_mask != 0); ok1(ht.common_mask != -1); ok1(check_mask(&ht, val, 2)); /* Now do the rest. */ add_vals(&ht, val, 2, NUM_VALS - 2); /* Find all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* Walk once, should get them all. */ i = 0; for (p = htable_first(&ht,&iter); p; p = htable_next(&ht, &iter)) i++; ok1(i == NUM_VALS); /* Delete all. */ del_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&val[0], NULL), objcmp, &val[0])); /* Worst case, a "pointer" which doesn't have any matching bits. */ htable_add(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); htable_add(&ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]); ok1(ht.common_mask == 0); ok1(ht.common_bits == 0); /* Get rid of bogus pointer before we trip over it! */ htable_del(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); /* Add the rest. */ add_vals(&ht, val, 0, NUM_VALS-1); /* Check we can find them all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* Corner cases: wipe out the perfect bit using bogus pointer. */ htable_clear(&ht); htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1])); ok1(ht.perfect_bit); perfect_bit = ht.perfect_bit; htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit)); ok1(ht.perfect_bit == 0); htable_del(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit)); /* Enlarging should restore it... */ add_vals(&ht, val, 0, NUM_VALS-1); ok1(ht.perfect_bit != 0); htable_clear(&ht); return exit_status(); }
/** @brief Handles the closing of the connection **/ inline static void handle_closing_connection ( pntoh_tcp_session_t session , pntoh_tcp_stream_t stream , pntoh_tcp_peer_t origin , pntoh_tcp_peer_t destination , pntoh_tcp_segment_t segment, int who ) { static unsigned short count = 0; pntoh_tcp_peer_t peer = origin; pntoh_tcp_peer_t side = destination; pntoh_tcp_stream_t twait = 0; ntoh_tcp_key_t key = 0; if ( segment != 0 ) queue_segment ( session , origin , segment ); send_peer_segments ( session , stream , destination , origin , origin->next_seq , 0 , 0, who ); if ( ! origin->segments ) return; if ( count++ < 1 ) { handle_closing_connection ( session , stream , destination , origin , 0, who ); count = 0; } if ( stream->status == NTOH_STATUS_CLOSING ) { if ( stream->closedby == NTOH_CLOSEDBY_CLIENT ) { peer = &stream->client; side = &stream->server; }else{ peer = &stream->server; side = &stream->client; } } /* check segment seq and ack */ if (origin->segments == NULL) return; if ( origin->segments->seq == origin->next_seq && origin->segments->ack == destination->next_seq ) { /* unlink the first segment */ segment = origin->segments; origin->segments = segment->next; }else return; switch ( peer->status ) { case NTOH_STATUS_ESTABLISHED: if ( ! (segment->flags & TH_FIN) ) break; origin->status = NTOH_STATUS_FINWAIT1; destination->status = NTOH_STATUS_CLOSEWAIT; stream->status = NTOH_STATUS_CLOSING; if ( origin == &stream->client ) stream->closedby = NTOH_CLOSEDBY_CLIENT; else if ( origin == &stream->server ) stream->closedby = NTOH_CLOSEDBY_SERVER; break; case NTOH_STATUS_FINWAIT1: if ( segment->flags & TH_FIN ) { peer->status = NTOH_STATUS_CLOSING; side->status = NTOH_STATUS_LASTACK; }else if ( segment->flags & TH_ACK ) peer->status = NTOH_STATUS_FINWAIT2; break; case NTOH_STATUS_CLOSING: if ( segment->flags & TH_ACK ) { peer->status = NTOH_STATUS_TIMEWAIT; side->status = NTOH_STATUS_CLOSED; stream->status = NTOH_STATUS_CLOSED; } break; case NTOH_STATUS_FINWAIT2: if ( segment->flags & (TH_ACK | TH_FIN) ) { peer->status = NTOH_STATUS_TIMEWAIT; if ( segment->flags & TH_FIN ) side->status = NTOH_STATUS_LASTACK; else if ( segment->flags & TH_ACK ) stream->status = side->status = NTOH_STATUS_CLOSED; } break; case NTOH_STATUS_TIMEWAIT: if ( segment->flags & TH_ACK ) stream->status = side->status = NTOH_STATUS_CLOSED; break; } if ( segment->flags & (TH_FIN | TH_RST) ) origin->next_seq++; free ( segment ); if ( stream->status != NTOH_STATUS_CLOSED && origin->receive ) ((pntoh_tcp_callback_t)stream->function) ( stream , origin , destination , 0 , NTOH_REASON_SYNC , 0 ); /* should we add this stream to TIMEWAIT queue? */ if ( stream->status == NTOH_STATUS_CLOSING && IS_TIMEWAIT(stream->client , stream->server) ) { if ( ! htable_find ( session->timewait , stream->key, 0 ) ) { htable_remove ( session->streams , stream->key, 0 ); sem_post ( &session->max_streams ); while ( sem_trywait ( &session->max_timewait ) != 0 ) { key = htable_first ( session->timewait ); twait = htable_remove ( session->timewait , key, 0 ); __tcp_free_stream ( session , &twait , NTOH_REASON_SYNC , NTOH_REASON_CLOSED ); } htable_insert ( session->timewait , stream->key , stream ); } } return; }
void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec) { SecmListCookiesReplyMsg msg = SECM_LIST_COOKIES_REPLY_MSG__INIT; struct htable *db = sec->client_db; client_entry_st *t; struct htable_iter iter; CookieIntMsg *cookies; int ret; time_t now = time(0); if (db == NULL) { send_empty_reply(pool, fd, sec); return; } seclog(sec, LOG_DEBUG, "sending list cookies reply to main"); msg.cookies = talloc_size(pool, sizeof(CookieIntMsg*)*db->elems); if (msg.cookies == NULL) { send_empty_reply(pool, fd, sec); return; } cookies = talloc_size(pool, sizeof(CookieIntMsg)*db->elems); if (cookies == NULL) { send_empty_reply(pool, fd, sec); return; } t = htable_first(db, &iter); while (t != NULL) { if IS_CLIENT_ENTRY_EXPIRED(sec, t, now) goto cont; if (msg.n_cookies >= db->elems) break; cookie_int_msg__init(&cookies[msg.n_cookies]); cookies[msg.n_cookies].safe_id.data = (void*)t->acct_info.safe_id; cookies[msg.n_cookies].safe_id.len = sizeof(t->acct_info.safe_id); cookies[msg.n_cookies].session_is_open = t->session_is_open; cookies[msg.n_cookies].tls_auth_ok = t->tls_auth_ok; if (t->created > 0) cookies[msg.n_cookies].created = t->created; else cookies[msg.n_cookies].created = 0; /* a session which is in use, does not expire */ if (t->exptime > 0 && t->in_use == 0) cookies[msg.n_cookies].expires = t->exptime; else cookies[msg.n_cookies].expires = 0; cookies[msg.n_cookies].username = t->acct_info.username; cookies[msg.n_cookies].groupname = t->acct_info.groupname; cookies[msg.n_cookies].user_agent = t->acct_info.user_agent; cookies[msg.n_cookies].remote_ip = t->acct_info.remote_ip; cookies[msg.n_cookies].status = t->status; cookies[msg.n_cookies].in_use = t->in_use; cookies[msg.n_cookies].vhost = VHOSTNAME(t->vhost); msg.cookies[msg.n_cookies] = &cookies[msg.n_cookies]; msg.n_cookies++; cont: t = htable_next(db, &iter); } ret = send_msg(pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg, (pack_size_func) secm_list_cookies_reply_msg__get_packed_size, (pack_func) secm_list_cookies_reply_msg__pack); if (ret < 0) { seclog(sec, LOG_ERR, "Error sending show cookies reply to main"); } talloc_free(msg.cookies); talloc_free(cookies); }