Fix mdoc(7)/man(7) mix up.
[netbsd-mini2440.git] / lib / libform / type_ipv4.c
blob3f77ad0288cbf2d7a15b6ddd2055eb5c2f7c15eb
1 /* $NetBSD: type_ipv4.c,v 1.9 2004/11/24 11:57:09 blymn Exp $ */
3 /*-
4 * Copyright (c) 1998-1999 Brett Lymn
5 * (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6 * All rights reserved.
8 * This code has been donated to The NetBSD Foundation by the Author.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: type_ipv4.c,v 1.9 2004/11/24 11:57:09 blymn Exp $");
35 #include <string.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <limits.h>
40 #include "form.h"
41 #include "internals.h"
44 * The IP v4 address type handling.
48 * define the styles of address we can have, they are:
49 * FORMI_DOTTED_QUAD address of form aaa.bbb.ccc.ddd
50 * FORMI_HEX address of form 0xaabbccdd
51 * FORMI_CLASSLESS address of form aaa.bbb.ccc.ddd/ee
53 #define FORMI_DOTTED_QUAD 0
54 #define FORMI_HEX 1
55 #define FORMI_CLASSLESS 2
58 * Check the contents of the field buffer are a valid IPv4 address only.
60 static int
61 ipv4_check_field(FIELD *field, char *args)
63 char *buf, *buf1, *keeper, *p, *slash;
64 unsigned int vals[4], style, start, mask;
65 unsigned long hex_val, working;
66 int i;
68 if (args == NULL)
69 return FALSE;
71 if (asprintf(&keeper, "%s", args) < 0)
72 return FALSE;
74 #ifdef DEBUG
75 fprintf(dbg, "ipv4_check_field: enter with args of %s\n", keeper);
76 #endif
77 style = FORMI_DOTTED_QUAD;
78 buf = keeper;
79 hex_val = 0;
80 mask = 0;
82 if ((slash = index(buf, '/')) != NULL)
83 style = FORMI_CLASSLESS;
84 else {
85 start = _formi_skip_blanks(buf, 0);
86 if ((buf[start] != '\0') && (buf[start + 1] != '\0') &&
87 (buf[start] == '0') && ((buf[start + 1] == 'x') ||
88 (buf[start + 1] == 'X')))
89 style = FORMI_HEX;
92 switch (style) {
93 case FORMI_CLASSLESS:
94 *slash = '\0';
95 slash++;
96 mask = atoi(slash);
97 if (mask > 32)
98 goto FAIL;
99 /* FALLTHROUGH */
101 case FORMI_DOTTED_QUAD:
102 for (i = 0; i < 4; i++) {
103 p = strsep(&buf, ".");
104 if ((p == NULL) || (*p == '\0'))
105 goto FAIL;
106 vals[i] = atoi(p);
107 if (vals[i] > 255)
108 goto FAIL;
110 break;
113 case FORMI_HEX:
114 errno = 0;
115 hex_val = strtoul(buf, NULL, 16);
116 if ((hex_val == ULONG_MAX) && (errno == ERANGE))
117 goto FAIL;
119 working = hex_val;
120 for (i = 3; i >= 0; i--) {
121 vals[i] = (unsigned int)(working & 0xffUL);
122 working = working >> 8;
124 break;
128 free(keeper);
130 buf1 = NULL;
132 switch (style) {
133 case FORMI_DOTTED_QUAD:
134 if (asprintf(&buf, "%d.%d.%d.%d", vals[0], vals[1], vals[2],
135 vals[3]) < 0)
136 return FALSE;
137 if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
138 vals[2], vals[3]) < 0)
139 return FALSE;
140 break;
142 case FORMI_CLASSLESS:
143 if (asprintf(&buf, "%d.%d.%d.%d/%d", vals[0], vals[1],
144 vals[2], vals[3], mask) < 0)
145 return FALSE;
146 if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
147 vals[2], vals[3]) < 0)
148 return FALSE;
149 break;
151 case FORMI_HEX:
152 if (asprintf(&buf, "0x%.8lx", hex_val) < 0)
153 return FALSE;
154 if (asprintf(&buf1, "%d.%d.%d.%d", vals[0], vals[1],
155 vals[2], vals[3]) < 0)
156 return FALSE;
157 break;
160 /* re-set the field buffer to be the reformatted IPv4 address */
161 set_field_buffer(field, 0, buf);
164 * Set the field buffer 1 to the dotted quad format regardless
165 * of the input format, only if buffer 1 exists.
167 if (field->nbuf > 1)
168 set_field_buffer(field, 1, buf1);
170 #ifdef DEBUG
171 fprintf(dbg, "ipv4_check_field: buf0 set to %s\n", buf);
172 fprintf(dbg, "ipv4_check_field: buf1 set to %s\n", buf1);
173 #endif
174 free(buf);
175 free(buf1);
177 return TRUE;
179 /* bail out point if we got a bad entry */
180 FAIL:
181 free(keeper);
182 return FALSE;
187 * Check the given character is numeric, return TRUE if it is.
189 static int
190 ipv4_check_char(/* ARGSUSED1 */ int c, char *args)
192 return (isxdigit(c) || (c == '.') || (tolower(c) == 'x') ||
193 (c == '/'))? TRUE : FALSE;
196 static FIELDTYPE builtin_ipv4 = {
197 _TYPE_IS_BUILTIN, /* flags */
198 0, /* refcount */
199 NULL, /* link */
200 NULL, /* make_args */
201 NULL, /* copy_args */
202 NULL, /* free_args */
203 ipv4_check_field, /* field_check */
204 ipv4_check_char, /* char_check */
205 NULL, /* next_choice */
206 NULL /* prev_choice */
209 FIELDTYPE *TYPE_IPV4 = &builtin_ipv4;