xref: /freebsd/contrib/sendmail/src/stab.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
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 	  default:
208 		/*
209 		**  Each mailer has its own MCI stab entry:
210 		**
211 		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
212 		**
213 		**  Therefore, anything ST_MCI or larger is an s_mci.
214 		*/
215 
216 		if (type >= ST_MCI)
217 			len = sizeof(s->s_mci);
218 		else
219 		{
220 			syserr("stab: unknown symbol type %d", type);
221 			len = sizeof(s->s_value);
222 		}
223 		break;
224 	}
225 	len += sizeof(*s) - sizeof(s->s_value);
226 
227 	if (tTd(36, 15))
228 		sm_dprintf("size of stab entry: %d\n", len);
229 
230 	/* make new entry */
231 	s = (STAB *) sm_pmalloc_x(len);
232 	memset((char *) s, '\0', len);
233 	s->s_name = sm_pstrdup_x(name);
234 	s->s_symtype = type;
235 
236 	/* link it in */
237 	*ps = s;
238 
239 	/* set a default value for rulesets */
240 	if (type == ST_RULESET)
241 		s->s_ruleset = -1;
242 
243 	return s;
244 }
245 /*
246 **  STABAPPLY -- apply function to all stab entries
247 **
248 **	Parameters:
249 **		func -- the function to apply.  It will be given two
250 **			parameters (the stab entry and the arg).
251 **		arg -- an arbitrary argument, passed to func.
252 **
253 **	Returns:
254 **		none.
255 */
256 
257 void
258 stabapply(func, arg)
259 	void (*func)__P((STAB *, int));
260 	int arg;
261 {
262 	register STAB **shead;
263 	register STAB *s;
264 
265 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
266 	{
267 		for (s = *shead; s != NULL; s = s->s_next)
268 		{
269 			if (tTd(36, 90))
270 				sm_dprintf("stabapply: trying %d/%s\n",
271 					s->s_symtype, s->s_name);
272 			func(s, arg);
273 		}
274 	}
275 }
276 /*
277 **  QUEUEUP_MACROS -- queueup the macros in a class
278 **
279 **	Write the macros listed in the specified class into the
280 **	file referenced by qfp.
281 **
282 **	Parameters:
283 **		class -- class ID.
284 **		qfp -- file pointer to the queue file.
285 **		e -- the envelope.
286 **
287 **	Returns:
288 **		none.
289 */
290 
291 void
292 queueup_macros(class, qfp, e)
293 	int class;
294 	SM_FILE_T *qfp;
295 	ENVELOPE *e;
296 {
297 	register STAB **shead;
298 	register STAB *s;
299 
300 	if (e == NULL)
301 		return;
302 
303 	class = bitidx(class);
304 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
305 	{
306 		for (s = *shead; s != NULL; s = s->s_next)
307 		{
308 			int m;
309 			char *p;
310 
311 			if (s->s_symtype == ST_CLASS &&
312 			    bitnset(bitidx(class), s->s_class) &&
313 			    (m = macid(s->s_name)) != 0 &&
314 			    (p = macvalue(m, e)) != NULL)
315 			{
316 				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
317 						      "$%s%s\n",
318 						      s->s_name,
319 						      denlstring(p, true,
320 								 false));
321 			}
322 		}
323 	}
324 }
325 /*
326 **  COPY_CLASS -- copy class members from one class to another
327 **
328 **	Parameters:
329 **		src -- source class.
330 **		dst -- destination class.
331 **
332 **	Returns:
333 **		none.
334 */
335 
336 void
337 copy_class(src, dst)
338 	int src;
339 	int dst;
340 {
341 	register STAB **shead;
342 	register STAB *s;
343 
344 	src = bitidx(src);
345 	dst = bitidx(dst);
346 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
347 	{
348 		for (s = *shead; s != NULL; s = s->s_next)
349 		{
350 			if (s->s_symtype == ST_CLASS &&
351 			    bitnset(src, s->s_class))
352 				setbitn(dst, s->s_class);
353 		}
354 	}
355 }
356 
357 /*
358 **  RMEXPSTAB -- remove expired entries from SymTab.
359 **
360 **	These entries need to be removed in long-running processes,
361 **	e.g., persistent queue runners, to avoid consuming memory.
362 **
363 **	XXX It might be useful to restrict the maximum TTL to avoid
364 **		caching data very long.
365 **
366 **	Parameters:
367 **		none.
368 **
369 **	Returns:
370 **		none.
371 **
372 **	Side Effects:
373 **		can remove entries from the symbol table.
374 */
375 
376 #define SM_STAB_FREE(x)	\
377 	do \
378 	{ \
379 		char *o = (x); \
380 		(x) = NULL; \
381 		if (o != NULL) \
382 			sm_free(o); \
383 	} while (0)
384 
385 void
386 rmexpstab()
387 {
388 	int i;
389 	STAB *s, *p, *f;
390 	time_t now;
391 
392 	now = curtime();
393 	for (i = 0; i < STABSIZE; i++)
394 	{
395 		p = NULL;
396 		s = SymTab[i];
397 		while (s != NULL)
398 		{
399 			switch (s->s_symtype)
400 			{
401 			  case ST_HOSTSIG:
402 				if (s->s_hostsig.hs_exp >= now)
403 					goto next;	/* not expired */
404 				SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */
405 				break;
406 
407 			  case ST_NAMECANON:
408 				if (s->s_namecanon.nc_exp >= now)
409 					goto next;	/* not expired */
410 				SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */
411 				break;
412 
413 #if DANE
414 			  case ST_TLSA_RR:
415 				if (s->s_tlsa->dane_tlsa_exp >= now)
416 					goto next;	/* not expired */
417 				(void) dane_tlsa_free(s->s_tlsa);
418 				s->s_tlsa = NULL;
419 				break;
420 #endif /* DANE */
421 
422 			  default:
423 				if (s->s_symtype >= ST_MCI)
424 				{
425 					/* call mci_uncache? */
426 					SM_STAB_FREE(s->s_mci.mci_status);
427 					SM_STAB_FREE(s->s_mci.mci_rstatus);
428 					SM_STAB_FREE(s->s_mci.mci_heloname);
429 #if 0
430 					/* not dynamically allocated */
431 					SM_STAB_FREE(s->s_mci.mci_host);
432 					SM_STAB_FREE(s->s_mci.mci_tolist);
433 #endif /* 0 */
434 #if SASL
435 					/* should always by NULL */
436 					SM_STAB_FREE(s->s_mci.mci_sasl_string);
437 #endif
438 					if (s->s_mci.mci_rpool != NULL)
439 					{
440 						sm_rpool_free(s->s_mci.mci_rpool);
441 						s->s_mci.mci_macro.mac_rpool = NULL;
442 						s->s_mci.mci_rpool = NULL;
443 					}
444 					break;
445 				}
446   next:
447 				p = s;
448 				s = s->s_next;
449 				continue;
450 			}
451 
452 			/* remove entry */
453 			SM_STAB_FREE(s->s_name); /* XXX */
454 			f = s;
455 			s = s->s_next;
456 			sm_free(f);	/* XXX */
457 			if (p == NULL)
458 				SymTab[i] = s;
459 			else
460 				p->s_next = s;
461 		}
462 	}
463 }
464 
465 #if SM_HEAP_CHECK
466 /*
467 **  DUMPSTAB -- dump symbol table.
468 **
469 **	For debugging.
470 */
471 
472 #define MAXSTTYPES	(ST_MCI + 1)
473 
474 void
475 dumpstab()
476 {
477 	int i, t, total, types[MAXSTTYPES];
478 	STAB *s;
479 	static int prevt[MAXSTTYPES], prev = 0;
480 
481 	total = 0;
482 	for (i = 0; i < MAXSTTYPES; i++)
483 		types[i] = 0;
484 	for (i = 0; i < STABSIZE; i++)
485 	{
486 		s = SymTab[i];
487 		while (s != NULL)
488 		{
489 			++total;
490 			t = s->s_symtype;
491 			if (t > MAXSTTYPES - 1)
492 				t = MAXSTTYPES - 1;
493 			types[t]++;
494 			s = s->s_next;
495 		}
496 	}
497 	sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev);
498 	prev = total;
499 	for (i = 0; i < MAXSTTYPES; i++)
500 	{
501 		if (types[i] != 0)
502 		{
503 			sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)",
504 				i, types[i], types[i] - prevt[i]);
505 		}
506 		prevt[i] = types[i];
507 	}
508 }
509 #endif /* SM_HEAP_CHECK */
510