2 * Part of Very Secure FTPd
7 * A routine to parse ip addresses. I'm paranoid and don't want to use
11 #include "ipaddrparse.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
);
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
;
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
))
39 if (!ipv6_parse_main(&s_rhs_ret
, &s_rhs_str
))
43 lhs_len
= str_getlen(&s_ret
);
44 rhs_len
= str_getlen(&s_rhs_ret
);
45 if (lhs_len
+ rhs_len
> 16)
51 unsigned int add_nulls
= 16 - (lhs_len
+ rhs_len
);
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
);
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
));
69 vsf_sysutil_parse_uchar_string_sep(
70 const struct mystr
* p_str
, char sep
, unsigned char* p_items
,
73 static struct mystr s_tmp_str
;
75 str_copy(&s_tmp_str
, p_str
);
76 for (i
=0; i
<items
; i
++)
78 static struct mystr s_rhs_sep_str
;
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
)))
88 this_number
= str_atoi(&s_tmp_str
);
89 if (this_number
< 0 || this_number
> 255)
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
98 str_copy(&s_tmp_str
, &s_rhs_sep_str
);
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
))
117 loc_ret
= str_locate_char(&s_lhs_str
, '.');
120 if (!ipv4_parse_dotquad(p_out_str
, &s_lhs_str
))
125 else if (!ipv6_parse_hex(p_out_str
, &s_lhs_str
))
129 str_copy(&s_lhs_str
, &s_rhs_str
);
135 ipv6_parse_hex(struct mystr
* p_out_str
, const struct mystr
* p_in_str
)
137 unsigned int len
= str_getlen(p_in_str
);
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')
147 else if (ch
>= 'A' && ch
<= 'F')
163 str_append_char(p_out_str
, (val
>> 8));
164 str_append_char(p_out_str
, (val
& 0xFF));
169 ipv4_parse_dotquad(struct mystr
* p_out_str
, const struct mystr
* p_in_str
)
171 unsigned int len
= str_getlen(p_in_str
);
173 unsigned int val
= 0;
174 unsigned int final_val
= 0;
177 for (i
=0; i
<len
; ++i
)
179 int ch
= str_get_char_at(p_in_str
, i
);
182 if (!seen_char
|| dots
== 3)
192 else if (ch
>= '0' && ch
<= '9')
208 if (dots
!= 3 || !seen_char
)
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));