minix/lib/libform/type_ipv4.c
Thomas Cort a0e6850f82 Importing lib/libform
No Minix-specific changes needed.

Change-Id: Ia8ddbdb57ac04dfb42d79c374b9e25b189f9dc3b
2013-11-12 07:56:07 -05:00

212 lines
5.5 KiB
C

/* $NetBSD: type_ipv4.c,v 1.10 2007/01/17 23:24:22 hubertf Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn
* (blymn@baea.com.au, brett_lymn@yahoo.com.au)
* All rights reserved.
*
* This code has been donated to The NetBSD Foundation by the Author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: type_ipv4.c,v 1.10 2007/01/17 23:24:22 hubertf Exp $");
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include "form.h"
#include "internals.h"
/*
* The IP v4 address type handling.
*/
/*
* define the styles of address we can have, they are:
* FORMI_DOTTED_QUAD address of form aaa.bbb.ccc.ddd
* FORMI_HEX address of form 0xaabbccdd
* FORMI_CLASSLESS address of form aaa.bbb.ccc.ddd/ee
*/
#define FORMI_DOTTED_QUAD 0
#define FORMI_HEX 1
#define FORMI_CLASSLESS 2
/*
* Check the contents of the field buffer are a valid IPv4 address only.
*/
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
fprintf(dbg, "ipv4_check_field: enter with args of %s\n", 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;
/* FALLTHROUGH */
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;
}
/* re-set the field buffer to be the reformatted IPv4 address */
set_field_buffer(field, 0, buf);
/*
* Set the field buffer 1 to the dotted quad format regardless
* of the input format, only if buffer 1 exists.
*/
if (field->nbuf > 1)
set_field_buffer(field, 1, buf1);
#ifdef DEBUG
fprintf(dbg, "ipv4_check_field: buf0 set to %s\n", buf);
fprintf(dbg, "ipv4_check_field: buf1 set to %s\n", buf1);
#endif
free(buf);
free(buf1);
return TRUE;
/* bail out point if we got a bad entry */
FAIL:
free(keeper);
return FALSE;
}
/*
* Check the given character is numeric, return TRUE if it is.
*/
static int
ipv4_check_char(/* ARGSUSED1 */ int c, char *args)
{
return (isxdigit(c) || (c == '.') || (tolower(c) == 'x') ||
(c == '/'))? TRUE : FALSE;
}
static FIELDTYPE builtin_ipv4 = {
_TYPE_IS_BUILTIN, /* flags */
0, /* refcount */
NULL, /* link */
NULL, /* make_args */
NULL, /* copy_args */
NULL, /* free_args */
ipv4_check_field, /* field_check */
ipv4_check_char, /* char_check */
NULL, /* next_choice */
NULL /* prev_choice */
};
FIELDTYPE *TYPE_IPV4 = &builtin_ipv4;