]> git.pld-linux.org Git - packages/apt.git/commitdiff
2b73eaa52511bd811df5a4883ed740cd apt-newmethods.patch
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Tue, 11 Sep 2001 20:59:45 +0000 (20:59 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    apt-newmethods.patch -> 1.1

apt-newmethods.patch [new file with mode: 0644]

diff --git a/apt-newmethods.patch b/apt-newmethods.patch
new file mode 100644 (file)
index 0000000..6bef960
--- /dev/null
@@ -0,0 +1,1401 @@
+diff -urN apt-0.3.19cnc52.org/apt-pkg/acquire-method.cc apt-0.3.19cnc52/apt-pkg/acquire-method.cc
+--- apt-0.3.19cnc52.org/apt-pkg/acquire-method.cc      Thu Sep  6 22:20:42 2001
++++ apt-0.3.19cnc52/apt-pkg/acquire-method.cc  Sat Sep  8 13:18:36 2001
+@@ -97,7 +97,8 @@
+    if (Queue != 0)
+    {
+       snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
+-             "Message: %s\n",Queue->Uri.c_str(),Err.c_str());
++             "Message: %s %s\n",Queue->Uri.c_str(),Err.c_str(),
++             FailExtra.c_str());
+       // Dequeue
+       FetchItem *Tmp = Queue;
+@@ -108,7 +109,8 @@
+    }
+    else
+       snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
+-             "Message: %s\n",Err.c_str());
++             "Message: %s %s\n",Err.c_str(),
++             FailExtra.c_str());
+       
+    // Set the transient flag 
+    if (Transient == true)
+diff -urN apt-0.3.19cnc52.org/apt-pkg/acquire-method.h apt-0.3.19cnc52/apt-pkg/acquire-method.h
+--- apt-0.3.19cnc52.org/apt-pkg/acquire-method.h       Thu Sep  6 22:20:42 2001
++++ apt-0.3.19cnc52/apt-pkg/acquire-method.h   Sat Sep  8 13:15:34 2001
+@@ -50,6 +50,7 @@
+    vector<string> Messages;
+    FetchItem *Queue;
+    FetchItem *QueueBack;
++   string FailExtra;
+       
+    // Handlers for messages
+    virtual bool Configuration(string Message);
+@@ -75,6 +76,7 @@
+    void Status(const char *Format,...);
+    
+    int Run(bool Single = false);
++   inline void SetFailExtraMsg(string Msg) {FailExtra = Msg;};
+    
+    pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
+    virtual ~pkgAcqMethod() {};
+diff -urN apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.cc apt-0.3.19cnc52/apt-pkg/contrib/strutl.cc
+--- apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.cc      Thu Sep  6 22:20:42 2001
++++ apt-0.3.19cnc52/apt-pkg/contrib/strutl.cc  Sat Sep  8 12:54:40 2001
+@@ -861,7 +861,29 @@
+    return Hits;
+ }
+                                                                       /*}}}*/
+-
++// CheckDomainList - See if Host is in a , seperate list                /*{{{*/
++// ---------------------------------------------------------------------
++/* The domain list is a comma seperate list of domains that are suffix
++   matched against the argument */
++bool CheckDomainList(string Host,string List)
++{
++   string::const_iterator Start = List.begin();
++   for (string::const_iterator Cur = List.begin(); Cur <= List.end(); Cur++)
++   {
++      if (Cur < List.end() && *Cur != ',')
++         continue;
++      
++      // Match the end of the string..
++      if ((Host.size() >= (unsigned)(Cur - Start)) &&
++          Cur - Start != 0 &&
++          stringcasecmp(Host.end() - (Cur - Start),Host.end(),Start,Cur) == 0)
++         return true;
++      
++      Start = Cur + 1;
++   }
++   return false;
++}
++                                                                        /*}}}*/
+ // URI::CopyFrom - Copy from an object                                        /*{{{*/
+ // ---------------------------------------------------------------------
+ /* This parses the URI into all of its components */
+diff -urN apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.h apt-0.3.19cnc52/apt-pkg/contrib/strutl.h
+--- apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.h       Thu Sep  6 22:20:42 2001
++++ apt-0.3.19cnc52/apt-pkg/contrib/strutl.h   Sat Sep  8 12:53:14 2001
+@@ -45,6 +45,7 @@
+            unsigned int Length);
+ bool TokSplitString(char Tok,char *Input,char **List,
+                   unsigned long ListMax);
++bool CheckDomainList(string Host,string List);
+    
+ int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
+ inline int stringcmp(const char *A,const char *AEnd,const char *B) {return stringcmp(A,AEnd,B,B+strlen(B));};
+diff -urN apt-0.3.19cnc52.org/methods/connect.cc apt-0.3.19cnc52/methods/connect.cc
+--- apt-0.3.19cnc52.org/methods/connect.cc     Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/connect.cc Tue Feb 20 08:03:18 2001
+@@ -1,6 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+    Connect - Replacement connect call
+@@ -30,6 +30,18 @@
+ static struct addrinfo *LastHostAddr = 0;
+ static struct addrinfo *LastUsed = 0;
++// RotateDNS - Select a new server from a DNS rotation                        /*{{{*/
++// ---------------------------------------------------------------------
++/* This is called during certain errors in order to recover by selecting a 
++   new server */
++void RotateDNS()
++{
++   if (LastUsed != 0 && LastUsed->ai_next != 0)
++      LastUsed = LastUsed->ai_next;
++   else
++      LastUsed = LastHostAddr;
++}
++                                                                      /*}}}*/
+ // DoConnect - Attempt a connect operation                            /*{{{*/
+ // ---------------------------------------------------------------------
+ /* This helper function attempts a connection to a single address. */
+@@ -38,28 +50,44 @@
+ {
+    // Show a status indicator
+    char Name[NI_MAXHOST];
+-   Name[0] = 0;
++   char Service[NI_MAXSERV];
++   
++   Name[0] = 0;   
++   Service[0] = 0;
+    getnameinfo(Addr->ai_addr,Addr->ai_addrlen,
+-             Name,sizeof(Name),0,0,NI_NUMERICHOST);
++             Name,sizeof(Name),Service,sizeof(Service),
++             NI_NUMERICHOST|NI_NUMERICSERV);
+    Owner->Status("Connecting to %s (%s)",Host.c_str(),Name);
+-   
++
++   /* If this is an IP rotation store the IP we are using.. If something goes
++      wrong this will get tacked onto the end of the error message */
++   if (LastHostAddr->ai_next != 0)
++   {
++      char Name2[NI_MAXHOST + NI_MAXSERV + 10];
++      snprintf(Name2,sizeof(Name2),"[IP: %s %s]",Name,Service);
++      Owner->SetFailExtraMsg(string(Name2));
++   }   
++   else
++      Owner->SetFailExtraMsg("");
++      
+    // Get a socket
+    if ((Fd = socket(Addr->ai_family,Addr->ai_socktype,
+                   Addr->ai_protocol)) < 0)
+-      return _error->Errno("socket","Could not create a socket");
++      return _error->Errno("socket","Could not create a socket for %s (f=%u t=%u p=%u)",
++                         Name,Addr->ai_family,Addr->ai_socktype,Addr->ai_protocol);
+    
+    SetNonBlock(Fd,true);
+    if (connect(Fd,Addr->ai_addr,Addr->ai_addrlen) < 0 &&
+        errno != EINPROGRESS)
+       return _error->Errno("connect","Cannot initiate the connection "
+-                         "to %s (%s).",Host.c_str(),Name);
++                         "to %s:%s (%s).",Host.c_str(),Service,Name);
+    
+    /* This implements a timeout for connect by opening the connection
+       nonblocking */
+    if (WaitFd(Fd,true,TimeOut) == false)
+-      return _error->Error("Could not connect to %s (%s), "
+-                         "connection timed out",Host.c_str(),Name);
+-   
++      return _error->Error("Could not connect to %s:%s (%s), "
++                         "connection timed out",Host.c_str(),Service,Name);
++
+    // Check the socket for an error condition
+    unsigned int Err;
+    unsigned int Len = sizeof(Err);
+@@ -67,8 +95,12 @@
+       return _error->Errno("getsockopt","Failed");
+    
+    if (Err != 0)
+-      return _error->Error("Could not connect to %s (%s).",Host.c_str(),Name);
+-
++   {
++      errno = Err;
++      return _error->Errno("connect","Could not connect to %s:%s (%s).",Host.c_str(),
++                         Service,Name);
++   }
++   
+    return true;
+ }
+                                                                       /*}}}*/
+@@ -80,6 +112,13 @@
+ {
+    if (_error->PendingError() == true)
+       return false;
++
++   // Convert the port name/number
++   char ServStr[300];
++   if (Port != 0)
++      snprintf(ServStr,sizeof(ServStr),"%u",Port);
++   else
++      snprintf(ServStr,sizeof(ServStr),"%s",Service);
+    
+    /* 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
+@@ -88,59 +127,49 @@
+    {
+       Owner->Status("Connecting to %s",Host.c_str());
+-      // Lookup the host
+-      char S[300];
+-      if (Port != 0)
+-       snprintf(S,sizeof(S),"%u",Port);
+-      else
+-       snprintf(S,sizeof(S),"%s",Service);
+-
+       // Free the old address structure
+       if (LastHostAddr != 0)
+       {
+        freeaddrinfo(LastHostAddr);
+        LastHostAddr = 0;
++       LastUsed = 0;
+       }
+       
+       // We only understand SOCK_STREAM sockets.
+       struct addrinfo Hints;
+       memset(&Hints,0,sizeof(Hints));
+       Hints.ai_socktype = SOCK_STREAM;
+-      Hints.ai_protocol = IPPROTO_TCP;       // Right?
++      Hints.ai_protocol = 0;
+       
+       // Resolve both the host and service simultaneously
+       while (1)
+       {
+        int Res;
+-       if ((Res = getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr)) != 0 ||
++       if ((Res = getaddrinfo(Host.c_str(),ServStr,&Hints,&LastHostAddr)) != 0 ||
+            LastHostAddr == 0)
+        {
+           if (Res == EAI_NONAME || Res == EAI_SERVICE)
+           {
+              if (DefPort != 0)
+              {
+-                snprintf(S,sizeof(S),"%u",DefPort);
++                snprintf(ServStr,sizeof(ServStr),"%u",DefPort);
+                 DefPort = 0;
+                 continue;
+              }
+              return _error->Error("Could not resolve '%s'",Host.c_str());
+           }
+           
+-          return _error->Error("Something wicked happend resolving '%s/%s'",
+-                               Host.c_str(),S);
++          return _error->Error("Something wicked happened resolving '%s:%s' (%i)",
++                               Host.c_str(),ServStr,Res);
+        }
+        break;
+       }
+       
+-      if (LastHostAddr->ai_family == AF_UNIX)
+-       return _error->Error("getaddrinfo returned a unix domain socket\n");
+-      
+       LastHost = Host;
+       LastPort = Port;
+-      LastUsed = 0;
+    }
+-   // Get the printable IP address
++   // When we have an IP rotation stay with the last IP.
+    struct addrinfo *CurHost = LastHostAddr;
+    if (LastUsed != 0)
+        CurHost = LastUsed;
+@@ -155,14 +184,28 @@
+       close(Fd);
+       Fd = -1;
+       
+-      CurHost = CurHost->ai_next;
+-      LastUsed = 0;
++      // Ignore UNIX domain sockets
++      do
++      {
++       CurHost = CurHost->ai_next;
++      }
++      while (CurHost != 0 && CurHost->ai_family == AF_UNIX);
++
++      /* If we reached the end of the search list then wrap around to the
++         start */
++      if (CurHost == 0 && LastUsed != 0)
++       CurHost = LastHostAddr;
++      
++      // Reached the end of the search cycle
++      if (CurHost == LastUsed)
++       break;
++      
+       if (CurHost != 0)
+        _error->Discard();
+-   }
+-   
++   }   
++
+    if (_error->PendingError() == true)
+-      return false;
+-   return _error->Error("Unable to connect to '%s'",Host.c_str());
++      return false;   
++   return _error->Error("Unable to connect to %s %s:",Host.c_str(),ServStr);
+ }
+                                                                       /*}}}*/
+diff -urN apt-0.3.19cnc52.org/methods/connect.h apt-0.3.19cnc52/methods/connect.h
+--- apt-0.3.19cnc52.org/methods/connect.h      Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/connect.h  Tue Feb 20 08:03:18 2001
+@@ -1,6 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+    Connect - Replacement connect call
+@@ -15,5 +15,6 @@
+ bool Connect(string To,int Port,const char *Service,int DefPort,
+            int &Fd,unsigned long TimeOut,pkgAcqMethod *Owner);
++void RotateDNS();
+ #endif
+diff -urN apt-0.3.19cnc52.org/methods/ftp.cc apt-0.3.19cnc52/methods/ftp.cc
+--- apt-0.3.19cnc52.org/methods/ftp.cc Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/ftp.cc     Sat Sep  8 12:33:40 2001
+@@ -1,9 +1,9 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+-   HTTP Aquire Method - This is the FTP aquire method for APT.
++   FTP Aquire Method - This is the FTP aquire method for APT.
+    This is a very simple implementation that does not try to optimize
+    at all. Commands are sent syncronously with the FTP server (as the
+@@ -28,6 +28,7 @@
+ #include <stdio.h>
+ #include <errno.h>
+ #include <stdarg.h>
++#include <iostream>
+ // Internet stuff
+ #include <netinet/in.h>
+@@ -40,6 +41,22 @@
+ #include "ftp.h"
+                                                                       /*}}}*/
++using namespace std;
++
++/* This table is for the EPRT and EPSV commands, it maps the OS address
++   family to the IETF address families */
++struct AFMap
++{
++   unsigned long Family;
++   unsigned long IETFFamily;
++};
++
++#ifndef AF_INET6
++struct AFMap AFMap[] = {{AF_INET,1},{}};
++#else
++struct AFMap AFMap[] = {{AF_INET,1},{AF_INET6,2},{}};
++#endif
++
+ unsigned long TimeOut = 120;
+ URI Proxy;
+ string FtpMethod::FailFile;
+@@ -53,7 +70,7 @@
+                             DataListenFd(-1), ServerName(Srv)
+ {
+    Debug = _config->FindB("Debug::Acquire::Ftp",false);
+-   memset(&PasvAddr,0,sizeof(PasvAddr));
++   PasvAddr = 0;
+ }
+                                                                       /*}}}*/
+ // FTPConn::~FTPConn - Destructor                                     /*{{{*/
+@@ -75,7 +92,10 @@
+    DataFd = -1;
+    close(DataListenFd);
+    DataListenFd = -1;
+-   memset(&PasvAddr,0,sizeof(PasvAddr));
++   
++   if (PasvAddr != 0)
++      freeaddrinfo(PasvAddr);
++   PasvAddr = 0;
+ }
+                                                                       /*}}}*/
+ // FTPConn::Open - Open a new connection                              /*{{{*/
+@@ -89,7 +109,7 @@
+       return true;
+    
+    Close();
+-
++   
+    // Determine the proxy setting
+    if (getenv("ftp_proxy") == 0)
+    {
+@@ -108,32 +128,13 @@
+    else
+       Proxy = getenv("ftp_proxy");
+    
+-   // Parse no_proxy, a , seperated list of domains
++   // Parse no_proxy, a , separated list of domains
+    if (getenv("no_proxy") != 0)
+    {
+-      const char *Start = getenv("no_proxy");
+-      const char *ServerEnd = ServerName.Host.end();
+-      
+-      for (const char *Cur = Start; true ; Cur++)
+-      {
+-       if (*Cur != ',' && *Cur != 0)
+-          continue;
+-        
+-       // match end of the string
+-       if ((ServerName.Host.size() >= (Cur - Start))
+-           && stringcasecmp(ServerEnd - (Cur - Start),
+-                            ServerEnd,Start,Cur) == 0)
+-       {
+-          Proxy = "";
+-          break;
+-       }
+-       
+-       Start = Cur + 1;
+-       if (*Cur == 0)
+-          break;
+-      }        
++      if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
++       Proxy = "";
+    }
+-    
++   
+    // Determine what host and port to use based on the proxy settings
+    int Port = 0;
+    string Host;   
+@@ -150,15 +151,27 @@
+       Host = Proxy.Host;
+    }
+-   // Connect to the remote server
++   /* Connect to the remote server. Since FTP is connection oriented we
++      want to make sure we get a new server every time we reconnect */
++   RotateDNS();
+    if (Connect(Host,Port,"ftp",21,ServerFd,TimeOut,Owner) == false)
+       return false;
+-   socklen_t Len = sizeof(Peer);
+-   if (getpeername(ServerFd,(sockaddr *)&Peer,&Len) != 0)
++
++   // Login must be before getpeername otherwise dante won't work.
++   Owner->Status("Logging in");
++   bool Res = Login();
++   
++   // Get the remote server's address
++   PeerAddrLen = sizeof(PeerAddr);
++   if (getpeername(ServerFd,(sockaddr *)&PeerAddr,&PeerAddrLen) != 0)
+       return _error->Errno("getpeername","Unable to determine the peer name");
+    
+-   Owner->Status("Logging in");
+-   return Login();
++   // Get the local machine's address
++   ServerAddrLen = sizeof(ServerAddr);
++   if (getsockname(ServerFd,(sockaddr *)&ServerAddr,&ServerAddrLen) != 0)
++      return _error->Errno("getsockname","Unable to determine the local name");
++   
++   return Res;
+ }
+                                                                       /*}}}*/
+ // FTPConn::Login - Login to the remote server                                /*{{{*/
+@@ -172,11 +185,7 @@
+    
+    // Setup the variables needed for authentication
+    string User = "anonymous";
+-   string Pass;
+-   if (0) //akk
+-      Pass = "apt_get_ftp_2.0@debian.linux.user";
+-   else
+-      Pass = "apt_get_ftp_2.0@conectiva.linux.user";
++   string Pass = "apt_get_ftp_2.0@pld.linux.user";
+    // Fill in the user/pass
+    if (ServerName.User.empty() == false)
+@@ -209,7 +218,7 @@
+       if (_config->Exists("Acquire::FTP::Passive::" + ServerName.Host) == true)
+        TryPassive = _config->FindB("Acquire::FTP::Passive::" + ServerName.Host,true);
+       else
+-       TryPassive = _config->FindB("Acquire::FTP::Passive",true);
++       TryPassive = _config->FindB("Acquire::FTP::Passive",true);      
+    }
+    else
+    {      
+@@ -266,6 +275,12 @@
+       }            
+    }
++   // Force the use of extended commands
++   if (_config->Exists("Acquire::FTP::ForceExtended::" + ServerName.Host) == true)
++      ForceExtended = _config->FindB("Acquire::FTP::ForceExtended::" + ServerName.Host,true);
++   else
++      ForceExtended = _config->FindB("Acquire::FTP::ForceExtended",false);
++   
+    // Binary mode
+    if (WriteMsg(Tag,Msg,"TYPE I") == false)
+       return false;
+@@ -313,6 +328,8 @@
+       
+       // Suck it back
+       int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len);
++      if (Res == 0)
++       _error->Error("Server closed the connection");
+       if (Res <= 0)
+       {
+        _error->Errno("read","Read error");
+@@ -439,10 +456,19 @@
+ // ---------------------------------------------------------------------
+ /* Try to enter passive mode, the return code does not indicate if passive
+    mode could or could not be established, only if there was a fatal error. 
+-   Borrowed mostly from lftp. We have to enter passive mode every time 
+- we make a data connection :| */
++   We have to enter passive mode every time we make a data connection :| */
+ bool FTPConn::GoPasv()
+ {
++   /* The PASV command only works on IPv4 sockets, even though it could
++      in theory suppory IPv6 via an all zeros reply */
++   if (((struct sockaddr *)&PeerAddr)->sa_family != AF_INET || 
++       ForceExtended == true)
++      return ExtGoPasv();
++   
++   if (PasvAddr != 0)
++      freeaddrinfo(PasvAddr);
++   PasvAddr = 0;
++   
+    // Try to enable pasv mode
+    unsigned int Tag;
+    string Msg;
+@@ -452,41 +478,139 @@
+    // Unsupported function
+    string::size_type Pos = Msg.find('(');
+    if (Tag >= 400 || Pos == string::npos)
+-   {
+-      memset(&PasvAddr,0,sizeof(PasvAddr));
+       return true;
+-   }
+    // Scan it
+    unsigned a0,a1,a2,a3,p0,p1;
+    if (sscanf(Msg.c_str() + Pos,"(%u,%u,%u,%u,%u,%u)",&a0,&a1,&a2,&a3,&p0,&p1) != 6)
++      return true;
++   
++   /* Some evil servers return 0 to mean their addr. We can actually speak
++      to these servers natively using IPv6 */
++   if (a0 == 0 && a1 == 0 && a2 == 0 && a3 == 0)
+    {
+-      memset(&PasvAddr,0,sizeof(PasvAddr));
++      // Get the IP in text form
++      char Name[NI_MAXHOST];
++      char Service[NI_MAXSERV];
++      getnameinfo((struct sockaddr *)&PeerAddr,PeerAddrLen,
++                Name,sizeof(Name),Service,sizeof(Service),
++                NI_NUMERICHOST|NI_NUMERICSERV);
++      
++      struct addrinfo Hints;
++      memset(&Hints,0,sizeof(Hints));
++      Hints.ai_socktype = SOCK_STREAM;
++      Hints.ai_family = ((struct sockaddr *)&PeerAddr)->sa_family;
++      Hints.ai_flags |= AI_NUMERICHOST;
++      
++      // Get a new passive address.
++      char Port[100];
++      snprintf(Port,sizeof(Port),"%u",(p0 << 8) + p1);
++      if (getaddrinfo(Name,Port,&Hints,&PasvAddr) != 0)
++       return true;
+       return true;
+    }
+    
+-   // lftp used this horrid byte order manipulation.. Ik.
+-   PasvAddr.sin_family = AF_INET;
+-   unsigned char *a;
+-   unsigned char *p;
+-   a = (unsigned char *)&PasvAddr.sin_addr;
+-   p = (unsigned char *)&PasvAddr.sin_port;
++   struct addrinfo Hints;
++   memset(&Hints,0,sizeof(Hints));
++   Hints.ai_socktype = SOCK_STREAM;
++   Hints.ai_family = AF_INET;
++   Hints.ai_flags |= AI_NUMERICHOST;
++   
++   // Get a new passive address.
++   char Port[100];
++   snprintf(Port,sizeof(Port),"%u",(p0 << 8) + p1);
++   char Name[100];
++   snprintf(Name,sizeof(Name),"%u.%u.%u.%u",a0,a1,a2,a3);
++   if (getaddrinfo(Name,Port,&Hints,&PasvAddr) != 0)
++      return true;
++   return true;
++}
++                                                                      /*}}}*/
++// FTPConn::ExtGoPasv - Enter Extended Passive mode                   /*{{{*/
++// ---------------------------------------------------------------------
++/* Try to enter extended passive mode. See GoPasv above and RFC 2428 */
++bool FTPConn::ExtGoPasv()
++{
++   if (PasvAddr != 0)
++      freeaddrinfo(PasvAddr);
++   PasvAddr = 0;
+    
+-   // Some evil servers return 0 to mean their addr
+-   if (a0 == 0 && a1 == 0 && a2 == 0 && a3 == 0)
++   // Try to enable pasv mode
++   unsigned int Tag;
++   string Msg;
++   if (WriteMsg(Tag,Msg,"EPSV") == false)
++      return false;
++   
++   // Unsupported function
++   string::size_type Pos = Msg.find('(');
++   if (Tag >= 400 || Pos == string::npos)
++      return true;
++
++   // Scan it   
++   string::const_iterator List[4];
++   unsigned Count = 0;
++   Pos++;
++   for (string::const_iterator I = Msg.begin() + Pos; I < Msg.end(); I++)
+    {
+-      PasvAddr.sin_addr = Peer.sin_addr;
++      if (*I != Msg[Pos])
++       continue;
++      if (Count >= 4)
++       return true;
++      List[Count++] = I;
++   }
++   if (Count != 4)
++      return true;
++   
++   // Break it up ..
++   unsigned long Proto = 0;
++   unsigned long Port = 0;
++   string IP;
++   IP = string(List[1]+1,List[2]);
++   Port = atoi(string(List[2]+1,List[3]).c_str());
++   if (IP.empty() == false)
++      Proto = atoi(string(List[0]+1,List[1]).c_str());
++   
++   if (Port == 0)
++      return false;
++
++   // String version of the port
++   char PStr[100];
++   snprintf(PStr,sizeof(PStr),"%lu",Port);
++
++   // Get the IP in text form
++   struct addrinfo Hints;
++   memset(&Hints,0,sizeof(Hints));
++   Hints.ai_socktype = SOCK_STREAM;
++   Hints.ai_flags |= AI_NUMERICHOST;
++   
++   /* The RFC defined case, connect to the old IP/protocol using the
++      new port. */
++   if (IP.empty() == true)
++   {
++      // Get the IP in text form
++      char Name[NI_MAXHOST];
++      char Service[NI_MAXSERV];
++      getnameinfo((struct sockaddr *)&PeerAddr,PeerAddrLen,
++                Name,sizeof(Name),Service,sizeof(Service),
++                NI_NUMERICHOST|NI_NUMERICSERV);
++      IP = Name;
++      Hints.ai_family = ((struct sockaddr *)&PeerAddr)->sa_family;
+    }
+    else
+    {
+-      a[0] = a0; 
+-      a[1] = a1; 
+-      a[2] = a2; 
+-      a[3] = a3;
++      // Get the family..
++      Hints.ai_family = 0;
++      for (unsigned J = 0; AFMap[J].Family != 0; J++)
++       if (AFMap[J].IETFFamily == Proto)
++          Hints.ai_family = AFMap[J].Family;
++      if (Hints.ai_family == 0)
++       return true;
+    }
+    
+-   p[0] = p0;
+-   p[1] = p1;
++   // Get a new passive address.
++   int Res;
++   if ((Res = getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr)) != 0)
++      return true;
+    
+    return true;
+ }
+@@ -547,34 +671,35 @@
+        return false;
+       
+       // Oops, didn't work out, don't bother trying again.
+-      if (PasvAddr.sin_port == 0)
++      if (PasvAddr == 0)
+        TryPassive = false;
+    }
+    
+    // Passive mode?
+-   if (PasvAddr.sin_port != 0)
++   if (PasvAddr != 0)
+    {
+       // Get a socket
+-      if ((DataFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
++      if ((DataFd = socket(PasvAddr->ai_family,PasvAddr->ai_socktype,
++                         PasvAddr->ai_protocol)) < 0)
+        return _error->Errno("socket","Could not create a socket");
+       
+       // Connect to the server
+       SetNonBlock(DataFd,true);
+-      if (connect(DataFd,(sockaddr *)&PasvAddr,sizeof(PasvAddr)) < 0 &&
++      if (connect(DataFd,PasvAddr->ai_addr,PasvAddr->ai_addrlen) < 0 &&
+         errno != EINPROGRESS)
+        return _error->Errno("socket","Could not create a socket");
+    
+       /* This implements a timeout for connect by opening the connection
+          nonblocking */
+-      if (WaitFd(ServerFd,true,TimeOut) == false)
++      if (WaitFd(DataFd,true,TimeOut) == false)
+        return _error->Error("Could not connect data socket, connection timed out");
+       unsigned int Err;
+       unsigned int Len = sizeof(Err);
+-      if (getsockopt(ServerFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
++      if (getsockopt(DataFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
+        return _error->Errno("getsockopt","Failed");
+       if (Err != 0)
+-       return _error->Error("Could not connect.");
+-      
++       return _error->Error("Could not connect passive socket.");
++
+       return true;
+    }
+    
+@@ -582,43 +707,91 @@
+    close(DataListenFd);
+    DataListenFd = -1;
+-   // Get a socket
+-   if ((DataListenFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
++   // Get the information for a listening socket.
++   struct addrinfo *BindAddr = 0;
++   struct addrinfo Hints;
++   memset(&Hints,0,sizeof(Hints));
++   Hints.ai_socktype = SOCK_STREAM;
++   Hints.ai_flags |= AI_PASSIVE;
++   Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
++   int Res;
++   if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
++      return _error->Error("getaddrinfo was unable to get a listening socket");
++   
++   // Construct the socket
++   if ((DataListenFd = socket(BindAddr->ai_family,BindAddr->ai_socktype,
++                            BindAddr->ai_protocol)) < 0)
++   {
++      freeaddrinfo(BindAddr);
+       return _error->Errno("socket","Could not create a socket");
++   }
+    
+    // Bind and listen
+-   sockaddr_in Addr;
+-   memset(&Addr,0,sizeof(Addr));
+-   if (bind(DataListenFd,(sockaddr *)&Addr,sizeof(Addr)) < 0)
++   if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
++   {
++      freeaddrinfo(BindAddr);
+       return _error->Errno("bind","Could not bind a socket");
++   }
++   freeaddrinfo(BindAddr);   
+    if (listen(DataListenFd,1) < 0)
+       return _error->Errno("listen","Could not listen on the socket");
+    SetNonBlock(DataListenFd,true);
+    
+    // Determine the name to send to the remote
+-   sockaddr_in Addr2;
+-   socklen_t Jnk = sizeof(Addr);
+-   if (getsockname(DataListenFd,(sockaddr *)&Addr,&Jnk) < 0)
+-      return _error->Errno("getsockname","Could not determine the socket's name");
+-   Jnk = sizeof(Addr2);
+-   if (getsockname(ServerFd,(sockaddr *)&Addr2,&Jnk) < 0)
++   struct sockaddr_storage Addr;
++   socklen_t AddrLen = sizeof(Addr);
++   if (getsockname(DataListenFd,(sockaddr *)&Addr,&AddrLen) < 0)
+       return _error->Errno("getsockname","Could not determine the socket's name");
+-   
+-   // This bit ripped from qftp
+-   unsigned long badr = ntohl(*(unsigned long *)&Addr2.sin_addr);
+-   unsigned long bp = ntohs(Addr.sin_port);
+-   // Send the port command
++   // Reverse the address. We need the server address and the data port.
++   char Name[NI_MAXHOST];
++   char Service[NI_MAXSERV];
++   char Service2[NI_MAXSERV];
++   getnameinfo((struct sockaddr *)&Addr,AddrLen,
++             Name,sizeof(Name),Service,sizeof(Service),
++             NI_NUMERICHOST|NI_NUMERICSERV);
++   getnameinfo((struct sockaddr *)&ServerAddr,ServerAddrLen,
++             Name,sizeof(Name),Service2,sizeof(Service2),
++             NI_NUMERICHOST|NI_NUMERICSERV);
++
++   // Send off an IPv4 address in the old port format
++   if (((struct sockaddr *)&Addr)->sa_family == AF_INET && 
++       ForceExtended == false)
++   {
++      // Convert the dots in the quad into commas
++      for (char *I = Name; *I != 0; I++)
++       if (*I == '.')
++          *I = ',';
++      unsigned long Port = atoi(Service);
++      
++      // Send the port command
++      unsigned int Tag;
++      string Msg;
++      if (WriteMsg(Tag,Msg,"PORT %s,%d,%d",
++                 Name,
++                 (int)(Port >> 8) & 0xff, (int)(Port & 0xff)) == false)
++       return false;
++      if (Tag >= 400)
++       return _error->Error("Unable to send PORT command");
++      return true;
++   }
++
++   // Construct an EPRT command
++   unsigned Proto = 0;
++   for (unsigned J = 0; AFMap[J].Family != 0; J++)
++      if (AFMap[J].Family == ((struct sockaddr *)&Addr)->sa_family)
++       Proto = AFMap[J].IETFFamily;
++   if (Proto == 0)
++      return _error->Error("Unkonwn address family %u (AF_*)",
++                         ((struct sockaddr *)&Addr)->sa_family);
++   
++   // Send the EPRT command
+    unsigned int Tag;
+    string Msg;
+-   if (WriteMsg(Tag,Msg,"PORT %d,%d,%d,%d,%d,%d", 
+-              (int) (badr >> 24) & 0xff, (int) (badr >> 16) & 0xff, 
+-              (int) (badr >> 8) & 0xff,  (int) badr & 0xff, 
+-              (int) (bp >> 8) & 0xff, (int) bp & 0xff) == false)
++   if (WriteMsg(Tag,Msg,"EPRT |%u|%s|%s|",Proto,Name,Service) == false)
+       return false;
+    if (Tag >= 400)
+-      return _error->Error("Unable to send port command");
+-
++      return _error->Error("EPRT failed, server said: %s",Msg.c_str());
+    return true;
+ }
+                                                                       /*}}}*/
+@@ -629,7 +802,7 @@
+ bool FTPConn::Finalize()
+ {
+    // Passive mode? Do nothing
+-   if (PasvAddr.sin_port != 0)
++   if (PasvAddr != 0)
+       return true;
+    
+    // Close any old socket..
+@@ -906,18 +1079,20 @@
+ int main(int argc,const char *argv[])
+ { 
+-   /* See if we should become the http client - we do this for http
++   /* See if we should be come the http client - we do this for http
+       proxy urls */
+    if (getenv("ftp_proxy") != 0)
+    {
+       URI Proxy = string(getenv("ftp_proxy"));
+       
++      // Run the HTTP method
+       if (Proxy.Access == "http")
+       {
+        // Copy over the environment setting
+        char S[300];
+        snprintf(S,sizeof(S),"http_proxy=%s",getenv("ftp_proxy"));
+        putenv(S);
++       putenv("no_proxy=");
+        
+        // Run the http method
+        string Path = flNotFile(argv[0]) + "/http";
+diff -urN apt-0.3.19cnc52.org/methods/ftp.h apt-0.3.19cnc52/methods/ftp.h
+--- apt-0.3.19cnc52.org/methods/ftp.h  Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/ftp.h      Sat Sep  8 12:35:01 2001
+@@ -1,5 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+-// Description                                                                /*{{{*/// $Id$
++// Description                                                                /*{{{*/// $Id$
++// $Id$
+ /* ######################################################################
+    FTP Aquire Method - This is the FTP aquire method for APT.
+@@ -17,12 +18,20 @@
+    int DataFd;
+    int DataListenFd;
+    URI ServerName;
++   bool ForceExtended;
+    bool TryPassive;
+    bool Debug;
+-   
+-   struct sockaddr_in PasvAddr;
+-   struct sockaddr_in Peer;
++   struct addrinfo *PasvAddr;
++   
++   // Generic Peer Address
++   struct sockaddr_storage PeerAddr;
++   socklen_t PeerAddrLen;
++   
++   // Generic Server Address (us)
++   struct sockaddr_storage ServerAddr;
++   socklen_t ServerAddrLen;
++   
+    // Private helper functions
+    bool ReadLine(string &Text);      
+    bool Login();
+@@ -41,6 +50,7 @@
+    bool Open(pkgAcqMethod *Owner);
+    void Close();   
+    bool GoPasv();
++   bool ExtGoPasv();
+    
+    // Query
+    bool Size(const char *Path,unsigned long &Size);
+diff -urN apt-0.3.19cnc52.org/methods/http.cc apt-0.3.19cnc52/methods/http.cc
+--- apt-0.3.19cnc52.org/methods/http.cc        Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/http.cc    Sat Sep  8 12:41:18 2001
+@@ -1,20 +1,18 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+    HTTP Aquire Method - This is the HTTP aquire method for APT.
+    
+    It uses HTTP/1.1 and many of the fancy options there-in, such as
+-   pipelining, range, if-range and so on. It accepts on the command line
+-   a list of url destination pairs and writes to stdout the status of the
+-   operation as defined in the APT method spec.
+-   
+-   It is based on a doubly buffered select loop. All the requests are 
++   pipelining, range, if-range and so on. 
++
++   It is based on a doubly buffered select loop. A groupe of requests are 
+    fed into a single output buffer that is constantly fed out the 
+    socket. This provides ideal pipelining as in many cases all of the
+    requests will fit into a single packet. The input socket is buffered 
+-   the same way and fed into the fd for the file.
++   the same way and fed into the fd for the file (may be a pipe in future).
+    
+    This double buffering provides fairly substantial transfer rates,
+    compared to wget the http method is about 4% faster. Most importantly,
+@@ -39,6 +37,8 @@
+ #include <signal.h>
+ #include <stdio.h>
+ #include <errno.h>
++#include <string.h>
++#include <iostream>
+ // Internet stuff
+ #include <netdb.h>
+@@ -48,6 +48,7 @@
+ #include "http.h"
+                                                                       /*}}}*/
++using namespace std;
+ string HttpMethod::FailFile;
+ int HttpMethod::FailFd = -1;
+@@ -140,7 +141,7 @@
+       unsigned long Sz = LeftRead();
+       if (OutQueue.length() - StrPos < Sz)
+        Sz = OutQueue.length() - StrPos;
+-      memcpy(Buf + (InP%Size),OutQueue.begin() + StrPos,Sz);
++      memcpy(Buf + (InP%Size),OutQueue.c_str() + StrPos,Sz);
+       
+       // Advance
+       StrPos += Sz;
+@@ -258,9 +259,6 @@
+ // ServerState::Open - Open a connection to the server                        /*{{{*/
+ // ---------------------------------------------------------------------
+ /* This opens a connection to the server. */
+-string LastHost;
+-int LastPort = 0;
+-struct addrinfo *LastHostAddr = 0;
+ bool ServerState::Open()
+ {
+    // Use the already open connection if possible.
+@@ -270,7 +268,8 @@
+    Close();
+    In.Reset();
+    Out.Reset();
+-
++   Persistent = true;
++   
+    // Determine the proxy setting
+    if (getenv("http_proxy") == 0)
+    {
+@@ -289,32 +288,13 @@
+    else
+       Proxy = getenv("http_proxy");
+    
+-   // Parse no_proxy, a , seperated list of domains
++   // Parse no_proxy, a , separated list of domains
+    if (getenv("no_proxy") != 0)
+    {
+-      const char *Start = getenv("no_proxy");
+-      const char *ServerEnd = ServerName.Host.end();
+-      
+-      for (const char *Cur = Start; true ; Cur++)
+-      {
+-       if (*Cur != ',' && *Cur != 0)
+-          continue;
+-
+-       // match end of the string
+-       if ((ServerName.Host.size() >= (Cur - Start))
+-           && stringcasecmp(ServerEnd - (Cur - Start),
+-                            ServerEnd,Start,Cur) == 0)
+-       {
+-          Proxy = "";
+-          break;
+-       }
+-       
+-       Start = Cur + 1;
+-       if (*Cur == 0)
+-          break;
+-      }        
++      if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
++       Proxy = "";
+    }
+-
++   
+    // Determine what host and port to use based on the proxy settings
+    int Port = 0;
+    string Host;   
+@@ -380,14 +360,23 @@
+       {
+        string::const_iterator J = I;
+        for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
+-       if (HeaderLine(string(I,J-I)) == false)
++       if (HeaderLine(string(I,J)) == false)
+           return 2;
+        I = J;
+       }
++
++      // 100 Continue is a Nop...
++      if (Result == 100)
++       continue;
++      
++      // Tidy up the connection persistance state.
++      if (Encoding == Closes && HaveContent == true)
++       Persistent = false;
++      
+       return 0;
+    }
+    while (Owner->Go(false,this) == true);
+-
++   
+    return 1;
+ }
+                                                                       /*}}}*/
+@@ -513,7 +502,7 @@
+    string Tag = string(Line,0,Pos);
+    string Val = string(Line,Pos2);
+    
+-   if (stringcasecmp(Tag.begin(),Tag.begin()+4,"HTTP") == 0)
++   if (stringcasecmp(Tag.c_str(),Tag.c_str()+4,"HTTP") == 0)
+    {
+       // Evil servers return no version
+       if (Line[4] == '/')
+@@ -529,7 +518,19 @@
+        if (sscanf(Line.c_str(),"HTTP %u %[^\n]",&Result,Code) != 2)
+           return _error->Error("The http server sent an invalid reply header");
+       }
+-      
++
++      /* Check the HTTP response header to get the default persistance
++         state. */
++      if (Major < 1)
++       Persistent = false;
++      else
++      {
++       if (Major == 1 && Minor <= 0)
++          Persistent = false;
++       else
++          Persistent = true;
++      }
++
+       return true;
+    }      
+       
+@@ -569,11 +570,19 @@
+    {
+       HaveContent = true;
+       if (stringcasecmp(Val,"chunked") == 0)
+-       Encoding = Chunked;
+-      
++       Encoding = Chunked;      
+       return true;
+    }
++   if (stringcasecmp(Tag,"Connection:") == 0)
++   {
++      if (stringcasecmp(Val,"close") == 0)
++       Persistent = false;
++      if (stringcasecmp(Val,"keep-alive") == 0)
++       Persistent = true;
++      return true;
++   }
++   
+    if (stringcasecmp(Tag,"Last-Modified:") == 0)
+    {
+       if (StrToTime(Val,Date) == false)
+@@ -660,10 +669,11 @@
+       Req += string("Proxy-Authorization: Basic ") + 
+           Base64Encode(Proxy.User + ":" + Proxy.Password) + "\r\n";
+-   if (0)//akk
+-       Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
+-   else
+-       Req += "User-Agent: Conectiva APT-HTTP/1.2\r\n\r\n";
++   if (Uri.User.empty() == false || Uri.Password.empty() == false)
++      Req += string("Authorization: Basic ") + 
++          Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n";
++   
++   Req += "User-Agent: PLD APT-HTTP/1.2\r\n\r\n";
+    
+    if (Debug == true)
+       cerr << Req << endl;
+@@ -686,10 +696,12 @@
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    
+-   // Add the server
+-   if (Srv->Out.WriteSpace() == true && Srv->ServerFd != -1) 
++   /* Add the server. We only send more requests if the connection will 
++      be persisting */
++   if (Srv->Out.WriteSpace() == true && Srv->ServerFd != -1 
++       && Srv->Persistent == true)
+       FD_SET(Srv->ServerFd,&wfds);
+-   if (Srv->In.ReadSpace() == true && Srv->ServerFd != -1) 
++   if (Srv->In.ReadSpace() == true && Srv->ServerFd != -1)
+       FD_SET(Srv->ServerFd,&rfds);
+    
+    // Add the file
+@@ -714,7 +726,11 @@
+    tv.tv_usec = 0;
+    int Res = 0;
+    if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0)
++   {
++      if (errno == EINTR)
++       return true;
+       return _error->Errno("select","Select failed");
++   }
+    
+    if (Res == 0)
+    {
+@@ -1007,7 +1023,15 @@
+        delete Server;
+        Server = new ServerState(Queue->Uri,this);
+       }
+-            
++      
++      /* If the server has explicitly said this is the last connection
++         then we pre-emptively shut down the pipeline and tear down 
++       the connection. This will speed up HTTP/1.0 servers a tad
++       since we don't have to wait for the close sequence to
++         complete */
++      if (Server->Persistent == false)
++       Server->Close();
++      
+       // Reset the pipeline
+       if (Server->ServerFd == -1)
+        QueueBack = Queue;      
+@@ -1035,6 +1059,7 @@
+        {
+           _error->Error("Bad header Data");
+           Fail(true);
++          RotateDNS();
+           continue;
+        }
+        
+@@ -1053,6 +1078,7 @@
+              FailCounter = 0;
+           }
+           
++          RotateDNS();
+           continue;
+        }
+       };
+@@ -1070,6 +1096,11 @@
+           // Run the data
+           bool Result =  Server->RunData();
++          /* If the server is sending back sizeless responses then fill in
++             the size now */
++          if (Res.Size == 0)
++             Res.Size = File->Size();
++          
+           // Close the file, destroy the FD object and timestamp it
+           FailFd = -1;
+           delete File;
+@@ -1090,7 +1121,7 @@
+           }
+           else
+              Fail(true);
+-
++          
+           break;
+        }
+        
+@@ -1112,6 +1143,7 @@
+        case 5:
+        {
+           Fail();
++          RotateDNS();
+           Server->Close();
+           break;
+        }
+diff -urN apt-0.3.19cnc52.org/methods/http.h apt-0.3.19cnc52/methods/http.h
+--- apt-0.3.19cnc52.org/methods/http.h Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/http.h     Sat Sep  8 12:42:54 2001
+@@ -1,5 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+-// Description                                                                /*{{{*/// $Id$
++// Description                                                                /*{{{*/// $Id$
++// $Id$
+ /* ######################################################################
+    HTTP Aquire Method - This is the HTTP aquire method for APT.
+@@ -12,6 +13,11 @@
+ #define MAXLEN 360
++#include <iostream>
++
++using std::cout;
++using std::endl;
++
+ class HttpMethod;
+ class CircleBuf
+@@ -87,6 +93,9 @@
+    bool HaveContent;
+    enum {Chunked,Stream,Closes} Encoding;
+    enum {Header, Data} State;
++   bool Persistent;
++   
++   // This is a Persistent attribute of the server itself.
+    bool Pipeline;
+    
+    HttpMethod *Owner;
+@@ -130,7 +139,7 @@
+    static void SigTerm(int);
+    
+    public:
+-   friend ServerState;
++   friend class ServerState;
+    FileFd *File;
+    ServerState *Server;
+diff -urN apt-0.3.19cnc52.org/methods/rfc2553emu.cc apt-0.3.19cnc52/methods/rfc2553emu.cc
+--- apt-0.3.19cnc52.org/methods/rfc2553emu.cc  Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/rfc2553emu.cc      Tue Feb 20 08:03:18 2001
+@@ -1,6 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+    RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
+@@ -36,20 +36,6 @@
+    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;
+@@ -86,10 +72,32 @@
+         hints->ai_socktype != 0)
+        return EAI_SERVICE;
+    }
++      
++   // Hostname lookup, only if this is not a listening socket
++   if (hints != 0 && (hints->ai_flags & AI_PASSIVE) != AI_PASSIVE)
++   {
++      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;
++      
++      CurAddr = Addr->h_addr_list;
++   }
++   else
++      CurAddr = (char **)&End;    // Fake!
+    
+    // Start constructing the linked list
+    *res = 0;
+-   for (CurAddr = Addr->h_addr_list; *CurAddr != 0; CurAddr++)
++   for (; *CurAddr != 0; CurAddr++)
+    {
+       // New result structure
+       *Result = (struct addrinfo *)calloc(sizeof(**Result),1);
+@@ -124,8 +132,15 @@
+       // 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);
+-
++      
++      if (hints != 0 && (hints->ai_flags & AI_PASSIVE) != AI_PASSIVE)
++       ((struct sockaddr_in *)(*Result)->ai_addr)->sin_addr = *(in_addr *)(*CurAddr);
++      else
++      {
++         // Already zerod by calloc.
++       break;
++      }
++      
+       Result = &(*Result)->ai_next;
+    }
+    
+@@ -202,9 +217,9 @@
+       {
+        struct servent *Ent;
+        if ((flags & NI_DATAGRAM) == NI_DATAGRAM)
+-          Ent = getservbyport(sin->sin_port,"udp");
++          Ent = getservbyport(ntohs(sin->sin_port),"udp");
+        else
+-          Ent = getservbyport(sin->sin_port,"tcp");
++          Ent = getservbyport(ntohs(sin->sin_port),"tcp");
+        
+        if (Ent != 0)
+           strncpy(serv,Ent->s_name,servlen);
+@@ -220,7 +235,7 @@
+       // Resolve as a plain numberic
+       if ((flags & NI_NUMERICSERV) == NI_NUMERICSERV)
+       {
+-       snprintf(serv,servlen,"%u",sin->sin_port);
++       snprintf(serv,servlen,"%u",ntohs(sin->sin_port));
+       }
+    }
+    
+diff -urN apt-0.3.19cnc52.org/methods/rfc2553emu.h apt-0.3.19cnc52/methods/rfc2553emu.h
+--- apt-0.3.19cnc52.org/methods/rfc2553emu.h   Thu Sep  6 22:20:43 2001
++++ apt-0.3.19cnc52/methods/rfc2553emu.h       Sun Jun 18 08:04:45 2000
+@@ -1,6 +1,6 @@
+ // -*- mode: cpp; mode: fold -*-
+ // Description                                                                /*{{{*/
+-// $Id$
++// $Id$
+ /* ######################################################################
+    RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
+@@ -74,6 +74,11 @@
+   #define EAI_MEMORY     -11
+   #endif
++  /* If we don't have getaddrinfo then we probably don't have 
++     sockaddr_storage either (same RFC) so we definately will not be
++     doing any IPv6 stuff. Do not use the members of this structure to
++     retain portability, cast to a sockaddr. */
++  #define sockaddr_storage sockaddr_in
+ #endif
+ // getnameinfo support (glibc2.0 has getaddrinfo only)
+@@ -97,6 +102,12 @@
+   #define NI_DATAGRAM (1<<4)
+   #endif
++  #define sockaddr_storage sockaddr_in
++#endif
++
++// Glibc 2.0.7 misses this one
++#ifndef AI_NUMERICHOST
++#define AI_NUMERICHOST 0
+ #endif
+ #endif
This page took 0.156996 seconds and 4 git commands to generate.