aboutsummaryrefslogtreecommitdiff
path: root/src
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
parent494f33365cb6b1c8d290fb6ad06aa6be45b880a7 (diff)
downloadgnunet-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.h44
-rw-r--r--src/transport/plugin_transport_tcp.c108
-rw-r--r--src/util/strings.c132
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 */
328int
329GNUNET_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 */
341int
342GNUNET_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 */
358int
359GNUNET_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
542int
543tcp_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
581int
582tcp_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
631tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen, 554tcp_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 */
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 */