Back to index

glibc  2.9
nis-network.c
Go to the documentation of this file.
00001 /* Copyright (C) 1996-2003, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <nss.h>
00021 /* The following is an ugly trick to avoid a prototype declaration for
00022    _nss_nis_endgrent.  */
00023 #define _nss_nis_endnetent _nss_nis_endnetent_XXX
00024 #include <netdb.h>
00025 #undef _nss_nis_endnetent
00026 #include <ctype.h>
00027 #include <errno.h>
00028 #include <stdint.h>
00029 #include <string.h>
00030 #include <netinet/in.h>
00031 #include <arpa/inet.h>
00032 #include <bits/libc-lock.h>
00033 #include <rpcsvc/yp.h>
00034 #include <rpcsvc/ypclnt.h>
00035 
00036 #include "nss-nis.h"
00037 
00038 /* Get the declaration of the parser function.  */
00039 #define ENTNAME netent
00040 #define EXTERN_PARSER
00041 #include <nss/nss_files/files-parse.c>
00042 
00043 __libc_lock_define_initialized (static, lock)
00044 
00045 static bool_t new_start = 1;
00046 static char *oldkey;
00047 static int oldkeylen;
00048 
00049 enum nss_status
00050 _nss_nis_setnetent (int stayopen)
00051 {
00052   __libc_lock_lock (lock);
00053 
00054   new_start = 1;
00055   if (oldkey != NULL)
00056     {
00057       free (oldkey);
00058       oldkey = NULL;
00059       oldkeylen = 0;
00060     }
00061 
00062   __libc_lock_unlock (lock);
00063 
00064   return NSS_STATUS_SUCCESS;
00065 }
00066 /* Make _nss_nis_endnetent an alias of _nss_nis_setnetent.  We do this
00067    even though the prototypes don't match.  The argument of setnetent
00068    is not used so this makes no difference.  */
00069 strong_alias (_nss_nis_setnetent, _nss_nis_endnetent)
00070 
00071 static enum nss_status
00072 internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
00073                        int *errnop, int *herrnop)
00074 {
00075   struct parser_data *data = (void *) buffer;
00076 
00077   char *domain;
00078   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00079     return NSS_STATUS_UNAVAIL;
00080 
00081   /* Get the next entry until we found a correct one. */
00082   int parse_res;
00083   do
00084     {
00085       char *result;
00086       char *outkey;
00087       int len;
00088       int keylen;
00089       int yperr;
00090 
00091       if (new_start)
00092         yperr = yp_first (domain, "networks.byname", &outkey, &keylen, &result,
00093                        &len);
00094       else
00095         yperr = yp_next (domain, "networks.byname", oldkey, oldkeylen, &outkey,
00096                       &keylen, &result, &len);
00097 
00098       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00099         {
00100          enum nss_status retval = yperr2nss (yperr);
00101 
00102           if (retval == NSS_STATUS_TRYAGAIN)
00103            {
00104              *herrnop = NETDB_INTERNAL;
00105              *errnop = errno;
00106            }
00107           return retval;
00108         }
00109 
00110       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00111         {
00112           free (result);
00113          *errnop = ERANGE;
00114          *herrnop = NETDB_INTERNAL;
00115           return NSS_STATUS_TRYAGAIN;
00116         }
00117 
00118       char *p = strncpy (buffer, result, len);
00119       buffer[len] = '\0';
00120       while (isspace (*p))
00121         ++p;
00122       free (result);
00123 
00124       parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
00125       if (__builtin_expect (parse_res == -1, 0))
00126        {
00127          free (outkey);
00128          *herrnop = NETDB_INTERNAL;
00129          *errnop = ERANGE;
00130          return NSS_STATUS_TRYAGAIN;
00131        }
00132 
00133       free (oldkey);
00134       oldkey = outkey;
00135       oldkeylen = keylen;
00136       new_start = 0;
00137     }
00138   while (!parse_res);
00139 
00140   return NSS_STATUS_SUCCESS;
00141 }
00142 
00143 enum nss_status
00144 _nss_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
00145                     int *errnop, int *herrnop)
00146 {
00147   enum nss_status status;
00148 
00149   __libc_lock_lock (lock);
00150 
00151   status = internal_nis_getnetent_r (net, buffer, buflen, errnop, herrnop);
00152 
00153   __libc_lock_unlock (lock);
00154 
00155   return status;
00156 }
00157 
00158 enum nss_status
00159 _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
00160                       size_t buflen, int *errnop, int *herrnop)
00161 {
00162   if (name == NULL)
00163     {
00164       *errnop = EINVAL;
00165       *herrnop = NETDB_INTERNAL;
00166       return NSS_STATUS_UNAVAIL;
00167     }
00168 
00169   char *domain;
00170   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00171     return NSS_STATUS_UNAVAIL;
00172 
00173   struct parser_data *data = (void *) buffer;
00174   if (buflen < sizeof *data + 1)
00175     {
00176       *herrnop = NETDB_INTERNAL;
00177       *errnop = ERANGE;
00178       return NSS_STATUS_TRYAGAIN;
00179     }
00180 
00181   /* Convert name to lowercase.  */
00182   size_t namlen = strlen (name);
00183   char name2[namlen + 1];
00184   size_t i;
00185 
00186   for (i = 0; i < namlen; ++i)
00187     name2[i] = _tolower (name[i]);
00188   name2[i] = '\0';
00189 
00190   char *result;
00191   int len;
00192   int yperr = yp_match (domain, "networks.byname", name2, namlen, &result,
00193                      &len);
00194 
00195   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00196     {
00197       enum nss_status retval = yperr2nss (yperr);
00198 
00199       if (retval == NSS_STATUS_TRYAGAIN)
00200        {
00201          *errnop = errno;
00202          *herrnop = NETDB_INTERNAL;
00203        }
00204       return retval;
00205     }
00206 
00207   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00208     {
00209       free (result);
00210       *errnop = ERANGE;
00211       *herrnop = NETDB_INTERNAL;
00212       return NSS_STATUS_TRYAGAIN;
00213     }
00214 
00215   char *p = strncpy (buffer, result, len);
00216   buffer[len] = '\0';
00217   while (isspace (*p))
00218     ++p;
00219   free (result);
00220 
00221   int parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
00222 
00223   if (__builtin_expect (parse_res < 1, 0))
00224     {
00225       *herrnop = NETDB_INTERNAL;
00226       if (parse_res == -1)
00227        return NSS_STATUS_TRYAGAIN;
00228       else
00229        return NSS_STATUS_NOTFOUND;
00230     }
00231   else
00232     return NSS_STATUS_SUCCESS;
00233 }
00234 
00235 enum nss_status
00236 _nss_nis_getnetbyaddr_r (uint32_t addr, int type, struct netent *net,
00237                       char *buffer, size_t buflen, int *errnop,
00238                       int *herrnop)
00239 {
00240   char *domain;
00241   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00242     return NSS_STATUS_UNAVAIL;
00243 
00244   struct in_addr in = inet_makeaddr (addr, 0);
00245   char *buf = inet_ntoa (in);
00246   size_t blen = strlen (buf);
00247 
00248   while (1)
00249     {
00250       char *result;
00251       int len;
00252 
00253       int yperr = yp_match (domain, "networks.byaddr", buf, blen, &result,
00254                          &len);
00255 
00256       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00257          {
00258            enum nss_status retval = yperr2nss (yperr);
00259 
00260            if (retval == NSS_STATUS_NOTFOUND)
00261              {
00262               if (buf[blen - 2] == '.' && buf[blen - 1] == '0')
00263                 {
00264                   /* Try again, but with trailing dot(s)
00265                      removed (one by one) */
00266                   buf[blen - 2] = '\0';
00267                   blen -= 2;
00268                   continue;
00269                 }
00270               else
00271                 return NSS_STATUS_NOTFOUND;
00272              }
00273            else
00274              {
00275               if (retval == NSS_STATUS_TRYAGAIN)
00276                 *errnop = errno;
00277               return retval;
00278              }
00279          }
00280 
00281       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00282        {
00283          free (result);
00284          *errnop = ERANGE;
00285          *herrnop = NETDB_INTERNAL;
00286          return NSS_STATUS_TRYAGAIN;
00287        }
00288 
00289         char *p = strncpy (buffer, result, len);
00290        buffer[len] = '\0';
00291        while (isspace (*p))
00292          ++p;
00293        free (result);
00294 
00295        int parse_res = _nss_files_parse_netent (p, net, (void *) buffer,
00296                                            buflen, errnop);
00297 
00298        if (__builtin_expect (parse_res < 1, 0))
00299          {
00300            *herrnop = NETDB_INTERNAL;
00301            if (parse_res == -1)
00302              return NSS_STATUS_TRYAGAIN;
00303            else
00304              return NSS_STATUS_NOTFOUND;
00305          }
00306        else
00307          return NSS_STATUS_SUCCESS;
00308     }
00309 }