Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}