root/usr/src/lib/nsswitch/nis/common/getnetent.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
/*
 *      nis/getnetent.c -- "nis" backend for nsswitch "networks" database
 */

#include "nis_common.h"
#include <synch.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

static int nettoa(int anet, char *buf, int buflen, char **pnull);

static nss_status_t
getbyname(be, a)
        nis_backend_ptr_t       be;
        void                    *a;
{
        nss_XbyY_args_t         *argp = (nss_XbyY_args_t *)a;

        return (_nss_nis_lookup(be, argp, 1, "networks.byname",
                argp->key.name, 0));
}

static nss_status_t
getbyaddr(be, a)
        nis_backend_ptr_t       be;
        void                    *a;
{
        nss_XbyY_args_t         *argp = (nss_XbyY_args_t *)a;
        char                    addrstr[16];
        char                    *pnull;
        nss_status_t            rc;

        if (nettoa((int)argp->key.netaddr.net, addrstr, 16, &pnull) != 0)
                return (NSS_UNAVAIL);   /* it's really ENOMEM */
        rc = _nss_nis_lookup(be, argp, 1, "networks.byaddr", addrstr, 0);

        /*
         * if not found, try again with the untruncated address string
         * that has the trailing zero(s)
         */
        if (rc == NSS_NOTFOUND && pnull != NULL) {
                *pnull = '.';
                rc = _nss_nis_lookup(be, argp, 1, "networks.byaddr",
                        addrstr, 0);
        }
        return (rc);
}

static nis_backend_op_t net_ops[] = {
        _nss_nis_destr,
        _nss_nis_endent,
        _nss_nis_setent,
        _nss_nis_getent_netdb,
        getbyname,
        getbyaddr
};

/*ARGSUSED*/
nss_backend_t *
_nss_nis_networks_constr(dummy1, dummy2, dummy3)
        const char      *dummy1, *dummy2, *dummy3;
{
        return (_nss_nis_constr(net_ops,
                                sizeof (net_ops) / sizeof (net_ops[0]),
                                "networks.byaddr"));
}

/*
 * Takes an unsigned integer in host order, and returns a printable
 * string for it as a network number.  To allow for the possibility of
 * naming subnets, only trailing dot-zeros are truncated. The location
 * where the string is truncated (or set to '\0') is returned in *pnull.
 */
static int
nettoa(int anet, char *buf, int buflen, char **pnull)
{
        char *p;
        struct in_addr in;
        int addr;

        *pnull = NULL;

        if (buf == 0)
                return (1);
        in = inet_makeaddr(anet, INADDR_ANY);
        addr = in.s_addr;
        (void) strncpy(buf, inet_ntoa(in), buflen);
        if ((IN_CLASSA_HOST & htonl(addr)) == 0) {
                p = strchr(buf, '.');
                if (p == NULL)
                        return (1);
                *p = 0;
                *pnull = p;
        } else if ((IN_CLASSB_HOST & htonl(addr)) == 0) {
                p = strchr(buf, '.');
                if (p == NULL)
                        return (1);
                p = strchr(p+1, '.');
                if (p == NULL)
                        return (1);
                *p = 0;
                *pnull = p;
        } else if ((IN_CLASSC_HOST & htonl(addr)) == 0) {
                p = strrchr(buf, '.');
                if (p == NULL)
                        return (1);
                *p = 0;
                *pnull = p;
        }
        return (0);
}