dynamic-string: Optimize ds_put_char().
[openvswitch] / lib / unixctl.c
1 /*
2  * Copyright (c) 2008, 2009, 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include "unixctl.h"
19 #include <assert.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <poll.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include "coverage.h"
29 #include "dirs.h"
30 #include "dynamic-string.h"
31 #include "fatal-signal.h"
32 #include "list.h"
33 #include "ofpbuf.h"
34 #include "poll-loop.h"
35 #include "shash.h"
36 #include "socket-util.h"
37 #include "util.h"
38
39 #ifndef SCM_CREDENTIALS
40 #include <time.h>
41 #endif
42
43 #define THIS_MODULE VLM_unixctl
44 #include "vlog.h"
45 \f
46 struct unixctl_command {
47     unixctl_cb_func *cb;
48     void *aux;
49 };
50
51 struct unixctl_conn {
52     struct list node;
53     int fd;
54
55     enum { S_RECV, S_PROCESS, S_SEND } state;
56     struct ofpbuf in;
57     struct ds out;
58     size_t out_pos;
59 };
60
61 /* Server for control connection. */
62 struct unixctl_server {
63     char *path;
64     int fd;
65     struct list conns;
66 };
67
68 /* Client for control connection. */
69 struct unixctl_client {
70     char *connect_path;
71     char *bind_path;
72     FILE *stream;
73 };
74
75 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
76
77 static struct shash commands = SHASH_INITIALIZER(&commands);
78
79 static void
80 unixctl_help(struct unixctl_conn *conn, const char *args OVS_UNUSED,
81              void *aux OVS_UNUSED)
82 {
83     struct ds ds = DS_EMPTY_INITIALIZER;
84     struct shash_node *node;
85
86     ds_put_cstr(&ds, "The available commands are:\n");
87     SHASH_FOR_EACH (node, &commands) {
88         ds_put_format(&ds, "\t%s\n", node->name);
89     }
90     unixctl_command_reply(conn, 214, ds_cstr(&ds));
91     ds_destroy(&ds);
92 }
93
94 void
95 unixctl_command_register(const char *name, unixctl_cb_func *cb, void *aux)
96 {
97     struct unixctl_command *command;
98
99     assert(!shash_find_data(&commands, name)
100            || shash_find_data(&commands, name) == cb);
101     command = xmalloc(sizeof *command);
102     command->cb = cb;
103     command->aux = aux;
104     shash_add(&commands, name, command);
105 }
106
107 static const char *
108 translate_reply_code(int code)
109 {
110     switch (code) {
111     case 200: return "OK";
112     case 201: return "Created";
113     case 202: return "Accepted";
114     case 204: return "No Content";
115     case 211: return "System Status";
116     case 214: return "Help";
117     case 400: return "Bad Request";
118     case 401: return "Unauthorized";
119     case 403: return "Forbidden";
120     case 404: return "Not Found";
121     case 500: return "Internal Server Error";
122     case 501: return "Invalid Argument";
123     case 503: return "Service Unavailable";
124     default: return "Unknown";
125     }
126 }
127
128 void
129 unixctl_command_reply(struct unixctl_conn *conn,
130                       int code, const char *body)
131 {
132     struct ds *out = &conn->out;
133
134     COVERAGE_INC(unixctl_replied);
135     assert(conn->state == S_PROCESS);
136     conn->state = S_SEND;
137     conn->out_pos = 0;
138
139     ds_clear(out);
140     ds_put_format(out, "%03d %s\n", code, translate_reply_code(code));
141     if (body) {
142         const char *p;
143         for (p = body; *p != '\0'; ) {
144             size_t n = strcspn(p, "\n");
145
146             if (*p == '.') {
147                 ds_put_char(out, '.');
148             }
149             ds_put_buffer(out, p, n);
150             ds_put_char(out, '\n');
151             p += n;
152             if (*p == '\n') {
153                 p++;
154             }
155         }
156     }
157     ds_put_cstr(out, ".\n");
158 }
159
160 /* Creates a unixctl server listening on 'path', which may be:
161  *
162  *      - NULL, in which case <rundir>/<program>.<pid>.ctl is used.
163  *
164  *      - A name that does not start with '/', in which case it is put in
165  *        <rundir>.
166  *
167  *      - An absolute path (starting with '/') that gives the exact name of
168  *        the Unix domain socket to listen on.
169  *
170  * A program that (optionally) daemonizes itself should call this function
171  * *after* daemonization, so that the socket name contains the pid of the
172  * daemon instead of the pid of the program that exited.  (Otherwise,
173  * "ovs-appctl --target=<program>" will fail.)
174  *
175  * Returns 0 if successful, otherwise a positive errno value.  If successful,
176  * sets '*serverp' to the new unixctl_server, otherwise to NULL. */
177 int
178 unixctl_server_create(const char *path, struct unixctl_server **serverp)
179 {
180     struct unixctl_server *server;
181     int error;
182
183     unixctl_command_register("help", unixctl_help, NULL);
184
185     server = xmalloc(sizeof *server);
186     list_init(&server->conns);
187
188     if (path) {
189         server->path = abs_file_name(ovs_rundir, path);
190     } else {
191         server->path = xasprintf("%s/%s.%ld.ctl", ovs_rundir,
192                                  program_name, (long int) getpid());
193     }
194
195     server->fd = make_unix_socket(SOCK_STREAM, true, false, server->path,
196                                   NULL);
197     if (server->fd < 0) {
198         error = -server->fd;
199         ovs_error(error, "could not initialize control socket %s",
200                   server->path);
201         goto error;
202     }
203
204     if (chmod(server->path, S_IRUSR | S_IWUSR) < 0) {
205         error = errno;
206         ovs_error(error, "failed to chmod control socket %s", server->path);
207         goto error;
208     }
209
210     if (listen(server->fd, 10) < 0) {
211         error = errno;
212         ovs_error(error, "Failed to listen on control socket %s",
213                   server->path);
214         goto error;
215     }
216
217     *serverp = server;
218     return 0;
219
220 error:
221     if (server->fd >= 0) {
222         close(server->fd);
223     }
224     free(server->path);
225     free(server);
226     *serverp = NULL;
227     return error;
228 }
229
230 static void
231 new_connection(struct unixctl_server *server, int fd)
232 {
233     struct unixctl_conn *conn;
234
235     set_nonblocking(fd);
236
237     conn = xmalloc(sizeof *conn);
238     list_push_back(&server->conns, &conn->node);
239     conn->fd = fd;
240     conn->state = S_RECV;
241     ofpbuf_init(&conn->in, 128);
242     ds_init(&conn->out);
243     conn->out_pos = 0;
244 }
245
246 static int
247 run_connection_output(struct unixctl_conn *conn)
248 {
249     while (conn->out_pos < conn->out.length) {
250         size_t bytes_written;
251         int error;
252
253         error = write_fully(conn->fd, conn->out.string + conn->out_pos,
254                             conn->out.length - conn->out_pos, &bytes_written);
255         conn->out_pos += bytes_written;
256         if (error) {
257             return error;
258         }
259     }
260     conn->state = S_RECV;
261     return 0;
262 }
263
264 static void
265 process_command(struct unixctl_conn *conn, char *s)
266 {
267     struct unixctl_command *command;
268     size_t name_len;
269     char *name, *args;
270
271     COVERAGE_INC(unixctl_received);
272     conn->state = S_PROCESS;
273
274     name = s;
275     name_len = strcspn(name, " ");
276     args = name + name_len;
277     args += strspn(args, " ");
278     name[name_len] = '\0';
279
280     command = shash_find_data(&commands, name);
281     if (command) {
282         command->cb(conn, args, command->aux);
283     } else {
284         char *msg = xasprintf("\"%s\" is not a valid command", name);
285         unixctl_command_reply(conn, 400, msg);
286         free(msg);
287     }
288 }
289
290 static int
291 run_connection_input(struct unixctl_conn *conn)
292 {
293     for (;;) {
294         size_t bytes_read;
295         char *newline;
296         int error;
297
298         newline = memchr(conn->in.data, '\n', conn->in.size);
299         if (newline) {
300             char *command = conn->in.data;
301             size_t n = newline - command + 1;
302
303             if (n > 0 && newline[-1] == '\r') {
304                 newline--;
305             }
306             *newline = '\0';
307
308             process_command(conn, command);
309
310             ofpbuf_pull(&conn->in, n);
311             if (!conn->in.size) {
312                 ofpbuf_clear(&conn->in);
313             }
314             return 0;
315         }
316
317         ofpbuf_prealloc_tailroom(&conn->in, 128);
318         error = read_fully(conn->fd, ofpbuf_tail(&conn->in),
319                            ofpbuf_tailroom(&conn->in), &bytes_read);
320         conn->in.size += bytes_read;
321         if (conn->in.size > 65536) {
322             VLOG_WARN_RL(&rl, "excess command length, killing connection");
323             return EPROTO;
324         }
325         if (error) {
326             if (error == EAGAIN || error == EWOULDBLOCK) {
327                 if (!bytes_read) {
328                     return EAGAIN;
329                 }
330             } else {
331                 if (error != EOF || conn->in.size != 0) {
332                     VLOG_WARN_RL(&rl, "read failed: %s",
333                                  (error == EOF
334                                   ? "connection dropped mid-command"
335                                   : strerror(error)));
336                 }
337                 return error;
338             }
339         }
340     }
341 }
342
343 static int
344 run_connection(struct unixctl_conn *conn)
345 {
346     int old_state;
347     do {
348         int error;
349
350         old_state = conn->state;
351         switch (conn->state) {
352         case S_RECV:
353             error = run_connection_input(conn);
354             break;
355
356         case S_PROCESS:
357             error = 0;
358             break;
359
360         case S_SEND:
361             error = run_connection_output(conn);
362             break;
363
364         default:
365             NOT_REACHED();
366         }
367         if (error) {
368             return error;
369         }
370     } while (conn->state != old_state);
371     return 0;
372 }
373
374 static void
375 kill_connection(struct unixctl_conn *conn)
376 {
377     list_remove(&conn->node);
378     ofpbuf_uninit(&conn->in);
379     ds_destroy(&conn->out);
380     close(conn->fd);
381     free(conn);
382 }
383
384 void
385 unixctl_server_run(struct unixctl_server *server)
386 {
387     struct unixctl_conn *conn, *next;
388     int i;
389
390     for (i = 0; i < 10; i++) {
391         int fd = accept(server->fd, NULL, NULL);
392         if (fd < 0) {
393             if (errno != EAGAIN && errno != EWOULDBLOCK) {
394                 VLOG_WARN_RL(&rl, "accept failed: %s", strerror(errno));
395             }
396             break;
397         }
398         new_connection(server, fd);
399     }
400
401     LIST_FOR_EACH_SAFE (conn, next,
402                         struct unixctl_conn, node, &server->conns) {
403         int error = run_connection(conn);
404         if (error && error != EAGAIN) {
405             kill_connection(conn);
406         }
407     }
408 }
409
410 void
411 unixctl_server_wait(struct unixctl_server *server)
412 {
413     struct unixctl_conn *conn;
414
415     poll_fd_wait(server->fd, POLLIN);
416     LIST_FOR_EACH (conn, struct unixctl_conn, node, &server->conns) {
417         if (conn->state == S_RECV) {
418             poll_fd_wait(conn->fd, POLLIN);
419         } else if (conn->state == S_SEND) {
420             poll_fd_wait(conn->fd, POLLOUT);
421         }
422     }
423 }
424
425 /* Destroys 'server' and stops listening for connections. */
426 void
427 unixctl_server_destroy(struct unixctl_server *server)
428 {
429     if (server) {
430         struct unixctl_conn *conn, *next;
431
432         LIST_FOR_EACH_SAFE (conn, next,
433                             struct unixctl_conn, node, &server->conns) {
434             kill_connection(conn);
435         }
436
437         close(server->fd);
438         fatal_signal_unlink_file_now(server->path);
439         free(server->path);
440         free(server);
441     }
442 }
443 \f
444 /* Connects to a Vlog server socket.  'path' should be the name of a Vlog
445  * server socket.  If it does not start with '/', it will be prefixed with
446  * ovs_rundir (e.g. /var/run/openvswitch).
447  *
448  * Returns 0 if successful, otherwise a positive errno value.  If successful,
449  * sets '*clientp' to the new unixctl_client, otherwise to NULL. */
450 int
451 unixctl_client_create(const char *path, struct unixctl_client **clientp)
452 {
453     static int counter;
454     struct unixctl_client *client;
455     int error;
456     int fd = -1;
457
458     /* Determine location. */
459     client = xmalloc(sizeof *client);
460     client->connect_path = abs_file_name(ovs_rundir, path);
461     client->bind_path = xasprintf("/tmp/vlog.%ld.%d",
462                                   (long int) getpid(), counter++);
463
464     /* Open socket. */
465     fd = make_unix_socket(SOCK_STREAM, false, false,
466                           client->bind_path, client->connect_path);
467     if (fd < 0) {
468         error = -fd;
469         goto error;
470     }
471
472     /* Bind socket to stream. */
473     client->stream = fdopen(fd, "r+");
474     if (!client->stream) {
475         error = errno;
476         VLOG_WARN("%s: fdopen failed (%s)",
477                   client->connect_path, strerror(error));
478         goto error;
479     }
480     *clientp = client;
481     return 0;
482
483 error:
484     if (fd >= 0) {
485         close(fd);
486     }
487     free(client->connect_path);
488     free(client->bind_path);
489     free(client);
490     *clientp = NULL;
491     return error;
492 }
493
494 /* Destroys 'client'. */
495 void
496 unixctl_client_destroy(struct unixctl_client *client)
497 {
498     if (client) {
499         fatal_signal_unlink_file_now(client->bind_path);
500         free(client->bind_path);
501         free(client->connect_path);
502         fclose(client->stream);
503         free(client);
504     }
505 }
506
507 /* Sends 'request' to the server socket and waits for a reply.  Returns 0 if
508  * successful, otherwise to a positive errno value.  If successful, sets
509  * '*reply' to the reply, which the caller must free, otherwise to NULL. */
510 int
511 unixctl_client_transact(struct unixctl_client *client,
512                         const char *request,
513                         int *reply_code, char **reply_body)
514 {
515     struct ds line = DS_EMPTY_INITIALIZER;
516     struct ds reply = DS_EMPTY_INITIALIZER;
517     int error;
518
519     /* Send 'request' to server.  Add a new-line if 'request' didn't end in
520      * one. */
521     fputs(request, client->stream);
522     if (request[0] == '\0' || request[strlen(request) - 1] != '\n') {
523         putc('\n', client->stream);
524     }
525     if (ferror(client->stream)) {
526         VLOG_WARN("error sending request to %s: %s",
527                   client->connect_path, strerror(errno));
528         return errno;
529     }
530
531     /* Wait for response. */
532     *reply_code = -1;
533     for (;;) {
534         const char *s;
535
536         error = ds_get_line(&line, client->stream);
537         if (error) {
538             VLOG_WARN("error reading reply from %s: %s",
539                       client->connect_path,
540                       (error == EOF ? "unexpected end of file"
541                        : strerror(error)));
542             goto error;
543         }
544
545         s = ds_cstr(&line);
546         if (*reply_code == -1) {
547             if (!isdigit((unsigned char)s[0])
548                     || !isdigit((unsigned char)s[1])
549                     || !isdigit((unsigned char)s[2])) {
550                 VLOG_WARN("reply from %s does not start with 3-digit code",
551                           client->connect_path);
552                 error = EPROTO;
553                 goto error;
554             }
555             sscanf(s, "%3d", reply_code);
556         } else {
557             if (s[0] == '.') {
558                 if (s[1] == '\0') {
559                     break;
560                 }
561                 s++;
562             }
563             ds_put_cstr(&reply, s);
564             ds_put_char(&reply, '\n');
565         }
566     }
567     *reply_body = ds_cstr(&reply);
568     ds_destroy(&line);
569     return 0;
570
571 error:
572     ds_destroy(&line);
573     ds_destroy(&reply);
574     *reply_code = 0;
575     *reply_body = NULL;
576     return error == EOF ? EPROTO : error;
577 }
578
579 /* Returns the path of the server socket to which 'client' is connected.  The
580  * caller must not modify or free the returned string. */
581 const char *
582 unixctl_client_target(const struct unixctl_client *client)
583 {
584     return client->connect_path;
585 }