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
1 changed files with 145 additions and 127 deletions

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
*/
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;
policy_t *policy;
@ -460,7 +460,7 @@ destroy_hosts:
/**
* 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;
@ -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);
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
{
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
*/
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;
connection_t *connection;
@ -500,7 +500,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
{
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;
}
@ -516,7 +516,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
{
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);
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) &&
level <= msg->output_verbosity)
{
if (vfprintf(this->out, format, args) < 0 ||
fprintf(this->out, "\n") < 0 ||
fflush(this->out))
if (vfprintf(out, format, args) < 0 ||
fprintf(out, "\n") < 0 ||
fflush(out))
{
charon->bus->set_listen_state(charon->bus, FALSE);
break;
@ -583,7 +583,7 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
/**
* 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;
connection_t *connection;
@ -599,7 +599,7 @@ static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
msg->route.name);
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;
}
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);
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);
return;
}
fprintf(this->out, "%s policy '%s'\n",
fprintf(out, "%s policy '%s'\n",
route ? "routing" : "unrouting", msg->route.name);
job = route_job_create(connection, policy, route);
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
*/
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));
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
*/
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;
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;
char *name = NULL;
leak_detective_status(this->out);
leak_detective_status(out);
fprintf(this->out, "Performance:\n");
fprintf(this->out, " worker threads: %d idle of %d,",
fprintf(out, "Performance:\n");
fprintf(out, " worker threads: %d idle of %d,",
charon->thread_pool->get_idle_threads(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));
fprintf(this->out, " scheduled events: %d\n",
fprintf(out, " scheduled events: %d\n",
charon->event_queue->get_count(charon->event_queue));
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)
{
fprintf(this->out, " %H\n", host);
fprintf(out, " %H\n", host);
host->destroy(host);
}
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);
if (iterator->get_count(iterator) > 0)
{
fprintf(this->out, "Connections:\n");
fprintf(out, "Connections:\n");
}
while (iterator->iterate(iterator, (void**)&connection))
{
if (connection->is_ikev2(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_my_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);
if (iterator->get_count(iterator) > 0)
{
fprintf(this->out, "Policies:\n");
fprintf(out, "Policies:\n");
}
while (iterator->iterate(iterator, (void**)&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_my_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);
if (iterator->get_count(iterator) > 0)
{
fprintf(this->out, "Security Associations:\n");
fprintf(out, "Security Associations:\n");
}
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 */
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;
}
@ -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 */
if (!ike_sa_printed && child_sa_match)
{
fprintf(this->out, "%#K\n", ike_sa);
fprintf(out, "%#K\n", ike_sa);
ike_sa_printed = TRUE;
}
/* print CHILD_SA */
if (child_sa_match)
{
fprintf(this->out, "%#P\n", child_sa);
fprintf(out, "%#P\n", child_sa);
}
}
children->destroy(children);
@ -751,7 +751,7 @@ static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
/**
* 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;
ike_sa_t *ike_sa;
@ -773,7 +773,7 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
/* print IKE_SA */
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;
}
@ -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 */
if (!ike_sa_printed && child_sa_match)
{
fprintf(this->out, "%K\n", ike_sa);
fprintf(out, "%K\n", ike_sa);
ike_sa_printed = TRUE;
}
/* print CHILD_SA */
if (child_sa_match)
{
fprintf(this->out, "%P\n", child_sa);
fprintf(out, "%P\n", child_sa);
}
}
children->destroy(children);
@ -803,7 +803,7 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
/**
* 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;
@ -814,19 +814,19 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_cert_iterator(charon->credentials);
if (iterator->get_count(iterator))
{
fprintf(this->out, "\n");
fprintf(this->out, "List of X.509 End Entity Certificates:\n");
fprintf(this->out, "\n");
fprintf(out, "\n");
fprintf(out, "List of X.509 End Entity Certificates:\n");
fprintf(out, "\n");
}
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(
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);
@ -838,13 +838,13 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_cacert_iterator(charon->credentials);
if (iterator->get_count(iterator))
{
fprintf(this->out, "\n");
fprintf(this->out, "List of X.509 CA Certificates:\n");
fprintf(this->out, "\n");
fprintf(out, "\n");
fprintf(out, "List of X.509 CA Certificates:\n");
fprintf(out, "\n");
}
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);
}
@ -855,13 +855,13 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
iterator = charon->credentials->create_crl_iterator(charon->credentials);
if (iterator->get_count(iterator))
{
fprintf(this->out, "\n");
fprintf(this->out, "List of X.509 CRLs:\n");
fprintf(this->out, "\n");
fprintf(out, "\n");
fprintf(out, "List of X.509 CRLs:\n");
fprintf(out, "\n");
}
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);
}
@ -870,7 +870,7 @@ static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
/**
* 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)
{
@ -900,7 +900,7 @@ signal_t get_signal_from_logtype(char *type)
/**
* 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;
@ -911,7 +911,7 @@ static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
signal = get_signal_from_logtype(msg->loglevel.type);
if (signal < 0)
{
fprintf(this->out, "invalid type (%s)!\n", msg->loglevel.type);
fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
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);
}
/**
* 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.
*/
static void stroke_receive(private_stroke_t *this)
{
stroke_msg_t *msg;
u_int16_t msg_length;
struct sockaddr_un strokeaddr;
int strokeaddrlen = sizeof(strokeaddr);
ssize_t bytes_read;
int strokefd;
int oldstate;
pthread_t thread;
/* ignore sigpipe. writing over the pipe back to the console
* only fails if SIGPIPE is ignored. */
@ -939,7 +1021,7 @@ static void stroke_receive(private_stroke_t *this)
/* disable cancellation by default */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while (1)
while (TRUE)
{
/* wait for connections, but allow thread to terminate */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
@ -952,77 +1034,13 @@ static void stroke_receive(private_stroke_t *this)
continue;
}
/* 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);
continue;
/* handle request asynchronously */
if (pthread_create(&thread, NULL, (void*(*)(void*))stroke_process, (void*)&strokefd) != 0)
{
DBG1(DBG_CFG, "failed to spawn stroke thread: %m");
}
/* 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);
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);
/* detach so the thread terminates cleanly */
pthread_detach(thread);
}
}