]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Convert prefix to a , seperated list of multiple prefixes 226/head
authorBtbN <btbn@btbn.de>
Tue, 15 Jan 2013 14:27:44 +0000 (15:27 +0100)
committerBtbN <btbn@btbn.de>
Tue, 15 Jan 2013 15:33:21 +0000 (16:33 +0100)
src/access.c
src/access.h

index 4be611df00e96888823ed09a03f1294f334d4840..514e870766321cf0c8254da120ea43b720bc9fdb 100644 (file)
@@ -155,6 +155,7 @@ access_ticket_verify(const char *id, const char *resource)
 static int
 netmask_verify(access_entry_t *ae, struct sockaddr *src)
 {
+  access_ipmask_t *ai;
   int isv4v6 = 0;
   uint32_t v4v6 = 0;
   
@@ -169,45 +170,48 @@ netmask_verify(access_entry_t *ae, struct sockaddr *src)
     }
   }
 
-  if(ae->ae_ipv6 == 0 && src->sa_family == AF_INET)
+  LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link)
   {
-    struct sockaddr_in *in4 = (struct sockaddr_in *)src;
-    uint32_t b = ntohl(in4->sin_addr.s_addr);
-    return (b & ae->ae_netmask) == ae->ae_network;
-  }
-  else if(ae->ae_ipv6 == 0 && isv4v6)
-  {
-    return (v4v6 & ae->ae_netmask) == ae->ae_network;
-  }
-  else if(ae->ae_ipv6 && isv4v6)
-  {
-    return 0;
-  }
-  else if(ae->ae_ipv6 && src->sa_family == AF_INET6)
-  {
-    struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr);
-    uint8_t *a8 = (uint8_t*)in6->s6_addr;
-    uint8_t *m8 = (uint8_t*)ae->ae_ip6.s6_addr;
-    int slen = ae->ae_prefixlen;
-    uint32_t apos = 0;
-    uint8_t lastMask = (0xFFu << (8 - (slen % 8)));
-
-    if(slen < 0 || slen > 128)
-      return 0;
-
-    while(slen >= 8)
+    if(ai->ai_ipv6 == 0 && src->sa_family == AF_INET)
     {
-      if(a8[apos] != m8[apos])
-        return 0;
-
-      apos += 1;
-      slen -= 8;
+      struct sockaddr_in *in4 = (struct sockaddr_in *)src;
+      uint32_t b = ntohl(in4->sin_addr.s_addr);
+      if((b & ai->ai_netmask) == ai->ai_network)
+        return 1;
+    }
+    else if(ai->ai_ipv6 == 0 && isv4v6)
+    {
+      if((v4v6 & ai->ai_netmask) == ai->ai_network)
+        return 1;
+    }
+    else if(ai->ai_ipv6 && isv4v6)
+    {
+      continue;
+    }
+    else if(ai->ai_ipv6 && src->sa_family == AF_INET6)
+    {
+      struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr);
+      uint8_t *a8 = (uint8_t*)in6->s6_addr;
+      uint8_t *m8 = (uint8_t*)ai->ai_ip6.s6_addr;
+      int slen = ai->ai_prefixlen;
+      uint32_t apos = 0;
+      uint8_t lastMask = (0xFFu << (8 - (slen % 8)));
+
+      if(slen < 0 || slen > 128)
+        continue;
+
+      while(slen >= 8)
+      {
+        if(a8[apos] != m8[apos])
+          continue;
+
+        apos += 1;
+        slen -= 8;
+      }
+
+      if(slen == 0 || (a8[apos] & lastMask) == (m8[apos] & lastMask))
+        return 1;
     }
-
-    if(slen == 0)
-      return 1;
-
-    return (a8[apos] & lastMask) == (m8[apos] & lastMask);
   }
 
   return 0;
@@ -351,56 +355,89 @@ static void
 access_set_prefix(access_entry_t *ae, const char *prefix)
 {
   char buf[100];
+  char tokbuf[4096];
   int prefixlen;
-  char *p;
+  char *p, *tok, *saveptr;
+  access_ipmask_t *ai;
 
-  if(strlen(prefix) > 90)
-    return;
-  
-  strcpy(buf, prefix);
+  while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
+  {
+    LIST_REMOVE(ai, ai_link);
+    free(ai);
+  }
 
-  if(strchr(buf, ':') != NULL)
-    ae->ae_ipv6 = 1;
-  else
-    ae->ae_ipv6 = 0;
+  strncpy(tokbuf, prefix, 4095);
+  tokbuf[4095] = 0;
+  tok = strtok_r(tokbuf, ",;| ", &saveptr);
 
-  if(ae->ae_ipv6)
+  while(tok != NULL)
   {
-    p = strchr(buf, '/');
-    if(p)
+    ai = calloc(1, sizeof(access_ipmask_t));
+
+    if(strlen(tok) > 90 || strlen(tok) == 0)
     {
-      *p++ = 0;
-      prefixlen = atoi(p);
-      if(prefixlen > 128)
-        return;
-    } else {
-      prefixlen = 128;
+      free(ai);
+      tok = strtok_r(NULL, ",;| ", &saveptr);
+      continue;
     }
 
-    ae->ae_prefixlen = prefixlen;
-    inet_pton(AF_INET6, buf, &ae->ae_ip6);
+    strcpy(buf, tok);
 
-    ae->ae_netmask = 0xffffffff;
-    ae->ae_network = 0x00000000;
-  }
-  else
-  {
-    p = strchr(buf, '/');
-    if(p)
+    if(strchr(buf, ':') != NULL)
+      ai->ai_ipv6 = 1;
+    else
+      ai->ai_ipv6 = 0;
+
+    if(ai->ai_ipv6)
+    {
+      p = strchr(buf, '/');
+      if(p)
+      {
+        *p++ = 0;
+        prefixlen = atoi(p);
+        if(prefixlen > 128)
+        {
+          free(ai);
+          tok = strtok_r(NULL, ",;| ", &saveptr);
+          continue;
+        }
+      } else {
+        prefixlen = 128;
+      }
+
+      ai->ai_prefixlen = prefixlen;
+      inet_pton(AF_INET6, buf, &ai->ai_ip6);
+
+      ai->ai_netmask = 0xffffffff;
+      ai->ai_network = 0x00000000;
+    }
+    else
     {
-      *p++ = 0;
-      prefixlen = atoi(p);
-      if(prefixlen > 32)
-        return;
-    } else {
-      prefixlen = 32;
+      p = strchr(buf, '/');
+      if(p)
+      {
+        *p++ = 0;
+        prefixlen = atoi(p);
+        if(prefixlen > 32)
+        {
+          free(ai);
+          tok = strtok_r(NULL, ",;| ", &saveptr);
+          continue;
+        }
+      } else {
+        prefixlen = 32;
+      }
+
+      ai->ai_ip.s_addr = inet_addr(buf);
+      ai->ai_prefixlen = prefixlen;
+
+      ai->ai_netmask   = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
+      ai->ai_network   = ntohl(ai->ai_ip.s_addr) & ai->ai_netmask;
     }
 
-    ae->ae_ip.s_addr = inet_addr(buf);
-    ae->ae_prefixlen = prefixlen;
+    LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
 
-    ae->ae_netmask   = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
-    ae->ae_network   = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask;
+    tok = strtok_r(NULL, ",;| ", &saveptr);
   }
 }
 
@@ -450,6 +487,14 @@ access_entry_find(const char *id, int create)
 static void
 access_entry_destroy(access_entry_t *ae)
 {
+  access_ipmask_t *ai;
+
+  while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
+  {
+    LIST_REMOVE(ai, ai_link);
+    free(ai);
+  }
+
   free(ae->ae_id);
   free(ae->ae_username);
   free(ae->ae_password);
@@ -465,8 +510,12 @@ static htsmsg_t *
 access_record_build(access_entry_t *ae)
 {
   htsmsg_t *e = htsmsg_create_map();
+  access_ipmask_t *ai;
   char addrbuf[50];
-  char buf[100];
+  char buf[4096];
+  int pos = 0;
+
+  memset(buf, 0, 4096);
 
   htsmsg_add_u32(e, "enabled",  !!ae->ae_enabled);
 
@@ -474,14 +523,22 @@ access_record_build(access_entry_t *ae)
   htsmsg_add_str(e, "password", ae->ae_password);
   htsmsg_add_str(e, "comment",  ae->ae_comment);
 
-  if(ae->ae_ipv6)
+  LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link)
   {
-    inet_ntop(AF_INET6, &ae->ae_ip6, addrbuf, 50);
-    snprintf(buf, sizeof(buf), "%s/%d", addrbuf, ae->ae_prefixlen);
+    if(sizeof(buf)-pos <= 0)
+      break;
+
+    if(ai->ai_ipv6)
+    {
+      inet_ntop(AF_INET6, &ai->ai_ip6, addrbuf, 50);
+      pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", addrbuf, ai->ai_prefixlen);
+    }
+    else
+    {
+      pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", inet_ntoa(ai->ai_ip), ai->ai_prefixlen);
+    }
   }
-  else
-    snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(ae->ae_ip), ae->ae_prefixlen);
-  htsmsg_add_str(e, "prefix",   buf);
+  htsmsg_add_str(e, "prefix",   buf + 1);
 
   htsmsg_add_u32(e, "streaming", ae->ae_rights & ACCESS_STREAMING     ? 1 : 0);
   htsmsg_add_u32(e, "dvr"      , ae->ae_rights & ACCESS_RECORDER      ? 1 : 0);
@@ -631,6 +688,7 @@ access_init(int createdefault)
   dtable_t *dt;
   htsmsg_t *r, *m;
   access_entry_t *ae;
+  access_ipmask_t *ai;
   const char *s;
 
   static struct {
@@ -652,33 +710,25 @@ access_init(int createdefault)
     ae = access_entry_find(NULL, 1);
 
     free(ae->ae_comment);
-    ae->ae_comment = strdup("Default IPv6 access entry");
+    ae->ae_comment = strdup("Default access entry");
 
     ae->ae_enabled = 1;
     ae->ae_rights = 0xffffffff;
 
-    ae->ae_ipv6 = 1;
-
-    r = access_record_build(ae);
-    dtable_record_store(dt, ae->ae_id, r);
-    htsmsg_destroy(r);
-
-    ae = access_entry_find(NULL, 1);
-
-    free(ae->ae_comment);
-    ae->ae_comment = strdup("Default IPv4 access entry");
-
-    ae->ae_enabled = 1;
-    ae->ae_rights = 0xffffffff;
+    ai = calloc(1, sizeof(access_ipmask_t));
+    ai->ai_ipv6 = 0;
+    LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
 
-    ae->ae_ipv6 = 0;
+    ai = calloc(1, sizeof(access_ipmask_t));
+    ai->ai_ipv6 = 1;
+    LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
 
     r = access_record_build(ae);
     dtable_record_store(dt, ae->ae_id, r);
     htsmsg_destroy(r);
 
     tvhlog(LOG_WARNING, "accesscontrol",
-          "Created default wide open access controle entrys");
+          "Created default wide open access controle entry");
   }
 
   /* Load superuser account */
index 3562b0ac40a866a63c3fa7564a5564a7fc1aad36..466e380fb60cc2b0e1d71a219dbde4648aba0ccb 100644 (file)
 #define ACCESS_H_
 
 
+typedef struct access_ipmask {
+  LIST_ENTRY(access_ipmask) ai_link;
+
+  int ai_ipv6;
+
+  struct in_addr ai_ip;
+  struct in6_addr ai_ip6;
+
+  int ai_prefixlen;
+
+  uint32_t ai_network;
+  uint32_t ai_netmask;
+} access_ipmask_t;
+
 TAILQ_HEAD(access_entry_queue, access_entry);
 
 extern struct access_entry_queue access_entries;
@@ -31,17 +45,12 @@ typedef struct access_entry {
   char *ae_username;
   char *ae_password;
   char *ae_comment;
-  int ae_ipv6;
-  struct in_addr ae_ip;
-  struct in6_addr ae_ip6;
-  int ae_prefixlen;
   int ae_enabled;
   
 
   uint32_t ae_rights;
 
-  uint32_t ae_network; /* derived from ae_ip */
-  uint32_t ae_netmask; /* derived from ae_prefixlen */
+  LIST_HEAD(, access_ipmask) ae_ipmasks;
 } access_entry_t;
 
 TAILQ_HEAD(access_ticket_queue, access_ticket);