Beispiel #1
0
static int
doit_passive (kx_context *kc)
{
     int otherside;
     u_char msg[1024], *p;
     int len;
     uint32_t tmp;
     const char *host = kc->host;

     otherside = connect_host (kc);

     if (otherside < 0)
	 return 1;
#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
     if (kc->keepalive_flag) {
	 int one = 1;

	 setsockopt (otherside, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
		     sizeof(one));
     }
#endif

     p = msg;
     *p++ = INIT;
     len = strlen(kc->user);
     p += kx_put_int (len, p, sizeof(msg) - 1, 4);
     memcpy(p, kc->user, len);
     p += len;
     *p++ = PASSIVE | (kc->keepalive_flag ? KEEP_ALIVE : 0);
     if (kx_write (kc, otherside, msg, p - msg) != p - msg)
	 err (1, "write to %s", host);
     len = kx_read (kc, otherside, msg, sizeof(msg));
     if (len <= 0)
	 errx (1,
	       "error reading initial message from %s: "
	       "this probably means it's using an old version.",
	       host);
     p = (u_char *)msg;
     if (*p == ERROR) {
	 p++;
	 p += kx_get_int (p, &tmp, 4, 0);
	 errx (1, "%s: %.*s", host, (int)tmp, p);
     } else if (*p != ACK) {
	 errx (1, "%s: strange msg %d", host, *p);
     } else
	 p++;
     p += kx_get_int (p, &tmp, 4, 0);
     memcpy(display, p, tmp);
     display[tmp] = '\0';
     p += tmp;

     p += kx_get_int (p, &tmp, 4, 0);
     memcpy(xauthfile, p, tmp);
     xauthfile[tmp] = '\0';
     p += tmp;

     status_output (kc->debug_flag);
     for (;;) {
	 pid_t child;

	 len = kx_read (kc, otherside, msg, sizeof(msg));
	 if (len < 0)
	     err (1, "read from %s", host);
	 else if (len == 0)
	     return 0;

	 p = (u_char *)msg;
	 if (*p == ERROR) {
	     p++;
	     p += kx_get_int (p, &tmp, 4, 0);
	     errx (1, "%s: %.*s", host, (int)tmp, p);
	 } else if(*p != NEW_CONN) {
	     errx (1, "%s: strange msg %d", host, *p);
	 } else {
	     p++;
	     p += kx_get_int (p, &tmp, 4, 0);
	 }

	 ++nchild;
	 child = fork ();
	 if (child < 0) {
	     warn("fork");
	     continue;
	 } else if (child == 0) {
	     int fd;
	     int xserver;

	     close (otherside);

	     socket_set_port(kc->thataddr, htons(tmp));

	     fd = socket (kc->thataddr->sa_family, SOCK_STREAM, 0);
	     if (fd < 0)
		 err(1, "socket");
#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
	     {
		 int one = 1;

		 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one,
			     sizeof(one));
	     }
#endif
#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
	     if (kc->keepalive_flag) {
		 int one = 1;

		 setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&one,
			     sizeof(one));
	     }
#endif

	     if (connect (fd, kc->thataddr, kc->thataddr_len) < 0)
		 err(1, "connect(%s)", host);
	     {
		 int d = 0;
		 char *s;

		 s = getenv ("DISPLAY");
		 if (s != NULL) {
		     s = strchr (s, ':');
		     if (s != NULL)
			 d = atoi (s + 1);
		 }

		 xserver = connect_local_xsocket (d);
		 if (xserver < 0)
		     return 1;
	     }
	     return passive_session (xserver, fd, kc);
	 } else {
	 }
     }
}
Beispiel #2
0
/**
 * @brief
 *      This function is called whenever there is a connection accepted by the
 *      port forwarder at qsub side. It will further send the data read by port
 *      forwarder to the x server listening on the display number set in the
 *      environment.
 * @param[in] display - The display number where X server is listening in
 *                      qsub.
 * @param[in] alsounused - This parameter is not used. its there just to
 *                         maintain consistency between function pointers used
 *                         by port_forwarder.
 * @return	int
 * @retval	socket number which is connected to Xserver.	success
 * @retval 	-1   						Failure
 */
int
x11_connect_display(
	char *display,
	long alsounused)
{
	int display_number, sock = 0;
	char buf[1024], *cp;
	struct addrinfo hints, *ai, *aitop;
	char strport[NI_MAXSERV];
	int gaierr;

	/*
	 * Now we decode the value of the DISPLAY variable and make a
	 * connection to the real X server.
	 */

	/*
	 * Check if it is a unix domain socket.  Unix domain displays are in
	 * one of the following formats: unix:d[.s], :d[.s], ::d[.s]
	 */
	if (strncmp(display, "unix:", 5) == 0 ||
		display[0] == ':') {
		/* Connect to the unix domain socket. */
		if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {
			fprintf(stderr, "Could not parse display number from DISPLAY: %.100s",
				display);
			return -1;
		}
		/* Create a socket. */
		sock = connect_local_xsocket(display_number);
		if (sock < 0)
			return -1;
		/* OK, we now have a connection to the display. */
		return sock;
	}

	/*
	 * Connect to an inet socket.  The DISPLAY value is supposedly
	 * hostname:d[.s], where hostname may also be numeric IP address.
	 */
	strncpy(buf, display, sizeof(buf));
	cp = strchr(buf, ':');
	if (!cp) {
		fprintf(stderr, "Could not find ':' in DISPLAY: %.100s", display);
		return -1;
	}

	*cp = 0;
	/* buf now contains the host name.  But first we parse the display number. */
	if (sscanf(cp + 1, "%d", &display_number) != 1) {
		fprintf(stderr, "Could not parse display number from DISPLAY: %.100s",
			display);
		return -1;
	}

	/* Look up the host address */
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	snprintf(strport, sizeof(strport), "%d", 6000 + display_number);
	if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
		fprintf(stderr, "%100s: unknown host. (%s)", buf, gai_strerror(gaierr));
		return -1;
	}

	for (ai = aitop; ai; ai = ai->ai_next) {
		/* Create a socket. */
		sock = socket(ai->ai_family, SOCK_STREAM, 0);
		if (sock < 0) {
			fprintf(stderr, "socket: %.100s", strerror(errno));
			continue;
		}

		/* Connect it to the display. */
		if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
			fprintf(stderr, "connect %.100s port %d: %.100s", buf,
				6000 + display_number, strerror(errno));
			close(sock);
			continue;
		}

		/* Success */
		break;
	}

	freeaddrinfo(aitop);
	if (!ai) {
		fprintf(stderr, "connect %.100s port %d: %.100s", buf, 6000 + display_number,
			strerror(errno));
		return -1;
	}

	set_nodelay(sock);
	return sock;
}