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