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