diff options
author | Andreas Schneider <asn@samba.org> | 2014-06-03 15:10:19 +0200 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2014-06-05 23:57:10 +0200 |
commit | 6e6c817fd01112fdb137df666b3046757d0276d3 (patch) | |
tree | 6f7c6a652037856d13d628daff2fcebe66b8760c /lib/socket_wrapper | |
parent | 1b949b5d6ce6ca24f61c8b327f3234c0a864740c (diff) | |
download | samba-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.c | 87 | ||||
-rw-r--r-- | lib/socket_wrapper/wscript | 1 |
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', |