diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-03-11 22:45:56 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-03-11 22:45:56 +0000 |
commit | 0746baa7c3e4924ac6a687d0d1fff3b33138eca0 (patch) | |
tree | 22fd4320a4eb7323e817b6e4ac878dec168d65d1 /src | |
parent | 494f33365cb6b1c8d290fb6ad06aa6be45b880a7 (diff) | |
download | gnunet-0746baa7c3e4924ac6a687d0d1fff3b33138eca0.tar.gz gnunet-0746baa7c3e4924ac6a687d0d1fff3b33138eca0.zip |
-LRN: Generalize ip-address str->addr conversion
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_strings_lib.h | 44 | ||||
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 108 | ||||
-rw-r--r-- | src/util/strings.c | 132 |
3 files changed, 202 insertions, 82 deletions
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 385b6c042..2beaa9534 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h | |||
@@ -315,6 +315,50 @@ GNUNET_STRINGS_check_filename (const char *filename, | |||
315 | enum GNUNET_STRINGS_FilenameCheck checks); | 315 | enum GNUNET_STRINGS_FilenameCheck checks); |
316 | 316 | ||
317 | 317 | ||
318 | /** | ||
319 | * Tries to convert @zt_addr string to an IPv6 address. | ||
320 | * | ||
321 | * @param zt_addr 0-terminated string. May be mangled by the function. | ||
322 | * @param addrlen length of zt_addr (not counting 0-terminator). | ||
323 | * @param r_buf a buffer to fill. Initially gets filled with zeroes, | ||
324 | * then its sin6_port, sin6_family and sin6_addr are set appropriately. | ||
325 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which | ||
326 | * case the contents of r_buf are undefined. | ||
327 | */ | ||
328 | int | ||
329 | GNUNET_STRINGS_to_address_ipv6 (char *zt_addr, uint16_t addrlen, | ||
330 | struct sockaddr_in6 *r_buf); | ||
331 | |||
332 | /** | ||
333 | * Tries to convert @zt_addr string to an IPv4 address. | ||
334 | * | ||
335 | * @param zt_addr 0-terminated string. May be mangled by the function. | ||
336 | * @param addrlen length of zt_addr (not counting 0-terminator). | ||
337 | * @param r_buf a buffer to fill. | ||
338 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which case | ||
339 | * the contents of r_buf are undefined. | ||
340 | */ | ||
341 | int | ||
342 | GNUNET_STRINGS_to_address_ipv4 (char *zt_addr, uint16_t addrlen, | ||
343 | struct sockaddr_in *r_buf); | ||
344 | |||
345 | /** | ||
346 | * Tries to convert @addr string to an IP (v4 or v6) address. | ||
347 | * IPv6 address must have its address part enclosed in '()' parens | ||
348 | * instead of '[]'. | ||
349 | * Will automatically decide whether to treat @addr as v4 or v6 address. | ||
350 | * | ||
351 | * @param addr a string, may not be 0-terminated. | ||
352 | * @param addrlen number of bytes in addr (if addr is 0-terminated, | ||
353 | * 0-terminator should not be counted towards addrlen). | ||
354 | * @param r_buf a buffer to fill. | ||
355 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which | ||
356 | * case the contents of r_buf are undefined. | ||
357 | */ | ||
358 | int | ||
359 | GNUNET_STRINGS_to_address_ip (const char *addr, uint16_t addrlen, | ||
360 | struct sockaddr_storage *r_buf); | ||
361 | |||
318 | /* ifndef GNUNET_UTIL_STRING_H */ | 362 | /* ifndef GNUNET_UTIL_STRING_H */ |
319 | #endif | 363 | #endif |
320 | /* end of gnunet_util_string.h */ | 364 | /* end of gnunet_util_string.h */ |
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index e10dd74c1..e5d3014bc 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -537,82 +537,6 @@ tcp_address_to_string (void *cls, const void *addr, size_t addrlen) | |||
537 | return rbuf; | 537 | return rbuf; |
538 | } | 538 | } |
539 | 539 | ||
540 | #define MAX_IPV6_ADDRLEN 47 | ||
541 | |||
542 | int | ||
543 | tcp_string_to_address_ipv6 (void *cls, const char *addr, uint16_t addrlen, | ||
544 | void **buf, size_t *added) | ||
545 | { | ||
546 | char zt_addr[MAX_IPV6_ADDRLEN + 1]; | ||
547 | int ret; | ||
548 | char *port_colon; | ||
549 | unsigned int port; | ||
550 | struct IPv6TcpAddress *ipv6addr; | ||
551 | |||
552 | if (addrlen < 6) | ||
553 | return GNUNET_SYSERR; | ||
554 | |||
555 | memset (zt_addr, 0, MAX_IPV6_ADDRLEN + 1); | ||
556 | strncpy (zt_addr, addr, addrlen <= MAX_IPV6_ADDRLEN ? addrlen : MAX_IPV6_ADDRLEN); | ||
557 | |||
558 | port_colon = strrchr (zt_addr, ':'); | ||
559 | if (port_colon == NULL) | ||
560 | return GNUNET_SYSERR; | ||
561 | ret = sscanf (port_colon, ":%u", &port); | ||
562 | if (ret != 1 || port > 65535) | ||
563 | return GNUNET_SYSERR; | ||
564 | port_colon[0] = '\0'; | ||
565 | |||
566 | ipv6addr = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | ||
567 | ret = inet_pton (AF_INET6, zt_addr, &ipv6addr->ipv6_addr); | ||
568 | if (ret <= 0) | ||
569 | { | ||
570 | GNUNET_free (ipv6addr); | ||
571 | return GNUNET_SYSERR; | ||
572 | } | ||
573 | ipv6addr->t6_port = port; | ||
574 | *buf = ipv6addr; | ||
575 | *added = sizeof (struct IPv6TcpAddress); | ||
576 | return GNUNET_OK; | ||
577 | } | ||
578 | |||
579 | #define MAX_IPV4_ADDRLEN 21 | ||
580 | |||
581 | int | ||
582 | tcp_string_to_address_ipv4 (void *cls, const char *addr, uint16_t addrlen, | ||
583 | void **buf, size_t *added) | ||
584 | { | ||
585 | unsigned int temps[5]; | ||
586 | unsigned int port; | ||
587 | int cnt; | ||
588 | char zt_addr[MAX_IPV4_ADDRLEN + 1]; | ||
589 | struct IPv4TcpAddress *ipv4addr; | ||
590 | |||
591 | if (addrlen < 9) | ||
592 | return GNUNET_SYSERR; | ||
593 | |||
594 | memset (zt_addr, 0, MAX_IPV4_ADDRLEN + 1); | ||
595 | strncpy (zt_addr, addr, addrlen <= MAX_IPV4_ADDRLEN ? addrlen : MAX_IPV4_ADDRLEN); | ||
596 | |||
597 | cnt = sscanf (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port); | ||
598 | if (cnt != 5) | ||
599 | return GNUNET_SYSERR; | ||
600 | |||
601 | for (cnt = 0; cnt < 4; cnt++) | ||
602 | if (temps[cnt] > 0xFF) | ||
603 | return GNUNET_SYSERR; | ||
604 | if (port > 65535) | ||
605 | return GNUNET_SYSERR; | ||
606 | |||
607 | ipv4addr = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | ||
608 | ipv4addr->ipv4_addr = | ||
609 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
610 | temps[3]); | ||
611 | ipv4addr->t4_port = htonl (port); | ||
612 | *buf = ipv4addr; | ||
613 | *added = sizeof (struct IPv4TcpAddress); | ||
614 | return GNUNET_OK; | ||
615 | } | ||
616 | 540 | ||
617 | /** | 541 | /** |
618 | * Function called to convert a string address to | 542 | * Function called to convert a string address to |
@@ -622,7 +546,6 @@ tcp_string_to_address_ipv4 (void *cls, const char *addr, uint16_t addrlen, | |||
622 | * @param addr string address | 546 | * @param addr string address |
623 | * @param addrlen length of the address | 547 | * @param addrlen length of the address |
624 | * @param buf location to store the buffer | 548 | * @param buf location to store the buffer |
625 | * @param max size of the buffer | ||
626 | * @param added location to store the number of bytes in the buffer. | 549 | * @param added location to store the number of bytes in the buffer. |
627 | * If the function returns GNUNET_SYSERR, its contents are undefined. | 550 | * If the function returns GNUNET_SYSERR, its contents are undefined. |
628 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | 551 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure |
@@ -631,13 +554,34 @@ int | |||
631 | tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen, | 554 | tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen, |
632 | void **buf, size_t *added) | 555 | void **buf, size_t *added) |
633 | { | 556 | { |
634 | if (addrlen < 1) | 557 | struct sockaddr_storage socket_address; |
558 | int ret = GNUNET_STRINGS_to_address_ip (addr, addrlen, | ||
559 | &socket_address); | ||
560 | |||
561 | if (ret != GNUNET_OK) | ||
635 | return GNUNET_SYSERR; | 562 | return GNUNET_SYSERR; |
636 | 563 | ||
637 | if (addr[0] == '(') | 564 | if (socket_address.ss_family == AF_INET) |
638 | return tcp_string_to_address_ipv6 (cls, addr, addrlen, buf, added); | 565 | { |
639 | else | 566 | struct IPv4TcpAddress *t4; |
640 | return tcp_string_to_address_ipv4 (cls, addr, addrlen, buf, added); | 567 | struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address; |
568 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | ||
569 | t4->ipv4_addr = in4->sin_addr.s_addr; | ||
570 | t4->t4_port = in4->sin_port; | ||
571 | *buf = t4; | ||
572 | *added = sizeof (struct IPv4TcpAddress); | ||
573 | } | ||
574 | else if (socket_address.ss_family == AF_INET6) | ||
575 | { | ||
576 | struct IPv6TcpAddress *t6; | ||
577 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address; | ||
578 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | ||
579 | t6->ipv6_addr = in6->sin6_addr; | ||
580 | t6->t6_port = in6->sin6_port; | ||
581 | *buf = t6; | ||
582 | *added = sizeof (struct IPv6TcpAddress); | ||
583 | } | ||
584 | return GNUNET_SYSERR; | ||
641 | } | 585 | } |
642 | 586 | ||
643 | 587 | ||
diff --git a/src/util/strings.c b/src/util/strings.c index abc763b88..a6a5c7542 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -950,4 +950,136 @@ GNUNET_STRINGS_check_filename (const char *filename, | |||
950 | return GNUNET_YES; | 950 | return GNUNET_YES; |
951 | } | 951 | } |
952 | 952 | ||
953 | #define MAX_IPV6_ADDRLEN 47 | ||
954 | #define MAX_IPV4_ADDRLEN 21 | ||
955 | #define MAX_IP_ADDRLEN MAX_IPV6_ADDRLEN | ||
956 | |||
957 | /** | ||
958 | * Tries to convert @zt_addr string to an IPv6 address. | ||
959 | * | ||
960 | * @param zt_addr 0-terminated string. May be mangled by the function. | ||
961 | * @param addrlen length of zt_addr (not counting 0-terminator). | ||
962 | * @param r_buf a buffer to fill. Initially gets filled with zeroes, | ||
963 | * then its sin6_port, sin6_family and sin6_addr are set appropriately. | ||
964 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which | ||
965 | * case the contents of r_buf are undefined. | ||
966 | */ | ||
967 | int | ||
968 | GNUNET_STRINGS_to_address_ipv6 (char *zt_addr, uint16_t addrlen, | ||
969 | struct sockaddr_in6 *r_buf) | ||
970 | { | ||
971 | int ret; | ||
972 | char *port_colon; | ||
973 | unsigned int port; | ||
974 | |||
975 | if (addrlen < 6) | ||
976 | return GNUNET_SYSERR; | ||
977 | |||
978 | port_colon = strrchr (zt_addr, ':'); | ||
979 | if (port_colon == NULL) | ||
980 | return GNUNET_SYSERR; | ||
981 | ret = sscanf (port_colon, ":%u", &port); | ||
982 | if (ret != 1 || port > 65535) | ||
983 | return GNUNET_SYSERR; | ||
984 | port_colon[0] = '\0'; | ||
985 | |||
986 | memset (r_buf, 0, sizeof (struct sockaddr_in6)); | ||
987 | ret = inet_pton (AF_INET6, zt_addr, &r_buf->sin6_addr); | ||
988 | if (ret <= 0) | ||
989 | return GNUNET_SYSERR; | ||
990 | r_buf->sin6_port = htonl (port); | ||
991 | r_buf->sin6_family = AF_INET6; | ||
992 | return GNUNET_OK; | ||
993 | } | ||
994 | |||
995 | /** | ||
996 | * Tries to convert @zt_addr string to an IPv4 address. | ||
997 | * | ||
998 | * @param zt_addr 0-terminated string. May be mangled by the function. | ||
999 | * @param addrlen length of zt_addr (not counting 0-terminator). | ||
1000 | * @param r_buf a buffer to fill. | ||
1001 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which case | ||
1002 | * the contents of r_buf are undefined. | ||
1003 | */ | ||
1004 | int | ||
1005 | GNUNET_STRINGS_to_address_ipv4 (char *zt_addr, uint16_t addrlen, | ||
1006 | struct sockaddr_in *r_buf) | ||
1007 | { | ||
1008 | unsigned int temps[5]; | ||
1009 | unsigned int port; | ||
1010 | int cnt; | ||
1011 | |||
1012 | if (addrlen < 9) | ||
1013 | return GNUNET_SYSERR; | ||
1014 | |||
1015 | cnt = sscanf (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port); | ||
1016 | if (cnt != 5) | ||
1017 | return GNUNET_SYSERR; | ||
1018 | |||
1019 | for (cnt = 0; cnt < 4; cnt++) | ||
1020 | if (temps[cnt] > 0xFF) | ||
1021 | return GNUNET_SYSERR; | ||
1022 | if (port > 65535) | ||
1023 | return GNUNET_SYSERR; | ||
1024 | |||
1025 | r_buf->sin_family = AF_INET; | ||
1026 | r_buf->sin_port = htonl (port); | ||
1027 | r_buf->sin_addr.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + | ||
1028 | (temps[2] << 8) + temps[3]); | ||
1029 | return GNUNET_OK; | ||
1030 | } | ||
1031 | |||
1032 | /** | ||
1033 | * Tries to convert @addr string to an IP (v4 or v6) address. | ||
1034 | * IPv6 address must have its address part enclosed in '()' parens | ||
1035 | * instead of '[]'. | ||
1036 | * Will automatically decide whether to treat @addr as v4 or v6 address. | ||
1037 | * | ||
1038 | * @param addr a string, may not be 0-terminated. | ||
1039 | * @param addrlen number of bytes in addr (if addr is 0-terminated, | ||
1040 | * 0-terminator should not be counted towards addrlen). | ||
1041 | * @param r_buf a buffer to fill. | ||
1042 | * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which | ||
1043 | * case the contents of r_buf are undefined. | ||
1044 | */ | ||
1045 | int | ||
1046 | GNUNET_STRINGS_to_address_ip (const char *addr, uint16_t addrlen, | ||
1047 | struct sockaddr_storage *r_buf) | ||
1048 | { | ||
1049 | uint16_t i; | ||
1050 | char zt_addr[MAX_IP_ADDRLEN + 1]; | ||
1051 | uint16_t zt_len = addrlen <= MAX_IP_ADDRLEN ? addrlen : MAX_IP_ADDRLEN; | ||
1052 | |||
1053 | if (addrlen < 1) | ||
1054 | return GNUNET_SYSERR; | ||
1055 | |||
1056 | memset (zt_addr, 0, MAX_IP_ADDRLEN + 1); | ||
1057 | strncpy (zt_addr, addr, zt_len); | ||
1058 | |||
1059 | /* For URIs we use '(' and ')' instead of '[' and ']'. Do the substitution | ||
1060 | * now, as GNUNET_STRINGS_to_address_ipv6() takes a proper []-enclosed IPv6 | ||
1061 | * address. | ||
1062 | */ | ||
1063 | if (zt_addr[0] == '(') | ||
1064 | { | ||
1065 | for (i = 0; i < zt_len; i++) | ||
1066 | { | ||
1067 | switch (zt_addr[i]) | ||
1068 | { | ||
1069 | case '(': | ||
1070 | zt_addr[i] = '['; | ||
1071 | break; | ||
1072 | case ')': | ||
1073 | zt_addr[i] = ']'; | ||
1074 | break; | ||
1075 | default: | ||
1076 | break; | ||
1077 | } | ||
1078 | } | ||
1079 | return GNUNET_STRINGS_to_address_ipv6 (zt_addr, zt_len, (struct sockaddr_in6 *) r_buf); | ||
1080 | } | ||
1081 | else | ||
1082 | return GNUNET_STRINGS_to_address_ipv4 (zt_addr, zt_len, (struct sockaddr_in *) r_buf); | ||
1083 | } | ||
1084 | |||
953 | /* end of strings.c */ | 1085 | /* end of strings.c */ |