Fix incorrect data from set
authorNeutron Soutmun <neo.neutron@gmail.com>
Wed, 2 Jun 2010 13:33:16 +0000 (20:33 +0700)
committerNeutron Soutmun <neo.neutron@gmail.com>
Wed, 2 Jun 2010 13:33:16 +0000 (20:33 +0700)
src/rahunasd.c
src/rh-ipset.c
src/rh-ipset.h

index 649fc4d..c793ace 100644 (file)
@@ -64,14 +64,12 @@ void rh_sighandler(int sig)
 size_t expired_check(void *data)
 {
   struct processing_set *process = (struct processing_set *) data;
-  struct ip_set_list *setlist = (struct ip_set_list *) process->list;
-  size_t offset;
-  struct ip_set_rahu *table = NULL;
+  struct ip_set_req_rahunas *d = NULL;
   struct task_req req;
   unsigned int id;
   char *ip = NULL;
   int res  = 0;
-  GList *runner = g_list_first(process->vs->v_map->members);
+  GList *runner = NULL;
   struct rahunas_member *member = NULL;
 
   if (process == NULL)
@@ -80,8 +78,7 @@ size_t expired_check(void *data)
   if (process->list == NULL)
     return (-1); 
 
-  offset = sizeof(struct ip_set_list) + setlist->header_size;
-  table = (struct ip_set_rahu *)(process->list + offset);
+  runner = g_list_first(process->vs->v_map->members);
 
   while (runner != NULL) {
     member = (struct rahunas_member *)runner->data;
@@ -89,17 +86,22 @@ size_t expired_check(void *data)
 
     id = member->id;
 
+    d = get_data_from_set (process->list, id, process->vs->v_map);
+    if (d == NULL)
+      continue;
+
     DP("Processing id = %d", id);
 
-    DP("Time diff = %d, idle_timeout=%d", (time(NULL) - table[id].timestamp),
+    DP("Time now: %d, Time get: %d", time(NULL), d->timestamp);
+    DP("Time diff = %d, idle_timeout=%d", (time(NULL) - d->timestamp),
          process->vs->vserver_config->idle_timeout);
 
-    if ((time(NULL) - table[id].timestamp) > 
+    if ((time(NULL) - d->timestamp) >
          process->vs->vserver_config->idle_timeout) {
       // Idle Timeout
       DP("Found IP: %s idle timeout", idtoip(process->vs->v_map, id));
       req.id = id;
-      memcpy(req.mac_address, &table[id].ethernet, ETH_ALEN);
+      memcpy(req.mac_address, &d->ethernet, ETH_ALEN);
       req.req_opt = RH_RADIUS_TERM_IDLE_TIMEOUT;
       send_xmlrpc_stopacct(process->vs, id, 
                            RH_RADIUS_TERM_IDLE_TIMEOUT);
@@ -109,7 +111,7 @@ size_t expired_check(void *data)
       // Session Timeout (Expired)
       DP("Found IP: %s session timeout", idtoip(process->vs->v_map, id));
       req.id = id;
-      memcpy(req.mac_address, &table[id].ethernet, ETH_ALEN);
+      memcpy(req.mac_address, &d->ethernet, ETH_ALEN);
       req.req_opt = RH_RADIUS_TERM_SESSION_TIMEOUT;
       send_xmlrpc_stopacct(process->vs, id, 
                            RH_RADIUS_TERM_SESSION_TIMEOUT);
index 08fb88e..c377dbb 100644 (file)
 #include "rh-utils.h"
 
 ip_set_id_t max_sets;
+static int protocol_version = 0;
+
+#define DONT_ALIGN    (protocol_version == IP_SET_PROTOCOL_UNALIGNED)
+#define ALIGNED(len)  IPSET_VALIGN(len, DONT_ALIGN)
 
 int kernel_getsocket(void)
 {
@@ -84,8 +88,10 @@ int kernel_sendto_handleerrno(unsigned op, void *data, socklen_t size)
   int res = wrapped_setsockopt(data, size);
 
   if (res !=0) {
-    DP("res=%d errno=%d", res, errno);
-    return -1;
+    if (errno == EEXIST)
+      return -1;
+    else
+      DP("res=%d errno=%d", res, errno);
   }
 
   return 0;
@@ -104,13 +110,42 @@ int kernel_getfrom_handleerrno(void *data, size_t * size)
   int res = wrapped_getsockopt(data, size);
 
   if (res != 0) {
-    DP("res=%d errno=%d", res, errno);
-    return -1;
+    if (errno == EAGAIN)
+      return -1;
+    else
+      DP("res=%d errno=%d", res, errno);
   }
 
   return 0;
 }
 
+static void check_protocolversion(void)
+{
+  struct ip_set_req_version req_version;
+  socklen_t size = sizeof(struct ip_set_req_version);
+  int res;
+
+  if (protocol_version)
+    return;
+
+  req_version.op = IP_SET_OP_VERSION;
+  res = wrapped_getsockopt(&req_version, &size);
+
+  if (res != 0)
+    logmsg(RH_LOG_ERROR, "Couldn't verify kernel module version!");
+
+  if (!(req_version.version == IP_SET_PROTOCOL_VERSION
+        || req_version.version == IP_SET_PROTOCOL_UNALIGNED)) {
+    logmsg(RH_LOG_ERROR, "Kernel ip_set module is of protocol version %u."
+         "I'm of protocol version %u.\n"
+         "Please upgrade your kernel and/or ipset(8) utillity.",
+         req_version.version, IP_SET_PROTOCOL_VERSION);
+  }
+
+  protocol_version = req_version.version;
+  DP ("Protocol Version %u", protocol_version);
+}
+
 struct set *set_adt_get(const char *name)
 {
   struct ip_set_req_adt_get req_adt_get;
@@ -119,8 +154,10 @@ struct set *set_adt_get(const char *name)
 
   DP("%s", name);
 
+  check_protocolversion ();
+
   req_adt_get.op = IP_SET_OP_ADT_GET;
-  req_adt_get.version = IP_SET_PROTOCOL_VERSION;
+  req_adt_get.version = protocol_version;
   strncpy(req_adt_get.set.name, name, IP_SET_MAXNAMELEN);
   size = sizeof(struct ip_set_req_adt_get);
 
@@ -210,10 +247,12 @@ int set_adtip_nb(struct set *rahunas_set, ip_set_ip_t *adtip,
   void *data;
   int res = 0;
 
+  check_protocolversion ();
+
   if (rahunas_set == NULL)
     return -1;
 
-  size = sizeof(struct ip_set_req_adt) + sizeof(struct ip_set_req_rahunas);
+  size = ALIGNED(sizeof(struct ip_set_req_adt)) + sizeof(struct ip_set_req_rahunas);
   data = rh_malloc(size);
 
   memcpy(&req.ip, adtip, sizeof(ip_set_ip_t));
@@ -222,7 +261,7 @@ int set_adtip_nb(struct set *rahunas_set, ip_set_ip_t *adtip,
   req_adt = (struct ip_set_req_adt *) data;
   req_adt->op = op;
   req_adt->index = rahunas_set->index;
-  memcpy(data + sizeof(struct ip_set_req_adt), &req, 
+  memcpy(data + ALIGNED(sizeof(struct ip_set_req_adt)), &req,
            sizeof(struct ip_set_req_rahunas));
 
   if (kernel_sendto_handleerrno(op, data, size) == -1)
@@ -261,8 +300,10 @@ void set_flush(const char *name)
 {
   struct ip_set_req_std req;
 
+  check_protocolversion ();
+
   req.op = IP_SET_OP_FLUSH;
-  req.version = IP_SET_PROTOCOL_VERSION;
+  req.version = protocol_version;
   strncpy(req.name, name, IP_SET_MAXNAMELEN);
 
   kernel_sendto(&req, sizeof(struct ip_set_req_std));
@@ -280,6 +321,8 @@ size_t load_set_list(struct vserver *vs, const char name[IP_SET_MAXNAMELEN],
   socklen_t size, req_size;
   int repeated = 0, res = 0;
 
+  check_protocolversion ();
+
   DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
         : cmd == CMD_LIST_SIZE ? "LIST_SIZE"
         : "SAVE_SIZE",
@@ -289,7 +332,7 @@ tryagain:
 
   /* Get max_sets */
   req_max_sets.op = IP_SET_OP_MAX_SETS;
-  req_max_sets.version = IP_SET_PROTOCOL_VERSION;
+  req_max_sets.version = protocol_version;
   strncpy(req_max_sets.set.name, name, IP_SET_MAXNAMELEN);
   size = sizeof(req_max_sets);
   kernel_getfrom(&req_max_sets, &size);
@@ -306,8 +349,8 @@ tryagain:
   }
 
   /* Get setnames */
-  size = req_size = sizeof(struct ip_set_req_setnames) 
-        + req_max_sets.sets * sizeof(struct ip_set_name_list);
+  size = req_size = ALIGNED(sizeof(struct ip_set_req_setnames))
+        + req_max_sets.sets * ALIGNED(sizeof(struct ip_set_name_list));
   data = rh_malloc(size);
   ((struct ip_set_req_setnames *) data)->op = op;
   ((struct ip_set_req_setnames *) data)->index = *idx;
@@ -347,6 +390,8 @@ int get_header_from_set (struct vserver *vs)
   if (vs == NULL)
     return (-1);
 
+  check_protocolversion ();
+
   size = req_size = load_set_list(vs, vs->vserver_config->vserver_name, &idx, 
                                   IP_SET_OP_LIST_SIZE, CMD_LIST); 
 
@@ -369,7 +414,7 @@ int get_header_from_set (struct vserver *vs)
     size = 0;
   }
 
-  offset = sizeof(struct ip_set_list);
+  offset = ALIGNED(sizeof(struct ip_set_list));
   header = (struct ip_set_req_rahunas_create *) (data + offset);
 
   first_ip = htonl(header->from); 
@@ -401,6 +446,8 @@ int walk_through_set (int (*callback)(void *), struct vserver *vs)
   socklen_t size, req_size;
   int res = 0;
    
+  check_protocolversion ();
+
   size = req_size = load_set_list(vs, vs->vserver_config->vserver_name, &idx, 
                                   IP_SET_OP_LIST_SIZE, CMD_LIST); 
 
@@ -429,3 +476,36 @@ int walk_through_set (int (*callback)(void *), struct vserver *vs)
   rh_free(&data);
   return res;
 }
+
+struct ip_set_req_rahunas *get_data_from_set (void *data, unsigned int id,
+                                              const struct rahunas_map *map)
+{
+  struct ip_set_list *setlist = NULL;
+  size_t header_offset = 0;
+  size_t offset = 0;
+  struct ip_set_req_rahunas *d = NULL;
+  ip_set_ip_t ip;
+
+  if (data == NULL || map == NULL)
+    return NULL;
+
+  ip = ntohl (map->first_ip) + id;
+
+  setlist = (struct ip_set_list *) (data);
+
+  header_offset = ALIGNED(sizeof(struct ip_set_list)) + setlist->header_size;
+
+  DP ("members_size %u", setlist->members_size);
+
+  while (offset < setlist->members_size) {
+    d = data + header_offset + offset;
+    DP ("req_ip: %u, seek_ip: %u", ip, d->ip);
+
+    if (ip == d->ip)
+      return d;
+
+    offset += ALIGNED (sizeof (struct ip_set_req_rahunas));
+  }
+
+  return NULL;
+}
index 4177ffe..f45d0b7 100644 (file)
@@ -99,6 +99,9 @@ void parse_mac(const char *mac, unsigned char *ethernet);
 char *ip_tostring(ip_set_ip_t ip);
 char *mac_tostring(unsigned char macaddress[ETH_ALEN]);
 
+struct ip_set_req_rahunas *get_data_from_set (void *data, unsigned int id,
+                                              const struct rahunas_map *map);
+
 #define BITSPERBYTE (8*sizeof(char))
 #define ID2BYTE(id) ((id)/BITSPERBYTE)
 #define ID2MASK(id) (1 << ((id)%BITSPERBYTE))