2012年7月25日 星期三

Find process and send signal to it in Kernel

工作上覺得還蠻實用的程式片段。

struct task_struct *p;  
struct siginfo info;

pid_t pid = -1;

for_each_process(p) {
if (!strcmp(p->comm, "process name")){
pid = p->pid;
break;
}
}


if(pid != -1){

if(p != NULL) {
info.si_signo = SIGUSR1;
info.si_code = SI_QUEUE;
info.si_int = 0x3;
send_sig_info(SIGUSR1, &info, p);

printk(KERN_EMERG "Send SIGUSR1 with value %d to %s(%d)\n", info.si_int, "process name", pid);
}

}

Netlink 使用方法

Kernel Korner - Why and How to Use Netlink Socket這篇寫得非常好,關於netlink的使用方法,範例也非常簡潔易懂。

這裡就貼上關於不使用group方式process送訊息至kernel。

User Space

#include <sys/socket.h>
#include <linux/netlink.h>

#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;

void main() {
sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);

memset(&src_addr, 0, sizeof(src_addr));
src__addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
src_addr.nl_groups = 0; /* not in mcast groups */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_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));
/* Fill the netlink message header */
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid(); /* self pid */
nlh->nlmsg_flags = 0;
/* Fill in the netlink message payload */
strcpy(NLMSG_DATA(nlh), "Hello you!");

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;

sendmsg(fd, &msg, 0);

/* Read message from kernel */
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
recvmsg(fd, &msg, 0);
printf(" Received message payload: %s\n",
NLMSG_DATA(nlh));

/* Close Netlink Socket */
close(sock_fd);
}

Kernel Space

struct sock *nl_sk = NULL;

void nl_data_ready (struct sock *sk, int len)
{
wake_up_interruptible(sk->sleep);
}

void netlink_test() {
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh = NULL;
int err;
u32 pid;

nl_sk = netlink_kernel_create(NETLINK_TEST,
nl_data_ready);
/* wait for message coming down from user-space */
skb = skb_recv_datagram(nl_sk, 0, 0, &err);

nlh = (struct nlmsghdr *)skb->data;
printk("%s: received netlink message payload:%s\n",
__FUNCTION__, NLMSG_DATA(nlh));

pid = nlh->nlmsg_pid; /*pid of sending process */
NETLINK_CB(skb).groups = 0; /* not in mcast group */
NETLINK_CB(skb).pid = 0; /* from kernel */
NETLINK_CB(skb).dst_pid = pid;
NETLINK_CB(skb).dst_groups = 0; /* unicast */
netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
sock_release(nl_sk->socket);
}

2012年7月12日 星期四

ipv6 pton空字串

當inet_pton進一個空字串再反向inet_ntop回來時,值會變怎樣呢?
範例程式碼如下
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main()
{
    unsigned char a[16];
    char b[64] = "";
    char c[64] = "";
    
    
    inet_pton(PF_INET6, b, &a);
    inet_ntop(PF_INET6, b, c, sizeof(c));
    
    fprintf(stderr, "c is %s\n", c);
    
    return 0;
}

結果:
./ntop_test 
c is ::

2012.7.12更新
在這個範例中inet_pton轉換空字串其實是失敗的,並沒有寫入a中。
其實::的結果是c為空字串轉換回去的結果。