/*
* 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 */
syntax highlighted by Code2HTML, v. 0.9.1