int ndma_daemon_session (struct ndm_session *sess) { int listen_sock; int conn_sock, rc; socklen_t len; struct sockaddr sa; listen_sock = socket (AF_INET, SOCK_STREAM, 0); if (listen_sock < 0) { perror ("socket"); return 1; } ndmos_condition_listen_socket (sess, listen_sock); NDMOS_MACRO_SET_SOCKADDR(&sa, 0, NDMPPORT); if (bind (listen_sock, &sa, sizeof sa) < 0) { perror ("bind"); return 2; } if (listen (listen_sock, 1) < 0) { perror ("listen"); return 3; } for (;;) { len = sizeof sa; conn_sock = accept (listen_sock, &sa, &len); if (conn_sock < 0) { perror ("accept"); return 4; } rc = fork(); if (rc < 0) { perror ("fork"); return 5; } if (rc == 0) { close (listen_sock); ndma_server_session (sess, conn_sock); exit (0); } close (conn_sock); } return 0; }
static void ndma_proxy_session (struct ndm_session *sess, int proxy_port) { int conn_sock, len, rc; struct sockaddr sa; int proxy_sock; int fd; sess->proxy_starting = TRUE; sess->proxy_connections = 0; proxy_sock = socket (AF_INET, SOCK_STREAM, 0); if (proxy_sock < 0) { fprintf(stdout, "opening socket: %s\n", strerror(errno)); exit(1); } ndmalogf (sess, 0, 2, "set sess->protocol_listen"); ndmos_condition_listen_socket (sess, proxy_sock); NDMOS_MACRO_SET_SOCKADDR(&sa, 0, proxy_port); if (bind (proxy_sock, &sa, sizeof sa) < 0) { int err = errno; ndmalogf (sess, 0, 2, "Can't bind the socket(%d): %s\n", proxy_port, strerror(err)); if (err == EADDRINUSE) { fprintf(stdout, "INUSE\n"); fflush(stdout); exit(0); } else { fprintf(stdout, "while binding tcp port %d: %s\n", proxy_port, strerror(err)); fflush(stdout); exit(1); } } if (listen (proxy_sock, 5) < 0) { fprintf(stdout, "listening on socket: %s\n", strerror(errno)); exit(1); } /* set up to listen on this new socket */ ndmchan_initialize(&sess->listen_chan, "proxy-listen"); ndmchan_start_listen(&sess->listen_chan, proxy_sock); /* tell our invoker that we are OK */ if (full_write(1, "OK\n", 3) != 3) { fprintf(stderr, "ndmp-proxy writing to stdout: %s\n", strerror(errno)); exit(1); } /* send an EOF on stdout */ close(1); /* open /dev/null on fds 0 and 1 */ fd = open("/dev/null", O_RDONLY); if (fd < 0) { fprintf(stderr, "cannot open /dev/null\n"); /* ignore the error */ } else if (fd != 1) { dup2(fd, 1); close(fd); } fd = open("/dev/null", O_WRONLY); if (fd < 0) { fprintf(stderr, "cannot open /dev/null\n"); /* ignore the error */ } else if (fd != 0) { dup2(fd, 0); close(fd); } }
int ndmis_tcp_listen (struct ndm_session *sess, struct ndmp9_addr *listen_addr) { struct ndm_image_stream *is = &sess->plumb.image_stream; ndmp9_tcp_addr * tcp_addr = &listen_addr->ndmp9_addr_u.tcp_addr; struct ndmconn * conn; struct sockaddr c_sa; struct sockaddr l_sa; struct sockaddr_in * sin; socklen_t len; int listen_sock = -1; char * what = "???"; /* * Get the IP address thru which the CONTROL agent connected * to this session. The CONTROL agent may influence the * network used for the image-stream on multi-homed hosts * simply by connecting to the prefered IP address. */ what = "determine-conn"; conn = sess->plumb.control; if (!conn || conn->conn_type != NDMCONN_TYPE_REMOTE) { /* * If CONTROL is resident, try the other * control connections in hopes of finding * a clue about what IP address to offer. */ conn = sess->plumb.data; if (!conn || conn->conn_type != NDMCONN_TYPE_REMOTE) { conn = sess->plumb.tape; if (!conn || conn->conn_type != NDMCONN_TYPE_REMOTE) { conn = 0; } } } if (conn) { /* * We found a connection to use for determining * what IP address to offer. */ what = "getsockname-ctrl"; len = sizeof c_sa; if (getsockname (ndmconn_fileno(conn), &c_sa, &len) < 0) { /* we'll try the fallback rules */ conn = 0; } } if (!conn) { /* * For whatever reason, we can't determine a good * IP address from the connections. Try the boring * fallback rules. */ ndmos_sync_config_info (sess); sin = (struct sockaddr_in *) &c_sa; what = "ndmhost_lookup"; if (ndmhost_lookup (sess->config_info.hostname, sin) != 0) goto fail; } /* c_sa is a sockaddr_in for the IP address to use */ what = "socket"; listen_sock = socket (AF_INET, SOCK_STREAM, 0); if (listen_sock < 0) goto fail; /* could bind() to more restrictive addr based on c_sa */ NDMOS_MACRO_SET_SOCKADDR(&l_sa, 0, 0); what = "bind"; if (bind (listen_sock, &l_sa, sizeof l_sa) < 0) goto fail; what = "listen"; if (listen (listen_sock, 1) < 0) goto fail; ndmos_condition_listen_socket (sess, listen_sock); /* Get the port */ what = "getsockname-listen"; len = sizeof l_sa; if (getsockname (listen_sock, &l_sa, &len) < 0) goto fail; /* * Fill in the return address */ listen_addr->addr_type = NDMP9_ADDR_TCP; tcp_addr = &listen_addr->ndmp9_addr_u.tcp_addr; /* IP addr from CONTROL connection, or where ever c_sa came from */ sin = (struct sockaddr_in *) &c_sa; tcp_addr->ip_addr = ntohl (sin->sin_addr.s_addr); /* port from the bind() and getsockname() above */ sin = (struct sockaddr_in *) &l_sa; tcp_addr->port = ntohs (sin->sin_port); /* * Start the listen channel */ ndmchan_start_listen (&is->remote.listen_chan, listen_sock); is->remote.connect_status = NDMIS_CONN_LISTEN; is->remote.listen_addr = *listen_addr; return 0; fail: ndmalogf (sess, 0, 2, "ndmis_tcp_listen(): %s failed", what); if (listen_sock >= 0) close (listen_sock); return -1; }
int ndma_daemon_session (struct ndm_session *sess, int port, int is_test_daemon) { int listen_sock; int conn_sock, rc; socklen_t len; struct sockaddr sa; listen_sock = socket (AF_INET, SOCK_STREAM, 0); if (listen_sock < 0) { perror ("socket"); return 1; } ndmos_condition_listen_socket (sess, listen_sock); NDMOS_MACRO_SET_SOCKADDR(&sa, 0, port); if (bind (listen_sock, &sa, sizeof sa) < 0) { perror ("bind"); close(listen_sock); return 2; } if (listen (listen_sock, 1) < 0) { perror ("listen"); close(listen_sock); return 3; } if (is_test_daemon) { /* the listen socket is running, so tell our invoker */ printf("READY\n"); fflush(stdout); /* and exit when our stdin goes away */ g_debug("will exit on EOF from stdin"); g_thread_init(NULL); g_thread_create(exit_on_stdin_eof_thread, NULL, FALSE, NULL); } for (;;) { len = sizeof sa; conn_sock = accept (listen_sock, &sa, &len); if (conn_sock < 0) { perror ("accept"); close(listen_sock); return 4; } rc = fork(); if (rc < 0) { perror ("fork"); close(listen_sock); close(conn_sock); return 5; } if (rc == 0) { close (listen_sock); ndma_server_session (sess, conn_sock); exit (0); } close (conn_sock); } return 0; }