1: /* 2: ** id_open.c Establish/initiate a connection to an IDENT server 3: ** 4: ** Author: Peter Eriksson <pen@lysator.liu.se> 5: ** Fixes: Pdr Emanuelsson <pell@lysator.liu.se> 6: */ 7: 8: #ifdef NeXT3 9: # include <libc.h> 10: #endif 11: 12: #include <stdio.h> 13: #include <errno.h> 14: #include <fcntl.h> 15: 16: #ifdef HAVE_ANSIHEADERS 17: # include <stdlib.h> 18: # include <string.h> 19: # include <unistd.h> 20: # if !defined(__sgi) && !defined(VMS) 21: # define bzero(p,l) memset(p, 0, l) 22: # endif 23: #endif 24: 25: #include <sys/types.h> 26: #include <sys/socket.h> 27: #include <sys/wait.h> 28: #include <sys/time.h> 29: #include <sys/file.h> 30: 31: #define IN_LIBIDENT_SRC 32: #include "ident.h" 33: 34: #include <arpa/inet.h> 35: 36: #ifdef _AIX 37: # include <sys/select.h> 38: #endif 39: 40: ident_t *id_open __P3(struct in_addr *, laddr, 41: struct in_addr *, faddr, 42: struct timeval *, timeout) 43: { 44: ident_t *id; 45: int res, tmperrno; 46: struct sockaddr_in sin_laddr, sin_faddr; 47: fd_set rs, ws, es; 48: #ifndef OLD_SETSOCKOPT 49: int on = 1; 50: struct linger linger; 51: #endif 52: 53: if ((id = (ident_t *) malloc(sizeof(*id))) == 0) 54: return 0; 55: 56: if ((id->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 57: { 58: free(id); 59: return 0; 60: } 61: 62: if (timeout) 63: { 64: if ((res = fcntl(id->fd, F_GETFL, 0)) < 0) 65: goto ERROR; 66: 67: #ifndef VMS 68: if (fcntl(id->fd, F_SETFL, res | FNDELAY) < 0) 69: goto ERROR; 70: #endif 71: } 72: 73: /* We silently ignore errors if we can't change LINGER */ 74: #ifdef OLD_SETSOCKOPT 75: /* Old style setsockopt() */ 76: (void) setsockopt(id->fd, SOL_SOCKET, SO_DONTLINGER); 77: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR); 78: #else 79: /* New style setsockopt() */ 80: linger.l_onoff = 0; 81: linger.l_linger = 0; 82: 83: (void) setsockopt(id->fd, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); 84: (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); 85: #endif 86: 87: id->buf[0] = '\0'; 88: 89: bzero((char *)&sin_laddr, sizeof(sin_laddr)); 90: sin_laddr.sin_family = AF_INET; 91: sin_laddr.sin_addr = *laddr; 92: sin_laddr.sin_port = 0; 93: 94: if (bind(id->fd, (struct sockaddr *) &sin_laddr, sizeof(sin_laddr)) < 0) 95: { 96: #ifdef DEBUG 97: perror("libident: bind"); 98: #endif 99: goto ERROR; 100: } 101: 102: bzero((char *)&sin_faddr, sizeof(sin_faddr)); 103: sin_faddr.sin_family = AF_INET; 104: sin_faddr.sin_addr = *faddr; 105: sin_faddr.sin_port = htons(IDPORT); 106: 107: errno = 0; 108: res = connect(id->fd, (struct sockaddr *) &sin_faddr, sizeof(sin_faddr)); 109: if (res < 0 && errno != EINPROGRESS) 110: { 111: #ifdef DEBUG 112: perror("libident: connect"); 113: #endif 114: goto ERROR; 115: } 116: 117: if (timeout) 118: { 119: FD_ZERO(&rs); 120: FD_ZERO(&ws); 121: FD_ZERO(&es); 122: 123: FD_SET(id->fd, &rs); 124: FD_SET(id->fd, &ws); 125: FD_SET(id->fd, &es); 126: 127: #ifdef __hpux 128: if ((res = select(FD_SETSIZE, (int *) &rs, (int *) &ws, (int *) &es, timeout)) < 0) 129: #else 130: if ((res = select(FD_SETSIZE, &rs, &ws, &es, timeout)) < 0) 131: #endif 132: { 133: #ifdef DEBUG 134: perror("libident: select"); 135: #endif 136: goto ERROR; 137: } 138: 139: if (res == 0) 140: { 141: errno = ETIMEDOUT; 142: goto ERROR; 143: } 144: 145: if (FD_ISSET(id->fd, &es)) 146: goto ERROR; 147: 148: if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws)) 149: goto ERROR; 150: } 151: 152: return id; 153: 154: ERROR: 155: tmperrno = errno; /* Save, so close() won't erase it */ 156: close(id->fd); 157: free(id); 158: errno = tmperrno; 159: return 0; 160: }