Пример #1
0
/*
 * getaddrinfo_thread() resolves a name, calls Curl_addrinfo6_callback and then
 * exits.
 *
 * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
 * and wait on it.
 */
static unsigned __stdcall getaddrinfo_thread (void *arg)
{
  struct connectdata *conn = (struct connectdata*) arg;
  struct thread_data *td   = (struct thread_data*) conn->async.os_specific;
  struct addrinfo    *res;
  char   service [NI_MAXSERV];
  int    rc;

  *stderr = *td->stderr_file;

  itoa(conn->async.port, service, 10);

  WSASetLastError(conn->async.status = NO_DATA); /* pending status */

  rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);

  if (rc == 0) {
#ifdef DEBUG_THREADING_GETADDRINFO
    dump_addrinfo (conn, res);
#endif
    Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
  }
  else {
    Curl_addrinfo6_callback(conn, (int)WSAGetLastError(), NULL);
    TRACE(("Winsock-error %d, no address\n", conn->async.status));
  }
  return (rc);
  /* An implicit _endthreadex() here */
}
Пример #2
0
/*
 * Curl_getaddrinfo() when built ipv6-enabled (non-threading and
 * non-ares version).
 *
 * Returns name information about the given hostname and port number. If
 * successful, the 'addrinfo' is returned and the forth argument will point to
 * memory we need to free after use. That memory *MUST* be freed with
 * Curl_freeaddrinfo(), nothing else.
 */
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
                                const char *hostname,
                                int port,
                                int *waitp)
{
  struct addrinfo hints;
  Curl_addrinfo *res;
  int error;
  char sbuf[12];
  char *sbufptr = NULL;
  char addrbuf[128];
  int pf;
  struct SessionHandle *data = conn->data;

  *waitp = 0; /* synchronous response only */

  /*
   * Check if a limited name resolve has been requested.
   */
  switch(conn->ip_version) {
  case CURL_IPRESOLVE_V4:
    pf = PF_INET;
    break;
  case CURL_IPRESOLVE_V6:
    pf = PF_INET6;
    break;
  default:
    pf = PF_UNSPEC;
    break;
  }

  if((pf != PF_INET) && !Curl_ipv6works())
    /* the stack seems to be a non-ipv6 one */
    pf = PF_INET;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = pf;
  hints.ai_socktype = conn->socktype;

  if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
     (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
    /* the given address is numerical only, prevent a reverse lookup */
    hints.ai_flags = AI_NUMERICHOST;
  }

  if(port) {
    snprintf(sbuf, sizeof(sbuf), "%d", port);
    sbufptr=sbuf;
  }
  error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
  if(error) {
    infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
    return NULL;
  }

  dump_addrinfo(conn, res);

  return res;
}
Пример #3
0
/*
 * getaddrinfo_thread() resolves a name, calls Curl_addrinfo6_callback and then
 * exits.
 *
 * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
 * and wait on it.
 */
static unsigned __stdcall getaddrinfo_thread (void *arg)
{
  struct connectdata *conn = (struct connectdata*) arg;
  struct thread_data *td   = (struct thread_data*) conn->async.os_specific;
  struct addrinfo    *res;
  char   service [NI_MAXSERV];
  int    rc;

  /* Duplicate the passed mutex handle.
   * This allows us to use it even after the container gets destroyed
   * due to a resolver timeout.
   */
  HANDLE mutex_waiting = NULL;
  HANDLE curr_proc = GetCurrentProcess();

  if (!DuplicateHandle(curr_proc, td->mutex_waiting,
                       curr_proc, &mutex_waiting, 0, FALSE,
                       DUPLICATE_SAME_ACCESS)) {
    /* failed to duplicate the mutex, no point in continuing */
    return -1;
  }

#ifndef _WIN32_WCE
  *stderr = *td->stderr_file;
#endif

  itoa(conn->async.port, service, 10);

  WSASetLastError(conn->async.status = NO_DATA); /* pending status */

  rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);

  /* is the thread initiator still waiting for us ? */
  if (WaitForSingleObject(mutex_waiting, 0) == WAIT_TIMEOUT) {
    /* yes, it is */

    /* Mark that we have obtained the information, and that we are
     * calling back with it.
     */
    SetEvent(td->event_resolved);

    if (rc == 0) {
#ifdef DEBUG_THREADING_GETADDRINFO
      dump_addrinfo (conn, res);
#endif
      rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
    }
    else {
      rc = Curl_addrinfo6_callback(conn, (int)WSAGetLastError(), NULL);
      TRACE(("Winsock-error %d, no address\n", conn->async.status));
    }
  }

  /* clean up */
  CloseHandle(mutex_waiting);

  return (rc);
  /* An implicit _endthreadex() here */
}
Пример #4
0
static int setup_multicast_impl(char * bindAddr, unsigned int nTTL, char * p_multicast_addr, char * p_port, struct mcast_connection * p_mcast_conn)
{
	int rc;
    debug_outputln("%s %4.4u : %s %s %s %3.3u", __FILE__, __LINE__, bindAddr, p_multicast_addr, p_port, nTTL);
	p_mcast_conn->multiAddr_ 	= ResolveAddressWithFlags(p_multicast_addr, p_port, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, AI_PASSIVE);
	if (NULL == p_mcast_conn->multiAddr_)
	{
		debug_outputln("%s %4.4u : %10.10d %8.8x", __FILE__, __LINE__, WSAGetLastError(), WSAGetLastError());
		goto cleanup;
	}
    dump_addrinfo(p_mcast_conn->multiAddr_, __FILE__, __LINE__);
	// Resolve the binding address
	p_mcast_conn->bindAddr_ 	= ResolveAddressWithFlags(bindAddr, p_port, p_mcast_conn->multiAddr_->ai_family, p_mcast_conn->multiAddr_->ai_socktype, p_mcast_conn->multiAddr_->ai_protocol, AI_PASSIVE);
	if (NULL == p_mcast_conn->bindAddr_)
	{
		debug_outputln("%s %4.4u : %10.10d %8.8x", __FILE__, __LINE__, WSAGetLastError(), WSAGetLastError());
		goto cleanup;
	}
    dump_addrinfo(p_mcast_conn->bindAddr_, __FILE__, __LINE__);
	// 
	// Create the socket. In Winsock 1 you don't need any special
	// flags to indicate multicasting.
	//
	p_mcast_conn->socket_ 		= socket(p_mcast_conn->multiAddr_->ai_family, p_mcast_conn->multiAddr_->ai_socktype, p_mcast_conn->multiAddr_->ai_protocol);
	if (p_mcast_conn->socket_ == INVALID_SOCKET)
	{
		debug_outputln("%s %4.4u : %10.10d %8.8x", __FILE__, __LINE__, WSAGetLastError(), WSAGetLastError());
		goto cleanup;
	}
    if (!set_reuse_addr(p_mcast_conn->socket_))
    {
        debug_outputln("%s %4.4u : %10.10d %8.8x", __FILE__, __LINE__, WSAGetLastError(), WSAGetLastError());
        goto cleanup;
    }
	// Join the multicast group if specified
    rc = join_mcast_group_set_ttl(p_mcast_conn->socket_, p_mcast_conn->multiAddr_, p_mcast_conn->bindAddr_, nTTL);
	if (rc == SOCKET_ERROR)
	{
		debug_outputln("%s %4.4u : %10.10d %8.8x", __FILE__, __LINE__, WSAGetLastError(), WSAGetLastError());
		goto cleanup;
	}
    dump_locally_bound_socket(p_mcast_conn->socket_, __FILE__, __LINE__);
	return 1;
cleanup:
	return 0;
}
Пример #5
0
/*
 * getaddrinfo_thread() resolves a name, calls Curl_addrinfo6_callback and then
 * exits.
 *
 * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
 * and wait on it.
 */
static unsigned __stdcall getaddrinfo_thread (void *arg)
{
  struct connectdata *conn = (struct connectdata*) arg;
  struct thread_data *td   = (struct thread_data*) conn->async.os_specific;
  struct addrinfo    *res;
  char   service [NI_MAXSERV];
  int    rc;
  struct addrinfo hints = td->hints;

  /* Duplicate the passed mutex handle.
   * This allows us to use it even after the container gets destroyed
   * due to a resolver timeout.
   */
  struct thread_sync_data tsd = { 0,0,0,NULL };
  if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
    /* thread synchronization data initialization failed */
    return -1;
  }

#ifndef _WIN32_WCE
  *stderr = *td->stderr_file;
#endif

  itoa(conn->async.port, service, 10);

  WSASetLastError(conn->async.status = NO_DATA); /* pending status */

  /* Signaling that we have initialized all copies of data and handles we
     need */
  SetEvent(td->event_thread_started);

  rc = getaddrinfo(tsd.hostname, service, &hints, &res);

  /* is parent thread waiting for us and are we able to access conn members? */
  if (acquire_thread_sync(&tsd)) {
    /* Mark that we have obtained the information, and that we are calling
       back with it. */
    SetEvent(td->event_resolved);

    if (rc == 0) {
#ifdef DEBUG_THREADING_GETADDRINFO
      dump_addrinfo (conn, res);
#endif
      rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
    }
    else {
      rc = Curl_addrinfo6_callback(conn, (int)WSAGetLastError(), NULL);
      TRACE(("Winsock-error %d, no address\n", conn->async.status));
    }
    release_thread_sync(&tsd);
  }

  /* clean up */
  destroy_thread_sync_data(&tsd);

  return (rc);
  /* An implicit _endthreadex() here */
}
Пример #6
0
static int
compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, void *mdata)
{
	int rv;

	if (debug) {
		printf("testing equality of 2 addrinfo structures\n");
	}

	rv = compare_addrinfo_(ai1, ai2);

	if (debug) {
		if (rv == 0)
			printf("equal\n");
		else {
			dump_addrinfo(ai1);
			dump_addrinfo(ai2);
			printf("not equal\n");
		}
	}

	return (rv);
}
Пример #7
0
static int
addrinfo_test_correctness(struct addrinfo *ai, void *mdata)
{
	if (debug) {
		printf("testing correctness with the following data:\n");
		dump_addrinfo(ai);
	}

	if (ai == NULL)
		goto errfin;

	if (!((ai->ai_family >= 0) && (ai->ai_family < AF_MAX)))
		goto errfin;

	if ((ai->ai_socktype != 0) && (ai->ai_socktype != SOCK_STREAM) &&
	    (ai->ai_socktype != SOCK_DGRAM) && (ai->ai_socktype != SOCK_RAW))
		goto errfin;

	if ((ai->ai_protocol != 0) && (ai->ai_protocol != IPPROTO_UDP) &&
	    (ai->ai_protocol != IPPROTO_TCP))
		goto errfin;

	if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0)
		goto errfin;

	if ((ai->ai_addrlen != ai->ai_addr->sa_len) ||
	    (ai->ai_family != ai->ai_addr->sa_family))
		goto errfin;

	if (debug)
		printf("correct\n");

	return (0);
errfin:
	if (debug)
		printf("incorrect\n");

	return (-1);
}
Пример #8
0
void 
set_up_server(char hostname[], char port[], int af)
{ 

  struct addrinfo     hints;
  struct addrinfo     *local_res;
  struct addrinfo     *local_res_temp;

  struct sockaddr_storage     peeraddr;
  netperf_socklen_t                 peeraddr_len = sizeof(peeraddr);
  
  SOCKET server_control;
  int on=1;
  int count;
  int error;
  int not_listening;

#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
  FILE *rd_null_fp;    /* Used to redirect from "/dev/null". */
  FILE *wr_null_fp;    /* Used to redirect to   "/dev/null". */
#endif /* !WIN32 !MPE !__VMS */

  if (debug) {
    fprintf(stderr,
            "set_up_server called with host '%s' port '%s' remfam %d\n",
            hostname,
	    port,
            af);
    fflush(stderr);
  }

  memset(&hints,0,sizeof(hints));
  hints.ai_family = af;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  hints.ai_flags = AI_PASSIVE;

  count = 0;
  do {
    error = getaddrinfo((char *)hostname,
                        (char *)port,
                        &hints,
                        &local_res);
    count += 1;
    if (error == EAI_AGAIN) {
      if (debug) {
        fprintf(stderr,"Sleeping on getaddrinfo EAI_AGAIN\n");
        fflush(stderr);
      }
      sleep(1);
    }
  } while ((error == EAI_AGAIN) && (count <= 5));

  if (error) {
    fprintf(stderr,
	    "set_up_server: could not resolve remote '%s' port '%s' af %d",
	    hostname,
	    port,
	    af);
    fprintf(stderr,"\n\tgetaddrinfo returned %d %s\n",
	    error,
	    gai_strerror(error));
    exit(-1);
  }

  if (debug) {
    dump_addrinfo(stderr, local_res, hostname, port, af);
  }

  not_listening = 1;
  local_res_temp = local_res;

  while((local_res_temp != NULL) && (not_listening)) {

    fprintf(stderr,
	    "Starting netserver at port %s\n",
	    port);

    server_control = socket(local_res_temp->ai_family,SOCK_STREAM,0);

    if (server_control == INVALID_SOCKET) {
      perror("set_up_server could not allocate a socket");
      exit(-1);
    }

    /* happiness and joy, keep going */
    if (setsockopt(server_control, 
		   SOL_SOCKET, 
		   SO_REUSEADDR, 
		   (char *)&on , 
		   sizeof(on)) == SOCKET_ERROR) {
      if (debug) {
	perror("warning: set_up_server could not set SO_REUSEADDR");
      }
    }
    /* still happy and joyful */

    if ((bind (server_control, 
	       local_res_temp->ai_addr, 
	       local_res_temp->ai_addrlen) != SOCKET_ERROR) &&
	(listen (server_control,5) != SOCKET_ERROR))  {
      not_listening = 0;
      break;
    }
    else {
      /* we consider a bind() or listen() failure a transient and try
	 the next address */
      if (debug) {
	perror("warning: set_up_server failed a bind or listen call\n");
      }
      local_res_temp = local_res_temp->ai_next;
      continue;
    }
  }

  if (not_listening) {
    fprintf(stderr,
	    "set_up_server could not establish a listen endpoint for %s port %s with family %s\n",
	    host_name,
	    port,
	    inet_ftos(af));
    fflush(stderr);
    exit(-1);
  }
  else {
    printf("Starting netserver at hostname %s port %s and family %s\n",
	   hostname,
	   port,
	   inet_ftos(af));
  }

  /*
    setpgrp();
    */

#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
  /* Flush the standard I/O file descriptors before forking. */
  fflush (stdin);
  fflush (stdout);
  fflush (stderr);
#if defined(HAVE_FORK)
  switch (fork())
#else
  switch (vfork())
#endif
    {
    case -1:  	
      perror("netperf server error");
      exit(1);
      
    case 0:	
      /* Redirect stdin from "/dev/null". */
      rd_null_fp = fopen ("/dev/null", "r");
      if (rd_null_fp == NULL)
      {
	perror ("netserver: opening for reading: /dev/null");
	exit   (1);
      }
      if (close (STDIN_FILENO) == -1)
      {
	perror ("netserver: closing stdin file descriptor");
	exit   (1);
      }
      if (dup (fileno (rd_null_fp)) == -1)
      {
	perror ("netserver: duplicate /dev/null read file descr. to stdin");
	exit   (1);
      }

      /* Redirect stdout to the debug write file descriptor. */
      if (close (STDOUT_FILENO) == -1)
      {
	perror ("netserver: closing stdout file descriptor");
	exit   (1);
      }
      if (dup (fileno (where))  == -1)
      {
	perror ("netserver: duplicate the debug write file descr. to stdout");
	exit   (1);
      }

      /* Redirect stderr to "/dev/null". */
      wr_null_fp = fopen ("/dev/null", "w");
      if (wr_null_fp == NULL)
      {
	perror ("netserver: opening for writing: /dev/null");
	exit   (1);
      }
      if (close (STDERR_FILENO) == -1)
      {
	perror ("netserver: closing stderr file descriptor");
	exit   (1);
      }
      if (dup (fileno (wr_null_fp))  == -1)
      {
	perror ("netserver: dupicate /dev/null write file descr. to stderr");
	exit   (1);
      }
 
#ifndef NO_SETSID
      setsid();
#else
      setpgrp();
#endif /* NO_SETSID */

 /* some OS's have SIGCLD defined as SIGCHLD */
#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif /* SIGCLD */

      signal(SIGCLD, SIG_IGN);
      
#endif /* !WIN32 !MPE !__VMS */

      for (;;)
	{
	  if ((server_sock=accept(server_control,
				  (struct sockaddr *)&peeraddr,
				  &peeraddr_len)) == INVALID_SOCKET)
	    {
	      printf("server_control: accept failed errno %d\n",errno);
	      exit(1);
	    }
#if defined(MPE) || defined(__VMS)
	  /*
	   * Since we cannot fork this process , we cant fire any threads
	   * as they all share the same global data . So we better allow
	   * one request at at time 
	   */
	  process_requests() ;
#elif WIN32
		{
			BOOL b;
			char cmdline[80];
			PROCESS_INFORMATION pi;
			STARTUPINFO si;
			int i;

			memset(&si, 0 , sizeof(STARTUPINFO));
			si.cb = sizeof(STARTUPINFO);

			/* Pass the server_sock as stdin for the new process. */
			/* Hopefully this will continue to be created with the OBJ_INHERIT attribute. */
			si.hStdInput = (HANDLE)server_sock;
			si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
			si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
			si.dwFlags = STARTF_USESTDHANDLES;

			/* Build cmdline for child process */
			strcpy(cmdline, program);
			if (verbosity > 1) {
				snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -v %d", verbosity);
			}
			for (i=0; i < debug; i++) {
				snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -d");
			}
			snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -I %x", (int)(UINT_PTR)server_sock);
			snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)server_control);
			snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)where);

			b = CreateProcess(NULL,	 /* Application Name */
					cmdline,
					NULL,    /* Process security attributes */
					NULL,    /* Thread security attributes */
					TRUE,    /* Inherit handles */
					0,	   /* Creation flags  PROCESS_QUERY_INFORMATION,  */
					NULL,    /* Enviornment */
					NULL,    /* Current directory */
					&si,	   /* StartupInfo */
					&pi);
			if (!b)
			{
				perror("CreateProcessfailure: ");
				exit(1);
			}

			/* We don't need the thread or process handles any more; let them */
			/* go away on their own timeframe. */

			CloseHandle(pi.hThread);
			CloseHandle(pi.hProcess);

			/* And close the server_sock since the child will own it. */

			close(server_sock);
		}
#else
      signal(SIGCLD, SIG_IGN);
#if defined(HAVE_FORK)
	  switch (fork())
#else
	  switch (vfork())
#endif
	    {
	    case -1:
	      /* something went wrong */
	      exit(1);
	    case 0:
	      /* we are the child process */
	      close(server_control);
	      process_requests();
	      exit(0);
	      break;
	    default:
	      /* we are the parent process */
	      close(server_sock);
	      /* we should try to "reap" some of our children. on some */
	      /* systems they are being left as defunct processes. we */
	      /* will call waitpid, looking for any child process, */
	      /* with the WNOHANG feature. when waitpid return a zero, */
	      /* we have reaped all the children there are to reap at */
	      /* the moment, so it is time to move on. raj 12/94 */
#ifndef DONT_WAIT
#ifdef NO_SETSID
	      /* Only call "waitpid()" if "setsid()" is not used. */
	      while(waitpid(-1, NULL, WNOHANG) > 0) { }
#endif /* NO_SETSID */
#endif /* DONT_WAIT */
	      break;
	    }
#endif /* !WIN32 !MPE !__VMS */  
	} /*for*/
#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
      break; /*case 0*/
      
    default: 
      exit (0);
      
    }
#endif /* !WIN32 !MPE !__VMS */  
}
void
create_listens(char hostname[], char port[], int af) {

  struct addrinfo hints;
  struct addrinfo *local_res;
  struct addrinfo *local_res_temp;
  int count, error;
  int on = 1;
  SOCKET temp_socket;
  struct listen_elt *temp_elt;

  if (debug) {
    fprintf(stderr,
	    "%s: called with host '%s' port '%s' family %s(%d)\n",
	    __FUNCTION__,
            hostname,
	    port,
	    inet_ftos(af),
            af);
    fflush(stderr);
  }
 memset(&hints,0,sizeof(hints));
  hints.ai_family = af;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  hints.ai_flags = AI_PASSIVE;

  count = 0;
  do {
    error = getaddrinfo((char *)hostname,
                        (char *)port,
                        &hints,
                        &local_res);
    count += 1;
    if (error == EAI_AGAIN) {
      if (debug) {
        fprintf(stderr,
		"%s: Sleeping on getaddrinfo EAI_AGAIN\n",
		__FUNCTION__);
        fflush(stderr);
      }
      sleep(1);
    }
  } while ((error == EAI_AGAIN) && (count <= 5));

  if (error) {
    if (debug) {

      fprintf(stderr,
	      "%s: could not resolve remote '%s' port '%s' af %d\n"
	      "\tgetaddrinfo returned %s (%d)\n",
	      __FUNCTION__,
	      hostname,
	      port,
	      af,
	      gai_strerror(error),
	      error);

    }
    return;
  }

  if (debug) {
    dump_addrinfo(stderr, local_res, hostname, port, af);
  }

  local_res_temp = local_res;

  while (local_res_temp != NULL) {

    temp_socket = socket(local_res_temp->ai_family,SOCK_STREAM,0);

    if (temp_socket == INVALID_SOCKET) {
      if (debug) {
	fprintf(stderr,
		"%s could not allocate a socket: %s (errno %d)\n",
		__FUNCTION__,
		strerror(errno),
		errno);
	fflush(stderr);
      }
      local_res_temp = local_res_temp->ai_next;
      continue;
    }

    /* happiness and joy, keep going */
    if (setsockopt(temp_socket,
		   SOL_SOCKET,
		   SO_REUSEADDR,
		   (char *)&on ,
		   sizeof(on)) == SOCKET_ERROR) {
      if (debug) {
	fprintf(stderr,
		"%s: warning: could not set SO_REUSEADDR: %s (errno %d)\n",
		__FUNCTION__,
		strerror(errno),
		errno);
	fflush(stderr);
      }
    }
    /* still happy and joyful */

    if ((bind(temp_socket,
	      local_res_temp->ai_addr,
	      local_res_temp->ai_addrlen) != SOCKET_ERROR) &&
	(listen(temp_socket,1024) != SOCKET_ERROR))  {

      /* OK, now add to the list */
      temp_elt = (struct listen_elt *)malloc(sizeof(struct listen_elt));
      if (temp_elt) {
	temp_elt->fd = temp_socket;
	if (listen_list) {
	  temp_elt->next = listen_list;
	}
	else {
	  temp_elt->next = NULL;
	}
	listen_list = temp_elt;
      }
      else {
	fprintf(stderr,
		"%s: could not malloc a listen_elt\n",
		__FUNCTION__);
	fflush(stderr);
	exit(1);
      }
    }
    else {
      /* we consider a bind() or listen() failure a transient and try
	 the next address */
      if (debug) {
	fprintf(stderr,
		"%s: warning: bind or listen call failure: %s (errno %d)\n",
		__FUNCTION__,
		strerror(errno),
		errno);
	fflush(stderr);
      }
      close(temp_socket);
    }
    local_res_temp = local_res_temp->ai_next;
  }

}
Пример #10
0
/*
 * Curl_getaddrinfo() when built ipv6-enabled (non-threading and
 * non-ares version).
 *
 * Returns name information about the given hostname and port number. If
 * successful, the 'addrinfo' is returned and the forth argument will point to
 * memory we need to free after use. That memory *MUST* be freed with
 * Curl_freeaddrinfo(), nothing else.
 */
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
								const char *hostname,
								int port,
								int *waitp)
{
	struct addrinfo hints;
	Curl_addrinfo *res;
	int error;
	char sbuf[NI_MAXSERV];
	char *sbufptr = NULL;
	char addrbuf[128];
	int pf;
	struct SessionHandle *data = conn->data;

	*waitp = 0; /* don't wait, we have the response now */

	/*
	 * Check if a limited name resolve has been requested.
	 */
	switch (data->set.ip_version)
	{
	case CURL_IPRESOLVE_V4:
		pf = PF_INET;
		break;
	case CURL_IPRESOLVE_V6:
		pf = PF_INET6;
		break;
	default:
		pf = PF_UNSPEC;
		break;
	}

	if (pf != PF_INET)
	{
		/* see if we have an IPv6 stack */
		curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
		if (s == CURL_SOCKET_BAD)
		{
			/* Some non-IPv6 stacks have been found to make very slow name resolves
			 * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
			 * the stack seems to be a non-ipv6 one. */

			pf = PF_INET;
		}
		else
		{
			/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
			 * possible checks. And close the socket again.
			 */
			sclose(s);
		}
	}

	MEMSET(&hints, 0, sizeof(hints));
	hints.ai_family = pf;
	hints.ai_socktype = conn->socktype;

	if ((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
			(1 == Curl_inet_pton(AF_INET6, hostname, addrbuf)))
	{
		/* the given address is numerical only, prevent a reverse lookup */
		hints.ai_flags = AI_NUMERICHOST;
	}
#ifdef HAVE_GSSAPI
	if (conn->data->set.krb)
		/* if krb is used, we (might) need the canonical host name */
		hints.ai_flags |= AI_CANONNAME;
#endif

	if (port)
	{
		snprintf(sbuf, sizeof(sbuf), "%d", port);
		sbufptr = sbuf;
	}
	error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
	if (error)
	{
		infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
		return NULL;
	}

	dump_addrinfo(conn, res);

	return res;
}
Пример #11
0
int main(int argc, char ** argv)
{
    int result;
    fd_set read_fd;
    struct addrinfo * p_group_address;
    struct addrinfo * p_iface_address;
    struct addrinfo a_hints;
    memset(&a_hints, 0, sizeof(a_hints));
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
    assert(s>=0); 
    a_hints.ai_family = AF_INET;
    a_hints.ai_protocol = 0;
    a_hints.ai_socktype = SOCK_DGRAM;
    result = getaddrinfo(MCAST_GROUP_ADDRESS, MCAST_PORT_NUMBER, &a_hints, &p_group_address);
    assert(0 == result);
    dump_addrinfo(stderr, p_group_address);
    a_hints.ai_flags = AI_PASSIVE;
    result = getaddrinfo(INTEFACE_BIND_ADDRESS, MCAST_PORT_NUMBER, &a_hints, &p_iface_address);
    assert(0 == result);
    result = set_reuse_addr(s);
    assert(0 == result);
    dump_addrinfo(stderr, p_iface_address);
    result = join_mcast_group_set_ttl(s, p_group_address, p_iface_address, DEFAULT_TTL);
    assert(0 == result);
    {
        struct sigaction query_action;
        memset(&query_action, 0, sizeof(query_action));
        query_action.sa_handler = &sigint_handle;
        if (sigaction (SIGINT, NULL, &query_action) < 0)
            exit(EXIT_FAILURE);
            /* sigaction returns -1 in case of error. */
    }
    while (!g_stop_processing)
    {
        ssize_t bytes_read;
        struct sockaddr recv_from_data;
        socklen_t recv_from_length = sizeof(recv_from_data);
        struct timeval select_timeout = { 1, 0 };
        FD_ZERO(&read_fd);
        FD_SET(s, &read_fd);
        result = select(s+1, &read_fd, NULL, NULL, &select_timeout); 
        switch (result)
        {
            case -1:
                break;
            case 0: 
                fprintf(stdout, "%4.4u %s : Timeout\n", __LINE__, __func__);
                break;
            default:
                if (FD_ISSET(s, &read_fd))
                {
                    bytes_read = recvfrom(s, 
                        &g_input_buffer[0], 
                        sizeof(g_input_buffer), 
                        0, 
                        &recv_from_data, 
                        &recv_from_length);  
                    if (bytes_read >= 0)
                    {
                        fprintf(stdout, "%4.4u %s : %u %s %u %2.2hhx %2.2hhx..\n", __LINE__, __func__, bytes_read, 
                                inet_ntoa((((struct sockaddr_in *)&recv_from_data)->sin_addr)),
                                ntohs((((struct sockaddr_in *)&recv_from_data)->sin_port)),
                                g_input_buffer[0], 
                                g_input_buffer[1]
                               );
                    }
                    else
                    {
                        fprintf(stderr, "%4.4u %s : %d %s\n", __LINE__, __func__, errno, strerror(errno));
                    }
                }
                break;
        }
    }
    return 0;
}
Пример #12
0
SOCKET
establish_listen(char *hostname, char *service, int af, netperf_socklen_t *addrlenp)
{
  SOCKET sockfd;
  int error;
  int count;
  int len = *addrlenp;
  int one = 1;
  struct addrinfo hints, *res, *res_temp;

  if (debug) {
    fprintf(stderr,
	    "establish_listen: host '%s' service '%s' af %d socklen %d\n",
	    hostname ? hostname : "n/a",
	    service ? service : "n/a",
	    af,
	    len);
    fflush(stderr);
  }

  memset(&hints, 0, sizeof(hints));
  hints.ai_family   = af;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags    = AI_PASSIVE;

  count = 0;
  do {
    error = getaddrinfo(hostname,
			service,
			&hints,
			&res);
    count += 1;
    if (error == EAI_AGAIN) {
      if (debug) {
        fprintf(stderr,"Sleeping on getaddrinfo EAI_AGAIN\n");
        fflush(stderr);
      }
      usleep(1000);
    }
  } while ((error == EAI_AGAIN) && (count <= 5));

  if (error) {
    fprintf(stderr,
            "establish_listen: could not resolve host '%s' service '%s'\n",
            hostname,service);
    fprintf(stderr,"\tgetaddrinfo returned %d %s\n",
            error,gai_strerror(error));
    fflush(stderr);
    return(-1);
  }


  if (debug) {
    dump_addrinfo(stderr, res, hostname,
                  service, AF_UNSPEC);
  }

  res_temp = res;

  do {

    sockfd = socket(res_temp->ai_family,
                    res_temp->ai_socktype,
                    res_temp->ai_protocol);
    if (sockfd == INVALID_SOCKET) {
      if (debug) {
        fprintf(stderr,"establish_listen: socket error trying next one\n");
        fflush(stderr);
      }
      continue;
    }
    /* The Windows DDK compiler is quite picky about pointers so we
       cast one as a void to placate it. */
    if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(void *)&one,sizeof(one)) == 
	SOCKET_ERROR) {
      fprintf(stderr,"establish_listen: SO_REUSEADDR failed\n");
      fflush(stderr);
    }
    if (bind(sockfd, res_temp->ai_addr, res_temp->ai_addrlen) == 0) {
      break;
    }
    fprintf(stderr,"establish_listen: bind error close and try next\n");
    fflush(stderr);
    CLOSE_SOCKET(sockfd);
  } while ( (res_temp = res_temp->ai_next) != NULL );

  if (res_temp == NULL) {
    fprintf(stderr,"establish_listen: allocate server socket failed\n");
    fflush(stderr);
    sockfd = -1;
  } else if (listen (sockfd,20) == -1) {
    fprintf(stderr,"establish_listen: setting the listen backlog failed\n");
    fflush(stderr);
    CLOSE_SOCKET(sockfd);
    sockfd = -1;
  } else {
    if (addrlenp) *addrlenp = res_temp->ai_addrlen;
  }

  fcntl(sockfd,F_SETFL, O_NONBLOCK);

  freeaddrinfo(res);

  return (sockfd);

}