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