Kernel side code:
MODULE_LICENSE("GPL");
Make File:
$(MAKE) -C $(KERNELDIR) M=`pwd` clean
User side Code:
Send :
}
Receive :
}
Make file:
rm netlink-exam-user-recv netlink-exam-user-send
//kernel module: netlink-exam-kern.c |
#include <linux/module.h> |
#include <linux/netlink.h> |
#include <linux/sched.h> |
#include <net/sock.h> |
#include <linux/proc_fs.h> |
#include <linux/version.h> |
#define BUF_SIZE 16384 |
static struct sock *netlink_exam_sock; |
static unsigned char buffer[BUF_SIZE]; |
static unsigned int buffer_tail = 0; |
#define NETLINK_TEST 21 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) |
#define sk_sleep(sk) sk->sk_sleep |
#endif |
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
static void recv_handler(struct sk_buff *skb) |
{ |
struct nlmsghdr *nlhdr = (struct nlmsghdr *)skb->data; |
size_t len = 0; |
if (nlhdr->nlmsg_len < sizeof(struct nlmsghdr)) { |
printk("Corrupt netlink message.\n"); |
} |
len = nlhdr->nlmsg_len - NLMSG_LENGTH(0); |
if (len + buffer_tail > BUF_SIZE) { |
printk("netlink buffer is full.\n"); |
} |
else { |
memcpy(buffer + buffer_tail, NLMSG_DATA(nlhdr), len); |
buffer_tail += len; |
} |
} |
static int netlink_exam_readproc(char *page, char **start, off_t off, |
int count, int *eof, void *data) |
{ |
int len; |
if (off >= buffer_tail) { |
* eof = 1; |
return 0; |
} |
else { |
len = count; |
if (count > PAGE_SIZE) { |
len = PAGE_SIZE; |
} |
if (len > buffer_tail - off) { |
len = buffer_tail - off; |
} |
memcpy(page, buffer + off, len); |
*start = page; |
return len; |
} |
} |
static int __init netlink_exam_init(void) |
{ |
netlink_exam_sock = netlink_kernel_create(&init_net, NETLINK_TEST, 0, recv_handler, NULL, THIS_MODULE); |
if (!netlink_exam_sock) { |
printk("Fail to create netlink socket.\n"); |
return -1; |
} |
create_proc_read_entry("netlink_exam_buffer", 0444, NULL, netlink_exam_readproc, 0); |
return 0; |
} |
static void __exit netlink_exam_exit(void) |
{ |
wake_up(sk_sleep(netlink_exam_sock)); |
sock_release(netlink_exam_sock->sk_socket); |
remove_proc_entry("netlink_exam_buffer", NULL); |
} |
module_init(netlink_exam_init); |
module_exit(netlink_exam_exit); |
Make File:
mname :=file name |
$(mname)-objs := netlink-exam-kern.o |
obj-m := $(mname).o |
KERNELDIR := /lib/modules/`uname -r`/build |
all: |
$(MAKE) -C $(KERNELDIR) M=`pwd` modules |
clean: |
User side Code:
Send :
//application sender: netlink-exam-user-send.c |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <linux/netlink.h> |
#define MAX_MSGSIZE 1024 |
#define NETLINK_TEST 21 |
int main(int argc, char * argv[]) |
{ |
FILE * fp; |
struct sockaddr_nl saddr, daddr; |
struct nlmsghdr *nlhdr = NULL; |
struct msghdr msg; |
struct iovec iov; |
int sd; |
char text_line[MAX_MSGSIZE]; |
int ret = -1; |
if (argc < 2) { |
printf("Usage: %s atextfilename\n", argv[0]); |
exit(1); |
} |
if ((fp = fopen(argv[1], "r")) == NULL) { |
printf("File %s dosen't exist.\n", argv[1]); |
exit(1); |
} |
sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST); |
if (sd == -1) { |
printf("Cannot create netlink\n"); |
exit(1); |
} |
memset(&saddr, 0, sizeof(saddr)); |
memset(&daddr, 0, sizeof(daddr)); |
saddr.nl_family = AF_NETLINK; |
saddr.nl_pid = getpid(); |
saddr.nl_groups = 11; |
bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)); |
daddr.nl_family = AF_NETLINK; |
daddr.nl_pid = 0; |
daddr.nl_groups = 1; |
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE)); |
while (fgets(text_line, MAX_MSGSIZE, fp)) { |
memcpy(NLMSG_DATA(nlhdr), text_line, strlen(text_line)); |
memset(&msg, 0 ,sizeof(struct msghdr)); |
nlhdr->nlmsg_len = NLMSG_LENGTH(strlen(text_line)); |
nlhdr->nlmsg_pid = getpid(); /* self pid */ |
nlhdr->nlmsg_flags = 0; |
iov.iov_base = (void *)nlhdr; |
iov.iov_len = nlhdr->nlmsg_len; |
msg.msg_name = (void *)&daddr; |
msg.msg_namelen = sizeof(daddr); |
msg.msg_iov = &iov; |
msg.msg_iovlen = 1; |
ret = sendmsg(sd, &msg, 0); |
if (ret == -1) { |
perror("sendmsg error:"); |
} |
} |
close(sd); |
Receive :
//application receiver: netlink-exam-user-recv.c |
#include <stdio.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <linux/netlink.h> |
#include <string.h> |
#include <stdlib.h> |
#define MAX_MSGSIZE 1024 |
#define NETLINK_TEST 21 |
int main(void) |
{ |
struct sockaddr_nl saddr, daddr; |
struct nlmsghdr *nlhdr = NULL; |
struct msghdr msg; |
struct iovec iov; |
int sd; |
int ret = 1; |
sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST); |
if (sd == -1) { |
printf("cannot create netlink\n"); |
exit(-1); |
} |
memset(&saddr, 0, sizeof(saddr)); |
memset(&daddr, 0, sizeof(daddr)); |
saddr.nl_family = AF_NETLINK; |
saddr.nl_pid = getpid(); |
saddr.nl_groups = 11; |
bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)); |
nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE)); |
while (1) { |
memset(nlhdr, 0, NLMSG_SPACE(MAX_MSGSIZE)); |
iov.iov_base = (void *)nlhdr; |
iov.iov_len = NLMSG_SPACE(MAX_MSGSIZE); |
msg.msg_name = (void *)&daddr; |
msg.msg_namelen = sizeof(daddr); |
msg.msg_iov = &iov; |
msg.msg_iovlen = 1; |
ret = recvmsg(sd, &msg, 0); |
if (ret == 0) { |
printf("Exit.\n"); |
exit(0); |
} |
else if (ret == -1) { |
perror("recvmsg:"); |
exit(1); |
} |
printf("%s", (char *)NLMSG_DATA(nlhdr)); |
} |
close(sd); |
Make file:
.PHONY: clean |
all: |
gcc netlink-exam-user-recv.c -o netlink-exam-user-recv |
gcc netlink-exam-user-send.c -o netlink-exam-user-send |
clean: |
No comments:
Post a Comment