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