summaryrefslogtreecommitdiffstats
path: root/ncr-storage-low.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncr-storage-low.c')
-rw-r--r--ncr-storage-low.c670
1 files changed, 0 insertions, 670 deletions
diff --git a/ncr-storage-low.c b/ncr-storage-low.c
deleted file mode 100644
index 489aa2e..0000000
--- a/ncr-storage-low.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * New driver for /dev/crypto device (aka CryptoDev)
-
- * Copyright (c) 2010 Nikos Mavrogiannopoulos <nmav@gnutls.org>
- *
- * This file is part of linux cryptodev.
- *
- * cryptodev is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * cryptodev is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include "cryptodev.h"
-#include <asm/uaccess.h>
-#include <net/genetlink.h>
-#include <linux/kernel.h>
-#include <linux/completion.h>
-#include "ncr.h"
-#include "ncr_int.h"
-#include "ncr-storage.h"
-#include "ncr-storage-low.h"
-
-/* The idea here is to have communication via netlink to userspace
- * send our commands, put an id in the list and wait for completion of the
- * request. The server should compute our request and reply with the id.
- */
-
-struct event_item_st {
- struct list_head list;
- struct completion completed;
- void* reply;
- size_t reply_size;
- uint32_t ireply;
- uint32_t id;
-};
-
-
-static struct list_sem_st event_list;
-
-static int event_add(uint32_t id)
-{
-struct event_item_st* item;
-
- item = kmalloc( sizeof(*item), GFP_KERNEL);
- if (item == NULL) {
- err();
- return -ENOMEM;
- }
- item->id = id;
- item->reply = NULL;
- item->reply_size = 0;
- item->ireply = -1;
- init_completion(&item->completed);
-
- down(&event_list.sem);
- list_add(&item->list, &event_list.list);
- up(&event_list.sem);
-
- return 0;
-}
-
-static int event_wait(uint32_t id)
-{
-struct event_item_st* item;
-struct completion* completed = NULL;
-
- down(&event_list.sem);
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- completed = &item->completed;
- break;
- }
- }
- up(&event_list.sem);
-
- if (completed) {
- return wait_for_completion_interruptible(completed);
- } else {
- err();
- return -EIO;
- }
-}
-
-
-static void event_complete(uint32_t id)
-{
-struct event_item_st* item;
-
- down(&event_list.sem);
-
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- complete(&item->completed);
- break;
- }
- }
- up(&event_list.sem);
-}
-
-static void event_set_data(uint32_t id, void* data, size_t data_size)
-{
-struct event_item_st* item;
-
- down(&event_list.sem);
-
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- item->reply = data;
- item->reply_size = data_size;
- break;
- }
- }
- up(&event_list.sem);
-
- return;
-}
-
-static void event_set_idata(uint32_t id, uint32_t data)
-{
-struct event_item_st* item;
-
- down(&event_list.sem);
-
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- item->ireply = data;
- break;
- }
- }
- up(&event_list.sem);
-
- return;
-}
-
-static void* event_get_data(uint32_t id, size_t *reply_size)
-{
-struct event_item_st* item;
-void* reply = NULL;
-
- down(&event_list.sem);
-
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- reply = &item->reply;
- *reply_size = item->reply_size;
- break;
- }
- }
- up(&event_list.sem);
-
- return reply;
-}
-
-static uint32_t event_get_idata(uint32_t id)
-{
-struct event_item_st* item;
-uint32_t reply = -1;
-
- down(&event_list.sem);
-
- list_for_each_entry(item, &event_list.list, list) {
- if (id == item->id) {
- reply = item->ireply;
- break;
- }
- }
- up(&event_list.sem);
-
- return reply;
-}
-
-static void event_remove(uint32_t id)
-{
-struct event_item_st* item, *tmp;
-
- down(&event_list.sem);
-
- list_for_each_entry_safe(item, tmp, &event_list.list, list) {
- if (id == item->id) {
- list_del(&item->list);
- if (item->reply)
- kfree(item->reply);
- kfree(item);
- break;
- }
- }
- up(&event_list.sem);
-}
-
-
-/* attribute policy: defines which attribute has which type (e.g int, char * etc)
- * possible values defined in net/netlink.h
- */
-static struct nla_policy ncr_genl_policy[ATTR_MAX + 1] = {
- [ATTR_STRUCT_LOAD] = { .type = NLA_BINARY },
- [ATTR_STRUCT_LOADED] = { .type = NLA_BINARY },
- [ATTR_STORE_U8] = { .type = NLA_BINARY },
- [ATTR_STRUCT_STORE] = { .type = NLA_BINARY },
-};
-
-static atomic_t ncr_event_sr;
-static uint32_t listener_pid = -1;
-
-/* family definition */
-static struct genl_family ncr_gnl_family = {
- .id = GENL_ID_GENERATE, //genetlink should generate an id
- .hdrsize = 0,
- .name = NCR_NL_STORAGE_NAME, //the name of this family, used by userspace application
- .version = NCR_NL_STORAGE_VERSION, //version number
- .maxattr = ATTR_MAX,
-};
-
-/* an echo command, receives a message, prints it and sends another message back */
-static void _ncr_nl_close(void)
-{
- struct sk_buff *skb;
- int ret;
- void *msg_head;
- uint32_t id;
-
- if (listener_pid == -1) {
- err();
- return;
- }
-
- skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
- if (skb == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- id = atomic_add_return(1, &ncr_event_sr);
- msg_head = genlmsg_put(skb, 0, id, &ncr_gnl_family, 0, CMD_CLOSE);
- if (msg_head == NULL) {
- err();
- ret = -ENOMEM;
- goto out;
- }
-
- ret = nla_put_u8(skb, ATTR_STORE_U8, 1);
- if (ret != 0) {
- err();
- goto out;
- }
-
- /* finalize the message */
- genlmsg_end(skb, msg_head);
-
- /* send the message back */
- ret = genlmsg_unicast(skb, listener_pid);
- if (ret != 0) {
- err();
- goto out;
- }
-
- return;
-
-out:
- nlmsg_free(skb);
- printk("an error occured in ncr_gnl_store\n");
-
- return;
-}
-
-/* an echo command, receives a message, prints it and sends another message back */
-int _ncr_store(const struct storage_item_st * tostore)
-{
- struct sk_buff *skb;
- int ret;
- uint32_t reply;
- size_t size;
- struct nlattr *attr;
- void* msg, *msg_head;
- uint32_t id;
-
- if (listener_pid == -1) {
- err();
- return -EIO;
- }
-
- /* send a message back*/
- /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/
- size = nla_total_size(sizeof(struct storage_item_st)) +
- nla_total_size(0);
-
- skb = genlmsg_new(size, GFP_KERNEL);
- if (skb == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- id = atomic_add_return(1, &ncr_event_sr);
- msg_head = genlmsg_put(skb, 0, id,
- &ncr_gnl_family, 0, CMD_STORE);
- if (msg_head == NULL) {
- err();
- ret = -ENOMEM;
- goto out;
- }
-
- /* fill the data */
- attr = nla_reserve(skb, ATTR_STRUCT_STORE,
- sizeof(struct storage_item_st));
- if (!attr) {
- err();
- ret = -EINVAL;
- goto out;
- }
-
- msg = nla_data(attr);
- if (!msg) {
- err();
- ret = -EINVAL;
- goto out;
- }
-
- memcpy(msg, tostore, sizeof(*tostore));
-
- /* finalize the message */
- genlmsg_end(skb, msg_head);
-
- ret = event_add(id);
- if (ret < 0) {
- err();
- goto out;
- }
-
- /* send the message back */
- ret = genlmsg_unicast(skb, listener_pid);
- if (ret != 0)
- goto out;
-
- /* wait for an acknowledgment */
- ret = event_wait(id);
- if (ret) {
- err();
- printk(KERN_DEBUG"Error waiting for id %u\n", id);
- event_remove(id);
- return ret;
- }
-
- reply = event_get_idata(id);
- if (reply == (uint32_t)-1)
- BUG();
-
- if (reply != 0) {
- /* write failed */
- ret = -EIO;
- } else {
- ret = 0;
- }
-
- event_remove(id);
- return ret;
-
-out:
- nlmsg_free(skb);
- printk("an error occured in ncr_gnl_store\n");
-
- return ret;
-}
-
-
-/* an echo command, receives a message, prints it and sends another message back */
-int _ncr_load(struct storage_item_st * toload)
-{
- struct sk_buff *skb;
- int ret;
- void *msg_head;
- size_t reply_size=0, size;
- struct nlattr *attr;
- void* msg, *reply;
- struct ncr_gnl_load_cmd_st cmd;
- uint32_t id;
-
- if (listener_pid == -1) {
- err();
- return -EIO;
- }
-
- /* send a message back*/
- /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/
- size = nla_total_size(sizeof(struct ncr_gnl_load_cmd_st)) +
- nla_total_size(0);
-
- skb = genlmsg_new(size, GFP_KERNEL);
- if (skb == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- id = atomic_add_return(1, &ncr_event_sr);
- msg_head = genlmsg_put(skb, 0, id,
- &ncr_gnl_family, 0, CMD_LOAD);
- if (msg_head == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* fill the data */
- attr = nla_reserve(skb, ATTR_STRUCT_LOAD,
- sizeof(struct ncr_gnl_load_cmd_st));
- if (!attr) {
- err();
- ret = -EINVAL;
- goto out;
- }
-
- msg = nla_data(attr);
- if (!msg) {
- err();
- ret = -EINVAL;
- goto out;
- }
-
- cmd.owner = toload->owner;
- cmd.group = toload->group;
- strcpy(cmd.label, toload->label);
-
- memcpy(msg, &cmd, sizeof(cmd));
-
- /* finalize the message */
- genlmsg_end(skb, msg_head);
-
- ret = event_add(id);
- if (ret < 0) {
- err();
- goto out;
- }
-
- /* send the message */
- ret = genlmsg_unicast(skb, listener_pid);
- if (ret != 0)
- goto out;
-
- /* wait for an answer */
- ret = event_wait(id);
- if (ret) {
- err();
- printk(KERN_DEBUG"Error waiting for id %u\n", id);
- event_remove(id);
- return ret;
- }
-
- reply = event_get_data(id, &reply_size);
- if (reply_size != sizeof(struct storage_item_st))
- BUG();
-
- memcpy(toload, reply, reply_size);
-
- event_remove(id);
-
- return 0;
-
-out:
- nlmsg_free(skb);
- printk("an error occured in ncr_gnl_store\n");
-
- return ret;
-}
-
-/* with this command the userspace server registers */
-int ncr_gnl_listen(struct sk_buff *skb, struct genl_info *info)
-{
- if (info == NULL)
- return -EIO;
-
- listener_pid = info->snd_pid;
- atomic_set(&ncr_event_sr, info->snd_seq+1);
- printk(KERN_DEBUG"Setting listener pid to %d!\n", (int)listener_pid);
-
- return 0;
-}
-
-
-/* with this command the userspace server registers */
-int ncr_gnl_store_ack(struct sk_buff *skb, struct genl_info *info)
-{
- uint8_t * data;
- size_t len;
- struct ncr_gnl_store_ack_st *reply;
- struct nlattr *na;
-
- if (info == NULL)
- return -EIO;
-
- printk("Received store ack!\n");
- /*for each attribute there is an index in info->attrs which points to a nlattr structure
- *in this structure the data is given
- */
- na = info->attrs[ATTR_STORE_U8];
- if (na) {
- len = nla_len(na);
- data = (void *)nla_data(na);
- if (data == NULL || len != sizeof(struct ncr_gnl_store_ack_st))
- printk(KERN_DEBUG"error while receiving data\n");
- else {
- reply = (void*)data;
- event_set_idata(reply->id, (uint32_t)reply->reply);
-
- event_complete(reply->id);
- }
- } else
- printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STORE_U8);
-
- return 0;
-}
-
-/* an echo command, receives a message, prints it and sends another message back */
-int ncr_gnl_loaded_data(struct sk_buff *skb, struct genl_info *info)
-{
- uint8_t * data, *event_reply;
- size_t len;
- struct ncr_gnl_loaded_st *reply;
- struct nlattr *na;
-
- if (info == NULL)
- return -EIO;
-
- /*for each attribute there is an index in info->attrs which points to a nlattr structure
- *in this structure the data is given
- */
- na = info->attrs[ATTR_STRUCT_LOADED];
- if (na) {
- len = nla_len(na);
- data = (void *)nla_data(na);
- if (data == NULL || len != sizeof(struct ncr_gnl_loaded_st))
- printk(KERN_DEBUG"error while receiving data\n");
- else {
- reply = (void*)data;
- event_reply = kmalloc(sizeof(reply->storage), GFP_KERNEL);
- if (event_reply != NULL) {
- memcpy(event_reply, &reply->storage, sizeof(reply->storage));
- event_set_data(reply->id, event_reply, sizeof(reply->storage));
- }
- event_complete(reply->id);
- }
- } else
- printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STRUCT_LOADED);
-
- return 0;
-}
-
-
-/* commands: mapping between the command enumeration and the actual function*/
-struct genl_ops ncr_gnl_ops_listen = {
- .cmd = CMD_LISTENING,
- .flags = 0,
- .policy = ncr_genl_policy,
- .doit = ncr_gnl_listen,
- .dumpit = NULL,
-};
-
-struct genl_ops ncr_gnl_ops_load = {
- .cmd = CMD_LOADED_DATA,
- .flags = 0,
- .policy = ncr_genl_policy,
- .doit = ncr_gnl_loaded_data,
- .dumpit = NULL,
-};
-
-struct genl_ops ncr_gnl_ops_store_ack = {
- .cmd = CMD_STORE_ACK,
- .flags = 0,
- .policy = ncr_genl_policy,
- .doit = ncr_gnl_store_ack,
- .dumpit = NULL,
-};
-
-
-
-int ncr_gnl_init(void)
-{
- int rc;
-
- printk(KERN_NOTICE"cryptodev: Initializing netlink subsystem.\n");
-
- init_MUTEX(&event_list.sem);
- INIT_LIST_HEAD(&event_list.list);
- atomic_set(&ncr_event_sr, 1);
-
- /*register new family*/
- rc = genl_register_family(&ncr_gnl_family);
- if (rc != 0) {
- err();
- goto failure;
- }
- /*register functions (commands) of the new family*/
-
- rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_listen);
- if (rc != 0) {
- err();
- genl_unregister_family(&ncr_gnl_family);
- goto failure;
- }
-
- rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack);
- if (rc != 0) {
- err();
- genl_unregister_family(&ncr_gnl_family);
- goto failure;
- }
-
- rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_load);
- if (rc != 0) {
- err();
- genl_unregister_family(&ncr_gnl_family);
- goto failure;
- }
-
- return 0;
-
- failure:
- printk(KERN_ERR"an error occured while loading the cryptodev netlink subsystem\n");
- return rc;
-}
-
-void ncr_gnl_deinit(void)
-{
- int ret;
- struct event_item_st *item, *tmp;
-
- _ncr_nl_close();
-
- ret = genl_unregister_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack);
- if(ret != 0) {
- printk("unregister ops: %i\n",ret);
- return;
- }
-
- ret = genl_unregister_ops(&ncr_gnl_family, &ncr_gnl_ops_load);
- if(ret != 0) {
- printk("unregister ops: %i\n",ret);
- return;
- }
-
- ret = genl_unregister_ops(&ncr_gnl_family, &ncr_gnl_ops_listen);
- if(ret != 0) {
- printk("unregister ops: %i\n",ret);
- return;
- }
-
- /*unregister the family*/
- ret = genl_unregister_family(&ncr_gnl_family);
- if(ret !=0) {
- printk("unregister family %i\n",ret);
- }
-
- /* deinitialize the event list */
- down(&event_list.sem);
- list_for_each_entry_safe(item, tmp, &event_list.list, list) {
- list_del(&item->list);
- if (item->reply)
- kfree(item->reply);
- kfree(item);
- }
- up(&event_list.sem);
-
-}