2 control.c -- Control socket handling.
3 Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 static int control_socket = -1;
31 static struct event control_event;
32 static splay_tree_t *control_socket_tree;
33 extern char *controlsocketname;
35 static void handle_control_data(struct bufferevent *event, void *data) {
36 char *line = evbuffer_readline(event->input);
40 if(!strcasecmp(line, "stop")) {
41 logger(LOG_NOTICE, _("Got stop command"));
46 logger(LOG_DEBUG, _("Malformed control command received"));
47 close(event->ev_read.ev_fd);
48 splay_delete(control_socket_tree, event);
51 static void handle_control_error(struct bufferevent *event, short what, void *data) {
52 if(what & EVBUFFER_EOF)
53 logger(LOG_DEBUG, _("Control socket connection closed by peer"));
55 logger(LOG_DEBUG, _("Error while reading from control socket: %s"), strerror(errno));
57 close(event->ev_read.ev_fd);
58 splay_delete(control_socket_tree, event);
61 static void handle_new_control_socket(int fd, short events, void *data) {
63 struct bufferevent *ev;
65 newfd = accept(fd, NULL, NULL);
68 logger(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
69 event_del(&control_event);
73 ev = bufferevent_new(newfd, handle_control_data, NULL, handle_control_error, NULL);
75 logger(LOG_ERR, _("Could not create bufferevent for new control connection: %s"), strerror(errno));
80 bufferevent_enable(ev, EV_READ);
81 splay_insert(control_socket_tree, ev);
83 logger(LOG_DEBUG, _("Control socket connection accepted"));
86 static int control_compare(const struct event *a, const struct event *b) {
87 return a < b ? -1 : a > b ? 1 : 0;
92 struct sockaddr_un addr;
94 if(strlen(controlsocketname) >= sizeof addr.sun_path) {
95 logger(LOG_ERR, _("Control socket filename too long!"));
99 memset(&addr, 0, sizeof addr);
100 addr.sun_family = AF_UNIX;
101 strncpy(addr.sun_path, controlsocketname, sizeof addr.sun_path - 1);
103 control_socket = socket(PF_UNIX, SOCK_STREAM, 0);
105 if(control_socket < 0) {
106 logger(LOG_ERR, _("Creating UNIX socket failed: %s"), strerror(errno));
110 //unlink(controlsocketname);
111 result = bind(control_socket, (struct sockaddr *)&addr, sizeof addr);
113 if(result < 0 && errno == EADDRINUSE) {
114 result = connect(control_socket, (struct sockaddr *)&addr, sizeof addr);
116 logger(LOG_WARNING, _("Removing old control socket."));
117 unlink(controlsocketname);
118 result = bind(control_socket, (struct sockaddr *)&addr, sizeof addr);
120 close(control_socket);
122 logger(LOG_ERR, _("Another tincd is already running for net `%s'."), netname);
124 logger(LOG_ERR, _("Another tincd is already running."));
130 logger(LOG_ERR, _("Can't bind to %s: %s\n"), controlsocketname, strerror(errno));
131 close(control_socket);
135 if(listen(control_socket, 3) < 0) {
136 logger(LOG_ERR, _("Can't listen on %s: %s\n"), controlsocketname, strerror(errno));
137 close(control_socket);
141 control_socket_tree = splay_alloc_tree((splay_compare_t)control_compare, (splay_action_t)bufferevent_free);
143 event_set(&control_event, control_socket, EV_READ | EV_PERSIST, handle_new_control_socket, NULL);
144 event_add(&control_event, NULL);
149 void exit_control() {
150 event_del(&control_event);
151 close(control_socket);
152 unlink(controlsocketname);