Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

getaddrinfo.c

00001 /*****************************************************************************
00002  * getaddrinfo.c: getaddrinfo/getnameinfo replacement functions
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * Copyright (C) 2002-2004 Rémi Denis-Courmont
00006  * $Id: getaddrinfo.c 12850 2005-10-16 14:42:15Z courmisch $
00007  *
00008  * Author: Rémi Denis-Courmont <rem # videolan.org>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 #include <vlc/vlc.h>
00026 
00027 #include <stddef.h> /* size_t */
00028 #include <string.h> /* strncpy(), strlen(), memcpy(), memset(), strchr() */
00029 #include <stdlib.h> /* malloc(), free(), strtoul() */
00030 #include <errno.h>
00031 
00032 #ifdef HAVE_SYS_TYPES_H
00033 #   include <sys/types.h>
00034 #endif
00035 #ifdef HAVE_ARPA_INET_H
00036 #   include <arpa/inet.h>
00037 #endif
00038 #ifdef HAVE_NETINET_IN_H
00039 #   include <netinet/in.h>
00040 #endif
00041 #ifdef HAVE_UNISTD_H
00042 #   include <unistd.h>
00043 #endif
00044 
00045 #include "network.h"
00046 
00047 #ifndef NO_ADDRESS
00048 #   define NO_ADDRESS  NO_DATA
00049 #endif
00050 #ifndef INADDR_NONE
00051 #   define INADDR_NONE 0xFFFFFFFF
00052 #endif
00053 #ifndef AF_UNSPEC
00054 #   define AF_UNSPEC   0
00055 #endif
00056 
00057 #define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\
00058                   NI_DGRAM)
00059 #define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
00060 
00061 
00062 #ifndef HAVE_GAI_STRERROR
00063 static struct
00064 {
00065     int code;
00066     const char *msg;
00067 } const __gai_errlist[] =
00068 {
00069     { 0,              "Error 0" },
00070     { EAI_BADFLAGS,   "Invalid flag used" },
00071     { EAI_NONAME,     "Host or service not found" },
00072     { EAI_AGAIN,      "Temporary name service failure" },
00073     { EAI_FAIL,       "Non-recoverable name service failure" },
00074     { EAI_NODATA,     "No data for host name" },
00075     { EAI_FAMILY,     "Unsupported address family" },
00076     { EAI_SOCKTYPE,   "Unsupported socket type" },
00077     { EAI_SERVICE,    "Incompatible service for socket type" },
00078     { EAI_ADDRFAMILY, "Unavailable address family for host name" },
00079     { EAI_MEMORY,     "Memory allocation failure" },
00080     { EAI_SYSTEM,     "System error" },
00081     { 0,              NULL }
00082 };
00083 
00084 static const char *__gai_unknownerr = "Unrecognized error number";
00085 
00086 /****************************************************************************
00087  * Converts an EAI_* error code into human readable english text.
00088  ****************************************************************************/
00089 const char *vlc_gai_strerror( int errnum )
00090 {
00091     int i;
00092 
00093     for (i = 0; __gai_errlist[i].msg != NULL; i++)
00094         if (errnum == __gai_errlist[i].code)
00095             return __gai_errlist[i].msg;
00096 
00097     return __gai_unknownerr;
00098 }
00099 # undef _EAI_POSITIVE_MAX
00100 #else /* ifndef HAVE_GAI_STRERROR */
00101 const char *vlc_gai_strerror( int errnum )
00102 {
00103     return gai_strerror( errnum );
00104 }
00105 #endif
00106 
00107 #if !(defined (HAVE_GETNAMEINFO) && defined (HAVE_GETADDRINFO))
00108 /*
00109  * Converts the current herrno error value into an EAI_* error code.
00110  * That error code is normally returned by getnameinfo() or getaddrinfo().
00111  */
00112 static int
00113 gai_error_from_herrno( void )
00114 {
00115     switch(h_errno)
00116     {
00117         case HOST_NOT_FOUND:
00118             return EAI_NONAME;
00119 
00120         case NO_ADDRESS:
00121 # if (NO_ADDRESS != NO_DATA)
00122         case NO_DATA:
00123 # endif
00124             return EAI_NODATA;
00125 
00126         case NO_RECOVERY:
00127             return EAI_FAIL;
00128 
00129         case TRY_AGAIN:
00130             return EAI_AGAIN;
00131     }
00132     return EAI_SYSTEM;
00133 }
00134 #endif /* if !(HAVE_GETNAMEINFO && HAVE_GETADDRINFO) */
00135 
00136 #ifndef HAVE_GETNAMEINFO
00137 /*
00138  * getnameinfo() non-thread-safe IPv4-only implementation,
00139  * Address-family-independant address to hostname translation
00140  * (reverse DNS lookup in case of IPv4).
00141  *
00142  * This is meant for use on old IP-enabled systems that are not IPv6-aware,
00143  * and probably do not have getnameinfo(), but have the old gethostbyaddr()
00144  * function.
00145  *
00146  * GNU C library 2.0.x is known to lack this function, even though it defines
00147  * getaddrinfo().
00148  */
00149 static int
00150 __getnameinfo( const struct sockaddr *sa, socklen_t salen,
00151                char *host, int hostlen, char *serv, int servlen, int flags )
00152 {
00153     if (((unsigned)salen < sizeof (struct sockaddr_in))
00154      || (sa->sa_family != AF_INET))
00155         return EAI_FAMILY;
00156     else if (flags & (~_NI_MASK))
00157         return EAI_BADFLAGS;
00158     else
00159     {
00160         const struct sockaddr_in *addr;
00161 
00162         addr = (const struct sockaddr_in *)sa;
00163 
00164         if (host != NULL)
00165         {
00166             int solved = 0;
00167 
00168             /* host name resolution */
00169             if (!(flags & NI_NUMERICHOST))
00170             {
00171                 struct hostent *hent;
00172 
00173                 hent = gethostbyaddr ((const void*)&addr->sin_addr,
00174                                       4, AF_INET);
00175 
00176                 if (hent != NULL)
00177                 {
00178                     strncpy (host, hent->h_name, hostlen);
00179                     host[hostlen - 1] = '\0';
00180 
00181                     /*
00182                      * only keep first part of hostname
00183                      * if user don't want fully qualified
00184                      * domain name
00185                      */
00186                     if (flags & NI_NOFQDN)
00187                     {
00188                         char *ptr;
00189 
00190                         ptr = strchr (host, '.');
00191                         if (ptr != NULL)
00192                             *ptr = 0;
00193                     }
00194 
00195                     solved = 1;
00196                 }
00197                 else if (flags & NI_NAMEREQD)
00198                     return gai_error_from_herrno ();
00199             }
00200 
00201             if (!solved)
00202             {
00203                 /* inet_ntoa() can't fail */
00204                 strncpy (host, inet_ntoa (addr->sin_addr), hostlen);
00205                 host[hostlen - 1] = '\0';
00206             }
00207         }
00208 
00209         if (serv != NULL)
00210         {
00211             struct servent *sent = NULL;
00212 
00213 #ifndef SYS_BEOS /* No getservbyport() */
00214             int solved = 0;
00215 
00216             /* service name resolution */
00217             if (!(flags & NI_NUMERICSERV))
00218             {
00219 
00220                 sent = getservbyport(addr->sin_port,
00221                                      (flags & NI_DGRAM)
00222                                      ? "udp" : "tcp");
00223                 if (sent != NULL)
00224                 {
00225                     strncpy (serv, sent->s_name, servlen);
00226                     serv[servlen - 1] = 0;
00227                     solved = 1;
00228                 }
00229             }
00230 #else
00231             sent = NULL;
00232 #endif
00233             if (sent == NULL)
00234             {
00235                 snprintf (serv, servlen, "%u",
00236                           (unsigned int)ntohs (addr->sin_port));
00237                 serv[servlen - 1] = '\0';
00238             }
00239         }
00240     }
00241     return 0;
00242 }
00243 
00244 #endif /* if !HAVE_GETNAMEINFO */
00245 
00246 
00247 #ifndef HAVE_GETADDRINFO
00248 /*
00249  * This functions must be used to free the memory allocated by getaddrinfo().
00250  */
00251 static void
00252 __freeaddrinfo (struct addrinfo *res)
00253 {
00254     if (res != NULL)
00255     {
00256         if (res->ai_canonname != NULL)
00257             free (res->ai_canonname);
00258         if (res->ai_addr != NULL)
00259             free (res->ai_addr);
00260         if (res->ai_next != NULL)
00261             free (res->ai_next);
00262         free (res);
00263     }
00264 }
00265 
00266 
00267 /*
00268  * Internal function that builds an addrinfo struct.
00269  */
00270 static struct addrinfo *
00271 makeaddrinfo (int af, int type, int proto,
00272               const struct sockaddr *addr, size_t addrlen,
00273               const char *canonname)
00274 {
00275     struct addrinfo *res;
00276 
00277     res = (struct addrinfo *)malloc (sizeof (struct addrinfo));
00278     if (res != NULL)
00279     {
00280         res->ai_flags = 0;
00281         res->ai_family = af;
00282         res->ai_socktype = type;
00283         res->ai_protocol = proto;
00284         res->ai_addrlen = addrlen;
00285         res->ai_addr = malloc (addrlen);
00286         res->ai_canonname = NULL;
00287         res->ai_next = NULL;
00288 
00289         if (res->ai_addr != NULL)
00290         {
00291             memcpy (res->ai_addr, addr, addrlen);
00292 
00293             if (canonname != NULL)
00294             {
00295                 res->ai_canonname = strdup (canonname);
00296                 if (res->ai_canonname != NULL)
00297                     return res; /* success ! */
00298             }
00299             else
00300                 return res;
00301         }
00302     }
00303     /* failsafe */
00304     vlc_freeaddrinfo (res);
00305     return NULL;
00306 }
00307 
00308 
00309 static struct addrinfo *
00310 makeipv4info (int type, int proto, u_long ip, u_short port, const char *name)
00311 {
00312     struct sockaddr_in addr;
00313 
00314     memset (&addr, 0, sizeof (addr));
00315     addr.sin_family = AF_INET;
00316 # ifdef HAVE_SA_LEN
00317     addr.sin_len = sizeof (addr);
00318 # endif
00319     addr.sin_port = port;
00320     addr.sin_addr.s_addr = ip;
00321 
00322     return makeaddrinfo (AF_INET, type, proto,
00323                          (struct sockaddr*)&addr, sizeof (addr), name);
00324 }
00325 
00326 
00327 /*
00328  * getaddrinfo() non-thread-safe IPv4-only implementation
00329  * Address-family-independant hostname to address resolution.
00330  *
00331  * This is meant for IPv6-unaware systems that do probably not provide
00332  * getaddrinfo(), but still have old function gethostbyname().
00333  *
00334  * Only UDP and TCP over IPv4 are supported here.
00335  */
00336 static int
00337 __getaddrinfo (const char *node, const char *service,
00338                const struct addrinfo *hints, struct addrinfo **res)
00339 {
00340     struct addrinfo *info;
00341     u_long ip;
00342     u_short port;
00343     int protocol = 0, flags = 0;
00344     const char *name = NULL;
00345 
00346     if (hints != NULL)
00347     {
00348         flags = hints->ai_flags;
00349 
00350         if (flags & ~_AI_MASK)
00351             return EAI_BADFLAGS;
00352         /* only accept AF_INET and AF_UNSPEC */
00353         if (hints->ai_family && (hints->ai_family != AF_INET))
00354             return EAI_FAMILY;
00355 
00356         /* protocol sanity check */
00357         switch (hints->ai_socktype)
00358         {
00359             case SOCK_STREAM:
00360                 protocol = IPPROTO_TCP;
00361                 break;
00362 
00363             case SOCK_DGRAM:
00364                 protocol = IPPROTO_UDP;
00365                 break;
00366 
00367 #ifndef SYS_BEOS
00368             case SOCK_RAW:
00369 #endif
00370             case 0:
00371                 break;
00372 
00373             default:
00374                 return EAI_SOCKTYPE;
00375         }
00376         if (hints->ai_protocol && protocol
00377          && (protocol != hints->ai_protocol))
00378             return EAI_SERVICE;
00379     }
00380 
00381     *res = NULL;
00382 
00383     /* default values */
00384     if (node == NULL)
00385     {
00386         if (flags & AI_PASSIVE)
00387             ip = htonl (INADDR_ANY);
00388         else
00389             ip = htonl (INADDR_LOOPBACK);
00390     }
00391     else
00392     if ((ip = inet_addr (node)) == INADDR_NONE)
00393     {
00394         struct hostent *entry = NULL;
00395 
00396         /* hostname resolution */
00397         if (!(flags & AI_NUMERICHOST))
00398             entry = gethostbyname (node);
00399 
00400         if (entry == NULL)
00401             return EAI_NONAME;
00402 
00403         if ((entry->h_length != 4) || (entry->h_addrtype != AF_INET))
00404             return EAI_FAMILY;
00405 
00406         ip = *((u_long *) entry->h_addr);
00407         if (flags & AI_CANONNAME)
00408             name = entry->h_name;
00409     }
00410 
00411     if ((flags & AI_CANONNAME) && (name == NULL))
00412         name = node;
00413 
00414     /* service resolution */
00415     if (service == NULL)
00416         port = 0;
00417     else
00418     {
00419         long d;
00420         char *end;
00421 
00422         d = strtoul (service, &end, 0);
00423         if (end[0] /* service is not a number */
00424          || (d > 65535))
00425         {
00426             struct servent *entry;
00427             const char *protoname;
00428 
00429             switch (protocol)
00430             {
00431                 case IPPROTO_TCP:
00432                     protoname = "tcp";
00433                     break;
00434 
00435                 case IPPROTO_UDP:
00436                     protoname = "udp";
00437                     break;
00438 
00439                 default:
00440                     protoname = NULL;
00441             }
00442 
00443             entry = getservbyname (service, protoname);
00444             if (entry == NULL)
00445                 return EAI_SERVICE;
00446 
00447             port = entry->s_port;
00448         }
00449         else
00450             port = htons ((u_short)d);
00451     }
00452 
00453     /* building results... */
00454     if ((!protocol) || (protocol == IPPROTO_UDP))
00455     {
00456         info = makeipv4info (SOCK_DGRAM, IPPROTO_UDP, ip, port, name);
00457         if (info == NULL)
00458         {
00459             errno = ENOMEM;
00460             return EAI_SYSTEM;
00461         }
00462         if (flags & AI_PASSIVE)
00463             info->ai_flags |= AI_PASSIVE;
00464         *res = info;
00465     }
00466     if ((!protocol) || (protocol == IPPROTO_TCP))
00467     {
00468         info = makeipv4info (SOCK_STREAM, IPPROTO_TCP, ip, port, name);
00469         if (info == NULL)
00470         {
00471             errno = ENOMEM;
00472             return EAI_SYSTEM;
00473         }
00474         info->ai_next = *res;
00475         if (flags & AI_PASSIVE)
00476             info->ai_flags |= AI_PASSIVE;
00477         *res = info;
00478     }
00479 
00480     return 0;
00481 }
00482 #endif /* if !HAVE_GETADDRINFO */
00483 
00484 
00485 int vlc_getnameinfo( const struct sockaddr *sa, int salen,
00486                      char *host, int hostlen, int *portnum, int flags )
00487 {
00488     char psz_servbuf[6], *psz_serv;
00489     int i_servlen, i_val;
00490 #if defined( WIN32 ) && !defined( UNDER_CE )
00491     /*
00492      * Here is the kind of kludge you need to keep binary compatibility among
00493      * varying OS versions...
00494      */
00495     typedef int (CALLBACK * GETNAMEINFO) ( const struct sockaddr*, socklen_t,
00496                                            char*, DWORD, char*, DWORD, int );
00497     HINSTANCE wship6_module;
00498     GETNAMEINFO ws2_getnameinfo;
00499 #endif
00500 
00501     flags |= NI_NUMERICSERV;
00502     if( portnum != NULL )
00503     {
00504         psz_serv = psz_servbuf;
00505         i_servlen = sizeof( psz_servbuf );
00506     }
00507     else
00508     {
00509         psz_serv = NULL;
00510         i_servlen = 0;
00511     }
00512 #if defined( WIN32 ) && !defined( UNDER_CE )
00513     wship6_module = LoadLibrary( "wship6.dll" );
00514     if( wship6_module != NULL )
00515     {
00516         ws2_getnameinfo = (GETNAMEINFO)GetProcAddress( wship6_module,
00517                                                        "getnameinfo" );
00518 
00519         if( ws2_getnameinfo != NULL )
00520         {
00521             i_val = ws2_getnameinfo( sa, salen, host, hostlen, psz_serv,
00522                                      i_servlen, flags );
00523             FreeLibrary( wship6_module );
00524 
00525             if( portnum != NULL )
00526                 *portnum = atoi( psz_serv );
00527             return i_val;
00528         }
00529             
00530         FreeLibrary( wship6_module );
00531     }
00532 #endif
00533 #if defined( HAVE_GETNAMEINFO ) || defined( UNDER_CE )
00534     i_val = getnameinfo(sa, salen, host, hostlen, psz_serv, i_servlen, flags);
00535 #else
00536     {
00537 # ifdef HAVE_USABLE_MUTEX_THAT_DONT_NEED_LIBVLC_POINTER
00538         static vlc_value_t lock;
00539     
00540         /* my getnameinfo implementation is not thread-safe as it uses
00541          * gethostbyaddr and the likes */
00542         vlc_mutex_lock( lock.p_address );
00543 #else
00544 //# warning FIXME : This is not thread-safe!
00545 #endif
00546         i_val = __getnameinfo( sa, salen, host, hostlen, psz_serv, i_servlen,
00547                                flags );
00548 # ifdef HAVE_USABLE_MUTEX_THAT_DONT_NEED_LIBVLC_POINTER
00549         vlc_mutex_unlock( lock.p_address );
00550 # endif
00551     }
00552 #endif
00553 
00554     if( portnum != NULL )
00555         *portnum = atoi( psz_serv );
00556 
00557     return i_val;
00558 }
00559 
00560 
00561 /* TODO: support for setting sin6_scope_id */
00562 int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
00563                      int i_port, const struct addrinfo *p_hints,
00564                      struct addrinfo **res )
00565 {
00566     struct addrinfo hints;
00567     char psz_buf[NI_MAXHOST], *psz_node, psz_service[6];
00568 
00569     /*
00570      * In VLC, we always use port number as integer rather than strings
00571      * for historical reasons (and portability).
00572      */
00573     if( ( i_port > 65535 ) || ( i_port < 0 ) )
00574     {
00575         msg_Err( p_this, "invalid port number %d specified", i_port );
00576         return EAI_SERVICE;
00577     }
00578 
00579     /* cannot overflow */
00580     snprintf( psz_service, 6, "%d", i_port );
00581 
00582     /* Check if we have to force ipv4 or ipv6 */
00583     if( p_hints == NULL )
00584         memset( &hints, 0, sizeof( hints ) );
00585     else
00586         memcpy( &hints, p_hints, sizeof( hints ) );
00587 
00588     if( hints.ai_family == AF_UNSPEC )
00589     {
00590         vlc_value_t val;
00591 
00592         var_Create( p_this, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00593         var_Get( p_this, "ipv4", &val );
00594         if( val.b_bool )
00595             hints.ai_family = AF_INET;
00596 
00597 #ifdef AF_INET6
00598         var_Create( p_this, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00599         var_Get( p_this, "ipv6", &val );
00600         if( val.b_bool )
00601             hints.ai_family = AF_INET6;
00602 #endif
00603     }
00604 
00605     /* 
00606      * VLC extensions :
00607      * - accept "" as NULL
00608      * - ignore square brackets
00609      */
00610     if( ( node == NULL ) || (node[0] == '\0' ) )
00611     {
00612         psz_node = NULL;
00613     }
00614     else
00615     {
00616         strncpy( psz_buf, node, NI_MAXHOST );
00617         psz_buf[NI_MAXHOST - 1] = '\0';
00618 
00619         psz_node = psz_buf;
00620 
00621         if( psz_buf[0] == '[' )
00622         {
00623             char *ptr;
00624 
00625             ptr = strrchr( psz_buf, ']' );
00626             if( ( ptr != NULL ) && (ptr[1] == '\0' ) )
00627             {
00628                 *ptr = '\0';
00629                 psz_node++;
00630             }
00631         }
00632     }
00633 
00634 #if defined( WIN32 ) && !defined( UNDER_CE )
00635     {
00636         typedef int (CALLBACK * GETADDRINFO) ( const char *, const char *,
00637                                             const struct addrinfo *,
00638                                             struct addrinfo ** );
00639         HINSTANCE wship6_module;
00640         GETADDRINFO ws2_getaddrinfo;
00641 
00642         wship6_module = LoadLibrary( "wship6.dll" );
00643         if( wship6_module != NULL )
00644         {
00645             ws2_getaddrinfo = (GETADDRINFO)GetProcAddress( wship6_module,
00646                                                         "getaddrinfo" );
00647 
00648             if( ws2_getaddrinfo != NULL )
00649             {
00650                 int i_ret;
00651 
00652                 i_ret = ws2_getaddrinfo( psz_node, psz_service, &hints, res );
00653                 FreeLibrary( wship6_module ); /* is this wise ? */
00654                 return i_ret;
00655             }
00656 
00657             FreeLibrary( wship6_module );
00658         }
00659     }
00660 #endif
00661 #if defined( HAVE_GETADDRINFO ) || defined( UNDER_CE )
00662 # ifdef AI_IDN
00663     /* Run-time I18n Domain Names support */
00664     {
00665         static vlc_bool_t i_idn = VLC_TRUE; /* beware of thread-safety */
00666 
00667         if( i_idn )
00668         {
00669             int i_ret;
00670 
00671             hints.ai_flags |= AI_IDN;
00672             i_ret = getaddrinfo( psz_node, psz_service, &hints, res );
00673 
00674             if( i_ret != EAI_BADFLAGS )
00675                 return i_ret;
00676 
00677             /* libidn not available: disable and retry without it */
00678 
00679             /* NOTE: Using i_idn here would not be thread-safe */
00680             hints.ai_flags &= ~AI_IDN;
00681             i_idn = VLC_FALSE;
00682             msg_Dbg( p_this, "I18n Domain Names not supported - disabled" );
00683         }
00684     }
00685 # endif
00686     return getaddrinfo( psz_node, psz_service, &hints, res );
00687 #else
00688 {
00689     int i_ret;
00690 
00691     vlc_value_t lock;
00692 
00693     var_Create( p_this->p_libvlc, "getaddrinfo_mutex", VLC_VAR_MUTEX );
00694     var_Get( p_this->p_libvlc, "getaddrinfo_mutex", &lock );
00695     vlc_mutex_lock( lock.p_address );
00696 
00697     i_ret = __getaddrinfo( psz_node, psz_service, &hints, res );
00698     vlc_mutex_unlock( lock.p_address );
00699     return i_ret;
00700 }
00701 #endif
00702 }
00703 
00704 
00705 void vlc_freeaddrinfo( struct addrinfo *infos )
00706 {
00707 #if defined( WIN32 ) && !defined( UNDER_CE )
00708     typedef void (CALLBACK * FREEADDRINFO) ( struct addrinfo * );
00709     HINSTANCE wship6_module;
00710     FREEADDRINFO ws2_freeaddrinfo;
00711      
00712     wship6_module = LoadLibrary( "wship6.dll" );
00713     if( wship6_module != NULL )
00714     {
00715         ws2_freeaddrinfo = (FREEADDRINFO)GetProcAddress( wship6_module,
00716                                                          "freeaddrinfo" );
00717 
00718         /*
00719          * NOTE: it is assumed that wship6.dll defines either both
00720          * getaddrinfo and freeaddrinfo or none of them.
00721          */
00722         if( ws2_freeaddrinfo != NULL )
00723         {
00724             ws2_freeaddrinfo( infos );
00725             FreeLibrary( wship6_module );
00726             return;
00727         }
00728 
00729         FreeLibrary( wship6_module );
00730     }
00731 #endif
00732 #if defined( HAVE_GETADDRINFO ) || defined( UNDER_CE )
00733     freeaddrinfo( infos );
00734 #else
00735     __freeaddrinfo( infos );
00736 #endif
00737 }

Generated on Tue Dec 20 10:15:00 2005 for vlc-0.8.4a by  doxygen 1.4.2