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