diff options
Diffstat (limited to 'util/http.c')
-rw-r--r-- | util/http.c | 135 |
1 files changed, 85 insertions, 50 deletions
diff --git a/util/http.c b/util/http.c index fa3d512e9..4cc31e3c0 100644 --- a/util/http.c +++ b/util/http.c @@ -42,8 +42,8 @@ #include "util.h" #include "iobuf.h" #include "i18n.h" - #include "http.h" +#include "srv.h" #ifdef __riscos__ #define HTTP_PROXY_ENV "GnuPG$HttpProxy" @@ -80,7 +80,7 @@ static int send_request( HTTP_HD hd ); static byte *build_rel_path( PARSED_URI uri ); static int parse_response( HTTP_HD hd ); -static int connect_server( const char *server, ushort port ); +static int connect_server(const char *server, ushort port, unsigned int flags); static int write_server( int sock, const char *data, size_t length ); #ifdef __MINGW32__ @@ -494,11 +494,11 @@ send_request( HTTP_HD hd ) return G10ERR_NETWORK; } hd->sock = connect_server( *uri->host? uri->host : "localhost", - uri->port? uri->port : 80 ); + uri->port? uri->port : 80, 0 ); release_parsed_uri( uri ); } else - hd->sock = connect_server( server, port ); + hd->sock = connect_server( server, port, hd->flags ); if( hd->sock == -1 ) return G10ERR_NETWORK; @@ -707,19 +707,17 @@ start_server() #endif - static int -connect_server( const char *server, ushort port ) +connect_server( const char *server, ushort port, unsigned int flags ) { - int sock,i=0; + int sock,srv,srvcount=0; struct sockaddr_in addr; struct hostent *host=NULL; - unsigned long l; + struct srventry *srvlist=NULL; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(port); #ifdef __MINGW32__ init_sockets (); @@ -740,63 +738,100 @@ connect_server( const char *server, ushort port ) #ifdef __MINGW32__ /* Win32 gethostbyname doesn't handle IP addresses internally, so we try inet_addr first on that platform only. */ - if((l=inet_addr(server))==SOCKET_ERROR) -#endif - if((host=gethostbyname(server))==NULL) - { -#ifdef __MINGW32__ - log_error("%s: host not found: ec=%d\n",server,(int)WSAGetLastError()); -#else - log_error("%s: host not found\n",server); -#endif - sock_close(sock); - return -1; - } - - if(host) + if((addr.sin_addr.s_addr=inet_addr(server))!=SOCKET_ERROR) { - if(host->h_addrtype != AF_INET) - { - log_error ("%s: unknown address family\n", server); - sock_close(sock); - return -1; - } + addr.sin_port = htons(port); - if(host->h_length != 4 ) + if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0) + return sock; + else { - log_error ("%s: illegal address length\n", server); sock_close(sock); return -1; } + } +#endif - /* Try all A records until one responds. */ - while(host->h_addr_list[i]) - { - memcpy(&addr.sin_addr,host->h_addr_list[i],host->h_length); - - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0) - break; +#ifdef USE_DNS_SRV + /* Do the SRV thing */ + if(flags&HTTP_FLAG_TRY_SRV) + { + /* We're using SRV, so append the tags */ + char srvname[MAXDNAME]; - i++; - } + strcpy(srvname,"_hkp._tcp."); + strncat(srvname,server,MAXDNAME-11); + srvname[MAXDNAME-1]='\0'; + srvcount=getsrv(srvname,&srvlist); + } +#endif - if(host->h_addr_list[i]==0) - { - sock_close(sock); - return -1; - } + if(srvlist==NULL) + { + /* Either we're not using SRV, or the SRV lookup failed. Make + up a fake SRV record. */ + srvlist=m_alloc_clear(sizeof(struct srventry)); + srvlist->port=port; + strncpy(srvlist->target,server,MAXDNAME); + srvcount=1; } - else + + for(srv=0;srv<srvcount;srv++) { - memcpy(&addr.sin_addr,&l,sizeof(l)); + int i=0; - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))!=0) + addr.sin_port = htons(srvlist[srv].port); + + if((host=gethostbyname(srvlist[srv].target))==NULL) + continue; + + if(host) { - sock_close(sock); - return -1; + if(host->h_addrtype != AF_INET) + { + log_error ("%s: unknown address family\n", srvlist[srv].target); + sock_close(sock); + m_free(srvlist); + return -1; + } + + if(host->h_length != 4 ) + { + log_error ("%s: illegal address length\n", srvlist[srv].target); + sock_close(sock); + m_free(srvlist); + return -1; + } + + /* Try all A records until one responds. */ + while(host->h_addr_list[i]) + { + memcpy(&addr.sin_addr,host->h_addr_list[i],host->h_length); + + if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0) + break; + + i++; + } + + if(host->h_addr_list[i]) + break; } } + m_free(srvlist); + + if(!host) + { +#ifdef __MINGW32__ + log_error("%s: host not found: ec=%d\n",server,(int)WSAGetLastError()); +#else + log_error("%s: host not found\n",server); +#endif + sock_close(sock); + return -1; + } + return sock; } |