Convert prefix to a , seperated list of multiple prefixes

This commit is contained in:
BtbN 2013-01-15 15:27:44 +01:00
parent 3b758e5ce7
commit 89c3271368
2 changed files with 163 additions and 104 deletions

View 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)
return 1;
if(slen < 0 || slen > 128)
continue;
return (a8[apos] & lastMask) == (m8[apos] & lastMask);
while(slen >= 8)
{
if(a8[apos] != m8[apos])
continue;
apos += 1;
slen -= 8;
}
if(slen == 0 || (a8[apos] & lastMask) == (m8[apos] & lastMask))
return 1;
}
}
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);
if(strchr(buf, ':') != NULL)
ae->ae_ipv6 = 1;
else
ae->ae_ipv6 = 0;
if(ae->ae_ipv6)
while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
{
p = strchr(buf, '/');
if(p)
{
*p++ = 0;
prefixlen = atoi(p);
if(prefixlen > 128)
return;
} else {
prefixlen = 128;
}
ae->ae_prefixlen = prefixlen;
inet_pton(AF_INET6, buf, &ae->ae_ip6);
ae->ae_netmask = 0xffffffff;
ae->ae_network = 0x00000000;
LIST_REMOVE(ai, ai_link);
free(ai);
}
else
strncpy(tokbuf, prefix, 4095);
tokbuf[4095] = 0;
tok = strtok_r(tokbuf, ",;| ", &saveptr);
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 > 32)
return;
} else {
prefixlen = 32;
free(ai);
tok = strtok_r(NULL, ",;| ", &saveptr);
continue;
}
ae->ae_ip.s_addr = inet_addr(buf);
ae->ae_prefixlen = prefixlen;
strcpy(buf, tok);
ae->ae_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
ae->ae_network = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask;
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 = 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;
}
LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
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;
ai = calloc(1, sizeof(access_ipmask_t));
ai->ai_ipv6 = 0;
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);
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;
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 */

View file

@ -20,6 +20,20 @@
#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);