1 diff -urN apt-0.3.19cnc52.org/apt-pkg/acquire-method.cc apt-0.3.19cnc52/apt-pkg/acquire-method.cc
2 --- apt-0.3.19cnc52.org/apt-pkg/acquire-method.cc Thu Sep 6 22:20:42 2001
3 +++ apt-0.3.19cnc52/apt-pkg/acquire-method.cc Sat Sep 8 13:18:36 2001
7 snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
8 - "Message: %s\n",Queue->Uri.c_str(),Err.c_str());
9 + "Message: %s %s\n",Queue->Uri.c_str(),Err.c_str(),
13 FetchItem *Tmp = Queue;
17 snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
18 - "Message: %s\n",Err.c_str());
19 + "Message: %s %s\n",Err.c_str(),
22 // Set the transient flag
23 if (Transient == true)
24 diff -urN apt-0.3.19cnc52.org/apt-pkg/acquire-method.h apt-0.3.19cnc52/apt-pkg/acquire-method.h
25 --- apt-0.3.19cnc52.org/apt-pkg/acquire-method.h Thu Sep 6 22:20:42 2001
26 +++ apt-0.3.19cnc52/apt-pkg/acquire-method.h Sat Sep 8 13:15:34 2001
28 vector<string> Messages;
33 // Handlers for messages
34 virtual bool Configuration(string Message);
36 void Status(const char *Format,...);
38 int Run(bool Single = false);
39 + inline void SetFailExtraMsg(string Msg) {FailExtra = Msg;};
41 pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
42 virtual ~pkgAcqMethod() {};
43 diff -urN apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.cc apt-0.3.19cnc52/apt-pkg/contrib/strutl.cc
44 --- apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.cc Thu Sep 6 22:20:42 2001
45 +++ apt-0.3.19cnc52/apt-pkg/contrib/strutl.cc Sat Sep 8 12:54:40 2001
51 +// CheckDomainList - See if Host is in a , seperate list /*{{{*/
52 +// ---------------------------------------------------------------------
53 +/* The domain list is a comma seperate list of domains that are suffix
54 + matched against the argument */
55 +bool CheckDomainList(string Host,string List)
57 + string::const_iterator Start = List.begin();
58 + for (string::const_iterator Cur = List.begin(); Cur <= List.end(); Cur++)
60 + if (Cur < List.end() && *Cur != ',')
63 + // Match the end of the string..
64 + if ((Host.size() >= (unsigned)(Cur - Start)) &&
66 + stringcasecmp(Host.end() - (Cur - Start),Host.end(),Start,Cur) == 0)
74 // URI::CopyFrom - Copy from an object /*{{{*/
75 // ---------------------------------------------------------------------
76 /* This parses the URI into all of its components */
77 diff -urN apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.h apt-0.3.19cnc52/apt-pkg/contrib/strutl.h
78 --- apt-0.3.19cnc52.org/apt-pkg/contrib/strutl.h Thu Sep 6 22:20:42 2001
79 +++ apt-0.3.19cnc52/apt-pkg/contrib/strutl.h Sat Sep 8 12:53:14 2001
82 bool TokSplitString(char Tok,char *Input,char **List,
83 unsigned long ListMax);
84 +bool CheckDomainList(string Host,string List);
86 int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
87 inline int stringcmp(const char *A,const char *AEnd,const char *B) {return stringcmp(A,AEnd,B,B+strlen(B));};
88 diff -urN apt-0.3.19cnc52.org/methods/connect.cc apt-0.3.19cnc52/methods/connect.cc
89 --- apt-0.3.19cnc52.org/methods/connect.cc Thu Sep 6 22:20:43 2001
90 +++ apt-0.3.19cnc52/methods/connect.cc Tue Feb 20 08:03:18 2001
92 // -*- mode: cpp; mode: fold -*-
93 // Description /*{{{*/
96 /* ######################################################################
98 Connect - Replacement connect call
100 static struct addrinfo *LastHostAddr = 0;
101 static struct addrinfo *LastUsed = 0;
103 +// RotateDNS - Select a new server from a DNS rotation /*{{{*/
104 +// ---------------------------------------------------------------------
105 +/* This is called during certain errors in order to recover by selecting a
109 + if (LastUsed != 0 && LastUsed->ai_next != 0)
110 + LastUsed = LastUsed->ai_next;
112 + LastUsed = LastHostAddr;
115 // DoConnect - Attempt a connect operation /*{{{*/
116 // ---------------------------------------------------------------------
117 /* This helper function attempts a connection to a single address. */
120 // Show a status indicator
121 char Name[NI_MAXHOST];
123 + char Service[NI_MAXSERV];
127 getnameinfo(Addr->ai_addr,Addr->ai_addrlen,
128 - Name,sizeof(Name),0,0,NI_NUMERICHOST);
129 + Name,sizeof(Name),Service,sizeof(Service),
130 + NI_NUMERICHOST|NI_NUMERICSERV);
131 Owner->Status("Connecting to %s (%s)",Host.c_str(),Name);
134 + /* If this is an IP rotation store the IP we are using.. If something goes
135 + wrong this will get tacked onto the end of the error message */
136 + if (LastHostAddr->ai_next != 0)
138 + char Name2[NI_MAXHOST + NI_MAXSERV + 10];
139 + snprintf(Name2,sizeof(Name2),"[IP: %s %s]",Name,Service);
140 + Owner->SetFailExtraMsg(string(Name2));
143 + Owner->SetFailExtraMsg("");
146 if ((Fd = socket(Addr->ai_family,Addr->ai_socktype,
147 Addr->ai_protocol)) < 0)
148 - return _error->Errno("socket","Could not create a socket");
149 + return _error->Errno("socket","Could not create a socket for %s (f=%u t=%u p=%u)",
150 + Name,Addr->ai_family,Addr->ai_socktype,Addr->ai_protocol);
152 SetNonBlock(Fd,true);
153 if (connect(Fd,Addr->ai_addr,Addr->ai_addrlen) < 0 &&
154 errno != EINPROGRESS)
155 return _error->Errno("connect","Cannot initiate the connection "
156 - "to %s (%s).",Host.c_str(),Name);
157 + "to %s:%s (%s).",Host.c_str(),Service,Name);
159 /* This implements a timeout for connect by opening the connection
161 if (WaitFd(Fd,true,TimeOut) == false)
162 - return _error->Error("Could not connect to %s (%s), "
163 - "connection timed out",Host.c_str(),Name);
165 + return _error->Error("Could not connect to %s:%s (%s), "
166 + "connection timed out",Host.c_str(),Service,Name);
168 // Check the socket for an error condition
170 unsigned int Len = sizeof(Err);
172 return _error->Errno("getsockopt","Failed");
175 - return _error->Error("Could not connect to %s (%s).",Host.c_str(),Name);
179 + return _error->Errno("connect","Could not connect to %s:%s (%s).",Host.c_str(),
188 if (_error->PendingError() == true)
191 + // Convert the port name/number
194 + snprintf(ServStr,sizeof(ServStr),"%u",Port);
196 + snprintf(ServStr,sizeof(ServStr),"%s",Service);
198 /* We used a cached address record.. Yes this is against the spec but
199 the way we have setup our rotating dns suggests that this is more
202 Owner->Status("Connecting to %s",Host.c_str());
207 - snprintf(S,sizeof(S),"%u",Port);
209 - snprintf(S,sizeof(S),"%s",Service);
211 // Free the old address structure
212 if (LastHostAddr != 0)
214 freeaddrinfo(LastHostAddr);
219 // We only understand SOCK_STREAM sockets.
220 struct addrinfo Hints;
221 memset(&Hints,0,sizeof(Hints));
222 Hints.ai_socktype = SOCK_STREAM;
223 - Hints.ai_protocol = IPPROTO_TCP; // Right?
224 + Hints.ai_protocol = 0;
226 // Resolve both the host and service simultaneously
230 - if ((Res = getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr)) != 0 ||
231 + if ((Res = getaddrinfo(Host.c_str(),ServStr,&Hints,&LastHostAddr)) != 0 ||
234 if (Res == EAI_NONAME || Res == EAI_SERVICE)
238 - snprintf(S,sizeof(S),"%u",DefPort);
239 + snprintf(ServStr,sizeof(ServStr),"%u",DefPort);
243 return _error->Error("Could not resolve '%s'",Host.c_str());
246 - return _error->Error("Something wicked happend resolving '%s/%s'",
248 + return _error->Error("Something wicked happened resolving '%s:%s' (%i)",
249 + Host.c_str(),ServStr,Res);
254 - if (LastHostAddr->ai_family == AF_UNIX)
255 - return _error->Error("getaddrinfo returned a unix domain socket\n");
262 - // Get the printable IP address
263 + // When we have an IP rotation stay with the last IP.
264 struct addrinfo *CurHost = LastHostAddr;
267 @@ -155,14 +184,28 @@
271 - CurHost = CurHost->ai_next;
273 + // Ignore UNIX domain sockets
276 + CurHost = CurHost->ai_next;
278 + while (CurHost != 0 && CurHost->ai_family == AF_UNIX);
280 + /* If we reached the end of the search list then wrap around to the
282 + if (CurHost == 0 && LastUsed != 0)
283 + CurHost = LastHostAddr;
285 + // Reached the end of the search cycle
286 + if (CurHost == LastUsed)
295 if (_error->PendingError() == true)
297 - return _error->Error("Unable to connect to '%s'",Host.c_str());
299 + return _error->Error("Unable to connect to %s %s:",Host.c_str(),ServStr);
302 diff -urN apt-0.3.19cnc52.org/methods/connect.h apt-0.3.19cnc52/methods/connect.h
303 --- apt-0.3.19cnc52.org/methods/connect.h Thu Sep 6 22:20:43 2001
304 +++ apt-0.3.19cnc52/methods/connect.h Tue Feb 20 08:03:18 2001
306 // -*- mode: cpp; mode: fold -*-
307 // Description /*{{{*/
310 /* ######################################################################
312 Connect - Replacement connect call
315 bool Connect(string To,int Port,const char *Service,int DefPort,
316 int &Fd,unsigned long TimeOut,pkgAcqMethod *Owner);
320 diff -urN apt-0.3.19cnc52.org/methods/ftp.cc apt-0.3.19cnc52/methods/ftp.cc
321 --- apt-0.3.19cnc52.org/methods/ftp.cc Thu Sep 6 22:20:43 2001
322 +++ apt-0.3.19cnc52/methods/ftp.cc Sat Sep 8 12:33:40 2001
324 // -*- mode: cpp; mode: fold -*-
325 // Description /*{{{*/
328 /* ######################################################################
330 - HTTP Aquire Method - This is the FTP aquire method for APT.
331 + FTP Aquire Method - This is the FTP aquire method for APT.
333 This is a very simple implementation that does not try to optimize
334 at all. Commands are sent syncronously with the FTP server (as the
342 #include <netinet/in.h>
347 +using namespace std;
349 +/* This table is for the EPRT and EPSV commands, it maps the OS address
350 + family to the IETF address families */
353 + unsigned long Family;
354 + unsigned long IETFFamily;
358 +struct AFMap AFMap[] = {{AF_INET,1},{}};
360 +struct AFMap AFMap[] = {{AF_INET,1},{AF_INET6,2},{}};
363 unsigned long TimeOut = 120;
365 string FtpMethod::FailFile;
367 DataListenFd(-1), ServerName(Srv)
369 Debug = _config->FindB("Debug::Acquire::Ftp",false);
370 - memset(&PasvAddr,0,sizeof(PasvAddr));
374 // FTPConn::~FTPConn - Destructor /*{{{*/
379 - memset(&PasvAddr,0,sizeof(PasvAddr));
382 + freeaddrinfo(PasvAddr);
386 // FTPConn::Open - Open a new connection /*{{{*/
393 // Determine the proxy setting
394 if (getenv("ftp_proxy") == 0)
396 @@ -108,32 +128,13 @@
398 Proxy = getenv("ftp_proxy");
400 - // Parse no_proxy, a , seperated list of domains
401 + // Parse no_proxy, a , separated list of domains
402 if (getenv("no_proxy") != 0)
404 - const char *Start = getenv("no_proxy");
405 - const char *ServerEnd = ServerName.Host.end();
407 - for (const char *Cur = Start; true ; Cur++)
409 - if (*Cur != ',' && *Cur != 0)
412 - // match end of the string
413 - if ((ServerName.Host.size() >= (Cur - Start))
414 - && stringcasecmp(ServerEnd - (Cur - Start),
415 - ServerEnd,Start,Cur) == 0)
425 + if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
430 // Determine what host and port to use based on the proxy settings
433 @@ -150,15 +151,27 @@
437 - // Connect to the remote server
438 + /* Connect to the remote server. Since FTP is connection oriented we
439 + want to make sure we get a new server every time we reconnect */
441 if (Connect(Host,Port,"ftp",21,ServerFd,TimeOut,Owner) == false)
443 - socklen_t Len = sizeof(Peer);
444 - if (getpeername(ServerFd,(sockaddr *)&Peer,&Len) != 0)
446 + // Login must be before getpeername otherwise dante won't work.
447 + Owner->Status("Logging in");
448 + bool Res = Login();
450 + // Get the remote server's address
451 + PeerAddrLen = sizeof(PeerAddr);
452 + if (getpeername(ServerFd,(sockaddr *)&PeerAddr,&PeerAddrLen) != 0)
453 return _error->Errno("getpeername","Unable to determine the peer name");
455 - Owner->Status("Logging in");
457 + // Get the local machine's address
458 + ServerAddrLen = sizeof(ServerAddr);
459 + if (getsockname(ServerFd,(sockaddr *)&ServerAddr,&ServerAddrLen) != 0)
460 + return _error->Errno("getsockname","Unable to determine the local name");
465 // FTPConn::Login - Login to the remote server /*{{{*/
468 // Setup the variables needed for authentication
469 string User = "anonymous";
472 - Pass = "apt_get_ftp_2.0@debian.linux.user";
474 - Pass = "apt_get_ftp_2.0@conectiva.linux.user";
475 + string Pass = "apt_get_ftp_2.0@pld.linux.user";
477 // Fill in the user/pass
478 if (ServerName.User.empty() == false)
480 if (_config->Exists("Acquire::FTP::Passive::" + ServerName.Host) == true)
481 TryPassive = _config->FindB("Acquire::FTP::Passive::" + ServerName.Host,true);
483 - TryPassive = _config->FindB("Acquire::FTP::Passive",true);
484 + TryPassive = _config->FindB("Acquire::FTP::Passive",true);
492 + // Force the use of extended commands
493 + if (_config->Exists("Acquire::FTP::ForceExtended::" + ServerName.Host) == true)
494 + ForceExtended = _config->FindB("Acquire::FTP::ForceExtended::" + ServerName.Host,true);
496 + ForceExtended = _config->FindB("Acquire::FTP::ForceExtended",false);
499 if (WriteMsg(Tag,Msg,"TYPE I") == false)
504 int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len);
506 + _error->Error("Server closed the connection");
509 _error->Errno("read","Read error");
510 @@ -439,10 +456,19 @@
511 // ---------------------------------------------------------------------
512 /* Try to enter passive mode, the return code does not indicate if passive
513 mode could or could not be established, only if there was a fatal error.
514 - Borrowed mostly from lftp. We have to enter passive mode every time
515 - we make a data connection :| */
516 + We have to enter passive mode every time we make a data connection :| */
517 bool FTPConn::GoPasv()
519 + /* The PASV command only works on IPv4 sockets, even though it could
520 + in theory suppory IPv6 via an all zeros reply */
521 + if (((struct sockaddr *)&PeerAddr)->sa_family != AF_INET ||
522 + ForceExtended == true)
523 + return ExtGoPasv();
526 + freeaddrinfo(PasvAddr);
529 // Try to enable pasv mode
532 @@ -452,41 +478,139 @@
533 // Unsupported function
534 string::size_type Pos = Msg.find('(');
535 if (Tag >= 400 || Pos == string::npos)
537 - memset(&PasvAddr,0,sizeof(PasvAddr));
542 unsigned a0,a1,a2,a3,p0,p1;
543 if (sscanf(Msg.c_str() + Pos,"(%u,%u,%u,%u,%u,%u)",&a0,&a1,&a2,&a3,&p0,&p1) != 6)
546 + /* Some evil servers return 0 to mean their addr. We can actually speak
547 + to these servers natively using IPv6 */
548 + if (a0 == 0 && a1 == 0 && a2 == 0 && a3 == 0)
550 - memset(&PasvAddr,0,sizeof(PasvAddr));
551 + // Get the IP in text form
552 + char Name[NI_MAXHOST];
553 + char Service[NI_MAXSERV];
554 + getnameinfo((struct sockaddr *)&PeerAddr,PeerAddrLen,
555 + Name,sizeof(Name),Service,sizeof(Service),
556 + NI_NUMERICHOST|NI_NUMERICSERV);
558 + struct addrinfo Hints;
559 + memset(&Hints,0,sizeof(Hints));
560 + Hints.ai_socktype = SOCK_STREAM;
561 + Hints.ai_family = ((struct sockaddr *)&PeerAddr)->sa_family;
562 + Hints.ai_flags |= AI_NUMERICHOST;
564 + // Get a new passive address.
566 + snprintf(Port,sizeof(Port),"%u",(p0 << 8) + p1);
567 + if (getaddrinfo(Name,Port,&Hints,&PasvAddr) != 0)
572 - // lftp used this horrid byte order manipulation.. Ik.
573 - PasvAddr.sin_family = AF_INET;
576 - a = (unsigned char *)&PasvAddr.sin_addr;
577 - p = (unsigned char *)&PasvAddr.sin_port;
578 + struct addrinfo Hints;
579 + memset(&Hints,0,sizeof(Hints));
580 + Hints.ai_socktype = SOCK_STREAM;
581 + Hints.ai_family = AF_INET;
582 + Hints.ai_flags |= AI_NUMERICHOST;
584 + // Get a new passive address.
586 + snprintf(Port,sizeof(Port),"%u",(p0 << 8) + p1);
588 + snprintf(Name,sizeof(Name),"%u.%u.%u.%u",a0,a1,a2,a3);
589 + if (getaddrinfo(Name,Port,&Hints,&PasvAddr) != 0)
594 +// FTPConn::ExtGoPasv - Enter Extended Passive mode /*{{{*/
595 +// ---------------------------------------------------------------------
596 +/* Try to enter extended passive mode. See GoPasv above and RFC 2428 */
597 +bool FTPConn::ExtGoPasv()
600 + freeaddrinfo(PasvAddr);
603 - // Some evil servers return 0 to mean their addr
604 - if (a0 == 0 && a1 == 0 && a2 == 0 && a3 == 0)
605 + // Try to enable pasv mode
608 + if (WriteMsg(Tag,Msg,"EPSV") == false)
611 + // Unsupported function
612 + string::size_type Pos = Msg.find('(');
613 + if (Tag >= 400 || Pos == string::npos)
617 + string::const_iterator List[4];
618 + unsigned Count = 0;
620 + for (string::const_iterator I = Msg.begin() + Pos; I < Msg.end(); I++)
622 - PasvAddr.sin_addr = Peer.sin_addr;
623 + if (*I != Msg[Pos])
633 + unsigned long Proto = 0;
634 + unsigned long Port = 0;
636 + IP = string(List[1]+1,List[2]);
637 + Port = atoi(string(List[2]+1,List[3]).c_str());
638 + if (IP.empty() == false)
639 + Proto = atoi(string(List[0]+1,List[1]).c_str());
644 + // String version of the port
646 + snprintf(PStr,sizeof(PStr),"%lu",Port);
648 + // Get the IP in text form
649 + struct addrinfo Hints;
650 + memset(&Hints,0,sizeof(Hints));
651 + Hints.ai_socktype = SOCK_STREAM;
652 + Hints.ai_flags |= AI_NUMERICHOST;
654 + /* The RFC defined case, connect to the old IP/protocol using the
656 + if (IP.empty() == true)
658 + // Get the IP in text form
659 + char Name[NI_MAXHOST];
660 + char Service[NI_MAXSERV];
661 + getnameinfo((struct sockaddr *)&PeerAddr,PeerAddrLen,
662 + Name,sizeof(Name),Service,sizeof(Service),
663 + NI_NUMERICHOST|NI_NUMERICSERV);
665 + Hints.ai_family = ((struct sockaddr *)&PeerAddr)->sa_family;
673 + // Get the family..
674 + Hints.ai_family = 0;
675 + for (unsigned J = 0; AFMap[J].Family != 0; J++)
676 + if (AFMap[J].IETFFamily == Proto)
677 + Hints.ai_family = AFMap[J].Family;
678 + if (Hints.ai_family == 0)
684 + // Get a new passive address.
686 + if ((Res = getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr)) != 0)
691 @@ -547,34 +671,35 @@
694 // Oops, didn't work out, don't bother trying again.
695 - if (PasvAddr.sin_port == 0)
701 - if (PasvAddr.sin_port != 0)
705 - if ((DataFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
706 + if ((DataFd = socket(PasvAddr->ai_family,PasvAddr->ai_socktype,
707 + PasvAddr->ai_protocol)) < 0)
708 return _error->Errno("socket","Could not create a socket");
710 // Connect to the server
711 SetNonBlock(DataFd,true);
712 - if (connect(DataFd,(sockaddr *)&PasvAddr,sizeof(PasvAddr)) < 0 &&
713 + if (connect(DataFd,PasvAddr->ai_addr,PasvAddr->ai_addrlen) < 0 &&
714 errno != EINPROGRESS)
715 return _error->Errno("socket","Could not create a socket");
717 /* This implements a timeout for connect by opening the connection
719 - if (WaitFd(ServerFd,true,TimeOut) == false)
720 + if (WaitFd(DataFd,true,TimeOut) == false)
721 return _error->Error("Could not connect data socket, connection timed out");
723 unsigned int Len = sizeof(Err);
724 - if (getsockopt(ServerFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
725 + if (getsockopt(DataFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
726 return _error->Errno("getsockopt","Failed");
728 - return _error->Error("Could not connect.");
730 + return _error->Error("Could not connect passive socket.");
735 @@ -582,43 +707,91 @@
740 - if ((DataListenFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
741 + // Get the information for a listening socket.
742 + struct addrinfo *BindAddr = 0;
743 + struct addrinfo Hints;
744 + memset(&Hints,0,sizeof(Hints));
745 + Hints.ai_socktype = SOCK_STREAM;
746 + Hints.ai_flags |= AI_PASSIVE;
747 + Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
749 + if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
750 + return _error->Error("getaddrinfo was unable to get a listening socket");
752 + // Construct the socket
753 + if ((DataListenFd = socket(BindAddr->ai_family,BindAddr->ai_socktype,
754 + BindAddr->ai_protocol)) < 0)
756 + freeaddrinfo(BindAddr);
757 return _error->Errno("socket","Could not create a socket");
762 - memset(&Addr,0,sizeof(Addr));
763 - if (bind(DataListenFd,(sockaddr *)&Addr,sizeof(Addr)) < 0)
764 + if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
766 + freeaddrinfo(BindAddr);
767 return _error->Errno("bind","Could not bind a socket");
769 + freeaddrinfo(BindAddr);
770 if (listen(DataListenFd,1) < 0)
771 return _error->Errno("listen","Could not listen on the socket");
772 SetNonBlock(DataListenFd,true);
774 // Determine the name to send to the remote
776 - socklen_t Jnk = sizeof(Addr);
777 - if (getsockname(DataListenFd,(sockaddr *)&Addr,&Jnk) < 0)
778 - return _error->Errno("getsockname","Could not determine the socket's name");
779 - Jnk = sizeof(Addr2);
780 - if (getsockname(ServerFd,(sockaddr *)&Addr2,&Jnk) < 0)
781 + struct sockaddr_storage Addr;
782 + socklen_t AddrLen = sizeof(Addr);
783 + if (getsockname(DataListenFd,(sockaddr *)&Addr,&AddrLen) < 0)
784 return _error->Errno("getsockname","Could not determine the socket's name");
786 - // This bit ripped from qftp
787 - unsigned long badr = ntohl(*(unsigned long *)&Addr2.sin_addr);
788 - unsigned long bp = ntohs(Addr.sin_port);
790 - // Send the port command
791 + // Reverse the address. We need the server address and the data port.
792 + char Name[NI_MAXHOST];
793 + char Service[NI_MAXSERV];
794 + char Service2[NI_MAXSERV];
795 + getnameinfo((struct sockaddr *)&Addr,AddrLen,
796 + Name,sizeof(Name),Service,sizeof(Service),
797 + NI_NUMERICHOST|NI_NUMERICSERV);
798 + getnameinfo((struct sockaddr *)&ServerAddr,ServerAddrLen,
799 + Name,sizeof(Name),Service2,sizeof(Service2),
800 + NI_NUMERICHOST|NI_NUMERICSERV);
802 + // Send off an IPv4 address in the old port format
803 + if (((struct sockaddr *)&Addr)->sa_family == AF_INET &&
804 + ForceExtended == false)
806 + // Convert the dots in the quad into commas
807 + for (char *I = Name; *I != 0; I++)
810 + unsigned long Port = atoi(Service);
812 + // Send the port command
815 + if (WriteMsg(Tag,Msg,"PORT %s,%d,%d",
817 + (int)(Port >> 8) & 0xff, (int)(Port & 0xff)) == false)
820 + return _error->Error("Unable to send PORT command");
824 + // Construct an EPRT command
825 + unsigned Proto = 0;
826 + for (unsigned J = 0; AFMap[J].Family != 0; J++)
827 + if (AFMap[J].Family == ((struct sockaddr *)&Addr)->sa_family)
828 + Proto = AFMap[J].IETFFamily;
830 + return _error->Error("Unkonwn address family %u (AF_*)",
831 + ((struct sockaddr *)&Addr)->sa_family);
833 + // Send the EPRT command
836 - if (WriteMsg(Tag,Msg,"PORT %d,%d,%d,%d,%d,%d",
837 - (int) (badr >> 24) & 0xff, (int) (badr >> 16) & 0xff,
838 - (int) (badr >> 8) & 0xff, (int) badr & 0xff,
839 - (int) (bp >> 8) & 0xff, (int) bp & 0xff) == false)
840 + if (WriteMsg(Tag,Msg,"EPRT |%u|%s|%s|",Proto,Name,Service) == false)
843 - return _error->Error("Unable to send port command");
845 + return _error->Error("EPRT failed, server said: %s",Msg.c_str());
850 bool FTPConn::Finalize()
852 // Passive mode? Do nothing
853 - if (PasvAddr.sin_port != 0)
857 // Close any old socket..
858 @@ -906,18 +1079,20 @@
860 int main(int argc,const char *argv[])
862 - /* See if we should become the http client - we do this for http
863 + /* See if we should be come the http client - we do this for http
865 if (getenv("ftp_proxy") != 0)
867 URI Proxy = string(getenv("ftp_proxy"));
869 + // Run the HTTP method
870 if (Proxy.Access == "http")
872 // Copy over the environment setting
874 snprintf(S,sizeof(S),"http_proxy=%s",getenv("ftp_proxy"));
876 + putenv("no_proxy=");
878 // Run the http method
879 string Path = flNotFile(argv[0]) + "/http";
880 diff -urN apt-0.3.19cnc52.org/methods/ftp.h apt-0.3.19cnc52/methods/ftp.h
881 --- apt-0.3.19cnc52.org/methods/ftp.h Thu Sep 6 22:20:43 2001
882 +++ apt-0.3.19cnc52/methods/ftp.h Sat Sep 8 12:35:01 2001
884 // -*- mode: cpp; mode: fold -*-
885 -// Description /*{{{*/// $Id$
886 +// Description /*{{{*/// $Id$
888 /* ######################################################################
890 FTP Aquire Method - This is the FTP aquire method for APT.
895 + bool ForceExtended;
899 - struct sockaddr_in PasvAddr;
900 - struct sockaddr_in Peer;
902 + struct addrinfo *PasvAddr;
904 + // Generic Peer Address
905 + struct sockaddr_storage PeerAddr;
906 + socklen_t PeerAddrLen;
908 + // Generic Server Address (us)
909 + struct sockaddr_storage ServerAddr;
910 + socklen_t ServerAddrLen;
912 // Private helper functions
913 bool ReadLine(string &Text);
916 bool Open(pkgAcqMethod *Owner);
922 bool Size(const char *Path,unsigned long &Size);
923 diff -urN apt-0.3.19cnc52.org/methods/http.cc apt-0.3.19cnc52/methods/http.cc
924 --- apt-0.3.19cnc52.org/methods/http.cc Thu Sep 6 22:20:43 2001
925 +++ apt-0.3.19cnc52/methods/http.cc Sat Sep 8 12:41:18 2001
927 // -*- mode: cpp; mode: fold -*-
928 // Description /*{{{*/
931 /* ######################################################################
933 HTTP Aquire Method - This is the HTTP aquire method for APT.
935 It uses HTTP/1.1 and many of the fancy options there-in, such as
936 - pipelining, range, if-range and so on. It accepts on the command line
937 - a list of url destination pairs and writes to stdout the status of the
938 - operation as defined in the APT method spec.
940 - It is based on a doubly buffered select loop. All the requests are
941 + pipelining, range, if-range and so on.
943 + It is based on a doubly buffered select loop. A groupe of requests are
944 fed into a single output buffer that is constantly fed out the
945 socket. This provides ideal pipelining as in many cases all of the
946 requests will fit into a single packet. The input socket is buffered
947 - the same way and fed into the fd for the file.
948 + the same way and fed into the fd for the file (may be a pipe in future).
950 This double buffering provides fairly substantial transfer rates,
951 compared to wget the http method is about 4% faster. Most importantly,
965 +using namespace std;
967 string HttpMethod::FailFile;
968 int HttpMethod::FailFd = -1;
970 unsigned long Sz = LeftRead();
971 if (OutQueue.length() - StrPos < Sz)
972 Sz = OutQueue.length() - StrPos;
973 - memcpy(Buf + (InP%Size),OutQueue.begin() + StrPos,Sz);
974 + memcpy(Buf + (InP%Size),OutQueue.c_str() + StrPos,Sz);
979 // ServerState::Open - Open a connection to the server /*{{{*/
980 // ---------------------------------------------------------------------
981 /* This opens a connection to the server. */
984 -struct addrinfo *LastHostAddr = 0;
985 bool ServerState::Open()
987 // Use the already open connection if possible.
995 // Determine the proxy setting
996 if (getenv("http_proxy") == 0)
998 @@ -289,32 +288,13 @@
1000 Proxy = getenv("http_proxy");
1002 - // Parse no_proxy, a , seperated list of domains
1003 + // Parse no_proxy, a , separated list of domains
1004 if (getenv("no_proxy") != 0)
1006 - const char *Start = getenv("no_proxy");
1007 - const char *ServerEnd = ServerName.Host.end();
1009 - for (const char *Cur = Start; true ; Cur++)
1011 - if (*Cur != ',' && *Cur != 0)
1014 - // match end of the string
1015 - if ((ServerName.Host.size() >= (Cur - Start))
1016 - && stringcasecmp(ServerEnd - (Cur - Start),
1017 - ServerEnd,Start,Cur) == 0)
1027 + if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
1032 // Determine what host and port to use based on the proxy settings
1035 @@ -380,14 +360,23 @@
1037 string::const_iterator J = I;
1038 for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
1039 - if (HeaderLine(string(I,J-I)) == false)
1040 + if (HeaderLine(string(I,J)) == false)
1045 + // 100 Continue is a Nop...
1046 + if (Result == 100)
1049 + // Tidy up the connection persistance state.
1050 + if (Encoding == Closes && HaveContent == true)
1051 + Persistent = false;
1055 while (Owner->Go(false,this) == true);
1062 string Tag = string(Line,0,Pos);
1063 string Val = string(Line,Pos2);
1065 - if (stringcasecmp(Tag.begin(),Tag.begin()+4,"HTTP") == 0)
1066 + if (stringcasecmp(Tag.c_str(),Tag.c_str()+4,"HTTP") == 0)
1068 // Evil servers return no version
1070 @@ -529,7 +518,19 @@
1071 if (sscanf(Line.c_str(),"HTTP %u %[^\n]",&Result,Code) != 2)
1072 return _error->Error("The http server sent an invalid reply header");
1076 + /* Check the HTTP response header to get the default persistance
1079 + Persistent = false;
1082 + if (Major == 1 && Minor <= 0)
1083 + Persistent = false;
1085 + Persistent = true;
1091 @@ -569,11 +570,19 @@
1094 if (stringcasecmp(Val,"chunked") == 0)
1095 - Encoding = Chunked;
1097 + Encoding = Chunked;
1101 + if (stringcasecmp(Tag,"Connection:") == 0)
1103 + if (stringcasecmp(Val,"close") == 0)
1104 + Persistent = false;
1105 + if (stringcasecmp(Val,"keep-alive") == 0)
1106 + Persistent = true;
1110 if (stringcasecmp(Tag,"Last-Modified:") == 0)
1112 if (StrToTime(Val,Date) == false)
1113 @@ -660,10 +669,11 @@
1114 Req += string("Proxy-Authorization: Basic ") +
1115 Base64Encode(Proxy.User + ":" + Proxy.Password) + "\r\n";
1118 - Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
1120 - Req += "User-Agent: Conectiva APT-HTTP/1.2\r\n\r\n";
1121 + if (Uri.User.empty() == false || Uri.Password.empty() == false)
1122 + Req += string("Authorization: Basic ") +
1123 + Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n";
1125 + Req += "User-Agent: PLD APT-HTTP/1.2\r\n\r\n";
1128 cerr << Req << endl;
1129 @@ -686,10 +696,12 @@
1134 - if (Srv->Out.WriteSpace() == true && Srv->ServerFd != -1)
1135 + /* Add the server. We only send more requests if the connection will
1137 + if (Srv->Out.WriteSpace() == true && Srv->ServerFd != -1
1138 + && Srv->Persistent == true)
1139 FD_SET(Srv->ServerFd,&wfds);
1140 - if (Srv->In.ReadSpace() == true && Srv->ServerFd != -1)
1141 + if (Srv->In.ReadSpace() == true && Srv->ServerFd != -1)
1142 FD_SET(Srv->ServerFd,&rfds);
1145 @@ -714,7 +726,11 @@
1148 if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0)
1150 + if (errno == EINTR)
1152 return _error->Errno("select","Select failed");
1157 @@ -1007,7 +1023,15 @@
1159 Server = new ServerState(Queue->Uri,this);
1163 + /* If the server has explicitly said this is the last connection
1164 + then we pre-emptively shut down the pipeline and tear down
1165 + the connection. This will speed up HTTP/1.0 servers a tad
1166 + since we don't have to wait for the close sequence to
1168 + if (Server->Persistent == false)
1171 // Reset the pipeline
1172 if (Server->ServerFd == -1)
1174 @@ -1035,6 +1059,7 @@
1176 _error->Error("Bad header Data");
1182 @@ -1053,6 +1078,7 @@
1190 @@ -1070,6 +1096,11 @@
1192 bool Result = Server->RunData();
1194 + /* If the server is sending back sizeless responses then fill in
1196 + if (Res.Size == 0)
1197 + Res.Size = File->Size();
1199 // Close the file, destroy the FD object and timestamp it
1202 @@ -1090,7 +1121,7 @@
1211 @@ -1112,6 +1143,7 @@
1219 diff -urN apt-0.3.19cnc52.org/methods/http.h apt-0.3.19cnc52/methods/http.h
1220 --- apt-0.3.19cnc52.org/methods/http.h Thu Sep 6 22:20:43 2001
1221 +++ apt-0.3.19cnc52/methods/http.h Sat Sep 8 12:42:54 2001
1223 // -*- mode: cpp; mode: fold -*-
1224 -// Description /*{{{*/// $Id$
1225 +// Description /*{{{*/// $Id$
1227 /* ######################################################################
1229 HTTP Aquire Method - This is the HTTP aquire method for APT.
1234 +#include <iostream>
1244 enum {Chunked,Stream,Closes} Encoding;
1245 enum {Header, Data} State;
1248 + // This is a Persistent attribute of the server itself.
1253 static void SigTerm(int);
1256 - friend ServerState;
1257 + friend class ServerState;
1260 ServerState *Server;
1261 diff -urN apt-0.3.19cnc52.org/methods/rfc2553emu.cc apt-0.3.19cnc52/methods/rfc2553emu.cc
1262 --- apt-0.3.19cnc52.org/methods/rfc2553emu.cc Thu Sep 6 22:20:43 2001
1263 +++ apt-0.3.19cnc52/methods/rfc2553emu.cc Tue Feb 20 08:03:18 2001
1265 // -*- mode: cpp; mode: fold -*-
1266 // Description /*{{{*/
1269 /* ######################################################################
1271 RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
1276 - Addr = gethostbyname(nodename);
1279 - if (h_errno == TRY_AGAIN)
1281 - if (h_errno == NO_RECOVERY)
1283 - return EAI_NONAME;
1287 - if (Addr->h_addr_list[0] == 0)
1288 - return EAI_NONAME;
1290 // Try to convert the service as a number
1291 Port = htons(strtol(servname,(char **)&End,0));
1292 Proto = SOCK_STREAM;
1294 hints->ai_socktype != 0)
1298 + // Hostname lookup, only if this is not a listening socket
1299 + if (hints != 0 && (hints->ai_flags & AI_PASSIVE) != AI_PASSIVE)
1301 + Addr = gethostbyname(nodename);
1304 + if (h_errno == TRY_AGAIN)
1306 + if (h_errno == NO_RECOVERY)
1308 + return EAI_NONAME;
1312 + if (Addr->h_addr_list[0] == 0)
1313 + return EAI_NONAME;
1315 + CurAddr = Addr->h_addr_list;
1318 + CurAddr = (char **)&End; // Fake!
1320 // Start constructing the linked list
1322 - for (CurAddr = Addr->h_addr_list; *CurAddr != 0; CurAddr++)
1323 + for (; *CurAddr != 0; CurAddr++)
1325 // New result structure
1326 *Result = (struct addrinfo *)calloc(sizeof(**Result),1);
1327 @@ -124,8 +132,15 @@
1329 ((struct sockaddr_in *)(*Result)->ai_addr)->sin_family = AF_INET;
1330 ((struct sockaddr_in *)(*Result)->ai_addr)->sin_port = Port;
1331 - ((struct sockaddr_in *)(*Result)->ai_addr)->sin_addr = *(in_addr *)(*CurAddr);
1334 + if (hints != 0 && (hints->ai_flags & AI_PASSIVE) != AI_PASSIVE)
1335 + ((struct sockaddr_in *)(*Result)->ai_addr)->sin_addr = *(in_addr *)(*CurAddr);
1338 + // Already zerod by calloc.
1342 Result = &(*Result)->ai_next;
1347 struct servent *Ent;
1348 if ((flags & NI_DATAGRAM) == NI_DATAGRAM)
1349 - Ent = getservbyport(sin->sin_port,"udp");
1350 + Ent = getservbyport(ntohs(sin->sin_port),"udp");
1352 - Ent = getservbyport(sin->sin_port,"tcp");
1353 + Ent = getservbyport(ntohs(sin->sin_port),"tcp");
1356 strncpy(serv,Ent->s_name,servlen);
1358 // Resolve as a plain numberic
1359 if ((flags & NI_NUMERICSERV) == NI_NUMERICSERV)
1361 - snprintf(serv,servlen,"%u",sin->sin_port);
1362 + snprintf(serv,servlen,"%u",ntohs(sin->sin_port));
1366 diff -urN apt-0.3.19cnc52.org/methods/rfc2553emu.h apt-0.3.19cnc52/methods/rfc2553emu.h
1367 --- apt-0.3.19cnc52.org/methods/rfc2553emu.h Thu Sep 6 22:20:43 2001
1368 +++ apt-0.3.19cnc52/methods/rfc2553emu.h Sun Jun 18 08:04:45 2000
1370 // -*- mode: cpp; mode: fold -*-
1371 // Description /*{{{*/
1374 /* ######################################################################
1376 RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
1378 #define EAI_MEMORY -11
1381 + /* If we don't have getaddrinfo then we probably don't have
1382 + sockaddr_storage either (same RFC) so we definately will not be
1383 + doing any IPv6 stuff. Do not use the members of this structure to
1384 + retain portability, cast to a sockaddr. */
1385 + #define sockaddr_storage sockaddr_in
1388 // getnameinfo support (glibc2.0 has getaddrinfo only)
1390 #define NI_DATAGRAM (1<<4)
1393 + #define sockaddr_storage sockaddr_in
1396 +// Glibc 2.0.7 misses this one
1397 +#ifndef AI_NUMERICHOST
1398 +#define AI_NUMERICHOST 0