meillo@0: /* meillo@0: ** id_open.c Establish/initiate a connection to an IDENT server meillo@0: ** meillo@0: ** Author: Peter Eriksson meillo@0: ** Fixes: Pär Emanuelsson meillo@0: */ meillo@0: meillo@0: #ifdef NeXT3 meillo@0: # include meillo@0: #endif meillo@0: meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: meillo@0: #ifdef HAVE_ANSIHEADERS meillo@0: # include meillo@0: # include meillo@0: # include meillo@0: # if !defined(__sgi) && !defined(VMS) meillo@0: # define bzero(p,l) memset(p, 0, l) meillo@0: # endif meillo@0: #endif meillo@0: meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: meillo@0: #define IN_LIBIDENT_SRC meillo@0: #include "ident.h" meillo@0: meillo@0: #include meillo@0: meillo@0: #ifdef _AIX meillo@0: # include meillo@0: #endif meillo@0: meillo@0: meillo@0: /* meillo@10: ident_t *id_open __P3(struct in_addr *, laddr, struct in_addr *, faddr, struct timeval *, timeout) meillo@0: */ meillo@0: meillo@10: ident_t* meillo@10: id_open __P((__STRUCT_IN_ADDR_P laddr, __STRUCT_IN_ADDR_P faddr, __STRUCT_TIMEVAL_P timeout)) meillo@0: { meillo@10: ident_t *id; meillo@10: int res, tmperrno; meillo@10: struct sockaddr_in sin_laddr, sin_faddr; meillo@10: fd_set rs, ws, es; meillo@0: #ifndef OLD_SETSOCKOPT meillo@10: int on = 1; meillo@10: struct linger linger; meillo@0: #endif meillo@10: meillo@10: if ((id = (ident_t *) malloc(sizeof(*id))) == 0) meillo@10: return 0; meillo@10: meillo@10: if ((id->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { meillo@10: free(id); meillo@10: return 0; meillo@10: } meillo@10: meillo@10: if (timeout) { meillo@10: if ((res = fcntl(id->fd, F_GETFL, 0)) < 0) meillo@10: goto ERROR; meillo@0: meillo@0: #ifndef VMS meillo@10: if (fcntl(id->fd, F_SETFL, res | FNDELAY) < 0) meillo@10: goto ERROR; meillo@0: #endif meillo@10: } meillo@0: meillo@10: /* We silently ignore errors if we can't change LINGER */ meillo@0: #ifdef OLD_SETSOCKOPT meillo@10: /* Old style setsockopt() */ meillo@10: (void) setsockopt(id->fd, SOL_SOCKET, SO_DONTLINGER); meillo@10: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR); meillo@0: #else meillo@10: /* New style setsockopt() */ meillo@10: linger.l_onoff = 0; meillo@10: linger.l_linger = 0; meillo@10: meillo@10: (void) setsockopt(id->fd, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); meillo@10: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); meillo@0: #endif meillo@10: meillo@10: id->buf[0] = '\0'; meillo@10: meillo@10: bzero((char *) &sin_laddr, sizeof(sin_laddr)); meillo@10: sin_laddr.sin_family = AF_INET; meillo@10: sin_laddr.sin_addr = *laddr; meillo@10: sin_laddr.sin_port = 0; meillo@10: meillo@10: if (bind(id->fd, (struct sockaddr *) &sin_laddr, sizeof(sin_laddr)) < 0) { meillo@0: #ifdef DEBUG meillo@10: perror("libident: bind"); meillo@0: #endif meillo@10: goto ERROR; meillo@10: } meillo@0: meillo@10: bzero((char *) &sin_faddr, sizeof(sin_faddr)); meillo@10: sin_faddr.sin_family = AF_INET; meillo@10: sin_faddr.sin_addr = *faddr; meillo@10: sin_faddr.sin_port = htons(IDPORT); meillo@10: meillo@10: errno = 0; meillo@10: res = connect(id->fd, (struct sockaddr *) &sin_faddr, sizeof(sin_faddr)); meillo@10: if (res < 0 && errno != EINPROGRESS) { meillo@0: #ifdef DEBUG meillo@10: perror("libident: connect"); meillo@0: #endif meillo@10: goto ERROR; meillo@10: } meillo@0: meillo@10: if (timeout) { meillo@10: FD_ZERO(&rs); meillo@10: FD_ZERO(&ws); meillo@10: FD_ZERO(&es); meillo@10: meillo@10: FD_SET(id->fd, &rs); meillo@10: FD_SET(id->fd, &ws); meillo@10: FD_SET(id->fd, &es); meillo@0: meillo@0: #ifdef __hpux meillo@10: if ((res = select(FD_SETSIZE, (int *) &rs, (int *) &ws, (int *) &es, timeout)) < 0) meillo@0: #else meillo@10: if ((res = select(FD_SETSIZE, &rs, &ws, &es, timeout)) < 0) meillo@0: #endif meillo@10: { meillo@0: #ifdef DEBUG meillo@10: perror("libident: select"); meillo@0: #endif meillo@10: goto ERROR; meillo@10: } meillo@10: meillo@10: if (res == 0) { meillo@10: errno = ETIMEDOUT; meillo@10: goto ERROR; meillo@10: } meillo@10: meillo@10: if (FD_ISSET(id->fd, &es)) meillo@10: goto ERROR; meillo@10: meillo@10: if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws)) meillo@10: goto ERROR; meillo@0: } meillo@10: meillo@10: return id; meillo@10: meillo@0: ERROR: meillo@10: tmperrno = errno; /* Save, so close() won't erase it */ meillo@10: close(id->fd); meillo@10: free(id); meillo@10: errno = tmperrno; meillo@10: return 0; meillo@0: }