1 #ifdef __linux__ /* only build on linux */
5 #include <sys/socket.h>
6 #include <linux/netlink.h>
7 #include <linux/connector.h>
8 #include <linux/cn_proc.h>
11 static VALUE cNetlinkHandler
;
12 static VALUE cEventHandler
;
18 static ID m_watching_pid
;
20 static int nl_sock
; /* socket for netlink connection */
26 char buff
[CONNECTOR_MAX_MSG_SIZE
];
28 struct proc_event
*event
;
33 FD_SET(nl_sock
, &fds
);
35 if (0 > select(nl_sock
+ 1, &fds
, NULL
, NULL
, NULL
)) {
36 rb_raise(rb_eStandardError
, strerror(errno
));
39 /* If there were no events detected, return */
40 if (! FD_ISSET(nl_sock
, &fds
)) {
44 /* if there are events, make calls */
45 if (-1 == recv(nl_sock
, buff
, sizeof(buff
), 0)) {
46 rb_raise(rb_eStandardError
, strerror(errno
));
49 hdr
= (struct nlmsghdr
*)buff
;
51 if (NLMSG_ERROR
== hdr
->nlmsg_type
) {
52 rb_raise(rb_eStandardError
, strerror(errno
));
53 } else if (NLMSG_DONE
== hdr
->nlmsg_type
) {
55 event
= (struct proc_event
*)((struct cn_msg
*)NLMSG_DATA(hdr
))->data
;
59 if (Qnil
== rb_funcall(cEventHandler
, m_watching_pid
, 1, INT2FIX(event
->event_data
.exit
.process_pid
))) {
63 rb_funcall(cEventHandler
, m_call
, 2, INT2FIX(event
->event_data
.exit
.process_pid
), ID2SYM(proc_exit
));
66 /* TODO: On fork, call and pass pid of child */
68 if (Qnil
== rb_funcall(cEventHandler
, m_watching_pid
, 1, INT2FIX(event
->event_data
.fork
.parent_pid
))) {
72 rb_funcall(cEventHandler
, m_call
, 2, INT2FIX(event
->event_data
.fork
.parent_pid
), ID2SYM(proc_fork
));
81 #define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
87 struct sockaddr_nl sa_nl
; /* netlink interface info */
88 char buff
[NL_MESSAGE_SIZE
];
89 struct nlmsghdr
*hdr
; /* for telling netlink what we want */
90 struct cn_msg
*msg
; /* the actual connector message
92 /* connect to netlink socket */
93 nl_sock
= socket(PF_NETLINK
, SOCK_DGRAM
, NETLINK_CONNECTOR
);
95 bzero(sa_nl
, sizeof(sa_nl
));
96 sa_nl
.nl_family
= AF_NETLINK
;
97 sa_nl
.nl_groups
= CN_IDX_PROC
;
98 sa_nl
.nl_pid
= getpid();
100 bind(nl_sock
, (struct sockaddr
*)&sa_nl
, sizeof(sa_nl
));
103 hdr
= (struct nlmsghdr
*)buff
;
104 hdr
->nlmsg_len
= NL_MESSAGE_SIZE
;
105 hdr
->nlmsg_type
= NLMSG_DONE
;
106 hdr
->nlmsg_flags
= 0;
108 hdr
->nlmsg_pid
= getpid();
111 msg
= (struct cn_msg
*)NLMSG_DATA(hdr
);
112 msg
->id
.idx
= CN_IDX_PROC
; /* Connecting to process information */
113 msg
->id
.val
= CN_VAL_PROC
;
116 msg
->len
= sizeof(int);
117 msg
->data
[0] = PROC_CN_MCAST_LISTEN
;
119 if (-1 == send(nl_sock
, hdr
, hdr
->nlmsg_len
, 0)) {
120 rb_raise(rb_eStandardError
, strerror(errno
));
125 Init_netlink_handler_ext()
127 proc_exit
= rb_intern("proc_exit");
128 proc_fork
= rb_intern("proc_fork");
129 m_call
= rb_intern("call");
130 m_watching_pid
= rb_intern("watching_pid?");
132 mGod
= rb_const_get(rb_cObject
, rb_intern("God"));
133 cEventHandler
= rb_const_get(mGod
, rb_intern("EventHandler"));
134 cNetlinkHandler
= rb_define_class_under(mGod
, "NetlinkHandler", rb_cObject
);
135 rb_define_singleton_method(cNetlinkHandler
, "handle_events", nlh_handle_events
, 0);
137 connect_to_netlink();