Browse Source

Add dual stack support

Closes #46
tags/1.4
Timo Röhling 8 years ago
parent
commit
af7a24ac27
1 changed files with 41 additions and 42 deletions
  1. 41
    42
      postsrsd.c

+ 41
- 42
postsrsd.c View File

@@ -48,11 +48,12 @@
48 48
 
49 49
 static char *self = NULL;
50 50
 
51
-static int bind_service (const char *service, int family)
51
+static size_t bind_service (const char *service, int family, int* socks, size_t max_socks)
52 52
 {
53 53
   struct addrinfo *addr, *it;
54 54
   struct addrinfo hints;
55 55
   int err, sock, flags;
56
+  size_t count = 0;
56 57
   static const int one = 1;
57 58
 
58 59
   memset (&hints, 0, sizeof(hints));
@@ -62,10 +63,11 @@ static int bind_service (const char *service, int family)
62 63
   err = getaddrinfo(NULL, service, &hints, &addr);
63 64
   if (err != 0) {
64 65
     fprintf(stderr, "%s: bind_service(%s): %s\n", self, service, gai_strerror(err));
65
-    return -1;
66
+    return count;
66 67
   }
67 68
   sock = -1;
68 69
   for (it = addr; it; it = it->ai_next) {
70
+    if (max_socks == 0) break;
69 71
     sock = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
70 72
     if (sock < 0) goto fail;
71 73
     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) goto fail;
@@ -74,16 +76,18 @@ static int bind_service (const char *service, int family)
74 76
     flags = fcntl (sock, F_GETFL, 0);
75 77
     if (flags < 0) goto fail;
76 78
     if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) goto fail;
77
-    break;
79
+    *socks++ = sock;
80
+    ++count;
81
+    --max_socks;
82
+    continue;
78 83
   fail:
79 84
     err = errno;
80 85
     if (sock >= 0) close (sock);
81
-    sock = -1;
82 86
   }
83 87
   freeaddrinfo (addr);
84
-  if (sock < 0)
88
+  if (count == 0)
85 89
     fprintf (stderr, "%s: bind_service(%s): %s\n", self, service, strerror(err));
86
-  return sock;
90
+  return count;
87 91
 }
88 92
 
89 93
 static int is_hexdigit (char c)
@@ -237,12 +241,11 @@ typedef void(*handle_t)(srs_t*, FILE*, const char*, const char*, const char**);
237 241
 
238 242
 int main (int argc, char **argv)
239 243
 {
240
-  int opt, timeout = 1800, family = AF_INET;
244
+  int opt, timeout = 1800, family = AF_UNSPEC;
241 245
   int daemonize = FALSE;
242 246
   char *forward_service = NULL, *reverse_service = NULL,
243 247
        *user = NULL, *domain = NULL, *chroot_dir = NULL;
244 248
   char separator = '=';
245
-  int forward_sock, reverse_sock;
246 249
   char *secret_file = NULL, *pid_file = NULL;
247 250
   FILE *pf = NULL, *sf = NULL;
248 251
   struct passwd *pwd = NULL;
@@ -250,10 +253,12 @@ int main (int argc, char **argv)
250 253
   char *tmp;
251 254
   time_t now;
252 255
   srs_t *srs;
253
-  struct pollfd fds[3];
254 256
   const char **excludes;
255 257
   size_t s1 = 0, s2 = 1;
256
-  handle_t handler[2] = { handle_forward, handle_reverse };
258
+  struct pollfd fds[4];
259
+  size_t socket_count = 0, sc;
260
+  int sockets[4] = { -1, -1, -1, -1 };
261
+  handle_t handler[4] = { 0, 0, 0, 0 };
257 262
 
258 263
   excludes = (const char**)calloc(1, sizeof(char*));
259 264
   tmp = strrchr(argv[0], '/');
@@ -374,6 +379,8 @@ int main (int argc, char **argv)
374 379
     fprintf (stderr, "%s: SRS separator character must be one of '=+-'\n", self);
375 380
     return EXIT_FAILURE;
376 381
   }
382
+  if (forward_service == NULL) forward_service = strdup("10001");
383
+  if (reverse_service == NULL) reverse_service = strdup("10002");
377 384
 
378 385
   /* The stuff we do first may not be possible from within chroot or without privileges */
379 386
 
@@ -397,21 +404,14 @@ int main (int argc, char **argv)
397 404
     return EXIT_FAILURE;
398 405
   }
399 406
   /* Bind ports. May require privileges if the config specifies ports below 1024 */
400
-  if (forward_service != NULL) {
401
-    forward_sock = bind_service(forward_service, family);
402
-    free (forward_service);
403
-  } else {
404
-    forward_sock = bind_service("10001", family);
405
-  }
406
-  if (forward_sock < 0) return EXIT_FAILURE;
407
-  if (reverse_service != NULL) {
408
-    reverse_sock = bind_service(reverse_service, family);
409
-    free (reverse_service);
410
-  } else {
411
-    reverse_sock = bind_service("10002", family);
412
-  }
413
-  if (reverse_sock < 0) return EXIT_FAILURE;
414
-
407
+  sc = bind_service(forward_service, family, &sockets[socket_count], 4 - socket_count);
408
+  if (sc == 0) return EXIT_FAILURE;
409
+  while (sc-- > 0) handler[socket_count++] = handle_forward;
410
+  free (forward_service);
411
+  sc = bind_service(reverse_service, family, &sockets[socket_count], 4 - socket_count);
412
+  if (sc == 0) return EXIT_FAILURE;
413
+  while (sc-- > 0) handler[socket_count++] = handle_reverse;
414
+  free (reverse_service);
415 415
   /* Open syslog now (NDELAY), because it may no longer be reachable from chroot */
416 416
   openlog (self, LOG_PID | LOG_NDELAY, LOG_MAIL);
417 417
   /* Force loading of timezone info (suggested by patrickdk77) */
@@ -470,18 +470,17 @@ int main (int argc, char **argv)
470 470
 
471 471
   srs_set_separator (srs, separator);
472 472
 
473
-  fds[0].fd = forward_sock;
474
-  fds[0].events = POLLIN;
475
-  fds[1].fd = reverse_sock;
476
-  fds[1].events = POLLIN;
477
-
473
+  for (sc = 0; sc < socket_count; ++sc) {
474
+    fds[sc].fd = sockets[sc];
475
+    fds[sc].events = POLLIN;
476
+  }
478 477
   while(TRUE) {
479
-    int i, conn;
478
+    int conn;
480 479
     FILE *fp;
481 480
     char linebuf[1024], *line;
482 481
     char keybuf[1024], *key;
483 482
 
484
-    if (poll(fds, 2, 1000) < 0) {
483
+    if (poll(fds, socket_count, 1000) < 0) {
485 484
       if (errno == EINTR)
486 485
         continue;
487 486
       if (daemonize)
@@ -490,20 +489,20 @@ int main (int argc, char **argv)
490 489
         fprintf (stderr, "%s: Poll failure: %s\n", self, strerror(errno));
491 490
       return EXIT_FAILURE;
492 491
     }
493
-    for (i = 0; i < 2; ++i) {
494
-      if (fds[i].revents) {
495
-        conn = accept(fds[i].fd, NULL, NULL);
492
+    for (sc = 0; sc < socket_count; ++sc) {
493
+      if (fds[sc].revents) {
494
+        conn = accept(fds[sc].fd, NULL, NULL);
496 495
         if (conn < 0) continue;
497 496
         if (fork() == 0) {
497
+          int i;
498 498
           // close listen sockets so that we don't stop the main daemon process from restarting
499
-          close(forward_sock);
500
-          close(reverse_sock);
499
+          for (i = 0; i < socket_count; ++i) close (sockets[i]);
501 500
 
502 501
           fp = fdopen(conn, "r+");
503 502
           if (fp == NULL) exit(EXIT_FAILURE);
504
-          fds[2].fd = conn;
505
-          fds[2].events = POLLIN;
506
-          if (poll(&fds[2], 1, timeout * 1000) <= 0) return EXIT_FAILURE;
503
+          fds[0].fd = conn;
504
+          fds[0].events = POLLIN;
505
+          if (poll(fds, 1, timeout * 1000) <= 0) return EXIT_FAILURE;
507 506
           line = fgets(linebuf, sizeof(linebuf), fp);
508 507
           while (line) {
509 508
             fseek (fp, 0, SEEK_CUR); /* Workaround for Solaris */
@@ -522,9 +521,9 @@ int main (int argc, char **argv)
522 521
             }
523 522
             key = url_decode(keybuf, sizeof(keybuf), token);
524 523
             if (!key) break;
525
-            handler[i](srs, fp, key, domain, excludes);
524
+            handler[sc](srs, fp, key, domain, excludes);
526 525
             fflush (fp);
527
-            if (poll(&fds[2], 1, timeout * 1000) <= 0) break;
526
+            if (poll(fds, 1, timeout * 1000) <= 0) break;
528 527
             line = fgets(linebuf, sizeof(linebuf), fp);
529 528
           }
530 529
           fclose (fp);

Loading…
Cancel
Save