diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-05-21 01:27:49 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-05-21 01:27:49 +0000 |
commit | f666fe802124b85b8215835d15363b64fa5af727 (patch) | |
tree | 92b6ea00b0feb6e89f68318bec78873d7de4c57d /usr.sbin/smtpd | |
parent | 3f542ffa36fa54b9a6a0decb07e9a48a29d33a9f (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.y | 115 |
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); +} |