root/ext/net/netdb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. make_hostent
  2. Scm_GetHostByName
  3. Scm_GetHostByAddr
  4. hostent_name
  5. hostent_aliases
  6. hostent_addresses
  7. make_protoent
  8. Scm_GetProtoByName
  9. Scm_GetProtoByNumber
  10. protoent_name
  11. protoent_aliases
  12. protoent_proto
  13. make_servent
  14. Scm_GetServByName
  15. Scm_GetServByPort
  16. servent_name
  17. servent_aliases
  18. servent_port
  19. servent_proto
  20. addrinfo_allocate
  21. make_addrinfo
  22. Scm_GetAddrinfo
  23. Scm_GetNameinfo
  24. Scm_Init_NetDB

   1 /*
   2  * netdb.c - obtain information about network
   3  *
   4  *   Copyright (c) 2000-2004 Shiro Kawai, All rights reserved.
   5  * 
   6  *   Redistribution and use in source and binary forms, with or without
   7  *   modification, are permitted provided that the following conditions
   8  *   are met:
   9  * 
  10  *   1. Redistributions of source code must retain the above copyright
  11  *      notice, this list of conditions and the following disclaimer.
  12  *
  13  *   2. Redistributions in binary form must reproduce the above copyright
  14  *      notice, this list of conditions and the following disclaimer in the
  15  *      documentation and/or other materials provided with the distribution.
  16  *
  17  *   3. Neither the name of the authors nor the names of its contributors
  18  *      may be used to endorse or promote products derived from this
  19  *      software without specific prior written permission.
  20  *
  21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  27  *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  *
  33  *  $Id: netdb.c,v 1.12 2005/11/02 06:03:26 shirok Exp $
  34  */
  35 
  36 #include "gauche/net.h"
  37 #include <gauche/class.h>
  38 
  39 #define DATA_BUFSIZ  980
  40 
  41 static struct netdb_data_rec {
  42     int dummy;                  /* dummy var to make sure this structure is
  43                                    placed in data area. */
  44     ScmInternalMutex hostent_mutex;
  45     ScmInternalMutex protoent_mutex;
  46     ScmInternalMutex servent_mutex;
  47 } netdb_data = { 1 };
  48 
  49 #define WITH_GLOBAL_LOCK(mutex, body)           \
  50     SCM_UNWIND_PROTECT {                        \
  51       SCM_INTERNAL_MUTEX_LOCK(mutex);           \
  52       body;                                     \
  53     } SCM_WHEN_ERROR {                          \
  54         SCM_INTERNAL_MUTEX_UNLOCK(mutex);       \
  55         SCM_NEXT_HANDLER;                       \
  56     } SCM_END_PROTECT;                          \
  57     SCM_INTERNAL_MUTEX_UNLOCK(mutex)
  58 
  59 /*-------------------------------------------------------------
  60  * Hostent
  61  */
  62 
  63 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SysHostentClass, NULL);
  64 
  65 static ScmSysHostent *make_hostent(struct hostent *he)
  66 {
  67     ScmSysHostent *entry = SCM_NEW(ScmSysHostent);
  68     ScmObj h = SCM_NIL, t = SCM_NIL;
  69     char **p;
  70     
  71     SCM_SET_CLASS(entry, SCM_CLASS_SYS_HOSTENT);
  72     entry->name = SCM_MAKE_STR_COPYING(he->h_name);
  73     for (p = he->h_aliases; *p; p++) {
  74         SCM_APPEND1(h, t, SCM_MAKE_STR_COPYING(*p));
  75     }
  76     entry->aliases = h;
  77     h = t = SCM_NIL;
  78     if (he->h_addrtype == AF_INET) {
  79         for (p = he->h_addr_list; *p; p++) {
  80             char buf[50];
  81             struct in_addr *addr = (struct in_addr*)*p;
  82             unsigned long addrval = ntohl(addr->s_addr);
  83             /* avoid using inet_ntoa, for it is not reentrant */
  84             snprintf(buf, 50, "%d.%d.%d.%d",
  85                      ((addrval >> 24)& 0xff), ((addrval >> 16) & 0xff),
  86                      ((addrval >> 8) & 0xff), (addrval & 0xff));
  87             SCM_APPEND1(h, t, SCM_MAKE_STR_COPYING(buf));
  88         }
  89     } else {
  90         /* soon AF_INET6 will be supported (hopefully) */
  91         Scm_Error("unknown address type (%d)", he->h_addrtype);
  92     }
  93     entry->addresses = h;
  94     return entry;
  95 }
  96 
  97 ScmObj Scm_GetHostByName(const char *name)
  98 {
  99 #if defined(GETHOSTBYNAME_R_NUMARGS)
 100     ScmObj entry = SCM_FALSE;
 101     {
 102         int herr = 0, bufsiz = DATA_BUFSIZ;
 103         struct hostent he;
 104         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 105         
 106         for (;;) {
 107 #if GETHOSTBYNAME_R_NUMARGS == 5
 108             if (gethostbyname_r(name, &he, buf, bufsiz, &herr) != NULL) break;
 109             if (herr != ERANGE) return SCM_FALSE;
 110             bufsiz *= 2;
 111             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 112 #elif GETHOSTBYNAME_R_NUMARGS == 6
 113             struct hostent *rhe;
 114             gethostbyname_r(name, &he, buf, bufsiz, &rhe, &herr);
 115             if (rhe != 0) break;
 116             else if (herr != ERANGE) return SCM_FALSE;
 117             bufsiz *= 2;
 118             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 119 #else
 120 #error unsupported gethostbyname_r variant (configuration error?)
 121 #endif
 122         }
 123         entry = SCM_OBJ(make_hostent(&he));
 124     }
 125     return entry;
 126 #else /* !defined(GETHOSTBYNAME_R_NUMARGS) */
 127     /* We don't have thread-safe call.  Using global lock. */
 128     volatile ScmObj entry = SCM_FALSE;
 129     WITH_GLOBAL_LOCK(netdb_data.hostent_mutex,
 130                      do {
 131                          struct hostent *he;
 132                          he = gethostbyname(name);
 133                          if (he != NULL) entry = SCM_OBJ(make_hostent(he));
 134                      } while (0));
 135     return entry;
 136 #endif /* !defined(GETHOSTBYNAME_R_NUMARGS) */
 137 }
 138 
 139 ScmObj Scm_GetHostByAddr(const char *addr, int type)
 140 {
 141     struct in_addr iaddr;
 142     if (type != AF_INET) {
 143         Scm_Error("unsupported address type: %d", type);
 144     }
 145     if (!inet_aton(addr, &iaddr)) {
 146         Scm_Error("bad inet address format: %s", addr);
 147     }
 148     
 149 #if defined(GETHOSTBYADDR_R_NUMARGS)
 150     {
 151         ScmObj entry = SCM_FALSE;
 152         int herr = 0, bufsiz = DATA_BUFSIZ;
 153         struct hostent he;
 154         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 155         for (;;) {
 156 #if GETHOSTBYADDR_R_NUMARGS == 7
 157             if (gethostbyaddr_r((void *)&iaddr, sizeof(struct in_addr),
 158                                 AF_INET, &he, buf, bufsiz, &herr) != NULL) {
 159                 break;
 160             }
 161             if (herr != ERANGE) return SCM_FALSE;
 162             bufsiz *= 2;
 163             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 164 #elif GETHOSTBYADDR_R_NUMARGS == 8
 165             struct hostent *rhe;
 166             gethostbyaddr_r((void *)&iaddr, sizeof(struct in_addr),
 167                             AF_INET, &he, buf, bufsiz, &rhe, &herr);
 168             if (rhe != NULL) break;
 169             if (herr != ERANGE) return SCM_FALSE;
 170             bufsiz *= 2;
 171             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 172 #else
 173 #error unsupported gethostbyaddr_r variant (configuration error?)
 174 #endif
 175         }
 176         entry = SCM_OBJ(make_hostent(&he));
 177         return entry;
 178     }
 179 #else /* !defined(GETHOSTBYADDR_R_NUMARGS) */
 180     {
 181         volatile ScmObj entry = SCM_FALSE;
 182         struct hostent *he;
 183         
 184         WITH_GLOBAL_LOCK(netdb_data.hostent_mutex,
 185                          do {
 186                              he = gethostbyaddr((void*)&iaddr,
 187                                                 sizeof(struct in_addr),
 188                                                 AF_INET);
 189                              if (he != NULL) {
 190                                  entry = SCM_OBJ(make_hostent(he));
 191                              }
 192                          } while (0));
 193         return entry;
 194     }
 195 #endif /* !defined(GETHOSTBYADDR_R_NUMARGS) */
 196 }
 197 
 198 static ScmObj hostent_name(ScmSysHostent *entry)
 199 {
 200     return entry->name;
 201 }
 202 
 203 static ScmObj hostent_aliases(ScmSysHostent *entry)
 204 {
 205     return entry->aliases;
 206 }
 207 
 208 static ScmObj hostent_addresses(ScmSysHostent *entry)
 209 {
 210     return entry->addresses;
 211 }
 212 
 213 static ScmClassStaticSlotSpec hostent_slots[] = {
 214     SCM_CLASS_SLOT_SPEC("name", hostent_name, NULL),
 215     SCM_CLASS_SLOT_SPEC("aliases", hostent_aliases, NULL),
 216     SCM_CLASS_SLOT_SPEC("addresses", hostent_addresses, NULL),
 217     { NULL }
 218 };
 219 
 220 /*-------------------------------------------------------------
 221  * Protoent
 222  */
 223 
 224 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SysProtoentClass, NULL);
 225 
 226 static ScmSysProtoent *make_protoent(struct protoent *pe)
 227 {
 228     ScmSysProtoent *entry = SCM_NEW(ScmSysProtoent);
 229     ScmObj h = SCM_NIL, t = SCM_NIL;
 230     char **p;
 231     
 232     SCM_SET_CLASS(entry, SCM_CLASS_SYS_PROTOENT);
 233     entry->name = SCM_MAKE_STR_COPYING(pe->p_name);
 234     for (p = pe->p_aliases; *p; p++) {
 235         SCM_APPEND1(h, t, SCM_MAKE_STR_COPYING(*p));
 236     }
 237     entry->aliases = h;
 238     entry->proto = Scm_MakeInteger(pe->p_proto);
 239     return entry;
 240 }
 241 
 242 ScmObj Scm_GetProtoByName(const char *name)
 243 {
 244 #if defined(GETPROTOBYNAME_R_NUMARGS)
 245     ScmObj entry = SCM_FALSE;
 246     {
 247         int bufsiz = DATA_BUFSIZ;
 248         struct protoent pe;
 249         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 250         
 251         for (;;) {
 252 #if GETPROTOBYNAME_R_NUMARGS == 4
 253             if (getprotobyname_r(name, &pe, buf, bufsiz) != NULL) break;
 254             if (errno != ERANGE) return SCM_FALSE;
 255             bufsiz *= 2;
 256             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 257 #elif GETPROTOBYNAME_R_NUMARGS == 5
 258             struct protoent *rpe;
 259             getprotobyname_r(name, &pe, buf, bufsiz, &rpe);
 260             if (rpe != 0) break;
 261             else if (errno != ERANGE) return SCM_FALSE;
 262             bufsiz *= 2;
 263             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 264 #else
 265 #error unsupported getprotobyname_r variant (configuration error?)
 266 #endif
 267         }
 268         entry = SCM_OBJ(make_protoent(&pe));
 269     }
 270     return entry;
 271 #else /* !defined(GETPROTOBYNAME_R_NUMARGS) */
 272     volatile ScmObj entry = SCM_FALSE;
 273     WITH_GLOBAL_LOCK(netdb_data.protoent_mutex,
 274                      do {
 275                          struct protoent *pe = getprotobyname(name);
 276                          if (pe != NULL) entry = SCM_OBJ(make_protoent(pe));
 277                      } while (0));
 278     return entry;
 279 #endif /* !defined(GETPROTOBYNAME_R_NUMARGS) */
 280 }
 281 
 282 ScmObj Scm_GetProtoByNumber(int number)
 283 {
 284 #if defined(GETPROTOBYNUMBER_R_NUMARGS)
 285     ScmObj entry = SCM_FALSE;
 286     {
 287         int bufsiz = DATA_BUFSIZ;
 288         struct protoent pe;
 289         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 290         
 291         for (;;) {
 292 #if GETPROTOBYNUMBER_R_NUMARGS == 4
 293             if (getprotobynumber_r(number, &pe, buf, bufsiz) != NULL) break;
 294             if (errno != ERANGE) return SCM_FALSE;
 295             bufsiz *= 2;
 296             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 297 #elif GETPROTOBYNUMBER_R_NUMARGS == 5
 298             struct protoent *rpe;
 299             getprotobynumber_r(number, &pe, buf, bufsiz, &rpe);
 300             if (rpe != 0) break;
 301             else if (errno != ERANGE) return SCM_FALSE;
 302             bufsiz *= 2;
 303             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 304 #else
 305 #error unsupported getprotobyname_r variant (configuration error?)
 306 #endif
 307         }
 308         entry = SCM_OBJ(make_protoent(&pe));
 309     }
 310     return entry;
 311 #else /* !defined(GETPROTOBYNUMBER_R_NUMARGS) */
 312     volatile ScmObj entry = SCM_FALSE;
 313     WITH_GLOBAL_LOCK(netdb_data.protoent_mutex,
 314                      do {
 315                          struct protoent *pe = getprotobynumber(number);
 316                          if (pe != NULL) entry = SCM_OBJ(make_protoent(pe));
 317                      } while (0));
 318     return entry;
 319 #endif /* !defined(GETPROTOBYNUMBER_R_NUMARGS) */
 320 }
 321 
 322 static ScmObj protoent_name(ScmSysProtoent *entry)
 323 {
 324     return entry->name;
 325 }
 326 
 327 static ScmObj protoent_aliases(ScmSysProtoent *entry)
 328 {
 329     return entry->aliases;
 330 }
 331 
 332 static ScmObj protoent_proto(ScmSysProtoent *entry)
 333 {
 334     return entry->proto;
 335 }
 336 
 337 static ScmClassStaticSlotSpec protoent_slots[] = {
 338     SCM_CLASS_SLOT_SPEC("name", protoent_name, NULL),
 339     SCM_CLASS_SLOT_SPEC("aliases", protoent_aliases, NULL),
 340     SCM_CLASS_SLOT_SPEC("proto", protoent_proto, NULL),
 341     { NULL }
 342 };
 343 
 344 /*-------------------------------------------------------------
 345  * Servent
 346  */
 347 
 348 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SysServentClass, NULL);
 349 
 350 static ScmSysServent *make_servent(struct servent *se)
 351 {
 352     ScmSysServent *entry = SCM_NEW(ScmSysServent);
 353     ScmObj h = SCM_NIL, t = SCM_NIL;
 354     char **p;
 355     
 356     SCM_SET_CLASS(entry, SCM_CLASS_SYS_SERVENT);
 357     entry->name = SCM_MAKE_STR_COPYING(se->s_name);
 358     for (p = se->s_aliases; *p; p++) {
 359         SCM_APPEND1(h, t, SCM_MAKE_STR_COPYING(*p));
 360     }
 361     entry->aliases = h;
 362     entry->port = Scm_MakeInteger(ntohs(se->s_port));
 363     entry->proto = SCM_MAKE_STR_COPYING(se->s_proto);
 364     return entry;
 365 }
 366 
 367 ScmObj Scm_GetServByName(const char *name, const char *proto)
 368 {
 369 #if defined(GETSERVBYNAME_R_NUMARGS)
 370     ScmObj entry = SCM_FALSE;
 371     {
 372         int bufsiz = DATA_BUFSIZ;
 373         struct servent se;
 374         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 375         
 376         for (;;) {
 377 #if GETSERVBYNAME_R_NUMARGS == 5
 378             if (getservbyname_r(name, proto, &se, buf, bufsiz) != NULL) break;
 379             if (errno != ERANGE) return SCM_FALSE;
 380             bufsiz *= 2;
 381             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 382 #elif GETSERVBYNAME_R_NUMARGS == 6
 383             struct servent *rse;
 384             getservbyname_r(name, proto, &se, buf, bufsiz, &rse);
 385             if (rse != 0) break;
 386             else if (errno != ERANGE) return SCM_FALSE;
 387             bufsiz *= 2;
 388             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 389 #else
 390 #error unsupported getservbyname_r variant (configuration error?)
 391 #endif
 392         }
 393         entry = SCM_OBJ(make_servent(&se));
 394     }
 395     return entry;
 396 #else /* !defined(GETSERVBYNAME_R_NUMARGS) */
 397     volatile ScmObj entry = SCM_FALSE;
 398     WITH_GLOBAL_LOCK(netdb_data.servent_mutex,
 399                      do {
 400                          struct servent *se = getservbyname(name, proto);
 401                          if (se != NULL) entry = SCM_OBJ(make_servent(se));
 402                      } while (0));
 403     return entry;
 404 #endif /* !defined(GETSERVBYNAME_R_NUMARGS) */
 405 }
 406 
 407 ScmObj Scm_GetServByPort(int port, const char *proto)
 408 {
 409 #if defined(GETSERVBYPORT_R_NUMARGS)
 410     ScmObj entry = SCM_FALSE;
 411     {
 412         int bufsiz = DATA_BUFSIZ;
 413         struct servent se;
 414         char staticbuf[DATA_BUFSIZ], *buf = staticbuf;
 415         
 416         for (;;) {
 417 #if GETSERVBYPORT_R_NUMARGS == 5
 418             if (getservbyport_r(htons(port), proto, &se, buf, bufsiz) != NULL)
 419                 break;
 420             if (errno != ERANGE) return SCM_FALSE;
 421             bufsiz *= 2;
 422             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 423 #elif GETSERVBYPORT_R_NUMARGS == 6
 424             struct servent *rse;
 425             getservbyport_r(htons(port), proto, &se, buf, bufsiz, &rse);
 426             if (rse != 0) break;
 427             else if (errno != ERANGE) return SCM_FALSE;
 428             bufsiz *= 2;
 429             buf = SCM_NEW_ATOMIC2(char*, bufsiz);
 430 #else
 431 #error unsupported getservbyport_r variant (configuration error?)
 432 #endif
 433         }
 434         entry = SCM_OBJ(make_servent(&se));
 435     }
 436     return entry;
 437 #else /* !defined(GETSERVBYPORT_R_NUMARGS) */
 438     volatile ScmObj entry = SCM_FALSE;
 439     WITH_GLOBAL_LOCK(netdb_data.servent_mutex,
 440                      do {
 441                          struct servent *se =
 442                              getservbyport(htons(port), proto);
 443                          if (se != NULL) entry = SCM_OBJ(make_servent(se));
 444                      } while (0));
 445     return entry;
 446 #endif /* !defined(GETSERVBYPORT_R_NUMARGS) */
 447 }
 448 
 449 static ScmObj servent_name(ScmSysServent *entry)
 450 {
 451     return entry->name;
 452 }
 453 
 454 static ScmObj servent_aliases(ScmSysServent *entry)
 455 {
 456     return entry->aliases;
 457 }
 458 
 459 static ScmObj servent_port(ScmSysServent *entry)
 460 {
 461     return entry->port;
 462 }
 463 
 464 static ScmObj servent_proto(ScmSysServent *entry)
 465 {
 466     return entry->proto;
 467 }
 468 
 469 static ScmClassStaticSlotSpec servent_slots[] = {
 470     SCM_CLASS_SLOT_SPEC("name", servent_name, NULL),
 471     SCM_CLASS_SLOT_SPEC("aliases", servent_aliases, NULL),
 472     SCM_CLASS_SLOT_SPEC("port", servent_port, NULL),
 473     SCM_CLASS_SLOT_SPEC("proto", servent_proto, NULL),
 474     { NULL }
 475 };
 476 
 477 /*-------------------------------------------------------------
 478  * Addrinfo
 479  */
 480 
 481 #ifdef HAVE_IPV6
 482 
 483 ScmObj addrinfo_allocate(ScmClass *klass, ScmObj initargs)
 484 {
 485     ScmSysAddrinfo *info = SCM_ALLOCATE(ScmSysAddrinfo, klass);
 486     SCM_SET_CLASS(info, klass);
 487     info->canonname = NULL;
 488     info->addr = NULL;
 489     return SCM_OBJ(info);
 490 }
 491 
 492 static ScmSysAddrinfo *make_addrinfo(struct addrinfo *ai)
 493 {
 494     ScmSysAddrinfo *info = SCM_NEW(ScmSysAddrinfo);
 495 
 496     SCM_SET_CLASS(info, SCM_CLASS_SYS_ADDRINFO);
 497     info->flags = ai->ai_flags;
 498     info->family = ai->ai_family;
 499     info->socktype = ai->ai_socktype;
 500     info->protocol = ai->ai_protocol;
 501     info->addrlen = ai->ai_addrlen;
 502     if (ai->ai_canonname != NULL)
 503         info->canonname = SCM_STRING(SCM_MAKE_STR_COPYING(ai->ai_canonname));
 504     if (ai->ai_addr != NULL)
 505         info->addr = SCM_SOCKADDR(Scm_MakeSockAddr(NULL,
 506                                                    ai->ai_addr,
 507                                                    ai->ai_addrlen));
 508     return info;
 509 }
 510 
 511 ScmObj Scm_GetAddrinfo(const char *nodename,
 512                        const char *servname,
 513                        struct addrinfo *hints)
 514 {
 515     ScmObj h = SCM_NIL, t = SCM_NIL;
 516     struct addrinfo *res, *res0;
 517     int r;
 518 
 519     r = getaddrinfo(nodename, servname, hints, &res0);
 520     if (r) Scm_Error("getaddrinfo failed: %s", gai_strerror(r));
 521 
 522     for (res = res0; res != NULL; res = res->ai_next) {
 523         SCM_APPEND1(h, t, SCM_OBJ(make_addrinfo(res)));
 524     }
 525     freeaddrinfo(res0);
 526     return h;
 527 }
 528 
 529 ScmObj Scm_GetNameinfo(ScmSockAddr *addr, int flags)
 530 {
 531     char host[NI_MAXHOST], serv[NI_MAXSERV];
 532     int r;
 533 
 534     r = getnameinfo(&addr->addr, addr->addrlen,
 535                     host, sizeof(host), serv, sizeof(serv), flags);
 536     if (r) Scm_Error("getnameinfo failed: %s", gai_strerror(r));
 537     return Scm_Values2(SCM_MAKE_STR_COPYING(host), SCM_MAKE_STR_COPYING(serv));
 538 }
 539 
 540 #endif /* HAVE_IPV6 */
 541 
 542 /*-------------------------------------------------------------
 543  * Initialize
 544  */
 545 
 546 void Scm_Init_NetDB(ScmModule *mod)
 547 {
 548     Scm_InitStaticClass(&Scm_SysHostentClass, "<sys-hostent>", mod,
 549                         hostent_slots, 0);
 550     Scm_InitStaticClass(&Scm_SysProtoentClass, "<sys-protoent>", mod,
 551                         protoent_slots, 0);
 552     Scm_InitStaticClass(&Scm_SysServentClass, "<sys-servent>", mod,
 553                         servent_slots, 0);
 554     SCM_INTERNAL_MUTEX_INIT(netdb_data.hostent_mutex);
 555     SCM_INTERNAL_MUTEX_INIT(netdb_data.protoent_mutex);
 556     SCM_INTERNAL_MUTEX_INIT(netdb_data.servent_mutex);
 557 }

/* [<][>][^][v][top][bottom][index][help] */