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
00357 req->spf_response = spf_response;
00358 req->spf_request = spf_request;
00359 }
00360
00361
00362 static inline const char *
00363 W(const char *c)
00364 {
00365 if (c)
00366 return c;
00367 return "(null)";
00368 }
00369
00370 static void
00371 request_format(request_t *req)
00372 {
00373 SPF_response_t *spf_response;
00374
00375 spf_response = req->spf_response;
00376
00377 if (spf_response) {
00378 req->fmtlen = snprintf(req->fmt, 4095,
00379 "ip=%s\n"
00380 "sender=%s\n"
00381 "result=%s\n"
00382 "reason=%s\n"
00383 "smtp_comment=%s\n"
00384 "header_comment=%s\n"
00385 "error=%s\n"
00386 , req->ip, req->sender
00387 , W(SPF_strresult(SPF_response_result(spf_response)))
00388 , W(SPF_strreason(SPF_response_reason(spf_response)))
00389 , W(SPF_response_get_smtp_comment(spf_response))
00390 , W(SPF_response_get_header_comment(spf_response))
00391 , W(SPF_strerror(SPF_response_errcode(spf_response)))
00392 );
00393 }
00394 else {
00395 req->fmtlen = snprintf(req->fmt, 4095,
00396 "ip=%s\n"
00397 "sender=%s\n"
00398 "result=unknown\n"
00399 "error=%s\n"
00400 , req->ip, req->sender
00401 , SPF_strerror(req->spf_err)
00402 );
00403 }
00404
00405 req->fmt[4095] = '\0';
00406 }
00407
00408 static void
00409 request_handle(request_t *req)
00410 {
00411 printf("| %s\n", req->sender); fflush(stdout);
00412 if (!request_check(req)) {
00413 request_query(req);
00414 request_format(req);
00415 }
00416
00417 }
00418
00419 static const struct option longopts[] = {
00420 { "debug", required_argument, NULL, 'd', },
00421 { "tcpport", required_argument, NULL, 't', },
00422 { "udpport", required_argument, NULL, 'p', },
00423 { "path", required_argument, NULL, 'f', },
00424 #ifdef HAVE_PWD_H
00425 { "pathuser", required_argument, NULL, 'x', },
00426 #endif
00427 #ifdef HAVE_GRP_H
00428 { "pathgroup", required_argument, NULL, 'y', },
00429 #endif
00430 { "pathmode", required_argument, NULL, 'm', },
00431 #ifdef HAVE_PWD_H
00432 { "setuser", required_argument, NULL, 'u', },
00433 #endif
00434 #ifdef HAVE_GRP_H
00435 { "setgroup", required_argument, NULL, 'g', },
00436 #endif
00437 { "help", no_argument, NULL, 'h', },
00438 };
00439
00440 static const char *shortopts = "d:t:p:f:x:y:m:u:g:h:";
00441
00442 void usage (void) {
00443 fprintf(stdout,"Flags\n");
00444 fprintf(stdout,"\t-tcpport\n");
00445 fprintf(stdout,"\t-udpport\n");
00446 fprintf(stdout,"\t-path\n");
00447 #ifdef HAVE_PWD_H
00448 fprintf(stdout,"\t-pathuser\n");
00449 #endif
00450 #ifdef HAVE_GRP_H
00451 fprintf(stdout,"\t-pathgroup\n");
00452 #endif
00453 fprintf(stdout,"\t-pathmode\n");
00454 #ifdef HAVE_PWD_H
00455 fprintf(stdout,"\t-setuser\n");
00456 #endif
00457 #ifdef HAVE_GRP_H
00458 fprintf(stdout,"\t-setgroup\n");
00459 #endif
00460 fprintf(stdout,"\t-help\n");
00461
00462 }
00463
00464 #define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
00465
00466 #ifdef HAVE_PWD_H
00467 static gid_t
00468 daemon_get_user(const char *arg)
00469 {
00470 struct passwd *pwd;
00471 if (isdigit(arg[0]))
00472 pwd = getpwuid(atol(arg));
00473 else
00474 pwd = getpwnam(arg);
00475 if (pwd == NULL) {
00476 fprintf(stderr, "Failed to find user %s\n", arg);
00477 DIE("Unknown user");
00478 }
00479 return pwd->pw_uid;
00480 }
00481 #endif
00482
00483 #ifdef HAVE_GRP_H
00484 static gid_t
00485 daemon_get_group(const char *arg)
00486 {
00487 struct group *grp;
00488 if (isdigit(arg[0]))
00489 grp = getgrgid(atol(arg));
00490 else
00491 grp = getgrnam(arg);
00492 if (grp == NULL) {
00493 fprintf(stderr, "Failed to find user %s\n", arg);
00494 DIE("Unknown group");
00495 }
00496 return grp->gr_gid;
00497 }
00498 #endif
00499
00500 static void
00501 daemon_config(int argc, char *argv[])
00502 {
00503 int idx;
00504 char c;
00505
00506 memset(&spfd_config, 0, sizeof(spfd_config));
00507
00508 while ((c =
00509 getopt_long(argc, argv, shortopts, longopts, &idx)
00510 ) != -1) {
00511 switch (c) {
00512 case 't':
00513 spfd_config.tcpport = atol(optarg);
00514 break;
00515 case 'p':
00516 spfd_config.udpport = atol(optarg);
00517 break;
00518 case 'f':
00519 spfd_config.path = optarg;
00520 break;
00521
00522 case 'd':
00523 spfd_config.debug = atol(optarg);
00524 break;
00525
00526 #ifdef HAVE_PWD_H
00527 case 'x':
00528 spfd_config.pathuser = daemon_get_user(optarg);
00529 break;
00530 #endif
00531 #ifdef HAVE_GRP_H
00532 case 'y':
00533 spfd_config.pathgroup = daemon_get_group(optarg);
00534 break;
00535 #endif
00536
00537 case 'm':
00538 spfd_config.pathmode = atol(optarg);
00539 break;
00540
00541 #ifdef HAVE_PWD_H
00542 case 'u':
00543 spfd_config.setuser = daemon_get_user(optarg);
00544 break;
00545 #endif
00546 #ifdef HAVE_GRP_H
00547 case 'g':
00548 spfd_config.setgroup = daemon_get_group(optarg);
00549 break;
00550 #endif
00551
00552 case 0:
00553 case '?':
00554 usage();
00555 DIE("Invalid argument");
00556 break;
00557 case 'h' :
00558 usage();
00559 DIE("");
00560 break;
00561
00562 default:
00563 fprintf(stderr, "Error: getopt returned character code 0%o ??\n", c);
00564 DIE("WHAT?");
00565 }
00566 }
00567 }
00568
00569 static int
00570 daemon_bind_inet_udp()
00571 {
00572 struct sockaddr_in addr;
00573 int sock;
00574
00575 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00576 perror("socket");
00577 DIE("Failed to create socket");
00578 }
00579 memset(&addr, 0, sizeof(addr));
00580 addr.sin_family = AF_INET;
00581 addr.sin_port = htons(spfd_config.udpport);
00582 addr.sin_addr.s_addr = INADDR_ANY;
00583 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00584 perror("bind");
00585 DIE("Failed to bind socket");
00586 }
00587
00588 fprintf(stderr, "Accepting datagrams on %d\n", spfd_config.udpport);
00589
00590 return sock;
00591 }
00592
00593 static int
00594 daemon_bind_inet_tcp()
00595 {
00596 struct sockaddr_in addr;
00597 int sock;
00598
00599 int optval;
00600 size_t optlen;
00601
00602 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00603 perror("socket");
00604 DIE("Failed to create socket");
00605 }
00606
00607 optval = 1;
00608 optlen = sizeof(int);
00609 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
00610
00611 memset(&addr, 0, sizeof(addr));
00612 addr.sin_family = AF_INET;
00613 addr.sin_port = htons(spfd_config.tcpport);
00614 addr.sin_addr.s_addr = INADDR_ANY;
00615 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00616 perror("bind");
00617 DIE("Failed to bind socket");
00618 }
00619
00620 if (listen(sock, 5) < 0) {
00621 perror("listen");
00622 DIE("Failed to listen on socket");
00623 }
00624
00625 fprintf(stderr, "Accepting connections on %d\n", spfd_config.tcpport);
00626
00627 return sock;
00628 }
00629
00630 static int
00631 daemon_bind_unix()
00632 {
00633 struct sockaddr_un addr;
00634 int sock;
00635
00636 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
00637 perror("socket");
00638 DIE("Failed to create socket");
00639 }
00640 memset(&addr, 0, sizeof(addr));
00641 addr.sun_family = AF_UNIX;
00642 strncpy(addr.sun_path, spfd_config.path, sizeof(addr.sun_path) - 1);
00643 if (unlink(spfd_config.path) < 0) {
00644 if (errno != ENOENT) {
00645 perror("unlink");
00646 DIE("Failed to unlink socket");
00647 }
00648 }
00649 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
00650 perror("bind");
00651 DIE("Failed to bind socket");
00652 }
00653 if (listen(sock, 5) < 0) {
00654 perror("listen");
00655 DIE("Failed to listen on socket");
00656 }
00657
00658 fprintf(stderr, "Accepting connections on %s\n", spfd_config.path);
00659
00660 return sock;
00661 }
00662
00663 static void
00664 daemon_init()
00665 {
00666 SPF_response_t *spf_response = NULL;
00667 SPF_errcode_t err;
00668
00669 memset(&spfd_state, 0, sizeof(spfd_state));
00670
00671 spf_server = SPF_server_new(SPF_DNS_CACHE, spfd_config.debug);
00672
00673 if (spfd_config.rec_dom) {
00674 UNLESS(SPF_server_set_rec_dom(spf_server,
00675 spfd_config.rec_dom)) {
00676 DIE("Failed to set receiving domain name");
00677 }
00678 }
00679
00680 if (spfd_config.sanitize) {
00681 UNLESS(SPF_server_set_sanitize(spf_server,
00682 spfd_config.sanitize)) {
00683 DIE("Failed to set server sanitize flag");
00684 }
00685 }
00686
00687 if (spfd_config.max_lookup) {
00688 UNLESS(SPF_server_set_max_dns_mech(spf_server,
00689 spfd_config.max_lookup)){
00690 DIE("Failed to set maximum DNS requests");
00691 }
00692 }
00693
00694 if (spfd_config.localpolicy) {
00695 UNLESS(SPF_server_set_localpolicy(spf_server,
00696 spfd_config.localpolicy,
00697 spfd_config.use_trusted,
00698 &spf_response)){
00699 response_print_errors("Compiling local policy",
00700 spf_response, err);
00701 DIE("Failed to set local policy");
00702 }
00703 FREE_RESPONSE(spf_response);
00704 }
00705
00706 if (spfd_config.explanation) {
00707 UNLESS(SPF_server_set_explanation(spf_server,
00708 spfd_config.explanation,
00709 &spf_response)){
00710 response_print_errors("Setting default explanation",
00711 spf_response, err);
00712 DIE("Failed to set default explanation");
00713 }
00714 FREE_RESPONSE(spf_response);
00715 }
00716
00717 if (spfd_config.udpport)
00718 spfd_state.sock_udp = daemon_bind_inet_udp();
00719 if (spfd_config.tcpport)
00720 spfd_state.sock_tcp = daemon_bind_inet_tcp();
00721 if (spfd_config.path)
00722 spfd_state.sock_unix = daemon_bind_unix();
00723
00724 }
00725
00726
00727
00728 static char **
00729 find_field(request_t *req, const char *key)
00730 {
00731 #define STREQ(a, b) (strcmp((a), (b)) == 0)
00732
00733 if (STREQ(key, "ip"))
00734 return &req->ip;
00735 if (STREQ(key, "helo"))
00736 return &req->helo;
00737 if (STREQ(key, "sender"))
00738 return &req->sender;
00739 if (STREQ(key, "rcpt"))
00740 return &req->rcpt_to;
00741 fprintf(stderr, "Invalid key %s\n", key);
00742 return NULL;
00743 }
00744
00745
00746 static void *
00747 handle_datagram(void *arg)
00748 {
00749 request_t *req;
00750 char **fp;
00751 char *key;
00752 char *value;
00753 char *end;
00754 int err;
00755
00756 req = (request_t *)arg;
00757 key = req->data;
00758
00759
00760
00761 while (key < (req->data + req->datalen)) {
00762 end = key + strcspn(key, "\r\n");
00763 *end = '\0';
00764 value = strchr(key, '=');
00765
00766
00767 if (!value)
00768 continue;
00769
00770 *value++ = '\0';
00771 fp = find_field(req, key);
00772 if (fp != NULL)
00773 *fp = value;
00774 else
00775 ;
00776
00777 key = end + 1;
00778 while (key < (req->data + req->datalen)) {
00779 if (strchr("\r\n", *key))
00780 key++;
00781 else
00782 break;
00783 }
00784 }
00785
00786 request_handle(req);
00787
00788 #ifdef DEBUG
00789 printf("Target address length is %d: %s:%d\n", req->addrlen,
00790 inet_ntoa(req->addr.in.sin_addr),
00791 req->addr.in.sin_port);
00792 #endif
00793
00794 printf("- %s\n", req->sender); fflush(stdout);
00795 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
00796 (struct sockaddr *)(&req->addr.in), req->addrlen);
00797 if (err == -1)
00798 perror("sendto");
00799
00800 FREE_RESPONSE(req->spf_response);
00801 FREE_REQUEST(req->spf_request);
00802
00803 FREE_STRING(req->data);
00804 free(arg);
00805 return NULL;
00806 }
00807
00808
00809 static void *
00810 handle_stream(void *arg)
00811 {
00812 request_t *req;
00813 char **fp;
00814 FILE *stream;
00815 char key[BUFSIZ];
00816 char *value;
00817 char *end;
00818
00819 req = (request_t *)arg;
00820 stream = fdopen(req->sock, "r");
00821
00822 do {
00823 while (fgets(key, BUFSIZ, stream) != NULL) {
00824 key[strcspn(key, "\r\n")] = '\0';
00825
00826
00827 if (*key == '\0')
00828 break;
00829
00830 end = key + strcspn(key, "\r\n");
00831 *end = '\0';
00832 value = strchr(key, '=');
00833
00834 if (!value)
00835 continue;
00836
00837 *value++ = '\0';
00838 fp = find_field(req, key);
00839 if (fp != NULL)
00840 *fp = strdup(value);
00841 else
00842 ;
00843 }
00844
00845 request_handle(req);
00846
00847 printf("- %s\n", req->sender); fflush(stdout);
00848 send(req->sock, req->fmt, req->fmtlen, 0);
00849
00850 FREE_STRING(req->ip);
00851 FREE_STRING(req->helo);
00852 FREE_STRING(req->sender);
00853 FREE_STRING(req->rcpt_to);
00854 } while (!feof(stream));
00855
00856 free(arg);
00857 return NULL;
00858 }
00859
00860 static void
00861 daemon_main()
00862 {
00863 pthread_attr_t attr;
00864 pthread_t th;
00865
00866 request_t *req;
00867 char buf[4096];
00868 fd_set rfd;
00869 fd_set sfd;
00870 int maxfd;
00871
00872
00873 pthread_attr_init(&attr);
00874 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00875
00876 FD_ZERO(&rfd);
00877 maxfd = 0;
00878
00879 if (spfd_state.sock_udp) {
00880
00881 FD_SET(spfd_state.sock_udp, &rfd);
00882 if (spfd_state.sock_udp > maxfd)
00883 maxfd = spfd_state.sock_udp;
00884 }
00885 if (spfd_state.sock_tcp) {
00886
00887 FD_SET(spfd_state.sock_tcp, &rfd);
00888 if (spfd_state.sock_tcp > maxfd)
00889 maxfd = spfd_state.sock_tcp;
00890 }
00891 if (spfd_state.sock_unix) {
00892
00893 FD_SET(spfd_state.sock_unix, &rfd);
00894 if (spfd_state.sock_unix > maxfd)
00895 maxfd = spfd_state.sock_unix;
00896 }
00897
00898
00899 #define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
00900
00901 for (;;) {
00902 memcpy(&sfd, &rfd, sizeof(rfd));
00903 if (select(maxfd + 1, &sfd, NULL, NULL, NULL) == -1)
00904 break;
00905
00906 if (spfd_state.sock_udp) {
00907 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
00908 req = NEW_REQUEST;
00909 req->addrlen = sizeof(req->addr);
00910
00911 req->sock = spfd_state.sock_udp;
00912 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
00913 (struct sockaddr *)(&req->addr.in), &req->addrlen);
00914 if (req->datalen >= 0) {
00915 buf[req->datalen] = '\0';
00916 req->data = strdup(buf);
00917 pthread_create(&th, &attr, handle_datagram, req);
00918 }
00919 else {
00920 free(req);
00921 }
00922 }
00923 }
00924 if (spfd_state.sock_tcp) {
00925 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
00926 req = NEW_REQUEST;
00927 req->addrlen = sizeof(req->addr);
00928
00929 req->sock = accept(spfd_state.sock_tcp,
00930 (struct sockaddr *)(&req->addr.in), &req->addrlen);
00931 if (req->sock >= 0)
00932 pthread_create(&th, &attr, handle_stream, req);
00933 else
00934 free(req);
00935 }
00936 }
00937 if (spfd_state.sock_unix) {
00938 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
00939 req = NEW_REQUEST;
00940 req->addrlen = sizeof(req->addr);
00941
00942 req->sock = accept(spfd_state.sock_unix,
00943 (struct sockaddr *)(&req->addr.un), &req->addrlen);
00944 if (req->sock >= 0)
00945 pthread_create(&th, &attr, handle_stream, req);
00946 else
00947 free(req);
00948 }
00949 }
00950 }
00951
00952 pthread_attr_destroy(&attr);
00953 }
00954
00955 int
00956 main(int argc, char *argv[])
00957 {
00958 daemon_config(argc, argv);
00959 daemon_init();
00960 daemon_main();
00961 return 0;
00962 }