Browse Source

Add dual stack support

Closes #46
tags/1.4
Timo Röhling 9 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
 
48
 
49
 static char *self = NULL;
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
   struct addrinfo *addr, *it;
53
   struct addrinfo *addr, *it;
54
   struct addrinfo hints;
54
   struct addrinfo hints;
55
   int err, sock, flags;
55
   int err, sock, flags;
56
+  size_t count = 0;
56
   static const int one = 1;
57
   static const int one = 1;
57
 
58
 
58
   memset (&hints, 0, sizeof(hints));
59
   memset (&hints, 0, sizeof(hints));
62
   err = getaddrinfo(NULL, service, &hints, &addr);
63
   err = getaddrinfo(NULL, service, &hints, &addr);
63
   if (err != 0) {
64
   if (err != 0) {
64
     fprintf(stderr, "%s: bind_service(%s): %s\n", self, service, gai_strerror(err));
65
     fprintf(stderr, "%s: bind_service(%s): %s\n", self, service, gai_strerror(err));
65
-    return -1;
66
+    return count;
66
   }
67
   }
67
   sock = -1;
68
   sock = -1;
68
   for (it = addr; it; it = it->ai_next) {
69
   for (it = addr; it; it = it->ai_next) {
70
+    if (max_socks == 0) break;
69
     sock = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
71
     sock = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
70
     if (sock < 0) goto fail;
72
     if (sock < 0) goto fail;
71
     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) goto fail;
73
     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) goto fail;
74
     flags = fcntl (sock, F_GETFL, 0);
76
     flags = fcntl (sock, F_GETFL, 0);
75
     if (flags < 0) goto fail;
77
     if (flags < 0) goto fail;
76
     if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) goto fail;
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
   fail:
83
   fail:
79
     err = errno;
84
     err = errno;
80
     if (sock >= 0) close (sock);
85
     if (sock >= 0) close (sock);
81
-    sock = -1;
82
   }
86
   }
83
   freeaddrinfo (addr);
87
   freeaddrinfo (addr);
84
-  if (sock < 0)
88
+  if (count == 0)
85
     fprintf (stderr, "%s: bind_service(%s): %s\n", self, service, strerror(err));
89
     fprintf (stderr, "%s: bind_service(%s): %s\n", self, service, strerror(err));
86
-  return sock;
90
+  return count;
87
 }
91
 }
88
 
92
 
89
 static int is_hexdigit (char c)
93
 static int is_hexdigit (char c)
237
 
241
 
238
 int main (int argc, char **argv)
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
   int daemonize = FALSE;
245
   int daemonize = FALSE;
242
   char *forward_service = NULL, *reverse_service = NULL,
246
   char *forward_service = NULL, *reverse_service = NULL,
243
        *user = NULL, *domain = NULL, *chroot_dir = NULL;
247
        *user = NULL, *domain = NULL, *chroot_dir = NULL;
244
   char separator = '=';
248
   char separator = '=';
245
-  int forward_sock, reverse_sock;
246
   char *secret_file = NULL, *pid_file = NULL;
249
   char *secret_file = NULL, *pid_file = NULL;
247
   FILE *pf = NULL, *sf = NULL;
250
   FILE *pf = NULL, *sf = NULL;
248
   struct passwd *pwd = NULL;
251
   struct passwd *pwd = NULL;
250
   char *tmp;
253
   char *tmp;
251
   time_t now;
254
   time_t now;
252
   srs_t *srs;
255
   srs_t *srs;
253
-  struct pollfd fds[3];
254
   const char **excludes;
256
   const char **excludes;
255
   size_t s1 = 0, s2 = 1;
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
   excludes = (const char**)calloc(1, sizeof(char*));
263
   excludes = (const char**)calloc(1, sizeof(char*));
259
   tmp = strrchr(argv[0], '/');
264
   tmp = strrchr(argv[0], '/');
374
     fprintf (stderr, "%s: SRS separator character must be one of '=+-'\n", self);
379
     fprintf (stderr, "%s: SRS separator character must be one of '=+-'\n", self);
375
     return EXIT_FAILURE;
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
   /* The stuff we do first may not be possible from within chroot or without privileges */
385
   /* The stuff we do first may not be possible from within chroot or without privileges */
379
 
386
 
397
     return EXIT_FAILURE;
404
     return EXIT_FAILURE;
398
   }
405
   }
399
   /* Bind ports. May require privileges if the config specifies ports below 1024 */
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
   /* Open syslog now (NDELAY), because it may no longer be reachable from chroot */
415
   /* Open syslog now (NDELAY), because it may no longer be reachable from chroot */
416
   openlog (self, LOG_PID | LOG_NDELAY, LOG_MAIL);
416
   openlog (self, LOG_PID | LOG_NDELAY, LOG_MAIL);
417
   /* Force loading of timezone info (suggested by patrickdk77) */
417
   /* Force loading of timezone info (suggested by patrickdk77) */
470
 
470
 
471
   srs_set_separator (srs, separator);
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
   while(TRUE) {
477
   while(TRUE) {
479
-    int i, conn;
478
+    int conn;
480
     FILE *fp;
479
     FILE *fp;
481
     char linebuf[1024], *line;
480
     char linebuf[1024], *line;
482
     char keybuf[1024], *key;
481
     char keybuf[1024], *key;
483
 
482
 
484
-    if (poll(fds, 2, 1000) < 0) {
483
+    if (poll(fds, socket_count, 1000) < 0) {
485
       if (errno == EINTR)
484
       if (errno == EINTR)
486
         continue;
485
         continue;
487
       if (daemonize)
486
       if (daemonize)
490
         fprintf (stderr, "%s: Poll failure: %s\n", self, strerror(errno));
489
         fprintf (stderr, "%s: Poll failure: %s\n", self, strerror(errno));
491
       return EXIT_FAILURE;
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
         if (conn < 0) continue;
495
         if (conn < 0) continue;
497
         if (fork() == 0) {
496
         if (fork() == 0) {
497
+          int i;
498
           // close listen sockets so that we don't stop the main daemon process from restarting
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
           fp = fdopen(conn, "r+");
501
           fp = fdopen(conn, "r+");
503
           if (fp == NULL) exit(EXIT_FAILURE);
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
           line = fgets(linebuf, sizeof(linebuf), fp);
506
           line = fgets(linebuf, sizeof(linebuf), fp);
508
           while (line) {
507
           while (line) {
509
             fseek (fp, 0, SEEK_CUR); /* Workaround for Solaris */
508
             fseek (fp, 0, SEEK_CUR); /* Workaround for Solaris */
522
             }
521
             }
523
             key = url_decode(keybuf, sizeof(keybuf), token);
522
             key = url_decode(keybuf, sizeof(keybuf), token);
524
             if (!key) break;
523
             if (!key) break;
525
-            handler[i](srs, fp, key, domain, excludes);
524
+            handler[sc](srs, fp, key, domain, excludes);
526
             fflush (fp);
525
             fflush (fp);
527
-            if (poll(&fds[2], 1, timeout * 1000) <= 0) break;
526
+            if (poll(fds, 1, timeout * 1000) <= 0) break;
528
             line = fgets(linebuf, sizeof(linebuf), fp);
527
             line = fgets(linebuf, sizeof(linebuf), fp);
529
           }
528
           }
530
           fclose (fp);
529
           fclose (fp);

Loading…
Cancel
Save