masqmail

annotate src/libident/id_open.c @ 281:ea5f86e0a81c

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