added threads to support multiple simultaneous stroke requests

This commit is contained in:
Martin Willi
2007-02-02 07:30:19 +00:00
parent d3032a9a82
commit 1908670f99
+145 -127
View File
@@ -150,7 +150,7 @@ static x509_t* load_end_certificate(const char *filename, identification_t **idp
/** /**
* Add a connection to the configuration list * Add a connection to the configuration list
*/ */
static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
{ {
connection_t *connection; connection_t *connection;
policy_t *policy; policy_t *policy;
@@ -460,7 +460,7 @@ destroy_hosts:
/** /**
* Delete a connection from the list * Delete a connection from the list
*/ */
static void stroke_del_conn(private_stroke_t *this, stroke_msg_t *msg) static void stroke_del_conn(stroke_msg_t *msg, FILE *out)
{ {
status_t status; status_t status;
@@ -472,18 +472,18 @@ static void stroke_del_conn(private_stroke_t *this, stroke_msg_t *msg)
charon->policies->delete_policy(charon->policies, msg->del_conn.name); charon->policies->delete_policy(charon->policies, msg->del_conn.name);
if (status == SUCCESS) if (status == SUCCESS)
{ {
fprintf(this->out, "deleted connection '%s'\n", msg->del_conn.name); fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
} }
else else
{ {
fprintf(this->out, "no connection named '%s'\n", msg->del_conn.name); fprintf(out, "no connection named '%s'\n", msg->del_conn.name);
} }
} }
/** /**
* initiate a connection by name * initiate a connection by name
*/ */
static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg) static void stroke_initiate(stroke_msg_t *msg, FILE *out)
{ {
initiate_job_t *job; initiate_job_t *job;
connection_t *connection; connection_t *connection;
@@ -500,7 +500,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
{ {
if (msg->output_verbosity >= 0) if (msg->output_verbosity >= 0)
{ {
fprintf(this->out, "no connection named '%s'\n", msg->initiate.name); fprintf(out, "no connection named '%s'\n", msg->initiate.name);
} }
return; return;
} }
@@ -516,7 +516,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
{ {
if (msg->output_verbosity >= 0) if (msg->output_verbosity >= 0)
{ {
fprintf(this->out, "no policy named '%s'\n", msg->initiate.name); fprintf(out, "no policy named '%s'\n", msg->initiate.name);
} }
connection->destroy(connection); connection->destroy(connection);
return; return;
@@ -547,9 +547,9 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
if ((init_ike_sa == NULL || ike_sa == init_ike_sa) && if ((init_ike_sa == NULL || ike_sa == init_ike_sa) &&
level <= msg->output_verbosity) level <= msg->output_verbosity)
{ {
if (vfprintf(this->out, format, args) < 0 || if (vfprintf(out, format, args) < 0 ||
fprintf(this->out, "\n") < 0 || fprintf(out, "\n") < 0 ||
fflush(this->out)) fflush(out))
{ {
charon->bus->set_listen_state(charon->bus, FALSE); charon->bus->set_listen_state(charon->bus, FALSE);
break; break;
@@ -583,7 +583,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
/** /**
* route/unroute a policy (install SPD entries) * route/unroute a policy (install SPD entries)
*/ */
static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route) static void stroke_route(stroke_msg_t *msg, FILE *out, bool route)
{ {
route_job_t *job; route_job_t *job;
connection_t *connection; connection_t *connection;
@@ -599,7 +599,7 @@ static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
msg->route.name); msg->route.name);
if (connection == NULL) if (connection == NULL)
{ {
fprintf(this->out, "no connection named '%s'\n", msg->route.name); fprintf(out, "no connection named '%s'\n", msg->route.name);
return; return;
} }
if (!connection->is_ikev2(connection)) if (!connection->is_ikev2(connection))
@@ -612,11 +612,11 @@ static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
msg->route.name); msg->route.name);
if (policy == NULL) if (policy == NULL)
{ {
fprintf(this->out, "no policy named '%s'\n", msg->route.name); fprintf(out, "no policy named '%s'\n", msg->route.name);
connection->destroy(connection); connection->destroy(connection);
return; return;
} }
fprintf(this->out, "%s policy '%s'\n", fprintf(out, "%s policy '%s'\n",
route ? "routing" : "unrouting", msg->route.name); route ? "routing" : "unrouting", msg->route.name);
job = route_job_create(connection, policy, route); job = route_job_create(connection, policy, route);
charon->job_queue->add(charon->job_queue, (job_t*)job); charon->job_queue->add(charon->job_queue, (job_t*)job);
@@ -625,7 +625,7 @@ static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
/** /**
* terminate a connection by name * terminate a connection by name
*/ */
static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg) static void stroke_terminate(stroke_msg_t *msg, FILE *out)
{ {
pop_string(msg, &(msg->terminate.name)); pop_string(msg, &(msg->terminate.name));
DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name); DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
@@ -636,7 +636,7 @@ static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
/** /**
* show status of daemon * show status of daemon
*/ */
static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg) static void stroke_statusall(stroke_msg_t *msg, FILE *out)
{ {
iterator_t *iterator; iterator_t *iterator;
linked_list_t *list; linked_list_t *list;
@@ -646,22 +646,22 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
ike_sa_t *ike_sa; ike_sa_t *ike_sa;
char *name = NULL; char *name = NULL;
leak_detective_status(this->out); leak_detective_status(out);
fprintf(this->out, "Performance:\n"); fprintf(out, "Performance:\n");
fprintf(this->out, " worker threads: %d idle of %d,", fprintf(out, " worker threads: %d idle of %d,",
charon->thread_pool->get_idle_threads(charon->thread_pool), charon->thread_pool->get_idle_threads(charon->thread_pool),
charon->thread_pool->get_pool_size(charon->thread_pool)); charon->thread_pool->get_pool_size(charon->thread_pool));
fprintf(this->out, " job queue load: %d,", fprintf(out, " job queue load: %d,",
charon->job_queue->get_count(charon->job_queue)); charon->job_queue->get_count(charon->job_queue));
fprintf(this->out, " scheduled events: %d\n", fprintf(out, " scheduled events: %d\n",
charon->event_queue->get_count(charon->event_queue)); charon->event_queue->get_count(charon->event_queue));
list = charon->socket->create_local_address_list(charon->socket); list = charon->socket->create_local_address_list(charon->socket);
fprintf(this->out, "Listening on %d IP addresses:\n", list->get_count(list)); fprintf(out, "Listening on %d IP addresses:\n", list->get_count(list));
while (list->remove_first(list, (void**)&host) == SUCCESS) while (list->remove_first(list, (void**)&host) == SUCCESS)
{ {
fprintf(this->out, " %H\n", host); fprintf(out, " %H\n", host);
host->destroy(host); host->destroy(host);
} }
list->destroy(list); list->destroy(list);
@@ -675,14 +675,14 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->connections->create_iterator(charon->connections); iterator = charon->connections->create_iterator(charon->connections);
if (iterator->get_count(iterator) > 0) if (iterator->get_count(iterator) > 0)
{ {
fprintf(this->out, "Connections:\n"); fprintf(out, "Connections:\n");
} }
while (iterator->iterate(iterator, (void**)&connection)) while (iterator->iterate(iterator, (void**)&connection))
{ {
if (connection->is_ikev2(connection) if (connection->is_ikev2(connection)
&& (name == NULL || streq(name, connection->get_name(connection)))) && (name == NULL || streq(name, connection->get_name(connection))))
{ {
fprintf(this->out, "%12s: %H...%H\n", fprintf(out, "%12s: %H...%H\n",
connection->get_name(connection), connection->get_name(connection),
connection->get_my_host(connection), connection->get_my_host(connection),
connection->get_other_host(connection)); connection->get_other_host(connection));
@@ -693,13 +693,13 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->policies->create_iterator(charon->policies); iterator = charon->policies->create_iterator(charon->policies);
if (iterator->get_count(iterator) > 0) if (iterator->get_count(iterator) > 0)
{ {
fprintf(this->out, "Policies:\n"); fprintf(out, "Policies:\n");
} }
while (iterator->iterate(iterator, (void**)&policy)) while (iterator->iterate(iterator, (void**)&policy))
{ {
if (name == NULL || streq(name, policy->get_name(policy))) if (name == NULL || streq(name, policy->get_name(policy)))
{ {
fprintf(this->out, "%12s: '%D'...'%D'\n", fprintf(out, "%12s: '%D'...'%D'\n",
policy->get_name(policy), policy->get_name(policy),
policy->get_my_id(policy), policy->get_my_id(policy),
policy->get_other_id(policy)); policy->get_other_id(policy));
@@ -710,7 +710,7 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager); iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
if (iterator->get_count(iterator) > 0) if (iterator->get_count(iterator) > 0)
{ {
fprintf(this->out, "Security Associations:\n"); fprintf(out, "Security Associations:\n");
} }
while (iterator->iterate(iterator, (void**)&ike_sa)) while (iterator->iterate(iterator, (void**)&ike_sa))
{ {
@@ -721,7 +721,7 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
/* print IKE_SA */ /* print IKE_SA */
if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0) if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
{ {
fprintf(this->out, "%#K\n", ike_sa); fprintf(out, "%#K\n", ike_sa);
ike_sa_printed = TRUE; ike_sa_printed = TRUE;
} }
@@ -733,14 +733,14 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
/* print IKE_SA if its name differs from the CHILD_SA's name */ /* print IKE_SA if its name differs from the CHILD_SA's name */
if (!ike_sa_printed && child_sa_match) if (!ike_sa_printed && child_sa_match)
{ {
fprintf(this->out, "%#K\n", ike_sa); fprintf(out, "%#K\n", ike_sa);
ike_sa_printed = TRUE; ike_sa_printed = TRUE;
} }
/* print CHILD_SA */ /* print CHILD_SA */
if (child_sa_match) if (child_sa_match)
{ {
fprintf(this->out, "%#P\n", child_sa); fprintf(out, "%#P\n", child_sa);
} }
} }
children->destroy(children); children->destroy(children);
@@ -751,7 +751,7 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
/** /**
* show status of daemon * show status of daemon
*/ */
static void stroke_status(private_stroke_t *this, stroke_msg_t *msg) static void stroke_status(stroke_msg_t *msg, FILE *out)
{ {
iterator_t *iterator; iterator_t *iterator;
ike_sa_t *ike_sa; ike_sa_t *ike_sa;
@@ -773,7 +773,7 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
/* print IKE_SA */ /* print IKE_SA */
if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0) if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
{ {
fprintf(this->out, "%K\n", ike_sa); fprintf(out, "%K\n", ike_sa);
ike_sa_printed = TRUE; ike_sa_printed = TRUE;
} }
@@ -785,14 +785,14 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
/* print IKE_SA if its name differs from the CHILD_SA's name */ /* print IKE_SA if its name differs from the CHILD_SA's name */
if (!ike_sa_printed && child_sa_match) if (!ike_sa_printed && child_sa_match)
{ {
fprintf(this->out, "%K\n", ike_sa); fprintf(out, "%K\n", ike_sa);
ike_sa_printed = TRUE; ike_sa_printed = TRUE;
} }
/* print CHILD_SA */ /* print CHILD_SA */
if (child_sa_match) if (child_sa_match)
{ {
fprintf(this->out, "%P\n", child_sa); fprintf(out, "%P\n", child_sa);
} }
} }
children->destroy(children); children->destroy(children);
@@ -803,7 +803,7 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
/** /**
* list various information * list various information
*/ */
static void stroke_list(private_stroke_t *this, stroke_msg_t *msg) static void stroke_list(stroke_msg_t *msg, FILE *out)
{ {
iterator_t *iterator; iterator_t *iterator;
@@ -814,19 +814,19 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_cert_iterator(charon->credentials); iterator = charon->credentials->create_cert_iterator(charon->credentials);
if (iterator->get_count(iterator)) if (iterator->get_count(iterator))
{ {
fprintf(this->out, "\n"); fprintf(out, "\n");
fprintf(this->out, "List of X.509 End Entity Certificates:\n"); fprintf(out, "List of X.509 End Entity Certificates:\n");
fprintf(this->out, "\n"); fprintf(out, "\n");
} }
while (iterator->iterate(iterator, (void**)&cert)) while (iterator->iterate(iterator, (void**)&cert))
{ {
fprintf(this->out, "%#Q", cert, msg->list.utc); fprintf(out, "%#Q", cert, msg->list.utc);
if (charon->credentials->has_rsa_private_key( if (charon->credentials->has_rsa_private_key(
charon->credentials, cert->get_public_key(cert))) charon->credentials, cert->get_public_key(cert)))
{ {
fprintf(this->out, ", has private key"); fprintf(out, ", has private key");
} }
fprintf(this->out, "\n"); fprintf(out, "\n");
} }
iterator->destroy(iterator); iterator->destroy(iterator);
@@ -838,13 +838,13 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_cacert_iterator(charon->credentials); iterator = charon->credentials->create_cacert_iterator(charon->credentials);
if (iterator->get_count(iterator)) if (iterator->get_count(iterator))
{ {
fprintf(this->out, "\n"); fprintf(out, "\n");
fprintf(this->out, "List of X.509 CA Certificates:\n"); fprintf(out, "List of X.509 CA Certificates:\n");
fprintf(this->out, "\n"); fprintf(out, "\n");
} }
while (iterator->iterate(iterator, (void**)&cert)) while (iterator->iterate(iterator, (void**)&cert))
{ {
fprintf(this->out, "%#Q\n", cert, msg->list.utc); fprintf(out, "%#Q\n", cert, msg->list.utc);
} }
iterator->destroy(iterator); iterator->destroy(iterator);
} }
@@ -855,13 +855,13 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_crl_iterator(charon->credentials); iterator = charon->credentials->create_crl_iterator(charon->credentials);
if (iterator->get_count(iterator)) if (iterator->get_count(iterator))
{ {
fprintf(this->out, "\n"); fprintf(out, "\n");
fprintf(this->out, "List of X.509 CRLs:\n"); fprintf(out, "List of X.509 CRLs:\n");
fprintf(this->out, "\n"); fprintf(out, "\n");
} }
while (iterator->iterate(iterator, (void**)&crl)) while (iterator->iterate(iterator, (void**)&crl))
{ {
fprintf(this->out, "%#U\n", crl, msg->list.utc); fprintf(out, "%#U\n", crl, msg->list.utc);
} }
iterator->destroy(iterator); iterator->destroy(iterator);
} }
@@ -870,7 +870,7 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
/** /**
* reread various information * reread various information
*/ */
static void stroke_reread(private_stroke_t *this, stroke_msg_t *msg) static void stroke_reread(stroke_msg_t *msg, FILE *out)
{ {
if (msg->reread.flags & REREAD_CACERTS) if (msg->reread.flags & REREAD_CACERTS)
{ {
@@ -900,7 +900,7 @@ signal_t get_signal_from_logtype(char *type)
/** /**
* set the verbosity debug output * set the verbosity debug output
*/ */
static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg) static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
{ {
signal_t signal; signal_t signal;
@@ -911,7 +911,7 @@ static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
signal = get_signal_from_logtype(msg->loglevel.type); signal = get_signal_from_logtype(msg->loglevel.type);
if (signal < 0) if (signal < 0)
{ {
fprintf(this->out, "invalid type (%s)!\n", msg->loglevel.type); fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
return; return;
} }
@@ -919,18 +919,100 @@ static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level); charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
} }
/**
* process a stroke request from the socket pointed by "fd"
*/
static void stroke_process(int *fd)
{
stroke_msg_t *msg;
u_int16_t msg_length;
ssize_t bytes_read;
FILE *out;
int strokefd = *fd;
/* peek the length */
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
if (bytes_read != sizeof(msg_length))
{
DBG1(DBG_CFG, "reading length of stroke message failed");
close(strokefd);
return;
}
/* read message */
msg = malloc(msg_length);
bytes_read = recv(strokefd, msg, msg_length, 0);
if (bytes_read != msg_length)
{
DBG1(DBG_CFG, "reading stroke message failed: %m");
close(strokefd);
return;
}
out = fdopen(dup(strokefd), "w");
if (out == NULL)
{
DBG1(DBG_CFG, "opening stroke output channel failed: %m");
close(strokefd);
free(msg);
return;
}
DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
switch (msg->type)
{
case STR_INITIATE:
stroke_initiate(msg, out);
break;
case STR_ROUTE:
stroke_route(msg, out, TRUE);
break;
case STR_UNROUTE:
stroke_route(msg, out, FALSE);
break;
case STR_TERMINATE:
stroke_terminate(msg, out);
break;
case STR_STATUS:
stroke_status(msg, out);
break;
case STR_STATUS_ALL:
stroke_statusall(msg, out);
break;
case STR_ADD_CONN:
stroke_add_conn(msg, out);
break;
case STR_DEL_CONN:
stroke_del_conn(msg, out);
break;
case STR_LOGLEVEL:
stroke_loglevel(msg, out);
break;
case STR_LIST:
stroke_list(msg, out);
break;
case STR_REREAD:
stroke_reread(msg, out);
break;
default:
DBG1(DBG_CFG, "received unknown stroke");
}
fclose(out);
close(strokefd);
free(msg);
}
/** /**
* Implementation of private_stroke_t.stroke_receive. * Implementation of private_stroke_t.stroke_receive.
*/ */
static void stroke_receive(private_stroke_t *this) static void stroke_receive(private_stroke_t *this)
{ {
stroke_msg_t *msg;
u_int16_t msg_length;
struct sockaddr_un strokeaddr; struct sockaddr_un strokeaddr;
int strokeaddrlen = sizeof(strokeaddr); int strokeaddrlen = sizeof(strokeaddr);
ssize_t bytes_read;
int strokefd; int strokefd;
int oldstate; int oldstate;
pthread_t thread;
/* ignore sigpipe. writing over the pipe back to the console /* ignore sigpipe. writing over the pipe back to the console
* only fails if SIGPIPE is ignored. */ * only fails if SIGPIPE is ignored. */
@@ -939,7 +1021,7 @@ static void stroke_receive(private_stroke_t *this)
/* disable cancellation by default */ /* disable cancellation by default */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while (1) while (TRUE)
{ {
/* wait for connections, but allow thread to terminate */ /* wait for connections, but allow thread to terminate */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
@@ -952,77 +1034,13 @@ static void stroke_receive(private_stroke_t *this)
continue; continue;
} }
/* peek the length */ /* handle request asynchronously */
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK); if (pthread_create(&thread, NULL, (void*(*)(void*))stroke_process, (void*)&strokefd) != 0)
if (bytes_read != sizeof(msg_length)) {
{ DBG1(DBG_CFG, "failed to spawn stroke thread: %m");
DBG1(DBG_CFG, "reading length of stroke message failed");
close(strokefd);
continue;
} }
/* detach so the thread terminates cleanly */
/* read message */ pthread_detach(thread);
msg = malloc(msg_length);
bytes_read = recv(strokefd, msg, msg_length, 0);
if (bytes_read != msg_length)
{
DBG1(DBG_CFG, "reading stroke message failed: %m");
close(strokefd);
continue;
}
this->out = fdopen(dup(strokefd), "w");
if (this->out == NULL)
{
DBG1(DBG_CFG, "opening stroke output channel failed: %m");
close(strokefd);
free(msg);
continue;
}
DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
switch (msg->type)
{
case STR_INITIATE:
stroke_initiate(this, msg);
break;
case STR_ROUTE:
stroke_route(this, msg, TRUE);
break;
case STR_UNROUTE:
stroke_route(this, msg, FALSE);
break;
case STR_TERMINATE:
stroke_terminate(this, msg);
break;
case STR_STATUS:
stroke_status(this, msg);
break;
case STR_STATUS_ALL:
stroke_statusall(this, msg);
break;
case STR_ADD_CONN:
stroke_add_conn(this, msg);
break;
case STR_DEL_CONN:
stroke_del_conn(this, msg);
break;
case STR_LOGLEVEL:
stroke_loglevel(this, msg);
break;
case STR_LIST:
stroke_list(this, msg);
break;
case STR_REREAD:
stroke_reread(this, msg);
break;
default:
DBG1(DBG_CFG, "received unknown stroke");
}
fclose(this->out);
close(strokefd);
free(msg);
} }
} }