summaryrefslogtreecommitdiffstats
path: root/lib/socket_wrapper
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2014-06-03 15:10:19 +0200
committerMichael Adam <obnox@samba.org>2014-06-05 23:57:10 +0200
commit6e6c817fd01112fdb137df666b3046757d0276d3 (patch)
tree6f7c6a652037856d13d628daff2fcebe66b8760c /lib/socket_wrapper
parent1b949b5d6ce6ca24f61c8b327f3234c0a864740c (diff)
downloadsamba-6e6c817fd01112fdb137df666b3046757d0276d3.tar.gz
samba-6e6c817fd01112fdb137df666b3046757d0276d3.tar.xz
samba-6e6c817fd01112fdb137df666b3046757d0276d3.zip
swrap: Add support for bindresvport().
Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'lib/socket_wrapper')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c87
-rw-r--r--lib/socket_wrapper/wscript1
2 files changed, 88 insertions, 0 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index 5bedfa79c2f..bf84dbe5169 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -111,6 +111,13 @@ enum swrap_dbglvl_e {
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
#endif
+#ifndef ZERO_STRUCTP
+#define ZERO_STRUCTP(x) do { \
+ if ((x) != NULL) \
+ memset((char *)(x), 0, sizeof(*(x))); \
+ } while(0)
+#endif
+
#ifndef discard_const
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
#endif
@@ -2753,6 +2760,86 @@ int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
}
/****************************************************************************
+ * BINDRESVPORT
+ ***************************************************************************/
+
+#ifdef HAVE_BINDRESVPORT
+static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
+
+static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
+{
+ struct sockaddr_storage myaddr;
+ socklen_t salen;
+ static uint16_t port;
+ uint16_t i;
+ int rc = -1;
+ int af;
+
+#define SWRAP_STARTPORT 600
+#define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
+#define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
+
+ if (port == 0) {
+ port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
+ }
+
+ if (sa == NULL) {
+ salen = sizeof(struct sockaddr);
+ sa = (struct sockaddr *)&myaddr;
+
+ rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
+ if (rc < 0) {
+ return -1;
+ }
+
+ af = sa->sa_family;
+ memset(&myaddr, 0, salen);
+ } else {
+ af = sa->sa_family;
+ }
+
+ for (i = 0; i < SWRAP_NPORTS; i++, port++) {
+ switch(af) {
+ case AF_INET: {
+ struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
+
+ salen = sizeof(struct sockaddr_in);
+ sinp->sin_port = htons(port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
+
+ salen = sizeof(struct sockaddr_in6);
+ sin6p->sin6_port = htons(port);
+ break;
+ }
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ sa->sa_family = af;
+
+ if (port > SWRAP_ENDPORT) {
+ port = SWRAP_STARTPORT;
+ }
+
+ rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
+ if (rc == 0 || errno != EADDRINUSE) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int bindresvport(int sockfd, struct sockaddr_in *sinp)
+{
+ return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
+}
+#endif
+
+/****************************************************************************
* LISTEN
***************************************************************************/
diff --git a/lib/socket_wrapper/wscript b/lib/socket_wrapper/wscript
index 60b4ca89d1c..517082a569e 100644
--- a/lib/socket_wrapper/wscript
+++ b/lib/socket_wrapper/wscript
@@ -60,6 +60,7 @@ def configure(conf):
conf.CHECK_FUNCS('getaddrinfo')
conf.CHECK_FUNCS('signalfd eventfd timerfd_create')
+ conf.CHECK_FUNCS('bindresvport')
conf.CHECK_FUNCS_IN('bind',
'socket',