aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/addr.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-05-17 18:57:06 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-05-17 18:57:36 +0100
commit748f6c6966500ca653418a4600868767f91ba70e (patch)
tree11c4aee2ac2a24161d3c33d013c725d9d48f1829 /src/libutil/addr.c
parent76159df4b2ee19ea36d5809e8a1a68e58fa12d5f (diff)
downloadrspamd-748f6c6966500ca653418a4600868767f91ba70e.tar.gz
rspamd-748f6c6966500ca653418a4600868767f91ba70e.zip
[Fix] Try to deal with v4 mapped to v6 addresses on accept
Diffstat (limited to 'src/libutil/addr.c')
-rw-r--r--src/libutil/addr.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/src/libutil/addr.c b/src/libutil/addr.c
index 5a1e9cf6e..1687c80bd 100644
--- a/src/libutil/addr.c
+++ b/src/libutil/addr.c
@@ -257,25 +257,52 @@ rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t **target,
return -1;
}
- addr = rspamd_inet_addr_create (su.sa.sa_family);
- addr->slen = len;
+ if (su.sa.sa_family == AF_INET6) {
+ /* Deal with bloody v4 mapped to v6 addresses */
- if (addr->af == AF_UNIX) {
- addr->u.un = g_slice_alloc0 (sizeof (*addr->u.un));
- /* Get name from the listening socket */
- len = sizeof (su);
+ static const guint8 mask[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ const guint8 *p;
- if (getsockname (sock, &su.sa, &len) != -1) {
- memcpy (&addr->u.un->addr, &su.su, MIN (len,
- sizeof (struct sockaddr_un)));
- }
- else {
- /* Just copy socket address */
- memcpy (&addr->u.un->addr, &su.sa, sizeof (struct sockaddr));
+ if (memcmp ((const guint8 *)&su.s6.sin6_addr, mask, sizeof (mask)) == 0) {
+ p = (const guint8 *)&su.s6.sin6_addr;
+
+ if ((p[10] == 0xff && p[11] == 0xff)) {
+ addr = rspamd_inet_addr_create (AF_INET);
+ memcpy (&addr->u.in.addr.s4.sin_addr, &p[12],
+ sizeof (struct in_addr));
+ }
+ else {
+ /* Something strange but not mapped v4 address */
+ addr = rspamd_inet_addr_create (AF_INET6);
+ memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
+ sizeof (struct in6_addr));
+ }
}
+
}
else {
- memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
+ addr = rspamd_inet_addr_create (su.sa.sa_family);
+ addr->slen = len;
+
+ if (addr->af == AF_UNIX) {
+ addr->u.un = g_slice_alloc0 (sizeof (*addr->u.un));
+ /* Get name from the listening socket */
+ len = sizeof (su);
+
+ if (getsockname (sock, &su.sa, &len) != -1) {
+ memcpy (&addr->u.un->addr, &su.su, MIN (len,
+ sizeof (struct sockaddr_un)));
+ }
+ else {
+ /* Just copy socket address */
+ memcpy (&addr->u.un->addr, &su.sa, sizeof (struct sockaddr));
+ }
+ }
+ else {
+ memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
+ }
}
if (rspamd_socket_nonblocking (nfd) < 0) {