[srvx-commits] CVS: services/src sockcheck.c,1.54.2.25,1.54.2.26
Brought to you by:
entrope
From: Entrope <en...@us...> - 2001-08-18 23:25:15
|
Update of /cvsroot/srvx/services/src In directory usw-pr-cvs1:/tmp/cvs-serv4281/src Modified Files: Tag: rel-1_0 sockcheck.c Log Message: fix some memory leaks/bugs, and periodically prune checked_ip_dict Index: sockcheck.c =================================================================== RCS file: /cvsroot/srvx/services/src/sockcheck.c,v retrieving revision 1.54.2.25 retrieving revision 1.54.2.26 diff -C2 -r1.54.2.25 -r1.54.2.26 *** sockcheck.c 2001/08/18 02:24:13 1.54.2.25 --- sockcheck.c 2001/08/18 23:25:12 1.54.2.26 *************** *** 91,94 **** --- 91,97 ---- } *sockcheck_cache_info; + DECLARE_LIST(sci_list, sockcheck_cache_info); + DEFINE_LIST(sci_list, sockcheck_cache_info); + /* And here's the list of hostnames that need to be started on. * This is primarily used by the worker thread, although the main *************** *** 172,175 **** --- 175,179 ---- static struct sockcheck_client **client_list; static struct timeval tv_now; + static time_t last_clean; static unsigned int proxies_detected, checked_ip_count; *************** *** 358,363 **** /* TODO: consider allowing non-NULL p_expansion with non-zero p_exp_length, ! * to avoid the malloc() impact. if it's important for speed. ! */ static void expand_var(const struct sockcheck_client *client, unsigned char var, unsigned char **p_expansion, unsigned int *p_exp_length) --- 362,366 ---- /* TODO: consider allowing non-NULL p_expansion with non-zero p_exp_length, ! * to avoid the malloc() impact. If it's important for speed. */ static void expand_var(const struct sockcheck_client *client, unsigned char var, unsigned char **p_expansion, unsigned int *p_exp_length) *************** *** 415,420 **** client->writing = 1; client->send_used = 0; - client->send_size = strlen(template) >> 1; - client->send = malloc(client->send_size); while (*template) { unsigned char *target; --- 418,421 ---- *************** *** 550,556 **** sockcheck_free_client(struct sockcheck_client *client) { ! if (client->send_size) free(client->send); free(client->read); free(client->resp_state); } --- 551,559 ---- sockcheck_free_client(struct sockcheck_client *client) { ! sockcheck_list_unref(client->tests); ! free(client->send); free(client->read); free(client->resp_state); + free(client); } *************** *** 595,598 **** --- 598,602 ---- { struct sockcheck_client *client = client_list[idx]; + unsigned int n; checked_ip_count++; *************** *** 611,621 **** log(PC_LOG, LOG_INFO, "Proxy check failed for client at IP %08x hostname %s (%s)\n", client->addr->addr, client->addr->hostname, client->addr->reason); #endif ! /* don't compare idx != 0 directly, because somebody else may have ! * reordered the tests already ! */ if (client->tests->list[client->test_index] != tests->list[0]) { struct sockcheck_list *new_tests = sockcheck_list_clone(tests); struct sockcheck_state *new_first = client->tests->list[client->test_index]; ! memmove(new_tests->list+1, new_tests->list, client->test_index*sizeof(new_tests->list[0])); new_tests->list[0] = new_first; sockcheck_list_unref(tests); --- 615,625 ---- log(PC_LOG, LOG_INFO, "Proxy check failed for client at IP %08x hostname %s (%s)\n", client->addr->addr, client->addr->hostname, client->addr->reason); #endif ! /* Don't compare idx != 0 directly, because somebody else may have ! * reordered the tests already. */ if (client->tests->list[client->test_index] != tests->list[0]) { struct sockcheck_list *new_tests = sockcheck_list_clone(tests); struct sockcheck_state *new_first = client->tests->list[client->test_index]; ! for (n=0; (n<tests->used) && (tests->list[n] != new_first); n++) ; ! for (; n>0; n--) new_tests->list[n] = new_tests->list[n-1]; new_tests->list[0] = new_first; sockcheck_list_unref(tests); *************** *** 625,639 **** log(PC_LOG, LOG_ERROR, "BUG: sockcheck_decide(\"%s\", %d): unrecognized decision\n", client->addr->hostname, decision); } - sockcheck_list_unref(client->tests); - /* .. and clean up this instance. */ - if (client->send_size) { - #if SOCKCHECK_DEBUG - log(PC_LOG, LOG_INFO, "Freeing client send buffer: size %d used %d buffer %p\n", client->send_size, client->send_used, client->send); - #endif - client->send_size = 0; - client->send_used = 0; - free(client->send); - } - client->addr = NULL; } --- 629,632 ---- *************** *** 878,881 **** --- 871,894 ---- } + static int + find_old_entries(const char *hostname, void *data, void *extra) + { + sockcheck_cache_info sci = data; + struct sci_list *cleaned = extra; + + (void)hostname; + switch (sci->decision) { + case ACCEPT: + case REJECT: + /* Forget anything more than an hour old. */ + if (sci->last_touched < (tv_now.tv_sec - 3600)) sci_list_append(cleaned, sci); + break; + default: + /* Do nothing. */ + break; + } + return 0; + } + static void * sockcheck_worker(void *arg) *************** *** 883,887 **** --- 896,903 ---- int res, timeout, err_count=0; unsigned int n; + struct sci_list cleaned; + (void)arg; + sci_list_init(&cleaned); while (1) { timeout = sockcheck_num_sockets ? 1000 : -1; *************** *** 889,914 **** if (pending_ip_pipe[0] == -1) break; if (res >= 0) { - err_count = 0; - if (poll_list[0].revents) sockcheck_read_pending(); if (gettimeofday(&tv_now, NULL) < 0) { log(PC_LOG, LOG_ERROR, "BUG: sockcheck_worker(): gettimeofday() returned errno %d (%s)\n", errno, strerror(errno)); } while (sockcheck_worker_queue_client(-1)) ; for (n=0; n<sockcheck_num_sockets; n++) { ! /* Do work. If we have work left to do, continue. */ ! if (sockcheck_advance(n) == 0) continue; ! /* Testing done. Decrement number of sockets in progress. */ sockcheck_num_sockets--; ! /* If we can replace the current client, continue. */ ! if (sockcheck_worker_queue_client(n)) continue; ! /* If we can't do more useful work, see if we should swap things down further. */ ! if (n == sockcheck_num_sockets) continue; ! /* no work to do, so swap something down */ #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "sockcheck moving client %s (at %d) to fill hole at %d\n", client_list[sockcheck_num_sockets]->addr->hostname, sockcheck_num_sockets, n); #endif ! poll_list[n+1] = poll_list[sockcheck_num_sockets+1]; ! sockcheck_free_client(client_list[n]); ! client_list[n] = client_list[sockcheck_num_sockets]; n--; } --- 905,939 ---- if (pending_ip_pipe[0] == -1) break; if (res >= 0) { if (gettimeofday(&tv_now, NULL) < 0) { log(PC_LOG, LOG_ERROR, "BUG: sockcheck_worker(): gettimeofday() returned errno %d (%s)\n", errno, strerror(errno)); } + /* This isn't done with timeq because timeq is in the wrong thread :( */ + if (tv_now.tv_sec > (last_clean + 3600)) { + cleaned.used = 0; + dict_foreach(checked_ip_dict, find_old_entries, &cleaned); + for (n=0; n<cleaned.used; n++) { + dict_remove(checked_ip_dict, cleaned.list[n]->hostname); + } + } + /* Do we have any new requests or connetions? */ + err_count = 0; + if (poll_list[0].revents) sockcheck_read_pending(); while (sockcheck_worker_queue_client(-1)) ; + /* Handle existing connections */ for (n=0; n<sockcheck_num_sockets; n++) { ! /* Do work. If the client's not done, continue. */ ! if (!sockcheck_advance(n)) continue; ! /* Testing done. Free client and decrement number of sockets in progress. */ sockcheck_num_sockets--; ! sockcheck_free_client(client_list[n]); ! /* Swap down the highest-numbered socket client, if necessary. */ ! if (n != sockcheck_num_sockets) { #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "sockcheck moving client %s (at %d) to fill hole at %d\n", client_list[sockcheck_num_sockets]->addr->hostname, sockcheck_num_sockets, n); #endif ! poll_list[n+1] = poll_list[sockcheck_num_sockets+1]; ! client_list[n] = client_list[sockcheck_num_sockets]; ! } ! client_list[sockcheck_num_sockets] = 0; n--; } *************** *** 925,928 **** --- 950,954 ---- } } + sci_list_clean(&cleaned); return NULL; } *************** *** 987,991 **** dict_t object; struct sockcheck_state *new_test; ! unsigned int n, found; rd = data; --- 1013,1017 ---- dict_t object; struct sockcheck_state *new_test; ! unsigned int n; rd = data; *************** *** 1018,1040 **** } dict_foreach(object, sockcheck_create_response, new_test); ! /* if none of the responses have template "other", create a ! * default response that goes to accept. ! */ ! found = (unsigned)-1; for (n=0; n<new_test->responses.used; n++) { ! if (!strcmp(new_test->responses.list[n]->template, "other")) { ! found = n; ! } } ! if (found == (unsigned)-1) { rd = alloc_record_data_qstring("accept"); sockcheck_create_response("other", rd, new_test); free_record_data(rd); ! } else if (found != (new_test->responses.used - 1)) { struct sockcheck_response *tmp; /* switch the response for "other" to the end */ tmp = new_test->responses.list[new_test->responses.used - 1]; ! new_test->responses.list[new_test->responses.used - 1] = new_test->responses.list[found]; ! new_test->responses.list[found] = tmp; } --- 1044,1062 ---- } dict_foreach(object, sockcheck_create_response, new_test); ! /* If none of the responses have template "other", create a ! * default response that goes to accept. */ for (n=0; n<new_test->responses.used; n++) { ! if (!strcmp(new_test->responses.list[n]->template, "other")) break; } ! if (n == new_test->responses.used) { rd = alloc_record_data_qstring("accept"); sockcheck_create_response("other", rd, new_test); free_record_data(rd); ! } else if (n != (new_test->responses.used - 1)) { struct sockcheck_response *tmp; /* switch the response for "other" to the end */ tmp = new_test->responses.list[new_test->responses.used - 1]; ! new_test->responses.list[new_test->responses.used - 1] = new_test->responses.list[n]; ! new_test->responses.list[n] = tmp; } *************** *** 1180,1183 **** --- 1202,1206 ---- dict_delete(checked_ip_dict); free(pending_ip_list); /* not free_string_list because it doesn't own them */ + free(deq_buff); if (tests) { for (n=0; n<tests->used; n++) { *************** *** 1230,1235 **** sockcheck_read_tests(); if (disable_sockcheck) return; ! client_list = malloc(sockcheck_conf.max_sockets * sizeof(client_list[0])); ! memset(client_list, 0, sockcheck_conf.max_sockets * sizeof(client_list[0])); if (pthread_create(&sockcheck_thread, NULL, sockcheck_worker, NULL)) { log(PC_LOG, LOG_ERROR, "pthread_create(..., sockcheck_worker, ...) returned errno %d (%s)\n", errno, strerror(errno)); --- 1253,1258 ---- sockcheck_read_tests(); if (disable_sockcheck) return; ! client_list = calloc(sockcheck_conf.max_sockets, sizeof(client_list[0])); ! last_clean = now; if (pthread_create(&sockcheck_thread, NULL, sockcheck_worker, NULL)) { log(PC_LOG, LOG_ERROR, "pthread_create(..., sockcheck_worker, ...) returned errno %d (%s)\n", errno, strerror(errno)); *************** *** 1278,1281 **** #endif - - --- 1301,1302 ---- |