diff --git a/Makefile b/Makefile index 4671759cd8..4e3e166805 100644 --- a/Makefile +++ b/Makefile @@ -664,7 +664,7 @@ OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocol.o \ src/session.o src/hdr_idx.o src/ev_select.o src/signal.o \ src/acl.o src/sample.o src/memory.o src/freq_ctr.o src/auth.o \ src/compression.o src/payload.o src/hash.o src/pattern.o src/map.o \ - src/namespace.o + src/namespace.o src/mailers.o EBTREE_OBJS = $(EBTREE_DIR)/ebtree.o \ $(EBTREE_DIR)/eb32tree.o $(EBTREE_DIR)/eb64tree.o \ diff --git a/include/types/mailers.h b/include/types/mailers.h new file mode 100644 index 0000000000..582bb94f6d --- /dev/null +++ b/include/types/mailers.h @@ -0,0 +1,65 @@ +/* + * include/types/mailer.h + * This file defines everything related to mailer. + * + * Copyright 2015 Horms Solutions Ltd., Simon Horman + * + * Based on include/types/peers.h + * + * Copyright 2010 EXCELIANCE, Emeric Brun + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, version 2.1 + * exclusively. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TYPES_EMAIL_ALERT_H +#define _TYPES_EMAIL_ALERT_H + +#include +#include +#include +#include + +struct mailer { + char *id; + struct mailers *mailers; + struct { + const char *file; /* file where the section appears */ + int line; /* line where the section appears */ + } conf; /* config information */ + struct sockaddr_storage addr; /* SMTP server address */ + struct protocol *proto; /* SMTP server address's protocol */ + struct xprt_ops *xprt; /* SMTP server socket operations at transport layer */ + void *sock_init_arg; /* socket operations's opaque init argument if needed */ + struct mailer *next; /* next mailer in the list */ +}; + + +struct mailers { + char *id; /* mailers section name */ + struct mailer *mailer_list; /* mailers in this mailers section */ + struct { + const char *file; /* file where the section appears */ + int line; /* line where the section appears */ + } conf; /* config information */ + struct mailers *next; /* next mailers section */ + int count; /* total number of mailers in this mailers section */ + int users; /* number of users of this mailers section */ +}; + + +extern struct mailers *mailers; + +#endif /* _TYPES_EMAIL_ALERT_H */ + diff --git a/src/cfgparse.c b/src/cfgparse.c index c5f20a36a2..2db5ed1955 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -1916,6 +1917,145 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) return err_code; } + +/* + * Parse a line in a , , or section. + * Returns the error code, 0 if OK, or any combination of : + * - ERR_ABORT: must abort ASAP + * - ERR_FATAL: we can continue parsing but not start the service + * - ERR_WARN: a warning has been emitted + * - ERR_ALERT: an alert has been emitted + * Only the two first ones can stop processing, the two others are just + * indicators. + */ +int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm) +{ + static struct mailers *curmailers = NULL; + struct mailer *newmailer = NULL; + const char *err; + int err_code = 0; + char *errmsg = NULL; + + if (strcmp(args[0], "mailers") == 0) { /* new mailers section */ + if (!*args[1]) { + Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + err = invalid_char(args[1]); + if (err) { + Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n", + file, linenum, *err, args[0], args[1]); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) { + /* + * If there are two proxies with the same name only following + * combinations are allowed: + */ + if (strcmp(curmailers->id, args[1]) == 0) { + Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n", + file, linenum, args[1], curmailers->conf.file, curmailers->conf.line); + err_code |= ERR_WARN; + } + } + + if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) { + Alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + curmailers->next = mailers; + mailers = curmailers; + curmailers->conf.file = strdup(file); + curmailers->conf.line = linenum; + curmailers->id = strdup(args[1]); + } + else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */ + struct sockaddr_storage *sk; + int port1, port2; + struct protocol *proto; + + if (!*args[2]) { + Alert("parsing [%s:%d] : '%s' expects and [:] as arguments.\n", + file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + err = invalid_char(args[1]); + if (err) { + Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n", + file, linenum, *err, args[1]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) { + Alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + /* the mailers are linked backwards first */ + curmailers->count++; + newmailer->next = curmailers->mailer_list; + curmailers->mailer_list = newmailer; + newmailer->mailers = curmailers; + newmailer->conf.file = strdup(file); + newmailer->conf.line = linenum; + + newmailer->id = strdup(args[1]); + + sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL); + if (!sk) { + Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + proto = protocol_by_family(sk->ss_family); + if (!proto || !proto->connect) { + Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", + file, linenum, args[0], args[1]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + if (port1 != port2) { + Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n", + file, linenum, args[0], args[1], args[2]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + if (!port1) { + Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n", + file, linenum, args[0], args[1], args[2]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + newmailer->addr = *sk; + newmailer->proto = proto; + newmailer->xprt = &raw_sock; + newmailer->sock_init_arg = NULL; + } /* neither "mailer" nor "mailers" */ + else if (*args[0] != 0) { + Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + +out: + free(errmsg); + return err_code; +} + int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) { static struct proxy *curproxy = NULL; @@ -5942,6 +6082,7 @@ int readcfgfile(const char *file) !cfg_register_section("global", cfg_parse_global) || !cfg_register_section("userlist", cfg_parse_users) || !cfg_register_section("peers", cfg_parse_peers) || + !cfg_register_section("mailers", cfg_parse_mailers) || !cfg_register_section("namespace_list", cfg_parse_netns)) return -1; @@ -7653,6 +7794,42 @@ int check_config_validity() } } + if (mailers) { + struct mailers *curmailers = mailers, **last; + struct mailer *m, *mb; + + /* Remove all mailers sections which don't have a valid listener. + * This can happen when a mailers section is never referenced. + */ + last = &mailers; + while (*last) { + curmailers = *last; + if (curmailers->users) { + last = &curmailers->next; + continue; + } + + Warning("Removing incomplete section 'mailers %s'.\n", + curmailers->id); + + m = curmailers->mailer_list; + while (m) { + mb = m->next; + free(m->id); + free(m); + m = mb; + } + + /* Destroy and unlink this curmailers section. + * Note: curmailers is backed up into *last. + */ + free(curmailers->id); + curmailers = curmailers->next; + free(*last); + *last = curmailers; + } + } + pool2_hdr_idx = create_pool("hdr_idx", global.tune.max_http_hdr * sizeof(struct hdr_idx_elem), MEM_F_SHARED); diff --git a/src/mailers.c b/src/mailers.c new file mode 100644 index 0000000000..4335453b59 --- /dev/null +++ b/src/mailers.c @@ -0,0 +1,17 @@ +/* + * Mailer management. + * + * Copyright 2015 Horms Solutions Ltd, Simon Horman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include + +#include + +struct mailers *mailers = NULL;