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@0: ident_t *id_open __P3(struct in_addr *, laddr, meillo@0: struct in_addr *, faddr, meillo@0: struct timeval *, timeout) meillo@0: */ meillo@0: meillo@0: ident_t *id_open __P(( __STRUCT_IN_ADDR_P laddr, meillo@0: __STRUCT_IN_ADDR_P faddr, meillo@0: __STRUCT_TIMEVAL_P timeout)) meillo@0: { meillo@0: ident_t *id; meillo@0: int res, tmperrno; meillo@0: struct sockaddr_in sin_laddr, sin_faddr; meillo@0: fd_set rs, ws, es; meillo@0: #ifndef OLD_SETSOCKOPT meillo@0: int on = 1; meillo@0: struct linger linger; meillo@0: #endif meillo@0: meillo@0: if ((id = (ident_t *) malloc(sizeof(*id))) == 0) meillo@0: return 0; meillo@0: meillo@0: if ((id->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) meillo@0: { meillo@0: free(id); meillo@0: return 0; meillo@0: } meillo@0: meillo@0: if (timeout) meillo@0: { meillo@0: if ((res = fcntl(id->fd, F_GETFL, 0)) < 0) meillo@0: goto ERROR; meillo@0: meillo@0: #ifndef VMS meillo@0: if (fcntl(id->fd, F_SETFL, res | FNDELAY) < 0) meillo@0: goto ERROR; meillo@0: #endif meillo@0: } meillo@0: meillo@0: /* We silently ignore errors if we can't change LINGER */ meillo@0: #ifdef OLD_SETSOCKOPT meillo@0: /* Old style setsockopt() */ meillo@0: (void) setsockopt(id->fd, SOL_SOCKET, SO_DONTLINGER); meillo@0: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR); meillo@0: #else meillo@0: /* New style setsockopt() */ meillo@0: linger.l_onoff = 0; meillo@0: linger.l_linger = 0; meillo@0: meillo@0: (void) setsockopt(id->fd, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); meillo@0: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); meillo@0: #endif meillo@0: meillo@0: id->buf[0] = '\0'; meillo@0: meillo@0: bzero((char *)&sin_laddr, sizeof(sin_laddr)); meillo@0: sin_laddr.sin_family = AF_INET; meillo@0: sin_laddr.sin_addr = *laddr; meillo@0: sin_laddr.sin_port = 0; meillo@0: meillo@0: if (bind(id->fd, (struct sockaddr *) &sin_laddr, sizeof(sin_laddr)) < 0) meillo@0: { meillo@0: #ifdef DEBUG meillo@0: perror("libident: bind"); meillo@0: #endif meillo@0: goto ERROR; meillo@0: } meillo@0: meillo@0: bzero((char *)&sin_faddr, sizeof(sin_faddr)); meillo@0: sin_faddr.sin_family = AF_INET; meillo@0: sin_faddr.sin_addr = *faddr; meillo@0: sin_faddr.sin_port = htons(IDPORT); meillo@0: meillo@0: errno = 0; meillo@0: res = connect(id->fd, (struct sockaddr *) &sin_faddr, sizeof(sin_faddr)); meillo@0: if (res < 0 && errno != EINPROGRESS) meillo@0: { meillo@0: #ifdef DEBUG meillo@0: perror("libident: connect"); meillo@0: #endif meillo@0: goto ERROR; meillo@0: } meillo@0: meillo@0: if (timeout) meillo@0: { meillo@0: FD_ZERO(&rs); meillo@0: FD_ZERO(&ws); meillo@0: FD_ZERO(&es); meillo@0: meillo@0: FD_SET(id->fd, &rs); meillo@0: FD_SET(id->fd, &ws); meillo@0: FD_SET(id->fd, &es); meillo@0: meillo@0: #ifdef __hpux meillo@0: if ((res = select(FD_SETSIZE, (int *) &rs, (int *) &ws, (int *) &es, timeout)) < 0) meillo@0: #else meillo@0: if ((res = select(FD_SETSIZE, &rs, &ws, &es, timeout)) < 0) meillo@0: #endif meillo@0: { meillo@0: #ifdef DEBUG meillo@0: perror("libident: select"); meillo@0: #endif meillo@0: goto ERROR; meillo@0: } meillo@0: meillo@0: if (res == 0) meillo@0: { meillo@0: errno = ETIMEDOUT; meillo@0: goto ERROR; meillo@0: } meillo@0: meillo@0: if (FD_ISSET(id->fd, &es)) meillo@0: goto ERROR; meillo@0: meillo@0: if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws)) meillo@0: goto ERROR; meillo@0: } meillo@0: meillo@0: return id; meillo@0: meillo@0: ERROR: meillo@0: tmperrno = errno; /* Save, so close() won't erase it */ meillo@0: close(id->fd); meillo@0: free(id); meillo@0: errno = tmperrno; meillo@0: return 0; meillo@0: }