Esempio n. 1
0
int tcp_con(const char *adr, int port)
{
  static int                s, ind;
  static struct sockaddr_in remoteAddr;
  static struct hostent     *host;
  static struct in_addr     RemoteIpAddress;
  int                       ret;
#ifdef AF_INET6_IS_AVAILABLE
  static struct addrinfo    hints, *res, *ressave;
  int                       n;
  char                      portstr[32];
#endif
  int is_localhost = 0;

  if(opt.arg_log) printf("conn=%s port=%d\n", adr, port);
  if(strcmp(adr,"localhost") == 0) is_localhost = 1;
  if(strcmp(adr,"127.0.0.1") == 0) is_localhost = 1;
  if(strcmp(adr,"::1")       == 0) is_localhost = 1;
  if(pvb_com_con != NULL)
  {
    int use_plugin = 0;
    s = (pvb_com_con)(adr,port,&use_plugin);
    if(opt.arg_debug) printf("plugin returned use_plugin=%d\n", use_plugin);
    if(s > 0)
    {
      for(ind=1; ind<=MAX_TABS; ind++)
      {
        if(socket_array[ind] == -1)
        {
          socket_array[ind] = s;
          use_pvb_com_plugin[ind] = use_plugin;
          if(opt.arg_debug) printf("use_pvb_con_plugin[%d]=%d\n", ind, s);
          break;
        }
      }
      return ind;
    }  
  }
  if(rl_ipversion == 4)
  {
    s = socket(AF_INET,SOCK_STREAM,0);
    if(s == -1) return -1;

    /* fill destblk structure */
    host = gethostbyname(adr);
    if(host == NULL)
    {
      /* See if the host is specified in "dot address" form */
      if(strchr(adr,'.') == NULL) return -1;
      RemoteIpAddress.s_addr = inet_addr(adr);
      if(RemoteIpAddress.s_addr == 0x0ffffffff) return -1;
    }
    else
    {
       memcpy(&RemoteIpAddress,host->h_addr,host->h_length);
    }

    memset(&remoteAddr,0,sizeof(remoteAddr));
    remoteAddr.sin_family = AF_INET;
    remoteAddr.sin_port = htons(port);
    remoteAddr.sin_addr = RemoteIpAddress;

    ret = connect_timed(s, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr), is_localhost);
    //if(ret == -1)
    if(ret < 0)
    {
      closesocket(s);
      return -1;
    }
  }
  else if(rl_ipversion == 6)
  {
#ifdef AF_INET6_IS_AVAILABLE
    sprintf(portstr,"%d",port);
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    n = getaddrinfo(adr, portstr, &hints, &res);
    if(n != 0)
    {
#ifndef PVWIN32
      ::printf("tcp_con 1: error for %s port=%s : %s\n", adr, portstr, gai_strerror(n));
#endif
      return -1;
    }
    ressave = res;
    do
    {
      s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      if(s < 0)                                                                continue; // ignore this one
      if(::connect_timed(s, res->ai_addr, res->ai_addrlen, is_localhost) == 0) break;    // success
      closesocket(s);
      s = -1;
    }
    while((res = res->ai_next) != NULL);
    if(res == NULL) ::printf("tcp_con 2: error for %s port=%s\n", adr, portstr);
    freeaddrinfo(ressave);
#else
    ::printf("tcp_con 3:ERROR IPV6 not available on this platform\n");
#endif
  }
  else
  {
    printf("tcp_con 4: ipversion=%d is not supported\n", rl_ipversion);
  }
  for(ind=1; ind<=MAX_TABS; ind++)
  {
    if(socket_array[ind] == -1)
    {
      socket_array[ind] = s;
      use_pvb_com_plugin[ind] = 0;
      break;
    }
  }
  return ind;
}
int
client_open(int timeout)
{
    int			sin_size = sizeof (struct sockaddr_in);
    struct sockaddr_in	sin_local;
    struct sockaddr_in	sin_dst;
    int			sock_fd;
    const char	       *dst_host;

    init_sockaddr_in(&sin_local, 0, 0);

    /*
     * create our local socket descriptor.  pay attention:
     *
     * SVR4 STREAMS-based socket implementations check permissions
     * on binds to privileged ports relative to the credentials of
     * the socket creator.  thus, if we want to bind to a privileged
     * port, we should become root before creating the socket.
     */

    if (rlpr_client->proxyhost == 0 && rlpr_client->no_bind == 0) {

	/*
	 * become root, but even if we can't become root (perhaps
	 * because we're not setuid), keep on going anyway, since
	 * some lpd implementations will allow connections from
	 * non-privileged ports.
	 */

	toggle_root();
	if (geteuid() != 0)
	    msg(R_WARNING, 0, "cannot bind to privileged port: lpd may reject");
    }

    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd == -1) {
	if (geteuid() == 0)
	    toggle_root();
	msg(R_ERROR, errno, "socket create for connection to lpd");
	return -1;
    }

    if (geteuid() == 0 && rlpr_client->no_bind == 0) {

	if (bind_try_range(&sin_local, sock_fd, R_LPD_SRC_PORT_LOW,
			   R_LPD_SRC_PORT_HIGH) == 0) {
	    toggle_root();
	    msg(R_FATAL, errno, "privileged bind failed (no ports left?)");
	    return -1;
	}
	toggle_root();
    }

    /*
     * connect to the remote endpoint.  for debugging purposes,
     * grab our local identity too.
     */

    dst_host = rlpr_client->proxyhost ? rlpr_client->proxyhost :
	       rlpr_client->printhost;
    if (init_sockaddr_in(&sin_dst, dst_host, rlpr_client->dst_port) == 0)
	return -1;

    if (connect_timed(sock_fd, &sin_dst, timeout) == -1) {
	msg(R_ERROR, errno, "connect to %s:%hi", dst_host,
	    rlpr_client->dst_port);
	return -1;
    }

    if (getsockname(sock_fd, (struct sockaddr *)&sin_local, &sin_size) == -1) {
	msg(R_ERROR, errno, "getsockname on connection to lpd");
	return -1;
    }

    rlpr_client->src_port = ntohs(sin_local.sin_port);
    msg(R_DEBUG, 0, "connected localhost:%hu -> %s:%hu", rlpr_client->src_port,
	dst_host, rlpr_client->dst_port);

    if (rlpr_client->proxyhost != 0) {

	size_t	printhost_len = strlen(rlpr_client->printhost);

	msg(R_DEBUG, 0, "pointing proxy to %s...", rlpr_client->printhost);

	if (full_write(sock_fd, rlpr_client->printhost, printhost_len, 0)
	    == 0 || full_write(sock_fd, "\n", 1, 0) == 0) {
	    msg(R_ERROR, 0, "unable to send printhost name to proxyhost");
	    return -1;
	}
    }

    return sock_fd;
}