123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- /*
- This file is part of GNUnet
- Copyright (C) 2003-2013 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file transport/plugin_transport_smtp.c
- * @brief Implementation of the SMTP transport service
- * @author Christian Grothoff
- * @author Renaldo Ferreira
- */
- #include "platform.h"
- #include "gnunet_util.h"
- #include "gnunet_constants.h"
- #include "gnunet_protocols.h"
- #include "gnunet_transport.h"
- #include "gnunet_stats_service.h"
- #include <libesmtp.h>
- #include <signal.h>
- /**
- * The default maximum size of each outbound SMTP message.
- */
- #define SMTP_MESSAGE_SIZE 65528
- #define DEBUG_SMTP GNUNET_EXTRA_LOGGING
- #define FILTER_STRING_SIZE 64
- /* how long can a line in base64 encoded
- mime text be? (in characters, excluding "\n") */
- #define MAX_CHAR_PER_LINE 76
- #define EBUF_LEN 128
- /**
- * Host-Address in a SMTP network.
- */
- typedef struct
- {
- /**
- * Filter line that every sender must include in the E-mails such
- * that the receiver can effectively filter out the GNUnet traffic
- * from the E-mail.
- */
- char filter[FILTER_STRING_SIZE];
- /**
- * Claimed E-mail address of the sender.
- * Format is "foo@bar.com" with null termination, padded to be
- * of a multiple of 8 bytes long.
- */
- char senderAddress[0];
- } EmailAddress;
- GNUNET_NETWORK_STRUCT_BEGIN
- /**
- * Encapsulation of a GNUnet message in the SMTP mail body (before
- * base64 encoding).
- */
- typedef struct
- {
- GNUNET_MessageHeader header;
- /**
- * What is the identity of the sender (GNUNET_hash of public key)
- */
- GNUNET_PeerIdentity sender;
- } SMTPMessage;
- GNUNET_NETWORK_STRUCT_END
- /* *********** globals ************* */
- /**
- * apis (our advertised API and the core api )
- */
- static GNUNET_CoreAPIForTransport *core_api;
- static struct GNUNET_GE_Context *ectx;
- /**
- * Thread that listens for inbound messages
- */
- static struct GNUNET_ThreadHandle *dispatchThread;
- /**
- * Flag to indicate that server has been shut down.
- */
- static int smtp_shutdown = GNUNET_YES;
- /**
- * Set to the SMTP server hostname (and port) for outgoing messages.
- */
- static char *smtp_server_name;
- static char *pipename;
- /**
- * Lock for uses of libesmtp (not thread-safe).
- */
- static struct GNUNET_Mutex *lock;
- /**
- * Old handler for SIGPIPE (kept to be able to restore).
- */
- static struct sigaction old_handler;
- static char *email;
- static GNUNET_TransportAPI smtpAPI;
- static GNUNET_Stats_ServiceAPI *stats;
- static int stat_bytesReceived;
- static int stat_bytesSent;
- static int stat_bytesDropped;
- /**
- * How many e-mails are we allowed to send per hour?
- */
- static unsigned long long rate_limit;
- static GNUNET_CronTime last_transmission;
- /* ********************* the real stuff ******************* */
- #define strAUTOncmp(a, b) strncmp (a, b, strlen (b))
- /**
- * Listen to the pipe, decode messages and send to core.
- */
- static void *
- listenAndDistribute (void *unused)
- {
- char *line;
- unsigned int linesize;
- SMTPMessage *mp;
- FILE *fdes;
- char *retl;
- char *out;
- unsigned int size;
- GNUNET_TransportPacket *coreMP;
- int fd;
- unsigned int pos;
- linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2)
- / MAX_CHAR_PER_LINE; /* maximum size of a line supported */
- line = GNUNET_malloc (linesize + 2); /* 2 bytes for off-by-one errors, just to be safe... */
- #define READLINE(l, limit) \
- do { retl = fgets (l, (limit), fdes); \
- if ((retl == NULL) || (smtp_shutdown == GNUNET_YES)) { \
- goto END; \
- } \
- if (core_api->load_monitor != NULL) \
- GNUNET_network_monitor_notify_transmission (core_api->load_monitor, \
- GNUNET_ND_DOWNLOAD, \
- strlen (retl)); \
- } while (0)
- while (smtp_shutdown == GNUNET_NO)
- {
- fd = OPEN (pipename, O_RDONLY | O_ASYNC);
- if (fd == -1)
- {
- if (smtp_shutdown == GNUNET_NO)
- GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
- continue;
- }
- fdes = fdopen (fd, "r");
- while (smtp_shutdown == GNUNET_NO)
- {
- /* skip until end of header */
- do
- {
- READLINE (line, linesize);
- }
- while ((line[0] != '\r') && (line[0] != '\n')); /* expect newline */
- READLINE (line, linesize); /* read base64 encoded message; decode, process */
- pos = 0;
- while (1)
- {
- pos = strlen (line) - 1; /* ignore new line */
- READLINE (&line[pos], linesize - pos); /* read base64 encoded message; decode, process */
- if ((line[pos] == '\r') || (line[pos] == '\n'))
- break; /* empty line => end of message! */
- }
- size = GNUNET_STRINGS_base64_decode (line, pos, &out);
- if (size < sizeof(SMTPMessage))
- {
- GNUNET_GE_BREAK (ectx, 0);
- GNUNET_free (out);
- goto END;
- }
- mp = (SMTPMessage *) &out[size - sizeof(SMTPMessage)];
- if (ntohs (mp->header.size) != size)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _ ("Received malformed message via %s. Ignored.\n"),
- "SMTP");
- #if DEBUG_SMTP
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "Size returned by base64=%d, in the msg=%d.\n", size,
- ntohl (mp->size));
- #endif
- GNUNET_free (out);
- goto END;
- }
- if (stats != NULL)
- stats->change (stat_bytesReceived, size);
- coreMP = GNUNET_new (GNUNET_TransportPacket);
- coreMP->msg = out;
- coreMP->size = size - sizeof(SMTPMessage);
- coreMP->tsession = NULL;
- coreMP->sender = mp->sender;
- #if DEBUG_SMTP
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "SMTP message passed to the core.\n");
- #endif
- core_api->receive (coreMP);
- }
- END:
- #if DEBUG_SMTP
- GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
- "SMTP message processed.\n");
- #endif
- if (fdes != NULL)
- fclose (fdes);
- }
- GNUNET_free (line);
- return NULL;
- }
- /* *************** API implementation *************** */
- /**
- * Verify that a hello-Message is correct (a node is reachable at that
- * address). Since the reply will be asynchronous, a method must be
- * called on success.
- *
- * @param hello the hello message to verify
- * (the signature/crc have been verified before)
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- */
- static int
- api_verify_hello (const GNUNET_MessageHello *hello)
- {
- const EmailAddress *maddr;
- maddr = (const EmailAddress *) &hello[1];
- if ((ntohs (hello->header.size) !=
- sizeof(GNUNET_MessageHello) + ntohs (hello->senderAddressSize)) ||
- (maddr->senderAddress
- [ntohs (hello->senderAddressSize) - 1 - FILTER_STRING_SIZE] != '\0'))
- {
- GNUNET_GE_BREAK (ectx, 0);
- return GNUNET_SYSERR; /* obviously invalid */
- }
- if (NULL == strstr (maddr->filter, ": "))
- return GNUNET_SYSERR;
- return GNUNET_OK;
- }
- /**
- * Create a hello-Message for the current node. The hello is created
- * without signature and without a timestamp. The GNUnet core will
- * GNUNET_RSA_sign the message and add an expiration time.
- *
- * @return hello on success, NULL on error
- */
- static GNUNET_MessageHello *
- api_create_hello ()
- {
- GNUNET_MessageHello *msg;
- char *filter;
- EmailAddress *haddr;
- int i;
- GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "FILTER",
- "X-mailer: GNUnet", &filter);
- if (NULL == strstr (filter, ": "))
- {
- GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _ ("SMTP filter string to invalid, lacks ': '\n"));
- GNUNET_free (filter);
- return NULL;
- }
- if (strlen (filter) > FILTER_STRING_SIZE)
- {
- filter[FILTER_STRING_SIZE] = '\0';
- GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
- _ ("SMTP filter string to long, capped to `%s'\n"), filter);
- }
- i = (strlen (email) + 8) & (~7); /* make multiple of 8 */
- msg =
- GNUNET_malloc (sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
- memset (msg, 0, sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
- haddr = (EmailAddress *) &msg[1];
- memset (&haddr->filter[0], 0, FILTER_STRING_SIZE);
- strcpy (&haddr->filter[0], filter);
- GNUNET_memcpy (&haddr->senderAddress[0], email, strlen (email) + 1);
- msg->senderAddressSize = htons (strlen (email) + 1 + sizeof(EmailAddress));
- msg->protocol = htons (GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
- msg->MTU = htonl (smtpAPI.mtu);
- msg->header.size = htons (GNUNET_sizeof_hello (msg));
- if (api_verify_hello (msg) == GNUNET_SYSERR)
- GNUNET_GE_ASSERT (ectx, 0);
- GNUNET_free (filter);
- return msg;
- }
- struct GetMessageClosure
- {
- unsigned int esize;
- unsigned int pos;
- char *ebody;
- };
- static const char *
- get_message (void **buf, int *len, void *cls)
- {
- struct GetMessageClosure *gmc = cls;
- *buf = NULL;
- if (len == NULL)
- {
- gmc->pos = 0;
- return NULL;
- }
- if (gmc->pos == gmc->esize)
- return NULL; /* done */
- *len = gmc->esize;
- gmc->pos = gmc->esize;
- return gmc->ebody;
- }
- /**
- * Send a message to the specified remote node.
- *
- * @param tsession the GNUNET_MessageHello identifying the remote node
- * @param msg what to send
- * @param size the size of the message
- * @param important is this message important enough to override typical limits?
- * @return GNUNET_SYSERR on error, GNUNET_OK on success
- */
- static int
- api_send (GNUNET_TSession *tsession, const void *msg, const unsigned int size,
- int important)
- {
- const GNUNET_MessageHello *hello;
- const EmailAddress *haddr;
- char *m;
- char *filter;
- char *fvalue;
- SMTPMessage *mp;
- struct GetMessageClosure gm_cls;
- smtp_session_t session;
- smtp_message_t message;
- smtp_recipient_t recipient;
- #define EBUF_LEN 128
- char ebuf[EBUF_LEN];
- GNUNET_CronTime now;
- if (smtp_shutdown == GNUNET_YES)
- return GNUNET_SYSERR;
- if ((size == 0) || (size > smtpAPI.mtu))
- {
- GNUNET_GE_BREAK (ectx, 0);
- return GNUNET_SYSERR;
- }
- now = GNUNET_get_time ();
- if ((important != GNUNET_YES) &&
- ( ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS) )
- return GNUNET_NO; /* rate too high */
- last_transmission = now;
- hello = (const GNUNET_MessageHello *) tsession->internal;
- if (hello == NULL)
- return GNUNET_SYSERR;
- GNUNET_mutex_lock (lock);
- session = smtp_create_session ();
- if (session == NULL)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_create_session", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- if (0 == smtp_set_server (session, smtp_server_name))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_set_server", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- haddr = (const EmailAddress *) &hello[1];
- message = smtp_add_message (session);
- if (message == NULL)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_add_message", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- smtp_set_header (message, "To", NULL, haddr->senderAddress);
- smtp_set_header (message, "From", NULL, email);
- filter = GNUNET_strdup (haddr->filter);
- fvalue = strstr (filter, ": ");
- GNUNET_GE_ASSERT (NULL, NULL != fvalue);
- fvalue[0] = '\0';
- fvalue += 2;
- if (0 == smtp_set_header (message, filter, fvalue))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_set_header", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- GNUNET_free (filter);
- return GNUNET_SYSERR;
- }
- GNUNET_free (filter);
- m = GNUNET_malloc (size + sizeof(SMTPMessage));
- GNUNET_memcpy (m, msg, size);
- mp = (SMTPMessage *) &m[size];
- mp->header.size = htons (size + sizeof(SMTPMessage));
- mp->header.type = htons (0);
- mp->sender = *core_api->my_identity;
- gm_cls.ebody = NULL;
- gm_cls.pos = 0;
- gm_cls.esize = GNUNET_STRINGS_base64_encode (m, size + sizeof(SMTPMessage),
- &gm_cls.ebody);
- GNUNET_free (m);
- if (0 == smtp_size_set_estimate (message, gm_cls.esize))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- }
- if (0 == smtp_set_messagecb (message, &get_message, &gm_cls))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- GNUNET_free (gm_cls.ebody);
- return GNUNET_SYSERR;
- }
- recipient = smtp_add_recipient (message, haddr->senderAddress);
- if (recipient == NULL)
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- if (0 == smtp_start_session (session))
- {
- GNUNET_GE_LOG (ectx,
- GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
- | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
- "smtp_start_session", smtp_strerror (smtp_errno (), ebuf,
- EBUF_LEN));
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- GNUNET_free (gm_cls.ebody);
- return GNUNET_SYSERR;
- }
- if (stats != NULL)
- stats->change (stat_bytesSent, size);
- if (core_api->load_monitor != NULL)
- GNUNET_network_monitor_notify_transmission (core_api->load_monitor,
- GNUNET_ND_UPLOAD, gm_cls.esize);
- smtp_message_reset_status (message); /* this is needed to plug a 28-byte/message memory leak in libesmtp */
- smtp_destroy_session (session);
- GNUNET_mutex_unlock (lock);
- GNUNET_free (gm_cls.ebody);
- return GNUNET_OK;
- }
- /**
- * Establish a connection to a remote node.
- * @param hello the hello-Message for the target node
- * @param tsessionPtr the session handle that is to be set
- * @param may_reuse can we re-use an existing connection?
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
- */
- static int
- api_connect (const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr,
- int may_reuse)
- {
- GNUNET_TSession *tsession;
- tsession = GNUNET_new (GNUNET_TSession);
- tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello));
- tsession->peer = hello->senderIdentity;
- GNUNET_memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
- tsession->ttype = smtpAPI.protocol_number;
- (*tsessionPtr) = tsession;
- return GNUNET_OK;
- }
- /**
- * Disconnect from a remote node.
- *
- * @param tsession the session that is closed
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
- */
- static int
- api_disconnect (GNUNET_TSession *tsession)
- {
- if (tsession != NULL)
- {
- if (tsession->internal != NULL)
- GNUNET_free (tsession->internal);
- GNUNET_free (tsession);
- }
- return GNUNET_OK;
- }
- /**
- * Start the server process to receive inbound traffic.
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
- */
- static int
- api_start_transport_server ()
- {
- smtp_shutdown = GNUNET_NO;
- /* initialize SMTP network */
- dispatchThread = GNUNET_thread_create (&listenAndDistribute, NULL, 1024 * 4);
- if (dispatchThread == NULL)
- {
- GNUNET_GE_DIE_STRERROR (ectx,
- GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
- "pthread_create");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- /**
- * Shutdown the server process (stop receiving inbound traffic). Maybe
- * restarted later!
- */
- static int
- api_stop_transport_server ()
- {
- void *unused;
- smtp_shutdown = GNUNET_YES;
- GNUNET_thread_stop_sleep (dispatchThread);
- GNUNET_thread_join (dispatchThread, &unused);
- return GNUNET_OK;
- }
- /**
- * Convert SMTP hello to an IP address (always fails).
- */
- static int
- api_hello_to_address (const GNUNET_MessageHello *hello, void **sa,
- unsigned int *sa_len)
- {
- return GNUNET_SYSERR;
- }
- /**
- * Always fails.
- */
- static int
- api_associate (GNUNET_TSession *tsession)
- {
- return GNUNET_SYSERR; /* SMTP connections can never be associated */
- }
- /**
- * Always succeeds (for now; we should look at adding
- * frequency limits to SMTP in the future!).
- */
- static int
- api_test_would_try (GNUNET_TSession *tsession, unsigned int size,
- int important)
- {
- return GNUNET_OK; /* we always try... */
- }
- /**
- * The exported method. Makes the core api available via a global and
- * returns the smtp transport API.
- */
- GNUNET_TransportAPI *
- inittransport_smtp (struct GNUNET_CoreAPIForTransport *core)
- {
- unsigned long long mtu;
- struct sigaction sa;
- core_api = core;
- ectx = core->ectx;
- if (! GNUNET_GC_have_configuration_value (core_api->cfg, "SMTP", "EMAIL"))
- {
- GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
- _
- (
- "No email-address specified, can not start SMTP transport.\n"));
- return NULL;
- }
- GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "MTU", 1200,
- SMTP_MESSAGE_SIZE,
- SMTP_MESSAGE_SIZE, &mtu);
- GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "RATELIMIT",
- 0, 0, 1024 * 1024, &rate_limit);
- stats = core_api->service_request ("stats");
- if (stats != NULL)
- {
- stat_bytesReceived =
- stats->create (gettext_noop ("# bytes received via SMTP"));
- stat_bytesSent = stats->create (gettext_noop ("# bytes sent via SMTP"));
- stat_bytesDropped =
- stats->create (gettext_noop ("# bytes dropped by SMTP (outgoing)"));
- }
- GNUNET_GC_get_configuration_value_filename (core_api->cfg, "SMTP", "PIPE",
- &pipename);
- unlink (pipename);
- if (0 != mkfifo (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
- {
- GNUNET_GE_LOG_STRERROR (ectx,
- GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
- "mkfifo");
- GNUNET_free (pipename);
- core_api->service_release (stats);
- stats = NULL;
- return NULL;
- }
- /* we need to allow the mailer program to send us messages;
- * easiest done by giving it write permissions (see Mantis #1142) */
- if (0 != chmod (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
- GNUNET_GE_LOG_STRERROR (ectx,
- GNUNET_GE_ADMIN | GNUNET_GE_BULK
- | GNUNET_GE_WARNING, "chmod");
- GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "EMAIL",
- NULL,
- &email);
- lock = GNUNET_mutex_create (GNUNET_NO);
- GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "SERVER",
- "localhost:25", &smtp_server_name);
- sa.sa_handler = SIG_IGN;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction (SIGPIPE, &sa, &old_handler);
- smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
- smtpAPI.mtu = mtu - sizeof(SMTPMessage);
- smtpAPI.cost = 50;
- smtpAPI.hello_verify = &api_verify_hello;
- smtpAPI.hello_create = &api_create_hello;
- smtpAPI.connect = &api_connect;
- smtpAPI.send = &api_send;
- smtpAPI.associate = &api_associate;
- smtpAPI.disconnect = &api_disconnect;
- smtpAPI.server_start = &api_start_transport_server;
- smtpAPI.server_stop = &api_stop_transport_server;
- smtpAPI.hello_to_address = &api_hello_to_address;
- smtpAPI.send_now_test = &api_test_would_try;
- return &smtpAPI;
- }
- void
- donetransport_smtp ()
- {
- sigaction (SIGPIPE, &old_handler, NULL);
- GNUNET_free (smtp_server_name);
- if (stats != NULL)
- {
- core_api->service_release (stats);
- stats = NULL;
- }
- GNUNET_mutex_destroy (lock);
- lock = NULL;
- unlink (pipename);
- GNUNET_free (pipename);
- pipename = NULL;
- GNUNET_free (email);
- email = NULL;
- }
- /* end of smtp.c */
|