xref: /freebsd/contrib/sendmail/libmilter/docs/overview.html (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
1<HTML>
2<HEAD>
3<TITLE>Technical Overview</TITLE>
4</HEAD>
5<BODY>
6<!--
7$Id: overview.html,v 1.22 2013-11-22 20:51:39 ca Exp $
8-->
9
10<H1>Technical Overview</H1>
11
12<H2>Contents</H2>
13
14<UL>
15    <LI><A HREF="#Initialization">Initialization</A>
16    <LI><A HREF="#ControlFlow">Control Flow</A>
17    <LI><A HREF="#Multithreading">Multithreading</A>
18    <LI><A HREF="#ResourceManagement">Resource Management</A>
19    <LI><A HREF="#SignalHandling">Signal Handling</A>
20</UL>
21
22<H2><A NAME="Initialization">Initialization</A></H2>
23
24In addition to its own initialization,
25libmilter expects a filter to initialize several parameters
26before calling <A HREF="smfi_main.html">smfi_main</A>:
27<UL>
28    <LI>The callbacks the filter wishes to be called, and the types of
29    message modification it intends to perform (required, see
30    <A HREF="smfi_register.html">smfi_register</A>).
31
32    <LI>The socket address to be used when communicating with the MTA
33    (required, see <A HREF="smfi_setconn.html">smfi_setconn</A>).
34
35    <LI>The number of seconds to wait for MTA connections before
36    timing out (optional, see
37    <A HREF="smfi_settimeout.html">smfi_settimeout</A>).
38</UL>
39<P>
40If the filter fails to initialize libmilter,
41or if one or more of the parameters it has passed are invalid,
42a subsequent call to smfi_main will fail.
43
44<H2><A NAME="ControlFlow">Control Flow</A></H2>
45
46<P>
47The following pseudocode describes the filtering process from the
48perspective of a set of <CODE>N</CODE> MTA's,
49each corresponding to a connection.
50Callbacks are shown beside the processing stages in which they are invoked;
51if no callbacks are defined for a particular stage,
52that stage may be bypassed.
53Though it is not shown,
54processing may be aborted at any time during a message,
55in which case the
56<A HREF="xxfi_abort.html">xxfi_abort</A> callback is invoked and control
57returns to <CODE>MESSAGE</CODE>.
58<P>
59<PRE>
60For each of N connections
61{
62	For each filter
63		egotiate MTA/milter capabilities/requirements (<A HREF="xxfi_negotiate.html">xxfi_negotiate</A>)
64	For each filter
65		process connection (<A HREF="xxfi_connect.html">xxfi_connect</A>)
66	For each filter
67		process helo/ehlo (<A HREF="xxfi_helo.html">xxfi_helo</A>)
68MESSAGE:For each message in this connection (sequentially)
69	{
70		For each filter
71			process sender (<A HREF="xxfi_envfrom.html">xxfi_envfrom</A>)
72		For each recipient
73		{
74			For each filter
75				process recipient (<A HREF="xxfi_envrcpt.html">xxfi_envrcpt</A>)
76		}
77		For each filter
78		{
79			process DATA (<A HREF="xxfi_data.html">xxfi_data</A>)
80			For each header
81				process header (<A HREF="xxfi_header.html">xxfi_header</A>)
82			process end of headers (<A HREF="xxfi_eoh.html">xxfi_eoh</A>)
83			For each body block
84				process this body block (<A HREF="xxfi_body.html">xxfi_body</A>)
85			process end of message (<A HREF="xxfi_eom.html">xxfi_eom</A>)
86		}
87	}
88	For each filter
89		process end of connection (<A HREF="xxfi_close.html">xxfi_close</A>)
90}
91</PRE>
92
93<P>Note: Filters are contacted in order defined in config file.</P>
94
95<P>
96To write a filter, a vendor supplies callbacks to process relevant
97parts of a message transaction.
98The library then controls all sequencing, threading,
99and protocol exchange with the MTA.
100<A HREF="#figure-3">Figure 3</A> outlines control flow for a filter
101process, showing where different callbacks are invoked.
102</P>
103
104<DIV ALIGN="center"><A NAME="figure-3"></A>
105<TABLE border=1 cellspacing=0 cellpadding=2 width="70%">
106<TR bgcolor="#dddddd"><TH>SMTP Commands</TH><TH>Milter Callbacks</TH></TR>
107<TR><TD>(open SMTP connection)</TD><TD>xxfi_connect</TD></TR>
108<TR><TD>HELO ...</TD><TD>xxfi_helo</TD></TR>
109<TR><TD>MAIL From: ...</TD><TD>xxfi_envfrom</TD></TR>
110<TR><TD>RCPT To: ...</TD><TD>xxfi_envrcpt</TD></TR>
111<TR><TD>[more RCPTs]</TD><TD>[xxfi_envrcpt]</TD></TR>
112<TR><TD>DATA</TD><TD>xxfi_data</TD></TR>
113<TR><TD>Header: ...</TD><TD>xxfi_header</TD></TR>
114<TR><TD>[more headers]</TD><TD>[xxfi_header]</TD></TR>
115<TR><TD>&nbsp;</TD><TD>xxfi_eoh</TD></TR>
116<TR><TD>body... </TD><TD>xxfi_body</TD></TR>
117<TR><TD>[more body...]</TD><TD>[xxfi_body]</TD></TR>
118<TR><TD>.</TD><TD>xxfi_eom</TD></TR>
119<TR><TD>QUIT</TD><TD>xxfi_close</TD></TR>
120<TR><TD>(close SMTP connection)</TD><TD>&nbsp;</TD></TR>
121</TABLE>
122<B>Figure 3: Milter callbacks related to an SMTP transaction.</B>
123</DIV>
124
125<P>
126Note that although only a single message is shown above, multiple
127messages may be sent in a single connection.
128Note also that a message or connection may be aborted by
129either the remote host or the MTA
130at any point during the SMTP transaction.
131If this occurs during a message (between the MAIL command and the final "."),
132the filter's
133<A HREF="xxfi_abort.html">xxfi_abort</A> routine will be called.
134<A HREF="xxfi_close.html">xxfi_close</A> is called any time the
135connection closes.
136
137<H2><A NAME="Multithreading">Multithreading</A></H2>
138
139<P>
140A single filter process may handle any number of connections
141simultaneously.
142All filtering callbacks must therefore be reentrant,
143and use some appropriate external synchronization methods to access
144global data.
145Furthermore, since there is not a one-to-one correspondence
146between threads and connections
147(N connections mapped onto M threads, M &lt;= N),
148connection-specific data must be accessed
149through the handles provided by the Milter library.
150The programmer cannot rely on library-supplied thread-specific data blocks
151(e.g., <CODE>pthread_getspecific(3)</CODE>) to store connection-specific data.
152See the API documentation for
153<A HREF="smfi_setpriv.html">smfi_setpriv</A> and
154<A HREF="smfi_getpriv.html">smfi_getpriv</A> for details.
155
156<H2><A NAME="ResourceManagement">Resource Management</A></H2>
157
158Since filters are likely to be long-lived,
159and to handle many connections,
160proper deallocation of per-connection resources is important.
161The lifetime of a connection is bracketed by calls to the
162callbacks <A HREF="xxfi_connect.html">xxfi_connect</A> and
163<A HREF="xxfi_close.html">xxfi_close</A>.
164Therefore connection-specific
165resources (accessed via <A HREF="smfi_getpriv.html">smfi_getpriv</A>
166and <A HREF="smfi_setpriv.html">smfi_setpriv</A>) may be allocated in
167<A HREF="xxfi_connect.html">xxfi_connect</A>,
168and should be freed in
169<A HREF="xxfi_close.html">xxfi_close</A>.
170For further information see
171the <A HREF="api.html#conn-msg">discussion</A> of message- versus
172connection-oriented routines.
173In particular,
174note that there is only one connection-specific data pointer per connection.
175<P>
176
177Each message is bracketed by calls to
178<A HREF="xxfi_envfrom.html">xxfi_envfrom</A> and
179<A HREF="xxfi_eom.html">xxfi_eom</A> (or
180<A HREF="xxfi_abort.html">xxfi_abort</A>),
181implying that message-specific resources can be allocated
182and reclaimed in these routines.
183Since the messages in a connection are processed sequentially by each filter,
184there will be only one active message associated with a given
185connection and filter (and connection-private data block).
186These resources must still be accessed through
187<A HREF="smfi_getpriv.html">smfi_getpriv</A> and
188<A HREF="smfi_setpriv.html">smfi_setpriv</A>,
189and must be reclaimed in
190<A HREF="xxfi_abort.html">xxfi_abort</A>.
191
192<H2><A NAME="SignalHandling">Signal Handling</A></H2>
193
194libmilter takes care of signal handling,
195the filters are not influenced directly by signals.
196There are basically two types of signal handlers:
197
198<OL>
199<LI><TT>Stop</TT>: no new connections from the MTA will be accepted,
200but existing connections are allowed to continue.
201<LI><TT>Abort</TT>: all filters will be stopped as soon as the next
202communication with the MTA happens.
203</OL>
204
205Filters are not terminated asynchronously
206(except by signals that can't be caught).
207In the case of <TT>Abort</TT> the
208<A HREF="xxfi_abort.html">xxfi_abort</A> callback is usually invoked
209if there is an active transaction.
210However, if an invoked callback takes too long to execute
211(the maximum time <TT>Abort</TT> waits is currently 5s)
212<!-- XREF: MI_CHK_TIME -->
213then the filter is simply terminated, i.e.,
214neither the
215<A HREF="xxfi_abort.html">xxfi_abort</A> callback
216nor the
217<A HREF="xxfi_close.html">xxfi_close</A> callback
218is invoked.
219
220<HR size="1">
221<FONT size="-1">
222Copyright (c) 2000, 2001, 2003, 2006, 2018 Proofpoint, Inc. and its suppliers.
223All rights reserved.
224<BR>
225By using this file, you agree to the terms and conditions set
226forth in the LICENSE.
227</FONT>
228</BODY>
229</HTML>
230