aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-11 22:45:56 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-11 22:45:56 +0000
commit0746baa7c3e4924ac6a687d0d1fff3b33138eca0 (patch)
tree22fd4320a4eb7323e817b6e4ac878dec168d65d1 /src/util
parent494f33365cb6b1c8d290fb6ad06aa6be45b880a7 (diff)
downloadgnunet-0746baa7c3e4924ac6a687d0d1fff3b33138eca0.tar.gz
gnunet-0746baa7c3e4924ac6a687d0d1fff3b33138eca0.zip
-LRN: Generalize ip-address str->addr conversion
Diffstat (limited to 'src/util')
-rw-r--r--src/util/strings.c132
1 files changed, 132 insertions, 0 deletions
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 */
967int
968GNUNET_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 */
1004int
1005GNUNET_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 */
1045int
1046GNUNET_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 */