Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lnet / utils / acceptor.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 #include <stdio.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/tcp.h>
8 #include <netdb.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <unistd.h>
14 #include <syslog.h>
15 #include <errno.h>
16 #ifdef HAVE_LIBWRAP
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #include <tcpd.h>
20 #endif
21
22 #include <portals/api-support.h>
23 #include <portals/list.h>
24 #include <portals/lib-types.h>
25 #include <portals/socknal.h>
26
27 /* should get this from autoconf somehow */
28 #ifndef PIDFILE_DIR
29 #define PIDFILE_DIR "/var/run"
30 #endif 
31
32 #define PROGNAME "acceptor"
33
34 #ifdef HAVE_LIBWRAP
35 /* needed because libwrap declares these as externs */
36 int     allow_severity = LOG_INFO;
37 int     deny_severity = LOG_WARNING;
38 #endif
39
40 void create_pidfile(char *name, int port)
41 {
42         char pidfile[1024];
43         FILE *fp;
44
45         snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid", 
46                  PIDFILE_DIR, name, port);
47         
48         if ((fp = fopen(pidfile, "w"))) {
49                 fprintf(fp, "%d\n", getpid());
50                 fclose(fp);
51         } else {
52                 syslog(LOG_ERR, "%s: %s\n", pidfile, 
53                        strerror(errno));
54         }
55 }
56
57 int pidfile_exists(char *name, int port)
58 {
59         char pidfile[1024];
60
61         snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid", 
62                  PIDFILE_DIR, name, port);
63         
64         if (!access(pidfile, F_OK)) {
65                 fprintf(stderr, "%s: exists, acceptor already running.\n", 
66                         pidfile);
67                 return (1);
68         } 
69         return (0);
70 }
71
72 void
73 show_connection (int fd, __u32 net_ip)
74 {
75         struct hostent *h = gethostbyaddr ((char *)&net_ip, sizeof net_ip, AF_INET);
76         __u32 host_ip = ntohl (net_ip);
77         int  len;
78         char host[1024];
79         
80         if (h == NULL)
81                 snprintf (host, sizeof(host), "%d.%d.%d.%d", (host_ip >> 24) & 0xff,
82                                     (host_ip >> 16) & 0xff, (host_ip >> 8) & 0xff, host_ip & 0xff);
83         else
84                 snprintf (host, sizeof(host), "%s", h->h_name);
85                 
86         syslog (LOG_INFO, "Accepted host: %s\n", host);
87 }
88
89 void
90 usage (char *myname)
91 {
92         fprintf (stderr, "Usage: %s [-N nal_id] port\n", myname);
93         exit (1);
94 }
95
96 int main(int argc, char **argv)
97 {
98         int o, fd, rc, port, pfd;
99         struct sockaddr_in srvaddr;
100         int c;
101         int noclose = 0;
102         int nal = SOCKNAL;
103         
104         while ((c = getopt (argc, argv, "N:l")) != -1)
105                 switch (c)
106                 {
107                 case 'l':
108                         noclose = 1;
109                         break;
110
111                 case 'N':
112                         if (sscanf(optarg, "%d", &nal) != 1 ||
113                             nal < 0 || nal > NAL_MAX_NR)
114                                 usage(argv[0]);
115                         break;
116                         
117                 default:
118                         usage (argv[0]);
119                         break;
120                 }
121
122         if (optind >= argc)
123                 usage (argv[0]);
124
125         port = atol(argv[optind++]);
126
127         if (pidfile_exists(PROGNAME, port))
128                 exit(1);
129
130         memset(&srvaddr, 0, sizeof(srvaddr));
131         srvaddr.sin_family = AF_INET;
132         srvaddr.sin_port = htons(port);
133         srvaddr.sin_addr.s_addr = INADDR_ANY;
134
135         fd = socket(PF_INET, SOCK_STREAM, 0);
136         if (fd < 0) {
137                 perror("opening socket");
138                 exit(1);
139         }
140
141         o = 1;
142         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o))) {
143                 perror("Cannot set REUSEADDR socket opt");
144                 exit(1);
145         }
146
147         rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
148         if ( rc == -1 ) {
149                 perror("bind: ");
150                 exit(1);
151         }
152
153         if (listen(fd, 127)) {
154                 perror("listen: ");
155                 exit(1);
156         }
157         fprintf(stderr, "listening on port %d\n", port);
158
159         pfd = open("/dev/portals", O_RDWR);
160         if ( pfd < 0 ) {
161                 perror("opening portals device");
162                 exit(1);
163         }
164
165         rc = daemon(1, noclose);
166         if (rc < 0) {
167                 perror("daemon(): ");
168                 exit(1);
169         }
170
171         openlog(PROGNAME, LOG_PID, LOG_DAEMON);
172         syslog(LOG_INFO, "started, listening on port %d\n", port);
173         create_pidfile(PROGNAME, port);
174
175         while (1) {
176                 struct sockaddr_in clntaddr;
177                 int len = sizeof(clntaddr);
178                 int cfd;
179                 struct portal_ioctl_data data;
180                 struct portals_cfg pcfg;
181 #ifdef HAVE_LIBWRAP
182                 struct request_info request;
183                 char addrstr[INET_ADDRSTRLEN];
184 #endif
185                
186                 cfd = accept(fd, (struct sockaddr *)&clntaddr, &len);
187                 if ( cfd < 0 ) {
188                         perror("accept");
189                         exit(0);
190                         continue;
191                 }
192
193 #ifdef HAVE_LIBWRAP
194                 /* libwrap access control */
195                 request_init(&request, RQ_DAEMON, "lustre", RQ_FILE, cfd, 0);
196                 sock_host(&request);
197                 if (!hosts_access(&request)) {
198                         inet_ntop(AF_INET, &clntaddr.sin_addr,
199                                   addrstr, INET_ADDRSTRLEN);
200                         syslog(LOG_WARNING, "Unauthorized access from %s:%hd\n",
201                                addrstr, ntohs(clntaddr.sin_port));
202                         close (cfd);
203                         continue;
204                 }
205 #endif
206                 show_connection (cfd, clntaddr.sin_addr.s_addr);
207
208                 PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
209                 pcfg.pcfg_nal = nal;
210                 pcfg.pcfg_fd = cfd;
211                 pcfg.pcfg_misc = SOCKNAL_CONN_NONE; /* == incoming connection */
212                 
213                 PORTAL_IOC_INIT(data);
214                 data.ioc_pbuf1 = (char*)&pcfg;
215                 data.ioc_plen1 = sizeof(pcfg);
216                 
217                 if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) {
218                         perror("ioctl failed");
219                 } else {
220                         printf("client registered\n");
221                 }
222                 rc = close(cfd);
223                 if (rc)
224                         perror ("close failed");
225         }
226
227         closelog();
228         exit(0);
229
230 }