summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2014-05-30 14:20:17 +0200
committerMichael Adam <obnox@samba.org>2014-06-01 10:03:21 +0200
commitda04f94dd0575245424cf7853d0a9fc5b7caacee (patch)
tree378ef0039315743ff328fd1c24044c5b20d32eac
parentf04ea324f6079e74532ee1ae085945097073a305 (diff)
downloadsocket_wrapper-da04f94dd0575245424cf7853d0a9fc5b7caacee.tar.gz
socket_wrapper-da04f94dd0575245424cf7853d0a9fc5b7caacee.tar.xz
socket_wrapper-da04f94dd0575245424cf7853d0a9fc5b7caacee.zip
swrap: implement check_addr_port_in_use()
Signed-off-by: Michael Adam <obnox@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
-rw-r--r--src/socket_wrapper.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index b66b951..477f115 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -1267,6 +1267,89 @@ static struct socket_info *find_socket_info(int fd)
return NULL;
}
+static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
+{
+ struct socket_info *s;
+
+ /* first catch invalid input */
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (len < sizeof(struct sockaddr_in)) {
+ return false;
+ }
+ break;
+#if HAVE_IPV6
+ case AF_INET6:
+ if (len < sizeof(struct sockaddr_in6)) {
+ return false;
+ }
+ break;
+#endif
+ default:
+ return false;
+ break;
+ }
+
+ for (s = sockets; s != NULL; s = s->next) {
+ if (s->myname == NULL) {
+ continue;
+ }
+ if (s->myname->sa_family != sa->sa_family) {
+ continue;
+ }
+ switch (s->myname->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in *)s->myname;
+ sin2 = (struct sockaddr_in *)sa;
+
+ if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ continue;
+ }
+ if (sin1->sin_port != sin2->sin_port) {
+ continue;
+ }
+ if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#if HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in6 *)s->myname;
+ sin2 = (struct sockaddr_in6 *)sa;
+
+ if (sin1->sin6_port != sin2->sin6_port) {
+ continue;
+ }
+ if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
+ &sin2->sin6_addr))
+ {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#endif
+ default:
+ continue;
+ break;
+
+ }
+ }
+
+ return false;
+}
+
+
static void swrap_remove_stale(int fd)
{
struct socket_info *si = find_socket_info(fd);