int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, char *tmp,char *hst) { int sock; size_t len; char *s; struct protoent *pt = getprotobyname ("tcp"); struct sockaddr *sadr = ip_sockaddr (family,adr,adrlen,port,&len); sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr)); mm_log (tmp,NIL); /* get a TCP stream */ if ((sock = socket (sadr->sa_family,SOCK_STREAM,pt ? pt->p_proto : 0)) == INVALID_SOCKET) sprintf (tmp,"Unable to create TCP socket (%d)",WSAGetLastError ()); else { wsa_sock_open++; /* count this socket as open */ /* open connection */ if (connect (sock,sadr,len) == SOCKET_ERROR) { switch (WSAGetLastError ()) { case WSAECONNREFUSED: s = "Refused"; break; case WSAENOBUFS: s = "Insufficient system resources"; break; case WSAETIMEDOUT: s = "Timed out"; break; case WSAEHOSTUNREACH: s = "Host unreachable"; break; default: s = "Unknown error"; break; } sprintf (tmp,"Can't connect to %.80s,%ld: %s (%d)",hst,port,s, WSAGetLastError ()); tcp_abort (&sock); /* flush socket */ sock = INVALID_SOCKET; } } fs_give ((void **) &sadr); return sock; /* return the socket */ }
long tcp_isclienthost (char *host) { int family; size_t adrlen,sadrlen,len; void *adr,*next; struct sockaddr *sadr; long ret = NIL; /* make sure that myClientAddr is set */ if (tcp_clienthost () && myClientAddr) /* get sockaddr of client */ for (adr = ip_nametoaddr (host,&adrlen,&family,NIL,&next); adr && !ret; adr = ip_nametoaddr (NIL,&adrlen,&family,NIL,&next)) { /* build sockaddr of given address */ sadr = ip_sockaddr (family,adr,adrlen,1,&len); if (!strcmp (myClientAddr,ip_sockaddrtostring (sadr))) ret = LONGT; fs_give ((void **) &sadr); /* done with client sockaddr */ } return ret; }
int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, char *tmp,int *ctr,char *hst) { int i,ti,sock,flgs; size_t len; time_t now; struct protoent *pt = getprotobyname ("tcp"); fd_set fds,efds; struct timeval tmo; struct sockaddr *sadr = ip_sockaddr (family,adr,adrlen,port,&len); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* fetid Solaris */ void *data = (*bn) (BLOCK_SENSITIVE,NIL); sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr)); mm_log (tmp,NIL); /* make a socket */ if ((sock = socket (sadr->sa_family,SOCK_STREAM,pt ? pt->p_proto : 0)) < 0) { sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno)); (*bn) (BLOCK_NONSENSITIVE,data); } else if (sock >= FD_SETSIZE) {/* unselectable sockets are useless */ sprintf (tmp,"Unable to create selectable TCP socket (%d >= %d)", sock,FD_SETSIZE); (*bn) (BLOCK_NONSENSITIVE,data); close (sock); sock = -1; errno = EMFILE; } else { /* get current socket flags */ flgs = fcntl (sock,F_GETFL,0); /* set non-blocking if want open timeout */ if (ctr) fcntl (sock,F_SETFL,flgs | FNDELAY); /* open connection */ while ((i = connect (sock,sadr,len)) < 0 && (errno == EINTR)); (*bn) (BLOCK_NONSENSITIVE,data); if (i < 0) switch (errno) { /* failed? */ case EAGAIN: /* DG brain damage */ case EINPROGRESS: /* what we expect to happen */ case EALREADY: /* or another form of it */ case EISCONN: /* restart after interrupt? */ case EADDRINUSE: /* restart after interrupt? */ break; /* well, not really, it was interrupted */ default: sprintf (tmp,"Can't connect to %.80s,%u: %s",hst,(unsigned int) port, strerror (errno)); close (sock); /* flush socket */ sock = -1; } if ((sock >= 0) && ctr) { /* want open timeout? */ now = time (0); /* open timeout */ ti = ttmo_open ? now + ttmo_open : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (sock,&fds); /* block for error or readable */ FD_SET (sock,&efds); do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; i = select (sock+1,&fds,NIL,&efds,ti ? &tmo : NIL); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i > 0) { /* success, make sure really connected */ /* restore blocking status */ fcntl (sock,F_SETFL,flgs); /* This used to be a zero-byte read(), but that crashes Solaris */ /* get socket status */ while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR)); } if (i <= 0) { /* timeout or error? */ i = i ? errno : ETIMEDOUT;/* determine error code */ close (sock); /* flush socket */ sock = -1; errno = i; /* return error code */ sprintf (tmp,"Connection failed to %.80s,%lu: %s",hst, (unsigned long) port,strerror (errno)); } } } fs_give ((void **) &sadr); return sock; /* return the socket */ }