]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/dsi/dsi_tcp.c
Merge master
[netatalk.git] / libatalk / dsi / dsi_tcp.c
index 795b80b98c48672cfb834f4cac394a4c8dd12ef3..b87c253b9c4a0f7e09cac95470235f02e44ca203 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: dsi_tcp.c,v 1.24 2009-11-08 09:44:22 franklahm Exp $
- *
  * Copyright (c) 1997, 1998 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
  *
@@ -17,9 +15,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_UNISTD_H */
 #include <errno.h>
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/socket.h>
-
-#ifdef HAVE_STDINT_H
 #include <stdint.h>
-#endif /* HAVE_STDINT_H */
 
 #include <sys/ioctl.h>
 #ifdef TRU64
@@ -58,7 +51,7 @@ int deny_severity = log_warning;
 #include <atalk/dsi.h>
 #include <atalk/compat.h>
 #include <atalk/util.h>
-#include <netatalk/endian.h>
+
 #include "dsi_private.h"
 
 #define min(a,b)  ((a) < (b) ? (a) : (b))
@@ -86,29 +79,10 @@ static void dsi_tcp_close(DSI *dsi)
     dsi->socket = -1;
 }
 
-static void dsi_tcp_timeout(DSI *dsi)
-{
-    struct timeval tv;
-    /* 2 seconds delay, most of the time it translates to 4 seconds:
-     * send/write returns first with whatever it has written and the
-     * second time it returns EAGAIN
-     */
-    tv.tv_sec = 2;
-    tv.tv_usec = 0;
-
-    /* Note: write isn't a restartable syscall if there's a timeout on the socket
-     * we have to test for EINTR
-     */
-    if (setsockopt(dsi->socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
-        LOG(log_error, logtype_default, "dsi_tcp_open: unable to set timeout %s", strerror(errno));
-        exit(EXITERR_CLNT);
-    }
-}
-
 /* alarm handler for tcp_open */
 static void timeout_handler(int sig _U_)
 {
-    LOG(log_error, logtype_default, "dsi_tcp_open: connection timed out");
+    LOG(log_error, logtype_dsi, "dsi_tcp_open: connection timed out");
     exit(EXITERR_CLNT);
 }
 
@@ -128,7 +102,7 @@ static int dsi_tcp_open(DSI *dsi)
         request_init(&req, RQ_DAEMON, dsi->program, RQ_FILE, dsi->socket, NULL);
         fromhost(&req);
         if (!hosts_access(&req)) {
-            LOG(deny_severity, logtype_default, "refused connect from %s", eval_client(&req));
+            LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req));
             close(dsi->socket);
             errno = ECONNREFUSED;
             dsi->socket = -1;
@@ -146,6 +120,9 @@ static int dsi_tcp_open(DSI *dsi)
         u_int8_t block[DSI_BLOCKSIZ];
         size_t stored;
 
+        /* Immediateyl mark globally that we're a child now */
+        parent_or_child = 1;
+
         /* reset signals */
         server_reset_signal();
 
@@ -160,7 +137,7 @@ static int dsi_tcp_open(DSI *dsi)
 
         if ((sigaction(SIGALRM, &newact, &oldact) < 0) ||
             (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
-            LOG(log_error, logtype_default, "dsi_tcp_open: %s", strerror(errno));
+            LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno));
             exit(EXITERR_SYS);
         }
 #endif
@@ -176,7 +153,7 @@ static int dsi_tcp_open(DSI *dsi)
             exit(EXITERR_CLNT);
         }
         if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) {
-            LOG(log_error, logtype_default, "dsi_tcp_open: invalid header");
+            LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header");
             exit(EXITERR_CLNT);
         }
 
@@ -187,7 +164,7 @@ static int dsi_tcp_open(DSI *dsi)
             if (len > 0)
                 stored += len;
             else {
-                LOG(log_error, logtype_default, "dsi_tcp_open: stream_read: %s", strerror(errno));
+                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                 exit(EXITERR_CLNT);
             }
         }
@@ -211,7 +188,7 @@ static int dsi_tcp_open(DSI *dsi)
             if (len > 0)
                 stored += len;
             else {
-                LOG(log_error, logtype_default, "dsi_tcp_open: stream_read: %s", strerror(errno));
+                LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno));
                 exit(EXITERR_CLNT);
             }
         }
@@ -223,9 +200,7 @@ static int dsi_tcp_open(DSI *dsi)
         sigaction(SIGALRM, &oldact, NULL);
 #endif
 
-        dsi_tcp_timeout(dsi);
-
-        LOG(log_info, logtype_default, "AFP/TCP session from %s:%u",
+        LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u",
             getip_string((struct sockaddr *)&dsi->client),
             getip_port((struct sockaddr *)&dsi->client));
     }
@@ -239,7 +214,7 @@ static int dsi_tcp_open(DSI *dsi)
 #define IFF_SLAVE 0
 #endif
 
-static void guess_interface(DSI *dsi, const char *hostname)
+static void guess_interface(DSI *dsi, const char *hostname, const char *port)
 {
     int fd;
     char **start, **list;
@@ -271,14 +246,14 @@ static void guess_interface(DSI *dsi, const char *hostname)
 
         memset(&dsi->server, 0, sizeof(struct sockaddr_storage));
         sa->sin_family = AF_INET;
-        sa->sin_port = htons(548);
+        sa->sin_port = htons(atoi(port));
         sa->sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
 
-        LOG(log_info, logtype_default, "dsi_tcp: '%s' on interface '%s' will be used instead.",
-                  getip_string((struct sockaddr *)&dsi->server), ifr.ifr_name);
+        LOG(log_info, logtype_dsi, "dsi_tcp: '%s:%s' on interface '%s' will be used instead.",
+            getip_string((struct sockaddr *)&dsi->server), port, ifr.ifr_name);
         goto iflist_done;
     }
-    LOG(log_info, logtype_default, "dsi_tcp (Chooser will not select afp/tcp) "
+    LOG(log_info, logtype_dsi, "dsi_tcp (Chooser will not select afp/tcp) "
         "Check to make sure %s is in /etc/hosts and the correct domain is in "
         "/etc/resolv.conf: %s", hostname, strerror(errno));
 
@@ -287,6 +262,11 @@ iflist_done:
     freeifacelist(start);
 }
 
+
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV 0
+#endif
+
 /* this needs to accept passed in addresses */
 int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
                  const char *port, const int proxy)
@@ -299,16 +279,25 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
 
     /* Prepare hint for getaddrinfo */
     memset(&hints, 0, sizeof hints);
+#if !defined(FREEBSD)
     hints.ai_family = AF_UNSPEC;
+#endif
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_flags = AI_NUMERICSERV;
-    if ( ! address)
+
+    if ( ! address) {
         hints.ai_flags |= AI_PASSIVE;
-    else
+#if defined(FREEBSD)
+        hints.ai_family = AF_INET6;
+#endif
+    } else {
         hints.ai_flags |= AI_NUMERICHOST;
-
+#if defined(FREEBSD)
+        hints.ai_family = AF_UNSPEC;
+#endif
+    }
     if ((ret = getaddrinfo(address ? address : NULL, port ? port : "548", &hints, &servinfo)) != 0) {
-        LOG(log_error, logtype_default, "dsi_tcp_init: getaddrinfo: %s\n", gai_strerror(ret));
+        LOG(log_error, logtype_dsi, "dsi_tcp_init: getaddrinfo: %s\n", gai_strerror(ret));
         return 0;
     }
 
@@ -319,7 +308,7 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
         /* loop through all the results and bind to the first we can */
         for (p = servinfo; p != NULL; p = p->ai_next) {
             if ((dsi->serversock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
-                LOG(log_info, logtype_default, "dsi_tcp_init: socket: %s", strerror(errno));
+                LOG(log_info, logtype_dsi, "dsi_tcp_init: socket: %s", strerror(errno));
                 continue;
             }
 
@@ -332,6 +321,10 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
             flag = 1;
             setsockopt(dsi->serversock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
 #endif
+#if defined(FREEBSD) && defined(IPV6_BINDV6ONLY)
+            int on = 0;
+            setsockopt(dsi->serversock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (on));
+#endif
 
 #ifdef USE_TCP_NODELAY
 #ifndef SOL_TCP
@@ -343,13 +336,13 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
             
             if (bind(dsi->serversock, p->ai_addr, p->ai_addrlen) == -1) {
                 close(dsi->serversock);
-                LOG(log_info, logtype_default, "dsi_tcp_init: bind: %s\n", strerror(errno));
+                LOG(log_info, logtype_dsi, "dsi_tcp_init: bind: %s\n", strerror(errno));
                 continue;
             }
 
             if (listen(dsi->serversock, DSI_TCPMAXPEND) < 0) {
                 close(dsi->serversock);
-                LOG(log_info, logtype_default, "dsi_tcp_init: listen: %s\n", strerror(errno));
+                LOG(log_info, logtype_dsi, "dsi_tcp_init: listen: %s\n", strerror(errno));
                 continue;
             }
             
@@ -357,7 +350,7 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
         }
 
         if (p == NULL)  {
-            LOG(log_error, logtype_default, "dsi_tcp_init: no suitable network config for TCP socket");
+            LOG(log_error, logtype_dsi, "dsi_tcp_init: no suitable network config for TCP socket");
             freeaddrinfo(servinfo);
             return 0;
         }
@@ -384,7 +377,7 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
     hints.ai_socktype = SOCK_STREAM;
 
     if ((ret = getaddrinfo(hostname, port ? port : "548", &hints, &servinfo)) != 0) {
-        LOG(log_info, logtype_default, "dsi_tcp_init: getaddrinfo '%s': %s\n", hostname, gai_strerror(ret));
+        LOG(log_info, logtype_dsi, "dsi_tcp_init: getaddrinfo '%s': %s\n", hostname, gai_strerror(ret));
         goto interfaces;
     }
 
@@ -407,11 +400,11 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address,
         freeaddrinfo(servinfo);
         return 1;
     }
-    LOG(log_info, logtype_default, "dsi_tcp: hostname '%s' resolves to loopback address", hostname);
+    LOG(log_info, logtype_dsi, "dsi_tcp: hostname '%s' resolves to loopback address", hostname);
     freeaddrinfo(servinfo);
 
 interfaces:
-    guess_interface(dsi, hostname);
+    guess_interface(dsi, hostname, port ? port : "548");
     return 1;
 }