Files
flexnbd-c/src/common/parse.c
Alex Young 4f31bd9340 Switch from a rake-based build to a make-based build.
This commit beefs up the Makefile to do the build, instead of the
Rakefile.

It also removes from the Rakefile the dependency on rake_utils, which
should mean it's ok to build in a schroot.

The files are reorganised to make the Makefile rules more tractable,
although the reorganisation reveals a problem with our current code
organisation.

The problem is that the proxy-specific code transitively depends on the
server code via flexnbd.h, which has a circular dependency on the server
and client structs. This should be broken in a future commit by
separating the flexnbd struct into a shared config struct and
server-specific parts, so that the server code can be moved into
src/server to more accurately show the functional dependencies.
2014-02-21 19:10:55 +00:00

128 lines
2.7 KiB
C

#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) == '.' \
)
/* FIXME: should change this to return negative on error like everything else */
int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
{
NULLCHECK( out );
NULLCHECK( src );
char temp[64];
struct sockaddr_in *v4 = (struct sockaddr_in *) out;
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out;
/* allow user to start with [ and end with any other invalid char */
{
int i=0, j=0;
if (src[i] == '[') { i++; }
for (; i<64 && IS_IP_VALID_CHAR(src[i]); i++) {
temp[j++] = src[i];
}
temp[j] = 0;
}
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;
}
if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) {
out->sa_family = AF_INET6;
return 1;
}
return 0;
}
int parse_to_sockaddr(struct sockaddr* out, char* address)
{
struct sockaddr_un* un = (struct sockaddr_un*) out;
NULLCHECK( address );
if ( address[0] == '/' ) {
un->sun_family = AF_UNIX;
strncpy( un->sun_path, address, 108 ); /* FIXME: linux only */
return 1;
}
return parse_ip_to_sockaddr( out, address );
}
int parse_acl(struct ip_and_mask (**out)[], int max, char **entries)
{
struct ip_and_mask* list;
int i;
if (max == 0) {
*out = NULL;
return 0;
}
else {
list = xmalloc(max * sizeof(struct ip_and_mask));
*out = (struct ip_and_mask (*)[])list;
debug("acl alloc: %p", *out);
}
for (i = 0; i < max; i++) {
int j;
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) {
return i;
}
for (j=0; entries[i][j] && entries[i][j] != '/'; j++)
; // increment j!
if (entries[i][j] == '/') {
outentry->mask = atoi(entries[i]+j+1);
if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS) {
return i;
}
}
else {
outentry->mask = MAX_MASK_BITS;
}
# undef MAX_MASK_BITS
debug("acl ptr[%d]: %p %d",i, outentry, outentry->mask);
}
for (i=0; i < max; i++) {
debug("acl entry %d @ %p has mask %d", i, list[i], list[i].mask);
}
return max;
}
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 );
}