2012-05-19 12:48:03 +01:00
|
|
|
#include "parse.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
int atoi(const char *nptr);
|
|
|
|
|
|
|
|
#define IS_IP_VALID_CHAR(x) ( ((x) >= '0' && (x) <= '9' ) || \
|
|
|
|
((x) >= 'a' && (x) <= 'f') || \
|
|
|
|
((x) >= 'A' && (x) <= 'F' ) || \
|
|
|
|
(x) == ':' || (x) == '.' \
|
|
|
|
)
|
2012-05-29 00:59:12 +01:00
|
|
|
/* FIXME: should change this to return negative on error like everything else */
|
2012-05-19 12:48:03 +01:00
|
|
|
int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
|
|
|
|
{
|
2012-06-21 18:01:50 +01:00
|
|
|
NULLCHECK( out );
|
|
|
|
NULLCHECK( src );
|
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
char temp[64];
|
2012-06-11 13:05:22 +01:00
|
|
|
struct sockaddr_in *v4 = (struct sockaddr_in *) out;
|
2012-05-19 12:48:03 +01:00
|
|
|
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out;
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
/* allow user to start with [ and end with any other invalid char */
|
|
|
|
{
|
|
|
|
int i=0, j=0;
|
2012-06-11 14:34:17 +01:00
|
|
|
if (src[i] == '[') { i++; }
|
|
|
|
for (; i<64 && IS_IP_VALID_CHAR(src[i]); i++) {
|
2012-05-19 12:48:03 +01:00
|
|
|
temp[j++] = src[i];
|
2012-06-11 14:34:17 +01:00
|
|
|
}
|
2012-05-19 12:48:03 +01:00
|
|
|
temp[j] = 0;
|
|
|
|
}
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
if (temp[0] == '0' && temp[1] == '\0') {
|
|
|
|
v4->sin_family = AF_INET;
|
|
|
|
v4->sin_addr.s_addr = INADDR_ANY;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inet_pton(AF_INET, temp, &v4->sin_addr) == 1) {
|
|
|
|
out->sa_family = AF_INET;
|
|
|
|
return 1;
|
|
|
|
}
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) {
|
|
|
|
out->sa_family = AF_INET6;
|
|
|
|
return 1;
|
|
|
|
}
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-21 04:03:17 +01:00
|
|
|
int parse_acl(struct ip_and_mask (**out)[], int max, char **entries)
|
2012-05-19 12:48:03 +01:00
|
|
|
{
|
2012-06-11 12:56:45 +01:00
|
|
|
struct ip_and_mask* list;
|
2012-05-19 12:48:03 +01:00
|
|
|
int i;
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
if (max == 0) {
|
|
|
|
*out = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
2012-06-11 12:56:45 +01:00
|
|
|
list = xmalloc(max * sizeof(struct ip_and_mask));
|
|
|
|
*out = (struct ip_and_mask (*)[])list;
|
2012-05-19 12:48:03 +01:00
|
|
|
debug("acl alloc: %p", *out);
|
|
|
|
}
|
2012-06-11 12:56:45 +01:00
|
|
|
|
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
for (i = 0; i < max; i++) {
|
|
|
|
int j;
|
2012-06-11 12:56:45 +01:00
|
|
|
struct ip_and_mask* outentry = &list[i];
|
|
|
|
# define MAX_MASK_BITS (outentry->ip.family == AF_INET ? 32 : 128)
|
|
|
|
if (parse_ip_to_sockaddr(&outentry->ip.generic, entries[i]) == 0) {
|
2012-05-19 12:48:03 +01:00
|
|
|
return i;
|
2012-06-11 12:56:45 +01:00
|
|
|
}
|
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
for (j=0; entries[i][j] && entries[i][j] != '/'; j++)
|
2012-06-11 12:56:45 +01:00
|
|
|
; // increment j!
|
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
if (entries[i][j] == '/') {
|
|
|
|
outentry->mask = atoi(entries[i]+j+1);
|
2012-06-11 14:34:17 +01:00
|
|
|
if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS) {
|
2012-05-19 12:48:03 +01:00
|
|
|
return i;
|
2012-06-11 14:34:17 +01:00
|
|
|
}
|
2012-05-19 12:48:03 +01:00
|
|
|
}
|
2012-06-11 12:56:45 +01:00
|
|
|
else {
|
2012-05-19 12:48:03 +01:00
|
|
|
outentry->mask = MAX_MASK_BITS;
|
2012-06-11 12:56:45 +01:00
|
|
|
}
|
2012-05-19 12:48:03 +01:00
|
|
|
# undef MAX_MASK_BITS
|
|
|
|
debug("acl ptr[%d]: %p %d",i, outentry, outentry->mask);
|
|
|
|
}
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
for (i=0; i < max; i++) {
|
2012-06-11 12:56:45 +01:00
|
|
|
debug("acl entry %d @ %p has mask %d", i, list[i], list[i].mask);
|
2012-05-19 12:48:03 +01:00
|
|
|
}
|
2012-06-11 13:05:22 +01:00
|
|
|
|
2012-05-19 12:48:03 +01:00
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
2012-06-11 13:57:03 +01:00
|
|
|
|
|
|
|
void parse_port( char *s_port, struct sockaddr_in *out )
|
|
|
|
{
|
|
|
|
NULLCHECK( s_port );
|
|
|
|
|
|
|
|
int raw_port;
|
|
|
|
|
|
|
|
raw_port = atoi( s_port );
|
|
|
|
if ( raw_port < 0 || raw_port > 65535 ) {
|
|
|
|
fatal( "Port number must be >= 0 and <= 65535" );
|
|
|
|
}
|
|
|
|
out->sin_port = htobe16( raw_port );
|
|
|
|
}
|
|
|
|
|