Skip to Content.
Sympa Menu

ndt-dev - [ndt-dev] [ndt] r816 committed - Fix for IPv4-mapped IPv6 socket handling. This branch should not only ...

Subject: NDT-DEV email list created

List archive

[ndt-dev] [ndt] r816 committed - Fix for IPv4-mapped IPv6 socket handling. This branch should not only ...


Chronological Thread 
  • From:
  • To:
  • Subject: [ndt-dev] [ndt] r816 committed - Fix for IPv4-mapped IPv6 socket handling. This branch should not only ...
  • Date: Sun, 14 Apr 2013 02:56:26 +0000
  • Authentication-results: sfpop-ironport05.merit.edu; dkim=neutral (message not signed) header.i=none

Revision: 816
Author:

Date: Sat Apr 13 19:56:13 2013
Log: Fix for IPv4-mapped IPv6 socket handling. This branch should not only compile but also work correctly now.
Fix for network.c/OpenSocket() this was modifying the list returned by getaddrinfo() by changing an ai_next pointer within it, creating a loop resulting in a double free when freeaddrinfo() is called.
http://code.google.com/p/ndt/source/detail?r=816

Modified:
/branches/ndt-web10g/WEB10G_README
/branches/ndt-web10g/configure.ac
/branches/ndt-web10g/src/network.c
/branches/ndt-web10g/src/test_mid_srv.c
/branches/ndt-web10g/src/web100srv.h
/branches/ndt-web10g/src/web10g-util.c

=======================================
--- /branches/ndt-web10g/WEB10G_README Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/WEB10G_README Sat Apr 13 19:56:13 2013
@@ -5,13 +5,15 @@

You need to make and install the Web10G-userland library I used Web10G-userland-2.0.4.

+NOTE: The older estats-userlands are not supported so the 3.2 kernel and earlier will not work.
+
Configure and build ndt as normal. Web10G libs should be detected and hence the web10gsrv built. Web100 is still fully supported and if Web100 libs are found web100srv will be built.

Known issues

Web10G related
* Logging functionality not yet implemented some related functions are missing.
-* Web10g patch not quite right - need to modify ktime_to_ns to ktime_to_us.
+* Web10g kernel patch not quite right - need to modify ktime_to_ns to ktime_to_us.
* Server and Client(C and Java Applet) have been ported, other tools have not. Depending on their function they may not work.

Other
=======================================
--- /branches/ndt-web10g/configure.ac Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/configure.ac Sat Apr 13 19:56:13 2013
@@ -291,7 +291,11 @@
echo ""

if test -z "$HAVE_TCPE_TRUE" && test -n "$HAVE_TCPE_FALSE"; then
+if test -z "$HAVE_PCAP_H_TRUE" && test -n "$HAVE_PCAP_H_FALSE"; then
SUMMARY_WEB10GSRV="YES"
+else
+ SUMMARY_WEB10GSRV="NO (missing pcap headers)"
+fi
else
SUMMARY_WEB10GSRV="NO (missing tcpe (web10g) library)"
fi
=======================================
--- /branches/ndt-web10g/src/network.c Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/src/network.c Sat Apr 13 19:56:13 2013
@@ -30,29 +30,47 @@
#error This file assumes AF_INET6 is defined.
#endif

+struct ai_node {
+ struct addrinfo* ai;
+ struct ai_node* next;
+};
+
static int OpenSocket(I2Addr addr, char* serv, int options) {
int fd = -1;
int return_code = 0;

+ // Keep a list of all ipv4 and ipv6 addresses we come across
+ // So we can search for ipv6 first
+ struct ai_node ipv4_list[5] = {{NULL}};
+ struct ai_node ipv6_list[5] = {{NULL}};
struct addrinfo *fai = NULL;
+ struct ai_node *fain = NULL;
+
if (!(fai = I2AddrAddrInfo(addr, NULL, serv))) {
return -2;
}

- struct addrinfo* ai_ipv6 = NULL;
- struct addrinfo* ai_ipv4 = NULL;
+ struct ai_node* ain_ipv6 = &ipv6_list[0];
+ struct ai_node* ain_ipv4 = &ipv4_list[0];

- // Get references to the first IPv6 and first IPv4 addresses. If INET6 support
- // is not compiled in, ignore AF_INET6 entries.
- // TODO: build lists of all IPv6 and IPv4 entries.
+ // Get lists of all IPv6 and IPv4 addresses.
for (struct addrinfo* ai = fai; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family == AF_INET6 && ai_ipv6 == NULL)
- ai_ipv6 = ai;
- else if (ai->ai_family == AF_INET && ai_ipv4 == NULL)
- ai_ipv4 = ai;
- if (ai_ipv4 != NULL && ai_ipv6 != NULL)
- break;
+ if (ai->ai_family == AF_INET6 && ain_ipv6 <= &ipv6_list[4]){
+ if(ain_ipv6->ai != NULL){
+ ain_ipv6 += 1;
+ ain_ipv6->next = ain_ipv6 + 1;
+ }
+ ain_ipv6->ai = ai;
+ }
+ else if (ai->ai_family == AF_INET && ain_ipv4 <= &ipv4_list[4]){
+ if(ain_ipv4->ai != NULL){
+ ain_ipv4 += 1;
+ ain_ipv4->next = ain_ipv4 + 1;
+ }
+ ain_ipv4->ai = ai;
+ }
}
+

// Determine which family the user would prefer, based on command line.
int family = AF_UNSPEC;
@@ -63,16 +81,23 @@
family = AF_INET;

// Prefer IPv6.
- if (family == AF_UNSPEC || family == AF_INET6) {
- fai = ai_ipv6;
- fai->ai_next = ai_ipv4;
+ if ( (family == AF_UNSPEC || family == AF_INET6)
+ && ipv6_list[0].ai != NULL) {
+ fain = &ipv6_list[0];
+ // Link IPv4 onto the end as a fallback
+ if(ipv4_list[0].ai != NULL){
+ ain_ipv6->next = &ipv4_list[0];
+ }
} else {
- fai = ai_ipv4;
+ if(ipv4_list[0].ai != NULL)
+ fain = &ipv4_list[0];
+ else
+ fain = NULL;
}

// Attempt to connect to one of the chosen addresses.
struct addrinfo* ai = NULL;
- for (ai = fai; ai; ai = ai->ai_next) {
+ for (ai = fain->ai; fain != NULL; fain = fain->next, ai = fain->ai) {
// create socket with obtained address domain, socket type and protocol
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

=======================================
--- /branches/ndt-web10g/src/test_mid_srv.c Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/src/test_mid_srv.c Sat Apr 13 19:56:13 2013
@@ -249,7 +249,7 @@
if ((conn = tcp_stat_connection_from_socket(agent, midsfd)) == -1) {
log_println(
0,
- "test_min() failed to get web10g connection data, rc=%d",
+ "test_mid() failed to get web10g connection data, rc=%d",
errno);
return -3;
}
=======================================
--- /branches/ndt-web10g/src/web100srv.h Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/src/web100srv.h Sat Apr 13 19:56:13 2013
@@ -290,7 +290,7 @@
typedef struct tcpe_data tcp_stat_snap;
/* Not relevent to web10g */
typedef void tcp_stat_group;
-/* Log currently unimplemented in web100 */
+/* Log currently unimplemented in web10g */
typedef void tcp_stat_log;
#define tcp_stat_connection_from_socket web10g_connection_from_socket

@@ -308,7 +308,6 @@
typedef web100_snapshot tcp_stat_snap;
/* Group only relevent to web100 */
typedef web100_group tcp_stat_group;
-/* Log currently unimplemented in web100 */
typedef web100_log tcp_stat_log;
#define tcp_stat_connection_from_socket web100_connection_from_socket

@@ -332,7 +331,7 @@

int KillHung(void);
void writeMeta(int compress, int cputime, int snaplog, int tcpdump);
-
+void ipv4mapped_to_ipv6(struct sockaddr_storage * ss);
char *get_remotehost();

/* global variables for signal processing */
=======================================
--- /branches/ndt-web10g/src/web10g-util.c Thu Apr 11 07:52:06 2013
+++ /branches/ndt-web10g/src/web10g-util.c Sat Apr 13 19:56:13 2013
@@ -5,13 +5,13 @@
*
*/

+#include "web100srv.h"
+#include "logging.h"
+
/*
* These are used to pass information between web10g_connection_from_socket
* and getremote_callback. It would be nice if these were not globals.
*/
-#include "web100srv.h"
-#include "logging.h"
-
static struct sockaddr_storage local_name;
static struct sockaddr_storage peer_name;
static int connection_id;
@@ -66,6 +66,25 @@
log_println(1, "WARNING: Mismatch between local and peer family");
}
}
+
+/**
+ * Converts a IPv4-mapped IPv6 sockaddr_in6 to a sockaddr_in4
+ *
+ * @param ss a sockaddr_storage
+ *
+ * @return if the ss represents a IPv6 mapped IPv4 address it will be converted
+ * into a IPv4 sockaddr_in. Otherwise ss will remain unchanged.
+ */
+void ipv4mapped_to_ipv6(struct sockaddr_storage * ss){
+ if (ss->ss_family == AF_INET6){
+ if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *) ss)->sin6_addr)){
+ // Ports already in the right place so just move the actual address
+ ss->ss_family = AF_INET;
+ ((struct sockaddr_in *) ss)->sin_addr.s_addr =
+ ((uint32_t *) &((struct sockaddr_in6 *) ss)->sin6_addr)[3];
+ }
+ }
+}

/**
* Find the web10g connection number related to a given socket.
@@ -91,6 +110,7 @@
log_println(1, "getsockname() failed: %s ", strerror(errno));
return -1;
}
+ ipv4mapped_to_ipv6(&local_name);

/* Get the ip address of our peer */
if (getpeername(sockfd, (struct sockaddr*) &peer_name,
@@ -98,6 +118,7 @@
log_println(1, "getpeername() failed: %s ", strerror(errno));
return -1;
}
+ ipv4mapped_to_ipv6(&peer_name);

tcpe_list_conns(client, fromsocket_callback);



  • [ndt-dev] [ndt] r816 committed - Fix for IPv4-mapped IPv6 socket handling. This branch should not only ..., ndt, 04/13/2013

Archive powered by MHonArc 2.6.16.

Top of Page