- if(req.type == REQ_RELOAD) {
- logger(LOG_NOTICE, "Got '%s' command", "reload");
- res.res_errno = reload_configuration();
- goto respond;
- }
-
- logger(LOG_DEBUG, "Malformed control command received");
- res.res_errno = EINVAL;
-
-respond:
- res.length = (sizeof res)
- + ((res_data == NULL) ? 0 : EVBUFFER_LENGTH(res_data));
- evbuffer_drain(event->input, req.length);
- if(bufferevent_write(event, &res, sizeof res) == -1)
- goto failure;
- if(res_data != NULL) {
- if(bufferevent_write_buffer(event, res_data) == -1)
- goto failure;
- evbuffer_free(res_data);
- }
- return;
-
-failure:
- logger(LOG_INFO, "Closing control socket on error");
- evbuffer_free(res_data);
- close(event->ev_read.ev_fd);
- splay_delete(control_socket_tree, event);
-}
-
-static void handle_control_error(struct bufferevent *event, short what, void *data) {
- if(what & EVBUFFER_EOF)
- logger(LOG_DEBUG, "Control socket connection closed by peer");
- else
- logger(LOG_DEBUG, "Error while reading from control socket: %s", strerror(errno));
-
- close(event->ev_read.ev_fd);
- splay_delete(control_socket_tree, event);
-}
-
-static void handle_new_control_socket(int fd, short events, void *data) {
- int newfd;
- struct bufferevent *ev;
- tinc_ctl_greeting_t greeting;
-
- newfd = accept(fd, NULL, NULL);
-
- if(newfd < 0) {
- logger(LOG_ERR, "Accepting a new connection failed: %s", strerror(errno));
- event_del(&control_event);
- return;
- }
-
- ev = bufferevent_new(newfd, handle_control_data, NULL, handle_control_error, NULL);
- if(!ev) {
- logger(LOG_ERR, "Could not create bufferevent for new control connection: %s", strerror(errno));
- close(newfd);
- return;
- }
+ case REQ_RETRY:
+ retry();
+ return control_ok(c, REQ_RETRY);
+
+ case REQ_RELOAD:
+ logger(LOG_NOTICE, "Got '%s' command", "reload");
+ int result = reload_configuration();
+ return control_return(c, REQ_RELOAD, result);
+
+ case REQ_DISCONNECT: {
+ char name[MAX_STRING_SIZE];
+ connection_t *other;
+ splay_node_t *node, *next;
+ bool found = false;
+
+ if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1)
+ return control_return(c, REQ_DISCONNECT, -1);
+
+ for(node = connection_tree->head; node; node = next) {
+ next = node->next;
+ other = node->data;
+ if(strcmp(other->name, name))
+ continue;
+ terminate_connection(other, other->status.active);
+ found = true;
+ }
+
+ return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
+ }