IPv6 address literals in --bind_address (1.19_rc4)
Ivan Nejgebauer <[email protected]>
| Newsgroups | gmane.mail.perdition.user |
|---|---|
| Message-ID | <[email protected]> |
Each server in the --bind_address option list passes through the function user_server_port_strn_assign() (in perdition/server_port.c) which separates the user, server and port components. This function does not recognize IPv6 address literals as documented in RFC 3986 (i.e., IPv6 addresses enclosed in brackets.) For example, address literal [2001:db8:1000:1::2] will be separated into "server" [2001:db8:1000:1: and "port" 2] , which are syntactically incorrect and will produce an error in getaddrinfo(). The enclosed patch adds IPv6 literal handling. (A workaround is to use a "naked" IPv6 address with the port specification, e.g., 2001:db8:1000:1::2:110 , but this is a) ugly and b) not standards-compliant.) i. ______________________________________________ Perdition-users mailing list [email protected] http://lists.vergenet.net/listinfo/perdition-users
ipv6-literal.patch
(text/x-diff, 2.1 KB)
--- perdition/server_port.h.orig 2010-09-29 10:42:01.000000000 +0200
+++ perdition/server_port.h 2010-09-29 10:45:13.000000000 +0200
@@ -32,6 +32,8 @@
#include "str.h"
#define SERVER_PORT_DELIMITER ':'
+#define IPV6_LITERAL_RIGHT_DELIMITER ']'
+#define IPV6_LITERAL_LEFT_DELIMITER '['
/* #defines to destroy and duplicate strings */
#define DESTROY_SP user_server_port_destroy_cb
--- perdition/server_port.c.orig 2010-09-29 10:41:54.000000000 +0200
+++ perdition/server_port.c 2010-09-29 11:37:53.000000000 +0200
@@ -99,6 +99,15 @@
return user_server_port_strn_assign(usp, str, strlen(str));
}
+#define FIX_IPV6_LITERAL \
+do { \
+ char *l; \
+ if (*(*usp)->server != IPV6_LITERAL_LEFT_DELIMITER) \
+ break; \
+ l = strchr((*usp)->server, IPV6_LITERAL_RIGHT_DELIMITER); \
+ (*usp)->server++; \
+ *l = '\0'; \
+} while(0);
/**********************************************************************
* user_server_port_strn_assign
@@ -119,6 +128,7 @@
size_t str_len)
{
int alloced = 0;
+ int ipv6_literal = 0;
if(!*usp) {
*usp = user_server_port_create();
@@ -139,7 +149,19 @@
memset((*usp)->server, 0, str_len + 1);
strncpy((*usp)->server, str, str_len);
- (*usp)->port = strrchr((*usp)->server, SERVER_PORT_DELIMITER);
+ (*usp)->port = strrchr((*usp)->server, IPV6_LITERAL_RIGHT_DELIMITER);
+ if((*usp)->port) {
+ char *l;
+
+ l = strchr((*usp)->server, IPV6_LITERAL_LEFT_DELIMITER);
+ if (l && (*usp)->port - l > 2) { /* at least [::] */
+ ipv6_literal = 1;
+ if (*++(*usp)->port != SERVER_PORT_DELIMITER)
+ (*usp)->port = NULL;
+ }
+ }
+ if (!ipv6_literal)
+ (*usp)->port = strrchr((*usp)->server, SERVER_PORT_DELIMITER);
if((*usp)->port) {
*(*usp)->port = '\0';
(*usp)->port++;
@@ -154,6 +176,8 @@
if((*usp)->server) {
*(*usp)->server = '\0';
(*usp)->server += strlen(opt.domain_delimiter);
+ if (ipv6_literal)
+ FIX_IPV6_LITERAL;
(*usp)->server = strdup((*usp)->server);
if(!(*usp)->server) {
goto strdup_fail;
@@ -161,6 +185,8 @@
}
else {
(*usp)->server = (*usp)->user;
+ if (ipv6_literal)
+ FIX_IPV6_LITERAL;
(*usp)->user = NULL;
}