Modifications to use the new mmlimitrate(3) API
[mmondor.git] / mmsoftware / mmmail / src / mmsmtpd / mmsmtpd.h
CommitLineData
da634739 1/* $Id: mmsmtpd.h,v 1.19 2003/10/23 01:01:30 mmondor Exp $ */
47071c2b
MM
2
3/*
5eb34fba 4 * Copyright (C) 2000-2003, Matthew Mondor
47071c2b
MM
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software written by Matthew Mondor.
18 * 4. The name of Matthew Mondor may not be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36
37#ifndef MMSMTPD_H
38#define MMSMTPD_H
39
40
41
42
43/* HEADERS */
44
45#include <sys/types.h>
46#include <time.h>
47
5eb34fba
MM
48#include <pth.h>
49
50#include <mmtypes.h>
47071c2b 51#include <mmlist.h>
7a56f31f 52#include <mmpool.h>
904cd663 53#include <mmhash.h>
47071c2b
MM
54#include <mmserver.h>
55#include <mmfd.h>
56#include <mmstat.h>
da634739 57#include <mmlimitrate.h>
47071c2b
MM
58
59
60
61
62/* DEFINITIONS */
63#define DAEMON_NAME "mmsmtpd"
ddb6d6f7 64#define DAEMON_VERSION "mmmail-0.0.24/mmondor"
47071c2b
MM
65
66/* Negative states are used by the state swapper, others are real states */
67#define STATE_ERROR -3
68#define STATE_END -2
69#define STATE_CURRENT -1
70#define STATE_ALL 0
71
72/* Invalid RCPT reason */
f36e2a66
MM
73enum rcpt_reason {
74 RCPT_OK = 0,
75 RCPT_NOFROM,
76 RCPT_MAX,
77 RCPT_INVALID,
78 RCPT_EXISTS,
79 RCPT_FULL,
80 RCPT_FLOOD,
81 RCPT_ERROR
82};
47071c2b
MM
83
84/* DATA errors */
f36e2a66
MM
85enum data_reason {
86 DATA_SUBMIT = 0,
87 DATA_OK,
88 DATA_OVERFLOW,
89 DATA_HOPS,
90 DATA_INTERNAL
91};
47071c2b 92
46cf2cd5
MM
93/* Resolving flags for valid_host() */
94#define HOST_NORES 0
95#define HOST_RES 1
96#define HOST_RES_MX 2
97
47071c2b
MM
98/* Custom fdbreadbuf() return result */
99#define CFDBRB_HOPS -1
100
101/* Asynchroneous functions we attach */
102#define ASYNC_RESQUERY 1
103
e334174e 104/* Error registration macro */
c363ee92 105#define REGISTER_ERROR(x) do { \
e334174e
MM
106 (x)->errors++; \
107 if (CONF.DELAY_ON_ERROR) \
108 pth_sleep((x)->errors); \
c363ee92 109} while(FALSE)
e334174e 110
c363ee92
MM
111/* Evaluates if a character is valid for addresses and hostnames */
112#define VALID_CHAR(c) (((c) >= 'a' && (c) <= 'z') || \
113 ((c) >= '0' && (c) <= '9') || (c) == '.' || (c) == '-' || (c) == '_')
47071c2b
MM
114
115
116
117/* STRUCTURES */
118/* We store config file read results in this structure */
119typedef struct config {
120 char CHROOT_DIR[256], PID_PATH[256], USER[32], GROUPS[256],
121 LOG_FACILITY[32], SERVER_NAMES[1024], LISTEN_IPS[1024], DB_HOST[64],
122 DB_USER[32], DB_PASSWORD[32], DB_DATABASE[32];
123 long ALLOC_BUFFERS, LOG_LEVEL, LISTEN_PORT, MAX_ERRORS, MAX_IPS,
124 MAX_PER_IP, CONNECTION_RATE, CONNECTION_PERIOD, INPUT_TIMEOUT,
125 BANDWIDTH_IN, BANDWIDTH_OUT, GBANDWIDTH_IN, GBANDWIDTH_OUT, MAX_RCPTS,
126 MAX_DATA_LINES, MAX_DATA_SIZE, MAX_HOPS, FLOOD_MESSAGES,
127 FLOOD_EXPIRES, FLOOD_CACHE, ASYNC_PROCESSES;
46cf2cd5 128 bool RESOLVE_HOSTS, RESOLVE_HELO, RESOLVE_MX_MAIL, REQUIRE_HELO,
47071c2b 129 FLOOD_PROTECTION, STATFAIL_ADDRESS, STATFAIL_FLOOD, STATFAIL_FULL,
1a5bbe01 130 STATFAIL_TIMEOUT, STATFAIL_EOF, DELAY_ON_ERROR;
47071c2b
MM
131} CONFIG;
132
133
134/* This consists of the state-shared clientenv structure */
135typedef struct clientenv {
7a56f31f 136 pnode_t node;
47071c2b
MM
137 fdbuf *fdb; /* Buffered handler around our fd */
138 char *buffer; /* Buffer that points to last command line */
139 char *helo; /* Cached helo hostname */
140 char *from; /* Cached mail sender address */
141 char *c_hostname; /* Pointer to client's hostname */
142 char *c_ipaddr; /* Pointer to client's IP address string */
143 long mesg_size; /* Current cached message size in bytes */
144 long errors; /* Total number of errors that occured */
145 int timeout; /* Timeout in ms */
146 unsigned long id; /* Our connection ID */
147 unsigned long messages; /* Messages user sent us */
148 unsigned long rcpts; /* Number of RCPT accepted */
149 struct iface *iface; /* Current interface user connected through */
150 struct async_clenv *aclenv; /* Thread context for async_call() */
7a56f31f 151 list_t rcpt; /* Cached recepients to send mail to */
4fd4b499 152 mmstat_t vstat, pstat; /* mmstat(3) handles */
47071c2b
MM
153} clientenv;
154
155/* Used for RCPT addresses */
156typedef struct rcptnode {
7a56f31f 157 pnode_t node;
47071c2b
MM
158 char address[64], foraddress[64];
159 u_int64_t hash;
160} rcptnode;
161
904cd663 162/* This structure is used to keep a cache of recent hosts from which mail was
47071c2b
MM
163 * received, along with information on it to determine if the rate of messages
164 * is too high.
165 */
399db776 166typedef struct hostnode {
904cd663 167 hashnode_t node;
da634739
MM
168 char host[128]; /* Hostname, key */
169 struct limitrate lr;
399db776 170} hostnode;
47071c2b 171
399db776 172struct hosts_expire_thread_iterator_udata {
904cd663
MM
173 time_t current, soonest;
174 int cnt;
175};
176
5eb34fba
MM
177/* Used for mmfd thread support delegation/abstraction */
178struct mutexnode {
7a56f31f 179 pnode_t node;
5eb34fba
MM
180 pth_mutex_t mutex;
181};
182
47071c2b
MM
183/* This defines a state */
184typedef struct state {
185 int (**functions)(clientenv *);
186 int errcode;
187 char *errtext;
188} state;
189
190/* A command of a state */
191typedef struct command {
47071c2b
MM
192 int loglevel;
193 char *name, *args, *desc;
194} command;
195
399db776
MM
196/* For fast command lookup */
197struct commandnode {
198 hashnode_t node;
199 u_int32_t hash;
200 struct command *command;
201 int index;
202};
203
47071c2b
MM
204/* Used for fast index of result messages */
205struct reply_messages {
206 int code;
207 char *msg;
208};
209
210/* Our validate_msg_line() context */
211struct validate_udata
212{
213 long hops, nhops;
214};
215
216/* Our union for async_resquery() */
217struct async_resquery_msg {
218 struct async_msg msg;
219 union {
220 struct {
221 int res;
222 char answer[128];
223 } res;
224 struct {
225 int r_class, r_type;
226 char host[128];
227 } args;
228 } un;
229};
230
231
232
233
234/* PROTOTYPES */
235
236int main(int, char **);
237
238static int all_noop(clientenv *);
239static int all_rset(clientenv *);
240static int all_quit(clientenv *);
241static int all_help(clientenv *);
242static int all_helo(clientenv *);
243static int all_mail(clientenv *);
244static int all_rcpt(clientenv *);
245static int all_data(clientenv *);
246static int all_beer(clientenv *);
247
399db776
MM
248static bool hash_commands(struct command *, size_t);
249static u_int32_t commandnode_keyhash(const void *, size_t);
250static int commandnode_keycmp(const void *, const void *, size_t);
47071c2b
MM
251static bool reply(fdbuf *, int, bool, const char *, ...);
252
253static clientenv *alloc_clientenv(void);
254static bool init_clientenv(clientenv *, bool);
255static clientenv *free_clientenv(clientenv *);
7a56f31f 256static void empty_rcpts(list_t *);
47071c2b 257static bool check_alias(char *);
c023a59c
MM
258static bool check_nofrom(const char *, const char *);
259static int best_match(const char *, const char *);
47071c2b
MM
260static bool local_address(const char *, long *, long *, long *, long *);
261static void rfc_time(char *);
46cf2cd5
MM
262static bool valid_address(clientenv *, char *, char *, int);
263static bool valid_host(clientenv *, char *, int, bool);
ec182166 264static bool valid_ipaddress(const char *);
47071c2b
MM
265
266static int validate_msg_line(char *, ssize_t *, int *, void *);
267static bool do_data(clientenv *);
268
269static int handleclient(unsigned long, int, clientlistnode *, struct iface *,
270 struct async_clenv *);
271
5eb34fba
MM
272static void *_pth_mutex_create(void);
273static void *_pth_mutex_destroy(void *);
274static void _pth_mutex_lock(void *);
275static void _pth_mutex_unlock(void *);
276static void _pth_thread_yield(void);
e6f6121b 277static bool _pth_eintr(void);
5eb34fba 278
47071c2b
MM
279static void async_resquery(struct async_msg *);
280static int a_res_query(clientenv *, const char *, int, int, u_char *, int);
281
399db776
MM
282static void *hosts_expire_thread(void *);
283static bool hosts_expire_thread_iterator(hashnode_t *, void *);
904cd663 284
47071c2b
MM
285
286
287
288#endif