00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef __GNUC__
00037 #define _GNU_SOURCE
00038 #endif
00039
00040 #ifdef HAVE_CONFIG_H
00041 # include "config.h"
00042 #endif
00043
00044 #ifdef STDC_HEADERS
00045 # include <stdio.h>
00046 # include <stdlib.h>
00047 # include <stddef.h>
00048 # include <stdarg.h>
00049 #endif
00050
00051 #ifdef HAVE_SYS_TYPES_H
00052 #include <sys/types.h>
00053 #endif
00054
00055 #ifdef HAVE_INTTYPES_H
00056 #include <inttypes.h>
00057 #endif
00058
00059 #ifdef HAVE_STRING_H
00060 # include <string.h>
00061 #else
00062 # ifdef HAVE_STRINGS_H
00063 # include <strings.h>
00064 # endif
00065 #endif
00066
00067 #ifdef HAVE_SYS_SOCKET_H
00068 # include <sys/socket.h>
00069 #endif
00070 #ifdef HAVE_NETINET_IN_H
00071 # include <netinet/in.h>
00072 #endif
00073 #ifdef HAVE_ARPA_INET_H
00074 # include <arpa/inet.h>
00075 #endif
00076
00077 #ifdef HAVE_ARPA_NAMESER_H
00078 # include <arpa/nameser.h>
00079 #endif
00080
00081 #include <sys/types.h>
00082
00083 #ifdef HAVE_PWD_H
00084 #include <pwd.h>
00085 #endif
00086
00087 #ifdef HAVE_GRP_H
00088 #include <grp.h>
00089 #endif
00090
00091 #ifdef HAVE_GETOPT_LONG_ONLY
00092 #define _GNU_SOURCE
00093 #include <getopt.h>
00094 #else
00095 #include "libreplace/getopt.h"
00096 #endif
00097
00098 #include <unistd.h>
00099 #include <netdb.h>
00100 #include <fcntl.h>
00101 #include <time.h>
00102 #include <signal.h>
00103 #include <syslog.h>
00104 #include <errno.h>
00105 #include <sys/types.h>
00106 #include <sys/stat.h>
00107 #include <sys/socket.h>
00108 #include <sys/un.h>
00109 #include <netinet/in.h>
00110 #include <ctype.h>
00111 #include <sys/wait.h>
00112
00113 #include <pthread.h>
00114
00115 #include "spf.h"
00116 #include "spf_dns.h"
00117 #include "spf_dns_null.h"
00118 #include "spf_dns_resolv.h"
00119 #include "spf_dns_test.h"
00120 #include "spf_dns_cache.h"
00121
00122
00123 #define TRUE 1
00124 #define FALSE 0
00125
00126 #define bool int
00127
00128 #define FREE(x, f) do { if ((x)) (f)((x)); (x) = NULL; } while(0)
00129 #define FREE_REQUEST(x) FREE((x), SPF_request_free)
00130 #define FREE_RESPONSE(x) FREE((x), SPF_response_free)
00131 #define FREE_STRING(x) FREE((x), free)
00132
00133 typedef
00134 struct _config_t {
00135 int tcpport;
00136 int udpport;
00137 char *path;
00138 #ifdef HAVE_PWD_H
00139 uid_t pathuser;
00140 #endif
00141 #ifdef HAVE_GRP_H
00142 gid_t pathgroup;
00143 #endif
00144 int pathmode;
00145 #ifdef HAVE_PWD_H
00146 uid_t setuser;
00147 #endif
00148 #ifdef HAVE_GRP_H
00149 gid_t setgroup;
00150 #endif
00151
00152 int debug;
00153 bool sec_mx;
00154 char *fallback;
00155
00156 char *rec_dom;
00157 bool sanitize;
00158 int max_lookup;
00159 char *localpolicy;
00160 bool use_trusted;
00161 char *explanation;
00162 } config_t;
00163
00164 typedef
00165 struct _request_t {
00166 int sock;
00167 union {
00168 struct sockaddr_in in;
00169 struct sockaddr_un un;
00170 } addr;
00171 socklen_t addrlen;
00172 char *data;
00173 int datalen;
00174
00175 char *ip;
00176 char *helo;
00177 char *sender;
00178 char *rcpt_to;
00179
00180 SPF_errcode_t spf_err;
00181 SPF_request_t *spf_request;
00182 SPF_response_t *spf_response;
00183
00184 char fmt[4096];
00185 int fmtlen;
00186 } request_t;
00187
00188 typedef
00189 struct _state_t {
00190 int sock_udp;
00191 int sock_tcp;
00192 int sock_unix;
00193 } state_t;
00194
00195 static SPF_server_t *spf_server;
00196 static config_t spfd_config;
00197 static state_t spfd_state;
00198
00199 static void
00200 response_print_errors(const char *context,
00201 SPF_response_t *spf_response, SPF_errcode_t err)
00202 {
00203 SPF_error_t *spf_error;
00204 int i;
00205
00206 if (context != NULL)
00207 printf("Context: %s\n", context);
00208 if (err != SPF_E_SUCCESS)
00209 printf("ErrorCode: (%d) %s\n", err, SPF_strerror(err));
00210
00211 if (spf_response != NULL) {
00212 for (i = 0; i < SPF_response_messages(spf_response); i++) {
00213 spf_error = SPF_response_message(spf_response, i);
00214 printf( "%s: %s%s\n",
00215 SPF_error_errorp(spf_error) ? "Error" : "Warning",
00216 ((SPF_error_errorp(spf_error) && (!err))
00217 ? "[UNRETURNED] "
00218 : ""),
00219 SPF_error_message(spf_error) );
00220 }
00221 }
00222 else {
00223 printf("Error: libspf2 gave a NULL spf_response");
00224 }
00225 }
00226
00227 static void
00228 response_print(const char *context, SPF_response_t *spf_response)
00229 {
00230 printf("--vv--\n");
00231 printf("Context: %s\n", context);
00232 if (spf_response == NULL) {
00233 printf("NULL RESPONSE!\n");
00234 }
00235 else {
00236 printf("Response result: %s\n",
00237 SPF_strresult(SPF_response_result(spf_response)));
00238 printf("Response reason: %s\n",
00239 SPF_strreason(SPF_response_reason(spf_response)));
00240 printf("Response err: %s\n",
00241 SPF_strerror(SPF_response_errcode(spf_response)));
00242 response_print_errors(NULL, spf_response,
00243 SPF_response_errcode(spf_response));
00244 }
00245 printf("--^^--\n");
00246 }
00247
00248 static const char *
00249 request_check(request_t *req)
00250 {
00251 const char *msg = NULL;
00252 if (!req->ip)
00253 msg = "No IP address given";
00254 else if (!req->sender)
00255 msg = "No sender address given";
00256 else
00257 return NULL;
00258 snprintf(req->fmt, 4095,
00259 "result=unknown\n"
00260 "reason=%s\n",
00261 msg);
00262 return msg;
00263 }
00264
00265 static void
00266 request_query(request_t *req)
00267 {
00268 SPF_request_t *spf_request = NULL;
00269 SPF_response_t *spf_response = NULL;
00270 SPF_response_t *spf_response_2mx = NULL;
00271 SPF_errcode_t err;
00272 char *p, *p_end;
00273
00274 #define UNLESS(x) err = (x); if (err)
00275
00276 #define FAIL(x) do { goto fail; } while(0)
00277 #define WARN(x, r) response_print_errors((x), (r), err)
00278
00279 spf_request = SPF_request_new(spf_server);
00280
00281 if (strchr(req->ip, ':')) {
00282 UNLESS(SPF_request_set_ipv6_str(spf_request, req->ip)) {
00283 FAIL("Setting IPv6 address");
00284 }
00285 }
00286 else {
00287 UNLESS(SPF_request_set_ipv4_str(spf_request, req->ip)) {
00288 FAIL("Setting IPv4 address");
00289 }
00290 }
00291
00292 if (req->helo) {
00293 UNLESS(SPF_request_set_helo_dom(spf_request, req->helo)) {
00294 FAIL("Failed to set HELO domain");
00295 }
00296
00297 }
00298
00299 if (req->sender) {
00300 UNLESS(SPF_request_set_env_from(spf_request, req->sender)) {
00301 FAIL("Failed to set envelope-from address");
00302 }
00303
00304 }
00305
00306
00307
00308 UNLESS(SPF_request_query_mailfrom(spf_request, &spf_response)) {
00309 FAIL("Failed to query based on mail-from address");
00310 }
00311
00312 if (spfd_config.sec_mx) {
00313 if (req->rcpt_to && *req->rcpt_to) {
00314 p = req->rcpt_to;
00315 p_end = p + strcspn(p, " ,;");
00316 while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) {
00317 if (*p_end)
00318 *p_end = '\0';
00319 else
00320 p_end = NULL;
00321 UNLESS(SPF_request_query_rcptto(spf_request,
00322 &spf_response_2mx, p)) {
00323 WARN("Failed to query based on 2mx recipient",
00324 spf_response_2mx);
00325 FREE_RESPONSE(spf_response_2mx);
00326 }
00327 else {
00328 spf_response = SPF_response_combine(spf_response,
00329 spf_response_2mx);
00330 spf_response_2mx = NULL;
00331 }
00332
00333 if (!p_end)
00334 break;
00335 p = p_end + 1;
00336 }
00337 }
00338 }
00339
00340 if (spfd_config.fallback) {
00341 UNLESS(SPF_request_query_fallback(spf_request,
00342 &spf_response, spfd_config.fallback)) {
00343 FAIL("Querying fallback record");
00344 }
00345 }
00346
00347 goto ok;
00348
00349 fail:
00350 req->spf_err = err;
00351 FREE_RESPONSE(spf_response);
00352 FREE_REQUEST(spf_request);
00353
00354 ok:
00355
00356 (void)response_print;
00357
00358 req->spf_response = spf_response;
00359 req->spf_request = spf_request;
00360 }
00361
00362
00363 static inline const char *
00364 W(const char *c)
00365 {
00366 if (c)
00367 return c;
00368 return "(null)";
00369 }
00370
00371 static void
00372 request_format(request_t *req)
00373 {
00374 SPF_response_t *spf_response;
00375
00376 spf_response = req->spf_response;
00377
00378 if (spf_response) {
00379 req->fmtlen = snprintf(req->fmt, 4095,
00380 "ip=%s\n"
00381 "sender=%s\n"
00382 "result=%s\n"
00383 "reason=%s\n"
00384 "smtp_comment=%s\n"
00385 "header_comment=%s\n"
00386 "error=%s\n"
00387 , req->ip, req->sender
00388 , W(SPF_strresult(SPF_response_result(spf_response)))
00389 , W(SPF_strreason(SPF_response_reason(spf_response)))
00390 , W(SPF_response_get_smtp_comment(spf_response))
00391 , W(SPF_response_get_header_comment(spf_response))
00392 , W(SPF_strerror(SPF_response_errcode(spf_response)))
00393 );
00394 }
00395 else {
00396 req->fmtlen = snprintf(req->fmt, 4095,
00397 "ip=%s\n"
00398 "sender=%s\n"
00399 "result=unknown\n"
00400 "error=%s\n"
00401 , req->ip, req->sender
00402 , SPF_strerror(req->spf_err)
00403 );
00404 }
00405
00406 req->fmt[4095] = '\0';
00407 }
00408
00409 static void
00410 request_handle(request_t *req)
00411 {
00412 printf("| %s\n", req->sender); fflush(stdout);
00413 if (!request_check(req)) {
00414 request_query(req);
00415 request_format(req);
00416 }
00417
00418 }
00419
00420 static const struct option longopts[] = {
00421 { "debug", required_argument, NULL, 'd', },
00422 { "tcpport", required_argument, NULL, 't', },
00423 { "udpport", required_argument, NULL, 'p', },
00424 { "path", required_argument, NULL, 'f', },
00425 #ifdef HAVE_PWD_H
00426 { "pathuser", required_argument, NULL, 'x', },
00427 #endif
00428 #ifdef HAVE_GRP_H
00429 { "pathgroup", required_argument, NULL, 'y', },
00430 #endif
00431 { "pathmode", required_argument, NULL, 'm', },
00432 #ifdef HAVE_PWD_H
00433 { "setuser", required_argument, NULL, 'u', },
00434 #endif
00435 #ifdef HAVE_GRP_H
00436 { "setgroup", required_argument, NULL, 'g', },
00437 #endif
00438 { "help", no_argument, NULL, 'h', },
00439 };
00440
00441 static const char *shortopts = "d:t:p:f:x:y:m:u:g:h:";
00442
00443 void usage (void) {
00444 fprintf(stdout,"Flags\n");
00445 fprintf(stdout,"\t-tcpport\n");
00446 fprintf(stdout,"\t-udpport\n");
00447 fprintf(stdout,"\t-path\n");
00448 #ifdef HAVE_PWD_H
00449 fprintf(stdout,"\t-pathuser\n");
00450 #endif
00451 #ifdef HAVE_GRP_H
00452 fprintf(stdout,"\t-pathgroup\n");
00453 #endif
00454 fprintf(stdout,"\t-pathmode\n");
00455 #ifdef HAVE_PWD_H
00456 fprintf(stdout,"\t-setuser\n");
00457 #endif
00458 #ifdef HAVE_GRP_H
00459 fprintf(stdout,"\t-setgroup\n");
00460 #endif
00461 fprintf(stdout,"\t-help\n");
00462
00463 }
00464
00465 #define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
00466
00467 #ifdef HAVE_PWD_H
00468 static gid_t
00469 daemon_get_user(const char *arg)
00470 {
00471 struct passwd *pwd;
00472 if (isdigit(arg[0]))
00473 pwd = getpwuid(atol(arg));
00474 else
00475 pwd = getpwnam(arg);
00476 if (pwd == NULL) {
00477 fprintf(stderr, "Failed to find user %s\n", arg);
00478 DIE("Unknown user");
00479 }
00480 return pwd->pw_uid;
00481 }
00482 #endif
00483
00484 #ifdef HAVE_GRP_H
00485 static gid_t
00486 daemon_get_group(const char *arg)
00487 {
00488 struct group *grp;
00489 if (isdigit(arg[0]))
00490 grp = getgrgid(atol(arg));
00491 else
00492 grp = getgrnam(arg);
00493 if (grp == NULL) {
00494 fprintf(stderr, "Failed to find user %s\n", arg);
00495 DIE("Unknown group");
00496 }
00497 return grp->gr_gid;
00498 }
00499 #endif
00500
00501 static void
00502 daemon_config(int argc, char *argv[])
00503 {
00504 int idx;
00505 char c;
00506
00507 memset(&spfd_config, 0, sizeof(spfd_config));
00508
00509 while ((c =
00510 getopt_long(argc, argv, shortopts, longopts, &idx)
00511 ) != -1) {
00512 switch (c) {
00513 case 't':
00514 spfd_config.tcpport = atol(optarg);
00515 break;
00516 case 'p':
00517 spfd_config.udpport = atol(optarg);
00518 break;
00519 case 'f':
00520 spfd_config.path = optarg;
00521 break;
00522
00523 case 'd':
00524 spfd_config.debug = atol(optarg);
00525 break;
00526
00527 #ifdef HAVE_PWD_H
00528 case 'x':
00529 spfd_config.pathuser = daemon_get_user(optarg);
00530 break;
00531 #endif
00532 #ifdef HAVE_GRP_H
00533 case 'y':
00534 spfd_config.pathgroup = daemon_get_group(optarg);
00535 break;
00536 #endif
00537
00538 case 'm':
00539 spfd_config.pathmode = atol(optarg);
00540 break;
00541
00542 #ifdef HAVE_PWD_H
00543 case 'u':
00544 spfd_config.setuser = daemon_get_user(optarg);
00545 break;
00546 #endif
00547 #ifdef HAVE_GRP_H
00548 case 'g':
00549 spfd_config.setgroup = daemon_get_group(optarg);
00550 break;
00551 #endif
00552
00553 case 0:
00554 case '?':
00555 usage();
00556 DIE("Invalid argument");
00557 break;
00558 case 'h' :
00559 usage();
00560 DIE("");
00561 break;
00562
00563 default:
00564 fprintf(stderr, "Error: getopt returned character code 0%o ??\n", c);
00565 DIE("WHAT?");
00566 }
00567 }
00568 }
00569
00570 static int
00571 daemon_bind_inet_udp()
00572 {
00573 struct sockaddr_in addr;
00574 int sock;
00575
00576 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00577 perror("socket");
00578 DIE("Failed to create socket");
00579 }
00580 memset(&addr, 0, sizeof(addr));
00581 addr.sin_family = AF_INET;
00582 addr.sin_port = htons(spfd_config.udpport);
00583 addr.sin_addr.s_addr = INADDR_ANY;
00584 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00585 perror("bind");
00586 DIE("Failed to bind socket");
00587 }
00588
00589 fprintf(stderr, "Accepting datagrams on %d\n", spfd_config.udpport);
00590
00591 return sock;
00592 }
00593
00594 static int
00595 daemon_bind_inet_tcp()
00596 {
00597 struct sockaddr_in addr;
00598 int sock;
00599
00600 int optval;
00601 size_t optlen;
00602
00603 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00604 perror("socket");
00605 DIE("Failed to create socket");
00606 }
00607
00608 optval = 1;
00609 optlen = sizeof(int);
00610 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
00611
00612 memset(&addr, 0, sizeof(addr));
00613 addr.sin_family = AF_INET;
00614 addr.sin_port = htons(spfd_config.tcpport);
00615 addr.sin_addr.s_addr = INADDR_ANY;
00616 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00617 perror("bind");
00618 DIE("Failed to bind socket");
00619 }
00620
00621 if (listen(sock, 5) < 0) {
00622 perror("listen");
00623 DIE("Failed to listen on socket");
00624 }
00625
00626 fprintf(stderr, "Accepting connections on %d\n", spfd_config.tcpport);
00627
00628 return sock;
00629 }
00630
00631 static int
00632 daemon_bind_unix()
00633 {
00634 struct sockaddr_un addr;
00635 int sock;
00636
00637 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
00638 perror("socket");
00639 DIE("Failed to create socket");
00640 }
00641 memset(&addr, 0, sizeof(addr));
00642 addr.sun_family = AF_UNIX;
00643 strncpy(addr.sun_path, spfd_config.path, sizeof(addr.sun_path) - 1);
00644 if (unlink(spfd_config.path) < 0) {
00645 if (errno != ENOENT) {
00646 perror("unlink");
00647 DIE("Failed to unlink socket");
00648 }
00649 }
00650 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00651 perror("bind");
00652 DIE("Failed to bind socket");
00653 }
00654 if (listen(sock, 5) < 0) {
00655 perror("listen");
00656 DIE("Failed to listen on socket");
00657 }
00658
00659 fprintf(stderr, "Accepting connections on %s\n", spfd_config.path);
00660
00661 return sock;
00662 }
00663
00664 static void
00665 daemon_init()
00666 {
00667 SPF_response_t *spf_response = NULL;
00668 SPF_errcode_t err;
00669
00670 memset(&spfd_state, 0, sizeof(spfd_state));
00671
00672 spf_server = SPF_server_new(SPF_DNS_CACHE, spfd_config.debug);
00673
00674 if (spfd_config.rec_dom) {
00675 UNLESS(SPF_server_set_rec_dom(spf_server,
00676 spfd_config.rec_dom)) {
00677 DIE("Failed to set receiving domain name");
00678 }
00679 }
00680
00681 if (spfd_config.sanitize) {
00682 UNLESS(SPF_server_set_sanitize(spf_server,
00683 spfd_config.sanitize)) {
00684 DIE("Failed to set server sanitize flag");
00685 }
00686 }
00687
00688 if (spfd_config.max_lookup) {
00689 UNLESS(SPF_server_set_max_dns_mech(spf_server,
00690 spfd_config.max_lookup)){
00691 DIE("Failed to set maximum DNS requests");
00692 }
00693 }
00694
00695 if (spfd_config.localpolicy) {
00696 UNLESS(SPF_server_set_localpolicy(spf_server,
00697 spfd_config.localpolicy,
00698 spfd_config.use_trusted,
00699 &spf_response)){
00700 response_print_errors("Compiling local policy",
00701 spf_response, err);
00702 DIE("Failed to set local policy");
00703 }
00704 FREE_RESPONSE(spf_response);
00705 }
00706
00707 if (spfd_config.explanation) {
00708 UNLESS(SPF_server_set_explanation(spf_server,
00709 spfd_config.explanation,
00710 &spf_response)){
00711 response_print_errors("Setting default explanation",
00712 spf_response, err);
00713 DIE("Failed to set default explanation");
00714 }
00715 FREE_RESPONSE(spf_response);
00716 }
00717
00718 if (spfd_config.udpport)
00719 spfd_state.sock_udp = daemon_bind_inet_udp();
00720 if (spfd_config.tcpport)
00721 spfd_state.sock_tcp = daemon_bind_inet_tcp();
00722 if (spfd_config.path)
00723 spfd_state.sock_unix = daemon_bind_unix();
00724
00725 }
00726
00727
00728
00729 static char **
00730 find_field(request_t *req, const char *key)
00731 {
00732 #define STREQ(a, b) (strcmp((a), (b)) == 0)
00733
00734 if (STREQ(key, "ip"))
00735 return &req->ip;
00736 if (STREQ(key, "helo"))
00737 return &req->helo;
00738 if (STREQ(key, "sender"))
00739 return &req->sender;
00740 if (STREQ(key, "rcpt"))
00741 return &req->rcpt_to;
00742 fprintf(stderr, "Invalid key %s\n", key);
00743 return NULL;
00744 }
00745
00746
00747 static void *
00748 handle_datagram(void *arg)
00749 {
00750 request_t *req;
00751 char **fp;
00752 char *key;
00753 char *value;
00754 char *end;
00755 int err;
00756
00757 req = (request_t *)arg;
00758 key = req->data;
00759
00760
00761
00762 while (key < (req->data + req->datalen)) {
00763 end = key + strcspn(key, "\r\n");
00764 *end = '\0';
00765 value = strchr(key, '=');
00766
00767
00768 if (!value)
00769 continue;
00770
00771 *value++ = '\0';
00772 fp = find_field(req, key);
00773 if (fp != NULL)
00774 *fp = value;
00775 else
00776 ;
00777
00778 key = end + 1;
00779 while (key < (req->data + req->datalen)) {
00780 if (strchr("\r\n", *key))
00781 key++;
00782 else
00783 break;
00784 }
00785 }
00786
00787 request_handle(req);
00788
00789 #ifdef DEBUG
00790 printf("Target address length is %d: %s:%d\n", req->addrlen,
00791 inet_ntoa(req->addr.in.sin_addr),
00792 req->addr.in.sin_port);
00793 #endif
00794
00795 printf("- %s\n", req->sender); fflush(stdout);
00796 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
00797 (struct sockaddr *)(&req->addr.in), req->addrlen);
00798 if (err == -1)
00799 perror("sendto");
00800
00801 FREE_RESPONSE(req->spf_response);
00802 FREE_REQUEST(req->spf_request);
00803
00804 FREE_STRING(req->data);
00805 free(arg);
00806 return NULL;
00807 }
00808
00809
00810 static void *
00811 handle_stream(void *arg)
00812 {
00813 request_t *req;
00814 char **fp;
00815 FILE *stream;
00816 char key[BUFSIZ];
00817 char *value;
00818 char *end;
00819
00820 req = (request_t *)arg;
00821 stream = fdopen(req->sock, "r");
00822
00823 do {
00824 while (fgets(key, BUFSIZ, stream) != NULL) {
00825 key[strcspn(key, "\r\n")] = '\0';
00826
00827
00828 if (*key == '\0')
00829 break;
00830
00831 end = key + strcspn(key, "\r\n");
00832 *end = '\0';
00833 value = strchr(key, '=');
00834
00835 if (!value)
00836 continue;
00837
00838 *value++ = '\0';
00839 fp = find_field(req, key);
00840 if (fp != NULL)
00841 *fp = strdup(value);
00842 else
00843 ;
00844 }
00845
00846 request_handle(req);
00847
00848 printf("- %s\n", req->sender); fflush(stdout);
00849 send(req->sock, req->fmt, req->fmtlen, 0);
00850
00851 FREE_STRING(req->ip);
00852 FREE_STRING(req->helo);
00853 FREE_STRING(req->sender);
00854 FREE_STRING(req->rcpt_to);
00855 } while (!feof(stream));
00856
00857 free(arg);
00858 return NULL;
00859 }
00860
00861 static void
00862 daemon_main()
00863 {
00864 pthread_attr_t attr;
00865 pthread_t th;
00866
00867 request_t *req;
00868 char buf[4096];
00869 fd_set rfd;
00870 fd_set sfd;
00871 int maxfd;
00872
00873
00874 pthread_attr_init(&attr);
00875 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00876
00877 FD_ZERO(&rfd);
00878 maxfd = 0;
00879
00880 if (spfd_state.sock_udp) {
00881
00882 FD_SET(spfd_state.sock_udp, &rfd);
00883 if (spfd_state.sock_udp > maxfd)
00884 maxfd = spfd_state.sock_udp;
00885 }
00886 if (spfd_state.sock_tcp) {
00887
00888 FD_SET(spfd_state.sock_tcp, &rfd);
00889 if (spfd_state.sock_tcp > maxfd)
00890 maxfd = spfd_state.sock_tcp;
00891 }
00892 if (spfd_state.sock_unix) {
00893
00894 FD_SET(spfd_state.sock_unix, &rfd);
00895 if (spfd_state.sock_unix > maxfd)
00896 maxfd = spfd_state.sock_unix;
00897 }
00898
00899
00900 #define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
00901
00902 for (;;) {
00903 memcpy(&sfd, &rfd, sizeof(rfd));
00904 if (select(maxfd + 1, &sfd, NULL, NULL, NULL) == -1)
00905 break;
00906
00907 if (spfd_state.sock_udp) {
00908 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
00909 req = NEW_REQUEST;
00910 req->addrlen = sizeof(req->addr);
00911
00912 req->sock = spfd_state.sock_udp;
00913 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
00914 (struct sockaddr *)(&req->addr.in), &req->addrlen);
00915 if (req->datalen >= 0) {
00916 buf[req->datalen] = '\0';
00917 req->data = strdup(buf);
00918 pthread_create(&th, &attr, handle_datagram, req);
00919 }
00920 else {
00921 free(req);
00922 }
00923 }
00924 }
00925 if (spfd_state.sock_tcp) {
00926 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
00927 req = NEW_REQUEST;
00928 req->addrlen = sizeof(req->addr);
00929
00930 req->sock = accept(spfd_state.sock_tcp,
00931 (struct sockaddr *)(&req->addr.in), &req->addrlen);
00932 if (req->sock >= 0)
00933 pthread_create(&th, &attr, handle_stream, req);
00934 else
00935 free(req);
00936 }
00937 }
00938 if (spfd_state.sock_unix) {
00939 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
00940 req = NEW_REQUEST;
00941 req->addrlen = sizeof(req->addr);
00942
00943 req->sock = accept(spfd_state.sock_unix,
00944 (struct sockaddr *)(&req->addr.un), &req->addrlen);
00945 if (req->sock >= 0)
00946 pthread_create(&th, &attr, handle_stream, req);
00947 else
00948 free(req);
00949 }
00950 }
00951 }
00952
00953 pthread_attr_destroy(&attr);
00954 }
00955
00956 int
00957 main(int argc, char *argv[])
00958 {
00959 daemon_config(argc, argv);
00960 daemon_init();
00961 daemon_main();
00962 return 0;
00963 }