int ndmca_data_connect (struct ndm_session *sess) { struct ndmconn * conn = sess->plumb.data; struct ndm_control_agent *ca = &sess->control_acb; int rc; ndmp9_addr addr; if (ca->job.tape_tcp) { char *host; char *port; struct sockaddr_in sin; host = ca->job.tape_tcp; port = strchr(ca->job.tape_tcp, ':'); *port++ = '\0'; rc = ndmhost_lookup(host, &sin); addr.addr_type = NDMP9_ADDR_TCP; addr.ndmp9_addr_u.tcp_addr.ip_addr = ntohl(sin.sin_addr.s_addr); addr.ndmp9_addr_u.tcp_addr.port = atoi(port); } else { addr = ca->mover_addr; } NDMC_WITH(ndmp9_data_connect, NDMP9VER) request->addr = addr; rc = NDMC_CALL(conn); NDMC_ENDWITH return rc; }
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; }