From bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 18 Mar 2015 17:10:00 +0000 Subject: Rework plain ip6/ip4 parsing. --- src/libserver/spf.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/libserver/spf.h | 9 ++++--- 2 files changed, 81 insertions(+), 6 deletions(-) (limited to 'src') 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; } diff --git a/src/libserver/spf.h b/src/libserver/spf.h index 93098e941..395e4ef02 100644 --- a/src/libserver/spf.h +++ b/src/libserver/spf.h @@ -28,10 +28,11 @@ typedef enum spf_action_e { } spf_action_t; #define RSPAMD_SPF_FLAG_IPV6 (1 << 0) -#define RSPAMD_SPF_FLAG_ANY (1 << 1) -#define RSPAMD_SPF_FLAG_PARSED (1 << 2) -#define RSPAMD_SPF_FLAG_VALID (1 << 3) -#define RSPAMD_SPF_FLAG_REFRENCE (1 << 4) +#define RSPAMD_SPF_FLAG_IPV4 (1 << 1) +#define RSPAMD_SPF_FLAG_ANY (1 << 2) +#define RSPAMD_SPF_FLAG_PARSED (1 << 3) +#define RSPAMD_SPF_FLAG_VALID (1 << 4) +#define RSPAMD_SPF_FLAG_REFRENCE (1 << 5) struct spf_addr { guchar addr6[sizeof (struct in6_addr)]; -- cgit v1.2.3