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>
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
22 #include <libcfs/portals_utils.h>
23 #include <portals/api-support.h>
24 #include <portals/lib-types.h>
25 #include <portals/socknal.h>
27 /* should get this from autoconf somehow */
29 #define PIDFILE_DIR "/var/run"
32 #define PROGNAME "acceptor"
35 /* needed because libwrap declares these as externs */
36 int allow_severity = LOG_INFO;
37 int deny_severity = LOG_WARNING;
40 void usage(char *myname)
42 fprintf(stderr, "usage: %s [-N nal_id] [-p] [-l] port\n\n"
43 " -l\tKeep stdin/stdout open\n"
44 " -p\tAllow connections from non-privileged ports\n", myname);
48 char *pidfile_name(char *name, int port)
50 static char pidfile[1024];
52 snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid",
53 PIDFILE_DIR, name, port);
58 void pidfile_create(char *name, int port)
60 char *pidfile = pidfile_name(name, port);
63 if ((fp = fopen(pidfile, "w"))) {
64 fprintf(fp, "%d\n", getpid());
67 syslog(LOG_DAEMON|LOG_ERR, "%s: %s\n", pidfile,strerror(errno));
71 int pidfile_cleanup(char *name, int port)
73 char *pidfile = pidfile_name(name, port);
77 if (rc && errno != -ENOENT)
78 fprintf(stderr, "%s: error removing %s: %s\n",
79 PROGNAME, pidfile, strerror(errno));
84 int pidfile_exists(char *name, int port)
86 char *pidfile = pidfile_name(name, port);
90 snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid",
91 PIDFILE_DIR, name, port);
93 fpid = fopen(pidfile, "r+");
98 fprintf(stderr, "%s: error opening %s: %s.\n",
99 PROGNAME, pidfile, strerror(errno));
103 rc = fscanf(fpid, "%i", &pid);
106 fprintf(stderr,"%s: %s didn't contain a valid pid, removing.\n",
111 if (kill(pid, 0) == 0) {
112 fprintf(stderr, "%s: %s exists, acceptor pid %d running.\n",
113 PROGNAME, pidfile, pid);
117 fprintf(stderr, "%s: stale %s exists, pid %d doesn't, removing.\n",
118 PROGNAME, pidfile, pid);
120 pidfile_cleanup(name, port);
125 show_connection (int fd, __u32 net_ip)
127 static long last_time;
128 static __u32 host_ip;
134 /* Don't show repeats for same host, it adds no value */
135 if (host_ip == ntohl(net_ip) && (now - last_time) < 5)
138 h = gethostbyaddr((char *)&net_ip, sizeof(net_ip), AF_INET);
140 host_ip = ntohl(net_ip);
143 snprintf(host, sizeof(host), "%d.%d.%d.%d",
144 (host_ip >> 24) & 0xff, (host_ip >> 16) & 0xff,
145 (host_ip >> 8) & 0xff, host_ip & 0xff);
147 snprintf(host, sizeof(host), "%s", h->h_name);
149 syslog(LOG_DAEMON | LOG_INFO, "Accepted host: %s\n", host);
152 int main(int argc, char **argv)
154 int o, fd, rc, port, pfd;
155 struct sockaddr_in srvaddr;
160 int require_privports = 1;
162 while ((c = getopt (argc, argv, "N:lp")) != -1) {
165 if (sscanf(optarg, "%d", &nal) != 1 ||
166 nal < 0 || nal > NAL_MAX_NR)
173 require_privports = 0;
184 port = atol(argv[optind++]);
186 if (pidfile_exists(PROGNAME, port))
189 memset(&srvaddr, 0, sizeof(srvaddr));
190 srvaddr.sin_family = AF_INET;
191 srvaddr.sin_port = htons(port);
192 srvaddr.sin_addr.s_addr = INADDR_ANY;
194 fd = socket(PF_INET, SOCK_STREAM, 0);
197 perror("opening socket");
202 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o))) {
204 perror("Cannot set REUSEADDR socket opt");
208 rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
215 if (listen(fd, 127)) {
220 fprintf(stderr, "listening on port %d\n", port);
222 pfd = open("/dev/portals", O_RDWR);
225 perror("opening portals device");
229 rc = daemon(0, noclose);
232 perror("daemon(): ");
236 openlog(PROGNAME, LOG_PID, LOG_DAEMON);
237 syslog(LOG_DAEMON | LOG_INFO, "started, listening on port %d\n", port);
238 pidfile_create(PROGNAME, port);
241 struct sockaddr_in clntaddr;
242 int len = sizeof(clntaddr);
244 struct portal_ioctl_data data;
245 struct portals_cfg pcfg;
247 struct request_info request;
249 char addrstr[INET_ADDRSTRLEN];
251 cfd = accept(fd, (struct sockaddr *)&clntaddr, &len);
254 pidfile_cleanup(PROGNAME, port);
260 /* libwrap access control */
261 request_init(&request, RQ_DAEMON, "lustre", RQ_FILE, cfd, 0);
263 if (!hosts_access(&request)) {
264 inet_ntop(AF_INET, &clntaddr.sin_addr,
265 addrstr, INET_ADDRSTRLEN);
266 syslog(LOG_DAEMON | LOG_WARNING,
267 "Unauthorized access from %s:%hd\n",
268 addrstr, ntohs(clntaddr.sin_port));
274 if (require_privports && ntohs(clntaddr.sin_port) >= IPPORT_RESERVED) {
275 inet_ntop(AF_INET, &clntaddr.sin_addr,
276 addrstr, INET_ADDRSTRLEN);
277 syslog(LOG_DAEMON | LOG_ERR,
278 "Closing non-privileged connection from %s:%d\n",
279 addrstr, ntohs(clntaddr.sin_port));
282 perror ("close un-privileged client failed");
286 show_connection (cfd, clntaddr.sin_addr.s_addr);
288 PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
291 pcfg.pcfg_misc = SOCKNAL_CONN_NONE; /* == incoming connection */
293 PORTAL_IOC_INIT(data);
294 data.ioc_pbuf1 = (char*)&pcfg;
295 data.ioc_plen1 = sizeof(pcfg);
297 if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) {
298 perror("ioctl failed");
300 printf("client registered\n");
304 perror ("close failed");
308 pidfile_cleanup(PROGNAME, port);