2 * keydctl.c - A simple program to control a running keyd instance
4 * Copyright 2011 Jonathan McDowell <noodles@earth.li>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <https://www.gnu.org/licenses/>.
25 #include <sys/types.h>
26 #include <sys/socket.h>
29 #include "build-config.h"
32 #include "onak-conf.h"
34 static int keyd_fd = -1;
35 static int verbose = 0;
37 static int keyd_do_command(enum keyd_ops cmd, void *buf, size_t len)
46 if (write(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
49 "Couldn't write keyd command %d: %s (%d)\n",
50 cmd, strerror(errno), errno);
53 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
56 "Couldn't read keyd command %d reply: "
58 cmd, strerror(errno), errno);
61 } else if (tmp != KEYD_REPLY_OK) {
63 } else if (buf == NULL) {
65 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
68 "Couldn't read keyd command %d reply length: "
70 cmd, strerror(errno), errno);
73 } else if (tmp > len) {
74 /* TODO: Read what we can into buf and skip the rest */
77 return read(keyd_fd, buf, tmp);
81 static void keyd_connect(void)
83 struct sockaddr_un sock;
84 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
86 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
90 "Couldn't open socket: %s (%d)\n",
97 sock.sun_family = AF_UNIX;
98 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
101 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
104 "Couldn't connect to socket %s: %s (%d)\n",
112 keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply));
113 if (reply != keyd_version) {
115 fprintf(stderr, "Error! keyd protocol version "
116 "mismatch. (us = %d, it = %d)\n",
117 keyd_version, reply);
125 static void keyd_close(void)
127 uint32_t cmd = KEYD_CMD_CLOSE;
129 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd) && verbose >= 0) {
130 fprintf(stderr, "Couldn't send close cmd: %s (%d)\n",
135 if (shutdown(keyd_fd, SHUT_RDWR) < 0 && verbose >= 0) {
136 fprintf(stderr, "Error shutting down socket: %d\n",
139 if (close(keyd_fd) < 0 && verbose >= 0) {
140 fprintf(stderr, "Error closing down socket: %d\n",
149 static void keyd_status(void)
152 struct keyd_stats stats;
153 char started[26]; /* ctime(3) says 26 is the necessary size */
155 if (keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply)) == -1) {
156 printf("Got failure asking for keyd version.\n");
159 printf("Using keyd protocol version %d.\n", reply);
161 if (keyd_do_command(KEYD_CMD_STATS, &stats, sizeof(stats)) == -1) {
162 printf("Got failure asking for keyd statistics.\n");
166 printf("keyd running since %s", ctime_r(&stats.started, started));
167 printf("%d client connections received\n", stats.connects);
169 printf("Command statistics:\n");
170 printf(" Version: %d\n",
171 stats.command_stats[KEYD_CMD_VERSION]);
172 printf(" Get key by ID: %d\n",
173 stats.command_stats[KEYD_CMD_GET_ID]);
174 printf(" Get key by FP: %d\n",
175 stats.command_stats[KEYD_CMD_GET_FP]);
176 printf(" Get key by hash: %d\n",
177 stats.command_stats[KEYD_CMD_GET_SKSHASH]);
178 printf(" Store key: %d\n",
179 stats.command_stats[KEYD_CMD_STORE]);
180 printf(" Delete key: %d\n",
181 stats.command_stats[KEYD_CMD_DELETE]);
182 printf(" Update key: %d\n",
183 stats.command_stats[KEYD_CMD_UPDATE]);
184 printf(" Search key: %d\n",
185 stats.command_stats[KEYD_CMD_GET_TEXT]);
186 printf(" Get full keyid: %d\n",
187 stats.command_stats[KEYD_CMD_GETFULLKEYID]);
188 printf(" Iterate all keys: %d\n",
189 stats.command_stats[KEYD_CMD_KEYITER]);
190 printf(" Close: %d\n",
191 stats.command_stats[KEYD_CMD_CLOSE]);
192 printf(" Quit: %d\n", stats.command_stats[KEYD_CMD_QUIT]);
193 printf(" Get statistics: %d\n",
194 stats.command_stats[KEYD_CMD_STATS]);
195 printf(" Unknown: %d\n",
196 stats.command_stats[KEYD_CMD_UNKNOWN]);
201 static void usage(void)
203 puts("keydctl " ONAK_VERSION " - control an onak keyd instance.\n");
205 puts("\tkeydctl [options] <command> <parameters>\n");
206 puts("\tCommands:\n");
207 puts("\tcheck - check if keyd is running");
208 puts("\tquit - request that keyd cleanly shuts down");
209 puts("\tstatus - display running keyd status");
213 int main(int argc, char *argv[])
216 char *configfile = NULL;
218 while ((optchar = getopt(argc, argv, "c:h")) != -1 ) {
221 configfile = strdup(optarg);
230 readconfig(configfile);
234 if ((argc - optind) < 1) {
237 } else if (!strcmp("check", argv[optind])) {
238 /* Just do the connect and close quietly */
242 } else if (!strcmp("status", argv[optind])) {
246 } else if (!strcmp("quit", argv[optind])) {
248 keyd_do_command(KEYD_CMD_QUIT, NULL, 0);