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 #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 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 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 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 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