190792Sgshapiro/*
2261194Sgshapiro * Copyright (c) 2001 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *	All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro */
990792Sgshapiro
1090792Sgshapiro#include <sm/gen.h>
11266527SgshapiroSM_RCSID("@(#)$Id: niprop.c,v 1.9 2013-11-22 20:51:43 ca Exp $")
1290792Sgshapiro
1390792Sgshapiro#if NETINFO
1490792Sgshapiro#include <ctype.h>
1590792Sgshapiro#include <stdlib.h>
1690792Sgshapiro#include <sm/io.h>
1790792Sgshapiro#include <sm/assert.h>
1890792Sgshapiro#include <sm/debug.h>
1990792Sgshapiro#include <sm/string.h>
2090792Sgshapiro#include <sm/varargs.h>
2190792Sgshapiro#include <sm/heap.h>
2290792Sgshapiro
2390792Sgshapiro/*
2490792Sgshapiro**  NI_PROPVAL -- NetInfo property value lookup routine
2590792Sgshapiro**
2690792Sgshapiro**	Parameters:
2790792Sgshapiro**		keydir -- the NetInfo directory name in which to search
2890792Sgshapiro**			for the key.
2990792Sgshapiro**		keyprop -- the name of the property in which to find the
3090792Sgshapiro**			property we are interested.  Defaults to "name".
3190792Sgshapiro**		keyval -- the value for which we are really searching.
3290792Sgshapiro**		valprop -- the property name for the value in which we
3390792Sgshapiro**			are interested.
3490792Sgshapiro**		sepchar -- if non-nil, this can be multiple-valued, and
3590792Sgshapiro**			we should return a string separated by this
3690792Sgshapiro**			character.
3790792Sgshapiro**
3890792Sgshapiro**	Returns:
3990792Sgshapiro**		NULL -- if:
4090792Sgshapiro**			1. the directory is not found
4190792Sgshapiro**			2. the property name is not found
4290792Sgshapiro**			3. the property contains multiple values
4390792Sgshapiro**			4. some error occurred
4490792Sgshapiro**		else -- the value of the lookup.
4590792Sgshapiro**
4690792Sgshapiro**	Example:
4790792Sgshapiro**		To search for an alias value, use:
4890792Sgshapiro**		  ni_propval("/aliases", "name", aliasname, "members", ',')
4990792Sgshapiro**
5090792Sgshapiro**	Notes:
5190792Sgshapiro**		Caller should free the return value of ni_proval
5290792Sgshapiro*/
5390792Sgshapiro
5490792Sgshapiro# include <netinfo/ni.h>
5590792Sgshapiro
5690792Sgshapiro# define LOCAL_NETINFO_DOMAIN	"."
5790792Sgshapiro# define PARENT_NETINFO_DOMAIN	".."
5890792Sgshapiro# define MAX_NI_LEVELS		256
5990792Sgshapiro
6090792Sgshapirochar *
6190792Sgshapironi_propval(keydir, keyprop, keyval, valprop, sepchar)
6290792Sgshapiro	char *keydir;
6390792Sgshapiro	char *keyprop;
6490792Sgshapiro	char *keyval;
6590792Sgshapiro	char *valprop;
6690792Sgshapiro	int sepchar;
6790792Sgshapiro{
6890792Sgshapiro	char *propval = NULL;
6990792Sgshapiro	int i;
7090792Sgshapiro	int j, alen, l;
7190792Sgshapiro	void *ni = NULL;
7290792Sgshapiro	void *lastni = NULL;
7390792Sgshapiro	ni_status nis;
7490792Sgshapiro	ni_id nid;
7590792Sgshapiro	ni_namelist ninl;
7690792Sgshapiro	register char *p;
7790792Sgshapiro	char keybuf[1024];
7890792Sgshapiro
7990792Sgshapiro	/*
8090792Sgshapiro	**  Create the full key from the two parts.
8190792Sgshapiro	**
8290792Sgshapiro	**	Note that directory can end with, e.g., "name=" to specify
8390792Sgshapiro	**	an alternate search property.
8490792Sgshapiro	*/
8590792Sgshapiro
8690792Sgshapiro	i = strlen(keydir) + strlen(keyval) + 2;
8790792Sgshapiro	if (keyprop != NULL)
8890792Sgshapiro		i += strlen(keyprop) + 1;
8990792Sgshapiro	if (i >= sizeof keybuf)
9090792Sgshapiro		return NULL;
9190792Sgshapiro	(void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/");
9290792Sgshapiro	if (keyprop != NULL)
9390792Sgshapiro	{
9490792Sgshapiro		(void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf);
9590792Sgshapiro	}
9690792Sgshapiro	(void) sm_strlcat(keybuf, keyval, sizeof keybuf);
9790792Sgshapiro
9890792Sgshapiro#if 0
9990792Sgshapiro	if (tTd(38, 21))
10090792Sgshapiro		sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n",
10190792Sgshapiro			keydir, keyprop, keyval, valprop, sepchar, keybuf);
102363466Sgshapiro#endif
10390792Sgshapiro
10490792Sgshapiro	/*
10590792Sgshapiro	**  If the passed directory and property name are found
10690792Sgshapiro	**  in one of netinfo domains we need to search (starting
10790792Sgshapiro	**  from the local domain moving all the way back to the
10890792Sgshapiro	**  root domain) set propval to the property's value
10990792Sgshapiro	**  and return it.
11090792Sgshapiro	*/
11190792Sgshapiro
11290792Sgshapiro	for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++)
11390792Sgshapiro	{
11490792Sgshapiro		if (i == 0)
11590792Sgshapiro		{
11690792Sgshapiro			nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
11790792Sgshapiro#if 0
11890792Sgshapiro			if (tTd(38, 20))
11990792Sgshapiro				sm_dprintf("ni_open(LOCAL) = %d\n", nis);
120363466Sgshapiro#endif
12190792Sgshapiro		}
12290792Sgshapiro		else
12390792Sgshapiro		{
12490792Sgshapiro			if (lastni != NULL)
12590792Sgshapiro				ni_free(lastni);
12690792Sgshapiro			lastni = ni;
12790792Sgshapiro			nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
12890792Sgshapiro#if 0
12990792Sgshapiro			if (tTd(38, 20))
13090792Sgshapiro				sm_dprintf("ni_open(PARENT) = %d\n", nis);
131363466Sgshapiro#endif
13290792Sgshapiro		}
13390792Sgshapiro
13490792Sgshapiro		/*
13590792Sgshapiro		**  Don't bother if we didn't get a handle on a
13690792Sgshapiro		**  proper domain.  This is not necessarily an error.
13790792Sgshapiro		**  We would get a positive ni_status if, for instance
13890792Sgshapiro		**  we never found the directory or property and tried
13990792Sgshapiro		**  to open the parent of the root domain!
14090792Sgshapiro		*/
14190792Sgshapiro
14290792Sgshapiro		if (nis != 0)
14390792Sgshapiro			break;
14490792Sgshapiro
14590792Sgshapiro		/*
14690792Sgshapiro		**  Find the path to the server information.
14790792Sgshapiro		*/
14890792Sgshapiro
14990792Sgshapiro		if (ni_pathsearch(ni, &nid, keybuf) != 0)
15090792Sgshapiro			continue;
15190792Sgshapiro
15290792Sgshapiro		/*
15390792Sgshapiro		**  Find associated value information.
15490792Sgshapiro		*/
15590792Sgshapiro
15690792Sgshapiro		if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
15790792Sgshapiro			continue;
15890792Sgshapiro
15990792Sgshapiro#if 0
16090792Sgshapiro		if (tTd(38, 20))
16190792Sgshapiro			sm_dprintf("ni_lookupprop: len=%d\n",
16290792Sgshapiro				ninl.ni_namelist_len);
163363466Sgshapiro#endif
16490792Sgshapiro
16590792Sgshapiro		/*
16690792Sgshapiro		**  See if we have an acceptable number of values.
16790792Sgshapiro		*/
16890792Sgshapiro
16990792Sgshapiro		if (ninl.ni_namelist_len <= 0)
17090792Sgshapiro			continue;
17190792Sgshapiro
17290792Sgshapiro		if (sepchar == '\0' && ninl.ni_namelist_len > 1)
17390792Sgshapiro		{
17490792Sgshapiro			ni_namelist_free(&ninl);
17590792Sgshapiro			continue;
17690792Sgshapiro		}
17790792Sgshapiro
17890792Sgshapiro		/*
17990792Sgshapiro		**  Calculate number of bytes needed and build result
18090792Sgshapiro		*/
18190792Sgshapiro
18290792Sgshapiro		alen = 1;
18390792Sgshapiro		for (j = 0; j < ninl.ni_namelist_len; j++)
18490792Sgshapiro			alen += strlen(ninl.ni_namelist_val[j]) + 1;
18590792Sgshapiro		propval = p = sm_malloc(alen);
18690792Sgshapiro		if (propval == NULL)
18790792Sgshapiro			goto cleanup;
18890792Sgshapiro		for (j = 0; j < ninl.ni_namelist_len; j++)
18990792Sgshapiro		{
19090792Sgshapiro			(void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen);
19190792Sgshapiro			l = strlen(p);
19290792Sgshapiro			p += l;
19390792Sgshapiro			*p++ = sepchar;
19490792Sgshapiro			alen -= l + 1;
19590792Sgshapiro		}
19690792Sgshapiro		*--p = '\0';
19790792Sgshapiro
19890792Sgshapiro		ni_namelist_free(&ninl);
19990792Sgshapiro	}
20090792Sgshapiro
20190792Sgshapiro  cleanup:
20290792Sgshapiro	if (ni != NULL)
20390792Sgshapiro		ni_free(ni);
20490792Sgshapiro	if (lastni != NULL && ni != lastni)
20590792Sgshapiro		ni_free(lastni);
20690792Sgshapiro#if 0
20790792Sgshapiro	if (tTd(38, 20))
20890792Sgshapiro		sm_dprintf("ni_propval returns: '%s'\n", propval);
209363466Sgshapiro#endif
21090792Sgshapiro
21190792Sgshapiro	return propval;
21290792Sgshapiro}
21390792Sgshapiro#endif /* NETINFO */
214