summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2014-06-03 15:13:59 +0200
committerMichael Adam <obnox@samba.org>2014-06-05 23:57:10 +0200
commit05c1e2db225be256da604d241da08ee0dc5ce0be (patch)
treea410807aa4f20f66697db7cd35d826d2bdf100b2
parentf9ddd20c2d51475f82e563f26232b9944ebba799 (diff)
downloadsamba-05c1e2db225be256da604d241da08ee0dc5ce0be.tar.gz
samba-05c1e2db225be256da604d241da08ee0dc5ce0be.tar.xz
samba-05c1e2db225be256da604d241da08ee0dc5ce0be.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--lib/socket_wrapper/socket_wrapper.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index b66b9510f47..477f1159715 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/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);