akaros/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm2_r.c
<<
>>
Prefs
   1/* 
   2 * This file is part of the UCB release of Plan 9. It is subject to the license
   3 * terms in the LICENSE file found in the top-level directory of this
   4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
   5 * part of the UCB release of Plan 9, including this file, may be copied,
   6 * modified, propagated, or distributed except according to the terms contained
   7 * in the LICENSE file.
   8 */
   9
  10/* posix */
  11#include <sys/types.h>
  12#include <unistd.h>
  13#include <stdlib.h>
  14#include <stdio.h>
  15#include <fcntl.h>
  16#include <string.h>
  17#include <errno.h>
  18
  19/* bsd extensions */
  20#include <sys/uio.h>
  21#include <sys/socket.h>
  22#include <netinet/in.h>
  23#include <netdb.h>
  24#include <arpa/inet.h>
  25
  26#include <sys/plan9_helpers.h>
  27
  28enum {
  29        Nname = 6,
  30};
  31
  32int __gethostbyname2_r(const char *name, int af, struct hostent *ret,
  33                       char *buf, size_t buflen,
  34                       struct hostent **result, int *h_errnop)
  35{
  36        int i, t, fd, m;
  37        char *p, *bp;
  38        int nn, na;
  39        unsigned long x;
  40        size_t csmsg_len = 0;
  41        /* These three used to be:
  42                static char *nptr[Nname + 1];
  43                static char *aptr[Nname + 1];
  44                static char addr[Nname][4];
  45         * we need to use space in buf for them */
  46        char **nptr, **aptr;
  47        char (*addr)[4];
  48        size_t nptr_sz, aptr_sz, addr_sz;
  49        nptr_sz = sizeof(char *) * (Nname + 1);
  50        aptr_sz = sizeof(char *) * (Nname + 1);
  51        addr_sz = sizeof(char[Nname][4]);
  52
  53        if (nptr_sz + aptr_sz + addr_sz >= buflen) {
  54                *result = 0;
  55                return -ERANGE;
  56        }
  57        nptr = buf; buf += nptr_sz; buflen -= nptr_sz;
  58        aptr = buf; buf += aptr_sz; buflen -= aptr_sz;
  59        addr = buf; buf += addr_sz; buflen -= addr_sz;
  60
  61        /* for inet addresses only */
  62        if (af != AF_INET) {
  63                *result = 0;
  64                return -EAFNOSUPPORT;
  65        }
  66
  67        ret->h_name = 0;
  68        t = _sock_ipattr(name);
  69
  70        /* connect to server */
  71        fd = open("/net/cs", O_RDWR);
  72        if (fd < 0) {
  73                *h_errnop = NO_RECOVERY;
  74                *result = 0;
  75                return -errno;
  76        }
  77
  78        /* construct the query, always expect an ip# back */
  79        switch (t) {
  80        case Tsys:
  81                csmsg_len = snprintf(buf, buflen, "!sys=%s ip=*", name);
  82                break;
  83        case Tdom:
  84                csmsg_len = snprintf(buf, buflen, "!dom=%s ip=*", name);
  85                break;
  86        case Tip:
  87                csmsg_len = snprintf(buf, buflen, "!ip=%s", name);
  88                break;
  89        default:
  90                /* we can't get here, but want to be safe for changes to
  91                 * _sock_ipattr() */
  92                close(fd);
  93                *result = 0;
  94                return -EINVAL;
  95        }
  96        /* we don't update buflen, since we're just going to reuse the space
  97         * after our nptr/aptr/addr/etc. */
  98        if (csmsg_len >= buflen) {
  99                close(fd);
 100                *result = 0;
 101                return -ERANGE;
 102        }
 103        /* query the server */
 104        if (write(fd, buf, csmsg_len) < 0) {
 105                *h_errnop = TRY_AGAIN;
 106                close(fd);
 107                *result = 0;
 108                return -1;
 109        }
 110        lseek(fd, 0, 0);
 111        for (i = 0; i < buflen - 1; i += m) {
 112                m = read(fd, buf + i, buflen - 1 - i);
 113                if (m <= 0)
 114                        break;
 115                buf[i + m++] = ' ';
 116        }
 117        close(fd);
 118        buf[i] = 0;
 119
 120        /* parse the reply */
 121        nn = na = 0;
 122        for (bp = buf;;) {
 123                p = strchr(bp, '=');
 124                if (p == 0)
 125                        break;
 126                *p++ = 0;
 127                if (strcmp(bp, "dom") == 0) {
 128                        if (ret->h_name == 0)
 129                                ret->h_name = p;
 130                        if (nn < Nname)
 131                                nptr[nn++] = p;
 132                } else if (strcmp(bp, "sys") == 0) {
 133                        if (nn < Nname)
 134                                nptr[nn++] = p;
 135                } else if (strcmp(bp, "ip") == 0) {
 136                        x = inet_addr(p);
 137                        x = ntohl(x);
 138                        if (na < Nname) {
 139                                addr[na][0] = x >> 24;
 140                                addr[na][1] = x >> 16;
 141                                addr[na][2] = x >> 8;
 142                                addr[na][3] = x;
 143                                aptr[na] = addr[na];
 144                                na++;
 145                        }
 146                }
 147                while (*p && *p != ' ')
 148                        p++;
 149                if (*p)
 150                        *p++ = 0;
 151                bp = p;
 152        }
 153        if (nn + na == 0) {
 154                *h_errnop = HOST_NOT_FOUND;
 155                *result = 0;
 156                return -1;
 157        }
 158
 159        nptr[nn] = 0;
 160        aptr[na] = 0;
 161        ret->h_aliases = nptr;
 162        ret->h_addr_list = aptr;
 163        ret->h_length = 4;
 164        ret->h_addrtype = AF_INET;
 165        if (ret->h_name == 0)
 166                ret->h_name = nptr[0];
 167        if (ret->h_name == 0)
 168                ret->h_name = aptr[0];
 169
 170        *result = ret;
 171        return 0;
 172}
 173weak_alias(__gethostbyname2_r, gethostbyname2_r);
 174