16 #include "item_inetfunc.h"
22 static const int IN_ADDR_SIZE=
sizeof (in_addr);
23 static const int IN6_ADDR_SIZE=
sizeof (
in6_addr);
24 static const int IN6_ADDR_NUM_WORDS= IN6_ADDR_SIZE / 2;
26 static const char HEX_DIGITS[]=
"0123456789abcdef";
30 longlong Item_func_inet_aton::val_int()
41 String tmp(buff,
sizeof (buff), &my_charset_latin1);
42 String *s= args[0]->val_str_ascii(&tmp);
54 int digit= (int) (c -
'0');
55 if (digit >= 0 && digit <= 9)
57 byte_result= byte_result * 10 + digit;
58 if (byte_result > 255)
64 result= (result << 8) + (ulonglong) byte_result;
85 return (result << 8) + (ulonglong) byte_result;
99 ulonglong
n= (ulonglong) args[0]->val_int();
107 null_value= args[0]->null_value || n > (ulonglong) LL(4294967295);
112 str->set_charset(collation.collation);
123 for (uchar *p= buf + 4; p-- >
buf;)
131 num[0]= (char) n1 +
'0';
132 num[1]= (char) n2 +
'0';
133 num[2]= (char) c +
'0';
134 uint length= (n1 ? 4 : n2 ? 3 : 2);
135 uint dot_length= (p <=
buf) ? 1 : 0;
137 str->append(num + 4 - length, length - dot_length, &my_charset_latin1);
155 if (args[0]->result_type() != STRING_RESULT)
159 String *arg_str= args[0]->val_str(&buffer);
164 return calc_value(arg_str) ? 1 : 0;
181 if (args[0]->result_type() != STRING_RESULT)
187 String *arg_str= args[0]->val_str(buffer);
194 null_value= !calc_value(arg_str, buffer);
196 return null_value ? NULL : buffer;
217 static bool str_to_ipv4(
const char *str,
int str_length, in_addr *ipv4_address)
221 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): "
222 "invalid IPv4 address: too short.",
229 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): "
230 "invalid IPv4 address: too long.",
235 unsigned char *ipv4_bytes= (
unsigned char *) ipv4_address;
238 int chars_in_group= 0;
242 while (((p - str) < str_length) && *p)
246 if (my_isdigit(&my_charset_latin1, c))
250 if (chars_in_group > 3)
252 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
253 "too many characters in a group.",
258 byte_value= byte_value * 10 + (c -
'0');
260 if (byte_value > 255)
262 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
263 "invalid byte value.",
270 if (chars_in_group == 0)
272 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
273 "too few characters in a group.",
278 ipv4_bytes[dot_count]= (
unsigned char) byte_value;
286 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
287 "too many dots.", str_length, str));
293 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
294 "invalid character at pos %d.",
295 str_length, str, (
int) (p - str)));
302 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
303 "ending at '.'.", str_length, str));
309 DBUG_PRINT(
"error", (
"str_to_ipv4(%.*s): invalid IPv4 address: "
315 ipv4_bytes[3]= (
unsigned char) byte_value;
317 DBUG_PRINT(
"info", (
"str_to_ipv4(%.*s): valid IPv4 address: %d.%d.%d.%d",
319 ipv4_bytes[0], ipv4_bytes[1],
320 ipv4_bytes[2], ipv4_bytes[3]));
342 static bool str_to_ipv6(
const char *str,
int str_length,
in6_addr *ipv6_address)
346 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: too short.",
351 if (str_length > 8 * 4 + 7)
353 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: too long.",
358 memset(ipv6_address, 0, IN6_ADDR_SIZE);
368 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
369 "can not start with ':x'.", str_length, str));
374 char *ipv6_bytes= (
char *) ipv6_address;
375 char *ipv6_bytes_end= ipv6_bytes + IN6_ADDR_SIZE;
376 char *dst= ipv6_bytes;
378 const char *group_start_ptr= p;
379 int chars_in_group= 0;
382 while (((p - str) < str_length) && *p)
394 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
395 "too many gaps(::).", str_length, str));
403 if (!*p || ((p - str) >= str_length))
405 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
406 "ending at ':'.", str_length, str));
410 if (dst + 2 > ipv6_bytes_end)
412 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
413 "too many groups (1).", str_length, str));
417 dst[0]= (
unsigned char) (group_value >> 8) & 0xff;
418 dst[1]= (
unsigned char) group_value & 0xff;
426 if (dst + IN_ADDR_SIZE > ipv6_bytes_end)
428 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
429 "unexpected IPv4-part.", str_length, str));
433 if (!str_to_ipv4(group_start_ptr,
434 str + str_length - group_start_ptr,
437 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
438 "invalid IPv4-part.", str_length, str));
449 const char *hdp= strchr(HEX_DIGITS, my_tolower(&my_charset_latin1, c));
453 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
454 "invalid character at pos %d.",
455 str_length, str, (
int) (p - str)));
459 if (chars_in_group >= 4)
461 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
462 "too many digits in group.",
468 group_value |= hdp - HEX_DIGITS;
470 DBUG_ASSERT(group_value <= 0xffff);
476 if (chars_in_group > 0)
478 if (dst + 2 > ipv6_bytes_end)
480 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
481 "too many groups (2).", str_length, str));
485 dst[0]= (
unsigned char) (group_value >> 8) & 0xff;
486 dst[1]= (
unsigned char) group_value & 0xff;
492 if (dst == ipv6_bytes_end)
494 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
495 "no room for a gap (::).", str_length, str));
499 int bytes_to_move= dst - gap_ptr;
501 for (
int i= 1;
i <= bytes_to_move; ++
i)
503 ipv6_bytes_end[-
i]= gap_ptr[bytes_to_move -
i];
504 gap_ptr[bytes_to_move -
i]= 0;
510 if (dst < ipv6_bytes_end)
512 DBUG_PRINT(
"error", (
"str_to_ipv6(%.*s): invalid IPv6 address: "
513 "too few groups.", str_length, str));
534 static void ipv4_to_str(
const in_addr *ipv4,
char *str)
536 const unsigned char *ipv4_bytes= (
const unsigned char *) ipv4;
538 sprintf(str,
"%d.%d.%d.%d",
539 ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3]);
555 static void ipv6_to_str(
const in6_addr *ipv6,
char *str)
563 const unsigned char *ipv6_bytes= (
const unsigned char *) ipv6;
569 uint16 ipv6_words[IN6_ADDR_NUM_WORDS];
571 for (
int i= 0;
i < IN6_ADDR_NUM_WORDS; ++
i)
572 ipv6_words[
i]= (ipv6_bytes[2 *
i] << 8) + ipv6_bytes[2 *
i + 1];
576 Region gap= { -1, -1 };
579 Region rg= { -1, -1 };
581 for (
int i = 0;
i < IN6_ADDR_NUM_WORDS; ++
i)
583 if (ipv6_words[
i] != 0)
587 if (rg.length > gap.length)
610 if (rg.length > gap.length)
619 for (
int i = 0;
i < IN6_ADDR_NUM_WORDS; ++
i)
640 else if (
i == 6 && gap.pos == 0 &&
642 (gap.length == 5 && ipv6_words[5] == 0xffff)
649 ipv4_to_str((
const in_addr *) (ipv6_bytes + 12), p);
659 p += sprintf(p,
"%x", ipv6_words[
i]);
661 if (
i != IN6_ADDR_NUM_WORDS - 1)
690 in_addr ipv4_address;
693 if (str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address))
696 buffer->append((
char *) &ipv4_address,
sizeof (in_addr), &my_charset_bin);
701 if (str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address))
704 buffer->append((
char *) &ipv6_address,
sizeof (
in6_addr), &my_charset_bin);
727 if (arg->charset() != &my_charset_bin)
730 if ((
int) arg->length() == IN_ADDR_SIZE)
732 char str[INET_ADDRSTRLEN];
734 ipv4_to_str((
const in_addr *) arg->ptr(), str);
737 buffer->append(str, (uint32) strlen(str), &my_charset_latin1);
741 else if ((
int) arg->length() == IN6_ADDR_SIZE)
743 char str[INET6_ADDRSTRLEN];
745 ipv6_to_str((
const in6_addr *) arg->ptr(), str);
748 buffer->append(str, (uint32) strlen(str), &my_charset_latin1);
754 (
"INET6_NTOA(): varbinary(4) or varbinary(16) expected."));
772 in_addr ipv4_address;
774 return str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address);
793 return str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address);
810 if ((
int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin)
813 return IN6_IS_ADDR_V4COMPAT((
struct in6_addr *) arg->ptr());
830 if ((
int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin)
833 return IN6_IS_ADDR_V4MAPPED((
struct in6_addr *) arg->ptr());