xref: /freebsd/contrib/sendmail/libmilter/docs/overview.html (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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			process DATA (<A HREF="xxfi_data.html">xxfi_data</A>)
79		For each filter
80		{
81			For each header
82				process header (<A HREF="xxfi_header.html">xxfi_header</A>)
83			process end of headers (<A HREF="xxfi_eoh.html">xxfi_eoh</A>)
84			For each body block
85				process this body block (<A HREF="xxfi_body.html">xxfi_body</A>)
86			process end of message (<A HREF="xxfi_eom.html">xxfi_eom</A>)
87		}
88	}
89	For each filter
90		process end of connection (<A HREF="xxfi_close.html">xxfi_close</A>)
91}
92</PRE>
93
94<P>Note: Filters are contacted in order defined in config file.</P>
95
96<P>
97To write a filter, a vendor supplies callbacks to process relevant
98parts of a message transaction.
99The library then controls all sequencing, threading,
100and protocol exchange with the MTA.
101<A HREF="#figure-3">Figure 3</A> outlines control flow for a filter
102process, showing where different callbacks are invoked.
103</P>
104
105<DIV ALIGN="center"><A NAME="figure-3"></A>
106<TABLE border=1 cellspacing=0 cellpadding=2 width="70%">
107<TR bgcolor="#dddddd"><TH>SMTP Commands</TH><TH>Milter Callbacks</TH></TR>
108<TR><TD>(open SMTP connection)</TD><TD>xxfi_connect</TD></TR>
109<TR><TD>HELO ...</TD><TD>xxfi_helo</TD></TR>
110<TR><TD>MAIL From: ...</TD><TD>xxfi_envfrom</TD></TR>
111<TR><TD>RCPT To: ...</TD><TD>xxfi_envrcpt</TD></TR>
112<TR><TD>[more RCPTs]</TD><TD>[xxfi_envrcpt]</TD></TR>
113<TR><TD>DATA</TD><TD>xxfi_data</TD></TR>
114<TR><TD>Header: ...</TD><TD>xxfi_header</TD></TR>
115<TR><TD>[more headers]</TD><TD>[xxfi_header]</TD></TR>
116<TR><TD>&nbsp;</TD><TD>xxfi_eoh</TD></TR>
117<TR><TD>body... </TD><TD>xxfi_body</TD></TR>
118<TR><TD>[more body...]</TD><TD>[xxfi_body]</TD></TR>
119<TR><TD>.</TD><TD>xxfi_eom</TD></TR>
120<TR><TD>QUIT</TD><TD>xxfi_close</TD></TR>
121<TR><TD>(close SMTP connection)</TD><TD>&nbsp;</TD></TR>
122</TABLE>
123<B>Figure 3: Milter callbacks related to an SMTP transaction.</B>
124</DIV>
125
126<P>
127Note that although only a single message is shown above, multiple
128messages may be sent in a single connection.
129Note also that a message or connection may be aborted by
130either the remote host or the MTA
131at any point during the SMTP transaction.
132If this occurs during a message (between the MAIL command and the final "."),
133the filter's
134<A HREF="xxfi_abort.html">xxfi_abort</A> routine will be called.
135<A HREF="xxfi_close.html">xxfi_close</A> is called any time the
136connection closes.
137
138<H2><A NAME="Multithreading">Multithreading</A></H2>
139
140<P>
141A single filter process may handle any number of connections
142simultaneously.
143All filtering callbacks must therefore be reentrant,
144and use some appropriate external synchronization methods to access
145global data.
146Furthermore, since there is not a one-to-one correspondence
147between threads and connections
148(N connections mapped onto M threads, M &lt;= N),
149connection-specific data must be accessed
150through the handles provided by the Milter library.
151The programmer cannot rely on library-supplied thread-specific data blocks
152(e.g., <CODE>pthread_getspecific(3)</CODE>) to store connection-specific data.
153See the API documentation for
154<A HREF="smfi_setpriv.html">smfi_setpriv</A> and
155<A HREF="smfi_getpriv.html">smfi_getpriv</A> for details.
156
157<H2><A NAME="ResourceManagement">Resource Management</A></H2>
158
159Since filters are likely to be long-lived,
160and to handle many connections,
161proper deallocation of per-connection resources is important.
162The lifetime of a connection is bracketed by calls to the
163callbacks <A HREF="xxfi_connect.html">xxfi_connect</A> and
164<A HREF="xxfi_close.html">xxfi_close</A>.
165Therefore connection-specific
166resources (accessed via <A HREF="smfi_getpriv.html">smfi_getpriv</A>
167and <A HREF="smfi_setpriv.html">smfi_setpriv</A>) may be allocated in
168<A HREF="xxfi_connect.html">xxfi_connect</A>,
169and should be freed in
170<A HREF="xxfi_close.html">xxfi_close</A>.
171For further information see
172the <A HREF="api.html#conn-msg">discussion</A> of message- versus
173connection-oriented routines.
174In particular,
175note that there is only one connection-specific data pointer per connection.
176<P>
177
178Each message is bracketed by calls to
179<A HREF="xxfi_envfrom.html">xxfi_envfrom</A> and
180<A HREF="xxfi_eom.html">xxfi_eom</A> (or
181<A HREF="xxfi_abort.html">xxfi_abort</A>),
182implying that message-specific resources can be allocated
183and reclaimed in these routines.
184Since the messages in a connection are processed sequentially by each filter,
185there will be only one active message associated with a given
186connection and filter (and connection-private data block).
187These resources must still be accessed through
188<A HREF="smfi_getpriv.html">smfi_getpriv</A> and
189<A HREF="smfi_setpriv.html">smfi_setpriv</A>,
190and must be reclaimed in
191<A HREF="xxfi_abort.html">xxfi_abort</A>.
192
193<H2><A NAME="SignalHandling">Signal Handling</A></H2>
194
195libmilter takes care of signal handling,
196the filters are not influenced directly by signals.
197There are basically two types of signal handlers:
198
199<OL>
200<LI><TT>Stop</TT>: no new connections from the MTA will be accepted,
201but existing connections are allowed to continue.
202<LI><TT>Abort</TT>: all filters will be stopped as soon as the next
203communication with the MTA happens.
204</OL>
205
206Filters are not terminated asynchronously
207(except by signals that can't be caught).
208In the case of <TT>Abort</TT> the
209<A HREF="xxfi_abort.html">xxfi_abort</A> callback is usually invoked
210if there is an active transaction.
211However, if an invoked callback takes too long to execute
212(the maximum time <TT>Abort</TT> waits is currently 5s)
213<!-- XREF: MI_CHK_TIME -->
214then the filter is simply terminated, i.e.,
215neither the
216<A HREF="xxfi_abort.html">xxfi_abort</A> callback
217nor the
218<A HREF="xxfi_close.html">xxfi_close</A> callback
219is invoked.
220
221<HR size="1">
222<FONT size="-1">
223Copyright (c) 2000, 2001, 2003, 2006, 2018 Proofpoint, Inc. and its suppliers.
224All rights reserved.
225<BR>
226By using this file, you agree to the terms and conditions set
227forth in the LICENSE.
228</FONT>
229</BODY>
230</HTML>
231