-struct dbfuncs keydb_keyd_funcs = {
- .initdb = keyd_initdb,
- .cleanupdb = keyd_cleanupdb,
- .starttrans = keyd_starttrans,
- .endtrans = keyd_endtrans,
- .fetch_key = keyd_fetch_key,
- .fetch_key_text = keyd_fetch_key_text,
- .store_key = keyd_store_key,
- .update_keys = generic_update_keys,
- .delete_key = keyd_delete_key,
- .getkeysigs = generic_getkeysigs,
- .cached_getkeysigs = generic_cached_getkeysigs,
- .keyid2uid = generic_keyid2uid,
- .getfullkeyid = keyd_getfullkeyid,
- .iterate_keys = keyd_iterate_keys,
-};
+/**
+ * cleanupdb - De-initialize the key database.
+ *
+ * This function should be called upon program exit to allow the DB to
+ * cleanup after itself.
+ */
+static void keyd_cleanupdb(struct onak_dbctx *dbctx)
+{
+ int keyd_fd = (intptr_t) dbctx->priv;
+ uint32_t cmd = KEYD_CMD_CLOSE;
+
+ if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+ logthing(LOGTHING_CRITICAL,
+ "Couldn't send close cmd: %s (%d)",
+ strerror(errno),
+ errno);
+ }
+
+ if (read(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+ logthing(LOGTHING_CRITICAL,
+ "Couldn't read close cmd reply: %s (%d)",
+ strerror(errno),
+ errno);
+ } else if (cmd != KEYD_REPLY_OK) {
+ logthing(LOGTHING_CRITICAL,
+ "Got bad reply to KEYD_CMD_CLOSE: %d", cmd);
+ }
+
+ if (shutdown(keyd_fd, SHUT_RDWR) < 0) {
+ logthing(LOGTHING_NOTICE, "Error shutting down socket: %d",
+ errno);
+ }
+ if (close(keyd_fd) < 0) {
+ logthing(LOGTHING_NOTICE, "Error closing down socket: %d",
+ errno);
+ }
+
+ free(dbctx);
+
+ return;
+}
+
+/**
+ * initdb - Initialize the key database.
+ * @readonly: If we'll only be reading the DB, not writing to it.
+ *
+ * This function should be called before any of the other functions in
+ * this file are called in order to allow the DB to be initialized ready
+ * for access.
+ */
+struct onak_dbctx *keydb_keyd_init(bool readonly)
+{
+ struct sockaddr_un sock;
+ uint32_t cmd = KEYD_CMD_UNKNOWN;
+ uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
+ ssize_t count;
+ int keyd_fd;
+ struct onak_dbctx *dbctx;
+
+ dbctx = malloc(sizeof(*dbctx));
+ if (dbctx == NULL) {
+ return NULL;
+ }
+
+ keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (keyd_fd < 0) {
+ logthing(LOGTHING_CRITICAL,
+ "Couldn't open socket: %s (%d)",
+ strerror(errno),
+ errno);
+ exit(EXIT_FAILURE);
+ }
+
+ sock.sun_family = AF_UNIX;
+ snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
+ config.db_dir,
+ KEYD_SOCKET);
+ if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
+ logthing(LOGTHING_CRITICAL,
+ "Couldn't connect to socket %s: %s (%d)",
+ sock.sun_path,
+ strerror(errno),
+ errno);
+ exit(EXIT_FAILURE);
+ }
+
+ cmd = KEYD_CMD_VERSION;
+ if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+ logthing(LOGTHING_CRITICAL,
+ "Couldn't write version cmd: %s (%d)",
+ strerror(errno),
+ errno);
+ } else {
+ count = read(keyd_fd, &reply, sizeof(reply));
+ if (count == sizeof(reply) && reply == KEYD_REPLY_OK) {
+ count = read(keyd_fd, &reply, sizeof(reply));
+ if (count != sizeof(reply) || reply != sizeof(reply)) {
+ logthing(LOGTHING_CRITICAL,
+ "Error! Unexpected keyd version "
+ "length: %d != %d",
+ reply, sizeof(reply));
+ exit(EXIT_FAILURE);
+ }
+
+ count = read(keyd_fd, &reply, sizeof(reply));
+ if (count != sizeof(reply)) {
+ logthing(LOGTHING_CRITICAL,
+ "Error! Unexpected keyd version "
+ "length: %d != %d",
+ count, sizeof(reply));
+ exit(EXIT_FAILURE);
+ }
+ logthing(LOGTHING_DEBUG,
+ "keyd protocol version %d",
+ reply);
+ if (reply != keyd_version) {
+ logthing(LOGTHING_CRITICAL,
+ "Error! keyd protocol version "
+ "mismatch. (us = %d, it = %d)",
+ keyd_version, reply);
+ }
+ }
+ }
+
+ dbctx->priv = (void *) (intptr_t) keyd_fd;
+ dbctx->cleanupdb = keyd_cleanupdb;
+ dbctx->starttrans = keyd_starttrans;
+ dbctx->endtrans = keyd_endtrans;
+ dbctx->fetch_key_id = keyd_fetch_key_id;
+ dbctx->fetch_key_fp = keyd_fetch_key_fp;
+ dbctx->fetch_key_text = keyd_fetch_key_text;
+ dbctx->fetch_key_skshash = keyd_fetch_key_skshash;
+ dbctx->store_key = keyd_store_key;
+ dbctx->update_keys = generic_update_keys;
+ dbctx->delete_key = keyd_delete_key;
+ dbctx->getkeysigs = generic_getkeysigs;
+ dbctx->cached_getkeysigs = generic_cached_getkeysigs;
+ dbctx->keyid2uid = generic_keyid2uid;
+ dbctx->getfullkeyid = keyd_getfullkeyid;
+ dbctx->iterate_keys = keyd_iterate_keys;
+
+ return dbctx;
+}