/* * Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: map.h,v 1.63 2006/11/13 00:42:04 ca Exp $ */ #ifndef SM_MAP_H #define SM_MAP_H 1 #include "sm/generic.h" #include "sm/types.h" #include "sm/magic.h" #include "sm/cstr.h" #include "sm/str-int.h" #include "sm/rdstr.h" #include "sm/time.h" #include "sm/map-str.h" #if MTA_USE_PTHREADS #include "sm/pthread.h" #endif /* XXX Missing: flags the specify who is responsible for memory allocation: DB should allocate key/data caller allocates key/data (and preserves it) what about persistence? there should be some flags the specify what a DB type can offer, e.g., DB close removes all data, maybe whether DB can't/won't allocate data. there should be also something that specifies the type of data that is stored, currently it is sm_str_P for BDB but char * for BHT. */ #if 0 typedef void *(*sm_map_key_alloc_F)(size_t size, void *app_ctx); typedef void (*sm_map_key_free_F)(void *ptr, void *app_ctx); typedef void *(*sm_map_data_alloc_F)(size_t size, void *app_ctx); typedef void (*sm_map_data_free_F)(void *ptr, void *app_ctx); #endif /* 0 */ struct sm_map_entry_S { sm_map_key_T sm_map_entry_key; sm_map_data_T sm_map_entry_data; }; struct sm_map_cursor_S { uint32_t sm_map_cursor_state; void *sm_map_cursor_val; }; /* XXX should one of these be 0 (to act as default)? */ #define SMAP_MODE_RDONLY 0x01 #define SMAP_MODE_WRONLY 0x02 #define SMAP_MODE_RDWR 0x04 #define SMAP_MODE_CREATE 0x08 /* sm map option, rest defined in implementation specific include files */ #define SMPO_END 0x0000 /* end of options (vararg) [must be 0] */ /* ** Some "generic" map open/setopt options ** Use a type marker: 0: int, 1: void * ** This is required to properly access the vararg and the data ** stored in sm_map_opt_T (see libsmmap/map.h). ** Note: short/char are expanded to int, so it's not necessary to have ** type markers for those. */ #define SMPO_INT 0x0000 #define SMPO_PTR 0x0001 #define SMPO_CACHE_SIZE (0x0010|SMPO_INT) #define SMPO_HASH_NELEM (0x0020|SMPO_INT) #define SMPO_MAX_ELEM (0x0030|SMPO_INT) #define SMPO_PORT (0x0040|SMPO_INT) /* port for socket map etc */ #define SMPO_IPV4 (0x0050|SMPO_INT) /* IPv4 address */ #define SMPO_SOCKPATH (0x0060|SMPO_PTR) /* path to Unix domain socket */ #define SMPO_MAP (0x0070|SMPO_PTR) /* sequence map: map to use */ #define SMPO_MAPNAME (0x0080|SMPO_PTR) /* sequence map: map name to use */ #define SMPO_TMOUT (0x0090|SMPO_INT) /* timeout for lookups */ #define SMPO_CAPS (0x00A0|SMPO_INT) /* capabilities */ #define SMPO_STR (0x0100|SMPO_PTR) /* str to use for str map */ #define SMPO_INIT_CB (0x0200|SMPO_PTR) /* init cb function (hash map) */ #define SMPO_TYPE_MASK 0x0000F #define SMPO_GET_TYPE(opt) ((opt) & SMPO_TYPE_MASK) #if 0 /* defines for sm_map_open() varargs: type and value, as well as end marker */ #define SM_MAPOPEN_INT 1 #define SM_MAPOPEN_UINT 2 #define SM_MAPOPEN_STR 3 #define SM_MAPOPEN_CSTR 4 #define SM_MAPOPEN_BUF 5 #define SM_MAPOPEN_END 8 #endif /* 0 */ /* user supplied function to initialize a map, called from open */ typedef sm_ret_T (*sm_map_init_cb_F)(void *app_ctx); /* ------------------------------------------------------------ */ /* function prototypes */ /* basic map function */ sm_ret_T sm_map_create(sm_maps_P _maps, sm_cstr_P _type, uint32_t _flags, sm_map_P *_map); sm_ret_T sm_map_open(sm_maps_P _maps, const sm_cstr_P _name, const sm_cstr_P _type, uint32_t _flags, const char *_path, int _mode, sm_map_P *_pmap, ...); sm_ret_T sm_map_close(sm_map_P _map, uint32_t _flags); sm_ret_T sm_map_destroy(sm_map_P _map, uint32_t flags); sm_ret_T sm_map_reopen(sm_map_P _map, uint32_t flags, ...); sm_ret_T sm_map_setopt(sm_map_P _map, ...); sm_ret_T sm_map_getopt(sm_map_P _map, int _which, void *_valp); sm_ret_T sm_map_lookup(sm_map_P _map, uint32_t _flags, sm_map_key_P _key, sm_map_data_P _data); sm_ret_T sm_map_add(sm_map_P _map, sm_map_key_P _key, sm_map_data_P _data, uint _flags); sm_ret_T sm_map_rm(sm_map_P _map, sm_map_key_P _key); sm_ret_T sm_map_rewrite(sm_map_P _map, uint32_t _flags, sm_str_P _old, sm_str_P _new); /* specific lookup function */ sm_ret_T sm_map_lookup_ip(sm_map_P _map, sm_str_P _ip, sm_str_P _tag, uint32_t _flags, sm_str_P _rhs); sm_ret_T sm_map_lookup_domain(sm_map_P _map, sm_rdstr_P _domain, sm_str_P _tag, uint32_t _flags, sm_str_P _rhs); sm_ret_T sm_map_lookup_addr(sm_map_P _map, sm_str_P _user, sm_str_P _detail, sm_str_P _domain, sm_str_P _tag, uchar delim, uint32_t _flags, sm_str_P _rhs); /* ------------------------------------------------------------ */ /* flags for map (this isn't correct yet) */ #define SMMAP_FL_NONE 0x00000000u #define SMMAP_FL_CREATED 0x00000001u #define SMMAP_FL_OPEN 0x00000002u #define SMMAP_FL_OPENBOGUS 0x00000004u #define SMMAP_FL_CLOSING 0x00000008u #define SMMAP_FL_CLOSED 0x00000010u #define SMMAP_FL_ALLOCKEY 0x00000020u #define SMMAP_FL_ALLOCDATA 0x00000040u #define SMMAP_FL_FREEKEY 0x00000080u #define SMMAP_FL_FREEDATA 0x00000100u #define SMMAP_FL_CLOSEFREEKEY 0x00000200u #define SMMAP_FL_CLOSEFREEDATA 0x00000400u #define SMMAP_FL_VALID 0x00000800u #define SMMAP_FL_INCLNULL 0x00001000u #define SMMAP_FL_OPTIONAL 0x00002000u #define SMMAP_FL_NOFOLDCASE 0x00004000u #define SMMAP_FL_MATCHONLY 0x00008000u #define SMMAP_FL_WRITABLE 0x00010000u #define SMMAP_FL_ALIAS 0x00020000u #define SMMAP_FL_TRY0NUL 0x00040000u #define SMMAP_FL_TRY1NUL 0x00080000u #define SMMAP_FL_LOCKED 0x00100000u #define SMMAP_FL_KEEPQUOTES 0x00200000u #define SMMAP_FL_NODEFER 0x00400000u #define SMMAP_FL_SINGLEMATCH 0x00800000u #define SMMAP_SET_FL(map, fl) (map)->sm_map_flags |= (fl) #define SMMAP_CLR_FL(map, fl) (map)->sm_map_flags &= ~(fl) #define SMMAP_IS_FL(map, fl) (((map)->sm_map_flags & (fl)) != 0) /* ** Capabilities of a map. ** What about the placement of '@'? Should that also be reflected here? ** (after user or before domain) */ #define SMMAP_CAPS_NONE 0x00000000u #define SMMAP_CAPS_DYNAMIC 0x00000001u /* dynamic close/open */ #define SMMAP_CAPS_DOMAIN 0x00000010u /* contains domain part */ #define SMMAP_CAPS_LOCALPART 0x00000020u /* contains local parts */ #define SMMAP_CAPS_DETAIL 0x00000040u /* may contains +detail */ #define SMMAP_CAPS_TAG 0x00000080u /* tag */ #define SMMAP_CAPS_IPV4 0x00000100u /* IPv4 */ #define SMMAP_CAPS_IPV6 0x00000200u /* IPv6 */ #define SMMAP_CAPS_LTMASK 0x000003F0u /* mask for lookup types */ #define SMMAP_CAPS_LTALL (SMMAP_CAPS_DOMAIN|SMMAP_CAPS_LOCALPART|\ SMMAP_CAPS_DETAIL|SMMAP_CAPS_TAG|\ SMMAP_CAPS_IPV4|SMMAP_CAPS_IPV6) #define SMMAP_SET_CAPS(map, caps) (map)->sm_map_caps |= (caps) #define SMMAP_CLR_CAPS(map, caps) (map)->sm_map_caps &= ~(caps) #define SMMAP_IS_CAPS(map, caps) (((map)->sm_map_caps & (caps)) != 0) /* ** Flags for lookup/add/rm etc ** There are different kinds: ** - those which describe actions (what to do) ** - those which describe features (what kind of key etc) */ #define SMMAP_FL_LWR_KEY 0x00000001u /* change key to lower case */ /* ** Type of key (for lookup/add/rm etc) ** NOTE: this is also used by capabilities! The values MUST be identical! */ #define SMMAP_FL_HAS_DOMAIN SMMAP_CAPS_DOMAIN /* contains domain */ #define SMMAP_FL_HAS_LOCALPART SMMAP_CAPS_LOCALPART /* contains localpart */ #define SMMAP_FL_HAS_DETAIL SMMAP_CAPS_DETAIL /* contains +detail */ #define SMMAP_FL_HAS_TAG SMMAP_CAPS_TAG /* has tag */ #define SMMAP_FL_HAS_IPV4 SMMAP_CAPS_IPV4 /* IPv4 address */ #define SMMAP_FL_HAS_IPV6 SMMAP_CAPS_IPV6 /* IPv6 address */ #define SMMAP_FL_HAS_LTALL (SMMAP_FL_HAS_DOMAIN|SMMAP_FL_HAS_LOCALPART|\ SMMAP_FL_HAS_DETAIL|SMMAP_FL_HAS_TAG|\ SMMAP_FL_HAS_IPV4|SMMAP_FL_HAS_IPV6) #define SMMAP_LT_M_CAPS(map, lookuptype) \ (((map)->sm_map_caps & (lookuptype & SMMAP_CAPS_LTMASK)) != 0) /* ------------------------------------------------------- */ /* lookup flags (for abstraction layer: sm_map_lookup_*()) */ #define SMMAP_LFL_NONE 0x00000000u #define SMMAP_LFL_FULL 0x00000001u /* full (exact) lookup */ #define SMMAP_LFL_DETPLUS 0x00000002u /* user++ lookup */ #define SMMAP_LFL_DETSTAR 0x00000004u /* user+* lookup */ #define SMMAP_LFL_STAR 0x00000008u /* user* lookup */ #define SMMAP_LFL_USER 0x00000010u /* user lookup */ #define SMMAP_LFL_DOMAIN 0x00000020u /* just domain (wo localpart) */ #define SMMAP_LFL_LOCAL 0x00000040u /* just localpart (wo domain) */ #define SMMAP_LFL_DOTSUBDOM 0x00000200u /* .sub.domain */ #define SMMAP_LFL_DOT 0x00000400u /* just . (for default if no tag) */ #define SMMAP_LFL_IMPLDET 0x00000800u /* user+detail matches user */ #define SMMAP_LFL_NOAT 0x00001000u /* don't put @ after user */ #define SMMAP_LFL_TAG 0x00002000u /* just tag (if not NULL) */ #define SMMAP_LFL_REPL 0x00004000u /* replace %n with wildcard match */ #define SMMAP_LFL_MCR_REPL 0x00008000u /* use macro replacement ${name} */ #define SMMAP_LFL_SUBNETS 0x00010000u /* IP address: lookup all subnets */ #define SMMAP_LFL_ALL 0x000007ffu /* default lookups */ #define SMMAP_LFL_ALIAS (SMMAP_LFL_FULL|SMMAP_LFL_DETPLUS|SMMAP_LFL_DETSTAR|SMMAP_LFL_STAR|SMMAP_LFL_USER|SMMAP_LFL_NOAT|SMMAP_LFL_LOCAL) #define SMMAP_LFL_ALIASWODET (SMMAP_LFL_FULL|SMMAP_LFL_STAR|SMMAP_LFL_USER|SMMAP_LFL_NOAT|SMMAP_LFL_LOCAL) #define SMMAP_LFL_DET (SMMAP_LFL_DETPLUS|SMMAP_LFL_DETSTAR) #define SMMAP_LFL_VIRTUSER (SMMAP_LFL_FULL|SMMAP_LFL_DETPLUS|SMMAP_LFL_DETSTAR|SMMAP_LFL_USER|SMMAP_LFL_DOTSUBDOM|SMMAP_LFL_LOCAL) #define SMMAP_LFL_MT (SMMAP_LFL_DOMAIN|SMMAP_LFL_DOTSUBDOM|SMMAP_LFL_DOT) #define SMMAP_IS_LFL(flags, fl) (((flags) & (fl)) != 0) /* map lookup return values */ #define SM_MAP_FOUND SM_SUCCESS /* ** return codes from lookup functions: ** SM_E_NOMAP: no map defined ** SM_E_NOTIMPL: (lookup) function not defined ** ENOENT: missing some internal entry, e.g., a context pointer ** SM_E_UNAVAIL: feature/capability unavailable ** SM_E_NOTFOUND: no matching entry found ** SM_E_TEMPMAP: temporary lookup error ** SM_E_PERMMAP: permanent lookup error ** SM_E_OVFLW_NS: buffer not big enough for result ** (usually handled internally by map layer) ** ENOMEM: out of memory ** SM_E_PR_ERR: protocol error (server response was bogus) */ /* entry found, but result doesn't fit into provided data str */ #define SM_MAP_DATA2BIG sm_error_temp(SM_EM_MAP, SM_E_OVFLW_NS) #define SM_MAP_NOTFOUND sm_error_perm(SM_EM_MAP, SM_E_NOTFOUND) #define SM_MAP_TEMPMAP sm_error_temp(SM_EM_MAP, SM_E_TEMPMAP) #define SM_MAP_PERMMAP sm_error_perm(SM_EM_MAP, SM_E_PERMMAP) /* map_add flags */ #define SMMAP_AFL_NONE 0x0000u #define SMMAP_AFL_UNIQUE 0x0001u /* unique keys */ #if SM_MAP_CHECK # define SM_IS_MAP(map) SM_REQUIRE_ISA((map), SM_MAP_MAGIC) #else # define SM_IS_MAP(map) SM_REQUIRE((map) != NULL) #endif #define SM_IS_KEY(key) SM_IS_BUF(key) #define SM_IS_DATA(data) SM_IS_BUF(data) sm_ret_T sm_mapname_find(sm_maps_P _maps, const sm_cstr_P _map_name, sm_map_P *_pmap); sm_ret_T sm_mapname_findc(sm_maps_P _maps, const char *_map_name, sm_map_P *_pmap); #endif /* SM_MAP_H */