Netlink 예제프로그램에서 전송 실패...

junee74의 이미지

netlink를 이용하여 kernel<->user간 테스트 프로그램을 작성해 보고 있습니다.
주로 kernel에서 메시지를 뿌리고, user에서 받기만 할 예정입니다.
왜 kernel에서 계속해서 메시지 전송을 실패하는지 이유를 모르겠습니다.

제가 작성한 테스트 코드는 다음과 같습니다.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/kthread.h>
 
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
 
#include <linux/netlink.h>
#include <net/netlink.h>
 
#include "netlink.h"
 
#define NETLINK_PROTOCOL		31
#define NETLINK_TYPE			SOCK_RAW
#define NETLINK_GROUP		4
#define MAX_PAYLOAD			1024
 
struct sock *nl_sock = 0;
int seq_id=0;
struct task_struct *my_task = NULL;
 
static int netlink_test(int index)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
	unsigned char *data;
	int ret;
 
	printk("%4d allocation sk_buff\n", index);
	skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD), GFP_KERNEL);
	if(skb == NULL)
	{
		printk("fail to alloc sk_buff\n");
		return -1;
	}
 
	printk("NLMSG_SPACE(MAX_PAYLOAD)=%d\n", NLMSG_SPACE(MAX_PAYLOAD));
	printk("skb->len=%d\n", skb->len);
 
#if 1
 
//	nlh = (struct nlmsghdr *)skb->data;
	nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD));
	data = NLMSG_DATA(nlh);
	printk("skb->len=%d\n", skb->len);
 
	nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
	nlh->nlmsg_type = 0;
	nlh->nlmsg_flags = 0;
	nlh->nlmsg_seq = 0;
	nlh->nlmsg_pid = 0; // from kerenel
 
	printk("copy data\n");
	strcpy(data, "Notify Message from kernel!!!!");
 
	NETLINK_CB(skb).dst_group = 1;
 
	/*
	int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
		      u32 group, gfp_t allocation)
	 */
 
	printk("broad casting\n");
	ret = netlink_broadcast(nl_sock, skb, 0, 1, GFP_KERNEL);
	if(ret)
	{
		printk("fail to send kernel->user\n=%d\n", ret);
	}
 
#endif
 
//	kfree_skb(skb);
 
 
	return ret;
}
 
static void netlink_recv(struct sk_buff *skb)
{
}
 
static int netlink_init(void)
{
	int i = NETLINK_KOBJECT_UEVENT;
	printk("create netlink socket\n");
	nl_sock = netlink_kernel_create(&init_net, 31, 1, netlink_recv, NULL, THIS_MODULE);
	if(nl_sock == NULL)
	{
		printk("fail to create netlink socket\n");
		return -1;
	}
	netlink_set_nonroot(31, NL_NONROOT_RECV);
	return 0;
}
 
static int netlink_close(void)
{
	printk("close netlink socket\n");
	netlink_kernel_release(nl_sock);
	return 0;
}
 
static int thread_proc(void *unused)
{
//	DECLARE_WAITQUEUE(wait, current);
	int thread_proc_count = 0;
//	int i;
 
	msleep(100);
 
	printk("thread start\n");
 
	while(!kthread_should_stop())
	{
		thread_proc_count++;
		printk("thread processing %d\n", thread_proc_count);
		netlink_test(thread_proc_count);
		msleep(1000);
	}
 
	printk("set current state TASK_RUNNING\n");
//	__set_current_state(TASK_RUNNING);
 
	printk("remove wait queue\n");
//	remove_wait_queue(&thread_proc_wait, &wait);
 
	return 0;
}
 
static int thread_start(void)
{
	my_task = kthread_create(thread_proc, NULL, "%s", "my_thread");
	if(my_task)
	{
		printk("thread start complete\n");
		wake_up_process(my_task);
//		wake_up(my_task);
	}
	return 0;
}
 
static int thread_terminate(void)
{
	if(my_task) kthread_stop(my_task);
	return 0;
}
 
int test_init(void)
{
	int ret = 0;
 
	printk("\n\n\n");
	printk("Module Init\n");
 
	printk("netlink init\n");
	netlink_init();
	printk("thread init\n");
	thread_start();
 
	/*
	 {
	 int i;
	 for(i=0; i<100; i++)
	 {
	 netlink_test(i);
	 msleep(1000);
	 }
	 }
	 */
 
	return ret;
}
 
void test_exit(void)
{
	printk("netlink close\n");
	netlink_close();
	printk("thread terminate\n");
	thread_terminate();
	printk("Module Exit\n");
}
 
module_init(test_init);
module_exit(test_exit);
 
//MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL");

실행 결과는 다음과 같습니다.

Module Init
netlink init
create netlink socket
thread init
thread start complete
thread start
thread processing 1
[   1] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 2
[   2] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 3
[   3] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 4
[   4] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 5
[   5] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 6
[   6] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 7
[   7] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 8
[   8] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 9
[   9] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 10
[  10] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 11
[  11] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 12
[  12] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 13
[  13] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
thread processing 14
[  14] allocation sk_buff
NLMSG_SPACE(MAX_PAYLOAD)=1040
skb->len=0
skb->len=1040
copy data
broad casting
fail to send kernel->user
=-3
netlink close
close netlink socket
thread terminate
set current state TASK_RUNNING
remove wait queue
Module Exit
wariua의 이미지

netlink_broadcast()에서 반환한 에러 코드가 -3입니다. /usr/include/asm-generic/errno-base.h를 보면 3은 ESRCH입니다.

~linux/net/netlink에서 ESRCH로 grep 해보면 한 군데가 잡히는데, netlink_broadcast_filtered()의 마지막 부분입니다.

그런데 info.delivered가 참이면 -ESRCH가 아니라 0을 반환합니다. 즉, 잘 전달했으면 0을 반환하고, (다른 심각한 오류가 발생한 건 아니지만) 전달은 안 됐으면 -ESRCH를 반환하는 거라고 추측할 수 있습니다.

자, 그래서... 현재 메시지를 받으려고 귀를 쫑긋 기울이고 있는 사용자 프로세스가 있는 상태인가요?

한편 커널의 다른 부분에서 netlink_broadcast()를 사용할 때 반환값을 어떻게 다루는지도 참고하실 수 있겠습니다.

$PWD `date`

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.