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 | |
parent | ed1d6587a088d4a64c4ca47604da5b79280ef85a (diff) | |
download | rspamd-bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0.tar.gz rspamd-bb00b2d8d4d116c600d6a4a05b5da14dbbe080a0.zip |
Rework plain ip6/ip4 parsing.
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/spf.c | 78 | ||||
-rw-r--r-- | src/libserver/spf.h | 9 |
2 files changed, 81 insertions, 6 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; } 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)]; |