Blame nss/networks.c

Packit 6bd9ab
/*
Packit 6bd9ab
   networks.c - NSS lookup functions for networks database
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2015 Arthur de Jong
Packit 6bd9ab
   Copyright (C) 2010 Symas Corporation
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#include "config.h"
Packit 6bd9ab
Packit 6bd9ab
#include <string.h>
Packit 6bd9ab
#include <errno.h>
Packit 6bd9ab
#include <sys/socket.h>
Packit 6bd9ab
#include <netinet/in.h>
Packit 6bd9ab
#include <arpa/inet.h>
Packit 6bd9ab
Packit 6bd9ab
#include "prototypes.h"
Packit 6bd9ab
#include "common.h"
Packit 6bd9ab
#include "compat/attrs.h"
Packit 6bd9ab
Packit 6bd9ab
/* Redefine some ERROR_OUT macros as we also want to set h_errnop. */
Packit 6bd9ab
Packit 6bd9ab
#undef ERROR_OUT_OPENERROR
Packit 6bd9ab
#define ERROR_OUT_OPENERROR                                                 \
Packit 6bd9ab
  *errnop = ENOENT;                                                         \
Packit 6bd9ab
  *h_errnop = HOST_NOT_FOUND;                                               \
Packit 6bd9ab
  return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
Packit 6bd9ab
Packit 6bd9ab
#undef ERROR_OUT_READERROR
Packit 6bd9ab
#define ERROR_OUT_READERROR(fp)                                             \
Packit 6bd9ab
  (void)tio_close(fp);                                                      \
Packit 6bd9ab
  fp = NULL;                                                                \
Packit 6bd9ab
  *errnop = ENOENT;                                                         \
Packit 6bd9ab
  *h_errnop = NO_RECOVERY;                                                  \
Packit 6bd9ab
  return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
Packit 6bd9ab
#undef ERROR_OUT_BUFERROR
Packit 6bd9ab
#define ERROR_OUT_BUFERROR(fp)                                              \
Packit 6bd9ab
  *errnop = ERANGE;                                                         \
Packit 6bd9ab
  *h_errnop = NETDB_INTERNAL;                                               \
Packit 6bd9ab
  return NSS_STATUS_TRYAGAIN;
Packit 6bd9ab
Packit 6bd9ab
#undef ERROR_OUT_WRITEERROR
Packit 6bd9ab
#define ERROR_OUT_WRITEERROR(fp)                                            \
Packit 6bd9ab
  ERROR_OUT_READERROR(fp)
Packit 6bd9ab
Packit 6bd9ab
/* read a single network entry from the stream, ignoring entries
Packit 6bd9ab
   that are not AF_INET (IPv4), result is stored in result */
Packit 6bd9ab
static nss_status_t read_netent(TFILE *fp, struct netent *result,
Packit 6bd9ab
                                char *buffer, size_t buflen, int *errnop,
Packit 6bd9ab
                                int *h_errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  int32_t tmpint32, tmp2int32, tmp3int32;
Packit 6bd9ab
  int32_t numaddr;
Packit 6bd9ab
  int readaf;
Packit 6bd9ab
  size_t bufptr = 0;
Packit 6bd9ab
  nss_status_t retv = NSS_STATUS_NOTFOUND;
Packit 6bd9ab
  memset(result, 0, sizeof(struct netent));
Packit 6bd9ab
  /* read the network entry */
Packit 6bd9ab
  READ_BUF_STRING(fp, result->n_name);
Packit 6bd9ab
  READ_BUF_STRINGLIST(fp, result->n_aliases);
Packit 6bd9ab
  result->n_addrtype = AF_INET;
Packit 6bd9ab
  /* read number of addresses to follow */
Packit 6bd9ab
  READ_INT32(fp, numaddr);
Packit 6bd9ab
  /* go through the address list and filter on af */
Packit 6bd9ab
  while (--numaddr >= 0)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* read address family and size */
Packit 6bd9ab
    READ_INT32(fp, readaf);
Packit 6bd9ab
    READ_INT32(fp, tmp2int32); /* address length */
Packit 6bd9ab
    if ((readaf == AF_INET) && (tmp2int32 == 4))
Packit 6bd9ab
    {
Packit 6bd9ab
      /* read address and translate to host byte order */
Packit 6bd9ab
      READ_INT32(fp, result->n_net);
Packit 6bd9ab
      /* signal that we've read a proper entry */
Packit 6bd9ab
      retv = NSS_STATUS_SUCCESS;
Packit 6bd9ab
      /* don't return here to not upset the stream */
Packit 6bd9ab
    }
Packit 6bd9ab
    else
Packit 6bd9ab
    {
Packit 6bd9ab
      /* skip unsupported address families */
Packit 6bd9ab
      SKIP(fp, tmpint32);
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  return retv;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* write an address value */
Packit 6bd9ab
/* version 2.10 of glibc changed the address from network to host order
Packit 6bd9ab
   (changelog entry 2009-07-01) */
Packit 6bd9ab
#define WRITE_ADDRESS(fp, addr)                                             \
Packit 6bd9ab
  WRITE_INT32(fp, AF_INET);                                                 \
Packit 6bd9ab
  WRITE_INT32(fp, 4);                                                       \
Packit 6bd9ab
  WRITE_INT32(fp, addr);
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
Packit 6bd9ab
/* get a network entry by name */
Packit 6bd9ab
nss_status_t NSS_NAME(getnetbyname_r)(const char *name,
Packit 6bd9ab
                                      struct netent *result, char *buffer,
Packit 6bd9ab
                                      size_t buflen, int *errnop,
Packit 6bd9ab
                                      int *h_errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETONE(NSLCD_ACTION_NETWORK_BYNAME,
Packit 6bd9ab
             WRITE_STRING(fp, name),
Packit 6bd9ab
             read_netent(fp, result, buffer, buflen, errnop, h_errnop));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* Note: the af parameter is ignored and is assumed to be AF_INET */
Packit 6bd9ab
/* TODO: implement handling of af parameter */
Packit 6bd9ab
nss_status_t NSS_NAME(getnetbyaddr_r)(uint32_t addr, int UNUSED(af),
Packit 6bd9ab
                                      struct netent *result, char *buffer,
Packit 6bd9ab
                                      size_t buflen, int *errnop,
Packit 6bd9ab
                                      int *h_errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETONE(NSLCD_ACTION_NETWORK_BYADDR,
Packit 6bd9ab
             WRITE_ADDRESS(fp, addr),
Packit 6bd9ab
             read_netent(fp, result, buffer, buflen, errnop, h_errnop));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* thread-local file pointer to an ongoing request */
Packit 6bd9ab
static TLS TFILE *netentfp;
Packit 6bd9ab
Packit 6bd9ab
/* start a request to read all networks */
Packit 6bd9ab
nss_status_t NSS_NAME(setnetent)(int UNUSED(stayopen))
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_SETENT(netentfp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* get a single network entry from the stream */
Packit 6bd9ab
nss_status_t NSS_NAME(getnetent_r)(struct netent *result,
Packit 6bd9ab
                                   char *buffer, size_t buflen, int *errnop,
Packit 6bd9ab
                                   int *h_errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETENT(netentfp, NSLCD_ACTION_NETWORK_ALL,
Packit 6bd9ab
             read_netent(netentfp, result, buffer, buflen, errnop, h_errnop));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* close the stream opened by setnetent() above */
Packit 6bd9ab
nss_status_t NSS_NAME(endnetent)(void)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_ENDENT(netentfp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_SOLARIS
Packit 6bd9ab
Packit 6bd9ab
#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
Packit 6bd9ab
static char *netent2str(struct netent *result, char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  int i, res;
Packit 6bd9ab
  struct in_addr priv_in_addr;
Packit 6bd9ab
  priv_in_addr.s_addr = htonl(result->n_net);
Packit 6bd9ab
  res = snprintf(buffer, buflen, "%s %s", result->n_name, inet_ntoa(priv_in_addr));
Packit 6bd9ab
  if ((res < 0) || (res >= (int)buflen))
Packit 6bd9ab
    return NULL;
Packit 6bd9ab
  if (result->n_aliases)
Packit 6bd9ab
    for (i = 0; result->n_aliases[i]; i++)
Packit 6bd9ab
    {
Packit 6bd9ab
      strlcat(buffer, " ", buflen);
Packit 6bd9ab
      strlcat(buffer, result->n_aliases[i], buflen);
Packit 6bd9ab
    }
Packit 6bd9ab
  if (strlen(buffer) >= buflen - 1)
Packit 6bd9ab
    return NULL;
Packit 6bd9ab
  return buffer;
Packit 6bd9ab
}
Packit 6bd9ab
#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
Packit 6bd9ab
{
Packit 6bd9ab
  READ_RESULT(netent, &args->erange, &args->h_errno);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* more of a dirty hack */
Packit 6bd9ab
#define h_errnop (&(NSS_ARGS(args)->h_errno))
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t networks_getnetbyname(nss_backend_t UNUSED(*be), void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETONE(NSLCD_ACTION_NETWORK_BYNAME,
Packit 6bd9ab
             WRITE_STRING(fp, NSS_ARGS(args)->key.name),
Packit 6bd9ab
             read_result(fp, args));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t networks_getnetbyaddr(nss_backend_t UNUSED(*be), void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETONE(NSLCD_ACTION_NETWORK_BYADDR,
Packit 6bd9ab
             WRITE_ADDRESS(fp, NSS_ARGS(args)->key.netaddr.net),
Packit 6bd9ab
             read_result(fp, args));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t networks_setnetent(nss_backend_t *be, void UNUSED(*args))
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_SETENT(LDAP_BE(be)->fp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t networks_getnetent(nss_backend_t *be, void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_NETWORK_ALL,
Packit 6bd9ab
             read_result(LDAP_BE(be)->fp, args));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t networks_endnetent(nss_backend_t *be, void UNUSED(*args))
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_ENDENT(LDAP_BE(be)->fp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_backend_op_t networks_ops[] = {
Packit 6bd9ab
  nss_ldap_destructor,
Packit 6bd9ab
  networks_endnetent,
Packit 6bd9ab
  networks_setnetent,
Packit 6bd9ab
  networks_getnetent,
Packit 6bd9ab
  networks_getnetbyname,
Packit 6bd9ab
  networks_getnetbyaddr
Packit 6bd9ab
};
Packit 6bd9ab
Packit 6bd9ab
nss_backend_t *NSS_NAME(networks_constr)(const char UNUSED(*db_name),
Packit 6bd9ab
                                         const char UNUSED(*src_name),
Packit 6bd9ab
                                         const char UNUSED(*cfg_args))
Packit 6bd9ab
{
Packit 6bd9ab
  return nss_ldap_constructor(networks_ops, sizeof(networks_ops));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
#endif /* NSS_FLAVOUR_SOLARIS */