xref: /freebsd/contrib/sendmail/src/stab.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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 
16 SM_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 
43 static STAB	*SymTab[STABSIZE];
44 
45 STAB *
46 stab(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 
238 void
239 stabapply(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 
272 void
273 queueup_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 
317 void
318 copy_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 
366 void
367 rmexpstab()
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 
455 void
456 dumpstab()
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