|
#include <linux/module.h> |
|
#include <linux/kernel.h> /* Needed for KERN_INFO */ |
|
|
|
#include <net/sock.h> |
|
#include <linux/netlink.h> |
|
#include <linux/skbuff.h> |
|
|
|
#define NETLINK_CHRIZ 25 |
|
|
|
struct sock *nl_sk = NULL; |
|
|
|
// ------------------------------------------------------------------ |
|
|
|
// upon receive, send back the received message |
|
static void chriz_nl_rcv(struct sk_buff *skb) |
|
{ |
|
struct nlmsghdr *nlh; // Netlink message header |
|
int pid = 0; |
|
|
|
struct sk_buff *skb_out; |
|
char *msg = NULL; |
|
char msg_len = 0; |
|
int ret = 0; |
|
|
|
// check received socket buffer: |
|
if (skb == NULL) |
|
{ |
|
printk(KERN_ERR "%s: socket buffer is empty...\n", __FUNCTION__); |
|
return; |
|
} |
|
|
|
// Print received message: |
|
nlh = (struct nlmsghdr *)skb->data; |
|
pid = nlh->nlmsg_pid; |
|
msg_len = strlen(NLMSG_DATA(nlh)); |
|
msg = NLMSG_DATA(nlh); |
|
printk(KERN_INFO "Received pid: %d, msg: %s, len: %d\n", pid, msg, msg_len); |
|
|
|
|
|
// Create a new socket buffer with received message copied: |
|
skb_out = nlmsg_new(msg_len, 0); |
|
if (skb_out == NULL) |
|
{ |
|
printk(KERN_ERR "%s: netlink new socket creation failed...\n", __FUNCTION__); |
|
return; |
|
} |
|
nlh = nlmsg_put(skb_out, 0, 0, 0, msg_len, 0); // flag 0, pid kernel 0, seq 0, payload msg_len, flags 0 |
|
strncpy(NLMSG_DATA(nlh), msg, msg_len); |
|
|
|
// Send back the message to app: |
|
ret = nlmsg_unicast(nl_sk, skb_out, pid); |
|
if (ret < 0) |
|
{ |
|
printk(KERN_ERR "%s: netlink unicast failed...\n", __FUNCTION__); |
|
return; |
|
} |
|
|
|
printk(KERN_INFO "%s: returned...", __FUNCTION__); |
|
|
|
} |
|
|
|
|
|
// ------------------------------------------------------------------ |
|
|
|
struct netlink_kernel_cfg cfg = { |
|
.input = chriz_nl_rcv, |
|
}; |
|
|
|
static int __init chriz_init_module(void) |
|
{ |
|
printk(KERN_INFO "chriz netlink module init... (%s)\n", __FUNCTION__); |
|
nl_sk = netlink_kernel_create(&init_net, NETLINK_CHRIZ, &cfg); |
|
if(nl_sk == NULL) |
|
{ |
|
printk(KERN_INFO "error creating netlink socket...\n"); |
|
return -1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static void __exit chriz_exit_module(void) |
|
{ |
|
netlink_kernel_release(nl_sk); |
|
printk(KERN_INFO "chriz netlink module exit... Goodbye!\n"); |
|
} |
|
|
|
module_init(chriz_init_module); |
|
module_exit(chriz_exit_module); |