Added support for optional DELAY_ON_ERROR
[mmondor.git] / mmsoftware / mmmail / src / mmsmtpd / mmsmtpd.h
1 /* $Id: mmsmtpd.h,v 1.2 2002/12/12 20:54:22 mmondor Exp $ */
2
3 /*
4 * Copyright (C) 2000-2002, Matthew Mondor
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
48 #include <mmlist.h>
49 #include <mmserver.h>
50 #include <mmfd.h>
51 #include <mmstat.h>
52
53
54
55
56 /* DEFINITIONS */
57 #define DAEMON_NAME "mmsmtpd"
58 #define DAEMON_VERSION "mmmail-0.0.21/mmondor"
59
60 /* Negative states are used by the state swapper, others are real states */
61 #define STATE_ERROR -3
62 #define STATE_END -2
63 #define STATE_CURRENT -1
64 #define STATE_ALL 0
65
66 /* Invalid RCPT reason */
67 #define RCPT_OK 0
68 #define RCPT_NOFROM 1
69 #define RCPT_MAX 2
70 #define RCPT_INVALID 3
71 #define RCPT_EXISTS 4
72 #define RCPT_FULL 5
73 #define RCPT_FLOOD 6
74 #define RCPT_ERROR 7
75
76 /* DATA errors */
77 #define DATA_SUBMIT 0
78 #define DATA_OK 1
79 #define DATA_OVERFLOW 2
80 #define DATA_HOPS 3
81 #define DATA_INTERNAL 4
82
83 /* Custom fdbreadbuf() return result */
84 #define CFDBRB_HOPS -1
85
86 /* Asynchroneous functions we attach */
87 #define ASYNC_RESQUERY 1
88
89 /* Error registration macro */
90 #define REGISTER_ERROR(x) do { \
91 (x)->errors++; \
92 if (CONF.DELAY_ON_ERROR) \
93 pth_sleep((x)->errors); \
94 } while(0)
95
96
97
98
99 /* STRUCTURES */
100 /* We store config file read results in this structure */
101 typedef struct config {
102 char CHROOT_DIR[256], PID_PATH[256], USER[32], GROUPS[256],
103 LOG_FACILITY[32], SERVER_NAMES[1024], LISTEN_IPS[1024], DB_HOST[64],
104 DB_USER[32], DB_PASSWORD[32], DB_DATABASE[32];
105 long ALLOC_BUFFERS, LOG_LEVEL, LISTEN_PORT, MAX_ERRORS, MAX_IPS,
106 MAX_PER_IP, CONNECTION_RATE, CONNECTION_PERIOD, INPUT_TIMEOUT,
107 BANDWIDTH_IN, BANDWIDTH_OUT, GBANDWIDTH_IN, GBANDWIDTH_OUT, MAX_RCPTS,
108 MAX_DATA_LINES, MAX_DATA_SIZE, MAX_HOPS, FLOOD_MESSAGES,
109 FLOOD_EXPIRES, FLOOD_CACHE, ASYNC_PROCESSES;
110 bool RESOLVE_HOSTS, RESOLVE_MX_HELO, RESOLVE_MX_MAIL, REQUIRE_HELO,
111 FLOOD_PROTECTION, STATFAIL_ADDRESS, STATFAIL_FLOOD, STATFAIL_FULL,
112 STATFAIL_TIMEOUT, DELAY_ON_ERROR;
113 } CONFIG;
114
115
116 /* This consists of the state-shared clientenv structure */
117 typedef struct clientenv {
118 node nod;
119 fdbuf *fdb; /* Buffered handler around our fd */
120 char *buffer; /* Buffer that points to last command line */
121 char *helo; /* Cached helo hostname */
122 char *from; /* Cached mail sender address */
123 char *c_hostname; /* Pointer to client's hostname */
124 char *c_ipaddr; /* Pointer to client's IP address string */
125 long mesg_size; /* Current cached message size in bytes */
126 long errors; /* Total number of errors that occured */
127 int timeout; /* Timeout in ms */
128 unsigned long id; /* Our connection ID */
129 unsigned long messages; /* Messages user sent us */
130 unsigned long rcpts; /* Number of RCPT accepted */
131 struct iface *iface; /* Current interface user connected through */
132 struct async_clenv *aclenv; /* Thread context for async_call() */
133 list rcpt; /* Cached recepients to send mail to */
134 MMSTAT vstat, pstat; /* mmstat(3) handles */
135 } clientenv;
136
137 /* Used for RCPT addresses */
138 typedef struct rcptnode {
139 node nod;
140 char address[64], foraddress[64];
141 u_int64_t hash;
142 } rcptnode;
143
144 /* This structure is used to keep a cache of recent boxes for which mail was
145 * received, along with information on it to determine if the rate of messages
146 * is too high.
147 */
148 typedef struct mnode {
149 node nod;
150 u_int64_t hash; /* 64-bit hash of host address or name */
151 time_t expires; /* Time entry will expire */
152 long posts; /* How many posts since entry creation */
153 } mnode;
154
155 /* This defines a state */
156 typedef struct state {
157 int (**functions)(clientenv *);
158 int errcode;
159 char *errtext;
160 } state;
161
162 /* A command of a state */
163 typedef struct command {
164 int32_t hash;
165 int loglevel;
166 char *name, *args, *desc;
167 } command;
168
169 /* Used for fast index of result messages */
170 struct reply_messages {
171 int code;
172 char *msg;
173 };
174
175 /* Our validate_msg_line() context */
176 struct validate_udata
177 {
178 long hops, nhops;
179 };
180
181 /* Our union for async_resquery() */
182 struct async_resquery_msg {
183 struct async_msg msg;
184 union {
185 struct {
186 int res;
187 char answer[128];
188 } res;
189 struct {
190 int r_class, r_type;
191 char host[128];
192 } args;
193 } un;
194 };
195
196
197
198
199 /* PROTOTYPES */
200
201 int main(int, char **);
202
203 static int all_noop(clientenv *);
204 static int all_rset(clientenv *);
205 static int all_quit(clientenv *);
206 static int all_help(clientenv *);
207 static int all_helo(clientenv *);
208 static int all_mail(clientenv *);
209 static int all_rcpt(clientenv *);
210 static int all_data(clientenv *);
211 static int all_beer(clientenv *);
212
213 static void packcommands(struct command *, size_t);
214 static bool reply(fdbuf *, int, bool, const char *, ...);
215
216 static clientenv *alloc_clientenv(void);
217 static bool init_clientenv(clientenv *, bool);
218 static clientenv *free_clientenv(clientenv *);
219 static void empty_rcpts(list *);
220 static bool check_alias(char *);
221 static bool check_nofrom(const char *);
222 static bool alias_match(const char *, const char *);
223 static bool local_address(const char *, long *, long *, long *, long *);
224 static void rfc_time(char *);
225 static bool valid_address(clientenv *, char *, char *, bool);
226 static bool valid_host(clientenv *, char *, bool);
227 static bool valid_char(char);
228
229 static int validate_msg_line(char *, ssize_t *, int *, void *);
230 static bool do_data(clientenv *);
231
232 static int handleclient(unsigned long, int, clientlistnode *, struct iface *,
233 struct async_clenv *);
234
235 static void async_resquery(struct async_msg *);
236 static int a_res_query(clientenv *, const char *, int, int, u_char *, int);
237
238
239
240
241 #endif