//
// Simple capability storage
- rpc get_cap(in String key[2048], out cap retcap, out errval reterr);
- rpc put_cap(in String key[2048], in cap storecap, out errval reterr);
- rpc remove_cap(in String key[2048], out errval reterr);
+ rpc get_cap(in String key[256], out cap retcap, out errval reterr);
+ rpc put_cap(in String key[256], in cap storecap, out errval reterr);
+ rpc sput_cap(in String key[256], in cap storecap, out String retkey[256], out errval reterr);
+ rpc remove_cap(in String key[256], out errval reterr);
};
errval_t oct_get_capability(const char*, struct capref*);
errval_t oct_put_capability(const char*, struct capref);
+errval_t oct_sput_capability(const char*, struct capref, char** retkey);
errval_t oct_remove_capability(const char*);
#endif /* OCTOPUS_CAPABILITY_STORAGE_H_ */
// For capability storage
struct capref cap;
+ char* retkey;
struct oct_reply_state *next;
};
// Capability Storage
void get_cap_handler(struct octopus_binding*, const char*);
void put_cap_handler(struct octopus_binding*, const char*, struct capref);
+void sput_cap_handler(struct octopus_binding*, const char*, struct capref);
void remove_cap_handler(struct octopus_binding*, const char*);
#endif /* OCTOPUS_SERVICE_H_ */
}
/**
+ * \brief Put a capability to the capability store with a generated identifier.
+ *
+ * The server appends a globally unique ID to the key and returns
+ * the generated ID as part of retkey.
+ * The caller is responsible to free retkey.
+ *
+ * \param[in] key Base key (server appends this with unique ID).
+ * \param[in] cap The capability to store
+ * \param[out] retkey Allocated string of generated unique identifier.
+ */
+errval_t oct_sput_capability(const char *key, struct capref cap, char **outkey)
+{
+ errval_t err;
+ struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
+ assert(cl != NULL);
+
+ struct octopus_sput_cap_response__rx_args reply;
+ err = cl->call_seq.sput_cap(cl, key, cap, reply.retkey, &reply.reterr);
+ if(err_is_fail(err)) {
+ return err;
+ }
+ //printf("%s:%s:%d: stored key= %s retkey = %s\n", __FILE__, __FUNCTION__, __LINE__, key, reply.retkey);
+ if (err_is_fail(reply.reterr)) {
+ DEBUG_ERR(reply.reterr, "call failed.");
+ }
+
+ if (reply.retkey != NULL) {
+ *outkey = strdup(reply.retkey);
+ }
+
+ return reply.reterr;
+}
+
+/**
* \brief Remove a capability from the capability store.
*
* \param key String that identifies the capability
ns->reply(b, ns);
}
+static void free_ns(void* arg) {
+ struct oct_reply_state* ns = (struct oct_reply_state*) arg;
+ free(ns->retkey);
+ free(ns);
+}
+
+static void sput_cap_reply(struct octopus_binding *b,
+ struct oct_reply_state* ns)
+{
+ errval_t err;
+ err = b->tx_vtbl.sput_cap_response(b, MKCONT(free_ns, ns), ns->retkey, ns->error);
+ if (err_is_fail(err)) {
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ oct_rpc_enqueue_reply(b, ns);
+ return;
+ }
+ USER_PANIC_ERR(err, "SKB: sending %s failed!", __FUNCTION__);
+ }
+}
+
+void sput_cap_handler(struct octopus_binding *b, const char *key,
+ struct capref cap)
+{
+ errval_t err, reterr = SYS_ERR_OK;
+ struct oct_reply_state* ns = NULL;
+ struct capref dbcap;
+ // Identfier to make sure all caps have a unique key
+ static uint32_t CAP_IDENT = 0;
+
+ char* uniquekey = NULL;
+ int r = asprintf(&uniquekey, "%s%d", key, CAP_IDENT++);
+ if (uniquekey == NULL || r == -1) {
+ reterr = LIB_ERR_MALLOC_FAIL;
+ goto out;
+ }
+
+ capdb->d.get_capability(&capdb->d, (CONST_CAST)key, &dbcap);
+ if(!capcmp(dbcap, NULL_CAP)) {
+ // This case is not intended to happen
+ // but can if a malicious client takes a key
+ reterr = OCT_ERR_CAP_OVERWRITE;
+ } else {
+ // we need to make our own copy of the key
+ char* dupkey = strdup(uniquekey);
+ r = capdb->d.put_capability(&capdb->d, (CONST_CAST)dupkey, cap);
+ assert(r == 0);
+ }
+
+out:
+ err = new_oct_reply_state(&ns, sput_cap_reply);
+ assert(err_is_ok(err));
+ ns->retkey = uniquekey;
+ ns->error = reterr;
+ ns->reply(b, ns);
+}
+
static void remove_cap_reply(struct octopus_binding *b,
struct oct_reply_state* ns)
{
// Cap storage
.get_cap_call = get_cap_handler,
.put_cap_call = put_cap_handler,
+ .sput_cap_call = sput_cap_handler,
.remove_cap_call = remove_cap_handler,
};