]> granicus.if.org Git - libevent/commitdiff
Export sockaddr comparison functionality.
authorNick Mathewson <nickm@torproject.org>
Thu, 30 Jul 2009 22:11:23 +0000 (22:11 +0000)
committerNick Mathewson <nickm@torproject.org>
Thu, 30 Jul 2009 22:11:23 +0000 (22:11 +0000)
svn:r1400

ChangeLog
evdns.c
evutil.c
include/event2/util.h

index c788d4f70777ed1e9862caff0b6f685a81229aa2..14eb423bac50ede422596ed96dee61e07271a2b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,7 +8,9 @@ Changes in 2.0.3-alpha:
  o Expose an ev_socklen_t type for consistent use across platforms.
  o Make bufferevenr_socket_connect() work when the original fd was -1.
  o Fix a bug in bufferevent_socket_connect() when the connection succeeds too quickly.
+ o Export an evutil_sockaddr_cmp() to compare to sockaddr objects for equality.
 
+       
 Changes in 2.0.2-alpha:
  o Add a new flag to bufferevents to make all callbacks automatically deferred.
  o Make evdns functionality locked, and automatically defer dns callbacks.
diff --git a/evdns.c b/evdns.c
index c997d56e07cfce559e7d35cc67b522528a496bb3..9c16c1fde69fc5f48953799a5c3751a80589ae01 100644 (file)
--- a/evdns.c
+++ b/evdns.c
@@ -448,39 +448,6 @@ debug_ntop(const struct sockaddr *sa)
        return "<unknown>";
 }
 
-static int
-sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2,
-                       int include_port)
-{
-       if (sa1->sa_family != sa2->sa_family)
-               return 0;
-       if (sa1->sa_family == AF_INET) {
-               const struct sockaddr_in *sin1, *sin2;
-               sin1 = (const struct sockaddr_in *)sa1;
-               sin2 = (const struct sockaddr_in *)sa2;
-               if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
-                       return 0;
-               else if (include_port && sin1->sin_port != sin2->sin_port)
-                       return 0;
-               else
-                       return 1;
-       }
-#ifdef AF_INET6
-       if (sa1->sa_family == AF_INET6) {
-               const struct sockaddr_in6 *sin1, *sin2;
-               sin1 = (const struct sockaddr_in6 *)sa1;
-               sin2 = (const struct sockaddr_in6 *)sa2;
-               if (memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))
-                       return 0;
-               else if (include_port && sin1->sin6_port != sin2->sin6_port)
-                       return 0;
-               else
-                       return 1;
-       }
-#endif
-       return 1;
-}
-
 static evdns_debug_log_fn_type evdns_log_fn = NULL;
 
 void
@@ -1349,7 +1316,7 @@ nameserver_read(struct nameserver *ns) {
                            evutil_socket_error_to_string(err));
                        return;
                }
-               if (!sockaddr_eq((struct sockaddr*)&ss,
+               if (evutil_sockaddr_cmp((struct sockaddr*)&ss,
                        (struct sockaddr*)&ns->address, 0)) {
                        log(EVDNS_LOG_WARN, "Address mismatch on received "
                            "DNS packet.  Apparent source was %s",
@@ -2398,7 +2365,7 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre
        ASSERT_LOCKED(base);
        if (server) {
                do {
-                       if (sockaddr_eq((struct sockaddr*)&server->address, address, 1)) return 3;
+                       if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3;
                        server = server->next;
                } while (server != started_at);
        }
index 8f338f993c0e342e74271c6f110158cf2efc6a73..9273e966179d216052f9f5a01f7313b32d8e0354 100644 (file)
--- a/evutil.c
+++ b/evutil.c
@@ -716,6 +716,45 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *
        }
 }
 
+int
+evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
+    int include_port)
+{
+       int r;
+       if (0 != (r = (sa1->sa_family - sa2->sa_family)))
+               return r;
+
+       if (sa1->sa_family == AF_INET) {
+               const struct sockaddr_in *sin1, *sin2;
+               sin1 = (const struct sockaddr_in *)sa1;
+               sin2 = (const struct sockaddr_in *)sa2;
+               if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr)
+                       return -1;
+               else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr)
+                       return 1;
+               else if (include_port &&
+                   (r = ((int)sin1->sin_port - (int)sin2->sin_port)))
+                       return r;
+               else
+                       return 0;
+       }
+#ifdef AF_INET6
+       else if (sa1->sa_family == AF_INET6) {
+               const struct sockaddr_in6 *sin1, *sin2;
+               sin1 = (const struct sockaddr_in6 *)sa1;
+               sin2 = (const struct sockaddr_in6 *)sa2;
+               if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)))
+                       return r;
+               else if (include_port &&
+                   (r = ((int)sin1->sin6_port - (int)sin2->sin6_port)))
+                       return r;
+               else
+                       return 0;
+       }
+#endif
+       return 1;
+}
+
 /* Tables to implement ctypes-replacement EVUTIL_IS*() functions.  Each table
  * has 256 bits to look up whether a character is in some set or not.  This
  * fails on non-ASCII platforms, but so does every other place where we
index 4042f47a1d29156b357d9b680b37029ab0f10a20..126a303739f827521759dcca133cdb8b08d7aef5 100644 (file)
@@ -303,6 +303,14 @@ struct sockaddr;
 */
 int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen);
 
+/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1
+ * preceeds sa2, or greater than 0 if sa1 follows sa2.  If include_port is
+ * true, consider the port as well as the address.  Only implemented for
+ * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain
+ * the same between Libevent versions. */
+int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
+    int include_port);
+
 /** As strcasecmp, but always compares the characters in locale-independent
     ASCII.  That's useful if you're handling data in ASCII-based protocols.
  */