1/* 2 * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11#include <sm/gen.h>
| 1/* 2 * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11#include <sm/gen.h>
|
12SM_RCSID("@(#)$Id: listener.c,v 8.85.2.1 2002/08/09 22:13:36 gshapiro Exp $")
| 12SM_RCSID("@(#)$Id: listener.c,v 8.85.2.7 2002/12/10 04:02:25 ca Exp $")
|
13 14/* 15** listener.c -- threaded network listener 16*/ 17 18#include "libmilter.h" 19#include <sm/errstring.h>
| 13 14/* 15** listener.c -- threaded network listener 16*/ 17 18#include "libmilter.h" 19#include <sm/errstring.h>
|
| 20#include <sm/fdset.h>
|
20 21 22# if NETINET || NETINET6 23# include <arpa/inet.h> 24# endif /* NETINET || NETINET6 */ 25 26static smutex_t L_Mutex; 27static int L_family; 28static SOCKADDR_LEN_T L_socksize; 29static socket_t listenfd = INVALID_SOCKET; 30 31static socket_t mi_milteropen __P((char *, int, char *)); 32 33/* 34** MI_OPENSOCKET -- create the socket where this filter and the MTA will meet 35** 36** Parameters: 37** conn -- connection description 38** backlog -- listen backlog 39** dbg -- debug level 40** smfi -- filter structure to use 41** 42** Return value: 43** MI_SUCCESS/MI_FAILURE 44*/ 45 46int 47mi_opensocket(conn, backlog, dbg, smfi) 48 char *conn; 49 int backlog; 50 int dbg; 51 smfiDesc_ptr smfi; 52{ 53 if (smfi == NULL || conn == NULL) 54 return MI_FAILURE; 55 56 if (ValidSocket(listenfd)) 57 return MI_SUCCESS; 58 59 if (dbg > 0) 60 { 61 smi_log(SMI_LOG_DEBUG, 62 "%s: Opening listen socket on conn %s", 63 smfi->xxfi_name, conn); 64 } 65 (void) smutex_init(&L_Mutex); 66 (void) smutex_lock(&L_Mutex); 67 listenfd = mi_milteropen(conn, backlog, smfi->xxfi_name); 68 if (!ValidSocket(listenfd)) 69 { 70 smi_log(SMI_LOG_FATAL, 71 "%s: Unable to create listening socket on conn %s", 72 smfi->xxfi_name, conn); 73 (void) smutex_unlock(&L_Mutex); 74 return MI_FAILURE; 75 }
| 21 22 23# if NETINET || NETINET6 24# include <arpa/inet.h> 25# endif /* NETINET || NETINET6 */ 26 27static smutex_t L_Mutex; 28static int L_family; 29static SOCKADDR_LEN_T L_socksize; 30static socket_t listenfd = INVALID_SOCKET; 31 32static socket_t mi_milteropen __P((char *, int, char *)); 33 34/* 35** MI_OPENSOCKET -- create the socket where this filter and the MTA will meet 36** 37** Parameters: 38** conn -- connection description 39** backlog -- listen backlog 40** dbg -- debug level 41** smfi -- filter structure to use 42** 43** Return value: 44** MI_SUCCESS/MI_FAILURE 45*/ 46 47int 48mi_opensocket(conn, backlog, dbg, smfi) 49 char *conn; 50 int backlog; 51 int dbg; 52 smfiDesc_ptr smfi; 53{ 54 if (smfi == NULL || conn == NULL) 55 return MI_FAILURE; 56 57 if (ValidSocket(listenfd)) 58 return MI_SUCCESS; 59 60 if (dbg > 0) 61 { 62 smi_log(SMI_LOG_DEBUG, 63 "%s: Opening listen socket on conn %s", 64 smfi->xxfi_name, conn); 65 } 66 (void) smutex_init(&L_Mutex); 67 (void) smutex_lock(&L_Mutex); 68 listenfd = mi_milteropen(conn, backlog, smfi->xxfi_name); 69 if (!ValidSocket(listenfd)) 70 { 71 smi_log(SMI_LOG_FATAL, 72 "%s: Unable to create listening socket on conn %s", 73 smfi->xxfi_name, conn); 74 (void) smutex_unlock(&L_Mutex); 75 return MI_FAILURE; 76 }
|
76
| 77 if (!SM_FD_OK_SELECT(listenfd)) 78 { 79 smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", 80 smfi->xxfi_name, listenfd, FD_SETSIZE); 81 (void) smutex_unlock(&L_Mutex); 82 return MI_FAILURE; 83 }
|
77 return MI_SUCCESS; 78} 79 80/* 81** MI_MILTEROPEN -- setup socket to listen on 82** 83** Parameters: 84** conn -- connection description 85** backlog -- listen backlog 86** name -- name for logging 87** 88** Returns: 89** socket upon success, error code otherwise. 90** 91** Side effect: 92** sets sockpath if UNIX socket. 93*/ 94 95#if NETUNIX 96static char *sockpath = NULL; 97#endif /* NETUNIX */ 98 99static socket_t 100mi_milteropen(conn, backlog, name) 101 char *conn; 102 int backlog; 103 char *name; 104{ 105 socket_t sock; 106 int sockopt = 1; 107 int fdflags; 108 size_t len = 0; 109 char *p; 110 char *colon; 111 char *at; 112 SOCKADDR addr; 113 114 if (conn == NULL || conn[0] == '\0') 115 { 116 smi_log(SMI_LOG_ERR, "%s: empty or missing socket information", 117 name); 118 return INVALID_SOCKET; 119 } 120 (void) memset(&addr, '\0', sizeof addr); 121 122 /* protocol:filename or protocol:port@host */ 123 p = conn; 124 colon = strchr(p, ':'); 125 if (colon != NULL) 126 { 127 *colon = '\0'; 128 129 if (*p == '\0') 130 { 131#if NETUNIX 132 /* default to AF_UNIX */ 133 addr.sa.sa_family = AF_UNIX; 134 L_socksize = sizeof (struct sockaddr_un); 135#else /* NETUNIX */ 136# if NETINET 137 /* default to AF_INET */ 138 addr.sa.sa_family = AF_INET; 139 L_socksize = sizeof addr.sin; 140# else /* NETINET */ 141# if NETINET6 142 /* default to AF_INET6 */ 143 addr.sa.sa_family = AF_INET6; 144 L_socksize = sizeof addr.sin6; 145# else /* NETINET6 */ 146 /* no protocols available */ 147 smi_log(SMI_LOG_ERR, 148 "%s: no valid socket protocols available", 149 name); 150 return INVALID_SOCKET; 151# endif /* NETINET6 */ 152# endif /* NETINET */ 153#endif /* NETUNIX */ 154 } 155#if NETUNIX 156 else if (strcasecmp(p, "unix") == 0 || 157 strcasecmp(p, "local") == 0) 158 { 159 addr.sa.sa_family = AF_UNIX; 160 L_socksize = sizeof (struct sockaddr_un); 161 } 162#endif /* NETUNIX */ 163#if NETINET 164 else if (strcasecmp(p, "inet") == 0) 165 { 166 addr.sa.sa_family = AF_INET; 167 L_socksize = sizeof addr.sin; 168 } 169#endif /* NETINET */ 170#if NETINET6 171 else if (strcasecmp(p, "inet6") == 0) 172 { 173 addr.sa.sa_family = AF_INET6; 174 L_socksize = sizeof addr.sin6; 175 } 176#endif /* NETINET6 */ 177 else 178 { 179 smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", 180 name, p); 181 return INVALID_SOCKET; 182 } 183 *colon++ = ':'; 184 } 185 else 186 { 187 colon = p; 188#if NETUNIX 189 /* default to AF_UNIX */ 190 addr.sa.sa_family = AF_UNIX; 191 L_socksize = sizeof (struct sockaddr_un); 192#else /* NETUNIX */ 193# if NETINET 194 /* default to AF_INET */ 195 addr.sa.sa_family = AF_INET; 196 L_socksize = sizeof addr.sin; 197# else /* NETINET */ 198# if NETINET6 199 /* default to AF_INET6 */ 200 addr.sa.sa_family = AF_INET6; 201 L_socksize = sizeof addr.sin6; 202# else /* NETINET6 */ 203 smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", 204 name, p); 205 return INVALID_SOCKET; 206# endif /* NETINET6 */ 207# endif /* NETINET */ 208#endif /* NETUNIX */ 209 } 210 211#if NETUNIX 212 if (addr.sa.sa_family == AF_UNIX) 213 { 214# if 0 215 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN; 216# endif /* 0 */ 217 218 at = colon; 219 len = strlen(colon) + 1; 220 if (len >= sizeof addr.sunix.sun_path) 221 { 222 errno = EINVAL; 223 smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long", 224 name, colon); 225 return INVALID_SOCKET; 226 } 227 (void) sm_strlcpy(addr.sunix.sun_path, colon, 228 sizeof addr.sunix.sun_path); 229# if 0 230 errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 231 S_IRUSR|S_IWUSR, NULL); 232 233 /* if not safe, don't create */ 234 if (errno != 0) 235 { 236 smi_log(SMI_LOG_ERR, 237 "%s: UNIX socket name %s unsafe", 238 name, colon); 239 return INVALID_SOCKET; 240 } 241# endif /* 0 */ 242 } 243#endif /* NETUNIX */ 244 245#if NETINET || NETINET6 246 if ( 247# if NETINET 248 addr.sa.sa_family == AF_INET 249# endif /* NETINET */ 250# if NETINET && NETINET6 251 || 252# endif /* NETINET && NETINET6 */ 253# if NETINET6 254 addr.sa.sa_family == AF_INET6 255# endif /* NETINET6 */ 256 ) 257 { 258 unsigned short port; 259 260 /* Parse port@host */ 261 at = strchr(colon, '@'); 262 if (at == NULL) 263 { 264 switch (addr.sa.sa_family) 265 { 266# if NETINET 267 case AF_INET: 268 addr.sin.sin_addr.s_addr = INADDR_ANY; 269 break; 270# endif /* NETINET */ 271 272# if NETINET6 273 case AF_INET6: 274 addr.sin6.sin6_addr = in6addr_any; 275 break; 276# endif /* NETINET6 */ 277 } 278 } 279 else 280 *at = '\0'; 281 282 if (isascii(*colon) && isdigit(*colon)) 283 port = htons((unsigned short) atoi(colon)); 284 else 285 { 286# ifdef NO_GETSERVBYNAME 287 smi_log(SMI_LOG_ERR, "%s: invalid port number %s", 288 name, colon); 289 return INVALID_SOCKET; 290# else /* NO_GETSERVBYNAME */ 291 register struct servent *sp; 292 293 sp = getservbyname(colon, "tcp"); 294 if (sp == NULL) 295 { 296 smi_log(SMI_LOG_ERR, 297 "%s: unknown port name %s", 298 name, colon); 299 return INVALID_SOCKET; 300 } 301 port = sp->s_port; 302# endif /* NO_GETSERVBYNAME */ 303 } 304 if (at != NULL) 305 { 306 *at++ = '@'; 307 if (*at == '[') 308 { 309 char *end; 310 311 end = strchr(at, ']'); 312 if (end != NULL) 313 { 314 bool found = false; 315# if NETINET 316 unsigned long hid = INADDR_NONE; 317# endif /* NETINET */ 318# if NETINET6 319 struct sockaddr_in6 hid6; 320# endif /* NETINET6 */ 321 322 *end = '\0'; 323# if NETINET 324 if (addr.sa.sa_family == AF_INET && 325 (hid = inet_addr(&at[1])) != INADDR_NONE) 326 { 327 addr.sin.sin_addr.s_addr = hid; 328 addr.sin.sin_port = port; 329 found = true; 330 } 331# endif /* NETINET */ 332# if NETINET6 333 (void) memset(&hid6, '\0', sizeof hid6); 334 if (addr.sa.sa_family == AF_INET6 && 335 mi_inet_pton(AF_INET6, &at[1], 336 &hid6.sin6_addr) == 1) 337 { 338 addr.sin6.sin6_addr = hid6.sin6_addr; 339 addr.sin6.sin6_port = port; 340 found = true; 341 } 342# endif /* NETINET6 */ 343 *end = ']'; 344 if (!found) 345 { 346 smi_log(SMI_LOG_ERR, 347 "%s: Invalid numeric domain spec \"%s\"", 348 name, at); 349 return INVALID_SOCKET; 350 } 351 } 352 else 353 { 354 smi_log(SMI_LOG_ERR, 355 "%s: Invalid numeric domain spec \"%s\"", 356 name, at); 357 return INVALID_SOCKET; 358 } 359 } 360 else 361 { 362 struct hostent *hp = NULL; 363 364 hp = mi_gethostbyname(at, addr.sa.sa_family); 365 if (hp == NULL) 366 { 367 smi_log(SMI_LOG_ERR, 368 "%s: Unknown host name %s", 369 name, at); 370 return INVALID_SOCKET; 371 } 372 addr.sa.sa_family = hp->h_addrtype; 373 switch (hp->h_addrtype) 374 { 375# if NETINET 376 case AF_INET: 377 memmove(&addr.sin.sin_addr, 378 hp->h_addr, 379 INADDRSZ); 380 addr.sin.sin_port = port; 381 break; 382# endif /* NETINET */ 383 384# if NETINET6 385 case AF_INET6: 386 memmove(&addr.sin6.sin6_addr, 387 hp->h_addr, 388 IN6ADDRSZ); 389 addr.sin6.sin6_port = port; 390 break; 391# endif /* NETINET6 */ 392 393 default: 394 smi_log(SMI_LOG_ERR, 395 "%s: Unknown protocol for %s (%d)", 396 name, at, hp->h_addrtype); 397 return INVALID_SOCKET; 398 } 399# if NETINET6 400 freehostent(hp); 401# endif /* NETINET6 */ 402 } 403 } 404 else 405 { 406 switch (addr.sa.sa_family) 407 { 408# if NETINET 409 case AF_INET: 410 addr.sin.sin_port = port; 411 break; 412# endif /* NETINET */ 413# if NETINET6 414 case AF_INET6: 415 addr.sin6.sin6_port = port; 416 break; 417# endif /* NETINET6 */ 418 } 419 } 420 } 421#endif /* NETINET || NETINET6 */ 422 423 sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 424 if (!ValidSocket(sock)) 425 { 426 smi_log(SMI_LOG_ERR, 427 "%s: Unable to create new socket: %s", 428 name, sm_errstring(errno)); 429 return INVALID_SOCKET; 430 } 431 432 if ((fdflags = fcntl(sock, F_GETFD, 0)) == -1 || 433 fcntl(sock, F_SETFD, fdflags | FD_CLOEXEC) == -1) 434 { 435 smi_log(SMI_LOG_ERR, 436 "%s: Unable to set close-on-exec: %s", name, 437 sm_errstring(errno)); 438 (void) closesocket(sock); 439 return INVALID_SOCKET; 440 } 441 442 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt, 443 sizeof(sockopt)) == -1) 444 { 445 smi_log(SMI_LOG_ERR, 446 "%s: Unable to setsockopt: %s", name, 447 sm_errstring(errno)); 448 (void) closesocket(sock); 449 return INVALID_SOCKET; 450 } 451 452 if (bind(sock, &addr.sa, L_socksize) < 0) 453 { 454 smi_log(SMI_LOG_ERR, 455 "%s: Unable to bind to port %s: %s", 456 name, conn, sm_errstring(errno)); 457 (void) closesocket(sock); 458 return INVALID_SOCKET; 459 } 460 461 if (listen(sock, backlog) < 0) 462 { 463 smi_log(SMI_LOG_ERR, 464 "%s: listen call failed: %s", name, 465 sm_errstring(errno)); 466 (void) closesocket(sock); 467 return INVALID_SOCKET; 468 } 469 470#if NETUNIX 471 if (addr.sa.sa_family == AF_UNIX && len > 0) 472 { 473 /* 474 ** Set global variable sockpath so the UNIX socket can be 475 ** unlink()ed at exit. 476 */ 477 478 sockpath = (char *) malloc(len); 479 if (sockpath != NULL) 480 (void) sm_strlcpy(sockpath, colon, len); 481 else 482 { 483 smi_log(SMI_LOG_ERR, 484 "%s: can't malloc(%d) for sockpath: %s",
| 84 return MI_SUCCESS; 85} 86 87/* 88** MI_MILTEROPEN -- setup socket to listen on 89** 90** Parameters: 91** conn -- connection description 92** backlog -- listen backlog 93** name -- name for logging 94** 95** Returns: 96** socket upon success, error code otherwise. 97** 98** Side effect: 99** sets sockpath if UNIX socket. 100*/ 101 102#if NETUNIX 103static char *sockpath = NULL; 104#endif /* NETUNIX */ 105 106static socket_t 107mi_milteropen(conn, backlog, name) 108 char *conn; 109 int backlog; 110 char *name; 111{ 112 socket_t sock; 113 int sockopt = 1; 114 int fdflags; 115 size_t len = 0; 116 char *p; 117 char *colon; 118 char *at; 119 SOCKADDR addr; 120 121 if (conn == NULL || conn[0] == '\0') 122 { 123 smi_log(SMI_LOG_ERR, "%s: empty or missing socket information", 124 name); 125 return INVALID_SOCKET; 126 } 127 (void) memset(&addr, '\0', sizeof addr); 128 129 /* protocol:filename or protocol:port@host */ 130 p = conn; 131 colon = strchr(p, ':'); 132 if (colon != NULL) 133 { 134 *colon = '\0'; 135 136 if (*p == '\0') 137 { 138#if NETUNIX 139 /* default to AF_UNIX */ 140 addr.sa.sa_family = AF_UNIX; 141 L_socksize = sizeof (struct sockaddr_un); 142#else /* NETUNIX */ 143# if NETINET 144 /* default to AF_INET */ 145 addr.sa.sa_family = AF_INET; 146 L_socksize = sizeof addr.sin; 147# else /* NETINET */ 148# if NETINET6 149 /* default to AF_INET6 */ 150 addr.sa.sa_family = AF_INET6; 151 L_socksize = sizeof addr.sin6; 152# else /* NETINET6 */ 153 /* no protocols available */ 154 smi_log(SMI_LOG_ERR, 155 "%s: no valid socket protocols available", 156 name); 157 return INVALID_SOCKET; 158# endif /* NETINET6 */ 159# endif /* NETINET */ 160#endif /* NETUNIX */ 161 } 162#if NETUNIX 163 else if (strcasecmp(p, "unix") == 0 || 164 strcasecmp(p, "local") == 0) 165 { 166 addr.sa.sa_family = AF_UNIX; 167 L_socksize = sizeof (struct sockaddr_un); 168 } 169#endif /* NETUNIX */ 170#if NETINET 171 else if (strcasecmp(p, "inet") == 0) 172 { 173 addr.sa.sa_family = AF_INET; 174 L_socksize = sizeof addr.sin; 175 } 176#endif /* NETINET */ 177#if NETINET6 178 else if (strcasecmp(p, "inet6") == 0) 179 { 180 addr.sa.sa_family = AF_INET6; 181 L_socksize = sizeof addr.sin6; 182 } 183#endif /* NETINET6 */ 184 else 185 { 186 smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", 187 name, p); 188 return INVALID_SOCKET; 189 } 190 *colon++ = ':'; 191 } 192 else 193 { 194 colon = p; 195#if NETUNIX 196 /* default to AF_UNIX */ 197 addr.sa.sa_family = AF_UNIX; 198 L_socksize = sizeof (struct sockaddr_un); 199#else /* NETUNIX */ 200# if NETINET 201 /* default to AF_INET */ 202 addr.sa.sa_family = AF_INET; 203 L_socksize = sizeof addr.sin; 204# else /* NETINET */ 205# if NETINET6 206 /* default to AF_INET6 */ 207 addr.sa.sa_family = AF_INET6; 208 L_socksize = sizeof addr.sin6; 209# else /* NETINET6 */ 210 smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", 211 name, p); 212 return INVALID_SOCKET; 213# endif /* NETINET6 */ 214# endif /* NETINET */ 215#endif /* NETUNIX */ 216 } 217 218#if NETUNIX 219 if (addr.sa.sa_family == AF_UNIX) 220 { 221# if 0 222 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN; 223# endif /* 0 */ 224 225 at = colon; 226 len = strlen(colon) + 1; 227 if (len >= sizeof addr.sunix.sun_path) 228 { 229 errno = EINVAL; 230 smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long", 231 name, colon); 232 return INVALID_SOCKET; 233 } 234 (void) sm_strlcpy(addr.sunix.sun_path, colon, 235 sizeof addr.sunix.sun_path); 236# if 0 237 errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, 238 S_IRUSR|S_IWUSR, NULL); 239 240 /* if not safe, don't create */ 241 if (errno != 0) 242 { 243 smi_log(SMI_LOG_ERR, 244 "%s: UNIX socket name %s unsafe", 245 name, colon); 246 return INVALID_SOCKET; 247 } 248# endif /* 0 */ 249 } 250#endif /* NETUNIX */ 251 252#if NETINET || NETINET6 253 if ( 254# if NETINET 255 addr.sa.sa_family == AF_INET 256# endif /* NETINET */ 257# if NETINET && NETINET6 258 || 259# endif /* NETINET && NETINET6 */ 260# if NETINET6 261 addr.sa.sa_family == AF_INET6 262# endif /* NETINET6 */ 263 ) 264 { 265 unsigned short port; 266 267 /* Parse port@host */ 268 at = strchr(colon, '@'); 269 if (at == NULL) 270 { 271 switch (addr.sa.sa_family) 272 { 273# if NETINET 274 case AF_INET: 275 addr.sin.sin_addr.s_addr = INADDR_ANY; 276 break; 277# endif /* NETINET */ 278 279# if NETINET6 280 case AF_INET6: 281 addr.sin6.sin6_addr = in6addr_any; 282 break; 283# endif /* NETINET6 */ 284 } 285 } 286 else 287 *at = '\0'; 288 289 if (isascii(*colon) && isdigit(*colon)) 290 port = htons((unsigned short) atoi(colon)); 291 else 292 { 293# ifdef NO_GETSERVBYNAME 294 smi_log(SMI_LOG_ERR, "%s: invalid port number %s", 295 name, colon); 296 return INVALID_SOCKET; 297# else /* NO_GETSERVBYNAME */ 298 register struct servent *sp; 299 300 sp = getservbyname(colon, "tcp"); 301 if (sp == NULL) 302 { 303 smi_log(SMI_LOG_ERR, 304 "%s: unknown port name %s", 305 name, colon); 306 return INVALID_SOCKET; 307 } 308 port = sp->s_port; 309# endif /* NO_GETSERVBYNAME */ 310 } 311 if (at != NULL) 312 { 313 *at++ = '@'; 314 if (*at == '[') 315 { 316 char *end; 317 318 end = strchr(at, ']'); 319 if (end != NULL) 320 { 321 bool found = false; 322# if NETINET 323 unsigned long hid = INADDR_NONE; 324# endif /* NETINET */ 325# if NETINET6 326 struct sockaddr_in6 hid6; 327# endif /* NETINET6 */ 328 329 *end = '\0'; 330# if NETINET 331 if (addr.sa.sa_family == AF_INET && 332 (hid = inet_addr(&at[1])) != INADDR_NONE) 333 { 334 addr.sin.sin_addr.s_addr = hid; 335 addr.sin.sin_port = port; 336 found = true; 337 } 338# endif /* NETINET */ 339# if NETINET6 340 (void) memset(&hid6, '\0', sizeof hid6); 341 if (addr.sa.sa_family == AF_INET6 && 342 mi_inet_pton(AF_INET6, &at[1], 343 &hid6.sin6_addr) == 1) 344 { 345 addr.sin6.sin6_addr = hid6.sin6_addr; 346 addr.sin6.sin6_port = port; 347 found = true; 348 } 349# endif /* NETINET6 */ 350 *end = ']'; 351 if (!found) 352 { 353 smi_log(SMI_LOG_ERR, 354 "%s: Invalid numeric domain spec \"%s\"", 355 name, at); 356 return INVALID_SOCKET; 357 } 358 } 359 else 360 { 361 smi_log(SMI_LOG_ERR, 362 "%s: Invalid numeric domain spec \"%s\"", 363 name, at); 364 return INVALID_SOCKET; 365 } 366 } 367 else 368 { 369 struct hostent *hp = NULL; 370 371 hp = mi_gethostbyname(at, addr.sa.sa_family); 372 if (hp == NULL) 373 { 374 smi_log(SMI_LOG_ERR, 375 "%s: Unknown host name %s", 376 name, at); 377 return INVALID_SOCKET; 378 } 379 addr.sa.sa_family = hp->h_addrtype; 380 switch (hp->h_addrtype) 381 { 382# if NETINET 383 case AF_INET: 384 memmove(&addr.sin.sin_addr, 385 hp->h_addr, 386 INADDRSZ); 387 addr.sin.sin_port = port; 388 break; 389# endif /* NETINET */ 390 391# if NETINET6 392 case AF_INET6: 393 memmove(&addr.sin6.sin6_addr, 394 hp->h_addr, 395 IN6ADDRSZ); 396 addr.sin6.sin6_port = port; 397 break; 398# endif /* NETINET6 */ 399 400 default: 401 smi_log(SMI_LOG_ERR, 402 "%s: Unknown protocol for %s (%d)", 403 name, at, hp->h_addrtype); 404 return INVALID_SOCKET; 405 } 406# if NETINET6 407 freehostent(hp); 408# endif /* NETINET6 */ 409 } 410 } 411 else 412 { 413 switch (addr.sa.sa_family) 414 { 415# if NETINET 416 case AF_INET: 417 addr.sin.sin_port = port; 418 break; 419# endif /* NETINET */ 420# if NETINET6 421 case AF_INET6: 422 addr.sin6.sin6_port = port; 423 break; 424# endif /* NETINET6 */ 425 } 426 } 427 } 428#endif /* NETINET || NETINET6 */ 429 430 sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); 431 if (!ValidSocket(sock)) 432 { 433 smi_log(SMI_LOG_ERR, 434 "%s: Unable to create new socket: %s", 435 name, sm_errstring(errno)); 436 return INVALID_SOCKET; 437 } 438 439 if ((fdflags = fcntl(sock, F_GETFD, 0)) == -1 || 440 fcntl(sock, F_SETFD, fdflags | FD_CLOEXEC) == -1) 441 { 442 smi_log(SMI_LOG_ERR, 443 "%s: Unable to set close-on-exec: %s", name, 444 sm_errstring(errno)); 445 (void) closesocket(sock); 446 return INVALID_SOCKET; 447 } 448 449 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt, 450 sizeof(sockopt)) == -1) 451 { 452 smi_log(SMI_LOG_ERR, 453 "%s: Unable to setsockopt: %s", name, 454 sm_errstring(errno)); 455 (void) closesocket(sock); 456 return INVALID_SOCKET; 457 } 458 459 if (bind(sock, &addr.sa, L_socksize) < 0) 460 { 461 smi_log(SMI_LOG_ERR, 462 "%s: Unable to bind to port %s: %s", 463 name, conn, sm_errstring(errno)); 464 (void) closesocket(sock); 465 return INVALID_SOCKET; 466 } 467 468 if (listen(sock, backlog) < 0) 469 { 470 smi_log(SMI_LOG_ERR, 471 "%s: listen call failed: %s", name, 472 sm_errstring(errno)); 473 (void) closesocket(sock); 474 return INVALID_SOCKET; 475 } 476 477#if NETUNIX 478 if (addr.sa.sa_family == AF_UNIX && len > 0) 479 { 480 /* 481 ** Set global variable sockpath so the UNIX socket can be 482 ** unlink()ed at exit. 483 */ 484 485 sockpath = (char *) malloc(len); 486 if (sockpath != NULL) 487 (void) sm_strlcpy(sockpath, colon, len); 488 else 489 { 490 smi_log(SMI_LOG_ERR, 491 "%s: can't malloc(%d) for sockpath: %s",
|
485 name, len, sm_errstring(errno));
| 492 name, (int) len, sm_errstring(errno));
|
486 (void) closesocket(sock); 487 return INVALID_SOCKET; 488 } 489 } 490#endif /* NETUNIX */ 491 L_family = addr.sa.sa_family; 492 return sock; 493} 494/* 495** MI_THREAD_HANDLE_WRAPPER -- small wrapper to handle session 496** 497** Parameters: 498** arg -- argument to pass to mi_handle_session() 499** 500** Returns: 501** results from mi_handle_session() 502*/ 503 504void * 505mi_thread_handle_wrapper(arg) 506 void *arg; 507{ 508 return (void *) mi_handle_session(arg); 509} 510 511/* 512** MI_CLOSENER -- close listen socket 513** 514** NOTE: It is assumed that this function is called from a 515** function that has a mutex lock (currently mi_stop_milters()). 516** 517** Parameters: 518** none. 519** 520** Returns: 521** none. 522*/ 523 524void 525mi_closener() 526{ 527 (void) smutex_lock(&L_Mutex); 528 if (ValidSocket(listenfd)) 529 { 530#if NETUNIX 531 bool removable; 532 struct stat sockinfo; 533 struct stat fileinfo; 534 535 removable = sockpath != NULL && 536#if _FFR_MILTER_ROOT_UNSAFE 537 geteuid() != 0 && 538#endif /* _FFR_MILTER_ROOT_UNSAFE */ 539 fstat(listenfd, &sockinfo) == 0 && 540 (S_ISFIFO(sockinfo.st_mode) 541# ifdef S_ISSOCK 542 || S_ISSOCK(sockinfo.st_mode) 543# endif /* S_ISSOCK */ 544 ); 545#endif /* NETUNIX */ 546 547 (void) closesocket(listenfd); 548 listenfd = INVALID_SOCKET; 549 550#if NETUNIX 551 /* XXX sleep() some time before doing this? */ 552 if (sockpath != NULL) 553 { 554 if (removable && 555 stat(sockpath, &fileinfo) == 0 && 556 ((fileinfo.st_dev == sockinfo.st_dev && 557 fileinfo.st_ino == sockinfo.st_ino) 558# ifdef S_ISSOCK 559 || S_ISSOCK(fileinfo.st_mode) 560# endif /* S_ISSOCK */ 561 ) 562 && 563 (S_ISFIFO(fileinfo.st_mode) 564# ifdef S_ISSOCK 565 || S_ISSOCK(fileinfo.st_mode) 566# endif /* S_ISSOCK */ 567 )) 568 (void) unlink(sockpath); 569 free(sockpath); 570 sockpath = NULL; 571 } 572#endif /* NETUNIX */ 573 } 574 (void) smutex_unlock(&L_Mutex); 575} 576 577/* 578** MI_LISTENER -- Generic listener harness 579** 580** Open up listen port 581** Wait for connections 582** 583** Parameters: 584** conn -- connection description 585** dbg -- debug level 586** smfi -- filter structure to use 587** timeout -- timeout for reads/writes 588** backlog -- listen queue backlog size 589** 590** Returns: 591** MI_SUCCESS -- Exited normally 592** (session finished or we were told to exit) 593** MI_FAILURE -- Network initialization failed. 594*/ 595 596#if BROKEN_PTHREAD_SLEEP 597 598/* 599** Solaris 2.6, perhaps others, gets an internal threads library panic 600** when sleep() is used: 601** 602** thread_create() failed, returned 11 (EINVAL) 603** co_enable, thr_create() returned error = 24 604** libthread panic: co_enable failed (PID: 17793 LWP 1) 605** stacktrace: 606** ef526b10 607** ef52646c 608** ef534cbc 609** 156a4 610** 14644 611** 1413c 612** 135e0 613** 0 614*/ 615 616# define MI_SLEEP(s) \ 617{ \ 618 int rs = 0; \ 619 struct timeval st; \ 620 \ 621 st.tv_sec = (s); \ 622 st.tv_usec = 0; \ 623 if (st.tv_sec > 0) \ 624 { \ 625 for (;;) \ 626 { \ 627 rs = select(0, NULL, NULL, NULL, &st); \ 628 if (rs < 0 && errno == EINTR) \ 629 continue; \ 630 if (rs != 0) \ 631 { \ 632 smi_log(SMI_LOG_ERR, \
| 493 (void) closesocket(sock); 494 return INVALID_SOCKET; 495 } 496 } 497#endif /* NETUNIX */ 498 L_family = addr.sa.sa_family; 499 return sock; 500} 501/* 502** MI_THREAD_HANDLE_WRAPPER -- small wrapper to handle session 503** 504** Parameters: 505** arg -- argument to pass to mi_handle_session() 506** 507** Returns: 508** results from mi_handle_session() 509*/ 510 511void * 512mi_thread_handle_wrapper(arg) 513 void *arg; 514{ 515 return (void *) mi_handle_session(arg); 516} 517 518/* 519** MI_CLOSENER -- close listen socket 520** 521** NOTE: It is assumed that this function is called from a 522** function that has a mutex lock (currently mi_stop_milters()). 523** 524** Parameters: 525** none. 526** 527** Returns: 528** none. 529*/ 530 531void 532mi_closener() 533{ 534 (void) smutex_lock(&L_Mutex); 535 if (ValidSocket(listenfd)) 536 { 537#if NETUNIX 538 bool removable; 539 struct stat sockinfo; 540 struct stat fileinfo; 541 542 removable = sockpath != NULL && 543#if _FFR_MILTER_ROOT_UNSAFE 544 geteuid() != 0 && 545#endif /* _FFR_MILTER_ROOT_UNSAFE */ 546 fstat(listenfd, &sockinfo) == 0 && 547 (S_ISFIFO(sockinfo.st_mode) 548# ifdef S_ISSOCK 549 || S_ISSOCK(sockinfo.st_mode) 550# endif /* S_ISSOCK */ 551 ); 552#endif /* NETUNIX */ 553 554 (void) closesocket(listenfd); 555 listenfd = INVALID_SOCKET; 556 557#if NETUNIX 558 /* XXX sleep() some time before doing this? */ 559 if (sockpath != NULL) 560 { 561 if (removable && 562 stat(sockpath, &fileinfo) == 0 && 563 ((fileinfo.st_dev == sockinfo.st_dev && 564 fileinfo.st_ino == sockinfo.st_ino) 565# ifdef S_ISSOCK 566 || S_ISSOCK(fileinfo.st_mode) 567# endif /* S_ISSOCK */ 568 ) 569 && 570 (S_ISFIFO(fileinfo.st_mode) 571# ifdef S_ISSOCK 572 || S_ISSOCK(fileinfo.st_mode) 573# endif /* S_ISSOCK */ 574 )) 575 (void) unlink(sockpath); 576 free(sockpath); 577 sockpath = NULL; 578 } 579#endif /* NETUNIX */ 580 } 581 (void) smutex_unlock(&L_Mutex); 582} 583 584/* 585** MI_LISTENER -- Generic listener harness 586** 587** Open up listen port 588** Wait for connections 589** 590** Parameters: 591** conn -- connection description 592** dbg -- debug level 593** smfi -- filter structure to use 594** timeout -- timeout for reads/writes 595** backlog -- listen queue backlog size 596** 597** Returns: 598** MI_SUCCESS -- Exited normally 599** (session finished or we were told to exit) 600** MI_FAILURE -- Network initialization failed. 601*/ 602 603#if BROKEN_PTHREAD_SLEEP 604 605/* 606** Solaris 2.6, perhaps others, gets an internal threads library panic 607** when sleep() is used: 608** 609** thread_create() failed, returned 11 (EINVAL) 610** co_enable, thr_create() returned error = 24 611** libthread panic: co_enable failed (PID: 17793 LWP 1) 612** stacktrace: 613** ef526b10 614** ef52646c 615** ef534cbc 616** 156a4 617** 14644 618** 1413c 619** 135e0 620** 0 621*/ 622 623# define MI_SLEEP(s) \ 624{ \ 625 int rs = 0; \ 626 struct timeval st; \ 627 \ 628 st.tv_sec = (s); \ 629 st.tv_usec = 0; \ 630 if (st.tv_sec > 0) \ 631 { \ 632 for (;;) \ 633 { \ 634 rs = select(0, NULL, NULL, NULL, &st); \ 635 if (rs < 0 && errno == EINTR) \ 636 continue; \ 637 if (rs != 0) \ 638 { \ 639 smi_log(SMI_LOG_ERR, \
|
633 "MI_SLEEP(): select() returned non-zero result %d, errno = %d", \
| 640 "MI_SLEEP(): select() returned non-zero result %d, errno = %d", \
|
634 rs, errno); \ 635 } \
| 641 rs, errno); \ 642 } \
|
| 643 break; \
|
636 } \ 637 } \ 638} 639#else /* BROKEN_PTHREAD_SLEEP */ 640# define MI_SLEEP(s) sleep((s)) 641#endif /* BROKEN_PTHREAD_SLEEP */ 642 643int 644mi_listener(conn, dbg, smfi, timeout, backlog) 645 char *conn; 646 int dbg; 647 smfiDesc_ptr smfi; 648 time_t timeout; 649 int backlog; 650{ 651 socket_t connfd = INVALID_SOCKET; 652 int sockopt = 1; 653 int r; 654 int ret = MI_SUCCESS; 655 int mcnt = 0; /* error count for malloc() failures */ 656 int tcnt = 0; /* error count for thread_create() failures */ 657 int acnt = 0; /* error count for accept() failures */ 658 int scnt = 0; /* error count for select() failures */ 659 int save_errno = 0; 660 sthread_t thread_id; 661 _SOCK_ADDR cliaddr; 662 SOCKADDR_LEN_T clilen; 663 SMFICTX_PTR ctx; 664 fd_set readset, excset; 665 struct timeval chktime; 666 667 if (mi_opensocket(conn, backlog, dbg, smfi) == MI_FAILURE) 668 return MI_FAILURE; 669 670 clilen = L_socksize;
| 644 } \ 645 } \ 646} 647#else /* BROKEN_PTHREAD_SLEEP */ 648# define MI_SLEEP(s) sleep((s)) 649#endif /* BROKEN_PTHREAD_SLEEP */ 650 651int 652mi_listener(conn, dbg, smfi, timeout, backlog) 653 char *conn; 654 int dbg; 655 smfiDesc_ptr smfi; 656 time_t timeout; 657 int backlog; 658{ 659 socket_t connfd = INVALID_SOCKET; 660 int sockopt = 1; 661 int r; 662 int ret = MI_SUCCESS; 663 int mcnt = 0; /* error count for malloc() failures */ 664 int tcnt = 0; /* error count for thread_create() failures */ 665 int acnt = 0; /* error count for accept() failures */ 666 int scnt = 0; /* error count for select() failures */ 667 int save_errno = 0; 668 sthread_t thread_id; 669 _SOCK_ADDR cliaddr; 670 SOCKADDR_LEN_T clilen; 671 SMFICTX_PTR ctx; 672 fd_set readset, excset; 673 struct timeval chktime; 674 675 if (mi_opensocket(conn, backlog, dbg, smfi) == MI_FAILURE) 676 return MI_FAILURE; 677 678 clilen = L_socksize;
|
671 672 if (listenfd >= FD_SETSIZE) 673 { 674 smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", 675 smfi->xxfi_name, listenfd, FD_SETSIZE); 676 (void) smutex_unlock(&L_Mutex); 677 return MI_FAILURE; 678 }
| |
679 (void) smutex_unlock(&L_Mutex);
| 679 (void) smutex_unlock(&L_Mutex);
|
680
| |
681 while (mi_stop() == MILTER_CONT) 682 { 683 (void) smutex_lock(&L_Mutex); 684 if (!ValidSocket(listenfd)) 685 { 686 (void) smutex_unlock(&L_Mutex); 687 break; 688 } 689 690 /* select on interface ports */ 691 FD_ZERO(&readset); 692 FD_ZERO(&excset); 693 FD_SET((unsigned int) listenfd, &readset); 694 FD_SET((unsigned int) listenfd, &excset); 695 chktime.tv_sec = MI_CHK_TIME; 696 chktime.tv_usec = 0; 697 r = select(listenfd + 1, &readset, NULL, &excset, &chktime); 698 if (r == 0) /* timeout */ 699 { 700 (void) smutex_unlock(&L_Mutex); 701 continue; /* just check mi_stop() */ 702 } 703 if (r < 0) 704 { 705 save_errno = errno; 706 (void) smutex_unlock(&L_Mutex); 707 if (save_errno == EINTR) 708 continue; 709 scnt++; 710 smi_log(SMI_LOG_ERR, 711 "%s: select() failed (%s), %s", 712 smfi->xxfi_name, sm_errstring(save_errno), 713 scnt >= MAX_FAILS_S ? "abort" : "try again"); 714 MI_SLEEP(scnt); 715 if (scnt >= MAX_FAILS_S) 716 { 717 ret = MI_FAILURE; 718 break; 719 } 720 continue; 721 } 722 if (!FD_ISSET(listenfd, &readset)) 723 { 724 /* some error: just stop for now... */ 725 ret = MI_FAILURE; 726 (void) smutex_unlock(&L_Mutex); 727 smi_log(SMI_LOG_ERR, 728 "%s: select() returned exception for socket, abort", 729 smfi->xxfi_name); 730 break; 731 } 732 scnt = 0; /* reset error counter for select() */ 733 734 memset(&cliaddr, '\0', sizeof cliaddr); 735 connfd = accept(listenfd, (struct sockaddr *) &cliaddr, 736 &clilen); 737 save_errno = errno; 738 (void) smutex_unlock(&L_Mutex); 739 740 /* 741 ** If remote side closes before 742 ** accept() finishes, sockaddr 743 ** might not be fully filled in. 744 */ 745 746 if (ValidSocket(connfd) && 747 (clilen == 0 || 748# ifdef BSD4_4_SOCKADDR 749 cliaddr.sa.sa_len == 0 || 750# endif /* BSD4_4_SOCKADDR */ 751 cliaddr.sa.sa_family != L_family)) 752 { 753 (void) closesocket(connfd); 754 connfd = INVALID_SOCKET; 755 save_errno = EINVAL; 756 } 757
| 680 while (mi_stop() == MILTER_CONT) 681 { 682 (void) smutex_lock(&L_Mutex); 683 if (!ValidSocket(listenfd)) 684 { 685 (void) smutex_unlock(&L_Mutex); 686 break; 687 } 688 689 /* select on interface ports */ 690 FD_ZERO(&readset); 691 FD_ZERO(&excset); 692 FD_SET((unsigned int) listenfd, &readset); 693 FD_SET((unsigned int) listenfd, &excset); 694 chktime.tv_sec = MI_CHK_TIME; 695 chktime.tv_usec = 0; 696 r = select(listenfd + 1, &readset, NULL, &excset, &chktime); 697 if (r == 0) /* timeout */ 698 { 699 (void) smutex_unlock(&L_Mutex); 700 continue; /* just check mi_stop() */ 701 } 702 if (r < 0) 703 { 704 save_errno = errno; 705 (void) smutex_unlock(&L_Mutex); 706 if (save_errno == EINTR) 707 continue; 708 scnt++; 709 smi_log(SMI_LOG_ERR, 710 "%s: select() failed (%s), %s", 711 smfi->xxfi_name, sm_errstring(save_errno), 712 scnt >= MAX_FAILS_S ? "abort" : "try again"); 713 MI_SLEEP(scnt); 714 if (scnt >= MAX_FAILS_S) 715 { 716 ret = MI_FAILURE; 717 break; 718 } 719 continue; 720 } 721 if (!FD_ISSET(listenfd, &readset)) 722 { 723 /* some error: just stop for now... */ 724 ret = MI_FAILURE; 725 (void) smutex_unlock(&L_Mutex); 726 smi_log(SMI_LOG_ERR, 727 "%s: select() returned exception for socket, abort", 728 smfi->xxfi_name); 729 break; 730 } 731 scnt = 0; /* reset error counter for select() */ 732 733 memset(&cliaddr, '\0', sizeof cliaddr); 734 connfd = accept(listenfd, (struct sockaddr *) &cliaddr, 735 &clilen); 736 save_errno = errno; 737 (void) smutex_unlock(&L_Mutex); 738 739 /* 740 ** If remote side closes before 741 ** accept() finishes, sockaddr 742 ** might not be fully filled in. 743 */ 744 745 if (ValidSocket(connfd) && 746 (clilen == 0 || 747# ifdef BSD4_4_SOCKADDR 748 cliaddr.sa.sa_len == 0 || 749# endif /* BSD4_4_SOCKADDR */ 750 cliaddr.sa.sa_family != L_family)) 751 { 752 (void) closesocket(connfd); 753 connfd = INVALID_SOCKET; 754 save_errno = EINVAL; 755 } 756
|
| 757 /* check if acceptable for select() */ 758 if (ValidSocket(connfd) && !SM_FD_OK_SELECT(connfd)) 759 { 760 (void) closesocket(connfd); 761 connfd = INVALID_SOCKET; 762 save_errno = ERANGE; 763 } 764
|
758 if (!ValidSocket(connfd)) 759 { 760 if (save_errno == EINTR) 761 continue; 762 acnt++; 763 smi_log(SMI_LOG_ERR, 764 "%s: accept() returned invalid socket (%s), %s", 765 smfi->xxfi_name, sm_errstring(save_errno), 766 acnt >= MAX_FAILS_A ? "abort" : "try again"); 767 MI_SLEEP(acnt); 768 if (acnt >= MAX_FAILS_A) 769 { 770 ret = MI_FAILURE; 771 break; 772 } 773 continue; 774 } 775 acnt = 0; /* reset error counter for accept() */ 776 777 if (setsockopt(connfd, SOL_SOCKET, SO_KEEPALIVE, 778 (void *) &sockopt, sizeof sockopt) < 0) 779 { 780 smi_log(SMI_LOG_WARN, "%s: setsockopt() failed (%s)", 781 smfi->xxfi_name, sm_errstring(errno)); 782 /* XXX: continue? */ 783 } 784 if ((ctx = (SMFICTX_PTR) malloc(sizeof *ctx)) == NULL) 785 { 786 (void) closesocket(connfd); 787 mcnt++; 788 smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed (%s), %s", 789 smfi->xxfi_name, sm_errstring(save_errno), 790 mcnt >= MAX_FAILS_M ? "abort" : "try again"); 791 MI_SLEEP(mcnt); 792 if (mcnt >= MAX_FAILS_M) 793 { 794 ret = MI_FAILURE; 795 break; 796 } 797 continue; 798 } 799 mcnt = 0; /* reset error counter for malloc() */ 800 memset(ctx, '\0', sizeof *ctx); 801 ctx->ctx_sd = connfd; 802 ctx->ctx_dbg = dbg; 803 ctx->ctx_timeout = timeout; 804 ctx->ctx_smfi = smfi; 805#if 0 806 if (smfi->xxfi_eoh == NULL) 807 if (smfi->xxfi_eom == NULL) 808 if (smfi->xxfi_abort == NULL) 809 if (smfi->xxfi_close == NULL) 810#endif /* 0 */ 811 if (smfi->xxfi_connect == NULL) 812 ctx->ctx_pflags |= SMFIP_NOCONNECT; 813 if (smfi->xxfi_helo == NULL) 814 ctx->ctx_pflags |= SMFIP_NOHELO; 815 if (smfi->xxfi_envfrom == NULL) 816 ctx->ctx_pflags |= SMFIP_NOMAIL; 817 if (smfi->xxfi_envrcpt == NULL) 818 ctx->ctx_pflags |= SMFIP_NORCPT; 819 if (smfi->xxfi_header == NULL) 820 ctx->ctx_pflags |= SMFIP_NOHDRS; 821 if (smfi->xxfi_eoh == NULL) 822 ctx->ctx_pflags |= SMFIP_NOEOH; 823 if (smfi->xxfi_body == NULL) 824 ctx->ctx_pflags |= SMFIP_NOBODY; 825 826 if ((r = thread_create(&thread_id, 827 mi_thread_handle_wrapper, 828 (void *) ctx)) != 0) 829 { 830 tcnt++; 831 smi_log(SMI_LOG_ERR, 832 "%s: thread_create() failed: %d, %s", 833 smfi->xxfi_name, r, 834 tcnt >= MAX_FAILS_T ? "abort" : "try again"); 835 MI_SLEEP(tcnt); 836 (void) closesocket(connfd); 837 free(ctx); 838 if (tcnt >= MAX_FAILS_T) 839 { 840 ret = MI_FAILURE; 841 break; 842 } 843 continue; 844 } 845 tcnt = 0; 846 } 847 if (ret != MI_SUCCESS) 848 mi_stop_milters(MILTER_ABRT); 849 else 850 mi_closener(); 851 (void) smutex_destroy(&L_Mutex); 852 return ret; 853}
| 765 if (!ValidSocket(connfd)) 766 { 767 if (save_errno == EINTR) 768 continue; 769 acnt++; 770 smi_log(SMI_LOG_ERR, 771 "%s: accept() returned invalid socket (%s), %s", 772 smfi->xxfi_name, sm_errstring(save_errno), 773 acnt >= MAX_FAILS_A ? "abort" : "try again"); 774 MI_SLEEP(acnt); 775 if (acnt >= MAX_FAILS_A) 776 { 777 ret = MI_FAILURE; 778 break; 779 } 780 continue; 781 } 782 acnt = 0; /* reset error counter for accept() */ 783 784 if (setsockopt(connfd, SOL_SOCKET, SO_KEEPALIVE, 785 (void *) &sockopt, sizeof sockopt) < 0) 786 { 787 smi_log(SMI_LOG_WARN, "%s: setsockopt() failed (%s)", 788 smfi->xxfi_name, sm_errstring(errno)); 789 /* XXX: continue? */ 790 } 791 if ((ctx = (SMFICTX_PTR) malloc(sizeof *ctx)) == NULL) 792 { 793 (void) closesocket(connfd); 794 mcnt++; 795 smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed (%s), %s", 796 smfi->xxfi_name, sm_errstring(save_errno), 797 mcnt >= MAX_FAILS_M ? "abort" : "try again"); 798 MI_SLEEP(mcnt); 799 if (mcnt >= MAX_FAILS_M) 800 { 801 ret = MI_FAILURE; 802 break; 803 } 804 continue; 805 } 806 mcnt = 0; /* reset error counter for malloc() */ 807 memset(ctx, '\0', sizeof *ctx); 808 ctx->ctx_sd = connfd; 809 ctx->ctx_dbg = dbg; 810 ctx->ctx_timeout = timeout; 811 ctx->ctx_smfi = smfi; 812#if 0 813 if (smfi->xxfi_eoh == NULL) 814 if (smfi->xxfi_eom == NULL) 815 if (smfi->xxfi_abort == NULL) 816 if (smfi->xxfi_close == NULL) 817#endif /* 0 */ 818 if (smfi->xxfi_connect == NULL) 819 ctx->ctx_pflags |= SMFIP_NOCONNECT; 820 if (smfi->xxfi_helo == NULL) 821 ctx->ctx_pflags |= SMFIP_NOHELO; 822 if (smfi->xxfi_envfrom == NULL) 823 ctx->ctx_pflags |= SMFIP_NOMAIL; 824 if (smfi->xxfi_envrcpt == NULL) 825 ctx->ctx_pflags |= SMFIP_NORCPT; 826 if (smfi->xxfi_header == NULL) 827 ctx->ctx_pflags |= SMFIP_NOHDRS; 828 if (smfi->xxfi_eoh == NULL) 829 ctx->ctx_pflags |= SMFIP_NOEOH; 830 if (smfi->xxfi_body == NULL) 831 ctx->ctx_pflags |= SMFIP_NOBODY; 832 833 if ((r = thread_create(&thread_id, 834 mi_thread_handle_wrapper, 835 (void *) ctx)) != 0) 836 { 837 tcnt++; 838 smi_log(SMI_LOG_ERR, 839 "%s: thread_create() failed: %d, %s", 840 smfi->xxfi_name, r, 841 tcnt >= MAX_FAILS_T ? "abort" : "try again"); 842 MI_SLEEP(tcnt); 843 (void) closesocket(connfd); 844 free(ctx); 845 if (tcnt >= MAX_FAILS_T) 846 { 847 ret = MI_FAILURE; 848 break; 849 } 850 continue; 851 } 852 tcnt = 0; 853 } 854 if (ret != MI_SUCCESS) 855 mi_stop_milters(MILTER_ABRT); 856 else 857 mi_closener(); 858 (void) smutex_destroy(&L_Mutex); 859 return ret; 860}
|