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