diff -rup curl-7.20.1.org/include/curl/curl.h curl-7.20.1.test/include/curl/curl.h --- curl-7.20.1.org/include/curl/curl.h 2010-03-24 13:41:07.000000000 +0100 +++ curl-7.20.1.test/include/curl/curl.h 2010-05-12 09:50:57.754870000 +0200 @@ -1764,9 +1764,12 @@ typedef enum { CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, /* Fill in new entries below here! */ - CURLINFO_LASTONE = 39 + CURLINFO_LASTONE = 42 } CURLINFO; /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as diff -rup curl-7.20.1.org/lib/connect.c curl-7.20.1.test/lib/connect.c --- curl-7.20.1.org/lib/connect.c 2010-03-24 13:41:07.000000000 +0100 +++ curl-7.20.1.test/lib/connect.c 2010-05-27 16:56:59.006356000 +0200 @@ -523,6 +523,52 @@ static bool trynextip(struct connectdata return TRUE; } +/* retrieves ip address and port from a sockaddr structure */ +static void getaddressinfo(struct sockaddr_storage* ss, char* addr, long* port) +{ + struct sockaddr_in* si = NULL; +#ifdef ENABLE_IPV6 + struct sockaddr_in6* si6 = NULL; +#endif + + switch (ss->ss_family) { + case AF_INET: + si = (struct sockaddr_in*) ss; + inet_ntop(ss->ss_family, &(si->sin_addr), addr, MAX_IPADR_LEN); + *port = ntohs(si->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + si6 = (struct sockaddr_in6*)ss; + inet_ntop(ss->ss_family, &(si6->sin6_addr), addr, MAX_IPADR_LEN); + *port = ntohs(si6->sin6_port); + break; +#endif + default: + addr[0] = '\0'; + *port = 0; + } +} + +/* retrieves the start/end point information of a socket of an established + connection */ +void Curl_updateconninfo(curl_socket_t sockfd, struct PureInfo* info) +{ + + struct sockaddr_storage ssrem; + struct sockaddr_storage ssloc; + + socklen_t len; + len = sizeof(struct sockaddr_storage); + + getpeername(sockfd, (struct sockaddr*) &ssrem, &len); + getsockname(sockfd, (struct sockaddr*) &ssloc, &len); + + getaddressinfo(&ssrem, info->ip, &(info->port)); + getaddressinfo(&ssloc, info->localIp, &(info->localPort)); + +} + /* * Curl_is_connected() is used from the multi interface to check if the * firstsocket has connected. @@ -575,6 +621,9 @@ CURLcode Curl_is_connected(struct connec /* we are connected, awesome! */ conn->bits.tcpconnect = TRUE; *connected = TRUE; + + Curl_updateconninfo(sockfd, &(data->info)); + return CURLE_OK; } /* nope, not connected for real */ @@ -691,6 +740,7 @@ void Curl_sndbufset(curl_socket_t sockfd #endif + /* singleipconnect() connects to the given IP only, and it may return without having connected if used from the multi interface. */ static curl_socket_t @@ -864,6 +914,9 @@ singleipconnect(struct connectdata *conn /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ infof(data, "connected\n"); + + Curl_updateconninfo(sockfd, &(data->info)); + return sockfd; } else if(WAITCONN_TIMEOUT == rc) diff -rup curl-7.20.1.org/lib/connect.h curl-7.20.1.test/lib/connect.h --- curl-7.20.1.org/lib/connect.h 2010-03-24 13:41:07.000000000 +0100 +++ curl-7.20.1.test/lib/connect.h 2010-05-19 13:52:39.986317000 +0200 @@ -68,4 +68,6 @@ void Curl_sndbufset(curl_socket_t sockfd #define Curl_sndbufset(y) #endif +void Curl_updateconninfo(curl_socket_t sockfd, struct PureInfo* info); + #endif diff -rup curl-7.20.1.org/lib/getinfo.c curl-7.20.1.test/lib/getinfo.c --- curl-7.20.1.org/lib/getinfo.c 2010-03-24 13:41:07.000000000 +0100 +++ curl-7.20.1.test/lib/getinfo.c 2010-05-27 16:58:58.809675000 +0200 @@ -66,6 +66,12 @@ CURLcode Curl_initinfo(struct SessionHan info->header_size = 0; info->request_size = 0; info->numconnects = 0; + + strcpy(info->ip, ""); + info->port=0; + strcpy(info->localIp, ""); + info->localPort=0; + return CURLE_OK; } @@ -224,6 +230,19 @@ CURLcode Curl_getinfo(struct SessionHand /* Return the ip address of the most recent (primary) connection */ *param_charp = data->info.ip; break; + /* Return the (remote) port of the most recent (primary) connection */ + case CURLINFO_PRIMARY_PORT: + *param_longp = data->info.port; + break; + /* Return the source/local ip address of the most recent (primary) + connection */ + case CURLINFO_LOCAL_IP: + *param_charp = data->info.localIp; + break; + /* Return the local port of the most recent (primary) connection */ + case CURLINFO_LOCAL_PORT: + *param_longp = data->info.localPort; + break; case CURLINFO_CERTINFO: /* Return the a pointer to the certinfo struct. Not really an slist pointer but we can pretend it is here */ diff -rup curl-7.20.1.org/lib/url.c curl-7.20.1.test/lib/url.c --- curl-7.20.1.org/lib/url.c 2010-03-27 19:52:53.000000000 +0100 +++ curl-7.20.1.test/lib/url.c 2010-05-19 14:02:32.255819000 +0200 @@ -4986,6 +4986,7 @@ static CURLcode setup_conn(struct connec Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ conn->bits.tcpconnect = TRUE; *protocol_done = TRUE; + Curl_updateconninfo(conn->sock[FIRSTSOCKET], &(data->info)); if(data->set.verbose) verboseconnect(conn); } Only in curl-7.20.1.test/lib: url.c.orig diff -rup curl-7.20.1.org/lib/urldata.h curl-7.20.1.test/lib/urldata.h --- curl-7.20.1.org/lib/urldata.h 2010-03-25 19:54:59.000000000 +0100 +++ curl-7.20.1.test/lib/urldata.h 2010-05-27 17:02:42.266129000 +0200 @@ -867,6 +867,12 @@ struct PureInfo { char ip[MAX_IPADR_LEN]; /* this buffer gets the numerical ip version stored at the connect *attempt* so it will get the last tried connect IP even on failures */ + long port; /* the remote port the last connection was established to */ + char localIp[MAX_IPADR_LEN]; /* this buffer gets the numerical (local) ip + stored from where the last connection was + established */ + long localPort; /* the local (src) port the last connection + originated from */ struct curl_certinfo certs; /* info about the certs, only populated in OpenSSL builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */