I have a user space program that I thought should work, but it fails when it calls the genl_Ctrl_resolve (see below). Can anyone help me why? I am using the libl 3.2.7. Both user space and kernel module compile and link. I cut and paste it here, so I maybe missing a } or something, but don't focus on that. Like I said, both programs compile and link, so no syntax issue.<br>
<br>Kernel side during the init calls the genl_register_family(), genl_register_ops(), so I don't understand why when the user space call to genl_ctrl_resolve() failes?<br> #include <stdio.h><br> 2 #include <netlink/netlink.h><br>
3 #include <netlink/genetlink.h><br> 4 #include <netlink/genl/genl.h><br> 5 #include <netlink/genl/ctrl.h><br> 6 #include <linux/errno.h><br><br>int clear_ctf_table() {<br> 58 struct nl_sock *sock;<br>
59 struct nl_msg *msg;<br> 60 int family;<br> 61 printf("**************Entering the USER SPACE portion***\n");<br> 62 /* Allocate a new netlink socket in userspace */<br> 63 sock = nl_socket_alloc();<br>
64 if(sock == NULL) {<br> 65 printf("couldn't allocate socket\n");<br> 66 goto out;<br> 67 }<br> 68 <br> 69 /* Connect to the generic netlink socket family in the kernel */<br>
70 if (genl_connect(sock) < 0) {<br> 71 printf("error while connecting\n");<br> 72 goto out;<br> 73 }<br> 74 <br> 75 /* obtain the family id for the CONTROL_GUARDIAN family */<br>
76 family = genl_ctrl_resolve(sock, "generic_netlink_family_name");<br> 77 if (family < 0) {<br> 78 printf("error obtaining family\n");<br> 79 goto out;<br>
80 }<br>........<br><br>It fails and prints "error obtaining family"<br><br>I followed the examples given and was expecting this to work. <br><br>On the kernel side I have the following code. The module is loaded in kernel and I see the module is loaded in kernel and init passes<br>
<br>Kernel side code:<br>#include <net/netlink.h><br>#include <net/genetlink.h><br>#include <linux/module.h><br>#include <linux/kernel.h><br><br>/* attributes (variables): the index in this enum is used as a reference for the type,<br>
* userspace application has to indicate the corresponding type<br> * the policy is used for security considerations <br> */<br>enum {<br> DOC_GUARD_ATT_UNSPEC,<br> DOC_GUARD_ATT_MSG,<br>
__DOC_GUARD_ATT_MAX,<br>};<br>#define DOC_GUARD_ATT_MAX (__DOC_GUARD_ATT_MAX - 1)<br><br>/* attribute policy: defines which attribute has which type (e.g int, char * etc)<br> * possible values defined in net/netlink.h <br>
*/<br>static struct nla_policy doc_exmpl_genl_policy[DOC_GUARD_ATT_MAX + 1] = {<br> [DOC_GUARD_ATT_MSG] = { .type = NLA_NUL_STRING },<br>};<br><br>#define VERSION_NR 1<br>/* family definition */<br>static struct genl_family doc_exmpl_gnl_family = {<br>
.id = GENL_ID_GENERATE, //genetlink should generate an id<br> .hdrsize = 0,<br> .name ="generic_netlink_family_name", //the name of this family, used by userspace application<br>
.version = VERSION_NR, //version number <br> .maxattr = DOC_GUARD_ATT_MAX,<br>};<br><br>/* commands: enumeration of all commands (functions), <br> * used by userspace application to identify command to be ececuted<br>
*/<br>enum {<br> DOC_GUARD_COMM_UNSPEC,<br> DOC_GUARD_COMM_ECHO,<br> __DOC_GUARD_COMM_MAX,<br>};<br>#define DOC_GUARD_COMM_MAX (__DOC_GUARD_COMM_MAX - 1)<br><br><br>/* an echo command, receives a message, prints it and sends another message back */<br>
int guardian_exmpl_echo(struct sk_buff *skb_2, struct genl_info *info)<br>#include <net/netlink.h><br>#include <net/genetlink.h><br>#include <linux/module.h><br>#include <linux/kernel.h><br><br>/* attributes (variables): the index in this enum is used as a reference for the type,<br>
* userspace application has to indicate the corresponding type<br> * the policy is used for security considerations <br> */<br>enum {<br> DOC_GUARD_ATT_UNSPEC,<br> DOC_GUARD_ATT_MSG,<br>
__DOC_GUARD_ATT_MAX,<br>};<br>#define DOC_GUARD_ATT_MAX (__DOC_GUARD_ATT_MAX - 1)<br><br>/* attribute policy: defines which attribute has which type (e.g int, char * etc)<br> * possible values defined in net/netlink.h <br>
*/<br>static struct nla_policy doc_exmpl_genl_policy[DOC_GUARD_ATT_MAX + 1] = {<br> [DOC_GUARD_ATT_MSG] = { .type = NLA_NUL_STRING },<br>};<br><br>#define VERSION_NR 1<br>/* family definition */<br>static struct genl_family doc_exmpl_gnl_family = {<br>
.id = GENL_ID_GENERATE, //genetlink should generate an id<br> .hdrsize = 0,<br> .name ="generic_netlink_family_name", //the name of this family, used by userspace application<br>
.version = VERSION_NR, //version number <br> .maxattr = DOC_GUARD_ATT_MAX,<br>};<br><br>/* commands: enumeration of all commands (functions), <br> * used by userspace application to identify command to be ececuted<br>
*/<br>enum {<br> DOC_GUARD_COMM_UNSPEC,<br> DOC_GUARD_COMM_ECHO,<br> __DOC_GUARD_COMM_MAX,<br>};<br>#define DOC_GUARD_COMM_MAX (__DOC_GUARD_COMM_MAX - 1)<br><br><br>/* an echo command, receives a message, prints it and sends another message back */<br>
int guardian_exmpl_echo(struct sk_buff *skb_2, struct genl_info *info)<br>{<br> struct nlattr *na;<br> struct sk_buff *skb;<br> int rc;<br> void *msg_head;<br> char * mydata;<br><br> if (info == NULL)<br>
goto out;<br><br> /*for each attribute there is an index in info->attrs which points to a nlattr structure<br> *in this structure the data is given<br> */<br> na = info->attrs[DOC_GUARD_ATT_MSG];<br>
if (na) {<br> mydata = (char *)nla_data(na);<br> if (mydata == NULL)<br> printk("error while receiving data\n");<br> else<br> printk("received: %s\n", mydata);<br>
}<br> else<br> printk("no info->attrs %i\n", DOC_GUARD_ATT_MSG);<br><br> /* send a message back*/<br> /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/<br>
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);<br> if (skb == NULL)<br> goto out;<br><br> /* create the message headers */<br> /* arguments of genlmsg_put: <br> struct sk_buff *, <br>
int (sending) pid, <br> int sequence number, <br> struct genl_family *, <br> int flags, <br> u8 command index (why do we need this?)<br> */<br> msg_head = genlmsg_put(skb, 0, info->snd_seq+1, &doc_exmpl_gnl_family, 0, DOC_GUARD_COMM_ECHO);<br>
if (msg_head == NULL) {<br> rc = -ENOMEM;<br> goto out;<br> }<br> /* add a DOC_GUARD_ATT_MSG attribute (actual value to be sent) */<br> rc = nla_put_string(skb, DOC_GUARD_ATT_MSG, "hello world from kernel space");<br>
if (rc != 0)<br> goto out;<br><br> /* finalize the message */<br> genlmsg_end(skb, msg_head);<br><br> /* send the message back */<br> rc = genlmsg_unicast(skb,info->snd_pid );<br>
if (rc != 0)<br> goto out;<br> return 0;<br><br> out:<br> printk("an error occured in guardian_exmpl_echo:\n");<br><br> return 0;<br>}<br>/* commands: mapping between the command enumeration and the actual function*/<br>
struct genl_ops doc_exmpl_gnl_ops_echo = {<br> .cmd = DOC_GUARD_COMM_ECHO,<br> .flags = 0,<br> .policy = doc_exmpl_genl_policy,<br> .doit = guardian_exmpl_echo,<br> .dumpit = NULL,<br>};<br>
<br>static int __init gnKernel_init(void)<br>{<br> int rc;<br> printk("INIT GENERIC NETLINK EXEMPLE MODULE\n");<br><br> /*register new family*/<br> rc = genl_register_family(&doc_exmpl_gnl_family);<br>
if (rc != 0)<br> goto failure;<br><br> printk("genl_register_family passed\n");<br> /*register functions (commands) of the new family*/<br> rc = genl_register_ops(&doc_exmpl_gnl_family, &doc_exmpl_gnl_ops_echo);<br>
if (rc != 0){<br> printk("register ops: %i\n",rc);<br> genl_unregister_family(&doc_exmpl_gnl_family);<br> goto failure;<br> 135,2-16 71%<br>
}<br><br> printk("genl_register_ops passed\n");<br> return 0;<br><br> failure:<br> printk("an error occured while inserting the generic netlink example module\n");<br>
return -1;<br><br><br>}<br><br>static void __exit gnKernel_exit(void)<br>{<br> int ret;<br> printk("EXIT GENERIC NETLINK GUARDIAN EXEMPLE MODULE\n");<br> /*unregister the functions*/<br>
ret = genl_unregister_ops(&doc_exmpl_gnl_family, &doc_exmpl_gnl_ops_echo);<br> if(ret != 0){<br> printk("unregister ops: %i\n",ret);<br> return;<br> }<br>
/*unregister the family*/<br> ret = genl_unregister_family(&doc_exmpl_gnl_family);<br> if(ret !=0){<br> printk("unregister family %i\n",ret);<br> }<br>}<br><br><br>
module_init(gnKernel_init);<br>module_exit(gnKernel_exit);<br>MODULE_LICENSE("GPL");<br> <br>