usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / vsftpd / ipaddrparse.c
bloba4a72150486fdfb1e9dc5d265eb392e569023d86
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * ipaddrparse.c
7 * A routine to parse ip addresses. I'm paranoid and don't want to use
8 * inet_pton.
9 */
11 #include "ipaddrparse.h"
12 #include "sysutil.h"
13 #include "str.h"
15 static int ipv6_parse_main(struct mystr* p_out_str,
16 const struct mystr* p_in_str);
17 static int ipv6_parse_hex(struct mystr* p_out_str,
18 const struct mystr* p_in_str);
19 static int ipv4_parse_dotquad(struct mystr* p_out_str,
20 const struct mystr* p_in_str);
22 const unsigned char*
23 vsf_sysutil_parse_ipv6(const struct mystr* p_str)
25 static struct mystr s_ret;
26 static struct mystr s_rhs_ret;
27 static struct mystr s_lhs_str;
28 static struct mystr s_rhs_str;
29 unsigned int lhs_len;
30 unsigned int rhs_len;
31 str_empty(&s_ret);
32 str_empty(&s_rhs_ret);
33 str_copy(&s_lhs_str, p_str);
34 str_split_text(&s_lhs_str, &s_rhs_str, "::");
35 if (!ipv6_parse_main(&s_ret, &s_lhs_str))
37 return 0;
39 if (!ipv6_parse_main(&s_rhs_ret, &s_rhs_str))
41 return 0;
43 lhs_len = str_getlen(&s_ret);
44 rhs_len = str_getlen(&s_rhs_ret);
45 if (lhs_len + rhs_len > 16)
47 return 0;
49 if (rhs_len > 0)
51 unsigned int add_nulls = 16 - (lhs_len + rhs_len);
52 while (add_nulls--)
54 str_append_char(&s_ret, '\0');
56 str_append_str(&s_ret, &s_rhs_ret);
58 return (const unsigned char*) str_getbuf(&s_ret);
61 const unsigned char*
62 vsf_sysutil_parse_ipv4(const struct mystr* p_str)
64 static unsigned char items[4];
65 return vsf_sysutil_parse_uchar_string_sep(p_str, '.', items, sizeof(items));
68 const unsigned char*
69 vsf_sysutil_parse_uchar_string_sep(
70 const struct mystr* p_str, char sep, unsigned char* p_items,
71 unsigned int items)
73 static struct mystr s_tmp_str;
74 unsigned int i;
75 str_copy(&s_tmp_str, p_str);
76 for (i=0; i<items; i++)
78 static struct mystr s_rhs_sep_str;
79 int this_number;
80 /* This puts a single separator delimited field in tmp_str */
81 str_split_char(&s_tmp_str, &s_rhs_sep_str, sep);
82 /* Sanity - check for too many or two few dots! */
83 if ( (i < (items-1) && str_isempty(&s_rhs_sep_str)) ||
84 (i == (items-1) && !str_isempty(&s_rhs_sep_str)))
86 return 0;
88 this_number = str_atoi(&s_tmp_str);
89 if (this_number < 0 || this_number > 255)
91 return 0;
93 /* If this truncates from int to uchar, we don't care */
94 p_items[i] = (unsigned char) this_number;
95 /* The right hand side of the comma now becomes the new string to
96 * breakdown
98 str_copy(&s_tmp_str, &s_rhs_sep_str);
100 return p_items;
103 static int
104 ipv6_parse_main(struct mystr* p_out_str, const struct mystr* p_in_str)
106 static struct mystr s_lhs_str;
107 static struct mystr s_rhs_str;
108 struct str_locate_result loc_ret;
109 str_copy(&s_lhs_str, p_in_str);
110 while (!str_isempty(&s_lhs_str))
112 str_split_char(&s_lhs_str, &s_rhs_str, ':');
113 if (str_isempty(&s_lhs_str))
115 return 0;
117 loc_ret = str_locate_char(&s_lhs_str, '.');
118 if (loc_ret.found)
120 if (!ipv4_parse_dotquad(p_out_str, &s_lhs_str))
122 return 0;
125 else if (!ipv6_parse_hex(p_out_str, &s_lhs_str))
127 return 0;
129 str_copy(&s_lhs_str, &s_rhs_str);
131 return 1;
134 static int
135 ipv6_parse_hex(struct mystr* p_out_str, const struct mystr* p_in_str)
137 unsigned int len = str_getlen(p_in_str);
138 unsigned int i;
139 unsigned int val = 0;
140 for (i=0; i<len; ++i)
142 int ch = vsf_sysutil_toupper(str_get_char_at(p_in_str, i));
143 if (ch >= '0' && ch <= '9')
145 ch -= '0';
147 else if (ch >= 'A' && ch <= 'F')
149 ch -= 'A';
150 ch += 10;
152 else
154 return 0;
156 val <<= 4;
157 val |= ch;
158 if (val > 0xFFFF)
160 return 0;
163 str_append_char(p_out_str, (val >> 8));
164 str_append_char(p_out_str, (val & 0xFF));
165 return 1;
168 static int
169 ipv4_parse_dotquad(struct mystr* p_out_str, const struct mystr* p_in_str)
171 unsigned int len = str_getlen(p_in_str);
172 unsigned int i;
173 unsigned int val = 0;
174 unsigned int final_val = 0;
175 int seen_char = 0;
176 int dots = 0;
177 for (i=0; i<len; ++i)
179 int ch = str_get_char_at(p_in_str, i);
180 if (ch == '.')
182 if (!seen_char || dots == 3)
184 return 0;
186 seen_char = 0;
187 dots++;
188 final_val <<= 8;
189 final_val |= val;
190 val = 0;
192 else if (ch >= '0' && ch <= '9')
194 ch -= '0';
195 val *= 10;
196 val += ch;
197 if (val > 255)
199 return 0;
201 seen_char = 1;
203 else
205 return 0;
208 if (dots != 3 || !seen_char)
210 return 0;
212 final_val <<= 8;
213 final_val |= val;
214 str_append_char(p_out_str, (final_val >> 24));
215 str_append_char(p_out_str, ((final_val >> 16) & 0xFF));
216 str_append_char(p_out_str, ((final_val >> 8) & 0xFF));
217 str_append_char(p_out_str, (final_val & 0xFF));
218 return 1;