Merge remote-tracking branch 'tizen.org/sandbox/kopasiak/event_fw'
authorŁukasz Stelmach <l.stelmach@samsung.com>
Wed, 26 Apr 2017 17:46:23 +0000 (19:46 +0200)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Wed, 26 Apr 2017 17:46:23 +0000 (19:46 +0200)
Conflicts:
Makefile.am
src/log.c

1  2 
Makefile.am
src/core/module.c
src/event.h
src/event_processor.c
src/event_types/decision_made_event.h
src/event_types/resource_violation_event.c
src/event_types/resource_violation_event.h
src/listeners/audit.c
src/listeners/systemd.c
src/log.c
src/service.c

diff --cc Makefile.am
index 0a4bbeae48e2ed312ac93d002a4b4fe43054f266,efd29802515c679c161eb6f746231e43b84c77e5..b91d67f7381a4f4efa832d77c1a0eadf85dd0764
@@@ -28,9 -32,16 +32,17 @@@ SED_PROCESS = 
  
  sbin_PROGRAMS = faultd
  faultd_SOURCES = \
-     src/audit.c \
      src/faultd.c \
      src/log.c \
-     src/systemd.c \
 +    src/util.c
+     src/core/module.c \
+     src/core/notify_queue.c \
+     src/listeners/systemd.c \
+     src/listeners/audit.c \
+     src/event.c \
+     src/service.c \
+     src/event_types/decision_made_event.c \
+     src/event_types/resource_violation_event.c \
+     src/decision_makers/rv_dm.c \
+     src/event_processor.c
  faultd_LDADD = $(LIBSYSTEMD_LIBS) ${AUDIT_LIBS}
index 0000000000000000000000000000000000000000,04fd49fde59c9b1be2c41d49db9152a4f5192e9b..b1837ce223eec902c387f6ecdd77d82e0689d7a2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,111 +1,111 @@@
 -                
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #include <errno.h>
+ #include "module.h"
+ #include "log.h"
+ #include "common.h"
+ static struct list_head modules[FAULTD_MODULE_TYPE_MAX];
+ static void init_heads(void)
+ {
+         unsigned i;
+         for (i = 0; i < ARRAY_SIZE(modules); ++i)
+                 INIT_LIST_HEAD(modules + i);
+ }
+ int faultd_module_register(struct faultd_module *module)
+ {
+         if (!module->name || !module->init) {
+                 log_error("Missing module name or init()");
+                 return -EINVAL;
+         }
 -                        
++
+         if (!modules[0].next)
+                 init_heads();
+         list_add_tail(&module->node, modules + module->type);
+         return 0;
+ }
+ void faultd_module_unregister(struct faultd_module *module)
+ {
+         list_del(&module->node);
+ }
+ int faultd_modules_init(sd_event *event_loop)
+ {
+         struct faultd_module *module, *module_to_clean;
+         int i;
+         int ret = 0;
+         if (!modules[0].next)
+                 init_heads();
+         for (i = 0; i < (int)(ARRAY_SIZE(modules)); ++i) {
+                 log_debug("Initializing modules category %d", i);
+                 list_for_each_entry(module, modules + i, node) {
+                         log_debug("Initializing %s module", module->name);
 -        
++
+                         ret = module->init(module, event_loop);
+                         if (ret)
+                                 goto err_cleanup;
+                 }
+         }
+         return 0;
+ err_cleanup:
+         for (; i >= 0; --i) {
+                 log_debug("Cleaning up modules category %d", i);
+                 /* From first element of the list... */
+                 for (module_to_clean = list_first_entry(modules + i,
+                                                         struct faultd_module,
+                                                         node);
+                      /* iterate as long as modules has been initialized */
+                      module_to_clean != module &&
+                              &module_to_clean->node != (modules + i);
+                      /* move to next one */
+                      module_to_clean = list_next_entry(module_to_clean, node)) {
+                         log_debug("Cleaning up %s module",
+                                   module_to_clean->name);
+                         module_to_clean->cleanup(module_to_clean);
+                 }
+         }
 -                        
++
+         return ret;
+ }
+ void faultd_modules_cleanup()
+ {
+         struct faultd_module *module;
+         int i;
+         for (i = FAULTD_MODULE_TYPE_MAX - 1; i >= 0; --i) {
+                 log_debug("Cleaning up modules category %d", i);
+                 list_for_each_entry(module, modules + i, node) {
+                         log_debug("Cleaning up %s module", module->name);
 -                }              
++
+                         module->cleanup(module);
++                }
+         }
+ }
diff --cc src/event.h
index 0000000000000000000000000000000000000000,59846e0bc9747960c01e636009180695d0e02d86..d3cd68d15a61b335932ba36f104cb2a6a79f7aeb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,120 +1,119 @@@
 -        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #ifndef FAULTD_EVENT_H
+ #define FAULTD_EVENT_H
+ #include <time.h>
+ #include <string.h>
+ #include "uref.h"
+ #include "list.h"
+ #include "notify_queue.h"
+ #include "module.h"
+ struct faultd_event;
+ struct faultd_event_ops {
+         char *(*to_string)(struct faultd_event *);
+         void (*release)(struct faultd_event *);
+ };
+ struct faultd_event_type {
+         char *name;
+         struct faultd_event_ops default_ops;
+         /* Add function to allocate event from DB */
+         /* Allocate event based on passed data */
+         int (*allocate_event)(struct faultd_event_type *type,
+                               void *data, struct faultd_event **);
+         /* To be used by event factory */
+         struct list_head node;
+ };
+ struct faultd_event {
+         struct timespec timestamp;
+         /* TODO: add here some id field */
+         struct faultd_event_type *type;
+         struct faultd_event_ops ops;
+         struct uref uref;
+         /* To be used by event holder */
+         struct list_head node;
+         /* To be used by event processig FW */
+         struct nqueue_node nq_node;
+ };
+ int faultd_event_type_register(struct faultd_event_type *type);
+ void faultd_event_type_unregister(struct faultd_event_type *type);
+ #define FAULTD_EVENT_TYPE_REGISTER(EVENT_TYPE, NAME)                    \
+ static int event_type_ ##NAME## _init(struct faultd_module *module,     \
+                                      sd_event *event_loop)              \
+ {                                                                       \
+         return faultd_event_type_register(&EVENT_TYPE);                 \
+ }                                                                       \
+                                                                         \
+ static void event_type_ ##NAME## _cleanup(struct faultd_module *module) \
+ {                                                                       \
+         faultd_event_type_unregister(&EVENT_TYPE);                      \
+ }                                                                       \
+                                                                         \
+ static struct faultd_module event_type_ ##NAME## _module = {            \
+         .name = #NAME,                                                  \
+         .type = FAULTD_MODULE_TYPE_EVENT,                               \
+         .init = event_type_ ##NAME## _init,                             \
+         .cleanup = event_type_ ##NAME## _cleanup,                       \
+         .node = LIST_HEAD_INIT(event_type_ ##NAME## _module.node),      \
+ };                                                                      \
+                                                                         \
+ FAULTD_MODULE_REGISTER(&event_type_ ##NAME## _module)
+ int faultd_event_create(const char *type, void *data, struct faultd_event **ev);
+ static inline void faultd_event_get(struct faultd_event *ev)
+ {
+         uref_get(&ev->uref);
+ }
+ static inline void faultd_event_put(struct faultd_event *ev)
+ {
+         uref_put(&ev->uref);
+ }
+ static inline int faultd_event_is_of_type(struct faultd_event *ev,
+                                           const char *type)
+ {
+         return strcmp(ev->type->name, type) == 0;
+ }
+ static inline char *faultd_event_to_string(struct faultd_event *ev)
+ {
+         return ev->ops.to_string(ev);
+ }
+ int faultd_event_init(struct faultd_event_type *ev_type,
+                       struct faultd_event *ev);
+ static inline void faultd_event_cleanup(struct faultd_event *ev) {}
+ #endif /* FAULTD_EVENT_H */
index 0000000000000000000000000000000000000000,64a790629070d53ee569858532b2c1523f6e0a31..b5594efa63bb083183ab718bcbab82363c5b7c24
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,197 +1,197 @@@
 -        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #include <errno.h>
+ #include "event_processor.h"
+ #include "log.h"
+ struct event_processor {
+         struct faultd_module module;
+         struct nqueue_head pending_events;
+         struct sd_event_source *pending_events_sd_source;
+         struct list_head event_handlers;
+         sd_event *loop;
+ };
+ #define to_event_processor(MOD) \
+         container_of(MOD, struct event_processor, module)
+ /* called each time when new event arrived */
+ static int event_processor_callback(sd_event_source *s,
+                                     int fd, uint32_t revents, void *userdata)
+ {
+         struct event_processor *eprocessor = userdata;
+         struct faultd_event *ev = nqueue_pop(&eprocessor->pending_events,
+                                              struct faultd_event, nq_node);
+         struct faultd_event_handler *handler;
+         /* TODO: Here is a good place to put our event into DB */
+         {
+                 char *str = faultd_event_to_string(ev);
+                 log_debug("New event arrived: %s", str);
+                 free(str);
+         }
+         list_for_each_entry(handler, &eprocessor->event_handlers, node) {
+                 if (handler->event_match(handler, ev)) {
+                         nqueue_append(&handler->event_queue, &ev->nq_node);
+                         ev = NULL;
+                 }
+         }
+         if (ev) {
+                 log_error("No handler for event found");
+                 faultd_event_put(ev);
+         }
 -        
++
+         return 0;
+ }
+ static int event_processor_init(struct faultd_module *module, sd_event *event)
+ {
+         struct event_processor *eprocessor = to_event_processor(module);
+         int ret;
+         ret = init_notify_queue_head(&eprocessor->pending_events);
+         if (ret)
+                 return ret;
+         ret = sd_event_add_io(event, &eprocessor->pending_events_sd_source,
+                               eprocessor->pending_events.fd, EPOLLIN,
+                               event_processor_callback, eprocessor);
+         if (ret)
+                 goto cleanup_queue;
+         eprocessor->loop = event;
+         return 0;
+ cleanup_queue:
+         cleanup_notify_queue_head(&eprocessor->pending_events);
+         return ret;
+ }
+ static void event_processor_cleanup(struct faultd_module *module)
+ {
+         struct event_processor *eprocessor = to_event_processor(module);
+         int ret;
+         /* We log errors but go forward to cleanup everything we can */
+         ret = sd_event_source_set_enabled(eprocessor->pending_events_sd_source,
+                                           SD_EVENT_OFF);
+         if (ret < 0)
+                 log_error("Could not disable queue event source %d", ret);
+         sd_event_source_unref(eprocessor->pending_events_sd_source);
+         /* TODO: What to do with unhandled events? */
+         while (!nqueue_empty(&eprocessor->pending_events)) {
+                 struct faultd_event *ev = nqueue_pop(&eprocessor->pending_events,
+                                                      struct faultd_event,
+                                                      nq_node);
+                 char *str = faultd_event_to_string(ev);
+                 log_error("Unhandled event: %s", str);
+                 free(str);
+                 faultd_event_put(ev);
+         }
+ }
+ struct event_processor event_processor = {
+         .module = {
+                 .name = "event_processor",
+                 .type = FAULTD_MODULE_TYPE_CORE,
+                 .init = event_processor_init,
+                 .cleanup = event_processor_cleanup,
+                 .node = LIST_HEAD_INIT(event_processor.module.node),
+         },
+         /* pending_events will be initialized in init() */
+         .event_handlers = LIST_HEAD_INIT(event_processor.event_handlers),
+ };
+ FAULTD_MODULE_REGISTER(&event_processor.module);
+ int event_processor_report_event(struct faultd_event *ev)
+ {
+         return nqueue_append(&event_processor.pending_events,
+                              &ev->nq_node);
+ }
+ static int event_processor_handler_callback(sd_event_source *s, int fd,
+                                             uint32_t revents, void *userdata)
+ {
+         struct faultd_event_handler *handler = userdata;
+         return handler->handle_event(handler);
+ }
+ int event_processor_handler_register(struct faultd_event_handler *handler)
+ {
+         int ret;
+         if (!handler->event_match || handler->handle_event)
+                 return -EINVAL;
+         ret = init_notify_queue_head(&handler->event_queue);
+         if (ret)
+                 return ret;
+         ret = sd_event_add_io(event_processor.loop,
+                               &handler->event_queue_sd_source,
+                               handler->event_queue.fd, EPOLLIN,
+                               event_processor_handler_callback, handler);
+         if (ret)
+                 goto cleanup_queue;
+         list_add_tail(&handler->node, &event_processor.event_handlers);
++
+         return 0;
+ cleanup_queue:
+         cleanup_notify_queue_head(&handler->event_queue);
+         return ret;
+ }
+ void event_processor_handler_unregister(struct faultd_event_handler *handler)
+ {
+         int ret;
+         /* We log errors but go forward to cleanup everything we can */
+         ret = sd_event_source_set_enabled(handler->event_queue_sd_source,
+                                           SD_EVENT_OFF);
+         if (ret < 0)
+                 log_error("Could not disable queue event source %d", ret);
+         sd_event_source_unref(handler->event_queue_sd_source);
+         /* TODO: What to do with unhandled events? */
+         while (!nqueue_empty(&handler->event_queue)) {
+                 struct faultd_event *ev = nqueue_pop(&event_processor.pending_events,
+                                                      struct faultd_event,
+                                                      nq_node);
+                 char *str = faultd_event_to_string(ev);
+                 log_error("Unhandled event: %s", str);
+                 free(str);
+                 faultd_event_put(ev);
+         }
+         list_del(&handler->node);
+ }
index 0000000000000000000000000000000000000000,c6fd8271f5d6ddb0a5e7264a189474b009721865..4efa1d87131110b6ccd05eb37f86f4d31ba03c79
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,54 +1,54 @@@
 -        void (*action_data_release)(void *);        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #ifndef FAULTD_DECISION_MADE_EVENT_H
+ #define FAULTD_DECISION_MADE_EVENT_H
+ #include <time.h>
+ #include "action.h"
+ #include "event.h"
+ #include "common.h"
+ #define DECISION_MADE_EVENT_ID "decision_made"
+ struct decision_made_event {
+         struct faultd_event event;
+         struct faultd_event *reason;
+         char *who_made;
+         char *action;
+         void *action_data;
+         void (*action_data_release)(void *);
+         /* TODO: what more do we need? */
+ };
+ struct dm_event_data {
+         /* This is referenced by dm event */
+         struct faultd_event *reason;
+         /* Strings are deep copied */
+         char *who_made;
+         char *action;
+         /* Action data is shallow copied */
+         void *action_data;
 -        
++        void (*action_data_release)(void *);
+ };
++
+ #define to_decision_made_event(EVENT)      \
+         container_of(EVENT, struct decision_made_event, event)
+ #endif /* FAULTD_DECISION_MADE_EVENT_H */
index 0000000000000000000000000000000000000000,90deeb1a9dcc8127263fc59927b830a8120bf036..f57ddcebb22fc576b8f34d468c2a7f6b49034efc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,94 +1,93 @@@
 -        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #define _GNU_SOURCE 1
+ #include <stdio.h>
+ #include <errno.h>
+ #include <malloc.h>
+ #include "resource_violation_event.h"
+ static int allocate_rv_event(struct faultd_event_type *type,
+                              void *data, struct faultd_event **ev)
+ {
+         struct resource_violation_event *rv_ev;
+         struct rv_event_data *rv_ev_data = data;
+         int ret;
+         rv_ev = malloc(sizeof(*rv_ev));
+         if (!rv_ev)
+                 return -ENOMEM;
+         ret = faultd_event_init(type, &rv_ev->event);
+         if (ret)
+                 goto free_rv_ev;
+         rv_ev->service = rv_ev_data->service;
+         rv_ev->detection_time = rv_ev_data->detection_time;
+         rv_ev->resource_type = rv_ev_data->resource_type;
+         return 0;
+ free_rv_ev:
+         free(rv_ev);
+         return ret;
+ }
+ static void rv_event_release(struct faultd_event *ev)
+ {
+         struct resource_violation_event *rv_ev =
+                 to_resource_violation_event(ev);
+         system_service_cleanup(&rv_ev->service);
+         faultd_event_cleanup(&rv_ev->event);
+         free(rv_ev);
+ }
+ static char *rv_event_to_string(struct faultd_event *ev)
+ {
+         struct resource_violation_event *rv_ev =
+                 to_resource_violation_event(ev);
+         char *str;
+         int ret;
+         /* TODO print other fields */
+         ret = asprintf(&str, "Resource Violation Event:"
+                        " Time: %lld.%.9ld"
+                        " Service: pid: %d, name %s"
+                        " Resource type: %d",
+                        (long long)rv_ev->event.timestamp.tv_sec,
+                        rv_ev->event.timestamp.tv_nsec,
+                        rv_ev->service.pid,
+                        rv_ev->service.name,
+                        rv_ev->resource_type);
+         return ret > 0 ? str : NULL;
+ }
+ static struct faultd_event_type resource_violation_event_type = {
+         .name = RESOURCE_VIOLATION_EVENT_ID,
+         .default_ops = {
+                 .to_string = rv_event_to_string,
+                 .release = rv_event_release,
+         },
+         .allocate_event = allocate_rv_event,
+         .node = LIST_HEAD_INIT(resource_violation_event_type.node),
+ };
+ FAULTD_EVENT_TYPE_REGISTER(resource_violation_event_type, resource_violation_et)
index 0000000000000000000000000000000000000000,5632c4d78a342e5d8768d50888b05f3c3bf76b80..7dd20c0a022c4db535f255aca58cd2719253f55c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,52 +1,52 @@@
 -        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #ifndef FAULTD_RESOURCE_VIOLATION_EVENT_H
+ #define FAULTD_RESOURCE_VIOLATION_EVENT_H
+ #include <time.h>
+ #include "event.h"
+ #include "common.h"
+ #include "service.h"
+ #define RESOURCE_VIOLATION_EVENT_ID "resource_violation"
+ enum resource_type {
+         FAULTD_RESOURCE_FD,
+         FAULTD_RESOURCE_MEM
+ };
+ struct resource_violation_event {
+         struct faultd_event event;
+         struct system_service service;
+         time_t detection_time;
+         enum resource_type resource_type;
+         /* TODO: what more do we need? */
+ };
+ struct rv_event_data {
+         struct system_service service;
+         time_t detection_time;
+         enum resource_type resource_type;
+ };
++
+ #define to_resource_violation_event(EVENT)      \
+         container_of(EVENT, struct resource_violation_event, event)
+ #endif /* FAULTD_RESOURCE_VIOLATION_EVENT_H */
index 0000000000000000000000000000000000000000,a00eff35206130210345e799287759e2c2fa0b89..70f7ba2395cafb41999fe4e1eba44808ba6004b8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,252 +1,252 @@@
 -        
+ /*
+  * This file is a part of faultd.
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #define _GNU_SOURCE 1
+ #include <errno.h>
+ #include <libaudit.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <systemd/sd-event.h>
+ #include <unistd.h>
+ #include "log.h"
+ #include "module.h"
+ #include "event.h"
+ #include "event_processor.h"
+ #include "resource_violation_event.h"
+ struct audit_listener {
+         struct faultd_module module;
+         int audit_fd;
+         sd_event_source *event_source;
+ };
+ #define to_audit_listener(MOD) \
+         container_of(MOD, struct audit_listener, module)
+ static struct audit_rule_data rule_data = {
+       .flags = AUDIT_FILTER_EXIT, /* trigger on exit from syscall */
+       .action = AUDIT_ALWAYS, /* always catch matching syscall */
+       .field_count = 1,
+       .fields = {AUDIT_EXIT}, /* watch exit code */
+       .values = {-EMFILE},
+       .fieldflags = {AUDIT_EQUAL}, /* trigger if equal to value*/
+ };
+ static int audit_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata);
+ enum {
+       KEY_PID,
+       KEY_UNKNOWN,
+ };
+ static int str2key(char *p, int len)
+ {
+       if (strncmp(p, "pid", len) == 0)
+               return KEY_PID;
+       return KEY_UNKNOWN;
+ }
+ static int parse_event(char *message, int len, struct rv_event_data *ev_data)
+ {
+       char *p = message;
+       char *e;
+       int key;
+       p = strchr(p, '(');
+       if (!p)
+               return -1;
+       ++p;
+       ev_data->detection_time = strtol(p, &p, 10);
+         ev_data->service.pid = 0;
+       while ((p = strchr(p, ' ')) != 0) {
+               ++p;
+               e = strchr(p, '=');
+               key = str2key(p, e - p);
+               p = e + 1;
+               e = strchrnul(p, ' ');
+               switch (key) {
+               case KEY_PID:
+                       ev_data->service.pid = strtol(p, &p, 10);
+                       break;
+               default:
+                       break;
+               }
+       }
+       return 0;
+ }
+ static int audit_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata)
+ {
+       struct audit_reply reply;
+       int ret;
+         struct rv_event_data rv_ev_data = {
+                 .resource_type = FAULTD_RESOURCE_FD,
+         };
+         struct faultd_event *ev;
 -        /* 
++
+       ret = audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);
+       if (ret < 0) {
+               log_error("Could not get reply.\n");
+               return ret;
+       }
+       if (reply.type != AUDIT_SYSCALL)
+               return 0;
+       reply.message[reply.len] = '\0';
+       ret = parse_event(reply.message, reply.len, &rv_ev_data);
+       if (ret < 0) {
+               log_error("Could not parse event\n");
+               return ret;
+       }
+         log_debug("Got audit event: timestamp = %ld, pid = %d",
+                   rv_ev_data.detection_time, rv_ev_data.service.pid);
+         ret = system_service_init(rv_ev_data.service.pid, NULL,
+                                   &rv_ev_data.service);
+         if (ret) {
+                 log_info("Got resource violation but not from service. Dropping.");
+                 return 0;
+         }
+         ret = faultd_event_create(RESOURCE_VIOLATION_EVENT_ID, &rv_ev_data, &ev);
+         if (ret) {
+                 log_error("Unable to allocate event");
+                 goto cleanup_service;
+         }
+         ret = event_processor_report_event(ev);
+         if (ret) {
+                 log_error("Unable to report event");
+                 goto put_event;
+         }
+       return 0;
+ put_event:
+         faultd_event_put(ev);
+         return ret;
+ cleanup_service:
+         system_service_cleanup(&rv_ev_data.service);
+         return ret;
+ }
+ static int audit_listener_init(struct faultd_module *module, sd_event *event)
+ {
+         struct audit_listener *alistener = to_audit_listener(module);
+       int fd;
+         sd_event_source *event_source;
+       int ret;
+       fd = audit_open();
+       if (fd < 0) {
+                 log_error("Could not open audit socket: %m\n");
+               return fd;
+       }
+       ret = audit_set_pid(fd, getpid(), WAIT_YES);
+       if (ret < 0) {
+               log_error("Could not set pid (%d)\n", ret);
+               goto close_audit;
+       }
++        /*
+          * TODO: Is this in a correct place?
+          * Shouldn't be after filter registration
+          */
+       ret = sd_event_add_io(event, &event_source,
+                               fd, EPOLLIN, audit_handler, NULL);
+       if (ret < 0) {
+                 log_error_errno(ret, "Could not add io event: %m");
+               goto unset_pid;
+       }
+       /* TODO: select only relevant syscalls */
+       audit_rule_syscallbyname_data(&rule_data, "all");
+       ret = audit_add_rule_data(fd, &rule_data, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);
+       if (ret <= 0 && ret != -EEXIST) {
+                 log_error("Could not add rule (%d).", ret);
+                 goto remove_from_event_loop;
+       }
+         alistener->audit_fd = fd;
+         alistener->event_source = event_source;
+       return 0;
+ remove_from_event_loop:
+         sd_event_source_unref(event_source);
+ unset_pid:
+         audit_set_pid(fd, 0, WAIT_YES);
+ close_audit:
+         audit_close(fd);
+         return ret;
+ }
+ static void audit_listener_cleanup(struct faultd_module *module)
+ {
+         struct audit_listener *alistener = to_audit_listener(module);
+         int fd = alistener->audit_fd;
+         sd_event_source *event_source = alistener->event_source;
+       int ret;
+         /* We log errors but go forward to cleanup everything we can */
+         ret = sd_event_source_set_enabled(event_source, SD_EVENT_OFF);
+         if (ret < 0)
+                 log_error("Could not disable audit event source %d", ret);
+         sd_event_source_unref(event_source);
+       ret = audit_delete_rule_data(fd, &rule_data, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);
+       if (ret < 0 && ret != -EEXIST)
+               log_error("Could not add rule (%d)", ret);
+       ret = audit_set_pid(fd, 0, WAIT_YES);
+       if (ret < 0)
+               log_error("Could not set pid (%d)", ret);
+       audit_close(fd);
+ }
+ struct audit_listener audit_listener = {
+         .module = {
+                 .name = "audit_listener",
+                 .type = FAULTD_MODULE_TYPE_LISTENER,
+                 .init = audit_listener_init,
+                 .cleanup = audit_listener_cleanup,
+                 .node = LIST_HEAD_INIT(audit_listener.module.node),
+         },
+         .audit_fd = -1,
+ };
+ FAULTD_MODULE_REGISTER(&audit_listener.module)
index 0000000000000000000000000000000000000000,3ec551fd4568f1c7ff0f4c030cc1897a5b9855bd..87f0423a0d2283fcbefb422a6e274066c3d9e114
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,216 +1,216 @@@
 -        
+ /*
+  * This file is part of faultd.
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #include <stdio.h>
+ #include <poll.h>
+ #include <systemd/sd-bus.h>
+ #include <systemd/sd-event.h>
+ #include "log.h"
+ #include "module.h"
+ struct systemd_listener {
+         struct faultd_module module;
+         /* Put your data here */
+ };
+ #define to_systemd_listener(MOD) \
+         container_of(MOD, struct systemd_listener, module)
+ static int on_unit_properties_changed(sd_bus_message *m, void *userdata,
+                                       sd_bus_error *ret_error)
+ {
+         int rc = 1;
+         const char *interface;
+         /* const char* path; */
+         /* path = NULL; */
+         uint8_t type;
+         rc = sd_bus_message_read(m, "s", &interface);
+         if (rc < 0) {
+                 log_error_errno(rc, "Invalid message format.");
+                 goto finish;
+         }
+         if (strcmp("org.freedesktop.systemd1.Unit", interface) != 0) {
+                 rc = 0;
+                 goto finish;
+         }
+         fprintf(stdout,"'");
+         fflush(stdout);
+         rc = sd_bus_message_get_type(m, &type);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to get message type.");
+                 goto finish;
+         }
+         log_debug("Received a message!");
+         log_debug("    Type: %s",
+                   type ==  SD_BUS_MESSAGE_METHOD_CALL ? "method call" :
+                   (type ==  SD_BUS_MESSAGE_METHOD_RETURN ? "method return" :
+                    (type ==  SD_BUS_MESSAGE_METHOD_ERROR ? "method error" :
+                     (type ==  SD_BUS_MESSAGE_SIGNAL ? "signal" : "INVALID"))));
+         log_debug("    Interface:  %s", sd_bus_message_get_interface(m));
+         log_debug("    Member:     %s", sd_bus_message_get_member(m));
+         log_debug("    Path:       %s", sd_bus_message_get_path(m));
+         log_debug("    Message If: %s", interface);
+         rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
+         if (rc < 0) {
+                 rc = 0;
+         }
+         log_debug("    Message dictionary:");
+         while((rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+                 const char *key;
+                 rc = sd_bus_message_read(m, "s", &key);
+                 if (rc < 0) {
+                         log_error_errno(rc, "Failed to read a DICT_ENTRY: %m.");
+                         rc = 0;
+                         goto finish;
+                 }
+                 if (strcmp("ActiveState", key) == 0) {
+                         const char *value;
+                         rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
+                         if (rc < 0) {
+                                 /* XXX */
+                                 rc = 0;
+                                 goto finish;
+                         }
+                         rc = sd_bus_message_read(m, "s", &value);
+                         if (rc < 0) {
+                                 log_error_errno(rc, "Failed to read the AciveSate value: %m.");
+                                 rc = 0;
+                                 goto finish;
+                         }
+                         rc = sd_bus_message_exit_container(m);
+                         log_debug("        %s:%s", key, value);
+                 } else {
+                         log_debug("        %s", key);
+                         rc = sd_bus_message_skip(m, "v");
+                         if (rc < 0) {
+                                 fprintf(stderr, "Failed to skip a value.");
+                                 rc = 0;
+                                 goto finish;
+                         }
+                 }
+                 rc = sd_bus_message_exit_container(m);
+                 if (rc < 0) {
+                         log_error_errno(rc, "Failed to exit a container: %s.", strerror(-rc));
+                         rc = 0;
+                         goto finish;
+                 }
+         }
+         rc = sd_bus_message_exit_container(m);
+         if (rc < 0) {
+                 rc = 0;
+         }
+ finish:
+         return rc;
+ }
+ static int systemd_listener_init(struct faultd_module *module, sd_event* loop)
+ {
+         sd_bus_error error = SD_BUS_ERROR_NULL;
+         sd_bus *bus = NULL;
+         int rc;
+         rc = sd_bus_default_system(&bus);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to acquire the defult system bus connection.");
+                 return -1;
+         }
+         rc = sd_bus_attach_event(bus, loop, SD_EVENT_PRIORITY_NORMAL);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to attach the bus to the event loop.");
+                 return -1;
+         }
+         rc = sd_bus_add_match(bus,
+                               NULL,
+                               "type='signal',sender='org.freedesktop.systemd1',"
+                               "interface='org.freedesktop.DBus.Properties',"
+                               "member='PropertiesChanged',"
+                               "path_namespace='/org/freedesktop/systemd1/unit'",
+                               on_unit_properties_changed,
+                               NULL);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to add match.");
+                 return -1;
+         }
+         rc = sd_bus_call_method(bus,
+                                 "org.freedesktop.systemd1",
+                                 "/org/freedesktop/systemd1",
+                                 "org.freedesktop.systemd1.Manager",
+                                 "Subscribe",
+                                 &error,
+                                 NULL, NULL);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to subscribe.");
+                 return -1;
+         }
+         return 0;
+ }
+ static void systemd_listener_cleanup(struct faultd_module *module)
+ {
+         sd_bus_error error = SD_BUS_ERROR_NULL;
+         sd_bus *bus = NULL;
+         int rc;
+         rc = sd_bus_default_system(&bus);
+         if (rc < 0) {
+                 log_error_errno(rc, "Failed to acquire the defult system bus connection.");
+                 /* We cannot do anything without bus.. */
+                 return;
+         }
+         rc = sd_bus_call_method(bus,
+                                 "org.freedesktop.systemd1",
+                                 "/org/freedesktop/systemd1",
+                                 "org.freedesktop.systemd1.Manager",
+                                 "Unsubscribe",
+                                 &error,
+                                 NULL, NULL);
++
+         /* TODO: shouldn't we also detach event here? */
+         if (rc < 0)
+                 log_error_errno(rc, "Failed to unsubscribe.");
+ }
+ struct systemd_listener systemd_listener = {
+         .module = {
+                 .name = "systemd_listener",
+                 .type = FAULTD_MODULE_TYPE_LISTENER,
+                 .init = systemd_listener_init,
+                 .cleanup = systemd_listener_cleanup,
+                 .node = LIST_HEAD_INIT(systemd_listener.module.node),
+         },
+ };
+ FAULTD_MODULE_REGISTER(&systemd_listener.module)
diff --cc src/log.c
Simple merge
diff --cc src/service.c
index 0000000000000000000000000000000000000000,c5dce60226ea14e3b0ff0f2bccd317b91b6e4294..a5e78cb558f46e0a31c4c701d30a84efd25e8512
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,39 +1,39 @@@
 -        
+ /*
+  * faultd
+  *
+  * Copyright © 2017 Samsung Electronics
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ #include <malloc.h>
+ #include "service.h"
+ int system_service_init(pid_t pid, char *name, struct system_service *s)
+ {
+         /* TODO: Get real pid if < 0 */
+         s->pid = pid;
++
+         /* TODO: Get real service name if NULL */
+         s->name = name;
+         return 0;
+ }
+ void system_service_cleanup(struct system_service *s)
+ {
+         if (s)
+                 free(s->name);
+ }