1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 #include <sys/socket.h>
7 #include <netinet/tcp.h>
12 #include <sys/ioctl.h>
19 #include <arpa/inet.h>
20 #include <netinet/in.h>
24 #include <libcfs/portals_utils.h>
25 #include <portals/api-support.h>
26 #include <portals/lib-types.h>
27 #include <portals/socknal.h>
29 /* should get this from autoconf somehow */
31 #define PIDFILE_DIR "/var/run"
34 char progname[] = "acceptor";
35 char name_port[40]; /* for signal handler */
38 /* needed because libwrap declares these as externs */
39 int allow_severity = LOG_INFO;
40 int deny_severity = LOG_WARNING;
43 void usage(char *progname)
45 fprintf(stderr, "usage: %s [-N nal_id] [-p] [-l] port\n\n"
46 " -l\tKeep stdin/stdout open\n"
47 " -p\tAllow connections from non-privileged ports\n", progname);
51 void errlog(int level, const char *fmt, ...)
67 fprintf(out, "%s: ", name_port);
68 vfprintf(out, fmt, arg);
71 vsyslog(level, fmt, arg);
75 char *pidfile_name(char *name_port)
77 static char pidfile[1024];
79 snprintf(pidfile, sizeof(pidfile), "%s/%s.pid", PIDFILE_DIR, name_port);
84 int pidfile_create(char *name_port)
86 char *pidfile = pidfile_name(name_port);
89 if ((fd = open(pidfile, O_CREAT | O_WRONLY)) >= 0) {
91 int size = snprintf(pid, sizeof(pid), "%u\n", getpid());
92 if (write(fd, pid, size) != size) {
93 /* hard error or short write */
104 errlog(LOG_ERR, " error creating %s: %s\n",
105 pidfile, strerror(rc));
110 int pidfile_cleanup(char *name_port)
112 char *pidfile = pidfile_name(name_port);
115 rc = unlink(pidfile);
116 if (rc && errno != -ENOENT)
117 fprintf(stderr, "%s: error removing %s: %s\n",
118 progname, pidfile, strerror(errno));
119 errlog(LOG_NOTICE, "exiting\n");
124 int pidfile_exists(char *name_port)
126 char *pidfile = pidfile_name(name_port);
130 fpid = fopen(pidfile, "r+");
135 fprintf(stderr, "%s: error opening %s: %s.\n",
136 progname, pidfile, strerror(errno));
140 rc = fscanf(fpid, "%i", &pid);
143 fprintf(stderr,"%s: %s didn't contain a valid pid, removing.\n",
148 if (kill(pid, 0) == 0) {
149 fprintf(stderr, "%s: %s exists, acceptor pid %d running.\n",
150 progname, pidfile, pid);
154 fprintf(stderr, "%s: stale %s exists, pid %d doesn't, removing.\n",
155 progname, pidfile, pid);
157 pidfile_cleanup(name_port);
161 void handler(int sig)
166 void atexit_handler(void)
168 pidfile_cleanup(name_port);
171 void show_connection(int fd, __u32 net_ip)
173 static long last_time;
174 static __u32 host_ip;
180 /* Don't show repeats for same host, it adds no value */
181 if (host_ip == ntohl(net_ip) && (now - last_time) < 5)
184 h = gethostbyaddr((char *)&net_ip, sizeof(net_ip), AF_INET);
186 host_ip = ntohl(net_ip);
189 snprintf(host, sizeof(host), "%d.%d.%d.%d",
190 (host_ip >> 24) & 0xff, (host_ip >> 16) & 0xff,
191 (host_ip >> 8) & 0xff, host_ip & 0xff);
193 snprintf(host, sizeof(host), "%s", h->h_name);
195 syslog(LOG_INFO, "accepted host: %s\n", host);
198 int main(int argc, char **argv)
200 int o, fd, rc, port, pfd;
201 struct sockaddr_in srvaddr;
206 int require_privports = 1;
208 while ((c = getopt (argc, argv, "N:lp")) != -1) {
211 if (sscanf(optarg, "%d", &nal) != 1 ||
212 nal < 0 || nal > NAL_MAX_NR)
219 require_privports = 0;
230 port = atol(argv[optind++]);
232 snprintf(name_port, sizeof(name_port) - 1, "%s-%d", progname, port);
233 if (pidfile_exists(name_port))
235 openlog(name_port, LOG_PID, LOG_DAEMON);
237 memset(&srvaddr, 0, sizeof(srvaddr));
238 srvaddr.sin_family = AF_INET;
239 srvaddr.sin_port = htons(port);
240 srvaddr.sin_addr.s_addr = INADDR_ANY;
242 fd = socket(PF_INET, SOCK_STREAM, 0);
245 errlog(LOG_ERR, "error opening socket: %s\n", strerror(errno));
250 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o))) {
252 errlog(LOG_ERR, "cannot set REUSEADDR socket opt: %s\n",
257 rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
260 errlog(LOG_ERR, "error binding to socket: %s\n",
265 if (listen(fd, 127)) {
270 printf("listening on port %d\n", port);
272 pfd = open("/dev/portals", O_RDWR);
275 errlog(LOG_ERR, "opening portals device: %s\n",strerror(errno));
279 rc = daemon(0, noclose);
282 errlog(LOG_ERR, "error daemonizing: %s\n", strerror(errno));
286 signal(SIGHUP, SIG_IGN);
287 signal(SIGINT, handler);
288 signal(SIGQUIT, handler);
289 signal(SIGTERM, handler);
291 errlog(LOG_NOTICE, "started, listening on port %d\n", port);
292 if (pidfile_create(name_port) == 0)
293 atexit(atexit_handler);
296 struct sockaddr_in clntaddr;
297 int len = sizeof(clntaddr);
299 struct portal_ioctl_data data;
300 struct portals_cfg pcfg;
302 struct request_info request;
304 char addrstr[INET_ADDRSTRLEN];
306 cfd = accept(fd, (struct sockaddr *)&clntaddr, &len);
308 errlog(LOG_ERR, "error accepting connection: %s\n",
314 inet_ntop(AF_INET, &clntaddr.sin_addr, addrstr,INET_ADDRSTRLEN);
316 /* libwrap access control */
317 request_init(&request, RQ_DAEMON, "lustre", RQ_FILE, cfd, 0);
319 if (!hosts_access(&request)) {
320 errlog(LOG_WARNING, "unauthorized access from %s:%hd\n",
321 addrstr, ntohs(clntaddr.sin_port));
327 if (require_privports &&
328 ntohs(clntaddr.sin_port) >= IPPORT_RESERVED) {
330 "closing non-privileged connection from %s:%d\n",
331 addrstr, ntohs(clntaddr.sin_port));
334 perror ("close un-privileged client failed");
338 show_connection (cfd, clntaddr.sin_addr.s_addr);
340 PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
343 pcfg.pcfg_misc = SOCKNAL_CONN_NONE; /* == incoming connection */
345 PORTAL_IOC_INIT(data);
346 data.ioc_pbuf1 = (char*)&pcfg;
347 data.ioc_plen1 = sizeof(pcfg);
349 if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) {
350 errlog(LOG_ERR, "portals ioctl failed for %s: %s\n",
351 addrstr, strerror(errno));
353 errlog(LOG_DEBUG, "client %s registered\n", addrstr);
357 perror("close failed");