1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A/*
2N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
1N/A */
1N/A
1N/A
1N/A#include <stdio.h>
1N/A#include <stdlib.h>
1N/A#include <libintl.h>
1N/A#include <strings.h>
1N/A#include <locale.h>
1N/A#include <syslog.h>
1N/A
1N/A#include "standalone.h"
1N/A
1N/Aextern char *set_filter(char **, char *, char **);
1N/Aextern char *set_filter_publickey(char **, char *, int, char **);
1N/Aextern void _printResult(ns_ldap_result_t *);
1N/Aextern void printMapping();
1N/A
1N/Aint listflag = 0;
1N/A
1N/A
1N/A
1N/Astatic struct database_t {
1N/A const char *database;
1N/A const char *sortattr;
1N/A}databaselist[] = {
1N/A { NS_LDAP_TYPE_HOSTS, "cn" },
1N/A { NS_LDAP_TYPE_IPNODES, "cn" },
1N/A { NS_LDAP_TYPE_RPC, "cn" },
1N/A { NS_LDAP_TYPE_PROTOCOLS, "cn" },
1N/A { NS_LDAP_TYPE_NETWORKS, "ipnetworknumber" },
1N/A { NS_LDAP_TYPE_SERVICES, "cn" },
1N/A { NS_LDAP_TYPE_GROUP, "gidnumber" },
1N/A { NS_LDAP_TYPE_NETMASKS, "ipnetworknumber"},
1N/A { NS_LDAP_TYPE_ETHERS, "cn" },
1N/A { NS_LDAP_TYPE_NETGROUP, "cn" },
1N/A { NS_LDAP_TYPE_BOOTPARAMS, "cn" },
1N/A { NS_LDAP_TYPE_PUBLICKEY, "cn" },
1N/A { NS_LDAP_TYPE_PASSWD, "uid" },
1N/A { NS_LDAP_TYPE_SHADOW, "uid" },
1N/A { NS_LDAP_TYPE_ALIASES, "cn" },
1N/A { NS_LDAP_TYPE_AUTOMOUNT, "automountKey" },
1N/A { NS_LDAP_TYPE_USERATTR, "uid" },
1N/A { NS_LDAP_TYPE_PROFILE, "cn" },
1N/A { NS_LDAP_TYPE_EXECATTR, "cn" },
1N/A { NS_LDAP_TYPE_AUTHATTR, "cn" },
1N/A { NS_LDAP_TYPE_AUUSER, "uid" },
1N/A { NS_LDAP_TYPE_TNRHDB, "ipTnetNumber" },
1N/A { NS_LDAP_TYPE_TNRHTP, "ipTnetTemplateName" },
1N/A { NS_LDAP_TYPE_PROJECT, "SolarisProjectName" },
1N/A { 0, 0 }
1N/A};
1N/A
1N/A
1N/Avoid
1N/Ausage(char *msg) {
1N/A if (msg)
1N/A (void) fprintf(stderr, "%s\n", msg);
1N/A
1N/A (void) fprintf(stderr,
1N/A gettext(
1N/A "\n"
1N/A "usage: ldaplist [-dlv] [-h LDAP_server[:serverPort] [-M domainName]\n"
1N/A "[-N profileName] [-a authenticationMethod] [-P certifPath]\n"
1N/A "[-D bindDN] [-w bindPassword] [-j passwdFile]]\n"
1N/A "[<database> [<key>] ...]\n\n"
1N/A "usage: ldaplist -h\n"
1N/A "\n"
1N/A "usage: ldaplist -g\n\n"
1N/A "\tOptions:\n"
1N/A "\t -l list all the attributes found in entry.\n"
1N/A "\t By default, it lists only the DNs.\n"
1N/A "\t -d list attributes for the database instead of its entries\n"
1N/A "\t -v print out the LDAP search filter.\n"
1N/A "\t -g list the database mappings.\n"
1N/A "\t -h An address (or a name) and a port of the LDAP server in\n"
1N/A "\t which the entries will be stored. The default value for\n"
1N/A "\t the port is 389 (or 636 for TLS connections).\n"
1N/A "\t -M The name of a domain served by the specified server.\n"
1N/A "\t If not specified, the default domain name will be used.\n"
1N/A "\t -N Specifies a DUAProfile name.\n"
1N/A "\t The default value is \"default\".\n"
1N/A "\t -a Specifies an authentication method.\n"
1N/A "\t -P The certificate path for the location of the certificate\n"
1N/A "\t database.\n"
1N/A "\t -D Specifies an entry which has read permission to\n"
1N/A "\t the requested database.\n"
1N/A "\t -w Password to be used for authenticating the bindDN.\n"
1N/A "\t -j File containing the password for bindDN or SSL key db.\n"
1N/A "\t<database> is the database to be searched in. Standard system\n"
1N/A "\tdatabases are:\n"
1N/A "\t\tpassword, printers, group, hosts, ethers, networks, netmasks,\n"
1N/A "\t\trpc, bootparams, protocols, services, netgroup, auto_*.\n"
1N/A "\tNon-standard system databases can be specified as follows:\n"
1N/A "\t\tby specific container: ou=<dbname> or\n"
1N/A "\t\tby default container: <dbname>. In this case, 'nismapname'\n"
1N/A "\t\twill be used, thus mapping this to nismapname=<dbname>.\n"
1N/A "\t<key> is the key to search in the database. For the standard\n"
1N/A "\tdatabases, the search type for the key is predefined. You can\n"
1N/A "\toverride this by specifying <type>=<key>.\n"
1N/A "\nNOTE: The old -h option printing the mapping information is "
1N/A "deprecated.\nFor backward compatibility the following mode is "
1N/A "available:\nldaplist -h\n"));
1N/A exit(1);
1N/A}
1N/A
1N/A/*
1N/A * This function has been copied from lib/libsldap/common/ns_getalias.c
1N/A * and had some DEBUG statemants added.
1N/A *
1N/A * This function builds a new string, as identified by realfilter, by
1N/A * replacing the first occurrence of '%s' in userdata with the string
1N/A * filter provided in the Service Search Descriptor (SSD).
1N/A *
1N/A * It is used as a call back function by __ns_ldap_list() API.
1N/A *
1N/A * As an example, lets assume the caller of __ns_ldap_list() is
1N/A * accessing password information. The userdata filter would previously
1N/A * have been constructed to contain "(&(%s)(userid=fred))". And the SSD
1N/A * filter consists of "dept=sds". The new filter would result in
1N/A * "(&(dept=sds)(userid=fred))".
1N/A */
1N/Astatic int
1N/Amerge_SSD_filter(const ns_ldap_search_desc_t *desc,
1N/A char **realfilter,
1N/A const void *userdata)
1N/A{
1N/A int filterlen;
1N/A int merged = 0;
1N/A char *realfilterp;
1N/A char *userdatap = (char *)userdata;
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stdout, "\n[ldaplist.c: merge_SSD_filter]\n");
1N/A#endif /* DEBUG */
1N/A
1N/A /* sanity check */
1N/A if (realfilter == NULL)
1N/A return (NS_LDAP_INVALID_PARAM);
1N/A *realfilter = NULL;
1N/A
1N/A if (desc == NULL || desc->filter == NULL || userdata == NULL)
1N/A return (NS_LDAP_INVALID_PARAM);
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata);
1N/A (void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter);
1N/A#endif /* DEBUG */
1N/A
1N/A filterlen = strlen(desc->filter);
1N/A *realfilter = (char *)malloc(strlen(userdata) + filterlen + 1);
1N/A if (*realfilter == NULL)
1N/A return (NS_LDAP_MEMORY);
1N/A
1N/A realfilterp = *realfilter;
1N/A while (*userdatap != '\0') {
1N/A if (!merged && *userdatap == '%' && *(userdatap + 1) == 's') {
1N/A userdatap += 2; /* step over "%s" */
1N/A (void) memcpy(realfilterp, desc->filter, filterlen);
1N/A realfilterp += filterlen;
1N/A merged = 1; /* Continue to copy rest of userdata only */
1N/A } else {
1N/A *realfilterp++ = *userdatap++; /* Copy and advance */
1N/A }
1N/A }
1N/A *realfilterp = '\0';
1N/A
1N/A#ifdef DEBUG
1N/A (void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter);
1N/A#endif /* DEBUG */
1N/A
1N/A return (NS_LDAP_SUCCESS);
1N/A}
1N/A
1N/A/* returns 0=success, 1=error */
1N/Aint
1N/Alist(char *database, char *ldapfilter, char **ldapattribute,
1N/Achar **err, char *userdata)
1N/A{
1N/A ns_ldap_result_t *result;
1N/A ns_ldap_error_t *errorp;
1N/A int rc;
1N/A char buf[500];
1N/A const char *sort = NULL;
1N/A int i;
1N/A
1N/A if (database) {
1N/A for (i = 0; databaselist[i].database; i++) {
1N/A if (strcmp(databaselist[i].database, database) == 0) {
1N/A sort = databaselist[i].sortattr;
1N/A break;
1N/A }
1N/A if (strcmp(databaselist[i].database,
1N/A NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
1N/A strncmp(database, NS_LDAP_TYPE_AUTOMOUNT,
1N/A sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
1N/A sort = databaselist[i].sortattr;
1N/A break;
1N/A }
1N/A }
1N/A }
1N/A
1N/A *err = NULL;
1N/A buf[0] = '\0';
1N/A rc = __ns_ldap_list_sort(database, (const char *)ldapfilter,
1N/A sort, merge_SSD_filter, (const char **)ldapattribute, NULL,
1N/A /* Binary data should be BASE64 encoded and tagged. */
1N/A listflag | NS_LDAP_BASE64_BINARY_ATTR_VALUE,
1N/A &result, &errorp, NULL, userdata);
1N/A if (rc != NS_LDAP_SUCCESS) {
1N/A char *p;
1N/A (void) __ns_ldap_err2str(rc, &p);
1N/A if (errorp && errorp->message) {
1N/A (void) snprintf(buf, sizeof (buf), "%s (%s)",
1N/A p, errorp->message);
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A } else
1N/A (void) snprintf(buf, sizeof (buf), "%s\n", p);
1N/A *err = strdup(buf);
1N/A return (rc);
1N/A }
1N/A
1N/A _printResult(result);
1N/A (void) __ns_ldap_freeResult(&result);
1N/A return (0);
1N/A}
1N/A
1N/A
1N/Aint
1N/Aswitch_err(int rc)
1N/A{
1N/A switch (rc) {
1N/A case NS_LDAP_SUCCESS:
1N/A return (0);
1N/A case NS_LDAP_NOTFOUND:
1N/A return (1);
1N/A }
1N/A return (2);
1N/A}
1N/A
1N/Aint
1N/Amain(int argc, char **argv)
1N/A{
1N/A
1N/A extern int optind;
1N/A char *database = NULL;
1N/A char *ldapfilter = NULL;
1N/A char *attribute = "dn";
1N/A char **key = NULL;
1N/A char **ldapattribute = NULL;
1N/A char *buffer[100];
1N/A char *err = NULL;
1N/A char *p;
1N/A int index = 1;
1N/A int c;
1N/A int rc;
1N/A int verbose = 0;
1N/A char *udata = NULL;
1N/A
1N/A ns_standalone_conf_t standalone_cfg = standaloneDefaults;
1N/A ns_ldap_error_t *errorp = NULL;
1N/A char *authmech = NULL;
1N/A ns_auth_t auth = {NS_LDAP_AUTH_NONE,
1N/A NS_LDAP_TLS_NONE,
1N/A NS_LDAP_SASL_NONE,
1N/A NS_LDAP_SASLOPT_NONE};
1N/A
1N/A (void) setlocale(LC_ALL, "");
1N/A (void) textdomain(TEXT_DOMAIN);
1N/A
1N/A openlog("ldaplist", LOG_PID, LOG_USER);
1N/A
1N/A if (argc == 2 &&
1N/A strlen(argv[1]) == 2 && strncmp(argv[1], "-h", 2) == 0) {
1N/A /* preserve backwards compatibility, support old -h option */
1N/A (void) printMapping();
1N/A exit(0);
1N/A }
1N/A
1N/A while ((c = getopt(argc, argv, "h:M:N:P:r:a:D:w:j:dgvl")) != EOF) {
1N/A switch (c) {
1N/A case 'd':
1N/A listflag |= NS_LDAP_SCOPE_BASE;
1N/A break;
1N/A case 'g':
1N/A (void) printMapping();
1N/A exit(0);
1N/A break; /* Never reached */
1N/A case 'l':
1N/A attribute = "NULL";
1N/A break;
1N/A case 'v':
1N/A verbose = 1;
1N/A break;
1N/A case 'M':
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_DOMAIN = optarg;
1N/A break;
1N/A case 'h':
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A if (separatePort(optarg,
1N/A &standalone_cfg.SA_SERVER,
1N/A &standalone_cfg.SA_PORT) > 0) {
1N/A exit(1);
1N/A }
1N/A break;
1N/A case 'P':
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_CERT_PATH = optarg;
1N/A break;
1N/A case 'N':
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_PROFILE_NAME = optarg;
1N/A break;
1N/A case 'D':
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_BIND_DN = strdup(optarg);
1N/A break;
1N/A case 'w':
1N/A if (standalone_cfg.SA_BIND_PWD != NULL) {
1N/A (void) fprintf(stderr,
1N/A gettext("The -w option is mutually "
1N/A "exclusive of -j. -w is ignored.\n"));
1N/A break;
1N/A }
1N/A
1N/A if (optarg != NULL &&
1N/A optarg[0] == '-' && optarg[1] == '\0') {
1N/A /* Ask for a password later */
1N/A break;
1N/A }
1N/A
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_BIND_PWD = strdup(optarg);
1N/A break;
1N/A case 'j':
1N/A if (standalone_cfg.SA_BIND_PWD != NULL) {
1N/A (void) fprintf(stderr,
1N/A gettext("The -w option is mutually "
1N/A "exclusive of -j. -w is ignored.\n"));
1N/A free(standalone_cfg.SA_BIND_PWD);
1N/A }
1N/A standalone_cfg.type = NS_LDAP_SERVER;
1N/A standalone_cfg.SA_BIND_PWD = readPwd(optarg);
1N/A if (standalone_cfg.SA_BIND_PWD == NULL) {
1N/A exit(1);
1N/A }
1N/A break;
1N/A case 'a':
1N/A authmech = optarg;
1N/A break;
1N/A default:
1N/A usage(gettext("Invalid option"));
1N/A }
1N/A }
1N/A
1N/A if (standalone_cfg.type == NS_LDAP_SERVER &&
1N/A standalone_cfg.SA_SERVER == NULL) {
1N/A (void) fprintf(stderr,
1N/A gettext("Please specify an LDAP server you want "
1N/A "to connect to. \n"));
1N/A exit(1);
1N/A }
1N/A
1N/A if ((c = argc - optind) > 0)
1N/A database = argv[optind++];
1N/A if ((--c) > 0)
1N/A key = &argv[optind];
1N/A
1N/A if (authmech != NULL) {
1N/A if (__ns_ldap_initAuth(authmech,
1N/A &auth,
1N/A &errorp) != NS_LDAP_SUCCESS) {
1N/A if (errorp) {
1N/A (void) fprintf(stderr, "%s", errorp->message);
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A }
1N/A exit(1);
1N/A }
1N/A }
1N/A
1N/A if (auth.saslmech != NS_LDAP_SASL_GSSAPI &&
1N/A standalone_cfg.SA_BIND_DN != NULL &&
1N/A standalone_cfg.SA_BIND_PWD == NULL) {
1N/A /* If password is not specified, then prompt user for it. */
1N/A standalone_cfg.SA_BIND_PWD =
1N/A strdup(getpassphrase("Enter password:"));
1N/A }
1N/A
1N/A standalone_cfg.SA_AUTH = (authmech == NULL) ? NULL : &auth;
1N/A
1N/A if (__ns_ldap_initStandalone(&standalone_cfg,
1N/A &errorp) != NS_LDAP_SUCCESS) {
1N/A if (errorp) {
1N/A (void) fprintf(stderr, "%s\n", errorp->message);
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A }
1N/A exit(1);
1N/A }
1N/A
1N/A if (authmech != NULL) {
1N/A if (__ns_ldap_setParam(NS_LDAP_AUTH_P,
1N/A authmech, &errorp) != NS_LDAP_SUCCESS) {
1N/A __ns_ldap_cancelStandalone();
1N/A if (errorp != NULL) {
1N/A (void) fprintf(stderr, "%s", errorp->message);
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A }
1N/A exit(1);
1N/A }
1N/A }
1N/A if (standalone_cfg.SA_CRED != NULL) {
1N/A if (__ns_ldap_setParam(NS_LDAP_CREDENTIAL_LEVEL_P,
1N/A standalone_cfg.SA_CRED, &errorp) != NS_LDAP_SUCCESS) {
1N/A __ns_ldap_cancelStandalone();
1N/A if (errorp != NULL) {
1N/A (void) fprintf(stderr, "%s", errorp->message);
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A }
1N/A exit(1);
1N/A }
1N/A }
1N/A
1N/A if (standalone_cfg.type != NS_CACHEMGR &&
1N/A standalone_cfg.SA_BIND_DN != NULL) {
1N/A ns_auth_t **authpp = NULL, **authp = NULL;
1N/A
1N/A if (__ns_ldap_getParam(NS_LDAP_AUTH_P,
1N/A (void ***)&authpp,
1N/A &errorp) != NS_LDAP_SUCCESS || authpp == NULL) {
1N/A __ns_ldap_cancelStandalone();
1N/A (void) __ns_ldap_freeParam((void ***)&authpp);
1N/A if (errorp) {
1N/A (void) fprintf(stderr,
1N/A gettext(errorp->message));
1N/A (void) __ns_ldap_freeError(&errorp);
1N/A }
1N/A exit(1);
1N/A }
1N/A for (authp = authpp; *authp; authp++) {
1N/A if ((*authp)->saslmech == NS_LDAP_SASL_GSSAPI) {
1N/A /*
1N/A * For now we have no use for bindDN and
1N/A * bindPassword when using SASL/GSSAPI.
1N/A */
1N/A (void) fprintf(stderr,
1N/A gettext("Warning: SASL/GSSAPI will be "
1N/A "used as an authentication method"
1N/A "The bind DN and password will "
1N/A "be ignored.\n"));
1N/A break;
1N/A }
1N/A }
1N/A }
1N/A
1N/A /*
1N/A * If dumpping a database,
1N/A * or all the containers,
1N/A * use page control just
1N/A * in case there are too many entries
1N/A */
1N/A if (!key && !(listflag & NS_LDAP_SCOPE_BASE))
1N/A listflag |= NS_LDAP_PAGE_CTRL;
1N/A
1N/A /* build the attribute array */
1N/A if (strncasecmp(attribute, "NULL", 4) == 0)
1N/A ldapattribute = NULL;
1N/A else {
1N/A buffer[0] = strdup(attribute);
1N/A while ((p = strchr(attribute, ',')) != NULL) {
1N/A buffer[index++] = attribute = p + 1;
1N/A *p = '\0';
1N/A }
1N/A buffer[index] = NULL;
1N/A ldapattribute = buffer;
1N/A }
1N/A
1N/A /* build the filter */
1N/A if (database && (strcasecmp(database, "publickey") == NULL)) {
1N/A /* user publickey lookup */
1N/A char *err1 = NULL;
1N/A int rc1;
1N/A
1N/A rc = rc1 = -1;
1N/A ldapfilter = set_filter_publickey(key, database, 0, &udata);
1N/A if (ldapfilter) {
1N/A if (verbose) {
1N/A (void) fprintf(stdout,
1N/A gettext("+++ database=%s\n"),
1N/A (database ? database : "NULL"));
1N/A (void) fprintf(stdout,
1N/A gettext("+++ filter=%s\n"),
1N/A (ldapfilter ? ldapfilter : "NULL"));
1N/A (void) fprintf(stdout,
1N/A gettext("+++ template for merging"
1N/A "SSD filter=%s\n"),
1N/A (udata ? udata : "NULL"));
1N/A }
1N/A rc = list("passwd", ldapfilter, ldapattribute,
1N/A &err, udata);
1N/A free(ldapfilter);
1N/A free(udata);
1N/A }
1N/A /* hosts publickey lookup */
1N/A ldapfilter = set_filter_publickey(key, database, 1, &udata);
1N/A if (ldapfilter) {
1N/A if (verbose) {
1N/A (void) fprintf(stdout,
1N/A gettext("+++ database=%s\n"),
1N/A (database ? database : "NULL"));
1N/A (void) fprintf(stdout,
1N/A gettext("+++ filter=%s\n"),
1N/A (ldapfilter ? ldapfilter : "NULL"));
1N/A (void) fprintf(stdout,
1N/A gettext("+++ template for merging"
1N/A "SSD filter=%s\n"),
1N/A (udata ? udata : "NULL"));
1N/A }
1N/A rc1 = list("hosts", ldapfilter, ldapattribute,
1N/A &err1, udata);
1N/A free(ldapfilter);
1N/A free(udata);
1N/A }
1N/A if (rc == -1 && rc1 == -1) {
1N/A /* this should never happen */
1N/A (void) fprintf(stderr,
1N/A gettext("ldaplist: invalid publickey lookup\n"));
1N/A rc = 2;
1N/A } else if (rc != 0 && rc1 != 0) {
1N/A (void) fprintf(stderr,
1N/A gettext("ldaplist: %s\n"), (err ? err : err1));
1N/A if (rc == -1)
1N/A rc = rc1;
1N/A } else
1N/A rc = 0;
1N/A exit(switch_err(rc));
1N/A }
1N/A
1N/A /*
1N/A * we set the search filter to (objectclass=*) when we want
1N/A * to list the directory attribute instead of the entries
1N/A * (the -d option).
1N/A */
1N/A if (((ldapfilter = set_filter(key, database, &udata)) == NULL) ||
1N/A (listflag == NS_LDAP_SCOPE_BASE)) {
1N/A ldapfilter = strdup("objectclass=*");
1N/A udata = strdup("%s");
1N/A }
1N/A
1N/A if (verbose) {
1N/A (void) fprintf(stdout, gettext("+++ database=%s\n"),
1N/A (database ? database : "NULL"));
1N/A (void) fprintf(stdout, gettext("+++ filter=%s\n"),
1N/A (ldapfilter ? ldapfilter : "NULL"));
1N/A (void) fprintf(stdout,
1N/A gettext("+++ template for merging SSD filter=%s\n"),
1N/A (udata ? udata : "NULL"));
1N/A }
1N/A if (rc = list(database, ldapfilter, ldapattribute, &err, udata))
1N/A (void) fprintf(stderr, gettext("ldaplist: %s\n"), err);
1N/A
1N/A __ns_ldap_cancelStandalone();
1N/A
1N/A if (ldapfilter)
1N/A free(ldapfilter);
1N/A if (udata)
1N/A free(udata);
1N/A exit(switch_err(rc));
2N/A /* LINTED - suppress E_FUNC_HAS_NO_RETURN_STMT (lint bug 7122677) */
1N/A}