1/*
2 * Copyright (c) 1998-2001, 2003 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
16SM_RCSID("@(#)$Id: stab.c,v 8.92 2013-11-22 20:51:56 ca Exp $")
17
18#if DANE
19# include <tls.h>
20#endif
21
22/*
23**  STAB -- manage the symbol table
24**
25**	Parameters:
26**		name -- the name to be looked up or inserted.
27**		type -- the type of symbol.
28**		op -- what to do:
29**			ST_ENTER -- enter the name if not already present.
30**			ST_FIND -- find it only.
31**
32**	Returns:
33**		pointer to a STAB entry for this name.
34**		NULL if not found and not entered.
35**
36**	Side Effects:
37**		can update the symbol table.
38*/
39
40#define STABSIZE	2003
41#define SM_LOWER(c)	((isascii(c) && isupper(c)) ? tolower(c) : (c))
42
43static STAB	*SymTab[STABSIZE];
44
45STAB *
46stab(name, type, op)
47	char *name;
48	int type;
49	int op;
50{
51	register STAB *s;
52	register STAB **ps;
53	register int hfunc;
54	register char *p;
55	int len;
56
57	if (tTd(36, 5))
58		sm_dprintf("STAB: %s %d ", name, type);
59
60	/*
61	**  Compute the hashing function
62	*/
63
64	hfunc = type;
65	for (p = name; *p != '\0'; p++)
66		hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE;
67
68	if (tTd(36, 9))
69		sm_dprintf("(hfunc=%d) ", hfunc);
70
71	ps = &SymTab[hfunc];
72	if (type == ST_MACRO || type == ST_RULESET || type == ST_NAMECANON)
73	{
74		while ((s = *ps) != NULL &&
75		       (s->s_symtype != type || strcmp(name, s->s_name)))
76			ps = &s->s_next;
77	}
78	else
79	{
80		while ((s = *ps) != NULL &&
81		       (s->s_symtype != type || sm_strcasecmp(name, s->s_name)))
82			ps = &s->s_next;
83	}
84
85	/*
86	**  Dispose of the entry.
87	*/
88
89	if (s != NULL || op == ST_FIND)
90	{
91		if (tTd(36, 5))
92		{
93			if (s == NULL)
94				sm_dprintf("not found\n");
95			else
96			{
97				long *lp = (long *) s->s_class;
98
99				sm_dprintf("type %d val %lx %lx %lx %lx\n",
100					s->s_symtype, lp[0], lp[1], lp[2], lp[3]);
101			}
102		}
103		return s;
104	}
105
106	/*
107	**  Make a new entry and link it in.
108	*/
109
110	if (tTd(36, 5))
111		sm_dprintf("entered\n");
112
113	/* determine size of new entry */
114	switch (type)
115	{
116	  case ST_CLASS:
117		len = sizeof(s->s_class);
118		break;
119
120	  case ST_MAILER:
121		len = sizeof(s->s_mailer);
122		break;
123
124	  case ST_ALIAS:
125		len = sizeof(s->s_alias);
126		break;
127
128	  case ST_MAPCLASS:
129		len = sizeof(s->s_mapclass);
130		break;
131
132	  case ST_MAP:
133		len = sizeof(s->s_map);
134		break;
135
136	  case ST_HOSTSIG:
137		len = sizeof(s->s_hostsig);
138		break;
139
140	  case ST_NAMECANON:
141		len = sizeof(s->s_namecanon);
142		break;
143
144	  case ST_MACRO:
145		len = sizeof(s->s_macro);
146		break;
147
148	  case ST_RULESET:
149		len = sizeof(s->s_ruleset);
150		break;
151
152	  case ST_HEADER:
153		len = sizeof(s->s_header);
154		break;
155
156	  case ST_SERVICE:
157		len = sizeof(s->s_service);
158		break;
159
160#if LDAPMAP
161	  case ST_LMAP:
162		len = sizeof(s->s_lmap);
163		break;
164#endif
165
166#if MILTER
167	  case ST_MILTER:
168		len = sizeof(s->s_milter);
169		break;
170#endif
171
172	  case ST_QUEUE:
173		len = sizeof(s->s_quegrp);
174		break;
175
176#if SOCKETMAP
177	  case ST_SOCKETMAP:
178		len = sizeof(s->s_socketmap);
179		break;
180#endif
181
182#if DANE
183	  case ST_TLSA_RR:
184		len = sizeof(s->s_tlsa);
185		break;
186#endif
187
188	  default:
189		/*
190		**  Each mailer has its own MCI stab entry:
191		**
192		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
193		**
194		**  Therefore, anything ST_MCI or larger is an s_mci.
195		*/
196
197		if (type >= ST_MCI)
198			len = sizeof(s->s_mci);
199		else
200		{
201			syserr("stab: unknown symbol type %d", type);
202			len = sizeof(s->s_value);
203		}
204		break;
205	}
206	len += sizeof(*s) - sizeof(s->s_value);
207
208	if (tTd(36, 15))
209		sm_dprintf("size of stab entry: %d\n", len);
210
211	/* make new entry */
212	s = (STAB *) sm_pmalloc_x(len);
213	memset((char *) s, '\0', len);
214	s->s_name = sm_pstrdup_x(name);
215	s->s_symtype = type;
216
217	/* link it in */
218	*ps = s;
219
220	/* set a default value for rulesets */
221	if (type == ST_RULESET)
222		s->s_ruleset = -1;
223
224	return s;
225}
226/*
227**  STABAPPLY -- apply function to all stab entries
228**
229**	Parameters:
230**		func -- the function to apply.  It will be given two
231**			parameters (the stab entry and the arg).
232**		arg -- an arbitrary argument, passed to func.
233**
234**	Returns:
235**		none.
236*/
237
238void
239stabapply(func, arg)
240	void (*func)__P((STAB *, int));
241	int arg;
242{
243	register STAB **shead;
244	register STAB *s;
245
246	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
247	{
248		for (s = *shead; s != NULL; s = s->s_next)
249		{
250			if (tTd(36, 90))
251				sm_dprintf("stabapply: trying %d/%s\n",
252					s->s_symtype, s->s_name);
253			func(s, arg);
254		}
255	}
256}
257/*
258**  QUEUEUP_MACROS -- queueup the macros in a class
259**
260**	Write the macros listed in the specified class into the
261**	file referenced by qfp.
262**
263**	Parameters:
264**		class -- class ID.
265**		qfp -- file pointer to the queue file.
266**		e -- the envelope.
267**
268**	Returns:
269**		none.
270*/
271
272void
273queueup_macros(class, qfp, e)
274	int class;
275	SM_FILE_T *qfp;
276	ENVELOPE *e;
277{
278	register STAB **shead;
279	register STAB *s;
280
281	if (e == NULL)
282		return;
283
284	class = bitidx(class);
285	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
286	{
287		for (s = *shead; s != NULL; s = s->s_next)
288		{
289			int m;
290			char *p;
291
292			if (s->s_symtype == ST_CLASS &&
293			    bitnset(bitidx(class), s->s_class) &&
294			    (m = macid(s->s_name)) != 0 &&
295			    (p = macvalue(m, e)) != NULL)
296			{
297				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
298						      "$%s%s\n",
299						      s->s_name,
300						      denlstring(p, true,
301								 false));
302			}
303		}
304	}
305}
306/*
307**  COPY_CLASS -- copy class members from one class to another
308**
309**	Parameters:
310**		src -- source class.
311**		dst -- destination class.
312**
313**	Returns:
314**		none.
315*/
316
317void
318copy_class(src, dst)
319	int src;
320	int dst;
321{
322	register STAB **shead;
323	register STAB *s;
324
325	src = bitidx(src);
326	dst = bitidx(dst);
327	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
328	{
329		for (s = *shead; s != NULL; s = s->s_next)
330		{
331			if (s->s_symtype == ST_CLASS &&
332			    bitnset(src, s->s_class))
333				setbitn(dst, s->s_class);
334		}
335	}
336}
337
338/*
339**  RMEXPSTAB -- remove expired entries from SymTab.
340**
341**	These entries need to be removed in long-running processes,
342**	e.g., persistent queue runners, to avoid consuming memory.
343**
344**	XXX It might be useful to restrict the maximum TTL to avoid
345**		caching data very long.
346**
347**	Parameters:
348**		none.
349**
350**	Returns:
351**		none.
352**
353**	Side Effects:
354**		can remove entries from the symbol table.
355*/
356
357#define SM_STAB_FREE(x)	\
358	do \
359	{ \
360		char *o = (x); \
361		(x) = NULL; \
362		if (o != NULL) \
363			sm_free(o); \
364	} while (0)
365
366void
367rmexpstab()
368{
369	int i;
370	STAB *s, *p, *f;
371	time_t now;
372
373	now = curtime();
374	for (i = 0; i < STABSIZE; i++)
375	{
376		p = NULL;
377		s = SymTab[i];
378		while (s != NULL)
379		{
380			switch (s->s_symtype)
381			{
382			  case ST_HOSTSIG:
383				if (s->s_hostsig.hs_exp >= now)
384					goto next;	/* not expired */
385				SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */
386				break;
387
388			  case ST_NAMECANON:
389				if (s->s_namecanon.nc_exp >= now)
390					goto next;	/* not expired */
391				SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */
392				break;
393
394#if DANE
395			  case ST_TLSA_RR:
396				if (s->s_tlsa->dane_tlsa_exp >= now)
397					goto next;	/* not expired */
398				(void) dane_tlsa_free(s->s_tlsa);
399				s->s_tlsa = NULL;
400				break;
401#endif /* DANE */
402
403			  default:
404				if (s->s_symtype >= ST_MCI)
405				{
406					/* call mci_uncache? */
407					SM_STAB_FREE(s->s_mci.mci_status);
408					SM_STAB_FREE(s->s_mci.mci_rstatus);
409					SM_STAB_FREE(s->s_mci.mci_heloname);
410#if 0
411					/* not dynamically allocated */
412					SM_STAB_FREE(s->s_mci.mci_host);
413					SM_STAB_FREE(s->s_mci.mci_tolist);
414#endif /* 0 */
415#if SASL
416					/* should always by NULL */
417					SM_STAB_FREE(s->s_mci.mci_sasl_string);
418#endif
419					if (s->s_mci.mci_rpool != NULL)
420					{
421						sm_rpool_free(s->s_mci.mci_rpool);
422						s->s_mci.mci_macro.mac_rpool = NULL;
423						s->s_mci.mci_rpool = NULL;
424					}
425					break;
426				}
427  next:
428				p = s;
429				s = s->s_next;
430				continue;
431			}
432
433			/* remove entry */
434			SM_STAB_FREE(s->s_name); /* XXX */
435			f = s;
436			s = s->s_next;
437			sm_free(f);	/* XXX */
438			if (p == NULL)
439				SymTab[i] = s;
440			else
441				p->s_next = s;
442		}
443	}
444}
445
446#if SM_HEAP_CHECK
447/*
448**  DUMPSTAB -- dump symbol table.
449**
450**	For debugging.
451*/
452
453#define MAXSTTYPES	(ST_MCI + 1)
454
455void
456dumpstab()
457{
458	int i, t, total, types[MAXSTTYPES];
459	STAB *s;
460	static int prevt[MAXSTTYPES], prev = 0;
461
462	total = 0;
463	for (i = 0; i < MAXSTTYPES; i++)
464		types[i] = 0;
465	for (i = 0; i < STABSIZE; i++)
466	{
467		s = SymTab[i];
468		while (s != NULL)
469		{
470			++total;
471			t = s->s_symtype;
472			if (t > MAXSTTYPES - 1)
473				t = MAXSTTYPES - 1;
474			types[t]++;
475			s = s->s_next;
476		}
477	}
478	sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev);
479	prev = total;
480	for (i = 0; i < MAXSTTYPES; i++)
481	{
482		if (types[i] != 0)
483		{
484			sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)",
485				i, types[i], types[i] - prevt[i]);
486		}
487		prevt[i] = types[i];
488	}
489}
490#endif /* SM_HEAP_CHECK */
491