/* * Opens a TCP socket and returns the descriptor * Returns: * socket descriptor, or * -1 on error */ int makeSocket(const char *host) { int sock; /* Socket descriptor */ int ret; int port; char *p; __pmFdSet wfds; struct timeval tv; struct timeval *ptv; __pmSockAddr *myaddr; __pmHostEnt *servInfo; void *enumIx; int flags = 0; /* Check for port number specified in URL */ p = strchr(host, ':'); if(p) { port = atoi(p + 1); *p = '\0'; } else port = PORT_NUMBER; servInfo = __pmGetAddrInfo(host); if(servInfo == NULL) { errorSource = H_ERRNO; return -1; } sock = -1; enumIx = NULL; for (myaddr = __pmHostEntGetSockAddr(servInfo, &enumIx); myaddr != NULL; myaddr = __pmHostEntGetSockAddr(servInfo, &enumIx)) { /* Create a socket */ if (__pmSockAddrIsInet(myaddr)) sock = __pmCreateSocket(); else if (__pmSockAddrIsIPv6(myaddr)) sock = __pmCreateIPv6Socket(); else sock = -1; if (sock < 0) { __pmSockAddrFree(myaddr); continue; /* Try the next address */ } /* Attempt to connect */ flags = __pmConnectTo(sock, myaddr, port); __pmSockAddrFree(myaddr); if (flags < 0) { /* * Mark failure in case we fall out the end of the loop * and try next address. sock has been closed in __pmConnectTo(). */ sock = -1; continue; } /* FNDELAY and we're in progress - wait on select */ tv.tv_sec = timeout; tv.tv_usec = 0; ptv = (tv.tv_sec || tv.tv_usec) ? &tv : NULL; __pmFD_ZERO(&wfds); __pmFD_SET(sock, &wfds); ret = __pmSelectWrite(sock+1, &wfds, ptv); /* Was the connection successful? */ if (ret < 0) { if (oserror() == EINTR) return _makeSocketErr(sock, FETCHER_ERROR, HF_CONNECTTIMEOUT); return _makeSocketErr(sock, ERRNO, 0); } ret = __pmConnectCheckError(sock); if (ret == 0) break; /* Unsuccessful connection. */ __pmCloseSocket(sock); sock = -1; } /* loop over addresses */ __pmHostEntFree(servInfo); if(sock == -1) { errorSource = ERRNO; return -1; } sock = __pmConnectRestoreFlags(sock, flags); if(sock < 0) { errorSource = ERRNO; return -1; } return sock; }
static int http_client_connectunix(const char *path, struct timeval *timeout) { #if defined(HAVE_STRUCT_SOCKADDR_UN) __pmFdSet wfds; __pmSockAddr *myAddr; struct timeval stv, *ptv; int fdFlags = 0; int fd = -1; int sts; int rc; /* Initialize the socket address. */ if ((myAddr = __pmSockAddrAlloc()) == NULL) { if (pmDebug & DBG_TRACE_HTTP) fprintf(stderr, "HTTP connect unix(%s): out of memory\n", path); return -ENOMEM; } __pmSockAddrSetFamily(myAddr, AF_UNIX); __pmSockAddrSetPath(myAddr, path); if ((fd = __pmCreateUnixSocket()) < 0) { if (pmDebug & DBG_TRACE_HTTP) { char errmsg[PM_MAXERRMSGLEN]; fprintf(stderr, "HTTP connect unix(%s) unable to create socket: %s\n", path, osstrerror_r(errmsg, sizeof(errmsg))); } __pmSockAddrFree(myAddr); return fd; } /* Attempt to connect */ fdFlags = __pmConnectTo(fd, myAddr, -1); __pmSockAddrFree(myAddr); if (fdFlags < 0) { __pmCloseSocket(fd); return -ECONNREFUSED; } /* FNDELAY and we're in progress - wait on select */ stv = *timeout; ptv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL; __pmFD_ZERO(&wfds); __pmFD_SET(fd, &wfds); sts = 0; if ((rc = __pmSelectWrite(fd+1, &wfds, ptv)) == 1) sts = __pmConnectCheckError(fd); else if (rc == 0) sts = ETIMEDOUT; else sts = (rc < 0) ? neterror() : EINVAL; if (sts != 0) { /* Unsuccessful connection. */ if (sts == ENOENT) sts = ECONNREFUSED; __pmCloseSocket(fd); fd = -sts; } if (fd < 0) return fd; /* * If we're here, it means we have a valid connection; restore the * flags and make sure this file descriptor is closed if exec() is * called */ return __pmConnectRestoreFlags(fd, fdFlags); #else if (pmDebug & DBG_TRACE_HTTP) __pmNotifyErr(LOG_ERR, "HTTP connect unix(%s) not supported\n", path); return -EOPNOTSUPP; #endif }
static int http_client_connectto(const char *host, int port, struct timeval *timeout) { struct timeval stv, *ptv; __pmHostEnt *servInfo; __pmSockAddr *myAddr; __pmFdSet readyFds, allFds; void *enumIx; int fdFlags[FD_SETSIZE]; int i, fd, sts, maxFd; if ((servInfo = __pmGetAddrInfo(host)) == NULL) { if (pmDebug & DBG_TRACE_HTTP) fprintf(stderr, "HTTP connect(%s, %d): hosterror=%d, ``%s''\n", host, port, hosterror(), hoststrerror()); return -EHOSTUNREACH; } /* * We want to respect the connect timeout that has been configured, but we * may have more than one address to try. Do this by creating a socket for * each address and then using __pmSelectWrite() to wait for one of them to * respond. That way, the timeout is applied to all of the addresses * simultaneously. First, create the sockets, add them to the fd set and * try to establish connectections. */ __pmFD_ZERO(&allFds); maxFd = -1; enumIx = NULL; for (myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx); myAddr != NULL; myAddr = __pmHostEntGetSockAddr(servInfo, &enumIx)) { /* Create a socket */ if (__pmSockAddrIsInet(myAddr)) fd = __pmCreateSocket(); else if (__pmSockAddrIsIPv6(myAddr)) fd = __pmCreateIPv6Socket(); else { if (pmDebug & DBG_TRACE_HTTP) fprintf(stderr, "HTTP connect(%s, %d): bad address family %d\n", host, port, __pmSockAddrGetFamily(myAddr)); fd = -EINVAL; } if (fd < 0) { __pmSockAddrFree(myAddr); continue; /* Try the next address */ } /* Attempt to connect */ fdFlags[fd] = __pmConnectTo(fd, myAddr, port); __pmSockAddrFree(myAddr); if (fdFlags[fd] < 0) { /* * Mark failure in case we fall out the end of the loop * and try next address */ __pmCloseSocket(fd); continue; } /* Add it to the fd set. */ __pmFD_SET(fd, &allFds); if (fd > maxFd) maxFd = fd; } __pmHostEntFree(servInfo); /* If we were unable to open any sockets, then give up. */ if (maxFd == -1) return -ECONNREFUSED; /* FNDELAY and we're in progress - wait on select */ __pmFD_COPY(&readyFds, &allFds); stv = *timeout; ptv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL; sts = __pmSelectWrite(maxFd+1, &readyFds, ptv); /* Figure out what happened. */ if (sts == 0) fd = -ETIMEDOUT; else if (sts < 0) fd = -neterror(); else { /* Scan fd set, find first successfully connected socket (if any). */ fd = -EINVAL; for (i = 0; i <= maxFd; ++i) { if (__pmFD_ISSET(i, &readyFds)) { /* Successful connection? */ sts = __pmConnectCheckError(i); if (sts == 0) { fd = i; break; } fd = -sts; } } } /* Clean up the unused fds. */ for (i = 0; i <= maxFd; ++i) { if (i != fd && __pmFD_ISSET(i, &allFds)) __pmCloseSocket(i); } if (fd < 0) return fd; /* * If we're here, it means we have a valid connection; restore the * flags and make sure this file descriptor is closed if exec() is * called */ return __pmConnectRestoreFlags(fd, fdFlags[fd]); }
static int stomp_connect(const char *hostname, int port) { __pmSockAddr *myaddr; __pmHostEnt *servinfo; void *enumIx; struct timeval tv; struct timeval *ptv; __pmFdSet wfds; int ret; int flags = 0; if ((servinfo = __pmGetAddrInfo(hostname)) == NULL) return -1; fd = -1; enumIx = NULL; for (myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx); myaddr != NULL; myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx)) { /* Create a socket */ if (__pmSockAddrIsInet(myaddr)) fd = __pmCreateSocket(); else if (__pmSockAddrIsIPv6(myaddr)) fd = __pmCreateIPv6Socket(); else fd = -1; if (fd < 0) { __pmSockAddrFree(myaddr); continue; /* Try the next address */ } /* Attempt to connect */ flags = __pmConnectTo(fd, myaddr, port); __pmSockAddrFree(myaddr); if (flags < 0) { /* * Mark failure in case we fall out the end of the loop * and try next address. fd has been closed in __pmConnectTo(). */ fd = -1; continue; } /* FNDELAY and we're in progress - wait on select */ tv.tv_sec = timeout; tv.tv_usec = 0; ptv = (tv.tv_sec || tv.tv_usec) ? &tv : NULL; __pmFD_ZERO(&wfds); __pmFD_SET(fd, &wfds); ret = __pmSelectWrite(fd+1, &wfds, ptv); /* Was the connection successful? */ if (ret <= 0) { if (oserror() == EINTR) return -2; continue; } ret = __pmConnectCheckError(fd); if (ret == 0) break; /* Unsuccessful connection. */ __pmCloseSocket(fd); fd = -1; } /* loop over addresses */ __pmHostEntFree(servinfo); if(fd == -1) return -4; fd = __pmConnectRestoreFlags(fd, flags); if(fd < 0) return -5; return fd; }
int conn_cisco(cisco_t * cp) { __pmFdSet wfds; __pmSockAddr *myaddr; void *enumIx; int flags = 0; int fd; int ret; fd = -1; enumIx = NULL; for (myaddr = __pmHostEntGetSockAddr(cp->hostinfo, &enumIx); myaddr != NULL; myaddr = __pmHostEntGetSockAddr(cp->hostinfo, &enumIx)) { /* Create a socket */ if (__pmSockAddrIsInet(myaddr)) fd = __pmCreateSocket(); else if (__pmSockAddrIsIPv6(myaddr)) fd = __pmCreateIPv6Socket(); else fd = -1; if (fd < 0) { __pmSockAddrFree(myaddr); continue; /* Try the next address */ } /* Attempt to connect */ flags = __pmConnectTo(fd, myaddr, cp->port); __pmSockAddrFree(myaddr); if (flags < 0) { /* * Mark failure in case we fall out the end of the loop * and try next address. fd has been closed in __pmConnectTo(). */ setoserror(ECONNREFUSED); fd = -1; continue; } /* FNDELAY and we're in progress - wait on select */ __pmFD_ZERO(&wfds); __pmFD_SET(fd, &wfds); ret = __pmSelectWrite(fd+1, &wfds, NULL); /* Was the connection successful? */ if (ret == 0) setoserror(ETIMEDOUT); else if (ret > 0) { ret = __pmConnectCheckError(fd); if (ret == 0) break; setoserror(ret); } /* Unsuccessful connection. */ __pmCloseSocket(fd); fd = -1; } /* loop over addresses */ if (fd == -1) { fprintf(stderr, "conn_cisco(%s): connect: %s\n", cp->host, netstrerror()); return -1; } fd = __pmConnectRestoreFlags(fd, flags); if (fd < 0) { fprintf(stderr, "conn_cisco(%s): setsockopt: %s\n", cp->host, netstrerror()); return -1; } return fd; }
static int _pmauxtraceconnect(void) { int port = TRACE_PORT; char hostname[MAXHOSTNAMELEN]; struct timeval timeout = { 3, 0 }; /* default 3 secs */ __pmSockAddr *myaddr; __pmHostEnt *servinfo; void *enumIx; #ifndef IS_MINGW struct itimerval _pmolditimer; void (*old_handler)(int foo); #endif int rc, sts; int flags = 0; char *sptr, *endptr, *endnum; struct timeval canwait = { 5, 000000 }; struct timeval stv; struct timeval *pstv; __pmFdSet wfds; #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_NOAGENT) { fprintf(stderr, "_pmtraceconnect: connecting to PMDA (skipped)\n"); return 0; } else if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, "_pmtraceconnect: connecting to PMDA ...\n"); #endif /* * get optional stuff from environment ... * PCP_TRACE_HOST, PCP_TRACE_PORT, PCP_TRACE_TIMEOUT, and * PCP_TRACE_NOAGENT */ if ((sptr = getenv(TRACE_ENV_HOST)) != NULL) strcpy(hostname, sptr); else { (void)gethostname(hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN-1] = '\0'; } if ((sptr = getenv(TRACE_ENV_PORT)) != NULL) { port = (int)strtol(sptr, &endnum, 0); if (*endnum != '\0' || port < 0) { fprintf(stderr, "trace warning: bad PCP_TRACE_PORT ignored."); port = TRACE_PORT; } } if ((sptr = getenv(TRACE_ENV_TIMEOUT)) != NULL) { double timesec = strtod(sptr, &endptr); if (*endptr != '\0' || timesec < 0.0) fprintf(stderr, "trace warning: bogus PCP_TRACE_TIMEOUT."); else { timeout.tv_sec = (time_t)timesec; timeout.tv_usec = (int)((timesec - (double)timeout.tv_sec)*1000000); } } if (getenv(TRACE_ENV_NOAGENT) != NULL) __pmstate |= PMTRACE_STATE_NOAGENT; if ((servinfo = __pmGetAddrInfo(hostname)) == NULL) { #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, "_pmtraceconnect(__pmGetAddrInfo(hostname=%s): " "hosterror=%d, ``%s''\n", hostname, hosterror(), hoststrerror()); #endif return -EHOSTUNREACH; } /* Try each address in turn until one connects. */ sts = EHOSTUNREACH; __pmfd = -1; enumIx = NULL; for (myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx); myaddr != NULL; myaddr = __pmHostEntGetSockAddr(servinfo, &enumIx)) { /* Create a socket */ if (__pmSockAddrIsInet(myaddr)) __pmfd = __pmCreateSocket(); else if (__pmSockAddrIsIPv6(myaddr)) __pmfd = __pmCreateIPv6Socket(); else { fprintf(stderr, "_pmtraceconnect(invalid address family): %d\n", __pmSockAddrGetFamily(myaddr)); } if (__pmfd < 0) { sts = neterror(); __pmSockAddrFree(myaddr); continue; /* Try the next address */ } /* Set the port. */ __pmSockAddrSetPort(myaddr, port); #ifndef IS_MINGW /* arm interval timer */ _pmmyitimer.it_value.tv_sec = timeout.tv_sec; _pmmyitimer.it_value.tv_usec = timeout.tv_usec; _pmmyitimer.it_interval.tv_sec = 0; _pmmyitimer.it_interval.tv_usec = 0; old_handler = signal(SIGALRM, _pmtracealarm); setitimer(ITIMER_REAL, &_pmmyitimer, &_pmolditimer); #endif #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) { char *name = __pmHostEntGetName (servinfo); fprintf(stderr, "_pmtraceconnect: PMDA host=%s port=%d timeout=%d" "secs\n", name == NULL ? "unknown" : name, port, (int)timeout.tv_sec); if (name != NULL) free(name); } #endif /* Attempt to connect */ flags = __pmConnectTo(__pmfd, myaddr, port); __pmSockAddrFree(myaddr); if (flags < 0) { /* * Mark failure in case we fall out the end of the loop * and try next address. __pmfd has been closed in __pmConnectTo(). */ sts = -flags; __pmfd = -1; continue; } /* FNDELAY and we're in progress - wait on select */ stv = canwait; pstv = (stv.tv_sec || stv.tv_usec) ? &stv : NULL; __pmFD_ZERO(&wfds); __pmFD_SET(__pmfd, &wfds); if ((rc = __pmSelectWrite(__pmfd+1, &wfds, pstv)) == 1) { sts = __pmConnectCheckError(__pmfd); } else if (rc == 0) { sts = ETIMEDOUT; } else { sts = (rc < 0) ? neterror() : EINVAL; } #ifndef IS_MINGW /* re-arm interval timer */ setitimer(ITIMER_REAL, &off_itimer, &_pmmyitimer); signal(SIGALRM, old_handler); if (_pmolditimer.it_value.tv_sec != 0 && _pmolditimer.it_value.tv_usec != 0) { _pmolditimer.it_value.tv_usec -= timeout.tv_usec - _pmmyitimer.it_value.tv_usec; while (_pmolditimer.it_value.tv_usec < 0) { _pmolditimer.it_value.tv_usec += 1000000; _pmolditimer.it_value.tv_sec--; } while (_pmolditimer.it_value.tv_usec > 1000000) { _pmolditimer.it_value.tv_usec -= 1000000; _pmolditimer.it_value.tv_sec++; } _pmolditimer.it_value.tv_sec -= timeout.tv_sec - _pmmyitimer.it_value.tv_sec; if (_pmolditimer.it_value.tv_sec < 0) { /* missed the user's itimer, pretend there is 1 msec to go! */ _pmolditimer.it_value.tv_sec = 0; _pmolditimer.it_value.tv_usec = 1000; } setitimer(ITIMER_REAL, &_pmolditimer, &_pmmyitimer); } #endif /* Was the connection successful? */ if (sts == 0) break; /* Unsuccessful connection. */ __pmCloseSocket(__pmfd); __pmfd = -1; } /* loop over addresses */ __pmHostEntFree(servinfo); /* Was the connection successful? */ if (__pmfd < 0) { #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, "_pmtraceconnect(socket failed): %s\n", netstrerror()); #endif return -sts; } _pmtimedout = 0; /* Restore the original file status flags. */ if (__pmSetFileStatusFlags(__pmfd, flags) < 0) { #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, ":_pmtraceconnect: cannot restore file status flags\n"); #endif return -oserror(); } /* make sure this file descriptor is closed if exec() is called */ if ((flags = __pmGetFileDescriptorFlags(__pmfd)) != -1) sts = __pmSetFileDescriptorFlags(__pmfd, flags | FD_CLOEXEC); else sts = -1; if (sts == -1) return -oserror(); if (__pmtraceprotocol(TRACE_PROTOCOL_QUERY) == TRACE_PROTOCOL_ASYNC) { /* in the asynchronoous protocol - ensure no delay after close */ if ((flags = __pmGetFileStatusFlags(__pmfd)) != -1) sts = __pmSetFileStatusFlags(__pmfd, flags | FNDELAY); else sts = -1; if (sts == -1) return -oserror(); #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, "_pmtraceconnect: async protocol setup complete\n"); #endif } else #ifdef PMTRACE_DEBUG if (__pmstate & PMTRACE_STATE_COMMS) fprintf(stderr, "_pmtraceconnect: sync protocol setup complete\n"); #endif /* trace PMDA sends an ACK on successful connect */ sts = _pmtracegetack(sts, 0); return sts; }