Whamcloud - gitweb
b=6277
[fs/lustre-release.git] / lnet / utils / acceptor.c
index c6590db..e5bb46b 100644 (file)
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
-#include <asm/byteorder.h>
 #include <syslog.h>
-
 #include <errno.h>
+#ifdef HAVE_LIBWRAP
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <tcpd.h>
+#endif
 
+#include <libcfs/portals_utils.h>
 #include <portals/api-support.h>
-#include <portals/list.h>
 #include <portals/lib-types.h>
+#include <portals/socknal.h>
 
 /* should get this from autoconf somehow */
 #ifndef PIDFILE_DIR
 
 #define PROGNAME "acceptor"
 
+#ifdef HAVE_LIBWRAP
+/* needed because libwrap declares these as externs */
+int     allow_severity = LOG_INFO;
+int     deny_severity = LOG_WARNING;
+#endif
+
 void create_pidfile(char *name, int port)
 {
         char pidfile[1024];
@@ -59,211 +69,31 @@ int pidfile_exists(char *name, int port)
         return (0);
 }
 
-int
-parse_size (int *sizep, char *str)
-{
-        int             size;
-        char            mod[32];
-
-        switch (sscanf (str, "%d%1[gGmMkK]", &size, mod))
-        {
-        default:
-                return (-1);
-
-        case 1:
-                *sizep = size;
-                return (0);
-
-        case 2:
-                switch (*mod)
-                {
-                case 'g':
-                case 'G':
-                        *sizep = size << 30;
-                        return (0);
-
-                case 'm':
-                case 'M':
-                        *sizep = size << 20;
-                        return (0);
-
-                case 'k':
-                case 'K':
-                        *sizep = size << 10;
-                        return (0);
-
-                default:
-                        *sizep = size;
-                        return (0);
-                }
-        }
-}
-
 void
-show_connection (int fd, __u32 net_ip, ptl_nid_t nid)
+show_connection (int fd, __u32 net_ip)
 {
         struct hostent *h = gethostbyaddr ((char *)&net_ip, sizeof net_ip, AF_INET);
         __u32 host_ip = ntohl (net_ip);
-        int  rxmem = 0;
-        int  txmem = 0;
-        int  nonagle = 0;
         int  len;
         char host[1024];
         
-        len = sizeof (txmem);
-        if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &len) != 0)
-                perror ("Cannot get write buffer size");
-        
-        len = sizeof (rxmem);
-        if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &len) != 0)
-                perror ("Cannot get read buffer size");
-        
-        len = sizeof (nonagle);
-        if (getsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nonagle, &len) != 0)
-                perror ("Cannot get nagle");
-
         if (h == NULL)
                 snprintf (host, sizeof(host), "%d.%d.%d.%d", (host_ip >> 24) & 0xff,
                                     (host_ip >> 16) & 0xff, (host_ip >> 8) & 0xff, host_ip & 0xff);
         else
                 snprintf (host, sizeof(host), "%s", h->h_name);
                 
-        syslog (LOG_INFO, "Accepted host: %s NID: "LPX64" snd: %d rcv %d nagle: %s\n", 
-                 host, nid, txmem, rxmem, nonagle ? "disabled" : "enabled");
-}
-
-int
-sock_write (int cfd, void *buffer, int nob)
-{
-        while (nob > 0)
-        {
-                int rc = write (cfd, buffer, nob);
-
-                if (rc < 0)
-                {
-                        if (errno == EINTR)
-                                continue;
-                        
-                        return (rc);
-                }
-
-                if (rc == 0)
-                {
-                        fprintf (stderr, "Unexpected zero sock_write\n");
-                        abort();
-                }
-
-                nob -= rc;
-                buffer = (char *)buffer + nob;
-        }
-        
-        return (0);
-}
-
-int
-sock_read (int cfd, void *buffer, int nob)
-{
-        while (nob > 0)
-        {
-                int rc = read (cfd, buffer, nob);
-                
-                if (rc < 0)
-                {
-                        if (errno == EINTR)
-                                continue;
-                        
-                        return (rc);
-                }
-                
-                if (rc == 0)                    /* EOF */
-                {
-                        errno = ECONNABORTED;
-                        return (-1);
-                }
-                
-                nob -= rc;
-                buffer = (char *)buffer + nob;
-        }
-        
-        return (0);
-}
-
-int
-exchange_nids (int cfd, ptl_nid_t my_nid, ptl_nid_t *peer_nid)
-{
-        int                      rc;
-        ptl_hdr_t                hdr;
-        ptl_magicversion_t      *hmv = (ptl_magicversion_t *)&hdr.dest_nid;
-
-        LASSERT (sizeof (*hmv) == sizeof (hdr.dest_nid));
-
-        memset (&hdr, 0, sizeof (hdr));
-        
-        hmv->magic          = __cpu_to_le32 (PORTALS_PROTO_MAGIC);
-        hmv->version_major  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR);
-        hmv->version_minor  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR);
-
-        hdr.src_nid = __cpu_to_le64 (my_nid);
-        hdr.type = __cpu_to_le32 (PTL_MSG_HELLO);
-        
-        /* Assume there's sufficient socket buffering for a portals HELLO header */
-        rc = sock_write (cfd, &hdr, sizeof (hdr));
-        if (rc != 0) {
-                perror ("Can't send initial HELLO");
-                return (-1);
-        }
-
-        /* First few bytes down the wire are the portals protocol magic and
-         * version, no matter what protocol version we're running. */
-
-        rc = sock_read (cfd, hmv, sizeof (*hmv));
-        if (rc != 0) {
-                perror ("Can't read from peer");
-                return (-1);
-        }
-
-        if (__cpu_to_le32 (hmv->magic) != PORTALS_PROTO_MAGIC) {
-                fprintf (stderr, "Bad magic %#08x (%#08x expected)\n", 
-                         __cpu_to_le32 (hmv->magic), PORTALS_PROTO_MAGIC);
-                return (-1);
-        }
-
-        if (__cpu_to_le16 (hmv->version_major) != PORTALS_PROTO_VERSION_MAJOR ||
-            __cpu_to_le16 (hmv->version_minor) != PORTALS_PROTO_VERSION_MINOR) {
-                fprintf (stderr, "Incompatible protocol version %d.%d (%d.%d expected)\n",
-                         __cpu_to_le16 (hmv->version_major),
-                         __cpu_to_le16 (hmv->version_minor),
-                         PORTALS_PROTO_VERSION_MAJOR,
-                         PORTALS_PROTO_VERSION_MINOR);
-        }
-
-        /* version 0 sends magic/version as the dest_nid of a 'hello' header,
-         * so read the rest of it in now... */
-        LASSERT (PORTALS_PROTO_VERSION_MAJOR == 0);
-        rc = sock_read (cfd, hmv + 1, sizeof (hdr) - sizeof (*hmv));
-        if (rc != 0) {
-                perror ("Can't read rest of HELLO hdr");
-                return (-1);
-        }
-
-        /* ...and check we got what we expected */
-        if (__cpu_to_le32 (hdr.type) != PTL_MSG_HELLO ||
-            __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)) != 0) {
-                fprintf (stderr, "Expecting a HELLO hdr with 0 payload,"
-                         " but got type %d with %d payload\n",
-                         __cpu_to_le32 (hdr.type),
-                         __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)));
-                return (-1);
-        }
-        
-        *peer_nid = __le64_to_cpu (hdr.src_nid);
-        return (0);
+        syslog (LOG_INFO, "Accepted host: %s\n", host);
 }
 
 void
 usage (char *myname)
 {
-        fprintf (stderr, "Usage: %s [-r recv_mem] [-s send_mem] [-n] [-N nal_id] port\n", myname);
+        fprintf (stderr, 
+                 "Usage: %s [-N nal_id] [-p] [-l] port\n\n"
+                 " -l\tKeep stdin/stdout open\n"
+                 " -p\tAllow connections from non-privileged ports\n",
+                 myname);
         exit (1);
 }
 
@@ -272,53 +102,29 @@ int main(int argc, char **argv)
         int o, fd, rc, port, pfd;
         struct sockaddr_in srvaddr;
         int c;
-        int rxmem = 0;
-        int txmem = 0;
         int noclose = 0;
-        int nonagle = 1;
         int nal = SOCKNAL;
-        int xchg_nids = 0;
-        int bind_irq = 0;
+        int rport;
+        int require_privports = 1;
         
-        while ((c = getopt (argc, argv, "N:r:s:nlxi")) != -1)
-                switch (c)
-                {
-                case 'r':
-                        if (parse_size (&rxmem, optarg) != 0 || rxmem < 0)
-                                usage (argv[0]);
-                        break;
-                        
-                case 's':
-                        if (parse_size (&txmem, optarg) != 0 || txmem < 0)
-                                usage (argv[0]);
-                        break;
-
-                case 'n':
-                        nonagle = 0;
+        while ((c = getopt (argc, argv, "N:lp")) != -1) {
+                switch (c) {
+                case 'N':
+                        if (sscanf(optarg, "%d", &nal) != 1 ||
+                            nal < 0 || nal > NAL_MAX_NR)
+                                usage(argv[0]);
                         break;
-
                 case 'l':
                         noclose = 1;
                         break;
-
-                case 'x':
-                        xchg_nids = 1;
-                        break;
-
-                case 'i':
-                        bind_irq = 1;
+                case 'p':
+                        require_privports = 0;
                         break;
-                        
-                case 'N':
-                        if (parse_size(&nal, optarg) != 0 || 
-                            nal < 0 || nal > NAL_MAX_NR)
-                                usage(argv[0]);
-                        break;
-                        
                 default:
                         usage (argv[0]);
                         break;
                 }
+        }
 
         if (optind >= argc)
                 usage (argv[0]);
@@ -345,37 +151,6 @@ int main(int argc, char **argv)
                 exit(1);
         }
 
-        if (nonagle)
-        {
-                o = 1;
-                rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &o, sizeof (o));
-                if (rc != 0) 
-                { 
-                        perror ("Cannot disable nagle");
-                        exit (1);
-                }
-        }
-
-        if (txmem != 0)
-        {
-                rc = setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, sizeof (txmem));
-                if (rc != 0)
-                {
-                        perror ("Cannot set write buffer size");
-                        exit (1);
-                }
-        }
-        
-        if (rxmem != 0)
-        {
-                rc = setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, sizeof (rxmem));
-                if (rc != 0)
-                {
-                        perror ("Cannot set read buffer size");
-                        exit (1);
-               }
-        }
-                
         rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
         if ( rc == -1 ) {
                 perror("bind: ");
@@ -394,7 +169,7 @@ int main(int argc, char **argv)
                 exit(1);
         }
 
-        rc = daemon(1, noclose);
+        rc = daemon(0, noclose);
         if (rc < 0) {
                 perror("daemon(): ");
                 exit(1);
@@ -409,8 +184,12 @@ int main(int argc, char **argv)
                 int len = sizeof(clntaddr);
                 int cfd;
                 struct portal_ioctl_data data;
-                ptl_nid_t peer_nid;
-                
+                struct portals_cfg pcfg;
+#ifdef HAVE_LIBWRAP
+                struct request_info request;
+#endif
+                char addrstr[INET_ADDRSTRLEN];
+               
                 cfd = accept(fd, (struct sockaddr *)&clntaddr, &len);
                 if ( cfd < 0 ) {
                         perror("accept");
@@ -418,40 +197,44 @@ int main(int argc, char **argv)
                         continue;
                 }
 
-                if (!xchg_nids)
-                        peer_nid = ntohl (clntaddr.sin_addr.s_addr); /* HOST byte order */
-                else
-                {
-                        PORTAL_IOC_INIT (data);
-                        data.ioc_nal = nal;
-                        rc = ioctl (pfd, IOC_PORTAL_GET_NID, &data);
-                        if (rc < 0)
-                        {
-                                perror ("Can't get my NID");
-                                close (cfd);
-                                continue;
-                        }
-                        
-                        rc = exchange_nids (cfd, data.ioc_nid, &peer_nid);
-                        if (rc != 0)
-                        {
-                                close (cfd);
-                                continue;
-                        }
+#ifdef HAVE_LIBWRAP
+                /* libwrap access control */
+                request_init(&request, RQ_DAEMON, "lustre", RQ_FILE, cfd, 0);
+                sock_host(&request);
+                if (!hosts_access(&request)) {
+                        inet_ntop(AF_INET, &clntaddr.sin_addr,
+                                  addrstr, INET_ADDRSTRLEN);
+                        syslog(LOG_WARNING, "Unauthorized access from %s:%hd\n",
+                               addrstr, ntohs(clntaddr.sin_port));
+                        close (cfd);
+                        continue;
+                }
+#endif
+
+                if (require_privports && ntohs(clntaddr.sin_port) >= IPPORT_RESERVED) {
+                        inet_ntop(AF_INET, &clntaddr.sin_addr,
+                                  addrstr, INET_ADDRSTRLEN);
+                        syslog(LOG_ERR, "Closing non-privileged connection from %s:%d\n",
+                               addrstr, ntohs(clntaddr.sin_port));
+                        rc = close(cfd);
+                        if (rc)
+                                perror ("close un-privileged client failed");
+                        continue;
                 }
 
-                show_connection (cfd, clntaddr.sin_addr.s_addr, peer_nid);
+                show_connection (cfd, clntaddr.sin_addr.s_addr);
+
+                PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
+                pcfg.pcfg_nal = nal;
+                pcfg.pcfg_fd = cfd;
+                pcfg.pcfg_misc = SOCKNAL_CONN_NONE; /* == incoming connection */
                 
                 PORTAL_IOC_INIT(data);
-                data.ioc_fd = cfd;
-                data.ioc_nal = nal;
-                data.ioc_nal_cmd = NAL_CMD_REGISTER_PEER_FD;
-                data.ioc_nid = peer_nid;
-                data.ioc_flags = bind_irq;
+                data.ioc_pbuf1 = (char*)&pcfg;
+                data.ioc_plen1 = sizeof(pcfg);
                 
                 if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) {
                         perror("ioctl failed");
-
                 } else {
                         printf("client registered\n");
                 }