Child signal handler, radius accounting on reboot
authorNeutron Soutmun <neo.neutron@gmail.com>
Tue, 2 Sep 2008 18:32:54 +0000 (01:32 +0700)
committerNeutron Soutmun <neo.neutron@gmail.com>
Sun, 2 Nov 2008 19:43:11 +0000 (02:43 +0700)
2008-09-03  Neutron Soutmun <neo.neutron@gmail.com>

* src/rahunasd.{h,c}:
  - Handle the signal and when child process is stopped or restart,
    send the stop accounting to Radius with NAS Reboot code.
* +src/rh-radius.h: Add predefined termination code of Radius.
* src/rh-xmlrpc-cmd.{h,c}: Change send_xmlrpc_stopacct() API, which provide
  the ability to send the cause of the stop accounting.

ChangeLog
src/rahunasd.c
src/rahunasd.h
src/rh-radius.h [new file with mode: 0644]
src/rh-xmlrpc-cmd.c
src/rh-xmlrpc-cmd.h

index 328a3a2..15a53db 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-09-03  Neutron Soutmun <neo.neutron@gmail.com>
+
+       * src/rahunasd.{h,c}: 
+         - Handle the signal and when child process is stopped or restart, 
+           send the stop accounting to Radius with NAS Reboot code.
+       * +src/rh-radius.h: Add predefined termination code of Radius.
+       * src/rh-xmlrpc-cmd.{h,c}: Change send_xmlrpc_stopacct() API, which provide
+         the ability to send the cause of the stop accounting.
+
 2008-09-02  Neutron Soutmun <neo.neutron@gmail.com>
 
        * src/rh-xmlrpc-cmd.h, src/rh-utils.h: Add header definitions.
index 77ef8bf..c7fa638 100644 (file)
@@ -33,6 +33,9 @@ int ipset_flush();
 struct rahunas_map* rh_init_map();
 int rh_init_members(struct rahunas_map *map);
 
+int walk_through_set (int (*callback)(void *));
+size_t expired_check(void *data);
+size_t nas_reboot(void *data);
 
 /* Declaration */
 struct rahunas_map *map = NULL;
@@ -158,17 +161,23 @@ void rh_sighandler(int sig)
     case SIGINT:
     case SIGTERM:
     case SIGKILL:
-      ipset_flush();
-      finish();
-      rh_closelog(DEFAULT_LOG);
-      exit(EXIT_SUCCESS);
+      if (pid == 0) {
+        walk_through_set(&nas_reboot);
+        rh_exit();
+        exit(EXIT_SUCCESS);
+      }
+
+      if (pid != 0) {
+        syslog(LOG_NOTICE, "Kill Child PID %d", pid);
+        kill(pid, SIGTERM);
+      }
       break;
   }
 }
 
 int ipset_flush()
 {
-  logmsg(RH_LOG_NORMAL, "Flushing IPSET...");
+  syslog(LOG_NOTICE, "Flushing IPSET...");
   set_flush(SET_NAME);
 }
 
@@ -179,9 +188,6 @@ int finish()
        int i;
   int end;
 
-  if (pid != 0) // Do not permit child to call this
-    kill(pid, SIGKILL);
-
   if (map) {
     if (map->members) {
       members = map->members;
@@ -199,7 +205,6 @@ int finish()
        }
 
   rh_free(&rahunas_set);
-  logmsg(RH_LOG_NORMAL, exitmsg);
        syslog(LOG_INFO, exitmsg);
   return 0;
 }
@@ -261,7 +266,7 @@ int rh_init_members (struct rahunas_map* map)
 gboolean polling(gpointer data) {
   struct rahunas_map *map = (struct rahunas_map *)data;
        DP("%s", "Start polling!");
-  walk_through_set();
+  walk_through_set(&expired_check);
   return TRUE;
 }
 
@@ -293,7 +298,7 @@ size_t expired_check(void *data)
         DP("set_adtip_nb() res=%d errno=%d", res, errno);
 
         if (res == 0) {
-                           send_xmlrpc_stopacct(map, i);
+                           send_xmlrpc_stopacct(map, i, RH_RADIUS_TERM_IDLE_TIMEOUT);
 
           if (!members[i].username)
             members[i].username = termstring;
@@ -315,6 +320,53 @@ size_t expired_check(void *data)
   }
 }
 
+size_t nas_reboot(void *data)
+{
+  struct ip_set_list *setlist = (struct ip_set_list *) data;
+  struct set *set = set_list[setlist->index];
+  size_t offset;
+  struct ip_set_rahunas *table = NULL;
+  struct rahunas_member *members = map->members;
+  unsigned int i;
+  char *ip = NULL;
+  ip_set_ip_t current_ip;
+  int res  = 0;
+
+  offset = sizeof(struct ip_set_list) + setlist->header_size;
+  table = (struct ip_set_rahunas *)(data + offset);
+
+  DP("Map size %d", map->size);
+  for (i = 0; i < map->size; i++) {
+    if (test_bit(IPSET_RAHUNAS_ISSET, (void *)&table[i].flags)) {
+      DP("Found IP: %s in set, try logout", idtoip(map, i));
+      current_ip = ntohl(map->first_ip) + i;
+      res = set_adtip_nb(rahunas_set, &current_ip, &table[i].ethernet,
+                         IP_SET_OP_DEL_IP);  
+      DP("set_adtip_nb() res=%d errno=%d", res, errno);
+
+      if (res == 0) {
+                           send_xmlrpc_stopacct(map, i, RH_RADIUS_TERM_NAS_REBOOT);
+
+        if (!members[i].username)
+          members[i].username = termstring;
+
+        if (!members[i].session_id)
+          members[i].session_id = termstring;
+
+        logmsg(RH_LOG_NORMAL, "Session Stop (NAS Reboot), User: %s, IP: %s, "
+                              "Session ID: %s, MAC: %s",
+                              members[i].username, 
+                              idtoip(map, i), 
+                              members[i].session_id,
+                              mac_tostring(members[i].mac_address)); 
+
+        rh_free_member(&members[i]);
+      }
+    }
+  }
+}
+
 int get_header_from_set ()
 {
   struct ip_set_req_rahunas_create *header = NULL;
@@ -363,7 +415,7 @@ int get_header_from_set ()
   return res;
 }
 
-int walk_through_set ()
+int walk_through_set (int (*callback)(void *))
 {
   void *data = NULL;
   ip_set_id_t idx;
@@ -388,13 +440,22 @@ int walk_through_set ()
     }
     size = 0;
   }
-
-  expired_check(data);
+  
+  if (data != NULL)
+    (*callback)(data);
 
   rh_free(&data);
   return res;
 }
 
+void rh_exit()
+{
+  syslog(LOG_ALERT, "Child Exiting ..");
+  ipset_flush();
+  finish();
+  rh_closelog(DEFAULT_LOG);
+}
+
 static void
 watch_child(char *argv[])
 {
@@ -406,7 +467,7 @@ watch_child(char *argv[])
 
        int nullfd;
   int pidfd;
-
+  
        if (*(argv[0]) == '(')
          return;
 
@@ -441,11 +502,6 @@ watch_child(char *argv[])
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
 
-  signal(SIGCHLD, SIG_IGN);
-  signal(SIGHUP, rh_sighandler);
-  signal(SIGINT, rh_sighandler);
-  signal(SIGTERM, rh_sighandler);
-  signal(SIGKILL, rh_sighandler);
 
   while(1) {
 
@@ -461,9 +517,9 @@ watch_child(char *argv[])
 
     time(&start);
          /* parent */
-       pid = wait3(&status, 0, NULL);
+       pid = waitpid(-1, &status, 0);
        time(&stop);
-  
+
        if (WIFEXITED(status)) {
          syslog(LOG_NOTICE,
                         "RahuNASd Parent: child process %d exited with status %d",
@@ -476,38 +532,21 @@ watch_child(char *argv[])
       syslog(LOG_NOTICE, "RahuNASd Parent: child process %d exited", pid);
        }
   
-               if (stop - start < 10)
-                 failcount++;
-               else
-                 failcount = 0;
+    if (stop - start < 10)
+      failcount++;
+    else
+      failcount = 0;
   
-               if (failcount == 5) {
-                 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
-                       exit(EXIT_FAILURE);
-               }
+    if (failcount == 5) {
+      syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
+      exit(EXIT_FAILURE);
+    }
   
   
        if (WIFEXITED(status))
          if (WEXITSTATUS(status) == 0)
                  exit(EXIT_SUCCESS);
        
-       if (WIFSIGNALED(status)) {
-      switch (WTERMSIG(status)) {
-                 case SIGKILL:
-          rh_sighandler(SIGKILL);
-                               break;
-                       
-                       case SIGINT:
-                       case SIGTERM:
-                         syslog(LOG_ALERT, "Exiting due to unexpected forced shutdown");
-                               exit(EXIT_FAILURE);
-                               break;
-                       
-                       default:
-                         break;
-               }
-       }
-       
        sleep(3);
   }
 }
@@ -523,7 +562,10 @@ int main(int argc, char **argv)
 
        GNetXmlRpcServer *server = NULL;
        GMainLoop* main_loop     = NULL;
-  
+
+  signal(SIGTERM, rh_sighandler);
+  signal(SIGKILL, rh_sighandler);
+
        watch_child(argv);
 
   /* Open log file */
@@ -582,5 +624,4 @@ int main(int argc, char **argv)
        g_main_loop_run(main_loop);
 
        exit(EXIT_SUCCESS);
-       return 0;
 }
index e5c9b9d..1aec3f6 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef __RAHUNASD_H
 #define __RAHUNASD_H
 
+#include <stdio.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 /* Configuration */
 #define DEFAULT_LOG "/var/log/rahunas/rahunas.log"
 #define DEFAULT_PID "/var/run/rahunasd.pid"
-#define IDLE_THRESHOLD 600
-#define POLLING 60 
+
+#ifdef RH_DEBUG
+#  define IDLE_THRESHOLD 30
+#  define POLLING 15 
+#else
+#  define IDLE_THRESHOLD 600
+#  define POLLING 60 
+#endif
+
 #define SET_NAME "rahunas_set"
 #define XMLSERVICE_HOST        "localhost"
 #define XMLSERVICE_PORT        8888
diff --git a/src/rh-radius.h b/src/rh-radius.h
new file mode 100644 (file)
index 0000000..6fa40db
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * radius predefined header
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-09-02
+ */
+
+#ifndef __RH_RADIUS_H
+#define __RH_RADIUS_H
+
+#define RH_RADIUS_TERM_USER_REQUEST               1
+#define RH_RADIUS_TERM_LOST_CARRIER               2
+#define RH_RADIUS_TERM_LOST_SERVICE               3
+#define RH_RADIUS_TERM_IDLE_TIMEOUT               4
+#define RH_RADIUS_TERM_SESSION_TIMEOUT            5
+#define RH_RADIUS_TERM_ADMIN_RESET                6
+#define RH_RADIUS_TERM_ADMIN_REBOOT               7
+#define RH_RADIUS_TERM_PORT_ERROR                 8
+#define RH_RADIUS_TERM_NAS_ERROR                  9
+#define RH_RADIUS_TERM_NAS_REQUEST                10 
+#define RH_RADIUS_TERM_NAS_REBOOT                 11 
+#define RH_RADIUS_TERM_PORT_UNNEEDED              12 
+#define RH_RADIUS_TERM_PORT_PREEMPTED             13 
+#define RH_RADIUS_TERM_PORT_SUSPENDED             14 
+#define RH_RADIUS_TERM_SERVICE_UNAVAILABLE        15 
+#define RH_RADIUS_TERM_CALLBACK                   16
+#define RH_RADIUS_TERM_USER_ERROR                 17
+#define RH_RADIUS_TERM_HOST_REQUEST               18
+
+#endif //__RH_RADIUS_H
+
index d39fbd7..1150c7c 100644 (file)
@@ -8,7 +8,7 @@
 #include "rahunasd.h"
 #include "rh-xmlrpc-cmd.h"
 
-int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id) {
+int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id, int cause) {
   struct rahunas_member *members = NULL;
   GNetXmlRpcClient *client = NULL;
   gchar *reply  = NULL;
@@ -33,12 +33,13 @@ int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id) {
     return (-1);
   }
        
-       params = g_strdup_printf("%s|%s|%s|%d|%s", 
+       params = g_strdup_printf("%s|%s|%s|%d|%s|%d", 
                            idtoip(map, id),
                                 members[id].username,
                                                                                                         members[id].session_id,
                                                                                                         members[id].session_start,
-                           mac_tostring(members[id].mac_address));
+                           mac_tostring(members[id].mac_address),
+                           cause);
 
   if (params == NULL)
     return (-1);
@@ -49,7 +50,10 @@ int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id) {
       g_free(reply);
     }
   else
-    DP("%s", "Failed executing stopacct!");
+    {
+      DP("%s", "Failed executing stopacct!");
+      return (-1);
+    }
        
        g_free(params);
 
index e221366..d08198a 100644 (file)
@@ -5,7 +5,8 @@
  */
 #ifndef __RH_XMLRPC_CMD_H
 #define __RH_XMLRPC_CMD_H
+#include "rh-radius.h"
 
-int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id);
+int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id, int cause);
 
 #endif // __RH_XMLRPC_CMD_H