From 621aafd27a3aafaab6c061f0522a27d62390b3bc Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 30 Jul 2009 22:11:23 +0000 Subject: [PATCH] Export sockaddr comparison functionality. svn:r1400 --- ChangeLog | 2 ++ evdns.c | 37 ++----------------------------------- evutil.c | 39 +++++++++++++++++++++++++++++++++++++++ include/event2/util.h | 8 ++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index c788d4f7..14eb423b 100644 --- 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 c997d56e..9c16c1fd 100644 --- a/evdns.c +++ b/evdns.c @@ -448,39 +448,6 @@ debug_ntop(const struct sockaddr *sa) return ""; } -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); } diff --git a/evutil.c b/evutil.c index 8f338f99..9273e966 100644 --- 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 diff --git a/include/event2/util.h b/include/event2/util.h index 4042f47a..126a3037 100644 --- a/include/event2/util.h +++ b/include/event2/util.h @@ -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. */ -- 2.50.1