]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Allow to hash and compare inet addresses considering port
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 4 Mar 2019 14:15:24 +0000 (14:15 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 4 Mar 2019 14:15:24 +0000 (14:15 +0000)
src/libmime/message.c
src/libutil/addr.c
src/libutil/addr.h
src/libutil/upstream.c
src/lua/lua_ip.c

index da065195d4126929cdf69a93d200da87347f3458..cca134f81fe4126c5424d751141464c7cbdfb2e0 100644 (file)
@@ -1150,7 +1150,7 @@ rspamd_message_parse (struct rspamd_task *task)
                                need_recv_correction = TRUE;
                        }
                        else {
-                               if (rspamd_inet_address_compare (raddr, task->from_addr) != 0) {
+                               if (rspamd_inet_address_compare (raddr, task->from_addr, FALSE) != 0) {
                                        need_recv_correction = TRUE;
                                }
                        }
index fd4621aef2afc6bad209b969f6b75cc3ccd1f0ff..7fa634f6f3d6ffc0b9a2d871af2235b1236ea631 100644 (file)
@@ -1636,7 +1636,7 @@ rspamd_inet_address_af_order (const rspamd_inet_addr_t *addr)
 
 gint
 rspamd_inet_address_compare (const rspamd_inet_addr_t *a1,
-               const rspamd_inet_addr_t *a2)
+               const rspamd_inet_addr_t *a2, gboolean compare_ports)
 {
        g_assert (a1 != NULL);
        g_assert (a2 != NULL);
@@ -1648,11 +1648,33 @@ rspamd_inet_address_compare (const rspamd_inet_addr_t *a1,
        else {
                switch (a1->af) {
                case AF_INET:
-                       return memcmp (&a1->u.in.addr.s4.sin_addr,
-                                       &a2->u.in.addr.s4.sin_addr, sizeof (struct in_addr));
+                       if (!compare_ports) {
+                               return memcmp (&a1->u.in.addr.s4.sin_addr,
+                                               &a2->u.in.addr.s4.sin_addr, sizeof (struct in_addr));
+                       }
+                       else {
+                               if (a1->u.in.addr.s4.sin_port == a2->u.in.addr.s4.sin_port) {
+                                       return memcmp (&a1->u.in.addr.s4.sin_addr,
+                                                       &a2->u.in.addr.s4.sin_addr, sizeof (struct in_addr));
+                               }
+                               else {
+                                       return a1->u.in.addr.s4.sin_port - a2->u.in.addr.s4.sin_port;
+                               }
+                       }
                case AF_INET6:
-                       return memcmp (&a1->u.in.addr.s6.sin6_addr,
-                               &a2->u.in.addr.s6.sin6_addr, sizeof (struct in6_addr));
+                       if (!compare_ports) {
+                               return memcmp (&a1->u.in.addr.s6.sin6_addr,
+                                               &a2->u.in.addr.s6.sin6_addr, sizeof (struct in6_addr));
+                       }
+                       else {
+                               if (a1->u.in.addr.s6.sin6_port == a2->u.in.addr.s6.sin6_port) {
+                                       return memcmp (&a1->u.in.addr.s6.sin6_addr,
+                                                       &a2->u.in.addr.s6.sin6_addr, sizeof (struct in6_addr));
+                               }
+                               else {
+                                       return a1->u.in.addr.s6.sin6_port - a2->u.in.addr.s6.sin6_port;
+                               }
+                       }
                case AF_UNIX:
                        return strncmp (a1->u.un->addr.sun_path,
                                a2->u.un->addr.sun_path, sizeof (a1->u.un->addr.sun_path));
@@ -1671,7 +1693,7 @@ rspamd_inet_address_compare_ptr (gconstpointer a1,
        const rspamd_inet_addr_t **i1 = (const rspamd_inet_addr_t **)a1,
                        **i2 = (const rspamd_inet_addr_t **)a2;
 
-       return rspamd_inet_address_compare (*i1, *i2);
+       return rspamd_inet_address_compare (*i1, *i2, FALSE);
 }
 
 rspamd_inet_addr_t *
@@ -1724,28 +1746,85 @@ guint
 rspamd_inet_address_hash (gconstpointer a)
 {
        const rspamd_inet_addr_t *addr = a;
-       rspamd_cryptobox_fast_hash_state_t st;
-
-       rspamd_cryptobox_fast_hash_init (&st, rspamd_hash_seed ());
-       rspamd_cryptobox_fast_hash_update (&st, &addr->af, sizeof (addr->af));
+       struct {
+               gchar buf[sizeof(struct in6_addr)]; /* 16 bytes */
+               int af;
+       } layout;
 
+       gint32 k;
 
        if (addr->af == AF_UNIX && addr->u.un) {
+               rspamd_cryptobox_fast_hash_state_t st;
+
+               rspamd_cryptobox_fast_hash_init (&st, rspamd_hash_seed ());
+               rspamd_cryptobox_fast_hash_update (&st, &addr->af, sizeof (addr->af));
                rspamd_cryptobox_fast_hash_update (&st, addr->u.un, sizeof (*addr->u.un));
+
+               return rspamd_cryptobox_fast_hash_final (&st);
        }
        else {
+               memset (&layout, 0, sizeof (layout));
+               layout.af = addr->af;
+
                /* We ignore port part here */
                if (addr->af == AF_INET) {
-                       rspamd_cryptobox_fast_hash_update (&st, &addr->u.in.addr.s4.sin_addr,
+                       memcpy (layout.buf, &addr->u.in.addr.s4.sin_addr,
+                                       sizeof (addr->u.in.addr.s4.sin_addr));
+               }
+               else {
+                       memcpy (layout.buf, &addr->u.in.addr.s6.sin6_addr,
+                                       sizeof (addr->u.in.addr.s6.sin6_addr));
+               }
+
+               k = rspamd_cryptobox_fast_hash (&layout, sizeof (layout),
+                               rspamd_hash_seed ());
+       }
+
+       return k;
+}
+
+guint
+rspamd_inet_address_port_hash (gconstpointer a)
+{
+       const rspamd_inet_addr_t *addr = a;
+       struct {
+               gchar buf[sizeof(struct in6_addr)]; /* 16 bytes */
+               int port;
+               int af;
+       } layout;
+
+       gint32 k;
+
+       if (addr->af == AF_UNIX && addr->u.un) {
+               rspamd_cryptobox_fast_hash_state_t st;
+
+               rspamd_cryptobox_fast_hash_init (&st, rspamd_hash_seed ());
+               rspamd_cryptobox_fast_hash_update (&st, &addr->af, sizeof (addr->af));
+               rspamd_cryptobox_fast_hash_update (&st, addr->u.un, sizeof (*addr->u.un));
+
+               return rspamd_cryptobox_fast_hash_final (&st);
+       }
+       else {
+               memset (&layout, 0, sizeof (layout));
+               layout.af = addr->af;
+
+               /* We consider port part here */
+               if (addr->af == AF_INET) {
+                       memcpy (layout.buf, &addr->u.in.addr.s4.sin_addr,
                                        sizeof (addr->u.in.addr.s4.sin_addr));
+                       layout.port = addr->u.in.addr.s4.sin_port;
                }
                else {
-                       rspamd_cryptobox_fast_hash_update (&st, &addr->u.in.addr.s6.sin6_addr,
+                       memcpy (layout.buf, &addr->u.in.addr.s6.sin6_addr,
                                        sizeof (addr->u.in.addr.s6.sin6_addr));
+                       layout.port = addr->u.in.addr.s6.sin6_port;
                }
+
+               k = rspamd_cryptobox_fast_hash (&layout, sizeof (layout),
+                               rspamd_hash_seed ());
        }
 
-       return rspamd_cryptobox_fast_hash_final (&st);
+       return k;
 }
 
 gboolean
@@ -1753,7 +1832,15 @@ rspamd_inet_address_equal (gconstpointer a, gconstpointer b)
 {
        const rspamd_inet_addr_t *a1 = a, *a2 = b;
 
-       return rspamd_inet_address_compare (a1, a2) == 0;
+       return rspamd_inet_address_compare (a1, a2, FALSE) == 0;
+}
+
+gboolean
+rspamd_inet_address_port_equal (gconstpointer a, gconstpointer b)
+{
+       const rspamd_inet_addr_t *a1 = a, *a2 = b;
+
+       return rspamd_inet_address_compare (a1, a2, TRUE) == 0;
 }
 
 #ifndef IN6_IS_ADDR_LOOPBACK
index 46b705a4bf41fb58876835338b97f084df7704f3..bfe586ad1e7cdd5904eefdbe23cca018fb9b2159 100644 (file)
@@ -263,7 +263,7 @@ void rspamd_inet_address_apply_mask (rspamd_inet_addr_t *addr, guint mask);
  * @return
  */
 gint rspamd_inet_address_compare (const rspamd_inet_addr_t *a1,
-               const rspamd_inet_addr_t *a2);
+               const rspamd_inet_addr_t *a2, gboolean compare_ports);
 
 /**
  * Utility function to compare addresses by in g_ptr_array
@@ -281,15 +281,16 @@ gint rspamd_inet_address_compare_ptr (gconstpointer a1,
 rspamd_inet_addr_t *rspamd_inet_address_copy (const rspamd_inet_addr_t *addr);
 
 /**
- * Returns hash for inet address
+ * Returns hash for inet address (ignoring port)
  */
 guint rspamd_inet_address_hash (gconstpointer a);
-
+guint rspamd_inet_address_port_hash (gconstpointer a);
 
 /**
  * Returns true if two address are equal
  */
 gboolean rspamd_inet_address_equal (gconstpointer a, gconstpointer b);
+gboolean rspamd_inet_address_port_equal (gconstpointer a, gconstpointer b);
 
 /**
  * Returns TRUE if an address belongs to some local address
index 2ce2945253df4445caf6f504b146c5aef463d73f..64d5291fa85ec1a08ca77462168b31675305a07e 100644 (file)
@@ -289,7 +289,7 @@ rspamd_upstream_update_addrs (struct upstream *up)
                        rspamd_inet_address_set_port (cur->addr, port);
 
                        PTR_ARRAY_FOREACH (up->addrs.addr, i, addr_elt) {
-                               if (rspamd_inet_address_compare (addr_elt->addr, cur->addr) == 0) {
+                               if (rspamd_inet_address_compare (addr_elt->addr, cur->addr, FALSE) == 0) {
                                        naddr = g_malloc0 (sizeof (*naddr));
                                        naddr->addr = cur->addr;
                                        naddr->errors = reset_errors ? 0 : addr_elt->errors;
index 5ee4a39b4e27b6ac1803283305491edcd9c63062..7f24f77123dadbbc113dd4fa824954277b58ba2e 100644 (file)
@@ -490,7 +490,7 @@ lua_ip_equal (lua_State *L)
        gboolean res = FALSE;
 
        if (ip1 && ip2 && ip1->addr && ip2->addr) {
-               res = rspamd_inet_address_compare (ip1->addr, ip2->addr);
+               res = rspamd_inet_address_compare (ip1->addr, ip2->addr, TRUE);
        }
 
        lua_pushboolean (L, res);