138032Speter/*
2261370Sgshapiro * Copyright (c) 1998-2001, 2003 Proofpoint, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
538032Speter * Copyright (c) 1988, 1993
638032Speter *	The Regents of the University of California.  All rights reserved.
738032Speter *
838032Speter * By using this file, you agree to the terms and conditions set
938032Speter * forth in the LICENSE file which can be found at the top level of
1038032Speter * the sendmail distribution.
1138032Speter *
1238032Speter */
1338032Speter
1464562Sgshapiro#include <sendmail.h>
1538032Speter
16266711SgshapiroSM_RCSID("@(#)$Id: stab.c,v 8.92 2013-11-22 20:51:56 ca Exp $")
1790792Sgshapiro
1838032Speter/*
1938032Speter**  STAB -- manage the symbol table
2038032Speter**
2138032Speter**	Parameters:
2238032Speter**		name -- the name to be looked up or inserted.
2338032Speter**		type -- the type of symbol.
2438032Speter**		op -- what to do:
2590792Sgshapiro**			ST_ENTER -- enter the name if not already present.
2638032Speter**			ST_FIND -- find it only.
2738032Speter**
2838032Speter**	Returns:
2938032Speter**		pointer to a STAB entry for this name.
3038032Speter**		NULL if not found and not entered.
3138032Speter**
3238032Speter**	Side Effects:
3338032Speter**		can update the symbol table.
3438032Speter*/
3538032Speter
3664562Sgshapiro#define STABSIZE	2003
3790792Sgshapiro#define SM_LOWER(c)	((isascii(c) && isupper(c)) ? tolower(c) : (c))
3838032Speter
3938032Speterstatic STAB	*SymTab[STABSIZE];
4038032Speter
4138032SpeterSTAB *
4238032Speterstab(name, type, op)
4338032Speter	char *name;
4438032Speter	int type;
4538032Speter	int op;
4638032Speter{
4738032Speter	register STAB *s;
4838032Speter	register STAB **ps;
4938032Speter	register int hfunc;
5038032Speter	register char *p;
5138032Speter	int len;
5238032Speter
5338032Speter	if (tTd(36, 5))
5490792Sgshapiro		sm_dprintf("STAB: %s %d ", name, type);
5538032Speter
5638032Speter	/*
5738032Speter	**  Compute the hashing function
5838032Speter	*/
5938032Speter
6038032Speter	hfunc = type;
6138032Speter	for (p = name; *p != '\0'; p++)
6290792Sgshapiro		hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE;
6338032Speter
6438032Speter	if (tTd(36, 9))
6590792Sgshapiro		sm_dprintf("(hfunc=%d) ", hfunc);
6638032Speter
6738032Speter	ps = &SymTab[hfunc];
68244928Sgshapiro	if (type == ST_MACRO || type == ST_RULESET || type == ST_NAMECANON)
6938032Speter	{
7038032Speter		while ((s = *ps) != NULL &&
7190792Sgshapiro		       (s->s_symtype != type || strcmp(name, s->s_name)))
7238032Speter			ps = &s->s_next;
7338032Speter	}
7438032Speter	else
7538032Speter	{
7638032Speter		while ((s = *ps) != NULL &&
7790792Sgshapiro		       (s->s_symtype != type || sm_strcasecmp(name, s->s_name)))
7838032Speter			ps = &s->s_next;
7938032Speter	}
8038032Speter
8138032Speter	/*
8238032Speter	**  Dispose of the entry.
8338032Speter	*/
8438032Speter
8538032Speter	if (s != NULL || op == ST_FIND)
8638032Speter	{
8738032Speter		if (tTd(36, 5))
8838032Speter		{
8938032Speter			if (s == NULL)
9090792Sgshapiro				sm_dprintf("not found\n");
9138032Speter			else
9238032Speter			{
9338032Speter				long *lp = (long *) s->s_class;
9438032Speter
9590792Sgshapiro				sm_dprintf("type %d val %lx %lx %lx %lx\n",
9690792Sgshapiro					s->s_symtype, lp[0], lp[1], lp[2], lp[3]);
9738032Speter			}
9838032Speter		}
9964562Sgshapiro		return s;
10038032Speter	}
10138032Speter
10238032Speter	/*
10338032Speter	**  Make a new entry and link it in.
10438032Speter	*/
10538032Speter
10638032Speter	if (tTd(36, 5))
10790792Sgshapiro		sm_dprintf("entered\n");
10838032Speter
10938032Speter	/* determine size of new entry */
11038032Speter	switch (type)
11138032Speter	{
11238032Speter	  case ST_CLASS:
113168515Sgshapiro		len = sizeof(s->s_class);
11438032Speter		break;
11538032Speter
11638032Speter	  case ST_MAILER:
117168515Sgshapiro		len = sizeof(s->s_mailer);
11864562Sgshapiro		break;
11938032Speter
12038032Speter	  case ST_ALIAS:
121168515Sgshapiro		len = sizeof(s->s_alias);
12238032Speter		break;
12338032Speter
12438032Speter	  case ST_MAPCLASS:
125168515Sgshapiro		len = sizeof(s->s_mapclass);
12638032Speter		break;
12738032Speter
12838032Speter	  case ST_MAP:
129168515Sgshapiro		len = sizeof(s->s_map);
13038032Speter		break;
13138032Speter
13238032Speter	  case ST_HOSTSIG:
133168515Sgshapiro		len = sizeof(s->s_hostsig);
13438032Speter		break;
13538032Speter
13638032Speter	  case ST_NAMECANON:
137168515Sgshapiro		len = sizeof(s->s_namecanon);
13838032Speter		break;
13938032Speter
14038032Speter	  case ST_MACRO:
141168515Sgshapiro		len = sizeof(s->s_macro);
14238032Speter		break;
14338032Speter
14438032Speter	  case ST_RULESET:
145168515Sgshapiro		len = sizeof(s->s_ruleset);
14638032Speter		break;
14738032Speter
14864562Sgshapiro	  case ST_HEADER:
149168515Sgshapiro		len = sizeof(s->s_header);
15064562Sgshapiro		break;
15164562Sgshapiro
15238032Speter	  case ST_SERVICE:
153168515Sgshapiro		len = sizeof(s->s_service);
15438032Speter		break;
15538032Speter
15690792Sgshapiro#if LDAPMAP
15777349Sgshapiro	  case ST_LMAP:
158168515Sgshapiro		len = sizeof(s->s_lmap);
15938032Speter		break;
16064562Sgshapiro#endif /* LDAPMAP */
16138032Speter
16290792Sgshapiro#if MILTER
16364562Sgshapiro	  case ST_MILTER:
164168515Sgshapiro		len = sizeof(s->s_milter);
16564562Sgshapiro		break;
16690792Sgshapiro#endif /* MILTER */
16764562Sgshapiro
16890792Sgshapiro	  case ST_QUEUE:
169168515Sgshapiro		len = sizeof(s->s_quegrp);
17090792Sgshapiro		break;
17190792Sgshapiro
172132943Sgshapiro#if SOCKETMAP
173132943Sgshapiro	  case ST_SOCKETMAP:
174168515Sgshapiro		len = sizeof(s->s_socketmap);
175132943Sgshapiro		break;
176132943Sgshapiro#endif /* SOCKETMAP */
177132943Sgshapiro
17838032Speter	  default:
17964562Sgshapiro		/*
18090792Sgshapiro		**  Each mailer has its own MCI stab entry:
18164562Sgshapiro		**
18264562Sgshapiro		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
18364562Sgshapiro		**
18464562Sgshapiro		**  Therefore, anything ST_MCI or larger is an s_mci.
18564562Sgshapiro		*/
18664562Sgshapiro
18738032Speter		if (type >= ST_MCI)
188168515Sgshapiro			len = sizeof(s->s_mci);
18938032Speter		else
19038032Speter		{
19138032Speter			syserr("stab: unknown symbol type %d", type);
192168515Sgshapiro			len = sizeof(s->s_value);
19338032Speter		}
19438032Speter		break;
19538032Speter	}
196168515Sgshapiro	len += sizeof(*s) - sizeof(s->s_value);
19738032Speter
19864562Sgshapiro	if (tTd(36, 15))
19990792Sgshapiro		sm_dprintf("size of stab entry: %d\n", len);
20064562Sgshapiro
20138032Speter	/* make new entry */
20290792Sgshapiro	s = (STAB *) sm_pmalloc_x(len);
20364562Sgshapiro	memset((char *) s, '\0', len);
20490792Sgshapiro	s->s_name = sm_pstrdup_x(name);
20590792Sgshapiro	s->s_symtype = type;
20638032Speter
20738032Speter	/* link it in */
20838032Speter	*ps = s;
20938032Speter
21064562Sgshapiro	/* set a default value for rulesets */
21164562Sgshapiro	if (type == ST_RULESET)
21264562Sgshapiro		s->s_ruleset = -1;
21364562Sgshapiro
21464562Sgshapiro	return s;
21538032Speter}
21690792Sgshapiro/*
21738032Speter**  STABAPPLY -- apply function to all stab entries
21838032Speter**
21938032Speter**	Parameters:
22090792Sgshapiro**		func -- the function to apply.  It will be given two
22190792Sgshapiro**			parameters (the stab entry and the arg).
22238032Speter**		arg -- an arbitrary argument, passed to func.
22338032Speter**
22438032Speter**	Returns:
22538032Speter**		none.
22638032Speter*/
22738032Speter
22838032Spetervoid
22938032Speterstabapply(func, arg)
23038032Speter	void (*func)__P((STAB *, int));
23138032Speter	int arg;
23238032Speter{
23338032Speter	register STAB **shead;
23438032Speter	register STAB *s;
23538032Speter
23638032Speter	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
23738032Speter	{
23838032Speter		for (s = *shead; s != NULL; s = s->s_next)
23938032Speter		{
24038032Speter			if (tTd(36, 90))
24190792Sgshapiro				sm_dprintf("stabapply: trying %d/%s\n",
24290792Sgshapiro					s->s_symtype, s->s_name);
24338032Speter			func(s, arg);
24438032Speter		}
24538032Speter	}
24638032Speter}
24790792Sgshapiro/*
24864562Sgshapiro**  QUEUEUP_MACROS -- queueup the macros in a class
24964562Sgshapiro**
25064562Sgshapiro**	Write the macros listed in the specified class into the
25164562Sgshapiro**	file referenced by qfp.
25264562Sgshapiro**
25364562Sgshapiro**	Parameters:
25464562Sgshapiro**		class -- class ID.
25590792Sgshapiro**		qfp -- file pointer to the queue file.
25664562Sgshapiro**		e -- the envelope.
25764562Sgshapiro**
25864562Sgshapiro**	Returns:
25964562Sgshapiro**		none.
26064562Sgshapiro*/
26164562Sgshapiro
26264562Sgshapirovoid
26364562Sgshapiroqueueup_macros(class, qfp, e)
26464562Sgshapiro	int class;
26590792Sgshapiro	SM_FILE_T *qfp;
26664562Sgshapiro	ENVELOPE *e;
26764562Sgshapiro{
26864562Sgshapiro	register STAB **shead;
26964562Sgshapiro	register STAB *s;
27064562Sgshapiro
27164562Sgshapiro	if (e == NULL)
27264562Sgshapiro		return;
27364562Sgshapiro
27471345Sgshapiro	class = bitidx(class);
27564562Sgshapiro	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
27664562Sgshapiro	{
27764562Sgshapiro		for (s = *shead; s != NULL; s = s->s_next)
27864562Sgshapiro		{
27964562Sgshapiro			int m;
28064562Sgshapiro			char *p;
28164562Sgshapiro
28290792Sgshapiro			if (s->s_symtype == ST_CLASS &&
28390792Sgshapiro			    bitnset(bitidx(class), s->s_class) &&
284120256Sgshapiro			    (m = macid(s->s_name)) != 0 &&
28564562Sgshapiro			    (p = macvalue(m, e)) != NULL)
28664562Sgshapiro			{
28790792Sgshapiro				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
28890792Sgshapiro						      "$%s%s\n",
28990792Sgshapiro						      s->s_name,
29090792Sgshapiro						      denlstring(p, true,
29190792Sgshapiro								 false));
29264562Sgshapiro			}
29364562Sgshapiro		}
29464562Sgshapiro	}
29564562Sgshapiro}
29690792Sgshapiro/*
29764562Sgshapiro**  COPY_CLASS -- copy class members from one class to another
29864562Sgshapiro**
29964562Sgshapiro**	Parameters:
30064562Sgshapiro**		src -- source class.
30164562Sgshapiro**		dst -- destination class.
30264562Sgshapiro**
30364562Sgshapiro**	Returns:
30464562Sgshapiro**		none.
30564562Sgshapiro*/
30664562Sgshapiro
30764562Sgshapirovoid
30864562Sgshapirocopy_class(src, dst)
30964562Sgshapiro	int src;
31064562Sgshapiro	int dst;
31164562Sgshapiro{
31264562Sgshapiro	register STAB **shead;
31364562Sgshapiro	register STAB *s;
31464562Sgshapiro
31571345Sgshapiro	src = bitidx(src);
31671345Sgshapiro	dst = bitidx(dst);
31764562Sgshapiro	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
31864562Sgshapiro	{
31964562Sgshapiro		for (s = *shead; s != NULL; s = s->s_next)
32064562Sgshapiro		{
32190792Sgshapiro			if (s->s_symtype == ST_CLASS &&
32271345Sgshapiro			    bitnset(src, s->s_class))
32364562Sgshapiro				setbitn(dst, s->s_class);
32464562Sgshapiro		}
32564562Sgshapiro	}
32664562Sgshapiro}
32790792Sgshapiro
32890792Sgshapiro/*
32990792Sgshapiro**  RMEXPSTAB -- remove expired entries from SymTab.
33090792Sgshapiro**
33190792Sgshapiro**	These entries need to be removed in long-running processes,
33290792Sgshapiro**	e.g., persistent queue runners, to avoid consuming memory.
33390792Sgshapiro**
33490792Sgshapiro**	XXX It might be useful to restrict the maximum TTL to avoid
33590792Sgshapiro**		caching data very long.
33690792Sgshapiro**
33790792Sgshapiro**	Parameters:
33890792Sgshapiro**		none.
33990792Sgshapiro**
34090792Sgshapiro**	Returns:
34190792Sgshapiro**		none.
34290792Sgshapiro**
34390792Sgshapiro**	Side Effects:
34490792Sgshapiro**		can remove entries from the symbol table.
34590792Sgshapiro*/
34690792Sgshapiro
34790792Sgshapiro#define SM_STAB_FREE(x)	\
34890792Sgshapiro	do \
34990792Sgshapiro	{ \
35090792Sgshapiro		char *o = (x); \
35190792Sgshapiro		(x) = NULL; \
35290792Sgshapiro		if (o != NULL) \
35390792Sgshapiro			sm_free(o); \
35490792Sgshapiro	} while (0)
35590792Sgshapiro
35690792Sgshapirovoid
35790792Sgshapirormexpstab()
35890792Sgshapiro{
35990792Sgshapiro	int i;
36090792Sgshapiro	STAB *s, *p, *f;
36190792Sgshapiro	time_t now;
36290792Sgshapiro
36390792Sgshapiro	now = curtime();
36490792Sgshapiro	for (i = 0; i < STABSIZE; i++)
36590792Sgshapiro	{
36690792Sgshapiro		p = NULL;
36790792Sgshapiro		s = SymTab[i];
36890792Sgshapiro		while (s != NULL)
36990792Sgshapiro		{
37090792Sgshapiro			switch (s->s_symtype)
37190792Sgshapiro			{
37290792Sgshapiro			  case ST_HOSTSIG:
37390792Sgshapiro				if (s->s_hostsig.hs_exp >= now)
37490792Sgshapiro					goto next;	/* not expired */
37590792Sgshapiro				SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */
37690792Sgshapiro				break;
37790792Sgshapiro
37890792Sgshapiro			  case ST_NAMECANON:
37990792Sgshapiro				if (s->s_namecanon.nc_exp >= now)
38090792Sgshapiro					goto next;	/* not expired */
38190792Sgshapiro				SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */
38290792Sgshapiro				break;
38390792Sgshapiro
38490792Sgshapiro			  default:
38590792Sgshapiro				if (s->s_symtype >= ST_MCI)
38690792Sgshapiro				{
38790792Sgshapiro					/* call mci_uncache? */
38890792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_status);
38990792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_rstatus);
39090792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_heloname);
39190792Sgshapiro#if 0
39290792Sgshapiro					/* not dynamically allocated */
39390792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_host);
39490792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_tolist);
39590792Sgshapiro#endif /* 0 */
39690792Sgshapiro#if SASL
39790792Sgshapiro					/* should always by NULL */
39890792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_sasl_string);
39990792Sgshapiro#endif /* SASL */
40090792Sgshapiro					if (s->s_mci.mci_rpool != NULL)
40190792Sgshapiro					{
40290792Sgshapiro						sm_rpool_free(s->s_mci.mci_rpool);
40390792Sgshapiro						s->s_mci.mci_macro.mac_rpool = NULL;
40490792Sgshapiro						s->s_mci.mci_rpool = NULL;
40590792Sgshapiro					}
40690792Sgshapiro					break;
40790792Sgshapiro				}
40890792Sgshapiro  next:
40990792Sgshapiro				p = s;
41090792Sgshapiro				s = s->s_next;
41190792Sgshapiro				continue;
41290792Sgshapiro			}
41390792Sgshapiro
41490792Sgshapiro			/* remove entry */
41590792Sgshapiro			SM_STAB_FREE(s->s_name); /* XXX */
41690792Sgshapiro			f = s;
41790792Sgshapiro			s = s->s_next;
41890792Sgshapiro			sm_free(f);	/* XXX */
41990792Sgshapiro			if (p == NULL)
42090792Sgshapiro				SymTab[i] = s;
42190792Sgshapiro			else
42290792Sgshapiro				p->s_next = s;
42390792Sgshapiro		}
42490792Sgshapiro	}
42590792Sgshapiro}
42690792Sgshapiro
42790792Sgshapiro#if SM_HEAP_CHECK
42890792Sgshapiro/*
42990792Sgshapiro**  DUMPSTAB -- dump symbol table.
43090792Sgshapiro**
43190792Sgshapiro**	For debugging.
43290792Sgshapiro*/
43390792Sgshapiro
43490792Sgshapiro#define MAXSTTYPES	(ST_MCI + 1)
43590792Sgshapiro
43690792Sgshapirovoid
43790792Sgshapirodumpstab()
43890792Sgshapiro{
43990792Sgshapiro	int i, t, total, types[MAXSTTYPES];
44090792Sgshapiro	STAB *s;
44190792Sgshapiro	static int prevt[MAXSTTYPES], prev = 0;
44290792Sgshapiro
44390792Sgshapiro	total = 0;
44490792Sgshapiro	for (i = 0; i < MAXSTTYPES; i++)
44590792Sgshapiro		types[i] = 0;
44690792Sgshapiro	for (i = 0; i < STABSIZE; i++)
44790792Sgshapiro	{
44890792Sgshapiro		s = SymTab[i];
44990792Sgshapiro		while (s != NULL)
45090792Sgshapiro		{
45190792Sgshapiro			++total;
45290792Sgshapiro			t = s->s_symtype;
45390792Sgshapiro			if (t > MAXSTTYPES - 1)
45490792Sgshapiro				t = MAXSTTYPES - 1;
45590792Sgshapiro			types[t]++;
45690792Sgshapiro			s = s->s_next;
45790792Sgshapiro		}
45890792Sgshapiro	}
45990792Sgshapiro	sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev);
46090792Sgshapiro	prev = total;
46190792Sgshapiro	for (i = 0; i < MAXSTTYPES; i++)
46290792Sgshapiro	{
46390792Sgshapiro		if (types[i] != 0)
46490792Sgshapiro		{
46590792Sgshapiro			sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)",
46690792Sgshapiro				i, types[i], types[i] - prevt[i]);
46790792Sgshapiro		}
46890792Sgshapiro		prevt[i] = types[i];
46990792Sgshapiro	}
47090792Sgshapiro}
47190792Sgshapiro#endif /* SM_HEAP_CHECK */
472