138032Speter/* 2261370Sgshapiro * Copyright (c) 1998-2001, 2003 Proofpoint, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1988, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 16266711SgshapiroSM_RCSID("@(#)$Id: stab.c,v 8.92 2013-11-22 20:51:56 ca Exp $") 1790792Sgshapiro 1838032Speter/* 1938032Speter** STAB -- manage the symbol table 2038032Speter** 2138032Speter** Parameters: 2238032Speter** name -- the name to be looked up or inserted. 2338032Speter** type -- the type of symbol. 2438032Speter** op -- what to do: 2590792Sgshapiro** ST_ENTER -- enter the name if not already present. 2638032Speter** ST_FIND -- find it only. 2738032Speter** 2838032Speter** Returns: 2938032Speter** pointer to a STAB entry for this name. 3038032Speter** NULL if not found and not entered. 3138032Speter** 3238032Speter** Side Effects: 3338032Speter** can update the symbol table. 3438032Speter*/ 3538032Speter 3664562Sgshapiro#define STABSIZE 2003 3790792Sgshapiro#define SM_LOWER(c) ((isascii(c) && isupper(c)) ? tolower(c) : (c)) 3838032Speter 3938032Speterstatic STAB *SymTab[STABSIZE]; 4038032Speter 4138032SpeterSTAB * 4238032Speterstab(name, type, op) 4338032Speter char *name; 4438032Speter int type; 4538032Speter int op; 4638032Speter{ 4738032Speter register STAB *s; 4838032Speter register STAB **ps; 4938032Speter register int hfunc; 5038032Speter register char *p; 5138032Speter int len; 5238032Speter 5338032Speter if (tTd(36, 5)) 5490792Sgshapiro sm_dprintf("STAB: %s %d ", name, type); 5538032Speter 5638032Speter /* 5738032Speter ** Compute the hashing function 5838032Speter */ 5938032Speter 6038032Speter hfunc = type; 6138032Speter for (p = name; *p != '\0'; p++) 6290792Sgshapiro hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE; 6338032Speter 6438032Speter if (tTd(36, 9)) 6590792Sgshapiro sm_dprintf("(hfunc=%d) ", hfunc); 6638032Speter 6738032Speter ps = &SymTab[hfunc]; 68244928Sgshapiro if (type == ST_MACRO || type == ST_RULESET || type == ST_NAMECANON) 6938032Speter { 7038032Speter while ((s = *ps) != NULL && 7190792Sgshapiro (s->s_symtype != type || strcmp(name, s->s_name))) 7238032Speter ps = &s->s_next; 7338032Speter } 7438032Speter else 7538032Speter { 7638032Speter while ((s = *ps) != NULL && 7790792Sgshapiro (s->s_symtype != type || sm_strcasecmp(name, s->s_name))) 7838032Speter ps = &s->s_next; 7938032Speter } 8038032Speter 8138032Speter /* 8238032Speter ** Dispose of the entry. 8338032Speter */ 8438032Speter 8538032Speter if (s != NULL || op == ST_FIND) 8638032Speter { 8738032Speter if (tTd(36, 5)) 8838032Speter { 8938032Speter if (s == NULL) 9090792Sgshapiro sm_dprintf("not found\n"); 9138032Speter else 9238032Speter { 9338032Speter long *lp = (long *) s->s_class; 9438032Speter 9590792Sgshapiro sm_dprintf("type %d val %lx %lx %lx %lx\n", 9690792Sgshapiro s->s_symtype, lp[0], lp[1], lp[2], lp[3]); 9738032Speter } 9838032Speter } 9964562Sgshapiro return s; 10038032Speter } 10138032Speter 10238032Speter /* 10338032Speter ** Make a new entry and link it in. 10438032Speter */ 10538032Speter 10638032Speter if (tTd(36, 5)) 10790792Sgshapiro sm_dprintf("entered\n"); 10838032Speter 10938032Speter /* determine size of new entry */ 11038032Speter switch (type) 11138032Speter { 11238032Speter case ST_CLASS: 113168515Sgshapiro len = sizeof(s->s_class); 11438032Speter break; 11538032Speter 11638032Speter case ST_MAILER: 117168515Sgshapiro len = sizeof(s->s_mailer); 11864562Sgshapiro break; 11938032Speter 12038032Speter case ST_ALIAS: 121168515Sgshapiro len = sizeof(s->s_alias); 12238032Speter break; 12338032Speter 12438032Speter case ST_MAPCLASS: 125168515Sgshapiro len = sizeof(s->s_mapclass); 12638032Speter break; 12738032Speter 12838032Speter case ST_MAP: 129168515Sgshapiro len = sizeof(s->s_map); 13038032Speter break; 13138032Speter 13238032Speter case ST_HOSTSIG: 133168515Sgshapiro len = sizeof(s->s_hostsig); 13438032Speter break; 13538032Speter 13638032Speter case ST_NAMECANON: 137168515Sgshapiro len = sizeof(s->s_namecanon); 13838032Speter break; 13938032Speter 14038032Speter case ST_MACRO: 141168515Sgshapiro len = sizeof(s->s_macro); 14238032Speter break; 14338032Speter 14438032Speter case ST_RULESET: 145168515Sgshapiro len = sizeof(s->s_ruleset); 14638032Speter break; 14738032Speter 14864562Sgshapiro case ST_HEADER: 149168515Sgshapiro len = sizeof(s->s_header); 15064562Sgshapiro break; 15164562Sgshapiro 15238032Speter case ST_SERVICE: 153168515Sgshapiro len = sizeof(s->s_service); 15438032Speter break; 15538032Speter 15690792Sgshapiro#if LDAPMAP 15777349Sgshapiro case ST_LMAP: 158168515Sgshapiro len = sizeof(s->s_lmap); 15938032Speter break; 16064562Sgshapiro#endif /* LDAPMAP */ 16138032Speter 16290792Sgshapiro#if MILTER 16364562Sgshapiro case ST_MILTER: 164168515Sgshapiro len = sizeof(s->s_milter); 16564562Sgshapiro break; 16690792Sgshapiro#endif /* MILTER */ 16764562Sgshapiro 16890792Sgshapiro case ST_QUEUE: 169168515Sgshapiro len = sizeof(s->s_quegrp); 17090792Sgshapiro break; 17190792Sgshapiro 172132943Sgshapiro#if SOCKETMAP 173132943Sgshapiro case ST_SOCKETMAP: 174168515Sgshapiro len = sizeof(s->s_socketmap); 175132943Sgshapiro break; 176132943Sgshapiro#endif /* SOCKETMAP */ 177132943Sgshapiro 17838032Speter default: 17964562Sgshapiro /* 18090792Sgshapiro ** Each mailer has its own MCI stab entry: 18164562Sgshapiro ** 18264562Sgshapiro ** s = stab(host, ST_MCI + m->m_mno, ST_ENTER); 18364562Sgshapiro ** 18464562Sgshapiro ** Therefore, anything ST_MCI or larger is an s_mci. 18564562Sgshapiro */ 18664562Sgshapiro 18738032Speter if (type >= ST_MCI) 188168515Sgshapiro len = sizeof(s->s_mci); 18938032Speter else 19038032Speter { 19138032Speter syserr("stab: unknown symbol type %d", type); 192168515Sgshapiro len = sizeof(s->s_value); 19338032Speter } 19438032Speter break; 19538032Speter } 196168515Sgshapiro len += sizeof(*s) - sizeof(s->s_value); 19738032Speter 19864562Sgshapiro if (tTd(36, 15)) 19990792Sgshapiro sm_dprintf("size of stab entry: %d\n", len); 20064562Sgshapiro 20138032Speter /* make new entry */ 20290792Sgshapiro s = (STAB *) sm_pmalloc_x(len); 20364562Sgshapiro memset((char *) s, '\0', len); 20490792Sgshapiro s->s_name = sm_pstrdup_x(name); 20590792Sgshapiro s->s_symtype = type; 20638032Speter 20738032Speter /* link it in */ 20838032Speter *ps = s; 20938032Speter 21064562Sgshapiro /* set a default value for rulesets */ 21164562Sgshapiro if (type == ST_RULESET) 21264562Sgshapiro s->s_ruleset = -1; 21364562Sgshapiro 21464562Sgshapiro return s; 21538032Speter} 21690792Sgshapiro/* 21738032Speter** STABAPPLY -- apply function to all stab entries 21838032Speter** 21938032Speter** Parameters: 22090792Sgshapiro** func -- the function to apply. It will be given two 22190792Sgshapiro** parameters (the stab entry and the arg). 22238032Speter** arg -- an arbitrary argument, passed to func. 22338032Speter** 22438032Speter** Returns: 22538032Speter** none. 22638032Speter*/ 22738032Speter 22838032Spetervoid 22938032Speterstabapply(func, arg) 23038032Speter void (*func)__P((STAB *, int)); 23138032Speter int arg; 23238032Speter{ 23338032Speter register STAB **shead; 23438032Speter register STAB *s; 23538032Speter 23638032Speter for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 23738032Speter { 23838032Speter for (s = *shead; s != NULL; s = s->s_next) 23938032Speter { 24038032Speter if (tTd(36, 90)) 24190792Sgshapiro sm_dprintf("stabapply: trying %d/%s\n", 24290792Sgshapiro s->s_symtype, s->s_name); 24338032Speter func(s, arg); 24438032Speter } 24538032Speter } 24638032Speter} 24790792Sgshapiro/* 24864562Sgshapiro** QUEUEUP_MACROS -- queueup the macros in a class 24964562Sgshapiro** 25064562Sgshapiro** Write the macros listed in the specified class into the 25164562Sgshapiro** file referenced by qfp. 25264562Sgshapiro** 25364562Sgshapiro** Parameters: 25464562Sgshapiro** class -- class ID. 25590792Sgshapiro** qfp -- file pointer to the queue file. 25664562Sgshapiro** e -- the envelope. 25764562Sgshapiro** 25864562Sgshapiro** Returns: 25964562Sgshapiro** none. 26064562Sgshapiro*/ 26164562Sgshapiro 26264562Sgshapirovoid 26364562Sgshapiroqueueup_macros(class, qfp, e) 26464562Sgshapiro int class; 26590792Sgshapiro SM_FILE_T *qfp; 26664562Sgshapiro ENVELOPE *e; 26764562Sgshapiro{ 26864562Sgshapiro register STAB **shead; 26964562Sgshapiro register STAB *s; 27064562Sgshapiro 27164562Sgshapiro if (e == NULL) 27264562Sgshapiro return; 27364562Sgshapiro 27471345Sgshapiro class = bitidx(class); 27564562Sgshapiro for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 27664562Sgshapiro { 27764562Sgshapiro for (s = *shead; s != NULL; s = s->s_next) 27864562Sgshapiro { 27964562Sgshapiro int m; 28064562Sgshapiro char *p; 28164562Sgshapiro 28290792Sgshapiro if (s->s_symtype == ST_CLASS && 28390792Sgshapiro bitnset(bitidx(class), s->s_class) && 284120256Sgshapiro (m = macid(s->s_name)) != 0 && 28564562Sgshapiro (p = macvalue(m, e)) != NULL) 28664562Sgshapiro { 28790792Sgshapiro (void) sm_io_fprintf(qfp, SM_TIME_DEFAULT, 28890792Sgshapiro "$%s%s\n", 28990792Sgshapiro s->s_name, 29090792Sgshapiro denlstring(p, true, 29190792Sgshapiro false)); 29264562Sgshapiro } 29364562Sgshapiro } 29464562Sgshapiro } 29564562Sgshapiro} 29690792Sgshapiro/* 29764562Sgshapiro** COPY_CLASS -- copy class members from one class to another 29864562Sgshapiro** 29964562Sgshapiro** Parameters: 30064562Sgshapiro** src -- source class. 30164562Sgshapiro** dst -- destination class. 30264562Sgshapiro** 30364562Sgshapiro** Returns: 30464562Sgshapiro** none. 30564562Sgshapiro*/ 30664562Sgshapiro 30764562Sgshapirovoid 30864562Sgshapirocopy_class(src, dst) 30964562Sgshapiro int src; 31064562Sgshapiro int dst; 31164562Sgshapiro{ 31264562Sgshapiro register STAB **shead; 31364562Sgshapiro register STAB *s; 31464562Sgshapiro 31571345Sgshapiro src = bitidx(src); 31671345Sgshapiro dst = bitidx(dst); 31764562Sgshapiro for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 31864562Sgshapiro { 31964562Sgshapiro for (s = *shead; s != NULL; s = s->s_next) 32064562Sgshapiro { 32190792Sgshapiro if (s->s_symtype == ST_CLASS && 32271345Sgshapiro bitnset(src, s->s_class)) 32364562Sgshapiro setbitn(dst, s->s_class); 32464562Sgshapiro } 32564562Sgshapiro } 32664562Sgshapiro} 32790792Sgshapiro 32890792Sgshapiro/* 32990792Sgshapiro** RMEXPSTAB -- remove expired entries from SymTab. 33090792Sgshapiro** 33190792Sgshapiro** These entries need to be removed in long-running processes, 33290792Sgshapiro** e.g., persistent queue runners, to avoid consuming memory. 33390792Sgshapiro** 33490792Sgshapiro** XXX It might be useful to restrict the maximum TTL to avoid 33590792Sgshapiro** caching data very long. 33690792Sgshapiro** 33790792Sgshapiro** Parameters: 33890792Sgshapiro** none. 33990792Sgshapiro** 34090792Sgshapiro** Returns: 34190792Sgshapiro** none. 34290792Sgshapiro** 34390792Sgshapiro** Side Effects: 34490792Sgshapiro** can remove entries from the symbol table. 34590792Sgshapiro*/ 34690792Sgshapiro 34790792Sgshapiro#define SM_STAB_FREE(x) \ 34890792Sgshapiro do \ 34990792Sgshapiro { \ 35090792Sgshapiro char *o = (x); \ 35190792Sgshapiro (x) = NULL; \ 35290792Sgshapiro if (o != NULL) \ 35390792Sgshapiro sm_free(o); \ 35490792Sgshapiro } while (0) 35590792Sgshapiro 35690792Sgshapirovoid 35790792Sgshapirormexpstab() 35890792Sgshapiro{ 35990792Sgshapiro int i; 36090792Sgshapiro STAB *s, *p, *f; 36190792Sgshapiro time_t now; 36290792Sgshapiro 36390792Sgshapiro now = curtime(); 36490792Sgshapiro for (i = 0; i < STABSIZE; i++) 36590792Sgshapiro { 36690792Sgshapiro p = NULL; 36790792Sgshapiro s = SymTab[i]; 36890792Sgshapiro while (s != NULL) 36990792Sgshapiro { 37090792Sgshapiro switch (s->s_symtype) 37190792Sgshapiro { 37290792Sgshapiro case ST_HOSTSIG: 37390792Sgshapiro if (s->s_hostsig.hs_exp >= now) 37490792Sgshapiro goto next; /* not expired */ 37590792Sgshapiro SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */ 37690792Sgshapiro break; 37790792Sgshapiro 37890792Sgshapiro case ST_NAMECANON: 37990792Sgshapiro if (s->s_namecanon.nc_exp >= now) 38090792Sgshapiro goto next; /* not expired */ 38190792Sgshapiro SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */ 38290792Sgshapiro break; 38390792Sgshapiro 38490792Sgshapiro default: 38590792Sgshapiro if (s->s_symtype >= ST_MCI) 38690792Sgshapiro { 38790792Sgshapiro /* call mci_uncache? */ 38890792Sgshapiro SM_STAB_FREE(s->s_mci.mci_status); 38990792Sgshapiro SM_STAB_FREE(s->s_mci.mci_rstatus); 39090792Sgshapiro SM_STAB_FREE(s->s_mci.mci_heloname); 39190792Sgshapiro#if 0 39290792Sgshapiro /* not dynamically allocated */ 39390792Sgshapiro SM_STAB_FREE(s->s_mci.mci_host); 39490792Sgshapiro SM_STAB_FREE(s->s_mci.mci_tolist); 39590792Sgshapiro#endif /* 0 */ 39690792Sgshapiro#if SASL 39790792Sgshapiro /* should always by NULL */ 39890792Sgshapiro SM_STAB_FREE(s->s_mci.mci_sasl_string); 39990792Sgshapiro#endif /* SASL */ 40090792Sgshapiro if (s->s_mci.mci_rpool != NULL) 40190792Sgshapiro { 40290792Sgshapiro sm_rpool_free(s->s_mci.mci_rpool); 40390792Sgshapiro s->s_mci.mci_macro.mac_rpool = NULL; 40490792Sgshapiro s->s_mci.mci_rpool = NULL; 40590792Sgshapiro } 40690792Sgshapiro break; 40790792Sgshapiro } 40890792Sgshapiro next: 40990792Sgshapiro p = s; 41090792Sgshapiro s = s->s_next; 41190792Sgshapiro continue; 41290792Sgshapiro } 41390792Sgshapiro 41490792Sgshapiro /* remove entry */ 41590792Sgshapiro SM_STAB_FREE(s->s_name); /* XXX */ 41690792Sgshapiro f = s; 41790792Sgshapiro s = s->s_next; 41890792Sgshapiro sm_free(f); /* XXX */ 41990792Sgshapiro if (p == NULL) 42090792Sgshapiro SymTab[i] = s; 42190792Sgshapiro else 42290792Sgshapiro p->s_next = s; 42390792Sgshapiro } 42490792Sgshapiro } 42590792Sgshapiro} 42690792Sgshapiro 42790792Sgshapiro#if SM_HEAP_CHECK 42890792Sgshapiro/* 42990792Sgshapiro** DUMPSTAB -- dump symbol table. 43090792Sgshapiro** 43190792Sgshapiro** For debugging. 43290792Sgshapiro*/ 43390792Sgshapiro 43490792Sgshapiro#define MAXSTTYPES (ST_MCI + 1) 43590792Sgshapiro 43690792Sgshapirovoid 43790792Sgshapirodumpstab() 43890792Sgshapiro{ 43990792Sgshapiro int i, t, total, types[MAXSTTYPES]; 44090792Sgshapiro STAB *s; 44190792Sgshapiro static int prevt[MAXSTTYPES], prev = 0; 44290792Sgshapiro 44390792Sgshapiro total = 0; 44490792Sgshapiro for (i = 0; i < MAXSTTYPES; i++) 44590792Sgshapiro types[i] = 0; 44690792Sgshapiro for (i = 0; i < STABSIZE; i++) 44790792Sgshapiro { 44890792Sgshapiro s = SymTab[i]; 44990792Sgshapiro while (s != NULL) 45090792Sgshapiro { 45190792Sgshapiro ++total; 45290792Sgshapiro t = s->s_symtype; 45390792Sgshapiro if (t > MAXSTTYPES - 1) 45490792Sgshapiro t = MAXSTTYPES - 1; 45590792Sgshapiro types[t]++; 45690792Sgshapiro s = s->s_next; 45790792Sgshapiro } 45890792Sgshapiro } 45990792Sgshapiro sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev); 46090792Sgshapiro prev = total; 46190792Sgshapiro for (i = 0; i < MAXSTTYPES; i++) 46290792Sgshapiro { 46390792Sgshapiro if (types[i] != 0) 46490792Sgshapiro { 46590792Sgshapiro sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)", 46690792Sgshapiro i, types[i], types[i] - prevt[i]); 46790792Sgshapiro } 46890792Sgshapiro prevt[i] = types[i]; 46990792Sgshapiro } 47090792Sgshapiro} 47190792Sgshapiro#endif /* SM_HEAP_CHECK */ 472