/**
* 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;
/**
* 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;
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;
{
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;
}
{
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;
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;
/**
* 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;
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))
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);
/**
* 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);
/**
* 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;
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);
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));
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));
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))
{
/* 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;
}
/* 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);
/**
* 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;
/* 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;
}
/* 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);
/**
* 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 = 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);
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);
}
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);
}
/**
* 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)
{
/**
* 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 = 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;
}
}
/**
- * Implementation of private_stroke_t.stroke_receive.
+ * process a stroke request from the socket pointed by "fd"
*/
-static void stroke_receive(private_stroke_t *this)
+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)
+{
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. */
/* 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);
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;
- }
-
- /* 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");
+ /* handle request asynchronously */
+ if (pthread_create(&thread, NULL, (void*(*)(void*))stroke_process, (void*)&strokefd) != 0)
+ {
+ DBG1(DBG_CFG, "failed to spawn stroke thread: %m");
}
- fclose(this->out);
- close(strokefd);
- free(msg);
+ /* detach so the thread terminates cleanly */
+ pthread_detach(thread);
}
}