Back to index

glibc  2.9
nis-rpc.c
Go to the documentation of this file.
00001 /* Copyright (C) 1996-1998,2000,2002,2003,2004,2006
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <nss.h>
00022 #include <netdb.h>
00023 #include <ctype.h>
00024 #include <errno.h>
00025 #include <string.h>
00026 #include <bits/libc-lock.h>
00027 #include <rpcsvc/yp.h>
00028 #include <rpcsvc/ypclnt.h>
00029 
00030 #include "nss-nis.h"
00031 
00032 /* Get the declaration of the parser function.  */
00033 #define ENTNAME rpcent
00034 #define EXTERN_PARSER
00035 #include <nss/nss_files/files-parse.c>
00036 
00037 __libc_lock_define_initialized (static, lock)
00038 
00039 static intern_t intern;
00040 
00041 
00042 static void
00043 internal_nis_endrpcent (intern_t *intern)
00044 {
00045   struct response_t *curr = intern->next;
00046 
00047   while (curr != NULL)
00048     {
00049       struct response_t *last = curr;
00050       curr = curr->next;
00051       free (last);
00052     }
00053 
00054   intern->next = intern->start = NULL;
00055 }
00056 
00057 static enum nss_status
00058 internal_nis_setrpcent (intern_t *intern)
00059 {
00060   char *domainname;
00061   struct ypall_callback ypcb;
00062   enum nss_status status;
00063 
00064   if (yp_get_default_domain (&domainname))
00065     return NSS_STATUS_UNAVAIL;
00066 
00067   internal_nis_endrpcent (intern);
00068 
00069   ypcb.foreach = _nis_saveit;
00070   ypcb.data = (char *) intern;
00071   status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
00072 
00073   /* Mark the last buffer as full.  */
00074   if (intern->next != NULL)
00075     intern->next->size = intern->offset;
00076 
00077   intern->next = intern->start;
00078   intern->offset = 0;
00079 
00080   return status;
00081 }
00082 
00083 enum nss_status
00084 _nss_nis_setrpcent (int stayopen)
00085 {
00086   enum nss_status status;
00087 
00088   __libc_lock_lock (lock);
00089 
00090   status = internal_nis_setrpcent (&intern);
00091 
00092   __libc_lock_unlock (lock);
00093 
00094   return status;
00095 }
00096 
00097 enum nss_status
00098 _nss_nis_endrpcent (void)
00099 {
00100   __libc_lock_lock (lock);
00101 
00102   internal_nis_endrpcent (&intern);
00103 
00104   __libc_lock_unlock (lock);
00105 
00106   return NSS_STATUS_SUCCESS;
00107 }
00108 
00109 static enum nss_status
00110 internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
00111                        int *errnop, intern_t *intern)
00112 {
00113   struct parser_data *pdata = (void *) buffer;
00114   int parse_res;
00115   char *p;
00116 
00117   if (intern->start == NULL)
00118     internal_nis_setrpcent (intern);
00119 
00120   if (intern->next == NULL)
00121     /* Not one entry in the map.  */
00122     return NSS_STATUS_NOTFOUND;
00123 
00124   /* Get the next entry until we found a correct one. */
00125   do
00126     {
00127       struct response_t *bucket = intern->next;
00128 
00129       if (__builtin_expect (intern->offset >= bucket->size, 0))
00130        {
00131          if (bucket->next == NULL)
00132            return NSS_STATUS_NOTFOUND;
00133 
00134          /* We look at all the content in the current bucket.  Go on
00135             to the next.  */
00136          bucket = intern->next = bucket->next;
00137          intern->offset = 0;
00138        }
00139 
00140       for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
00141         ++intern->offset;
00142 
00143       size_t len = strlen (p) + 1;
00144       if (__builtin_expect (len > buflen, 0))
00145        {
00146          *errnop = ERANGE;
00147          return NSS_STATUS_TRYAGAIN;
00148        }
00149 
00150       /* We unfortunately have to copy the data in the user-provided
00151         buffer because that buffer might be around for a very long
00152         time and the servent structure must remain valid.  If we would
00153         rely on the BUCKET memory the next 'setservent' or 'endservent'
00154         call would destroy it.
00155 
00156         The important thing is that it is a single NUL-terminated
00157         string.  This is what the parsing routine expects.  */
00158       p = memcpy (buffer, &bucket->mem[intern->offset], len);
00159 
00160       parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
00161       if (__builtin_expect (parse_res == -1, 0))
00162        return NSS_STATUS_TRYAGAIN;
00163 
00164       intern->offset += len;
00165     }
00166   while (!parse_res);
00167 
00168   return NSS_STATUS_SUCCESS;
00169 }
00170 
00171 enum nss_status
00172 _nss_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
00173                     int *errnop)
00174 {
00175   enum nss_status status;
00176 
00177   __libc_lock_lock (lock);
00178 
00179   status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop, &intern);
00180 
00181   __libc_lock_unlock (lock);
00182 
00183   return status;
00184 }
00185 
00186 enum nss_status
00187 _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
00188                       char *buffer, size_t buflen, int *errnop)
00189 {
00190   if (name == NULL)
00191     {
00192       *errnop = EINVAL;
00193       return NSS_STATUS_UNAVAIL;
00194     }
00195 
00196   intern_t data = { NULL, NULL, 0 };
00197   enum nss_status status = internal_nis_setrpcent (&data);
00198   if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0))
00199     return status;
00200 
00201   int found = 0;
00202   while (!found &&
00203          ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop,
00204                                          &data)) == NSS_STATUS_SUCCESS))
00205     {
00206       if (strcmp (rpc->r_name, name) == 0)
00207        found = 1;
00208       else
00209        {
00210          int i = 0;
00211 
00212          while (rpc->r_aliases[i] != NULL)
00213            {
00214              if (strcmp (rpc->r_aliases[i], name) == 0)
00215               {
00216                 found = 1;
00217                 break;
00218               }
00219              else
00220               ++i;
00221            }
00222        }
00223     }
00224 
00225   internal_nis_endrpcent (&data);
00226 
00227   if (__builtin_expect (!found && status == NSS_STATUS_SUCCESS, 0))
00228     return NSS_STATUS_NOTFOUND;
00229 
00230   return status;
00231 }
00232 
00233 enum nss_status
00234 _nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc,
00235                         char *buffer, size_t buflen, int *errnop)
00236 {
00237   char *domain;
00238   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00239     return NSS_STATUS_UNAVAIL;
00240 
00241   char buf[32];
00242   int nlen = snprintf (buf, sizeof (buf), "%d", number);
00243 
00244   char *result;
00245   int len;
00246   int yperr = yp_match (domain, "rpc.bynumber", buf, nlen, &result, &len);
00247 
00248   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00249     {
00250       enum nss_status retval = yperr2nss (yperr);
00251 
00252       if (retval == NSS_STATUS_TRYAGAIN)
00253        *errnop = errno;
00254       return retval;
00255     }
00256 
00257   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00258     {
00259       free (result);
00260       *errnop = ERANGE;
00261       return NSS_STATUS_TRYAGAIN;
00262     }
00263 
00264   char *p = strncpy (buffer, result, len);
00265   buffer[len] = '\0';
00266   while (isspace (*p))
00267     ++p;
00268   free (result);
00269 
00270   int parse_res = _nss_files_parse_rpcent (p, rpc, (void  *) buffer, buflen,
00271                                       errnop);
00272   if (__builtin_expect (parse_res < 1, 0))
00273     {
00274       if (parse_res == -1)
00275        return NSS_STATUS_TRYAGAIN;
00276       else
00277        return NSS_STATUS_NOTFOUND;
00278     }
00279   else
00280     return NSS_STATUS_SUCCESS;
00281 }