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