Comment utiliser netlink socket pour communiquer avec un module du noyau?

Je suis en train d'écrire un module du noyau linux qui communique avec l'utilisateur processus à l'aide de netlink. Je suis, en utilisant netlink parce que le programme de l'utilisateur j'ai envie de communiquer pour communiquer uniquement à l'aide de sockets et je ne peux pas changer cela d'ajouter ioctl() ou quoi que ce soit.

Problème est que je ne peux pas comprendre comment le faire. J'ai googlé mais tous les exemples que j'ai trouvé sont pour les vieux comme cette une et n'est plus valable pour les actuelles versions du noyau. J'ai aussi regardé cette SORTE de question mais l'exemple ici utilise libnl pour les opérations de socket mais je veux m'en tenir à douille standard de fonctions (définies par sys/socket.h). Si certains ont un plz me guide ici pour un tutoriel ou guide ou quelque chose qui peut m'aider à comprendre l'interface et l'utilisation de netlink. Je serais très apprécier un exemple de travail, rien de compliqué, juste un exemple de base de la façon d'établir une connexion à partir d'une prise dans le programme utilisateur à un socket dans le noyau et puis envoyer les données de l'utilisateur processus d'amande et de recevoir en retour de noyau.

Aussi s'il vous plaît ne me dites pas de regarder le code du noyau. Je fais déjà, mais il faudra beaucoup de temps et je n'ai pas beaucoup de la gauche.

Mise à jour:
Après beaucoup d'essais et d'erreur que j'ai suivantes code qui envoie un message à partir du programme utilisateur à noyau, mais le message à partir du noyau de l'utilisateur, programme, que je.e à l'aide de netlink_unicast() ne fonctionne pas. Ce n'est pas seulement ne fonctionne pas, l'appel se bloque les systèmes et puis j'ai redémarrer la machine. Certains plz un prendre un coup d'oeil et me dire ce que de mal, je suis en train de faire. Le netlink_unicast() appel est commenté dans le code suivant. Il doit être retirée pour le noyau de programme utilisateur message.

Programme Utilisateur

#include <sys/socket.h>  
#include <linux/netlink.h>  
#define NETLINK_USER 31  
#define MAX_PAYLOAD 1024  /* maximum payload size*/  
struct sockaddr_nl src_addr, dest_addr;  
struct nlmsghdr *nlh = NULL;  
struct iovec iov;  
int sock_fd;  
struct msghdr msg;  
void main()  
{  
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);  
if(sock_fd<0)  
return -1;  
memset(&src_addr, 0, sizeof(src_addr));  
src_addr.nl_family = AF_NETLINK;  
src_addr.nl_pid = getpid();  /* self pid */  
/* interested in group 1<<0 */  
bind(sock_fd, (struct sockaddr*)&src_addr,  
sizeof(src_addr));  
memset(&dest_addr, 0, sizeof(dest_addr));  
memset(&dest_addr, 0, sizeof(dest_addr));  
dest_addr.nl_family = AF_NETLINK;  
dest_addr.nl_pid = 0;   /* For Linux Kernel */  
dest_addr.nl_groups = 0; /* unicast */  
nlh = (struct nlmsghdr *)malloc(  
NLMSG_SPACE(MAX_PAYLOAD));  
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));  
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);  
nlh->nlmsg_pid = getpid();  
nlh->nlmsg_flags = 0;  
strcpy(NLMSG_DATA(nlh), "Hello");  
iov.iov_base = (void *)nlh;  
iov.iov_len = nlh->nlmsg_len;  
msg.msg_name = (void *)&dest_addr;  
msg.msg_namelen = sizeof(dest_addr);  
msg.msg_iov = &iov;  
msg.msg_iovlen = 1;  
printf("Sending message to kernel\n");  
sendmsg(sock_fd,&msg,0);  
printf("Waiting for message from kernel\n");  
/* Read message from kernel */  
recvmsg(sock_fd, &msg, 0);  
printf(" Received message payload: %s\n",  
NLMSG_DATA(nlh));  
close(sock_fd);  
}

Code Du Noyau

#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/init.h>  
#include <net/sock.h>  
#include <linux/socket.h>  
#include <linux/net.h>  
#include <asm/types.h>  
#include <linux/netlink.h>  
#include <linux/skbuff.h>  
#define NETLINK_USER 31  
struct sock *nl_sk = NULL;  
static void hello_nl_recv_msg(struct sk_buff *skb)  
{
struct nlmsghdr *nlh;  
int pid;  
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);  
nlh=(struct nlmsghdr*)skb->data;  
printk(KERN_INFO "Netlink received msg payload: %s\n",
(char*)NLMSG_DATA(nlh));  
pid = nlh->nlmsg_pid; /*pid of sending process */  
NETLINK_CB(skb).dst_group = 0; /* not in mcast group */  
NETLINK_CB(skb).pid = 0;      /* from kernel */  
//NETLINK_CB(skb).groups = 0; /* not in mcast group */ 
//NETLINK_CB(skb).dst_pid = pid;  
printk("About to send msg bak:\n");  
//netlink_unicast(nl_sk,skb,pid,MSG_DONTWAIT);  
}  
static int __init hello_init(void)  
{  
printk("Entering: %s\n",__FUNCTION__);  
nl_sk=netlink_kernel_create(&init_net, NETLINK_USER, 0,
hello_nl_recv_msg, NULL, THIS_MODULE);  
if(!nl_sk)  
{   
printk(KERN_ALERT "Error creating socket.\n");  
return -10;  
}  
return 0;  
}  
static void __exit hello_exit(void)  
{
printk(KERN_INFO "exiting hello module\n");  
netlink_kernel_release(nl_sk);  
}  
module_init(hello_init);  
module_exit(hello_exit);  
  • Comment pourrait-10 personnes marque ce en tant que favori, mais seulement de 5 personnes upvote il?
  • Je sais que c'est un peu en retard, mais ce livre (ch 2) aborde également les sockets netlink: amazon.com/Linux-Kernel-Networking-Implementation-Experts/dp/...
  • ce programme utilisateur fonctionne en tant que struct msghdr msg; est défini dans la portée globale. Mais dès que j'ai déplacer qu'à l'intérieur d'une fonction (comme principale), le programme utilisateur ne fonctionne plus et sendmsg renvoie -1 et errno est positionnée à l'erreur 105 (ENOBUFS - pas de tampon de l'espace disponible). Quelqu'un peut-il expliquer pourquoi msghdr ne fonctionne que lorsqu'il est défini à l'échelle mondiale dans ce programme?
InformationsquelleAutor binW | 2010-07-21