summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2012-05-13 00:10:50 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2012-05-13 00:10:50 +0000
commitd4519c494c7974b50ea27f225264140734385a4b (patch)
tree1eb6171f3d6576734c9b808deb6534dd93cf65ac /usr.sbin
parentbe2353b2a7b188c78bbf94f4c28cef23d8951bd7 (diff)
- cleanup parse.y by removing lots of code that should not have been there,
but in ruleset.c and util.c instead. - introduce the new map_compare() map API call to allow iterating over keys and comparing them with provided key using provided function. this allows checking a partial key in a key set, very useful for comparing an address to a set of netmask. - introduce new map kind K_NETADDR - implement K_NETADDR for map_db and map_stdio - teach ruleset checking how to use the map_compare() with K_NETADDR we can now do the following: map "srcaddr" source plain "/etc/mail/srcaddr.txt" accept from map srcaddr for domain "openbsd.org" [...]
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/smtpd/map.c28
-rw-r--r--usr.sbin/smtpd/map_db.c58
-rw-r--r--usr.sbin/smtpd/map_stdio.c82
-rw-r--r--usr.sbin/smtpd/parse.y155
-rw-r--r--usr.sbin/smtpd/ruleset.c65
-rw-r--r--usr.sbin/smtpd/smtpd.h12
-rw-r--r--usr.sbin/smtpd/util.c61
7 files changed, 293 insertions, 168 deletions
diff --git a/usr.sbin/smtpd/map.c b/usr.sbin/smtpd/map.c
index 3985641707a..89f3f24e86d 100644
--- a/usr.sbin/smtpd/map.c
+++ b/usr.sbin/smtpd/map.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: map.c,v 1.25 2011/12/13 22:09:53 eric Exp $ */
+/* $OpenBSD: map.c,v 1.26 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -100,3 +100,29 @@ map_lookup(objid_t mapid, char *key, enum map_kind kind)
backend->close(hdl);
return ret;
}
+
+int
+map_compare(objid_t mapid, char *key, enum map_kind kind,
+ int (*func)(char *, char *))
+{
+ void *hdl = NULL;
+ struct map *map;
+ struct map_backend *backend = NULL;
+ int ret;
+
+ map = map_find(mapid);
+ if (map == NULL)
+ return 0;
+
+ backend = map_backend_lookup(map->m_src);
+ hdl = backend->open(map->m_config);
+ if (hdl == NULL) {
+ log_warn("map_lookup: can't open %s", map->m_config);
+ return 0;
+ }
+
+ ret = backend->compare(hdl, key, kind, func);
+
+ backend->close(hdl);
+ return ret;
+}
diff --git a/usr.sbin/smtpd/map_db.c b/usr.sbin/smtpd/map_db.c
index 860a8a54c6f..6b1e462d61c 100644
--- a/usr.sbin/smtpd/map_db.c
+++ b/usr.sbin/smtpd/map_db.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: map_db.c,v 1.2 2012/05/12 15:29:16 gilles Exp $ */
+/* $OpenBSD: map_db.c,v 1.3 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -39,18 +39,22 @@
/* db(3) backend */
static void *map_db_open(char *);
static void *map_db_lookup(void *, char *, enum map_kind);
+static int map_db_compare(void *, char *, enum map_kind,
+ int (*)(char *, char *));
static void map_db_close(void *);
static char *map_db_get_entry(void *, char *, size_t *);
static void *map_db_credentials(char *, char *, size_t);
static void *map_db_alias(char *, char *, size_t);
static void *map_db_virtual(char *, char *, size_t);
+static void *map_db_netaddr(char *, char *, size_t);
struct map_backend map_backend_db = {
map_db_open,
map_db_close,
- map_db_lookup
+ map_db_lookup,
+ map_db_compare
};
@@ -93,6 +97,10 @@ map_db_lookup(void *hdl, char *key, enum map_kind kind)
ret = map_db_virtual(key, line, len);
break;
+ case K_NETADDR:
+ ret = map_db_netaddr(key, line, len);
+ break;
+
default:
break;
}
@@ -102,6 +110,32 @@ map_db_lookup(void *hdl, char *key, enum map_kind kind)
return ret;
}
+static int
+map_db_compare(void *hdl, char *key, enum map_kind kind,
+ int (*func)(char *, char *))
+{
+ int ret = 0;
+ DB *db = hdl;
+ DBT dbk;
+ DBT dbd;
+ int r;
+ char *buf = NULL;
+
+ for (r = db->seq(db, &dbk, &dbd, R_FIRST); !r;
+ r = db->seq(db, &dbk, &dbd, R_NEXT)) {
+ buf = calloc(dbk.size+1, 1);
+ if (buf == NULL)
+ fatalx("calloc");
+ strlcpy(buf, dbk.data, dbk.size+1);
+ log_debug("key: %s, buf: %s", key, buf);
+ if (func(key, buf))
+ ret = 1;
+ free(buf);
+ if (ret)
+ break;
+ }
+ return ret;
+}
static char *
map_db_get_entry(void *hdl, char *key, size_t *len)
@@ -256,3 +290,23 @@ error:
free(map_virtual);
return NULL;
}
+
+
+static void *
+map_db_netaddr(char *key, char *line, size_t len)
+{
+ struct map_netaddr *map_netaddr = NULL;
+
+ map_netaddr = calloc(1, sizeof(struct map_netaddr));
+ if (map_netaddr == NULL)
+ fatalx("calloc");
+
+ if (! text_to_netaddr(&map_netaddr->netaddr, line))
+ goto error;
+
+ return map_netaddr;
+
+error:
+ free(map_netaddr);
+ return NULL;
+}
diff --git a/usr.sbin/smtpd/map_stdio.c b/usr.sbin/smtpd/map_stdio.c
index 2e6e55a1788..bf0067afd64 100644
--- a/usr.sbin/smtpd/map_stdio.c
+++ b/usr.sbin/smtpd/map_stdio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: map_stdio.c,v 1.2 2012/05/12 15:29:16 gilles Exp $ */
+/* $OpenBSD: map_stdio.c,v 1.3 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -38,18 +38,22 @@
/* stdio(3) backend */
static void *map_stdio_open(char *);
static void *map_stdio_lookup(void *, char *, enum map_kind);
+static int map_stdio_compare(void *, char *, enum map_kind,
+ int (*)(char *, char *));
static void map_stdio_close(void *);
static char *map_stdio_get_entry(void *, char *, size_t *);
static void *map_stdio_credentials(char *, char *, size_t);
static void *map_stdio_alias(char *, char *, size_t);
static void *map_stdio_virtual(char *, char *, size_t);
+static void *map_stdio_netaddr(char *, char *, size_t);
struct map_backend map_backend_stdio = {
map_stdio_open,
map_stdio_close,
- map_stdio_lookup
+ map_stdio_lookup,
+ map_stdio_compare
};
@@ -72,24 +76,28 @@ map_stdio_lookup(void *hdl, char *key, enum map_kind kind)
{
char *line;
size_t len;
- struct map_alias *ma;
+ void *ret;
line = map_stdio_get_entry(hdl, key, &len);
if (line == NULL)
return NULL;
- ma = NULL;
+ ret = NULL;
switch (kind) {
case K_ALIAS:
- ma = map_stdio_alias(key, line, len);
+ ret = map_stdio_alias(key, line, len);
break;
case K_CREDENTIALS:
- ma = map_stdio_credentials(key, line, len);
+ ret = map_stdio_credentials(key, line, len);
break;
case K_VIRTUAL:
- ma = map_stdio_virtual(key, line, len);
+ ret = map_stdio_virtual(key, line, len);
+ break;
+
+ case K_NETADDR:
+ ret = map_stdio_netaddr(key, line, len);
break;
default:
@@ -98,7 +106,46 @@ map_stdio_lookup(void *hdl, char *key, enum map_kind kind)
free(line);
- return ma;
+ return ret;
+}
+
+static int
+map_stdio_compare(void *hdl, char *key, enum map_kind kind,
+ int (*func)(char *, char *))
+{
+ char *buf, *lbuf;
+ size_t flen;
+ char *keyp;
+ FILE *fp = hdl;
+ int ret = 0;
+
+ lbuf = NULL;
+ while ((buf = fgetln(fp, &flen))) {
+ if (buf[flen - 1] == '\n')
+ buf[flen - 1] = '\0';
+ else {
+ if ((lbuf = malloc(flen + 1)) == NULL)
+ err(1, NULL);
+ memcpy(lbuf, buf, flen);
+ lbuf[flen] = '\0';
+ buf = lbuf;
+ }
+
+ keyp = buf;
+ while (isspace((int)*keyp))
+ ++keyp;
+ if (*keyp == '\0' || *keyp == '#')
+ continue;
+
+ if (! func(key, keyp))
+ continue;
+
+ ret = 1;
+ break;
+ }
+ free(lbuf);
+
+ return ret;
}
static char *
@@ -278,3 +325,22 @@ error:
free(map_virtual);
return NULL;
}
+
+static void *
+map_stdio_netaddr(char *key, char *line, size_t len)
+{
+ struct map_netaddr *map_netaddr = NULL;
+
+ map_netaddr = calloc(1, sizeof(struct map_netaddr));
+ if (map_netaddr == NULL)
+ fatalx("calloc");
+
+ if (! text_to_netaddr(&map_netaddr->netaddr, line))
+ goto error;
+
+ return map_netaddr;
+
+error:
+ free(map_netaddr);
+ return NULL;
+}
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index dcebfcd5663..9f7c885abaa 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.87 2012/05/12 21:49:31 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.88 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -515,60 +515,17 @@ keyval_list : keyval
stringel : STRING {
struct mapel *me;
- int bits;
- struct sockaddr_in ssin;
- struct sockaddr_in6 ssin6;
if ((me = calloc(1, sizeof(*me))) == NULL)
fatal("out of memory");
- /* Attempt detection of $1 format */
- if (strchr($1, '/') != NULL) {
- /* Dealing with a netmask */
- bzero(&ssin, sizeof(struct sockaddr_in));
- bits = inet_net_pton(AF_INET, $1, &ssin.sin_addr, sizeof(struct in_addr));
- if (bits != -1) {
- ssin.sin_family = AF_INET;
- me->me_key.med_addr.bits = bits;
- memcpy(&me->me_key.med_addr.ss, &ssin, sizeof(ssin));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in);
- }
- else {
- bzero(&ssin6, sizeof(struct sockaddr_in6));
- bits = inet_net_pton(AF_INET6, $1, &ssin6.sin6_addr, sizeof(struct in6_addr));
- if (bits == -1)
- err(1, "inet_net_pton");
- ssin6.sin6_family = AF_INET6;
- me->me_key.med_addr.bits = bits;
- memcpy(&me->me_key.med_addr.ss, &ssin6, sizeof(ssin6));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in6);
- }
- }
- else {
- /* IP address ? */
- if (inet_pton(AF_INET, $1, &ssin.sin_addr) == 1) {
- ssin.sin_family = AF_INET;
- me->me_key.med_addr.bits = 32;
- memcpy(&me->me_key.med_addr.ss, &ssin, sizeof(ssin));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in);
- }
- else if (inet_pton(AF_INET6, $1, &ssin6.sin6_addr) == 1) {
- ssin6.sin6_family = AF_INET6;
- me->me_key.med_addr.bits = 128;
- memcpy(&me->me_key.med_addr.ss, &ssin6, sizeof(ssin6));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in6);
- }
- else {
- /* either a hostname or a value unrelated to network */
- if (strlcpy(me->me_key.med_string, $1,
- sizeof(me->me_key.med_string)) >=
- sizeof(me->me_key.med_string)) {
- yyerror("map element too long: %s", $1);
- free(me);
- free($1);
- YYERROR;
- }
- }
+ if (strlcpy(me->me_key.med_string, $1,
+ sizeof(me->me_key.med_string)) >=
+ sizeof(me->me_key.med_string)) {
+ yyerror("map element too long: %s", $1);
+ free(me);
+ free($1);
+ YYERROR;
}
free($1);
TAILQ_INSERT_TAIL(contents, me, me_entry);
@@ -582,9 +539,6 @@ string_list : stringel
mapref : STRING {
struct map *m;
struct mapel *me;
- int bits;
- struct sockaddr_in ssin;
- struct sockaddr_in6 ssin6;
if ((m = calloc(1, sizeof(*m))) == NULL)
fatal("out of memory");
@@ -604,54 +558,13 @@ mapref : STRING {
if ((me = calloc(1, sizeof(*me))) == NULL)
fatal("out of memory");
- /* Attempt detection of $1 format */
- if (strchr($1, '/') != NULL) {
- /* Dealing with a netmask */
- bzero(&ssin, sizeof(struct sockaddr_in));
- bits = inet_net_pton(AF_INET, $1, &ssin.sin_addr, sizeof(struct in_addr));
- if (bits != -1) {
- ssin.sin_family = AF_INET;
- me->me_key.med_addr.bits = bits;
- memcpy(&me->me_key.med_addr.ss, &ssin, sizeof(ssin));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in);
- }
- else {
- bzero(&ssin6, sizeof(struct sockaddr_in6));
- bits = inet_net_pton(AF_INET6, $1, &ssin6.sin6_addr, sizeof(struct in6_addr));
- if (bits == -1)
- err(1, "inet_net_pton");
- ssin6.sin6_family = AF_INET6;
- me->me_key.med_addr.bits = bits;
- memcpy(&me->me_key.med_addr.ss, &ssin6, sizeof(ssin6));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in6);
- }
- }
- else {
- /* IP address ? */
- if (inet_pton(AF_INET, $1, &ssin.sin_addr) == 1) {
- ssin.sin_family = AF_INET;
- me->me_key.med_addr.bits = 32;
- memcpy(&me->me_key.med_addr.ss, &ssin, sizeof(ssin));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in);
- }
- else if (inet_pton(AF_INET6, $1, &ssin6.sin6_addr) == 1) {
- ssin6.sin6_family = AF_INET6;
- me->me_key.med_addr.bits = 128;
- memcpy(&me->me_key.med_addr.ss, &ssin6, sizeof(ssin6));
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in6);
- }
- else {
- /* either a hostname or a value unrelated to network */
- if (strlcpy(me->me_key.med_string, $1,
- sizeof(me->me_key.med_string)) >=
- sizeof(me->me_key.med_string)) {
- yyerror("map element too long: %s", $1);
- free(me);
- free(m);
- free($1);
- YYERROR;
- }
- }
+ if (strlcpy(me->me_key.med_string, $1,
+ sizeof(me->me_key.med_string)) >=
+ sizeof(me->me_key.med_string)) {
+ yyerror("map element too long: %s", $1);
+ free(me);
+ free($1);
+ YYERROR;
}
free($1);
@@ -1025,8 +938,6 @@ from : FROM mapref {
| FROM ALL {
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");
@@ -1044,28 +955,14 @@ from : FROM mapref {
if ((me = calloc(1, sizeof(*me))) == NULL)
fatal("out of memory");
- me->me_key.med_addr.bits = 0;
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in);
- ssin = (struct sockaddr_in *)&me->me_key.med_addr.ss;
- ssin->sin_family = AF_INET;
- if (inet_pton(AF_INET, "0.0.0.0", &ssin->sin_addr) != 1) {
- free(me);
- free(m);
- YYERROR;
- }
+ (void)strlcpy(me->me_key.med_string, "0.0.0.0/0",
+ sizeof(me->me_key.med_string));
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;
- me->me_key.med_addr.ss.ss_len = sizeof(struct sockaddr_in6);
- ssin6 = (struct sockaddr_in6 *)&me->me_key.med_addr.ss;
- ssin6->sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, "::", &ssin6->sin6_addr) != 1) {
- free(me);
- free(m);
- YYERROR;
- }
+ (void)strlcpy(me->me_key.med_string, "::/0",
+ sizeof(me->me_key.med_string));
TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
TAILQ_INSERT_TAIL(conf->sc_maps, m, m_entry);
@@ -1962,26 +1859,24 @@ set_localaddrs(void)
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 = 32;
- me->me_key.med_addr.ss = *(struct sockaddr_storage *)sain;
+ (void)strlcpy(me->me_key.med_string,
+ ss_to_text(&ss),
+ sizeof(me->me_key.med_string));
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 = 128;
- me->me_key.med_addr.ss = *(struct sockaddr_storage *)sin6;
+ (void)strlcpy(me->me_key.med_string,
+ ss_to_text(&ss),
+ sizeof(me->me_key.med_string));
TAILQ_INSERT_TAIL(&m->m_contents, me, me_entry);
-
break;
}
}
diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c
index c5a9b68cff0..1923e0766d9 100644
--- a/usr.sbin/smtpd/ruleset.c
+++ b/usr.sbin/smtpd/ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ruleset.c,v 1.20 2011/10/23 09:30:07 gilles Exp $ */
+/* $OpenBSD: ruleset.c,v 1.21 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -71,32 +71,50 @@ ruleset_match(struct envelope *evp)
if (map == NULL)
fatal("failed to lookup map.");
- switch (map->m_src) {
- case S_NONE:
+ if (map->m_src == S_NONE) {
TAILQ_FOREACH(me, &map->m_contents, me_entry) {
- if (hostname_match(maddr->domain, me->me_key.med_string))
+ if (hostname_match(maddr->domain,
+ me->me_key.med_string))
return r;
}
- break;
- case S_DB:
- if (map_lookup(map->m_id, maddr->domain, K_VIRTUAL) != NULL)
- return r;
- break;
- default:
- log_info("unsupported map source for domain map");
- continue;
+ }
+ else if (map_lookup(map->m_id, maddr->domain,
+ K_VIRTUAL) != NULL) {
+ return r;
}
}
- if (r->r_condition.c_type == C_VDOM)
- if (aliases_vdomain_exists(r->r_condition.c_map, maddr->domain))
+ if (r->r_condition.c_type == C_VDOM) {
+ if (aliases_vdomain_exists(r->r_condition.c_map,
+ maddr->domain))
return r;
+ }
}
return NULL;
}
static int
+ruleset_cmp_source(char *s1, char *s2)
+{
+ struct netaddr n1;
+ struct netaddr n2;
+
+ if (! text_to_netaddr(&n1, s1))
+ return 0;
+
+ if (! text_to_netaddr(&n2, s2))
+ return 0;
+
+ if (n1.ss.ss_family != n2.ss.ss_family)
+ return 0;
+ if (n1.ss.ss_len != n2.ss.ss_len)
+ return 0;
+
+ return ruleset_match_mask(&n1.ss, &n2);
+}
+
+static int
ruleset_check_source(struct map *map, struct sockaddr_storage *ss)
{
struct mapel *me;
@@ -108,15 +126,16 @@ ruleset_check_source(struct map *map, struct sockaddr_storage *ss)
return 1;
}
- TAILQ_FOREACH(me, &map->m_contents, me_entry) {
-
- if (ss->ss_family != me->me_key.med_addr.ss.ss_family)
- continue;
-
- if (ss->ss_len != me->me_key.med_addr.ss.ss_len)
- continue;
-
- if (ruleset_match_mask(ss, &me->me_key.med_addr))
+ if (map->m_src == S_NONE) {
+ TAILQ_FOREACH(me, &map->m_contents, me_entry) {
+ if (ruleset_cmp_source(ss_to_text(ss),
+ me->me_key.med_string))
+ return 1;
+ }
+ }
+ else {
+ if (map_compare(map->m_id, ss_to_text(ss), K_NETADDR,
+ ruleset_cmp_source))
return 1;
}
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 98483b7256a..d01914be273 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.292 2012/05/12 21:49:31 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.293 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -241,7 +241,8 @@ enum map_kind {
K_NONE,
K_ALIAS,
K_VIRTUAL,
- K_CREDENTIALS
+ K_CREDENTIALS,
+ K_NETADDR
};
enum mapel_type {
@@ -254,7 +255,6 @@ struct mapel {
TAILQ_ENTRY(mapel) me_entry;
union mapel_data {
char med_string[MAX_LINE_SIZE];
- struct netaddr med_addr;
} me_key;
union mapel_data me_val;
};
@@ -274,6 +274,7 @@ struct map_backend {
void *(*open)(char *);
void (*close)(void *);
void *(*lookup)(void *, char *, enum map_kind);
+ int (*compare)(void *, char *, enum map_kind, int (*)(char *, char *));
};
@@ -882,6 +883,9 @@ struct map_virtual {
struct expandtree expandtree;
};
+struct map_netaddr {
+ struct netaddr netaddr;
+};
/* queue structures */
enum queue_type {
@@ -1079,6 +1083,7 @@ void lka_session_destroy(struct lka_session *);
/* map.c */
void *map_lookup(objid_t, char *, enum map_kind);
+int map_compare(objid_t, char *, enum map_kind, int (*)(char *, char *));
struct map *map_find(objid_t);
struct map *map_findbyname(const char *);
@@ -1225,3 +1230,4 @@ int ckdir(const char *, mode_t, uid_t, gid_t, int);
int rmtree(char *, int);
int mvpurge(char *, char *);
const char *parse_smtp_response(char *, size_t, char **, int *);
+int text_to_netaddr(struct netaddr *, char *);
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c
index 93f74f3fbf8..69a27cec97d 100644
--- a/usr.sbin/smtpd/util.c
+++ b/usr.sbin/smtpd/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.57 2012/01/28 16:54:10 gilles Exp $ */
+/* $OpenBSD: util.c,v 1.58 2012/05/13 00:10:49 gilles Exp $ */
/*
* Copyright (c) 2000,2001 Markus Friedl. All rights reserved.
@@ -27,6 +27,7 @@
#include <sys/resource.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
@@ -392,6 +393,64 @@ time_to_text(time_t when)
return buf;
}
+int
+text_to_netaddr(struct netaddr *netaddr, char *s)
+{
+ struct sockaddr_storage ss;
+ struct sockaddr_in ssin;
+ struct sockaddr_in6 ssin6;
+ int bits;
+
+ if (strncmp("IPv6:", s, 5) == 0)
+ s += 5;
+
+ if (strchr(s, '/') != NULL) {
+ /* dealing with netmask */
+
+ bzero(&ssin, sizeof(struct sockaddr_in));
+ bits = inet_net_pton(AF_INET, s, &ssin.sin_addr,
+ sizeof(struct in_addr));
+
+ if (bits != -1) {
+ ssin.sin_family = AF_INET;
+ memcpy(&ss, &ssin, sizeof(ssin));
+ ss.ss_len = sizeof(struct sockaddr_in);
+ }
+ else {
+ bzero(&ssin6, sizeof(struct sockaddr_in6));
+ bits = inet_net_pton(AF_INET6, s, &ssin6.sin6_addr,
+ sizeof(struct in6_addr));
+ if (bits == -1) {
+ log_warn("inet_net_pton");
+ return 0;
+ }
+ ssin6.sin6_family = AF_INET6;
+ memcpy(&ss, &ssin6, sizeof(ssin6));
+ ss.ss_len = sizeof(struct sockaddr_in6);
+ }
+ }
+ else {
+ /* IP address ? */
+ if (inet_pton(AF_INET, s, &ssin.sin_addr) == 1) {
+ ssin.sin_family = AF_INET;
+ bits = 32;
+ memcpy(&ss, &ssin, sizeof(ssin));
+ ss.ss_len = sizeof(struct sockaddr_in);
+ }
+ else if (inet_pton(AF_INET6, s, &ssin6.sin6_addr) == 1) {
+ ssin6.sin6_family = AF_INET6;
+ bits = 128;
+ memcpy(&ss, &ssin6, sizeof(ssin6));
+ ss.ss_len = sizeof(struct sockaddr_in6);
+ }
+ else return 0;
+ }
+
+ netaddr->ss = ss;
+ netaddr->bits = bits;
+ return 1;
+}
+
/*
* Check file for security. Based on usr.bin/ssh/auth.c.
*/