summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
authorArch Librarian <arch@canonical.com>2004-09-20 16:53:50 +0000
committerArch Librarian <arch@canonical.com>2004-09-20 16:53:50 +0000
commit934b6582b4518630a050c8b84853b8e78ed87905 (patch)
treea94e4b6fb6188311080355b6184bd20939143b99 /methods
parentab559b358d7c390ac63bfcf8d526ca44761aafc5 (diff)
Changed to using rfc2553 name resolution for http
Author: jgg Date: 1999-05-25 05:56:24 GMT Changed to using rfc2553 name resolution for http
Diffstat (limited to 'methods')
-rw-r--r--methods/ftp.cc6
-rw-r--r--methods/http.cc58
-rw-r--r--methods/makefile2
-rw-r--r--methods/rfc2553emu.cc139
-rw-r--r--methods/rfc2553emu.h85
5 files changed, 266 insertions, 24 deletions
diff --git a/methods/ftp.cc b/methods/ftp.cc
index a93777488..b567875e1 100644
--- a/methods/ftp.cc
+++ b/methods/ftp.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: ftp.cc,v 1.9 1999/05/23 23:30:09 jgg Exp $
+// $Id: ftp.cc,v 1.10 1999/05/25 05:56:24 jgg Exp $
/* ######################################################################
HTTP Aquire Method - This is the FTP aquire method for APT.
@@ -9,7 +9,9 @@
at all. Commands are sent syncronously with the FTP server (as the
rfc recommends, but it is not really necessary..) and no tricks are
done to speed things along.
-
+
+ RFC 2428 describes the IPv6 FTP behavior
+
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
diff --git a/methods/http.cc b/methods/http.cc
index 4bd7975a4..0c0acf60f 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: http.cc,v 1.30 1999/04/04 02:02:04 jgg Exp $
+// $Id: http.cc,v 1.31 1999/05/25 05:56:24 jgg Exp $
/* ######################################################################
HTTP Aquire Method - This is the HTTP aquire method for APT.
@@ -41,12 +41,14 @@
#include <errno.h>
// Internet stuff
-#include <netinet/in.h>
+/*#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-#include <netdb.h>
+#include <netdb.h>*/
+#include "rfc2553emu.h"
#include "http.h"
+
/*}}}*/
string HttpMethod::FailFile;
@@ -258,7 +260,8 @@ ServerState::ServerState(URI Srv,HttpMethod *Owner) : Owner(Owner),
// ---------------------------------------------------------------------
/* This opens a connection to the server. */
string LastHost;
-in_addr LastHostA;
+int LastPort = 0;
+struct addrinfo *LastHostAddr = 0;
bool ServerState::Open()
{
// Use the already open connection if possible.
@@ -288,7 +291,7 @@ bool ServerState::Open()
Proxy = getenv("http_proxy");
// Determine what host and port to use based on the proxy settings
- int Port = 80;
+ int Port = 0;
string Host;
if (Proxy.empty() == true)
{
@@ -306,33 +309,46 @@ bool ServerState::Open()
/* We used a cached address record.. Yes this is against the spec but
the way we have setup our rotating dns suggests that this is more
sensible */
- if (LastHost != Host)
+ if (LastHost != Host || LastPort != Port)
{
Owner->Status("Connecting to %s",Host.c_str());
// Lookup the host
- hostent *Addr = gethostbyname(Host.c_str());
- if (Addr == 0 || Addr->h_addr_list[0] == 0)
+ char S[30] = "http";
+ if (Port != 0)
+ snprintf(S,sizeof(S),"%u",Port);
+
+ // Free the old address structure
+ if (LastHostAddr != 0)
+ {
+ freeaddrinfo(LastHostAddr);
+ LastHostAddr = 0;
+ }
+
+ // We only understand SOCK_STREAM sockets.
+ struct addrinfo Hints;
+ memset(&Hints,0,sizeof(Hints));
+ Hints.ai_socktype = SOCK_STREAM;
+
+ // Resolve both the host and service simultaneously
+ if (getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr) != 0 ||
+ LastHostAddr == 0)
return _error->Error("Could not resolve '%s'",Host.c_str());
+
LastHost = Host;
- LastHostA = *(in_addr *)(Addr->h_addr_list[0]);
+ LastPort = Port;
}
-
- Owner->Status("Connecting to %s (%s)",Host.c_str(),inet_ntoa(LastHostA));
-
+
+ // Connect to the server
// Get a socket
- if ((ServerFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
+// Owner->Status("Connecting to %s (%s)",Host.c_str(),inet_ntoa(LastHostA));
+ if ((ServerFd = socket(LastHostAddr->ai_family,LastHostAddr->ai_socktype,
+ LastHostAddr->ai_protocol)) < 0)
return _error->Errno("socket","Could not create a socket");
-
- // Connect to the server
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_port = htons(Port);
- server.sin_addr = LastHostA;
SetNonBlock(ServerFd,true);
- if (connect(ServerFd,(sockaddr *)&server,sizeof(server)) < 0 &&
+ if (connect(ServerFd,LastHostAddr->ai_addr,LastHostAddr->ai_addrlen) < 0 &&
errno != EINPROGRESS)
- return _error->Errno("socket","Could not create a socket");
+ return _error->Errno("connect","Connect initiate the connection");
/* This implements a timeout for connect by opening the connection
nonblocking */
diff --git a/methods/makefile b/methods/makefile
index dc6b88780..2cfc15cae 100644
--- a/methods/makefile
+++ b/methods/makefile
@@ -38,7 +38,7 @@ include $(PROGRAM_H)
PROGRAM=http
SLIBS = -lapt-pkg
LIB_MAKES = apt-pkg/makefile
-SOURCE = http.cc
+SOURCE = http.cc rfc2553emu.cc
include $(PROGRAM_H)
# The ftp method
diff --git a/methods/rfc2553emu.cc b/methods/rfc2553emu.cc
new file mode 100644
index 000000000..66fe781fb
--- /dev/null
+++ b/methods/rfc2553emu.cc
@@ -0,0 +1,139 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: rfc2553emu.cc,v 1.1 1999/05/25 05:56:24 jgg Exp $
+/* ######################################################################
+
+ RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
+ freeaddrinfo and getnameinfo
+
+ Originally written by Jason Gunthorpe <jgg@debian.org> and placed into
+ the Public Domain, do with it what you will.
+
+ ##################################################################### */
+ /*}}}*/
+#include "rfc2553emu.h"
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <iostream.h>
+
+#ifndef HAVE_GETADDRINFO
+int getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ struct addrinfo **Result;
+ hostent *Addr;
+ unsigned int Port;
+ int Proto;
+ const char *End;
+ char **CurAddr;
+
+ Addr = gethostbyname(nodename);
+ if (Addr == 0)
+ {
+ if (h_errno == TRY_AGAIN)
+ return EAI_AGAIN;
+ if (h_errno == NO_RECOVERY)
+ return EAI_FAIL;
+ return EAI_NONAME;
+ }
+
+ // No A records
+ if (Addr->h_addr_list[0] == 0)
+ return EAI_NONAME;
+
+ // Try to convert the service as a number
+ Port = htons(strtol(servname,(char **)&End,0));
+ Proto = SOCK_STREAM;
+
+ if (hints != 0 && hints->ai_socktype != 0)
+ Proto = hints->ai_socktype;
+
+ // Not a number, must be a name.
+ if (End != servname + strlen(End))
+ {
+ struct servent *Srv = 0;
+
+ // Do a lookup in the service database
+ if (hints == 0 || hints->ai_socktype == SOCK_STREAM)
+ Srv = getservbyname(servname,"tcp");
+ if (hints != 0 && hints->ai_socktype == SOCK_DGRAM)
+ Srv = getservbyname(servname,"udp");
+ if (Srv == 0)
+ return EAI_NONAME;
+
+ // Get the right protocol
+ Port = Srv->s_port;
+ if (strcmp(Srv->s_proto,"tcp") == 0)
+ Proto = SOCK_STREAM;
+ else
+ {
+ if (strcmp(Srv->s_proto,"udp") == 0)
+ Proto = SOCK_DGRAM;
+ else
+ return EAI_NONAME;
+ }
+
+ if (hints != 0 && hints->ai_socktype != Proto &&
+ hints->ai_socktype != 0)
+ return EAI_SERVICE;
+ }
+
+ // Start constructing the linked list
+ *res = 0;
+ for (CurAddr = Addr->h_addr_list; *CurAddr != 0; CurAddr++)
+ {
+ // New result structure
+ *Result = (struct addrinfo *)calloc(sizeof(**Result),1);
+ if (*Result == 0)
+ {
+ freeaddrinfo(*res);
+ return EAI_MEMORY;
+ }
+ if (*res == 0)
+ *res = *Result;
+
+ (*Result)->ai_family = AF_INET;
+ (*Result)->ai_socktype = Proto;
+
+ // If we have the IPPROTO defines we can set the protocol field
+ #ifdef IPPROTO_TCP
+ if (Proto == SOCK_STREAM)
+ (*Result)->ai_protocol = IPPROTO_TCP;
+ if (Proto == SOCK_DGRAM)
+ (*Result)->ai_protocol = IPPROTO_UDP;
+ #endif
+
+ // Allocate space for the address
+ (*Result)->ai_addrlen = sizeof(struct sockaddr_in);
+ (*Result)->ai_addr = (struct sockaddr *)calloc(sizeof(sockaddr_in),1);
+ if ((*Result)->ai_addr == 0)
+ {
+ freeaddrinfo(*res);
+ return EAI_MEMORY;
+ }
+
+ // Set the address
+ ((struct sockaddr_in *)(*Result)->ai_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)(*Result)->ai_addr)->sin_port = Port;
+ ((struct sockaddr_in *)(*Result)->ai_addr)->sin_addr = *(in_addr *)(*CurAddr);
+
+ Result = &(*Result)->ai_next;
+ }
+
+ return 0;
+}
+
+void freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *Tmp;
+ while (ai != 0)
+ {
+ free(ai->ai_addr);
+ Tmp = ai;
+ ai = ai->ai_next;
+ free(ai);
+ }
+}
+
+#endif // HAVE_GETADDRINFO
diff --git a/methods/rfc2553emu.h b/methods/rfc2553emu.h
new file mode 100644
index 000000000..e24e7a3c1
--- /dev/null
+++ b/methods/rfc2553emu.h
@@ -0,0 +1,85 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: rfc2553emu.h,v 1.1 1999/05/25 05:56:24 jgg Exp $
+/* ######################################################################
+
+ RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
+ freeaddrinfo and getnameinfo
+
+ These functions are necessary to write portable protocol independent
+ networking. They transparently support IPv4, IPv6 and probably many
+ other protocols too. This implementation is needed when the host does
+ not support these standards. It implements a simple wrapper that
+ basically supports only IPv4.
+
+ Perfect emulation is not provided, but it is passable..
+
+ Originally written by Jason Gunthorpe <jgg@debian.org> and placed into
+ the Public Domain, do with it what you will.
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef RFC2553EMU_H
+#define RFC2553EMU_H
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// Autosense getaddrinfo
+#if defined(AI_PASSIVE) && defined(EAI_NONAME)
+#define HAVE_GETADDRINFO
+#endif
+
+// getaddrinfo support?
+#ifndef HAVE_GETADDRINFO
+ #error Boink
+
+ // Renamed to advoid type clashing.. (for debugging)
+ struct addrinfo_emu
+ {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for nodename */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+ };
+ #define addinfo addrinfo_emu
+
+ int getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+ void freeaddrinfo(struct addrinfo *ai);
+
+ #ifndef AI_PASSIVE
+ #define AI_PASSIVE (1<<1)
+ #endif
+
+ #ifndef EAI_NONAME
+ #define EAI_NONAME -1
+ #define EAI_AGAIN -2
+ #define EAI_FAIL -3
+ #define EAI_NODATA -4
+ #define EAI_FAMILY -5
+ #define EAI_SOCKTYPE -6
+ #define EAI_SERVICE -7
+ #define EAI_ADDRFAMILY -8
+ #define EAI_ADDRFAMILY -8
+ #define EAI_SYSTEM -10
+ #endif
+
+#endif
+
+// getnameinfo support (glibc2.0 has getaddrinfo only)
+#ifndef HAVE_GETNAMEINFO
+
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags);
+#endif
+
+#endif