00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <sys/un.h>
00026 #include <netinet/in.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <errno.h>
00030 #include <unistd.h>
00031 #include <arpa/inet.h>
00032 
00033 #include <qglobal.h>
00034 
00035 
00036 
00037 
00038 #include <netdb.h>
00039 
00040 #include "config.h"
00041 #include "kdebug.h"
00042 #include "klocale.h"
00043 
00044 #ifndef IN6_IS_ADDR_V4MAPPED
00045 #define NEED_IN6_TESTS
00046 #endif
00047 #undef CLOBBER_IN6
00048 #include "netsupp.h"
00049 
00050 #if defined(__hpux) || defined(_HPUX_SOURCE)
00051 extern int h_errno;
00052 #endif
00053 
00054 #if !defined(kde_sockaddr_in6)
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 # define sockaddr_in6   kde_sockaddr_in6
00063 # define in6_addr   kde_in6_addr
00064 #endif
00065 
00066 #ifdef offsetof
00067 #undef offsetof
00068 #endif
00069 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
00070 
00071 
00072 
00073 
00074 
00075 
00076 #define KRF_KNOWS_AF_INET6      0x01    
00077 #define KRF_USING_OWN_GETADDRINFO   0x02    
00078 #define KRF_USING_OWN_INET_NTOP     0x04    
00079 #define KRF_USING_OWN_INET_PTON     0x08    
00080 #define KRF_CAN_RESOLVE_UNIX        0x100   
00081 #define KRF_CAN_RESOLVE_IPV4        0x200   
00082 #define KRF_CAN_RESOLVE_IPV6        0x400   
00083 
00084 
00085 static void dofreeaddrinfo(struct addrinfo *ai)
00086 {
00087   while (ai)
00088     {
00089       struct addrinfo *ai2 = ai;
00090       if (ai->ai_canonname != NULL)
00091     free(ai->ai_canonname);
00092 
00093       if (ai->ai_addr != NULL)
00094     free(ai->ai_addr);
00095 
00096       ai = ai->ai_next;
00097       free(ai2);
00098     }
00099 }
00100 
00101 void kde_freeaddrinfo(struct kde_addrinfo *ai)
00102 {
00103   if (ai->origin == KAI_LOCALUNIX)
00104     {
00105       struct addrinfo *p, *last = NULL;
00106       
00107 
00108       for (p = ai->data; p; p = p->ai_next)
00109     {
00110       if (p->ai_family == AF_UNIX)
00111         {
00112           if (last)
00113         {
00114           last->ai_next = NULL;
00115           freeaddrinfo(ai->data);
00116         }
00117           dofreeaddrinfo(p);
00118           break;
00119         }
00120       last = p;
00121     }
00122     }
00123   else
00124     freeaddrinfo(ai->data);
00125 
00126   free(ai);
00127 }
00128 
00129 static struct addrinfo*
00130 make_unix(const char *name, const char *serv)
00131 {
00132   const char *buf;
00133   struct addrinfo *p;
00134   struct sockaddr_un *_sun;
00135   int len;
00136 
00137   p = (addrinfo*)malloc(sizeof(*p));
00138   if (p == NULL)
00139     return NULL;
00140   memset(p, 0, sizeof(*p));
00141 
00142   if (name != NULL)
00143     buf = name;
00144   else
00145     buf = serv;
00146 
00147   
00148   len = strlen(buf) + offsetof(struct sockaddr_un, sun_path) + 1;
00149   if (*buf != '/')
00150     len += 5;           
00151 
00152   _sun = (sockaddr_un*)malloc(len);
00153   if (_sun == NULL)
00154     {
00155       
00156       free(p);
00157       return NULL;
00158     }
00159 
00160   _sun->sun_family = AF_UNIX;
00161 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00162   _sun->sun_len = len;
00163 # endif
00164   if (*buf == '/')
00165     *_sun->sun_path = '\0'; 
00166   else
00167     strcpy(_sun->sun_path, "/tmp/");
00168   strcat(_sun->sun_path, buf);
00169 
00170   
00171   p->ai_family = AF_UNIX;
00172   p->ai_addrlen = len;
00173   p->ai_addr = (sockaddr*)_sun;
00174   p->ai_canonname = strdup(buf);
00175 
00176   return p;
00177 }
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 #if KDE_IPV6_LOOKUP_MODE == 1
00186 static int check_ipv6_stack()
00187 {
00188 # ifndef AF_INET6
00189   return 2;         
00190 # else
00191   int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
00192   if (fd == -1)
00193      return 2;
00194      
00195   ::close(fd);
00196   return 1;
00197 # endif
00198 }
00199 #endif
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 int kde_getaddrinfo(const char *name, const char *service,
00229             const struct addrinfo* hint,
00230             struct kde_addrinfo** result)
00231 {
00232   struct kde_addrinfo* res;
00233   struct addrinfo* p;
00234   int err = EAI_SERVICE;
00235 #if KDE_IPV6_LOOKUP_MODE == 1
00236   
00237   static int ipv6_stack = 0;    
00238 #endif
00239 
00240   
00241   res = (kde_addrinfo*)malloc(sizeof(*res));
00242   if (res == NULL)
00243     return EAI_MEMORY;
00244   res->data = NULL;
00245   res->origin = KAI_SYSTEM; 
00246 
00247   struct addrinfo* last = NULL;
00248   
00249   
00250   if (hint && (hint->ai_family == PF_UNIX))
00251   {
00252      if (service == NULL || *service == '\0')
00253        goto out;        
00254 
00255      
00256      
00257      
00258      if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
00259         strcmp("localhost", name) == 0))
00260        goto out;        
00261 
00262      goto do_unix;
00263   }
00264   
00265 #if KDE_IPV6_LOOKUP_MODE != 0
00266 # if KDE_IPV6_LOOKUP_MODE == 1
00267   
00268   if (ipv6_stack == 0)
00269     ipv6_stack = check_ipv6_stack();
00270 
00271   if (ipv6_stack == 2)
00272     {
00273 # endif
00274       
00275       
00276       struct addrinfo our_hint;
00277       if (hint != NULL)
00278     {
00279       memcpy(&our_hint, hint, sizeof(our_hint));
00280       if (our_hint.ai_family == AF_UNSPEC)
00281         our_hint.ai_family = AF_INET;
00282     }
00283       else
00284     {
00285       memset(&our_hint, 0, sizeof(our_hint));
00286       our_hint.ai_family = AF_INET;
00287     }
00288 
00289       
00290       err = getaddrinfo(name, service, &our_hint, &res->data);
00291 # if KDE_IPV6_LOOKUP_MODE == 1
00292     }
00293   else
00294 # endif
00295 #endif
00296 #if KDE_IPV6_LOOKUP_MODE != 2
00297       
00298       err = getaddrinfo(name, service, hint, &res->data);
00299 #endif
00300 
00301   
00302 
00303   if (service == NULL || *service == '\0')
00304     goto out;           
00305 
00306   
00307   
00308   
00309   if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
00310             strcmp("localhost", name) == 0))
00311     goto out;           
00312 
00313   
00314   
00315   if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
00316     goto out;           
00317 
00318   
00319   
00320   
00321   
00322   if (err == 0)
00323     for (p = res->data; p; p = p->ai_next)
00324       {
00325     last = p;           
00326     if (p->ai_family == AF_UNIX)
00327       
00328       goto out;
00329       }
00330 
00331  do_unix:
00332   
00333   p = make_unix(NULL, service);
00334   if (p == NULL)
00335     {
00336       err = EAI_MEMORY;
00337       goto out;
00338     }
00339   if (hint != NULL)
00340     p->ai_socktype = hint->ai_socktype;
00341   if (p->ai_socktype == 0)
00342     p->ai_socktype = SOCK_STREAM; 
00343 
00344   if (last)
00345     last->ai_next = p;
00346   else
00347     res->data = p;
00348   res->origin = KAI_LOCALUNIX;
00349   *result = res;
00350   return 0;
00351 
00352  out:
00353   
00354   if (err == 0)
00355     *result = res;
00356   else
00357     {
00358       if (res->data != NULL)
00359     freeaddrinfo(res->data);
00360       free(res);
00361     }
00362   return err;
00363 }
00364 
00365 #if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
00366 
00367 #define KRF_getaddrinfo     0
00368 #define KRF_resolver        0
00369 
00370 #else  // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
00371 
00372 #define KRF_getaddrinfo         KRF_USING_OWN_GETADDRINFO
00373 #define KRF_resolver            KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
00374 
00375 
00376 
00377 
00378 
00379 
00383 static int inet_lookup(const char *name, int portnum, int protonum,
00384                struct addrinfo *p, const struct addrinfo *hint,
00385                struct addrinfo** result)
00386 {
00387   struct addrinfo *q;
00388   struct hostent *h;
00389   struct sockaddr **psa = NULL;
00390   int len;
00391 
00392   
00393   
00394 # ifdef AF_INET6
00395   if (hint->ai_family == AF_INET6)
00396     {
00397       if (p != NULL)
00398     {
00399       *result = p;
00400       return 0;
00401     }
00402       return EAI_FAIL;
00403     }
00404 # endif
00405 
00406   q = (addrinfo*)malloc(sizeof(*q));
00407   if (q == NULL)
00408     {
00409       freeaddrinfo(p);
00410       return EAI_MEMORY;
00411     }
00412 
00413   h = gethostbyname(name);
00414   if (h == NULL)
00415     {
00416       if (p != NULL)
00417     {
00418       
00419       *result = p;
00420       return 0;
00421     }
00422 
00423       switch (h_errno)
00424     {
00425     case HOST_NOT_FOUND:
00426       return EAI_NONAME;
00427     case TRY_AGAIN:
00428       return EAI_AGAIN;
00429     case NO_RECOVERY:
00430       return EAI_FAIL;
00431     case NO_ADDRESS:
00432       return EAI_NODATA;
00433     default:
00434       
00435       return EAI_FAIL;
00436     }
00437     }
00438 
00439   
00440   if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
00441     len = sizeof(struct sockaddr_in);
00442 # ifdef AF_INET6
00443   else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
00444                      hint->ai_family == AF_UNSPEC))
00445     len = sizeof(struct sockaddr_in6);
00446 # endif
00447   else
00448     {
00449       
00450       
00451       if (p != NULL)
00452     {
00453       *result = p;
00454       return 0;
00455     }
00456       return EAI_NODATA;
00457     }
00458 
00459   q->ai_flags = 0;
00460   q->ai_family = h->h_addrtype;
00461   q->ai_socktype = hint->ai_socktype;
00462   q->ai_protocol = protonum;
00463   q->ai_addrlen = len;
00464 
00465   q->ai_addr = (sockaddr*)malloc(len);
00466   if (q->ai_addr == NULL)
00467     {
00468       free(q);
00469       freeaddrinfo(p);
00470       return EAI_MEMORY;
00471     }
00472   if (h->h_addrtype == AF_INET)
00473     {
00474       struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00475       sin->sin_family = AF_INET;
00476 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00477       sin->sin_len = sizeof(*sin);
00478 # endif
00479       sin->sin_port = portnum;
00480       memcpy(&sin->sin_addr, h->h_addr, h->h_length);
00481     }
00482 # ifdef AF_INET6
00483   else if (h->h_addrtype == AF_INET6)
00484     {
00485       struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00486       sin6->sin6_family = AF_INET6;
00487 #  ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00488       sin6->sin6_len = sizeof(*sin6);
00489 #  endif
00490       sin6->sin6_port = portnum;
00491       sin6->sin6_flowinfo = 0;
00492       memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
00493       sin6->sin6_scope_id = 0;
00494     }
00495 # endif
00496 
00497   if (hint->ai_flags & AI_CANONNAME)
00498     q->ai_canonname = strdup(h->h_name);
00499   else
00500     q->ai_canonname = NULL;
00501 
00502   q->ai_next = p;
00503   p = q;
00504 
00505   
00506   for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
00507     {
00508       q = (addrinfo*)malloc(sizeof(*q));
00509       if (q == NULL)
00510     {
00511       freeaddrinfo(p);
00512       return EAI_MEMORY;
00513     }
00514       memcpy(q, p, sizeof(*q));
00515 
00516       q->ai_addr = (sockaddr*)malloc(h->h_length);
00517       if (q->ai_addr == NULL)
00518     {
00519       freeaddrinfo(p);
00520       free(q);
00521       return EAI_MEMORY;
00522     }
00523       if (h->h_addrtype == AF_INET)
00524     {
00525       struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00526       sin->sin_family = AF_INET;
00527 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00528       sin->sin_len = sizeof(*sin);
00529 # endif
00530       sin->sin_port = portnum;
00531       memcpy(&sin->sin_addr, *psa, h->h_length);
00532     }
00533 # ifdef AF_INET6
00534       else if (h->h_addrtype == AF_INET6)
00535     {
00536       struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00537       sin6->sin6_family = AF_INET6;
00538 #  ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00539       sin6->sin6_len = sizeof(*sin6);
00540 #  endif
00541       sin6->sin6_port = portnum;
00542       sin6->sin6_flowinfo = 0;
00543       memcpy(&sin6->sin6_addr, *psa, h->h_length);
00544       sin6->sin6_scope_id = 0;
00545     }
00546 # endif
00547 
00548       if (q->ai_canonname != NULL)
00549     q->ai_canonname = strdup(q->ai_canonname);
00550 
00551       q->ai_next = p;
00552       p = q;
00553     }
00554 
00555   *result = p;
00556   return 0;         
00557 }
00558 
00559 static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p,
00560              const struct addrinfo *hint, struct addrinfo** result)
00561 {
00562   struct addrinfo *q;
00563 
00564   do
00565     {
00566       
00567 
00568       if (name != NULL)
00569     {
00570       
00571       
00572       struct sockaddr_in *sin;
00573       struct in_addr in;
00574 # ifdef AF_INET6
00575       struct sockaddr_in6 *sin6;
00576       struct in6_addr in6;
00577 
00578       if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
00579                           strchr(name, ':') != NULL))
00580         {
00581           
00582           if (inet_pton(AF_INET6, name, &in6) != 1)
00583         {
00584           if (hint->ai_flags & AI_NUMERICHOST)
00585             {
00586               freeaddrinfo(p);
00587               return EAI_FAIL;
00588             }
00589           break;    
00590         }
00591 
00592           sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
00593           if (sin6 == NULL)
00594         {
00595           freeaddrinfo(p);
00596           return EAI_MEMORY;
00597         }
00598           memcpy(&sin6->sin6_addr, &in6, sizeof(in6));
00599 
00600           if (strchr(name, '%') != NULL)
00601         {
00602           errno = 0;
00603           sin6->sin6_scope_id = strtoul(strchr(name, '%') + 1, NULL, 10);
00604           if (errno != 0)
00605             sin6->sin6_scope_id = 0; 
00606         }
00607 
00608           q = (addrinfo*)malloc(sizeof(*q));
00609           if (q == NULL)
00610         {
00611           freeaddrinfo(p);
00612           free(sin6);
00613           return EAI_MEMORY;
00614         }
00615 
00616           sin6->sin6_family = AF_INET6;
00617 #  ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00618           sin6->sin6_len = sizeof(*sin6);
00619 #  endif
00620           sin6->sin6_port = portnum;
00621           sin6->sin6_flowinfo = 0;
00622 
00623           q->ai_flags = 0;
00624           q->ai_family = AF_INET6;
00625           q->ai_socktype = hint->ai_socktype;
00626           q->ai_protocol = protonum;
00627           q->ai_addrlen = sizeof(*sin6);
00628           q->ai_canonname = NULL;
00629           q->ai_addr = (sockaddr*)sin6;
00630           q->ai_next = p;
00631 
00632           *result = q;
00633           return 0;     
00634         }
00635 # endif // AF_INET6
00636 
00637       if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00638         {
00639           
00640           if (inet_pton(AF_INET, name, &in) != 1)
00641         {
00642           if (hint->ai_flags & AI_NUMERICHOST)
00643             {
00644               freeaddrinfo(p);
00645               return EAI_FAIL;  
00646             }
00647           break;    
00648         }
00649 
00650           sin = (sockaddr_in*)malloc(sizeof(*sin));
00651           if (sin == NULL)
00652         {
00653           freeaddrinfo(p);
00654           return EAI_MEMORY;
00655         }
00656 
00657           q = (addrinfo*)malloc(sizeof(*q));
00658           if (q == NULL)
00659         {
00660           freeaddrinfo(p);
00661           free(sin);
00662           return EAI_MEMORY;
00663         }
00664 
00665           sin->sin_family = AF_INET;
00666 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00667           sin->sin_len = sizeof(*sin);
00668 # endif
00669           sin->sin_port = portnum;
00670           sin->sin_addr = in;
00671 
00672           q->ai_flags = 0;
00673           q->ai_family = AF_INET;
00674           q->ai_socktype = hint->ai_socktype;
00675           q->ai_protocol = protonum;
00676           q->ai_addrlen = sizeof(*sin);
00677           q->ai_canonname = NULL;
00678           q->ai_addr = (sockaddr*)sin;
00679           q->ai_next = p;
00680           *result = q;
00681           return 0;
00682         }
00683 
00684       
00685       
00686       kdError() << "I wasn't supposed to get here!";
00687     }
00688     } while (false);
00689 
00690   
00691   if (name == NULL)
00692     {
00693       struct sockaddr_in *sin = (sockaddr_in*)malloc(sizeof(*sin));
00694 # ifdef AF_INET6
00695       struct sockaddr_in6 *sin6;
00696 # endif
00697 
00698       if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00699     {
00700       if (sin == NULL)
00701         {
00702           free(sin);
00703           freeaddrinfo(p);
00704           return EAI_MEMORY;
00705         }
00706 
00707       
00708       q = (addrinfo*)malloc(sizeof(*q));
00709       if (q == NULL)
00710         {
00711           free(sin);
00712           freeaddrinfo(p);
00713           return EAI_MEMORY;
00714         }
00715 
00716       sin->sin_family = AF_INET;
00717 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00718       sin->sin_len = sizeof(*sin);
00719 # endif
00720       sin->sin_port = portnum;
00721       if (hint->ai_flags & AI_PASSIVE)
00722         *(Q_UINT32*)&sin->sin_addr = INADDR_ANY;
00723       else
00724         *(Q_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
00725       q->ai_flags = 0;
00726       q->ai_family = AF_INET;
00727       q->ai_socktype = hint->ai_socktype;
00728       q->ai_protocol = protonum;
00729       q->ai_addrlen = sizeof(*sin);
00730       q->ai_canonname = NULL;
00731       q->ai_addr = (sockaddr*)sin;
00732       q->ai_next = p;
00733       p = q;
00734     }
00735 
00736 # ifdef AF_INET6
00737       
00738 
00739       if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
00740     {
00741       sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
00742       q = (addrinfo*)malloc(sizeof(*q));
00743       if (q == NULL || sin6 == NULL)
00744         {
00745           free(sin6);
00746           free(q);
00747           freeaddrinfo(p);
00748           return EAI_MEMORY;
00749         }
00750 
00751       sin6->sin6_family = AF_INET6;
00752 #  ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00753       sin6->sin6_len = sizeof(*sin6);
00754 #  endif
00755       sin6->sin6_port = portnum;
00756       sin6->sin6_flowinfo = 0;
00757       sin6->sin6_scope_id = 0;
00758 
00759       
00760       memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
00761       if ((hint->ai_flags & AI_PASSIVE) == 0)
00762         ((char*)&sin6->sin6_addr)[15] = 1;
00763 
00764       q->ai_flags = 0;
00765       q->ai_family = AF_INET6;
00766       q->ai_socktype = hint->ai_socktype;
00767       q->ai_protocol = protonum;
00768       q->ai_addrlen = sizeof(*sin6);
00769       q->ai_canonname = NULL;
00770       q->ai_addr = (sockaddr*)sin6;
00771       q->ai_next = p;
00772       p = q;
00773     }
00774 
00775 # endif // AF_INET6
00776 
00777       *result = p;
00778       return 0;         
00779     }
00780 
00781   return inet_lookup(name, portnum, protonum, p, hint, result);
00782 }
00783 
00784 
00785 int getaddrinfo(const char *name, const char *serv,
00786         const struct addrinfo* hint,
00787         struct addrinfo** result)
00788 {
00789   unsigned short portnum;   
00790   int protonum = IPPROTO_TCP;
00791   const char *proto = "tcp";
00792   struct addrinfo *p = NULL;
00793 
00794   
00795   if (hint == NULL || result == NULL)
00796     return EAI_BADFLAGS;
00797   if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
00798       hint->ai_family != AF_INET
00799 # ifdef AF_INET6
00800       && hint->ai_family != AF_INET6
00801 # endif
00802       )
00803     return EAI_FAMILY;
00804   if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
00805       hint->ai_socktype != SOCK_DGRAM)
00806     return EAI_SOCKTYPE;
00807 
00808   
00809   if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0'))
00810     name = NULL;
00811   
00812   if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0'))
00813     serv = NULL;
00814 
00815   if (name == NULL && serv == NULL) 
00816     return EAI_NONAME;
00817 
00818   
00819   if (name != NULL && strcmp(name, "localhost") == 0)
00820      name = NULL;
00821 
00822   
00823   
00824   
00825   if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
00826     {
00827       if (name != NULL && serv != NULL)
00828     {
00829       
00830       if (hint->ai_family == AF_UNIX)
00831         return EAI_BADFLAGS;
00832     }
00833       else
00834     {
00835       p = make_unix(name, serv);
00836       if (p == NULL)
00837         return EAI_MEMORY;
00838 
00839       p->ai_socktype = hint->ai_socktype;
00840       
00841       
00842       if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') ||
00843                           (serv != NULL && *serv == '/')))
00844         {
00845           *result = p;
00846           return 0;     
00847         }
00848     }
00849     }
00850 
00851   
00852   if (serv != NULL)
00853     {
00854       char *tail;
00855       struct servent *sent;
00856 
00857       portnum = htons((unsigned)strtoul(serv, &tail, 10));
00858       if (*tail != '\0')
00859     {
00860       
00861       if (hint->ai_socktype == SOCK_DGRAM)
00862         {
00863           proto = "udp";
00864           protonum = IPPROTO_UDP;
00865         }
00866 
00867       sent = getservbyname(serv, proto);
00868       if (sent == NULL) 
00869         {
00870           if (p == NULL)
00871         return EAI_NONAME;
00872           else
00873         return 0;   
00874         }
00875 
00876       portnum = sent->s_port;
00877     }
00878     }
00879   else
00880     portnum = 0;        
00881 
00882   return make_inet(name, portnum, protonum, p, hint, result);
00883 }
00884 
00885 void freeaddrinfo(struct addrinfo *p)
00886 {
00887   dofreeaddrinfo(p);
00888 }
00889 
00890 char *gai_strerror(int errorcode)
00891 {
00892   static const char * const messages[] =
00893   {
00894     I18N_NOOP("no error"),  
00895     I18N_NOOP("address family for nodename not supported"), 
00896     I18N_NOOP("temporary failure in name resolution"),  
00897     I18N_NOOP("invalid value for 'ai_flags'"),  
00898     I18N_NOOP("non-recoverable failure in name resolution"), 
00899     I18N_NOOP("'ai_family' not supported"), 
00900     I18N_NOOP("memory allocation failure"), 
00901     I18N_NOOP("no address associated with nodename"),   
00902     I18N_NOOP("name or service not known"), 
00903     I18N_NOOP("servname not supported for ai_socktype"), 
00904     I18N_NOOP("'ai_socktype' not supported"),   
00905     I18N_NOOP("system error")           
00906   };
00907 
00908   if (errorcode > EAI_SYSTEM || errorcode < 0)
00909     return NULL;
00910 
00911   static char buffer[200];
00912   strcpy(buffer, i18n(messages[errorcode]).local8Bit());
00913   return buffer;
00914 }
00915 
00916 static void findport(unsigned short port, char *serv, size_t servlen, int flags)
00917 {
00918   if (serv == NULL)
00919     return;
00920 
00921   if ((flags & NI_NUMERICSERV) == 0)
00922     {
00923       struct servent *sent;
00924       sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
00925       if (sent != NULL && servlen > strlen(sent->s_name))
00926     {
00927       strcpy(serv, sent->s_name);
00928       return;
00929     }
00930     }
00931 
00932   snprintf(serv, servlen, "%u", ntohs(port));
00933 }
00934 
00935 int getnameinfo(const struct sockaddr *sa, ksocklen_t salen,
00936         char *host, size_t hostlen, char *serv, size_t servlen,
00937         int flags)
00938 {
00939   union
00940     {
00941       const sockaddr *sa;
00942       const sockaddr_un *_sun;
00943       const sockaddr_in *sin;
00944       const sockaddr_in6 *sin6;
00945   } s;
00946 
00947   if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
00948     return 1;
00949 
00950   s.sa = sa;
00951   if (s.sa->sa_family == AF_UNIX)
00952     {
00953       if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
00954     return 1;       
00955 
00956       if (servlen && serv != NULL)
00957     *serv = '\0';
00958       if (host != NULL && hostlen > strlen(s._sun->sun_path))
00959     strcpy(host, s._sun->sun_path);
00960 
00961       return 0;
00962     }
00963   else if (s.sa->sa_family == AF_INET)
00964     {
00965       if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
00966     return 1;       
00967 
00968       if (flags & NI_NUMERICHOST)
00969     inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00970       else
00971     {
00972       
00973       struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00974                         AF_INET);
00975       if (h == NULL && flags & NI_NAMEREQD)
00976         return 1;
00977       else if (h == NULL)
00978         inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00979       else if (host != NULL && hostlen > strlen(h->h_name))
00980         strcpy(host, h->h_name);
00981       else
00982         return 1;       
00983     }
00984 
00985       findport(s.sin->sin_port, serv, servlen, flags);
00986     }
00987 # ifdef AF_INET6
00988   else if (s.sa->sa_family == AF_INET6)
00989     {
00990       if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
00991     return 1;       
00992 
00993       if (flags & NI_NUMERICHOST)
00994     inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
00995       else
00996     {
00997       
00998       struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00999                         AF_INET6);
01000       if (h == NULL && flags & NI_NAMEREQD)
01001         return 1;
01002       else if (h == NULL)
01003         inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01004       else if (host != NULL && hostlen > strlen(h->h_name))
01005         strcpy(host, h->h_name);
01006       else
01007         return 1;       
01008     }
01009 
01010       findport(s.sin6->sin6_port, serv, servlen, flags);
01011     }
01012 # endif // AF_INET6
01013 
01014   return 1;         
01015 }
01016 
01017 #endif // HAVE_GETADDRINFO
01018 
01019 #ifndef HAVE_INET_NTOP
01020 
01021 #define KRF_inet_ntop   KRF_USING_OWN_INET_NTOP
01022 
01023 static void add_dwords(char *buf, Q_UINT16 *dw, int count)
01024 {
01025   int i = 1;
01026   sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
01027   while (--count)
01028     sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
01029 }
01030 
01031 const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
01032 {
01033   char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
01034   Q_UINT8 *data = (Q_UINT8*)cp;
01035 
01036   if (af == AF_INET)
01037     {
01038       sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
01039 
01040       if (len > strlen(buf2))
01041     {
01042       strcpy(buf, buf2);
01043       return buf;
01044     }
01045 
01046       errno = ENOSPC;
01047       return NULL;      
01048     }
01049 
01050 # ifdef AF_INET6
01051   if (af == AF_INET6)
01052     {
01053       Q_UINT16 *p = (Q_UINT16*)data;
01054       Q_UINT16 *longest = NULL, *cur = NULL;
01055       int longest_length = 0, cur_length;
01056       int i;
01057 
01058       if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
01059     sprintf(buf2, "::%s%u.%u.%u.%u",
01060         KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
01061         buf[12], buf[13], buf[14], buf[15]);
01062       else
01063     {
01064       
01065       for (i = 0; i < 8; i++)
01066         if (cur == NULL && p[i] == 0)
01067           {
01068         
01069         cur = p + i;
01070         cur_length = 1;
01071           }
01072         else if (cur != NULL && p[i] == 0)
01073           
01074           cur_length++;
01075         else if (cur != NULL && p[i] != 0)
01076           {
01077         
01078         if (cur_length > longest_length)
01079           {
01080             longest_length = cur_length;
01081             longest = cur;
01082           }
01083         cur = NULL;     
01084           }
01085       if (cur != NULL && cur_length > longest_length)
01086         {
01087           longest_length = cur_length;
01088           longest = cur;
01089         }
01090 
01091       if (longest_length > 1)
01092         {
01093           
01094           buf2[0] = '\0';
01095           if (longest != p)
01096         add_dwords(buf2, p, longest - p);
01097           strcat(buf2, "::");
01098           if (longest + longest_length < p + 8)
01099         add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
01100         }
01101       else
01102         {
01103           
01104           buf2[0] = '\0';
01105           add_dwords(buf2, p, 8);
01106         }
01107     }
01108 
01109       if (strlen(buf2) < len)
01110     {
01111       strcpy(buf, buf2);
01112       return buf;
01113     }
01114 
01115       errno = ENOSPC;
01116       return NULL;
01117     }
01118 # endif
01119 
01120   errno = EAFNOSUPPORT;
01121   return NULL;          
01122 }
01123 
01124 #else   // HAVE_INET_NTOP
01125 
01126 #define KRF_inet_ntop       0
01127 
01128 #endif  // HAVE_INET_NTOP
01129 
01130 #ifndef HAVE_INET_PTON
01131 
01132 #define KRF_inet_pton       KRF_USING_OWN_INET_PTON
01133 int inet_pton(int af, const char *cp, void *buf)
01134 {
01135   if (af == AF_INET)
01136     {
01137       
01138       unsigned p[4];
01139       unsigned char *q = (unsigned char*)buf;
01140       if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
01141     return 0;
01142 
01143       if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
01144     return 0;
01145 
01146       q[0] = p[0];
01147       q[1] = p[1];
01148       q[2] = p[2];
01149       q[3] = p[3];
01150 
01151       return 1;
01152     }
01153 
01154 # ifdef AF_INET6
01155   else if (af == AF_INET6)
01156     {
01157       Q_UINT16 addr[8];
01158       const char *p = cp;
01159       int n = 0, start = 8;
01160       bool has_v4 = strchr(p, '.') != NULL;
01161 
01162       memset(addr, 0, sizeof(addr));
01163 
01164       if (*p == '\0' || p[1] == '\0')
01165     return 0;       
01166 
01167       if (*p == ':' && p[1] == ':')
01168     {
01169       start = 0;
01170       p += 2;
01171     }
01172       while (*p)
01173     {
01174       if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
01175         {
01176           
01177           addr[n] = ntohs(addr[n]);
01178           n++;
01179           addr[n] = ntohs(addr[n]);
01180           n++;
01181           break;
01182         }
01183       if (sscanf(p, "%hx", addr + n++) != 1)
01184         return 0;
01185 
01186       while (*p && *p != ':')
01187         p++;
01188       if (!*p)
01189         break;
01190       p++;
01191 
01192       if (*p == ':')    
01193         {
01194           if (start != 8)
01195         return 0;   
01196           start = n;
01197           p++;
01198         }
01199     }
01200 
01201       
01202       
01203       
01204       
01205       if (start == 8 && n != 8)
01206     return 0;       
01207       memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(Q_UINT16));
01208       memset(addr + start, 0, (8 - n) * sizeof(Q_UINT16));
01209 
01210       
01211       
01212       if (htons(0x1234) != 0x1234)
01213     for (n = 0; n < 8; n++)
01214       addr[n] = htons(addr[n]);
01215 
01216       memcpy(buf, addr, sizeof(addr));
01217       return 1;
01218     }
01219 # endif
01220 
01221   errno = EAFNOSUPPORT;
01222   return -1;            
01223 }
01224 
01225 #else  // HAVE_INET_PTON
01226 
01227 #define KRF_inet_pton       0
01228 
01229 #endif // HAVE_INET_PTON
01230 
01231 #ifdef AF_INET6
01232 # define KRF_afinet6    KRF_KNOWS_AF_INET6
01233 #else
01234 # define KRF_afinet6    0
01235 #endif
01236 
01237 namespace KDE
01238 {
01240   extern const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01241 }