Back to index

glibc  2.9
nis-proto.c
Go to the documentation of this file.
00001 /* Copyright (C) 1996-1998, 2000-2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Thorsten Kukuk <kukuk@suse.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 #include <netdb.h>
00022 #include <ctype.h>
00023 #include <errno.h>
00024 #include <string.h>
00025 #include <bits/libc-lock.h>
00026 #include <rpcsvc/yp.h>
00027 #include <rpcsvc/ypclnt.h>
00028 
00029 #include "nss-nis.h"
00030 
00031 /* Get the declaration of the parser function.  */
00032 #define ENTNAME protoent
00033 #define EXTERN_PARSER
00034 #include <nss/nss_files/files-parse.c>
00035 
00036 __libc_lock_define_initialized (static, lock)
00037 
00038 struct response
00039 {
00040   struct response *next;
00041   char val[0];
00042 };
00043 
00044 static struct response *start;
00045 static struct response *next;
00046 
00047 static int
00048 saveit (int instatus, char *inkey, int inkeylen, char *inval,
00049         int invallen, char *indata)
00050 {
00051   if (instatus != YP_TRUE)
00052     return 1;
00053 
00054   if (inkey && inkeylen > 0 && inval && invallen > 0)
00055     {
00056       struct response *newp = malloc (sizeof (struct response) + invallen + 1);
00057       if (newp == NULL)
00058        return 1; /* We have no error code for out of memory */
00059 
00060       if (start == NULL)
00061        start = newp;
00062       else
00063        next->next = newp;
00064       next = newp;
00065 
00066       newp->next = NULL;
00067       *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
00068     }
00069 
00070   return 0;
00071 }
00072 
00073 static void
00074 internal_nis_endprotoent (void)
00075 {
00076   while (start != NULL)
00077     {
00078       next = start;
00079       start = start->next;
00080       free (next);
00081     }
00082 }
00083 
00084 static enum nss_status
00085 internal_nis_setprotoent (void)
00086 {
00087   char *domainname;
00088   struct ypall_callback ypcb;
00089   enum nss_status status;
00090 
00091   yp_get_default_domain (&domainname);
00092 
00093   internal_nis_endprotoent ();
00094 
00095   ypcb.foreach = saveit;
00096   ypcb.data = NULL;
00097   status = yperr2nss (yp_all (domainname, "protocols.bynumber", &ypcb));
00098   next = start;
00099 
00100   return status;
00101 }
00102 
00103 enum nss_status
00104 _nss_nis_setprotoent (int stayopen)
00105 {
00106   enum nss_status status;
00107 
00108   __libc_lock_lock (lock);
00109 
00110   status = internal_nis_setprotoent ();
00111 
00112   __libc_lock_unlock (lock);
00113 
00114   return status;
00115 }
00116 
00117 enum nss_status
00118 _nss_nis_endprotoent (void)
00119 {
00120   __libc_lock_lock (lock);
00121 
00122   internal_nis_endprotoent ();
00123   next = NULL;
00124 
00125   __libc_lock_unlock (lock);
00126 
00127   return NSS_STATUS_SUCCESS;
00128 }
00129 
00130 static enum nss_status
00131 internal_nis_getprotoent_r (struct protoent *proto,
00132                          char *buffer, size_t buflen, int *errnop)
00133 {
00134   struct parser_data *data = (void *) buffer;
00135   int parse_res;
00136 
00137   if (start == NULL)
00138     internal_nis_setprotoent ();
00139 
00140   /* Get the next entry until we found a correct one. */
00141   do
00142     {
00143       char *p;
00144 
00145       if (next == NULL)
00146        return NSS_STATUS_NOTFOUND;
00147 
00148       p = strncpy (buffer, next->val, buflen);
00149 
00150       while (isspace (*p))
00151         ++p;
00152 
00153       parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop);
00154       if (parse_res == -1)
00155         return NSS_STATUS_TRYAGAIN;
00156       next = next->next;
00157     }
00158   while (!parse_res);
00159 
00160   return NSS_STATUS_SUCCESS;
00161 }
00162 
00163 enum nss_status
00164 _nss_nis_getprotoent_r (struct protoent *proto, char *buffer, size_t buflen,
00165                      int *errnop)
00166 {
00167   enum nss_status status;
00168 
00169   __libc_lock_lock (lock);
00170 
00171   status = internal_nis_getprotoent_r (proto, buffer, buflen, errnop);
00172 
00173   __libc_lock_unlock (lock);
00174 
00175   return status;
00176 }
00177 
00178 enum nss_status
00179 _nss_nis_getprotobyname_r (const char *name, struct protoent *proto,
00180                         char *buffer, size_t buflen, int *errnop)
00181 {
00182   if (name == NULL)
00183     {
00184       *errnop = EINVAL;
00185       return NSS_STATUS_UNAVAIL;
00186     }
00187 
00188   char *domain;
00189   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00190     return NSS_STATUS_UNAVAIL;
00191 
00192   char *result;
00193   int len;
00194   int yperr = yp_match (domain, "protocols.byname", name, strlen (name),
00195                      &result, &len);
00196 
00197   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00198     {
00199       enum nss_status retval = yperr2nss (yperr);
00200 
00201       if (retval == NSS_STATUS_TRYAGAIN)
00202        *errnop = errno;
00203       return retval;
00204     }
00205 
00206   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00207     {
00208       free (result);
00209       *errnop = ERANGE;
00210       return NSS_STATUS_TRYAGAIN;
00211     }
00212 
00213   char *p = strncpy (buffer, result, len);
00214   buffer[len] = '\0';
00215   while (isspace (*p))
00216     ++p;
00217   free (result);
00218 
00219   int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
00220                                         errnop);
00221   if (__builtin_expect (parse_res < 1, 0))
00222     {
00223       if (parse_res == -1)
00224        return NSS_STATUS_TRYAGAIN;
00225       else
00226        return NSS_STATUS_NOTFOUND;
00227     }
00228   return NSS_STATUS_SUCCESS;
00229 }
00230 
00231 enum nss_status
00232 _nss_nis_getprotobynumber_r (int number, struct protoent *proto,
00233                           char *buffer, size_t buflen, int *errnop)
00234 {
00235   char *domain;
00236   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00237     return NSS_STATUS_UNAVAIL;
00238 
00239   char buf[32];
00240   int nlen = snprintf (buf, sizeof (buf), "%d", number);
00241 
00242   char *result;
00243   int len;
00244   int yperr = yp_match (domain, "protocols.bynumber", buf, nlen, &result,
00245                      &len);
00246 
00247   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00248     {
00249       enum nss_status retval = yperr2nss (yperr);
00250 
00251       if (retval == NSS_STATUS_TRYAGAIN)
00252        *errnop = errno;
00253       return retval;
00254     }
00255 
00256   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00257     {
00258       free (result);
00259       *errnop = ERANGE;
00260       return NSS_STATUS_TRYAGAIN;
00261     }
00262 
00263   char *p = strncpy (buffer, result, len);
00264   buffer[len] = '\0';
00265   while (isspace (*p))
00266     ++p;
00267   free (result);
00268 
00269   int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
00270                                         errnop);
00271   if (__builtin_expect (parse_res < 1, 0))
00272     {
00273       if (parse_res == -1)
00274        return NSS_STATUS_TRYAGAIN;
00275       else
00276        return NSS_STATUS_NOTFOUND;
00277     }
00278   return NSS_STATUS_SUCCESS;
00279 }