#include <sys/cdefs.h>
__RCSID("$NetBSD: type_ipv4.c,v 1.11 2016/03/09 19:47:13 christos Exp $");
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include "form.h"
#include "internals.h"
#define FORMI_DOTTED_QUAD 0
#define FORMI_HEX 1
#define FORMI_CLASSLESS 2
static int
ipv4_check_field(FIELD *field, char *args)
{
char *buf, *buf1, *keeper, *p, *slash;
unsigned int vals[4], style, start, mask;
unsigned long hex_val, working;
int i;
if (args == NULL)
return FALSE;
if (asprintf(&keeper, "%s", args) < 0)
return FALSE;
#ifdef DEBUG
_formi_dbg_printf("%s: enter with args of %s\n", __func__, keeper);
#endif
style = FORMI_DOTTED_QUAD;
buf = keeper;
hex_val = 0;
mask = 0;
if ((slash = index(buf, '/')) != NULL)
style = FORMI_CLASSLESS;
else {
start = _formi_skip_blanks(buf, 0);
if ((buf[start] != '\0') && (buf[start + 1] != '\0') &&
(buf[start] == '0') && ((buf[start + 1] == 'x') ||
(buf[start + 1] == 'X')))
style = FORMI_HEX;
}
switch (style) {
case FORMI_CLASSLESS:
*slash = '\0';
slash++;
mask = atoi(slash);
if (mask > 32)
goto FAIL;
case FORMI_DOTTED_QUAD:
for (i = 0; i < 4; i++) {
p = strsep(&buf, ".");
if ((p == NULL) || (*p == '\0'))
goto FAIL;
vals[i] = atoi(p);
if (vals[i] > 255)
goto FAIL;
}
break;
case FORMI_HEX:
errno = 0;
hex_val = strtoul(buf, NULL, 16);
if ((hex_val == ULONG_MAX) && (errno == ERANGE))
goto FAIL;
working = hex_val;
for (i = 3; i >= 0; i--) {
vals[i] = (unsigned int)(working & 0xffUL);
working = working >> 8;
}
break;
}
free(keeper);
buf1 = NULL;
switch (style) {
case FORMI_DOTTED_QUAD:
if (asprintf(&buf, "%d.%d.%d.%d", vals[0], vals[1], vals[2],
vals[3]) < 0)
return FALSE;
if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
vals[2], vals[3]) < 0)
return FALSE;
break;
case FORMI_CLASSLESS:
if (asprintf(&buf, "%d.%d.%d.%d/%d", vals[0], vals[1],
vals[2], vals[3], mask) < 0)
return FALSE;
if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
vals[2], vals[3]) < 0)
return FALSE;
break;
case FORMI_HEX:
if (asprintf(&buf, "0x%.8lx", hex_val) < 0)
return FALSE;
if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
vals[2], vals[3]) < 0)
return FALSE;
break;
}
set_field_buffer(field, 0, buf);
if (field->nbuf > 1)
set_field_buffer(field, 1, buf1);
#ifdef DEBUG
_formi_dbg_printf("%s: buf0 set to %s\n", __func__, buf);
_formi_dbg_printf("%s: buf1 set to %s\n", __func__, buf1);
#endif
free(buf);
free(buf1);
return TRUE;
FAIL:
free(keeper);
return FALSE;
}
static int
ipv4_check_char( int c, char *args)
{
return (isxdigit(c) || (c == '.') || (tolower(c) == 'x') ||
(c == '/'))? TRUE : FALSE;
}
static FIELDTYPE builtin_ipv4 = {
_TYPE_IS_BUILTIN,
0,
NULL,
NULL,
NULL,
NULL,
ipv4_check_field,
ipv4_check_char,
NULL,
NULL
};
FIELDTYPE *TYPE_IPV4 = &builtin_ipv4;