X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/934b6582b4518630a050c8b84853b8e78ed87905..2b0660b537581e9e65180e4cf1a94d763fd66847:/methods/rfc2553emu.cc diff --git a/methods/rfc2553emu.cc b/methods/rfc2553emu.cc index 66fe781fb..372882769 100644 --- a/methods/rfc2553emu.cc +++ b/methods/rfc2553emu.cc @@ -1,47 +1,43 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: rfc2553emu.cc,v 1.1 1999/05/25 05:56:24 jgg Exp $ +// $Id: rfc2553emu.cc,v 1.8 2001/02/20 07:03:18 jgg Exp $ /* ###################################################################### RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo, freeaddrinfo and getnameinfo + + This is really C code, it just has a .cc extensions to play nicer with + the rest of APT. Originally written by Jason Gunthorpe and placed into the Public Domain, do with it what you will. - + ##################################################################### */ /*}}}*/ -#include "rfc2553emu.h" +#include + #include #include -#include +#include +#include +#include +#include "rfc2553emu.h" #ifndef HAVE_GETADDRINFO +// getaddrinfo - Resolve a hostname /*{{{*/ +// --------------------------------------------------------------------- +/* */ int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { - struct addrinfo **Result; + struct addrinfo **Result = res; 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; @@ -50,7 +46,7 @@ int getaddrinfo(const char *nodename, const char *servname, Proto = hints->ai_socktype; // Not a number, must be a name. - if (End != servname + strlen(End)) + if (End != servname + strlen(servname)) { struct servent *Srv = 0; @@ -78,10 +74,32 @@ int getaddrinfo(const char *nodename, const char *servname, 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); @@ -116,24 +134,112 @@ int getaddrinfo(const char *nodename, const char *servname, // 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; } return 0; } - + /*}}}*/ +// freeaddrinfo - Free the result of getaddrinfo /*{{{*/ +// --------------------------------------------------------------------- +/* */ 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 + +#ifndef HAVE_GETNAMEINFO +// getnameinfo - Convert a sockaddr to a string /*{{{*/ +// --------------------------------------------------------------------- +/* */ +int getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + // This routine only supports internet addresses + if (sa->sa_family != AF_INET) + return EAI_ADDRFAMILY; + + if (host != 0) + { + // Try to resolve the hostname + if ((flags & NI_NUMERICHOST) != NI_NUMERICHOST) + { + struct hostent *Ent = gethostbyaddr((char *)&sin->sin_addr,sizeof(sin->sin_addr), + AF_INET); + if (Ent != 0) + strncpy(host,Ent->h_name,hostlen); + else + { + if ((flags & NI_NAMEREQD) == NI_NAMEREQD) + { + if (h_errno == TRY_AGAIN) + return EAI_AGAIN; + if (h_errno == NO_RECOVERY) + return EAI_FAIL; + return EAI_NONAME; + } + + flags |= NI_NUMERICHOST; + } + } + + // Resolve as a plain numberic + if ((flags & NI_NUMERICHOST) == NI_NUMERICHOST) + { + strncpy(host,inet_ntoa(sin->sin_addr),hostlen); + } + } + + if (serv != 0) + { + // Try to resolve the hostname + if ((flags & NI_NUMERICSERV) != NI_NUMERICSERV) + { + struct servent *Ent; + if ((flags & NI_DATAGRAM) == NI_DATAGRAM) + Ent = getservbyport(ntohs(sin->sin_port),"udp"); + else + Ent = getservbyport(ntohs(sin->sin_port),"tcp"); + + if (Ent != 0) + strncpy(serv,Ent->s_name,servlen); + else + { + if ((flags & NI_NAMEREQD) == NI_NAMEREQD) + return EAI_NONAME; + + flags |= NI_NUMERICSERV; + } + } + + // Resolve as a plain numberic + if ((flags & NI_NUMERICSERV) == NI_NUMERICSERV) + { + snprintf(serv,servlen,"%u",ntohs(sin->sin_port)); + } + } + + return 0; +} + /*}}}*/ +#endif // HAVE_GETNAMEINFO