Back to index

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