aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_smtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/plugin_transport_smtp.c')
-rw-r--r--src/transport/plugin_transport_smtp.c750
1 files changed, 0 insertions, 750 deletions
diff --git a/src/transport/plugin_transport_smtp.c b/src/transport/plugin_transport_smtp.c
deleted file mode 100644
index f3db4fc5a..000000000
--- a/src/transport/plugin_transport_smtp.c
+++ /dev/null
@@ -1,750 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2003-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file transport/plugin_transport_smtp.c
23 * @brief Implementation of the SMTP transport service
24 * @author Christian Grothoff
25 * @author Renaldo Ferreira
26 */
27
28#include "platform.h"
29#include "gnunet_util.h"
30#include "gnunet_constants.h"
31#include "gnunet_protocols.h"
32#include "gnunet_transport.h"
33#include "gnunet_stats_service.h"
34#include <libesmtp.h>
35#include <signal.h>
36
37
38/**
39 * The default maximum size of each outbound SMTP message.
40 */
41#define SMTP_MESSAGE_SIZE 65528
42
43#define DEBUG_SMTP GNUNET_EXTRA_LOGGING
44
45#define FILTER_STRING_SIZE 64
46
47/* how long can a line in base64 encoded
48 mime text be? (in characters, excluding "\n") */
49#define MAX_CHAR_PER_LINE 76
50
51#define EBUF_LEN 128
52
53/**
54 * Host-Address in a SMTP network.
55 */
56typedef struct
57{
58 /**
59 * Filter line that every sender must include in the E-mails such
60 * that the receiver can effectively filter out the GNUnet traffic
61 * from the E-mail.
62 */
63 char filter[FILTER_STRING_SIZE];
64
65 /**
66 * Claimed E-mail address of the sender.
67 * Format is "foo@bar.com" with null termination, padded to be
68 * of a multiple of 8 bytes long.
69 */
70 char senderAddress[0];
71} EmailAddress;
72
73GNUNET_NETWORK_STRUCT_BEGIN
74
75/**
76 * Encapsulation of a GNUnet message in the SMTP mail body (before
77 * base64 encoding).
78 */
79typedef struct
80{
81 GNUNET_MessageHeader header;
82
83 /**
84 * What is the identity of the sender (GNUNET_hash of public key)
85 */
86 GNUNET_PeerIdentity sender;
87} SMTPMessage;
88GNUNET_NETWORK_STRUCT_END
89
90/* *********** globals ************* */
91
92/**
93 * apis (our advertised API and the core api )
94 */
95static GNUNET_CoreAPIForTransport *core_api;
96
97static struct GNUNET_GE_Context *ectx;
98
99/**
100 * Thread that listens for inbound messages
101 */
102static struct GNUNET_ThreadHandle *dispatchThread;
103
104/**
105 * Flag to indicate that server has been shut down.
106 */
107static int smtp_shutdown = GNUNET_YES;
108
109/**
110 * Set to the SMTP server hostname (and port) for outgoing messages.
111 */
112static char *smtp_server_name;
113
114static char *pipename;
115
116/**
117 * Lock for uses of libesmtp (not thread-safe).
118 */
119static struct GNUNET_Mutex *lock;
120
121/**
122 * Old handler for SIGPIPE (kept to be able to restore).
123 */
124static struct sigaction old_handler;
125
126static char *email;
127
128static GNUNET_TransportAPI smtpAPI;
129
130static GNUNET_Stats_ServiceAPI *stats;
131
132static int stat_bytesReceived;
133
134static int stat_bytesSent;
135
136static int stat_bytesDropped;
137
138/**
139 * How many e-mails are we allowed to send per hour?
140 */
141static unsigned long long rate_limit;
142
143static GNUNET_CronTime last_transmission;
144
145
146/* ********************* the real stuff ******************* */
147
148#define strAUTOncmp(a, b) strncmp (a, b, strlen (b))
149
150/**
151 * Listen to the pipe, decode messages and send to core.
152 */
153static void *
154listenAndDistribute (void *unused)
155{
156 char *line;
157 unsigned int linesize;
158 SMTPMessage *mp;
159 FILE *fdes;
160 char *retl;
161 char *out;
162 unsigned int size;
163 GNUNET_TransportPacket *coreMP;
164 int fd;
165 unsigned int pos;
166
167 linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2)
168 / MAX_CHAR_PER_LINE; /* maximum size of a line supported */
169 line = GNUNET_malloc (linesize + 2); /* 2 bytes for off-by-one errors, just to be safe... */
170
171#define READLINE(l, limit) \
172 do { retl = fgets (l, (limit), fdes); \
173 if ((retl == NULL) || (smtp_shutdown == GNUNET_YES)) { \
174 goto END; \
175 } \
176 if (core_api->load_monitor != NULL) \
177 GNUNET_network_monitor_notify_transmission (core_api->load_monitor, \
178 GNUNET_ND_DOWNLOAD, \
179 strlen (retl)); \
180 } while (0)
181
182
183 while (smtp_shutdown == GNUNET_NO)
184 {
185 fd = OPEN (pipename, O_RDONLY | O_ASYNC);
186 if (fd == -1)
187 {
188 if (smtp_shutdown == GNUNET_NO)
189 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
190 continue;
191 }
192 fdes = fdopen (fd, "r");
193 while (smtp_shutdown == GNUNET_NO)
194 {
195 /* skip until end of header */
196 do
197 {
198 READLINE (line, linesize);
199 }
200 while ((line[0] != '\r') && (line[0] != '\n')); /* expect newline */
201 READLINE (line, linesize); /* read base64 encoded message; decode, process */
202 pos = 0;
203 while (1)
204 {
205 pos = strlen (line) - 1; /* ignore new line */
206 READLINE (&line[pos], linesize - pos); /* read base64 encoded message; decode, process */
207 if ((line[pos] == '\r') || (line[pos] == '\n'))
208 break; /* empty line => end of message! */
209 }
210 size = GNUNET_STRINGS_base64_decode (line, pos, &out);
211 if (size < sizeof(SMTPMessage))
212 {
213 GNUNET_GE_BREAK (ectx, 0);
214 GNUNET_free (out);
215 goto END;
216 }
217
218 mp = (SMTPMessage *) &out[size - sizeof(SMTPMessage)];
219 if (ntohs (mp->header.size) != size)
220 {
221 GNUNET_GE_LOG (ectx,
222 GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
223 _ ("Received malformed message via %s. Ignored.\n"),
224 "SMTP");
225#if DEBUG_SMTP
226 GNUNET_GE_LOG (ectx,
227 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
228 "Size returned by base64=%d, in the msg=%d.\n", size,
229 ntohl (mp->size));
230#endif
231 GNUNET_free (out);
232 goto END;
233 }
234 if (stats != NULL)
235 stats->change (stat_bytesReceived, size);
236 coreMP = GNUNET_new (GNUNET_TransportPacket);
237 coreMP->msg = out;
238 coreMP->size = size - sizeof(SMTPMessage);
239 coreMP->tsession = NULL;
240 coreMP->sender = mp->sender;
241#if DEBUG_SMTP
242 GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
243 "SMTP message passed to the core.\n");
244#endif
245
246 core_api->receive (coreMP);
247 }
248END:
249#if DEBUG_SMTP
250 GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
251 "SMTP message processed.\n");
252#endif
253 if (fdes != NULL)
254 fclose (fdes);
255 }
256 GNUNET_free (line);
257 return NULL;
258}
259
260
261/* *************** API implementation *************** */
262
263/**
264 * Verify that a hello-Message is correct (a node is reachable at that
265 * address). Since the reply will be asynchronous, a method must be
266 * called on success.
267 *
268 * @param hello the hello message to verify
269 * (the signature/crc have been verified before)
270 * @return GNUNET_OK on success, GNUNET_SYSERR on error
271 */
272static int
273api_verify_hello (const GNUNET_MessageHello *hello)
274{
275 const EmailAddress *maddr;
276
277 maddr = (const EmailAddress *) &hello[1];
278 if ((ntohs (hello->header.size) !=
279 sizeof(GNUNET_MessageHello) + ntohs (hello->senderAddressSize)) ||
280 (maddr->senderAddress
281 [ntohs (hello->senderAddressSize) - 1 - FILTER_STRING_SIZE] != '\0'))
282 {
283 GNUNET_GE_BREAK (ectx, 0);
284 return GNUNET_SYSERR; /* obviously invalid */
285 }
286 if (NULL == strstr (maddr->filter, ": "))
287 return GNUNET_SYSERR;
288 return GNUNET_OK;
289}
290
291
292/**
293 * Create a hello-Message for the current node. The hello is created
294 * without signature and without a timestamp. The GNUnet core will
295 * GNUNET_RSA_sign the message and add an expiration time.
296 *
297 * @return hello on success, NULL on error
298 */
299static GNUNET_MessageHello *
300api_create_hello ()
301{
302 GNUNET_MessageHello *msg;
303 char *filter;
304 EmailAddress *haddr;
305 int i;
306
307 GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "FILTER",
308 "X-mailer: GNUnet", &filter);
309 if (NULL == strstr (filter, ": "))
310 {
311 GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
312 _ ("SMTP filter string to invalid, lacks ': '\n"));
313 GNUNET_free (filter);
314 return NULL;
315 }
316
317 if (strlen (filter) > FILTER_STRING_SIZE)
318 {
319 filter[FILTER_STRING_SIZE] = '\0';
320 GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
321 _ ("SMTP filter string to long, capped to `%s'\n"), filter);
322 }
323 i = (strlen (email) + 8) & (~7); /* make multiple of 8 */
324 msg =
325 GNUNET_malloc (sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
326 memset (msg, 0, sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
327 haddr = (EmailAddress *) &msg[1];
328 memset (&haddr->filter[0], 0, FILTER_STRING_SIZE);
329 strcpy (&haddr->filter[0], filter);
330 GNUNET_memcpy (&haddr->senderAddress[0], email, strlen (email) + 1);
331 msg->senderAddressSize = htons (strlen (email) + 1 + sizeof(EmailAddress));
332 msg->protocol = htons (GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
333 msg->MTU = htonl (smtpAPI.mtu);
334 msg->header.size = htons (GNUNET_sizeof_hello (msg));
335 if (api_verify_hello (msg) == GNUNET_SYSERR)
336 GNUNET_GE_ASSERT (ectx, 0);
337 GNUNET_free (filter);
338 return msg;
339}
340
341
342struct GetMessageClosure
343{
344 unsigned int esize;
345 unsigned int pos;
346 char *ebody;
347};
348
349static const char *
350get_message (void **buf, int *len, void *cls)
351{
352 struct GetMessageClosure *gmc = cls;
353
354 *buf = NULL;
355 if (len == NULL)
356 {
357 gmc->pos = 0;
358 return NULL;
359 }
360 if (gmc->pos == gmc->esize)
361 return NULL; /* done */
362 *len = gmc->esize;
363 gmc->pos = gmc->esize;
364 return gmc->ebody;
365}
366
367
368/**
369 * Send a message to the specified remote node.
370 *
371 * @param tsession the GNUNET_MessageHello identifying the remote node
372 * @param msg what to send
373 * @param size the size of the message
374 * @param important is this message important enough to override typical limits?
375 * @return GNUNET_SYSERR on error, GNUNET_OK on success
376 */
377static int
378api_send (GNUNET_TSession *tsession, const void *msg, const unsigned int size,
379 int important)
380{
381 const GNUNET_MessageHello *hello;
382 const EmailAddress *haddr;
383 char *m;
384 char *filter;
385 char *fvalue;
386 SMTPMessage *mp;
387 struct GetMessageClosure gm_cls;
388 smtp_session_t session;
389 smtp_message_t message;
390 smtp_recipient_t recipient;
391
392#define EBUF_LEN 128
393 char ebuf[EBUF_LEN];
394 GNUNET_CronTime now;
395
396 if (smtp_shutdown == GNUNET_YES)
397 return GNUNET_SYSERR;
398 if ((size == 0) || (size > smtpAPI.mtu))
399 {
400 GNUNET_GE_BREAK (ectx, 0);
401 return GNUNET_SYSERR;
402 }
403 now = GNUNET_get_time ();
404 if ((important != GNUNET_YES) &&
405 ( ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS) )
406 return GNUNET_NO; /* rate too high */
407 last_transmission = now;
408
409 hello = (const GNUNET_MessageHello *) tsession->internal;
410 if (hello == NULL)
411 return GNUNET_SYSERR;
412 GNUNET_mutex_lock (lock);
413 session = smtp_create_session ();
414 if (session == NULL)
415 {
416 GNUNET_GE_LOG (ectx,
417 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
418 | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
419 "smtp_create_session", smtp_strerror (smtp_errno (), ebuf,
420 EBUF_LEN));
421 GNUNET_mutex_unlock (lock);
422 return GNUNET_SYSERR;
423 }
424 if (0 == smtp_set_server (session, smtp_server_name))
425 {
426 GNUNET_GE_LOG (ectx,
427 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
428 | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
429 "smtp_set_server", smtp_strerror (smtp_errno (), ebuf,
430 EBUF_LEN));
431 smtp_destroy_session (session);
432 GNUNET_mutex_unlock (lock);
433 return GNUNET_SYSERR;
434 }
435 haddr = (const EmailAddress *) &hello[1];
436 message = smtp_add_message (session);
437 if (message == NULL)
438 {
439 GNUNET_GE_LOG (ectx,
440 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
441 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
442 "smtp_add_message", smtp_strerror (smtp_errno (), ebuf,
443 EBUF_LEN));
444 smtp_destroy_session (session);
445 GNUNET_mutex_unlock (lock);
446 return GNUNET_SYSERR;
447 }
448 smtp_set_header (message, "To", NULL, haddr->senderAddress);
449 smtp_set_header (message, "From", NULL, email);
450
451 filter = GNUNET_strdup (haddr->filter);
452 fvalue = strstr (filter, ": ");
453 GNUNET_GE_ASSERT (NULL, NULL != fvalue);
454 fvalue[0] = '\0';
455 fvalue += 2;
456 if (0 == smtp_set_header (message, filter, fvalue))
457 {
458 GNUNET_GE_LOG (ectx,
459 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
460 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
461 "smtp_set_header", smtp_strerror (smtp_errno (), ebuf,
462 EBUF_LEN));
463 smtp_destroy_session (session);
464 GNUNET_mutex_unlock (lock);
465 GNUNET_free (filter);
466 return GNUNET_SYSERR;
467 }
468 GNUNET_free (filter);
469 m = GNUNET_malloc (size + sizeof(SMTPMessage));
470 GNUNET_memcpy (m, msg, size);
471 mp = (SMTPMessage *) &m[size];
472 mp->header.size = htons (size + sizeof(SMTPMessage));
473 mp->header.type = htons (0);
474 mp->sender = *core_api->my_identity;
475 gm_cls.ebody = NULL;
476 gm_cls.pos = 0;
477 gm_cls.esize = GNUNET_STRINGS_base64_encode (m, size + sizeof(SMTPMessage),
478 &gm_cls.ebody);
479 GNUNET_free (m);
480 if (0 == smtp_size_set_estimate (message, gm_cls.esize))
481 {
482 GNUNET_GE_LOG (ectx,
483 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
484 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
485 "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf,
486 EBUF_LEN));
487 }
488 if (0 == smtp_set_messagecb (message, &get_message, &gm_cls))
489 {
490 GNUNET_GE_LOG (ectx,
491 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
492 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
493 "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf,
494 EBUF_LEN));
495 smtp_destroy_session (session);
496 GNUNET_mutex_unlock (lock);
497 GNUNET_free (gm_cls.ebody);
498 return GNUNET_SYSERR;
499 }
500 recipient = smtp_add_recipient (message, haddr->senderAddress);
501 if (recipient == NULL)
502 {
503 GNUNET_GE_LOG (ectx,
504 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
505 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
506 "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf,
507 EBUF_LEN));
508 smtp_destroy_session (session);
509 GNUNET_mutex_unlock (lock);
510 return GNUNET_SYSERR;
511 }
512 if (0 == smtp_start_session (session))
513 {
514 GNUNET_GE_LOG (ectx,
515 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
516 | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
517 "smtp_start_session", smtp_strerror (smtp_errno (), ebuf,
518 EBUF_LEN));
519 smtp_destroy_session (session);
520 GNUNET_mutex_unlock (lock);
521 GNUNET_free (gm_cls.ebody);
522 return GNUNET_SYSERR;
523 }
524 if (stats != NULL)
525 stats->change (stat_bytesSent, size);
526 if (core_api->load_monitor != NULL)
527 GNUNET_network_monitor_notify_transmission (core_api->load_monitor,
528 GNUNET_ND_UPLOAD, gm_cls.esize);
529 smtp_message_reset_status (message); /* this is needed to plug a 28-byte/message memory leak in libesmtp */
530 smtp_destroy_session (session);
531 GNUNET_mutex_unlock (lock);
532 GNUNET_free (gm_cls.ebody);
533 return GNUNET_OK;
534}
535
536
537/**
538 * Establish a connection to a remote node.
539 * @param hello the hello-Message for the target node
540 * @param tsessionPtr the session handle that is to be set
541 * @param may_reuse can we re-use an existing connection?
542 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
543 */
544static int
545api_connect (const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr,
546 int may_reuse)
547{
548 GNUNET_TSession *tsession;
549
550 tsession = GNUNET_new (GNUNET_TSession);
551 tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello));
552 tsession->peer = hello->senderIdentity;
553 GNUNET_memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
554 tsession->ttype = smtpAPI.protocol_number;
555 (*tsessionPtr) = tsession;
556 return GNUNET_OK;
557}
558
559
560/**
561 * Disconnect from a remote node.
562 *
563 * @param tsession the session that is closed
564 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
565 */
566static int
567api_disconnect (GNUNET_TSession *tsession)
568{
569 if (tsession != NULL)
570 {
571 if (tsession->internal != NULL)
572 GNUNET_free (tsession->internal);
573 GNUNET_free (tsession);
574 }
575 return GNUNET_OK;
576}
577
578
579/**
580 * Start the server process to receive inbound traffic.
581 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
582 */
583static int
584api_start_transport_server ()
585{
586 smtp_shutdown = GNUNET_NO;
587 /* initialize SMTP network */
588 dispatchThread = GNUNET_thread_create (&listenAndDistribute, NULL, 1024 * 4);
589 if (dispatchThread == NULL)
590 {
591 GNUNET_GE_DIE_STRERROR (ectx,
592 GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
593 "pthread_create");
594 return GNUNET_SYSERR;
595 }
596 return GNUNET_OK;
597}
598
599
600/**
601 * Shutdown the server process (stop receiving inbound traffic). Maybe
602 * restarted later!
603 */
604static int
605api_stop_transport_server ()
606{
607 void *unused;
608
609 smtp_shutdown = GNUNET_YES;
610 GNUNET_thread_stop_sleep (dispatchThread);
611 GNUNET_thread_join (dispatchThread, &unused);
612 return GNUNET_OK;
613}
614
615
616/**
617 * Convert SMTP hello to an IP address (always fails).
618 */
619static int
620api_hello_to_address (const GNUNET_MessageHello *hello, void **sa,
621 unsigned int *sa_len)
622{
623 return GNUNET_SYSERR;
624}
625
626
627/**
628 * Always fails.
629 */
630static int
631api_associate (GNUNET_TSession *tsession)
632{
633 return GNUNET_SYSERR; /* SMTP connections can never be associated */
634}
635
636
637/**
638 * Always succeeds (for now; we should look at adding
639 * frequency limits to SMTP in the future!).
640 */
641static int
642api_test_would_try (GNUNET_TSession *tsession, unsigned int size,
643 int important)
644{
645 return GNUNET_OK; /* we always try... */
646}
647
648
649/**
650 * The exported method. Makes the core api available via a global and
651 * returns the smtp transport API.
652 */
653GNUNET_TransportAPI *
654inittransport_smtp (struct GNUNET_CoreAPIForTransport *core)
655{
656 unsigned long long mtu;
657 struct sigaction sa;
658
659 core_api = core;
660 ectx = core->ectx;
661 if (! GNUNET_GC_have_configuration_value (core_api->cfg, "SMTP", "EMAIL"))
662 {
663 GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
664 _
665 (
666 "No email-address specified, can not start SMTP transport.\n"));
667 return NULL;
668 }
669 GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "MTU", 1200,
670 SMTP_MESSAGE_SIZE,
671 SMTP_MESSAGE_SIZE, &mtu);
672 GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "RATELIMIT",
673 0, 0, 1024 * 1024, &rate_limit);
674 stats = core_api->service_request ("stats");
675 if (stats != NULL)
676 {
677 stat_bytesReceived =
678 stats->create (gettext_noop ("# bytes received via SMTP"));
679 stat_bytesSent = stats->create (gettext_noop ("# bytes sent via SMTP"));
680 stat_bytesDropped =
681 stats->create (gettext_noop ("# bytes dropped by SMTP (outgoing)"));
682 }
683 GNUNET_GC_get_configuration_value_filename (core_api->cfg, "SMTP", "PIPE",
684 &pipename);
685 unlink (pipename);
686 if (0 != mkfifo (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
687 {
688 GNUNET_GE_LOG_STRERROR (ectx,
689 GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
690 "mkfifo");
691 GNUNET_free (pipename);
692 core_api->service_release (stats);
693 stats = NULL;
694 return NULL;
695 }
696 /* we need to allow the mailer program to send us messages;
697 * easiest done by giving it write permissions (see Mantis #1142) */
698 if (0 != chmod (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
699 GNUNET_GE_LOG_STRERROR (ectx,
700 GNUNET_GE_ADMIN | GNUNET_GE_BULK
701 | GNUNET_GE_WARNING, "chmod");
702 GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "EMAIL",
703 NULL,
704 &email);
705 lock = GNUNET_mutex_create (GNUNET_NO);
706 GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "SERVER",
707 "localhost:25", &smtp_server_name);
708 sa.sa_handler = SIG_IGN;
709 sigemptyset (&sa.sa_mask);
710 sa.sa_flags = 0;
711 sigaction (SIGPIPE, &sa, &old_handler);
712
713 smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
714 smtpAPI.mtu = mtu - sizeof(SMTPMessage);
715 smtpAPI.cost = 50;
716 smtpAPI.hello_verify = &api_verify_hello;
717 smtpAPI.hello_create = &api_create_hello;
718 smtpAPI.connect = &api_connect;
719 smtpAPI.send = &api_send;
720 smtpAPI.associate = &api_associate;
721 smtpAPI.disconnect = &api_disconnect;
722 smtpAPI.server_start = &api_start_transport_server;
723 smtpAPI.server_stop = &api_stop_transport_server;
724 smtpAPI.hello_to_address = &api_hello_to_address;
725 smtpAPI.send_now_test = &api_test_would_try;
726 return &smtpAPI;
727}
728
729
730void
731donetransport_smtp ()
732{
733 sigaction (SIGPIPE, &old_handler, NULL);
734 GNUNET_free (smtp_server_name);
735 if (stats != NULL)
736 {
737 core_api->service_release (stats);
738 stats = NULL;
739 }
740 GNUNET_mutex_destroy (lock);
741 lock = NULL;
742 unlink (pipename);
743 GNUNET_free (pipename);
744 pipename = NULL;
745 GNUNET_free (email);
746 email = NULL;
747}
748
749
750/* end of smtp.c */