1/*++
2/* NAME
3/*	smtpd_resolve 3
4/* SUMMARY
5/*	caching resolve client
6/* SYNOPSIS
7/*	#include <smtpd_resolve.h>
8/*
9/*	void	smtpd_resolve_init(cache_size)
10/*	int	cache_size;
11/*
12/*	const RESOLVE_REPLY *smtpd_resolve_addr(addr)
13/*	const char *addr;
14/* DESCRIPTION
15/*	This module maintains a resolve client cache that persists
16/*	across SMTP sessions (not process life times). Addresses
17/*	are always resolved in local rewriting context.
18/*
19/*	smtpd_resolve_init() initializes the cache and must
20/*	called once before the cache can be used.
21/*
22/*	smtpd_resolve_addr() resolves one address or returns
23/*	a known result from cache.
24/*
25/*	Arguments:
26/* .IP cache_size
27/*	The requested cache size.
28/* .IP addr
29/*	The address to resolve.
30/* DIAGNOSTICS
31/*	All errors are fatal.
32/* BUGS
33/*	The recipient address is always case folded to lowercase.
34/*	Changing this requires great care, since the address is used
35/*	for policy lookups.
36/* LICENSE
37/* .ad
38/* .fi
39/*	The Secure Mailer license must be distributed with this software.
40/* AUTHOR(S)
41/*	Wietse Venema
42/*	IBM T.J. Watson Research
43/*	P.O. Box 704
44/*	Yorktown Heights, NY 10598, USA
45/*--*/
46
47/* System library. */
48
49#include <sys_defs.h>
50
51/* Utility library. */
52
53#include <msg.h>
54#include <mymalloc.h>
55#include <vstring.h>
56#include <ctable.h>
57#include <stringops.h>
58
59/* Global library. */
60
61#include <rewrite_clnt.h>
62#include <resolve_clnt.h>
63#include <mail_proto.h>
64
65/* Application-specific. */
66
67#include <smtpd_resolve.h>
68
69static CTABLE *smtpd_resolve_cache;
70
71#define STR(x) vstring_str(x)
72
73/* resolve_pagein - page in an address resolver result */
74
75static void *resolve_pagein(const char *addr, void *unused_context)
76{
77    static VSTRING *query;
78    RESOLVE_REPLY *reply;
79
80    /*
81     * Initialize on the fly.
82     */
83    if (query == 0)
84	query = vstring_alloc(10);
85
86    /*
87     * Initialize.
88     */
89    reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply));
90    resolve_clnt_init(reply);
91
92    /*
93     * Resolve the address.
94     */
95    rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query);
96    resolve_clnt_query(STR(query), reply);
97    lowercase(STR(reply->recipient));		/* XXX */
98
99    /*
100     * Save the result.
101     */
102    return ((void *) reply);
103}
104
105/* resolve_pageout - page out an address resolver result */
106
107static void resolve_pageout(void *data, void *unused_context)
108{
109    RESOLVE_REPLY *reply = (RESOLVE_REPLY *) data;
110
111    resolve_clnt_free(reply);
112    myfree((void *) reply);
113}
114
115/* smtpd_resolve_init - set up global cache */
116
117void    smtpd_resolve_init(int cache_size)
118{
119
120    /*
121     * Sanity check.
122     */
123    if (smtpd_resolve_cache)
124	msg_panic("smtpd_resolve_init: multiple initialization");
125
126    /*
127     * Initialize the resolved address cache. Note: the cache persists across
128     * SMTP sessions so we cannot make it dependent on session state.
129     */
130    smtpd_resolve_cache = ctable_create(cache_size, resolve_pagein,
131					resolve_pageout, (void *) 0);
132}
133
134/* smtpd_resolve_addr - resolve cached addres */
135
136const RESOLVE_REPLY *smtpd_resolve_addr(const char *addr)
137{
138
139    /*
140     * Sanity check.
141     */
142    if (smtpd_resolve_cache == 0)
143	msg_panic("smtpd_resolve_addr: missing initialization");
144
145    /*
146     * Reply from the read-through cache.
147     */
148    return (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr);
149}
150