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