(linenum→info "unix/slp.c:2238")

glibc/2.7/nss/digits_dots.c

    1: /* Copyright (C) 1997, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by H.J. Lu <hjl@gnu.ai.mit.edu>, 1997.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <assert.h>
   21: #include <errno.h>
   22: #include <string.h>
   23: #include <stdlib.h>
   24: #include <ctype.h>
   25: #include <wctype.h>
   26: #include <resolv.h>
   27: #include <netdb.h>
   28: #include <arpa/inet.h>
   29: #include "nsswitch.h"
   30: 
   31: #ifdef USE_NSCD
   32: # define inet_aton __inet_aton
   33: # include <nscd/nscd_proto.h>
   34: #endif
   35: 
   36: int
   37: __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
   38:                             char **buffer, size_t *buffer_size,
   39:                             size_t buflen, struct hostent **result,
   40:                             enum nss_status *status, int af, int *h_errnop)
   41: {
   42:   int save;
   43: 
   44:   /* We have to test for the use of IPv6 which can only be done by
   45:      examining `_res'.  */
   46:   if (__res_maybe_init (&_res, 0) == -1)
   47:     {
   48:       if (h_errnop)
   49:         *h_errnop = NETDB_INTERNAL;
   50:       *result = NULL;
   51:       return -1;
   52:     }
   53: 
   54:   /*
   55:    * disallow names consisting only of digits/dots, unless
   56:    * they end in a dot.
   57:    */
   58:   if (isdigit (name[0]) || isxdigit (name[0]) || name[0] == ':')
   59:     {
   60:       const char *cp;
   61:       char *hostname;
   62:       typedef unsigned char host_addr_t[16];
   63:       host_addr_t *host_addr;
   64:       typedef char *host_addr_list_t[2];
   65:       host_addr_list_t *h_addr_ptrs;
   66:       char **h_alias_ptr;
   67:       size_t size_needed;
   68:       int addr_size;
   69: 
   70:       switch (af)
   71:         {
   72:         case AF_INET:
   73:           addr_size = INADDRSZ;
   74:           break;
   75: 
   76:         case AF_INET6:
   77:           addr_size = IN6ADDRSZ;
   78:           break;
   79: 
   80:         default:
   81:           af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
   82:           addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ;
   83:           break;
   84:         }
   85: 
   86:       size_needed = (sizeof (*host_addr)
   87:                      + sizeof (*h_addr_ptrs) + strlen (name) + 1);
   88: 
   89:       if (buffer_size == NULL)
   90:         {
   91:           if (buflen < size_needed)
   92:             {
   93:               if (h_errnop != NULL)
   94:                 *h_errnop = TRY_AGAIN;
   95:               __set_errno (ERANGE);
   96:               goto done;
   97:             }
   98:         }
   99:       else if (buffer_size != NULL && *buffer_size < size_needed)
  100:         {
  101:           char *new_buf;
  102:           *buffer_size = size_needed;
  103:           new_buf = (char *) realloc (*buffer, *buffer_size);
  104: 
  105:           if (new_buf == NULL)
  106:             {
  107:               save = errno;
  108:               free (*buffer);
  109:               *buffer = NULL;
  110:               *buffer_size = 0;
  111:               __set_errno (save);
  112:               if (h_errnop != NULL)
  113:                 *h_errnop = TRY_AGAIN;
  114:               *result = NULL;
  115:               goto done;
  116:             }
  117:           *buffer = new_buf;
  118:         }
  119: 
  120:       memset (*buffer, '\0', size_needed);
  121: 
  122:       host_addr = (host_addr_t *) *buffer;
  123:       h_addr_ptrs = (host_addr_list_t *)
  124:         ((char *) host_addr + sizeof (*host_addr));
  125:       h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));
  126:       hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);
  127: 
  128:       if (isdigit (name[0]))
  129:         {
  130:           for (cp = name;; ++cp)
  131:             {
  132:               if (*cp == '\0')
  133:                 {
  134:                   int ok;
  135: 
  136:                   if (*--cp == '.')
  137:                     break;
  138: 
  139:                   /* All-numeric, no dot at the end. Fake up a hostent as if
  140:                      we'd actually done a lookup.  What if someone types
  141:                      255.255.255.255?  The test below will succeed
  142:                      spuriously... ???  */
  143:                   if (af == AF_INET)
  144:                     ok = __inet_aton (name, (struct in_addr *) host_addr);
  145:                   else
  146:                     {
  147:                       assert (af == AF_INET6);
  148:                       ok = inet_pton (af, name, host_addr) > 0;
  149:                     }
  150:                   if (! ok)
  151:                     {
  152:                       *h_errnop = HOST_NOT_FOUND;
  153:                       if (buffer_size)
  154:                         *result = NULL;
  155:                       goto done;
  156:                     }
  157: 
  158:                   resbuf->h_name = strcpy (hostname, name);
  159:                   h_alias_ptr[0] = NULL;
  160:                   resbuf->h_aliases = h_alias_ptr;
  161:                   (*h_addr_ptrs)[0] = (char *) host_addr;
  162:                   (*h_addr_ptrs)[1] = NULL;
  163:                   resbuf->h_addr_list = *h_addr_ptrs;
  164:                   if (af == AF_INET && (_res.options & RES_USE_INET6))
  165:                     {
  166:                       /* We need to change the IP v4 address into the
  167:                          IP v6 address.  */
  168:                       char tmp[INADDRSZ];
  169:                       char *p = (char *) host_addr;
  170:                       int i;
  171: 
  172:                       /* Save a copy of the IP v4 address. */
  173:                       memcpy (tmp, host_addr, INADDRSZ);
  174:                       /* Mark this ipv6 addr as a mapped ipv4. */
  175:                       for (i = 0; i < 10; i++)
  176:                         *p++ = 0x00;
  177:                       *p++ = 0xff;
  178:                       *p++ = 0xff;
  179:                       /* Copy the IP v4 address. */
  180:                       memcpy (p, tmp, INADDRSZ);
  181:                       resbuf->h_addrtype = AF_INET6;
  182:                       resbuf->h_length = IN6ADDRSZ;
  183:                     }
  184:                   else
  185:                     {
  186:                       resbuf->h_addrtype = af;
  187:                       resbuf->h_length = addr_size;
  188:                     }
  189:                   if (h_errnop != NULL)
  190:                     *h_errnop = NETDB_SUCCESS;
  191:                   if (buffer_size == NULL)
  192:                     *status = NSS_STATUS_SUCCESS;
  193:                   else
  194:                    *result = resbuf;
  195:                   goto done;
  196:                 }
  197: 
  198:               if (!isdigit (*cp) && *cp != '.')
  199:                 break;
  200:             }
  201:         }
  202: 
  203:       if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':')
  204:         {
  205:           const char *cp;
  206:           char *hostname;
  207:           typedef unsigned char host_addr_t[16];
  208:           host_addr_t *host_addr;
  209:           typedef char *host_addr_list_t[2];
  210:           host_addr_list_t *h_addr_ptrs;
  211:           size_t size_needed;
  212:           int addr_size;
  213: 
  214:           switch (af)
  215:             {
  216:             default:
  217:               af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
  218:               if (af == AF_INET6)
  219:                 {
  220:                   addr_size = IN6ADDRSZ;
  221:                   break;
  222:                 }
  223:               /* FALLTHROUGH */
  224: 
  225:             case AF_INET:
  226:               /* This is not possible.  We cannot represent an IPv6 address
  227:                  in an `struct in_addr' variable.  */
  228:               *h_errnop = HOST_NOT_FOUND;
  229:               *result = NULL;
  230:               goto done;
  231: 
  232:             case AF_INET6:
  233:               addr_size = IN6ADDRSZ;
  234:               break;
  235:             }
  236: 
  237:           size_needed = (sizeof (*host_addr)
  238:                          + sizeof (*h_addr_ptrs) + strlen (name) + 1);
  239: 
  240:           if (buffer_size == NULL && buflen < size_needed)
  241:             {
  242:               if (h_errnop != NULL)
  243:                 *h_errnop = TRY_AGAIN;
  244:               __set_errno (ERANGE);
  245:               goto done;
  246:             }
  247:           else if (buffer_size != NULL && *buffer_size < size_needed)
  248:             {
  249:               char *new_buf;
  250:               *buffer_size = size_needed;
  251:               new_buf = realloc (*buffer, *buffer_size);
  252: 
  253:               if (new_buf == NULL)
  254:                 {
  255:                   save = errno;
  256:                   free (*buffer);
  257:                   __set_errno (save);
  258:                   *buffer = NULL;
  259:                   *buffer_size = 0;
  260:                   *result = NULL;
  261:                   goto done;
  262:                 }
  263:               *buffer = new_buf;
  264:             }
  265: 
  266:           memset (*buffer, '\0', size_needed);
  267: 
  268:           host_addr = (host_addr_t *) *buffer;
  269:           h_addr_ptrs = (host_addr_list_t *)
  270:             ((char *) host_addr + sizeof (*host_addr));
  271:           hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
  272: 
  273:           for (cp = name;; ++cp)
  274:             {
  275:               if (!*cp)
  276:                 {
  277:                   if (*--cp == '.')
  278:                     break;
  279: 
  280:                   /* All-IPv6-legal, no dot at the end. Fake up a
  281:                      hostent as if we'd actually done a lookup.  */
  282:                   if (inet_pton (AF_INET6, name, host_addr) <= 0)
  283:                     {
  284:                       *h_errnop = HOST_NOT_FOUND;
  285:                       if (buffer_size)
  286:                         *result = NULL;
  287:                       goto done;
  288:                     }
  289: 
  290:                   resbuf->h_name = strcpy (hostname, name);
  291:                   h_alias_ptr[0] = NULL;
  292:                   resbuf->h_aliases = h_alias_ptr;
  293:                   (*h_addr_ptrs)[0] = (char *) host_addr;
  294:                   (*h_addr_ptrs)[1] = (char *) 0;
  295:                   resbuf->h_addr_list = *h_addr_ptrs;
  296:                   resbuf->h_addrtype = AF_INET6;
  297:                   resbuf->h_length = addr_size;
  298:                   *h_errnop = NETDB_SUCCESS;
  299:                   if (buffer_size == NULL)
  300:                     *status = NSS_STATUS_SUCCESS;
  301:                   else
  302:                     *result = resbuf;
  303:                   goto done;
  304:                 }
  305: 
  306:               if (!isxdigit (*cp) && *cp != ':' && *cp != '.')
  307:                 break;
  308:             }
  309:         }
  310:     }
  311: 
  312:   return 0;
  313: 
  314: done:
  315:   return 1;
  316: }
  317: libc_hidden_def (__nss_hostname_digits_dots)
Syntax (Markdown)