summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2009-05-21 01:27:49 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2009-05-21 01:27:49 +0000
commitf666fe802124b85b8215835d15363b64fa5af727 (patch)
tree92b6ea00b0feb6e89f68318bec78873d7de4c57d /usr.sbin/smtpd
parent3f542ffa36fa54b9a6a0decb07e9a48a29d33a9f (diff)
no longer create a dynamic map with 127.0.0.1 and ::1 for every single rule
that has an implicit local source. instead we create static "localhost" map before the configuration file is parsed, we fill it with every single local address we can find, and we have rules with implicit local source reference that special map. this unbreaks a behavior which I hated and which prevented: accept for all relay from accepting relaying if LOCAL session was initiated on any interface but lo0.
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r--usr.sbin/smtpd/parse.y115
1 files changed, 70 insertions, 45 deletions
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index 0a4413fac7c..d150902f29b 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.33 2009/05/20 14:29:44 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.34 2009/05/21 01:27:48 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -98,6 +98,7 @@ int host(const char *, const char *, struct listenerlist *,
int, in_port_t, u_int8_t);
int interface(const char *, const char *, struct listenerlist *,
int, in_port_t, u_int8_t);
+void set_localaddrs(void);
typedef struct {
union {
@@ -814,51 +815,8 @@ from : FROM mapref {
}
| /* empty */ {
struct map *m;
- struct mapel *me;
- struct sockaddr_in *ssin;
- struct sockaddr_in6 *ssin6;
-
- if ((m = calloc(1, sizeof(*m))) == NULL)
- fatal("out of memory");
- m->m_id = last_map_id++;
- if (m->m_id == INT_MAX) {
- yyerror("too many maps defined");
- free(m);
- YYERROR;
- }
- if (! bsnprintf(m->m_name, sizeof(m->m_name),
- "<dynamic(%u)>", m->m_id))
- fatal("snprintf");
- m->m_flags |= F_DYNAMIC|F_USED;
- m->m_type = T_SINGLE;
-
- TAILQ_INIT(&m->m_contents);
-
- if ((me = calloc(1, sizeof(*me))) == NULL)
- fatal("out of memory");
- me->me_key.med_addr.bits = 0;
- ssin = (struct sockaddr_in *)&me->me_key.med_addr.ss;
- ssin->sin_family = AF_INET;
- if (inet_pton(AF_INET, "127.0.0.1", &ssin->sin_addr) != 1) {
- free(me);
- free(m);
- YYERROR;
- }
- TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
-
- if ((me = calloc(1, sizeof(*me))) == NULL)
- fatal("out of memory");
- me->me_key.med_addr.bits = 0;
- ssin6 = (struct sockaddr_in6 *)&me->me_key.med_addr.ss;
- ssin6->sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, "::1", &ssin6->sin6_addr) != 1) {
- free(me);
- free(m);
- YYERROR;
- }
- TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
- TAILQ_INSERT_TAIL(conf->sc_maps, m, m_entry);
+ m = map_findbyname(conf, "localhost");
$$ = m->m_id;
}
;
@@ -1275,6 +1233,7 @@ int
parse_config(struct smtpd *x_conf, const char *filename, int opts)
{
struct sym *sym, *next;
+ struct map *m;
conf = x_conf;
bzero(conf, sizeof(*conf));
@@ -1287,6 +1246,12 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
free(conf->sc_maps);
return 0;
}
+ if ((m = calloc(1, sizeof(*m))) == NULL) {
+ log_warn("cannot allocate memory");
+ free(conf->sc_maps);
+ free(conf->sc_rules);
+ return 0;
+ }
errors = 0;
last_map_id = 0;
@@ -1311,6 +1276,18 @@ parse_config(struct smtpd *x_conf, const char *filename, int opts)
topfile = file;
/*
+ * declare special "local" map
+ */
+ m->m_id = last_map_id++;
+ if (strlcpy(m->m_name, "localhost", sizeof(m->m_name))
+ >= sizeof(m->m_name))
+ fatal("strlcpy");
+ m->m_type = T_LIST;
+ TAILQ_INIT(&m->m_contents);
+ TAILQ_INSERT_TAIL(conf->sc_maps, m, m_entry);
+ set_localaddrs();
+
+ /*
* parse configuration
*/
setservent(1);
@@ -1628,3 +1605,51 @@ interface(const char *s, const char *cert, struct listenerlist *al, int max, in_
return ret;
}
+
+void
+set_localaddrs(void)
+{
+ struct ifaddrs *ifap, *p;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sain;
+ struct sockaddr_in6 *sin6;
+ struct map *m;
+ struct mapel *me;
+
+ if (getifaddrs(&ifap) == -1)
+ fatal("getifaddrs");
+
+ m = map_findbyname(conf, "localhost");
+
+ for (p = ifap; p != NULL; p = p->ifa_next) {
+ switch (p->ifa_addr->sa_family) {
+ case AF_INET:
+ sain = (struct sockaddr_in *)&ss;
+ *sain = *(struct sockaddr_in *)p->ifa_addr;
+ sain->sin_len = sizeof(struct sockaddr_in);
+
+ if ((me = calloc(1, sizeof(*me))) == NULL)
+ fatal("out of memory");
+ me->me_key.med_addr.bits = 0;
+ me->me_key.med_addr.ss = *(struct sockaddr_storage *)sain;
+ TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
+
+ break;
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&ss;
+ *sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+
+ if ((me = calloc(1, sizeof(*me))) == NULL)
+ fatal("out of memory");
+ me->me_key.med_addr.bits = 0;
+ me->me_key.med_addr.ss = *(struct sockaddr_storage *)sin6;
+ TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
+
+ break;
+ }
+ }
+
+ freeifaddrs(ifap);
+}