diff options
Diffstat (limited to 'ncr-storage-low.c')
-rw-r--r-- | ncr-storage-low.c | 165 |
1 files changed, 118 insertions, 47 deletions
diff --git a/ncr-storage-low.c b/ncr-storage-low.c index 418bc8ff969..489aa2ecfe4 100644 --- a/ncr-storage-low.c +++ b/ncr-storage-low.c @@ -60,6 +60,7 @@ struct event_item_st* item; item->id = id; item->reply = NULL; item->reply_size = 0; + item->ireply = -1; init_completion(&item->completed); down(&event_list.sem); @@ -73,10 +74,8 @@ static int event_wait(uint32_t id) { struct event_item_st* item; struct completion* completed = NULL; -int ret = 0; down(&event_list.sem); - list_for_each_entry(item, &event_list.list, list) { if (id == item->id) { completed = &item->completed; @@ -84,10 +83,13 @@ int ret = 0; } } up(&event_list.sem); + if (completed) { - ret = wait_for_completion_interruptible(completed); + return wait_for_completion_interruptible(completed); + } else { + err(); + return -EIO; } - return 0; } @@ -203,23 +205,73 @@ struct event_item_st* item, *tmp; static struct nla_policy ncr_genl_policy[ATTR_MAX + 1] = { [ATTR_STRUCT_LOAD] = { .type = NLA_BINARY }, [ATTR_STRUCT_LOADED] = { .type = NLA_BINARY }, - [ATTR_STORE_ACK] = { .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; -#define VERSION_NR 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 = VERSION_NR, //version number + .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) @@ -236,7 +288,7 @@ int _ncr_store(const struct storage_item_st * tostore) 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)) + @@ -248,7 +300,7 @@ int _ncr_store(const struct storage_item_st * tostore) goto out; } - id = atomic_long_inc_return(&ncr_event_sr); + 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) { @@ -278,6 +330,12 @@ int _ncr_store(const struct storage_item_st * 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) @@ -286,10 +344,13 @@ int _ncr_store(const struct storage_item_st * tostore) /* wait for an acknowledgment */ ret = event_wait(id); if (ret) { - goto out; + err(); + printk(KERN_DEBUG"Error waiting for id %u\n", id); + event_remove(id); + return ret; } - reply = event_get_idata(id, &reply_size); + reply = event_get_idata(id); if (reply == (uint32_t)-1) BUG(); @@ -317,7 +378,7 @@ int _ncr_load(struct storage_item_st * toload) struct sk_buff *skb; int ret; void *msg_head; - size_t size, reply_size; + size_t reply_size=0, size; struct nlattr *attr; void* msg, *reply; struct ncr_gnl_load_cmd_st cmd; @@ -339,7 +400,7 @@ int _ncr_load(struct storage_item_st * toload) goto out; } - id = atomic_long_inc_return(&ncr_event_sr); + 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) { @@ -386,7 +447,10 @@ int _ncr_load(struct storage_item_st * toload) /* wait for an answer */ ret = event_wait(id); if (ret) { - goto out; + err(); + printk(KERN_DEBUG"Error waiting for id %u\n", id); + event_remove(id); + return ret; } reply = event_get_data(id, &reply_size); @@ -413,6 +477,8 @@ int ncr_gnl_listen(struct sk_buff *skb, struct genl_info *info) 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; } @@ -421,33 +487,32 @@ int ncr_gnl_listen(struct sk_buff *skb, struct genl_info *info) /* with this command the userspace server registers */ int ncr_gnl_store_ack(struct sk_buff *skb, struct genl_info *info) { - uint8_t * data, *event_reply; + uint8_t * data; size_t len; - struct ncr_gnl_store_ack_st reply; + 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_ACK]; + 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 { - - memcpy( &reply, data, sizeof(reply)); - - event_set_idata(reply.id, (uint32_t)reply.reply[0]); + reply = (void*)data; + event_set_idata(reply->id, (uint32_t)reply->reply); - event_complete(reply.id); + event_complete(reply->id); } } else - printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STORE_ACK); + printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STORE_U8); return 0; } @@ -457,7 +522,7 @@ 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 ncr_gnl_loaded_st *reply; struct nlattr *na; if (info == NULL) @@ -473,14 +538,13 @@ int ncr_gnl_loaded_data(struct sk_buff *skb, struct genl_info *info) if (data == NULL || len != sizeof(struct ncr_gnl_loaded_st)) printk(KERN_DEBUG"error while receiving data\n"); else { - - memcpy( &reply, data, sizeof(reply)); - event_reply = kmalloc(sizeof(reply.storage), GFP_KERNEL); + 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)); + memcpy(event_reply, &reply->storage, sizeof(reply->storage)); + event_set_data(reply->id, event_reply, sizeof(reply->storage)); } - event_complete(reply.id); + event_complete(reply->id); } } else printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STRUCT_LOADED); @@ -519,35 +583,38 @@ struct genl_ops ncr_gnl_ops_store_ack = { int ncr_gnl_init(void) { int rc; - printk("INIT GENERIC NETLINK EXEMPLE MODULE\n"); + + printk(KERN_NOTICE"cryptodev: Initializing netlink subsystem.\n"); init_MUTEX(&event_list.sem); INIT_LIST_HEAD(&event_list.list); - atomic_set(&ncr_event_sr, 0); + atomic_set(&ncr_event_sr, 1); - /*register new family*/ + /*register new family*/ rc = genl_register_family(&ncr_gnl_family); - if (rc != 0) + if (rc != 0) { + err(); goto failure; - /*register functions (commands) of the new family*/ + } + /*register functions (commands) of the new family*/ rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_listen); if (rc != 0) { - printk("register ops: %i\n",rc); + err(); genl_unregister_family(&ncr_gnl_family); goto failure; } rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack); if (rc != 0) { - printk("register ops: %i\n",rc); + err(); genl_unregister_family(&ncr_gnl_family); goto failure; } rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_load); if (rc != 0) { - printk("register ops: %i\n",rc); + err(); genl_unregister_family(&ncr_gnl_family); goto failure; } @@ -555,7 +622,7 @@ int ncr_gnl_init(void) return 0; failure: - printk("an error occured while inserting the generic netlink example module\n"); + printk(KERN_ERR"an error occured while loading the cryptodev netlink subsystem\n"); return rc; } @@ -563,15 +630,8 @@ void ncr_gnl_deinit(void) { int ret; struct event_item_st *item, *tmp; - printk("EXIT GENERIC NETLINK EXEMPLE MODULE\n"); - /* deinitialize the event list */ - down(&event_list.sem); - list_for_each_entry_safe(item, tmp, &event_list.list, list) { - list_del(&item->list); - kfree(item); - } - up(&event_list.sem); + _ncr_nl_close(); ret = genl_unregister_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack); if(ret != 0) { @@ -596,4 +656,15 @@ void ncr_gnl_deinit(void) 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); + } |