diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-03-18 17:10:00 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-03-18 17:10:00 +0000 |
commit | bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0 (patch) | |
tree | 6f8a7e9d7ab96d32d9c727744c826a4910f09446 /src/libserver/spf.c | |
parent | ed1d6587a088d4a64c4ca47604da5b79280ef85a (diff) | |
download | rspamd-bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0.tar.gz rspamd-bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0.zip |
Rework plain ip6/ip4 parsing.
Diffstat (limited to 'src/libserver/spf.c')
-rw-r--r-- | src/libserver/spf.c | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/src/libserver/spf.c b/src/libserver/spf.c index 69693db6f..51c4a67ac 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -941,18 +941,92 @@ static gboolean parse_spf_ip4 (struct spf_record *rec, struct spf_addr *addr) { /* ip4:addr[/mask] */ + const gchar *semicolon, *slash; + gsize len; + gchar ipbuf[INET_ADDRSTRLEN + 1]; + guint32 mask; CHECK_REC (rec); - return parse_spf_ipmask (addr->spf_string, addr, rec); + + semicolon = strchr (addr->spf_string, ':'); + + if (semicolon == NULL) { + return FALSE; + } + + semicolon ++; + slash = strchr (semicolon, '/'); + + if (slash) { + len = slash - semicolon; + } + else { + len = strlen (semicolon); + } + + rspamd_strlcpy (ipbuf, semicolon, MIN (len, sizeof (ipbuf))); + + if (inet_pton (AF_INET, ipbuf, addr->addr4) != 1) { + return FALSE; + } + + if (slash) { + mask = strtoul (slash + 1, NULL, 10); + if (mask > 32) { + return FALSE; + } + addr->m.dual.mask_v4 = mask; + } + + addr->flags |= RSPAMD_SPF_FLAG_IPV4; + + return TRUE; } static gboolean parse_spf_ip6 (struct spf_record *rec, struct spf_addr *addr) { /* ip6:addr[/mask] */ + const gchar *semicolon, *slash; + gsize len; + gchar ipbuf[INET6_ADDRSTRLEN + 1]; + guint32 mask; CHECK_REC (rec); - return parse_spf_ipmask (addr->spf_string, addr, rec); + + semicolon = strchr (addr->spf_string, ':'); + + if (semicolon == NULL) { + return FALSE; + } + + semicolon ++; + slash = strchr (semicolon, '/'); + + if (slash) { + len = slash - semicolon; + } + else { + len = strlen (semicolon); + } + + rspamd_strlcpy (ipbuf, semicolon, MIN (len, sizeof (ipbuf))); + + if (inet_pton (AF_INET6, ipbuf, addr->addr4) != 1) { + return FALSE; + } + + if (slash) { + mask = strtoul (slash + 1, NULL, 10); + if (mask > 128) { + return FALSE; + } + addr->m.dual.mask_v6 = mask; + } + + addr->flags |= RSPAMD_SPF_FLAG_IPV6; + + return TRUE; } |