/* * 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 */ }
/* * 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; }
/* * 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 */ }
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; }
/* * 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 */ }
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); }
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); }
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; } }
/* * 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; }
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; }
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); }