Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1173976
  • 博文数量: 101
  • 博客积分: 110
  • 博客等级: 民兵
  • 技术积分: 1842
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-24 13:26
个人简介

专注linux

文章分类

全部博文(101)

文章存档

2017年(2)

2016年(12)

2015年(17)

2014年(41)

2013年(27)

2012年(3)

分类: LINUX

2015-09-15 14:24:33

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/socket.h>
  4. #include <linux/netlink.h>

  5. struct uevent {
  6.     const char *action;
  7.     const char *path;
  8.     const char *subsystem;
  9.     const char *firmware;
  10.     int major;
  11.     int minor;
  12. };

  13. static int open_uevent_socket(void)
  14. {
  15.     struct sockaddr_nl addr;
  16.     int sz = 64*1024; // XXX larger? udev uses
  17.     int on = 1;
  18.     int s;

  19.     memset(&addr, 0, sizeof(addr));
  20.     addr.nl_family = AF_NETLINK;
  21.     addr.nl_pid = getpid();
  22.     addr.nl_groups = 0xffffffff;

  23.     s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  24.     if(s < 0)
  25.         return -1;

  26.     setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
  27.     setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));

  28.     if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  29.         close(s);
  30.         return -1;
  31.     }

  32.     return s;
  33. }

  34. static void parse_event(const char *msg, struct uevent *uevent)
  35. {
  36. #if 1
  37.     uevent->action = "";
  38.     uevent->path = "";
  39.     uevent->subsystem = "";
  40.     uevent->firmware = "";
  41.     uevent->major = -1;
  42.     uevent->minor = -1;

  43.         /* currently ignoring SEQNUM */
  44.     while(*msg) {
  45.         printf("%s\n", msg);
  46.         if(!strncmp(msg, "ACTION=", 7)) {
  47.             msg += 7;
  48.             uevent->action = msg;
  49.         } else if(!strncmp(msg, "DEVPATH=", 8)) {
  50.             msg += 8;
  51.             uevent->path = msg;
  52.         } else if(!strncmp(msg, "SUBSYSTEM=", 10)) {
  53.             msg += 10;
  54.             uevent->subsystem = msg;
  55.         } else if(!strncmp(msg, "FIRMWARE=", 9)) {
  56.             msg += 9;
  57.             uevent->firmware = msg;
  58.         } else if(!strncmp(msg, "MAJOR=", 6)) {
  59.             msg += 6;
  60.             uevent->major = atoi(msg);
  61.         } else if(!strncmp(msg, "MINOR=", 6)) {
  62.             msg += 6;
  63.             uevent->minor = atoi(msg);
  64.         }

  65.             /* advance to after the next \0 */
  66.         while(*msg++)
  67.             ;
  68.     }

  69.     printf("event { '%s', '%s', '%s', '%s', %d, %d }\n",
  70.                     uevent->action, uevent->path, uevent->subsystem,
  71.                     uevent->firmware, uevent->major, uevent->minor);
  72. #endif
  73. }

  74. #define UEVENT_MSG_LEN 1024
  75. void handle_device_fd(int fd)
  76. {
  77.     printf("enter %s\n", __func__);
  78.     for(;;) {
  79.         char msg[UEVENT_MSG_LEN+2];
  80.         char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
  81.         struct iovec iov = {msg, sizeof(msg)};
  82.         struct sockaddr_nl snl;
  83.         struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};

  84.         ssize_t n = recvmsg(fd, &hdr, 0);
  85.         if (n <= 0) {
  86.             break;
  87.         }

  88.         if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
  89.             /* ignoring non-kernel netlink multicast message */
  90.             continue;
  91.         }

  92.         struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr);
  93.         if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
  94.             /* no sender credentials received, ignore message */
  95.             continue;
  96.         }

  97.         struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg);
  98.         if (cred->uid != 0) {
  99.             /* message from non-root user, ignore */
  100.             continue;
  101.         }

  102.         if(n >= UEVENT_MSG_LEN) /* overflow -- discard */
  103.             continue;

  104.         msg[n] = '\0';
  105.         msg[n+1] = '\0';

  106.         struct uevent uevent;
  107.         parse_event(msg, &uevent);
  108.     }
  109. }

  110. int main(void)
  111. {
  112.     int fd = 0;
  113.     
  114.     fd = open_uevent_socket();
  115.     if (fd < 0) {
  116.         printf("error!\n");
  117.         return -1;
  118.     }
  119.     
  120.     handle_device_fd(fd);
  121. }
阅读(1557) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~