diff options
| author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-03 11:05:06 +0200 |
|---|---|---|
| committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-17 20:47:39 +0200 |
| commit | f3146e2631f23c80e9ce43cbff33b294cab9f535 (patch) | |
| tree | 57b7a51b687c4b720bb9ad38cfac7aee33338b2e /userspace | |
| parent | f72b0d07a071d20cf27ed1cc160de5bd675dc992 (diff) | |
| download | cryptodev-linux-f3146e2631f23c80e9ce43cbff33b294cab9f535.tar.gz cryptodev-linux-f3146e2631f23c80e9ce43cbff33b294cab9f535.tar.xz cryptodev-linux-f3146e2631f23c80e9ce43cbff33b294cab9f535.zip | |
Added some initial support for a userspace server to receive requests.
Diffstat (limited to 'userspace')
| -rw-r--r-- | userspace/ncr-server/Makefile | 7 | ||||
| -rw-r--r-- | userspace/ncr-server/list.h | 244 | ||||
| -rw-r--r-- | userspace/ncr-server/ncr-server.c | 210 | ||||
| -rw-r--r-- | userspace/ncr-server/ncr-server.h | 11 |
4 files changed, 472 insertions, 0 deletions
diff --git a/userspace/ncr-server/Makefile b/userspace/ncr-server/Makefile new file mode 100644 index 0000000..ee46dd6 --- /dev/null +++ b/userspace/ncr-server/Makefile @@ -0,0 +1,7 @@ +all: ncr-server + +CFLAGS=-O2 -Wall -g -I.. -I. +CC=gcc + +ncr-server: ncr-server.c ncr-server.h + $(CC) $(CFLAGS) ncr-server.c -o ncr-server diff --git a/userspace/ncr-server/list.h b/userspace/ncr-server/list.h new file mode 100644 index 0000000..3a76885 --- /dev/null +++ b/userspace/ncr-server/list.h @@ -0,0 +1,244 @@ +#ifndef __LIST_H +#define __LIST_H + +/* This file is from Linux Kernel (include/linux/list.h) + * and modified by simply removing hardware prefetching of list items. + * Here by copyright, credits attributed to wherever they belong. + * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +#endif diff --git a/userspace/ncr-server/ncr-server.c b/userspace/ncr-server/ncr-server.c new file mode 100644 index 0000000..3b3c72a --- /dev/null +++ b/userspace/ncr-server/ncr-server.c @@ -0,0 +1,210 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <netlink/netlink.h> +#include <netlink/socket.h> +#include <netlink/genl/genl.h> +#include <netlink/genl/ctrl.h> +#include "../ncr-storage-low.h" +#include "ncr-server.h" +#include <list.h> + +static int _notify_listening(struct nl_sock * sock); + +static struct nla_policy def_policy[ATTR_MAX+1] = +{ + [ATTR_STRUCT_STORE] = { .type = NLA_UNSPEC, + .minlen = sizeof(struct storage_item_st) }, + [ATTR_STRUCT_LOAD] = { .type = NLA_UNSPEC, + .minlen = sizeof(struct ncr_gnl_load_cmd_st) }, +}; + +static struct actions { + list_head list; + int cmd; /* CMD_* */ + union { + struct storage_item_st tostore; + struct ncr_gnl_load_cmd_st toload; + } data; +} todo; + +static int add_store_cmd(struct storage_item_st* tostore) +{ + struct actions* item; + + item = malloc(sizeof(*item)); + if (item == NULL) { + err(); + return -ERR_MEM; + } + item->cmd = CMD_STORE; + memcpy(item->data.tostore, tostore, sizeof(item->data.tostore)); + + list_add(item, &todo.list); + return 0; +} + +static int add_load_cmd(struct ncr_gnl_load_cmd_st* toload) +{ + struct actions* item; + + item = malloc(sizeof(*item)); + if (item == NULL) { + err(); + return -ERR_MEM; + } + item->cmd = CMD_LOAD; + memcpy(item->data.toload, toload, sizeof(item->data.toload)); + + list_add(item, &todo.list); + return 0; +} + +static int msg_cb(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nlattr *attrs[ATTR_MAX+1]; + + // Validate message and parse attributes + genlmsg_parse(nlh, 0, attrs, ATTR_MAX, def_policy); + + if (attrs[ATTR_STRUCT_STORE]) { + struct storage_item_st *item = nla_get(attrs[ATTR_STRUCT_STORE]); + fprintf(stderr, "asked to store: %s\n", item->label); + + add_store_cmd(item); + } + + if (attrs[ATTR_STRUCT_LOAD]) { + struct ncr_gnl_load_cmd_st *load = nla_get(attrs[ATTR_STRUCT_LOAD]); + fprintf(stderr, "asked to load: %s\n", load->label); + + add_load_cmd(item); + } + + return NL_STOP; +} + + +int main() +{ +struct nl_sock *sock; +int ret; + + memset(&todo, 0, sizeof(todo)); + LIST_HEAD_INIT(&todo.list); + + // Allocate a new netlink socket + sock = nl_socket_alloc(); + if (sock == NULL) { + err(); + return ERR_CONNECT; + } + + // Connect to generic netlink socket on kernel side + ret = genl_connect(sock); + if (ret < 0) { + err(); + return ERR_CONNECT; + } + + // Ask kernel to resolve family name to family id + family = genl_ctrl_resolve(sock, NCR_NL_STORAGE_NAME); + if (family < 0) { + err(); + return ERR_CONNECT; + } + + /* set our callback to receive messages */ + ret = nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, msg_cb, NULL); + if (ret < 0) { + fprintf(stderr, "Could not set listening callback.\n"); + exit(1); + } + + ret = _notify_listening(sock); + if (ret < 0) { + fprintf(stderr, "Could not notify kernel subsystem.\n"); + exit(1); + } + + // Wait for the answer and receive it + do { + ret = nl_recvmsgs_default(sock); + + /* we have to consume the todo list */ + if (ret == 0) { + //store_if_needed(sock); + //load_if_needed(sock); + } + } while (ret == 0); + fprintf(stderr, "received: %d\n", ret); + +} + +static int _notify_listening(struct nl_sock * sock) +{ +struct nl_msg *msg; +int family, ret; + + // Construct a generic netlink by allocating a new message, fill in + // the header and append a simple integer attribute. + msg = nlmsg_alloc(); + if (msg == NULL) { + err(); + return ERR_MEM; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST, + CMD_LISTENING, NCR_NL_STORAGE_VERSION); + + // Send message over netlink socket + ret = nl_send_auto_complete(sock, msg); + nlmsg_free(msg); + + if (ret < 0) { + err(); + return ERR_CONNECT; + } + + return 0; +} + + +static int send_store_ack(struct nl_sock * sock, uint8_t val) +{ +struct nl_msg *msg; +int family, ret; + + // Construct a generic netlink by allocating a new message, fill in + // the header and append a simple integer attribute. + msg = nlmsg_alloc(); + if (msg == NULL) { + err(); + return ERR_MEM; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST, + CMD_STORE_ACK, NCR_NL_STORAGE_VERSION); + + ret = nla_put_u8(msg, ATTR_STORE_ACK, val); + if (ret < 0) { + err(); + ret = ERR_SEND; + goto fail; + } + + // Send message over netlink socket + ret = nl_send_auto_complete(sock, msg); + nlmsg_free(msg); + + if (ret < 0) { + err(); + return ERR_SEND; + } + + return 0; +fail: + nlmsg_free(msg); + return ret; +} diff --git a/userspace/ncr-server/ncr-server.h b/userspace/ncr-server/ncr-server.h new file mode 100644 index 0000000..dae0757 --- /dev/null +++ b/userspace/ncr-server/ncr-server.h @@ -0,0 +1,11 @@ +#ifndef NCR_SERVER_H +#define NCR_SERVER_H + +#define err() fprintf(stderr, "Error in %s:%d\n", __FILE__, __LINE__); + +#define ERR_CONNECT -1 +#define ERR_MEM -2 +#define ERR_SEND -3 + + +#endif |
