---
src/util/virportallocator.c | 72 ++++++++++++++++++++++++++++-----------------
1 file changed, 45 insertions(+), 27 deletions(-)
diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c
index 42e1f28..1922ea6 100644
--- a/src/util/virportallocator.c
+++ b/src/util/virportallocator.c
@@ -98,19 +98,59 @@ virPortAllocatorPtr virPortAllocatorNew(const char *name,
return pa;
}
+static int virPortAllocatorBindToPort(bool *used,
+ unsigned short port)
+{
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(port),
+ .sin_addr.s_addr = htonl(INADDR_ANY)
+ };
+ int reuse = 1;
+ int ret = -1;
+ int fd = -1;
+
+ *used = false;
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ virReportSystemError(errno, "%s", _("Unable to open test
socket"));
+ goto cleanup;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse,
+ sizeof(reuse)) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to set socket reuse addr flag"));
+ goto cleanup;
+ }
+
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ if (errno == EADDRINUSE) {
+ *used = true;
+ ret = 0;
+ } else {
+ virReportSystemError(errno, _("Unable to bind to port %d"), port);
+ }
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FORCE_CLOSE(fd);
+ return ret;
+}
+
int virPortAllocatorAcquire(virPortAllocatorPtr pa,
unsigned short *port)
{
int ret = -1;
size_t i;
- int fd = -1;
*port = 0;
virObjectLock(pa);
for (i = pa->start; i <= pa->end && !*port; i++) {
- int reuse = 1;
- struct sockaddr_in addr;
bool used = false;
if (virBitmapGetBit(pa->bitmap,
@@ -123,31 +163,10 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa,
if (used)
continue;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(i);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- fd = socket(PF_INET, SOCK_STREAM, 0);
- if (fd < 0) {
- virReportSystemError(errno, "%s",
- _("Unable to open test socket"));
+ if (virPortAllocatorBindToPort(&used, i) < 0)
goto cleanup;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse))
< 0) {
- virReportSystemError(errno, "%s",
- _("Unable to set socket reuse addr flag"));
- goto cleanup;
- }
- if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- if (errno != EADDRINUSE) {
- virReportSystemError(errno,
- _("Unable to bind to port %zu"), i);
- goto cleanup;
- }
- /* In use, try next */
- VIR_FORCE_CLOSE(fd);
- } else {
+ if (!used) {
/* Add port to bitmap of reserved ports */
if (virBitmapSetBit(pa->bitmap,
i - pa->start) < 0) {
@@ -167,7 +186,6 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa,
}
cleanup:
virObjectUnlock(pa);
- VIR_FORCE_CLOSE(fd);
return ret;
}
--
1.8.1.5