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 *
stab(name,type,op)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
queueup_macros(class,qfp,e)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
copy_class(src,dst)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
rmexpstab()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
dumpstab()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