xref: /minix3/lib/libform/type_ipv4.c (revision a0e6850f820f09a03a1da1b4d78f9fafb3b9782f)
1 /*	$NetBSD: type_ipv4.c,v 1.10 2007/01/17 23:24:22 hubertf Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998-1999 Brett Lymn
5  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6  * All rights reserved.
7  *
8  * This code has been donated to The NetBSD Foundation by the Author.
9  *
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
17  *
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.
28  *
29  *
30  */
31 
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: type_ipv4.c,v 1.10 2007/01/17 23:24:22 hubertf Exp $");
34 
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"
42 
43 /*
44  * The IP v4 address type handling.
45  */
46 
47 /*
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
52  */
53 #define FORMI_DOTTED_QUAD  0
54 #define FORMI_HEX          1
55 #define FORMI_CLASSLESS    2
56 
57 /*
58  * Check the contents of the field buffer are a valid IPv4 address only.
59  */
60 static int
ipv4_check_field(FIELD * field,char * args)61 ipv4_check_field(FIELD *field, char *args)
62 {
63 	char *buf, *buf1, *keeper, *p, *slash;
64 	unsigned int vals[4], style, start, mask;
65 	unsigned long hex_val, working;
66 	int i;
67 
68 	if (args == NULL)
69 		return FALSE;
70 
71 	if (asprintf(&keeper, "%s", args) < 0)
72 		return FALSE;
73 
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;
81 
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;
90 	}
91 
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 */
100 
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;
109 		}
110 		break;
111 
112 
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;
118 
119 		working = hex_val;
120 		for (i = 3; i >= 0; i--) {
121 			vals[i] = (unsigned int)(working & 0xffUL);
122 			working = working >> 8;
123 		}
124 		break;
125 
126 	}
127 
128 	free(keeper);
129 
130 	buf1 = NULL;
131 
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;
141 
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;
150 
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;
158 	}
159 
160 	  /* re-set the field buffer to be the reformatted IPv4 address */
161 	set_field_buffer(field, 0, buf);
162 
163 	  /*
164 	   * Set the field buffer 1 to the dotted quad format regardless
165 	   * of the input format, only if buffer 1 exists.
166 	   */
167 	if (field->nbuf > 1)
168 		set_field_buffer(field, 1, buf1);
169 
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);
176 
177 	return TRUE;
178 
179 	  /* bail out point if we got a bad entry */
180   FAIL:
181 	free(keeper);
182 	return FALSE;
183 
184 }
185 
186 /*
187  * Check the given character is numeric, return TRUE if it is.
188  */
189 static int
ipv4_check_char(int c,char * args)190 ipv4_check_char(/* ARGSUSED1 */ int c, char *args)
191 {
192 	return (isxdigit(c) || (c == '.') || (tolower(c) == 'x') ||
193 		(c == '/'))? TRUE : FALSE;
194 }
195 
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 */
207 };
208 
209 FIELDTYPE *TYPE_IPV4 = &builtin_ipv4;
210 
211 
212