1 #ifdef __linux__ /* only build on linux */
6 #include <sys/socket.h>
7 #include <linux/netlink.h>
8 #include <linux/connector.h>
9 #include <linux/cn_proc.h>
13 static VALUE cNetlinkHandler
;
14 static VALUE cEventHandler
;
19 static ID m_watching_pid
;
21 static int nl_sock
; /* socket for netlink connection */
27 char buff
[CONNECTOR_MAX_MSG_SIZE
];
29 struct proc_event
*event
;
34 FD_SET(nl_sock
, &fds
);
36 if (0 > rb_thread_select(nl_sock
+ 1, &fds
, NULL
, NULL
, NULL
)) {
37 rb_raise(rb_eStandardError
, strerror(errno
));
40 /* If there were no events detected, return */
41 if (! FD_ISSET(nl_sock
, &fds
)) {
45 /* if there are events, make calls */
46 if (-1 == recv(nl_sock
, buff
, sizeof(buff
), 0)) {
47 rb_raise(rb_eStandardError
, strerror(errno
));
50 hdr
= (struct nlmsghdr
*)buff
;
52 if (NLMSG_ERROR
== hdr
->nlmsg_type
) {
53 rb_raise(rb_eStandardError
, strerror(errno
));
54 } else if (NLMSG_DONE
== hdr
->nlmsg_type
) {
56 event
= (struct proc_event
*)((struct cn_msg
*)NLMSG_DATA(hdr
))->data
;
60 if (Qnil
== rb_funcall(cEventHandler
, m_watching_pid
, 1, INT2FIX(event
->event_data
.exit
.process_pid
))) {
64 rb_funcall(cEventHandler
, m_call
, 2, INT2FIX(event
->event_data
.exit
.process_pid
), ID2SYM(proc_exit
));
67 /* TODO: On fork, call and pass pid of child */
69 if (Qnil
== rb_funcall(cEventHandler
, m_watching_pid
, 1, INT2FIX(event
->event_data
.fork
.parent_pid
))) {
73 rb_funcall(cEventHandler
, m_call
, 2, INT2FIX(event
->event_data
.fork
.parent_pid
), ID2SYM(proc_fork
));
88 #define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
94 struct sockaddr_nl sa_nl
; /* netlink interface info */
95 char buff
[NL_MESSAGE_SIZE
];
96 struct nlmsghdr
*hdr
; /* for telling netlink what we want */
97 struct cn_msg
*msg
; /* the actual connector message */
99 /* connect to netlink socket */
100 nl_sock
= socket(PF_NETLINK
, SOCK_DGRAM
, NETLINK_CONNECTOR
);
103 rb_raise(rb_eStandardError
, strerror(errno
));
106 bzero(&sa_nl
, sizeof(sa_nl
));
107 sa_nl
.nl_family
= AF_NETLINK
;
108 sa_nl
.nl_groups
= CN_IDX_PROC
;
109 sa_nl
.nl_pid
= getpid();
111 if (-1 == bind(nl_sock
, (struct sockaddr
*)&sa_nl
, sizeof(sa_nl
))) {
112 rb_raise(rb_eStandardError
, strerror(errno
));
116 hdr
= (struct nlmsghdr
*)buff
;
117 hdr
->nlmsg_len
= NL_MESSAGE_SIZE
;
118 hdr
->nlmsg_type
= NLMSG_DONE
;
119 hdr
->nlmsg_flags
= 0;
121 hdr
->nlmsg_pid
= getpid();
124 msg
= (struct cn_msg
*)NLMSG_DATA(hdr
);
125 msg
->id
.idx
= CN_IDX_PROC
; /* Connecting to process information */
126 msg
->id
.val
= CN_VAL_PROC
;
129 msg
->len
= sizeof(int);
130 msg
->data
[0] = PROC_CN_MCAST_LISTEN
;
132 if (-1 == send(nl_sock
, hdr
, hdr
->nlmsg_len
, 0)) {
133 rb_raise(rb_eStandardError
, strerror(errno
));
138 Init_netlink_handler_ext()
140 proc_exit
= rb_intern("proc_exit");
141 proc_fork
= rb_intern("proc_fork");
142 m_call
= rb_intern("call");
143 m_watching_pid
= rb_intern("watching_pid?");
145 mGod
= rb_const_get(rb_cObject
, rb_intern("God"));
146 cEventHandler
= rb_const_get(mGod
, rb_intern("EventHandler"));
147 cNetlinkHandler
= rb_define_class_under(mGod
, "NetlinkHandler", rb_cObject
);
148 rb_define_singleton_method(cNetlinkHandler
, "handle_events", nlh_handle_events
, 0);
150 connect_to_netlink();