diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2012-05-13 00:10:50 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2012-05-13 00:10:50 +0000 |
commit | d4519c494c7974b50ea27f225264140734385a4b (patch) | |
tree | 1eb6171f3d6576734c9b808deb6534dd93cf65ac /usr.sbin | |
parent | be2353b2a7b188c78bbf94f4c28cef23d8951bd7 (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.c | 28 | ||||
-rw-r--r-- | usr.sbin/smtpd/map_db.c | 58 | ||||
-rw-r--r-- | usr.sbin/smtpd/map_stdio.c | 82 | ||||
-rw-r--r-- | usr.sbin/smtpd/parse.y | 155 | ||||
-rw-r--r-- | usr.sbin/smtpd/ruleset.c | 65 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/util.c | 61 |
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. */ |