libspf2 1.2.11
spfd.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of either:
4 *
5 * a) The GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 2.1, or (at your option) any
7 * later version,
8 *
9 * OR
10 *
11 * b) The two-clause BSD license.
12 *
13 * These licenses can be found with the distribution in the file LICENSES
14 *
15 *
16 *
17 * This program is really a badly smashed together copy of spfquery.c and
18 * the public domain "helloserver" example daemon.
19 *
20 * The original helloserver code contained the following copyright notice:
21 *
22 * HELLOSERVER.C - a 'Hello World' TCP/IP based server daemon
23 *
24 * Implements a skeleton of a single process iterative server
25 * daemon.
26 *
27 * Wherever possible the code adheres to POSIX.
28 *
29 * David Gillies <daggillies@yahoo.com> Sep 2003
30 *
31 * Placed in the public domain. Unrestricted use or modification
32 * of this code is permitted without attribution to the author.
33 */
34
35
36#ifdef __GNUC__
37#define _GNU_SOURCE /* for strsignal() */
38#endif
39
40#ifdef HAVE_CONFIG_H
41# include "config.h"
42#endif
43
44#ifdef STDC_HEADERS
45# include <stdio.h>
46# include <stdlib.h> /* malloc / free */
47# include <stddef.h>
48# include <stdarg.h>
49#endif
50
51#ifdef HAVE_SYS_TYPES_H
52#include <sys/types.h> /* types (u_char .. etc..) */
53#endif
54
55#ifdef HAVE_INTTYPES_H
56#include <inttypes.h>
57#endif
58
59#ifdef HAVE_STRING_H
60# include <string.h> /* strstr / strdup */
61#else
62# ifdef HAVE_STRINGS_H
63# include <strings.h> /* strstr / strdup */
64# endif
65#endif
66
67#ifdef HAVE_SYS_SOCKET_H
68# include <sys/socket.h> /* inet_ functions / structs */
69#endif
70#ifdef HAVE_NETINET_IN_H
71# include <netinet/in.h> /* inet_ functions / structs */
72#endif
73#ifdef HAVE_ARPA_INET_H
74# include <arpa/inet.h> /* in_addr struct */
75#endif
76
77#ifdef HAVE_ARPA_NAMESER_H
78# include <arpa/nameser.h> /* DNS HEADER struct */
79#endif
80
81#include <sys/types.h>
82
83#ifdef HAVE_PWD_H
84#include <pwd.h>
85#endif
86
87#ifdef HAVE_GRP_H
88#include <grp.h>
89#endif
90
91#define _GNU_SOURCE
92#include <getopt.h>
93
94#include <unistd.h>
95#include <netdb.h>
96#include <fcntl.h>
97#include <time.h>
98#include <signal.h>
99#include <syslog.h>
100#include <errno.h>
101#include <sys/types.h>
102#include <sys/stat.h>
103#include <sys/socket.h>
104#include <sys/un.h>
105#include <netinet/in.h>
106#include <ctype.h>
107#include <sys/wait.h>
108
109#include <pthread.h>
110
111#include "spf.h"
112#include "spf_dns.h"
113#include "spf_dns_null.h"
114#include "spf_dns_resolv.h"
115#include "spf_dns_test.h"
116#include "spf_dns_cache.h"
117
118
119#define TRUE 1
120#define FALSE 0
121
122#define bool int
123
124#define FREE(x, f) do { if ((x)) (f)((x)); (x) = NULL; } while(0)
125#define FREE_REQUEST(x) FREE((x), SPF_request_free)
126#define FREE_RESPONSE(x) FREE((x), SPF_response_free)
127#define FREE_STRING(x) FREE((x), free)
128
129typedef
130struct _config_t {
133 char *path;
134#ifdef HAVE_PWD_H
135 uid_t pathuser;
136#endif
137#ifdef HAVE_GRP_H
138 gid_t pathgroup;
139#endif
141#ifdef HAVE_PWD_H
142 uid_t setuser;
143#endif
144#ifdef HAVE_GRP_H
145 gid_t setgroup;
146#endif
147
148 int debug;
149 bool sec_mx;
150 char *fallback;
151
152 char *rec_dom;
159} config_t;
160
161typedef
162struct _request_t {
163 int sock;
164 union {
165 struct sockaddr_in in;
166 struct sockaddr_un un;
167 } addr;
168 socklen_t addrlen;
169 char *data;
171
172 char *ip;
173 char *helo;
174 char *sender;
175 char *rcpt_to;
176
178 SPF_request_t *spf_request;
179 SPF_response_t *spf_response;
180
181 char fmt[4096];
183} request_t;
184
185typedef
186struct _state_t {
190} state_t;
191
192static SPF_server_t *spf_server;
193static config_t spfd_config;
194static state_t spfd_state;
195
196static void
197response_print_errors(const char *context,
198 SPF_response_t *spf_response, SPF_errcode_t err)
199{
200 SPF_error_t *spf_error;
201 int i;
202
203 if (context != NULL)
204 printf("Context: %s\n", context);
205 if (err != SPF_E_SUCCESS)
206 printf("ErrorCode: (%d) %s\n", err, SPF_strerror(err));
207
208 if (spf_response != NULL) {
209 for (i = 0; i < SPF_response_messages(spf_response); i++) {
210 spf_error = SPF_response_message(spf_response, i);
211 printf( "%s: %s%s\n",
212 SPF_error_errorp(spf_error) ? "Error" : "Warning",
213 ((SPF_error_errorp(spf_error) && (!err))
214 ? "[UNRETURNED] "
215 : ""),
216 SPF_error_message(spf_error) );
217 }
218 }
219 else {
220 printf("Error: libspf2 gave a NULL spf_response");
221 }
222}
223
224static void
225response_print(const char *context, SPF_response_t *spf_response)
226{
227 printf("--vv--\n");
228 printf("Context: %s\n", context);
229 if (spf_response == NULL) {
230 printf("NULL RESPONSE!\n");
231 }
232 else {
233 printf("Response result: %s\n",
234 SPF_strresult(SPF_response_result(spf_response)));
235 printf("Response reason: %s\n",
236 SPF_strreason(SPF_response_reason(spf_response)));
237 printf("Response err: %s\n",
238 SPF_strerror(SPF_response_errcode(spf_response)));
239 response_print_errors(NULL, spf_response,
240 SPF_response_errcode(spf_response));
241 }
242 printf("--^^--\n");
243}
244
245static const char *
246request_check(request_t *req)
247{
248 const char *msg = NULL;
249 if (!req->ip)
250 msg = "No IP address given";
251 else if (!req->sender)
252 msg = "No sender address given";
253 else
254 return NULL;
255 snprintf(req->fmt, 4095,
256 "result=unknown\n"
257 "reason=%s\n",
258 msg);
259 return msg;
260}
261
262static void
263request_query(request_t *req)
264{
265 SPF_request_t *spf_request = NULL;
266 SPF_response_t *spf_response = NULL;
267 SPF_response_t *spf_response_2mx = NULL;
268 SPF_errcode_t err;
269 char *p, *p_end;
270
271#define UNLESS(x) err = (x); if (err)
272// #define FAIL(x) do { response_print_errors((x), spf_response, err); goto fail; } while(0)
273#define FAIL(x) do { goto fail; } while(0)
274#define WARN(x, r) response_print_errors((x), (r), err)
275
276 spf_request = SPF_request_new(spf_server);
277
278 if (strchr(req->ip, ':')) {
279 UNLESS(SPF_request_set_ipv6_str(spf_request, req->ip)) {
280 FAIL("Setting IPv6 address");
281 }
282 }
283 else {
284 UNLESS(SPF_request_set_ipv4_str(spf_request, req->ip)) {
285 FAIL("Setting IPv4 address");
286 }
287 }
288
289 if (req->helo) {
290 UNLESS(SPF_request_set_helo_dom(spf_request, req->helo)) {
291 FAIL("Failed to set HELO domain");
292 }
293 /* XXX Set some flag saying to query on helo */
294 }
295
296 if (req->sender) {
297 UNLESS(SPF_request_set_env_from(spf_request, req->sender)) {
298 FAIL("Failed to set envelope-from address");
299 }
300 /* XXX Set some flag saying to query on sender */
301 }
302
303 /* XXX If flag not set, FAIL() */
304
305 UNLESS(SPF_request_query_mailfrom(spf_request, &spf_response)) {
306 FAIL("Failed to query based on mail-from address");
307 }
308
309 if (spfd_config.sec_mx) {
310 if (req->rcpt_to && *req->rcpt_to) {
311 p = req->rcpt_to;
312 p_end = p + strcspn(p, " ,;");
313 while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) {
314 if (*p_end)
315 *p_end = '\0';
316 else
317 p_end = NULL; /* Note this is last rcpt */
319 &spf_response_2mx, p)) {
320 WARN("Failed to query based on 2mx recipient",
321 spf_response_2mx);
322 FREE_RESPONSE(spf_response_2mx);
323 }
324 else {
325 spf_response = SPF_response_combine(spf_response,
326 spf_response_2mx);
327 spf_response_2mx = NULL; /* freed */
328 }
329
330 if (!p_end)
331 break;
332 p = p_end + 1;
333 }
334 }
335 }
336
337 if (spfd_config.fallback) {
339 &spf_response, spfd_config.fallback)) {
340 FAIL("Querying fallback record");
341 }
342 }
343
344 goto ok;
345
346fail:
347 req->spf_err = err;
348 FREE_RESPONSE(spf_response);
349 FREE_REQUEST(spf_request);
350
351ok:
352 // response_print("Result: ", spf_response);
353 (void)response_print;
354
355 req->spf_response = spf_response;
356 req->spf_request = spf_request;
357}
358
359/* This is needed on HP/UX, IIRC */
360static inline const char *
361W(const char *c)
362{
363 if (c)
364 return c;
365 return "(null)";
366}
367
368static void
369request_format(request_t *req)
370{
371 SPF_response_t *spf_response;
372
373 spf_response = req->spf_response;
374
375 if (spf_response) {
376 req->fmtlen = snprintf(req->fmt, 4095,
377 "ip=%s\n"
378 "sender=%s\n"
379 "result=%s\n"
380 "reason=%s\n"
381 "smtp_comment=%s\n"
382 "header_comment=%s\n"
383 "error=%s\n"
384 , req->ip, req->sender
385 , W(SPF_strresult(SPF_response_result(spf_response)))
386 , W(SPF_strreason(SPF_response_reason(spf_response)))
387 , W(SPF_response_get_smtp_comment(spf_response))
388 , W(SPF_response_get_header_comment(spf_response))
389 , W(SPF_strerror(SPF_response_errcode(spf_response)))
390 );
391 }
392 else {
393 req->fmtlen = snprintf(req->fmt, 4095,
394 "ip=%s\n"
395 "sender=%s\n"
396 "result=unknown\n"
397 "error=%s\n"
398 , req->ip, req->sender
399 , SPF_strerror(req->spf_err)
400 );
401 }
402
403 req->fmt[4095] = '\0';
404}
405
406static void
407request_handle(request_t *req)
408{
409 printf("| %s\n", req->sender); fflush(stdout);
410 if (!request_check(req)) {
411 request_query(req);
412 request_format(req);
413 }
414 // printf("==\n%s\n", req->fmt);
415}
416
417static const struct option longopts[] = {
418 { "debug", required_argument, NULL, 'd', },
419 { "tcpport", required_argument, NULL, 't', },
420 { "udpport", required_argument, NULL, 'p', },
421 { "path", required_argument, NULL, 'f', },
422#ifdef HAVE_PWD_H
423 { "pathuser", required_argument, NULL, 'x', },
424#endif
425#ifdef HAVE_GRP_H
426 { "pathgroup", required_argument, NULL, 'y', },
427#endif
428 { "pathmode", required_argument, NULL, 'm', },
429#ifdef HAVE_PWD_H
430 { "setuser", required_argument, NULL, 'u', },
431#endif
432#ifdef HAVE_GRP_H
433 { "setgroup", required_argument, NULL, 'g', },
434#endif
435 { "onerequest", no_argument, NULL, 'o', },
436 { "help", no_argument, NULL, 'h', },
437 { 0, 0, 0, 0 },
438};
439
440static const char *shortopts = "d:t:p:f:x:y:m:u:g:o:h:";
441
442void usage (void) {
443 fprintf(stdout,"Flags\n");
444 fprintf(stdout,"\t-tcpport\n");
445 fprintf(stdout,"\t-udpport\n");
446 fprintf(stdout,"\t-path\n");
447#ifdef HAVE_PWD_H
448 fprintf(stdout,"\t-pathuser\n");
449#endif
450#ifdef HAVE_GRP_H
451 fprintf(stdout,"\t-pathgroup\n");
452#endif
453 fprintf(stdout,"\t-pathmode\n");
454#ifdef HAVE_PWD_H
455 fprintf(stdout,"\t-setuser\n");
456#endif
457#ifdef HAVE_GRP_H
458 fprintf(stdout,"\t-setgroup\n");
459#endif
460 fprintf(stdout,"\t-onerequest\n");
461 fprintf(stdout,"\t-help\n");
462
463}
464
465#define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
466
467#ifdef HAVE_PWD_H
468static gid_t
469daemon_get_user(const char *arg)
470{
471 struct passwd *pwd;
472 if (isdigit(arg[0]))
473 pwd = getpwuid(atol(arg));
474 else
475 pwd = getpwnam(arg);
476 if (pwd == NULL) {
477 fprintf(stderr, "Failed to find user %s\n", arg);
478 DIE("Unknown user");
479 }
480 return pwd->pw_uid;
481}
482#endif
483
484#ifdef HAVE_GRP_H
485static gid_t
486daemon_get_group(const char *arg)
487{
488 struct group *grp;
489 if (isdigit(arg[0]))
490 grp = getgrgid(atol(arg));
491 else
492 grp = getgrnam(arg);
493 if (grp == NULL) {
494 fprintf(stderr, "Failed to find user %s\n", arg);
495 DIE("Unknown group");
496 }
497 return grp->gr_gid;
498}
499#endif
500
501static void
502daemon_config(int argc, char *argv[])
503{
504 int idx;
505 char c;
506
507 memset(&spfd_config, 0, sizeof(spfd_config));
508
509 while ((c =
510 getopt_long(argc, argv, shortopts, longopts, &idx)
511 ) != -1) {
512 switch (c) {
513 case 't':
514 spfd_config.tcpport = atol(optarg);
515 break;
516 case 'p':
517 spfd_config.udpport = atol(optarg);
518 break;
519 case 'f':
520 spfd_config.path = optarg;
521 break;
522
523 case 'd':
524 spfd_config.debug = atol(optarg);
525 break;
526
527#ifdef HAVE_PWD_H
528 case 'x':
529 spfd_config.pathuser = daemon_get_user(optarg);
530 break;
531#endif
532#ifdef HAVE_GRP_H
533 case 'y':
534 spfd_config.pathgroup = daemon_get_group(optarg);
535 break;
536#endif
537
538 case 'm':
539 spfd_config.pathmode = atol(optarg);
540 break;
541
542#ifdef HAVE_PWD_H
543 case 'u':
544 spfd_config.setuser = daemon_get_user(optarg);
545 break;
546#endif
547#ifdef HAVE_GRP_H
548 case 'g':
549 spfd_config.setgroup = daemon_get_group(optarg);
550 break;
551#endif
552 case 'o':
553 spfd_config.onerequest = 1;
554 fprintf(stdout, "One request mode\n");
555 break;
556
557 case 0:
558 case '?':
559 usage();
560 DIE("Invalid argument");
561 break;
562 case 'h' :
563 usage();
564 DIE("");
565 break;
566
567 default:
568 fprintf(stderr, "Error: getopt returned character code 0%o ??\n", c);
569 DIE("WHAT?");
570 }
571 }
572}
573
574static int
575daemon_bind_inet_udp()
576{
577 struct sockaddr_in addr;
578 int sock;
579
580 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
581 perror("socket");
582 DIE("Failed to create socket");
583 }
584 memset(&addr, 0, sizeof(addr));
585 addr.sin_family = AF_INET;
586 addr.sin_port = htons(spfd_config.udpport);
587 addr.sin_addr.s_addr = INADDR_ANY;
588 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
589 perror("bind");
590 DIE("Failed to bind socket");
591 }
592
593 fprintf(stderr, "Accepting datagrams on %d\n", spfd_config.udpport);
594
595 return sock;
596}
597
598static int
599daemon_bind_inet_tcp()
600{
601 struct sockaddr_in addr;
602 int sock;
603
604 int optval;
605 size_t optlen;
606
607 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
608 perror("socket");
609 DIE("Failed to create socket");
610 }
611
612 optval = 1;
613 optlen = sizeof(int);
614 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
615
616 memset(&addr, 0, sizeof(addr));
617 addr.sin_family = AF_INET;
618 addr.sin_port = htons(spfd_config.tcpport);
619 addr.sin_addr.s_addr = INADDR_ANY;
620 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
621 perror("bind");
622 DIE("Failed to bind socket");
623 }
624
625 if (listen(sock, 5) < 0) {
626 perror("listen");
627 DIE("Failed to listen on socket");
628 }
629
630 fprintf(stderr, "Accepting connections on %d\n", spfd_config.tcpport);
631
632 return sock;
633}
634
635static int
636daemon_bind_unix()
637{
638 struct sockaddr_un addr;
639 int sock;
640
641 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
642 perror("socket");
643 DIE("Failed to create socket");
644 }
645 memset(&addr, 0, sizeof(addr));
646 addr.sun_family = AF_UNIX;
647 strncpy(addr.sun_path, spfd_config.path, sizeof(addr.sun_path) - 1);
648 if (unlink(spfd_config.path) < 0) {
649 if (errno != ENOENT) {
650 perror("unlink");
651 DIE("Failed to unlink socket");
652 }
653 }
654 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
655 perror("bind");
656 DIE("Failed to bind socket");
657 }
658 if (listen(sock, 5) < 0) {
659 perror("listen");
660 DIE("Failed to listen on socket");
661 }
662
663 fprintf(stderr, "Accepting connections on %s\n", spfd_config.path);
664
665 return sock;
666}
667
668static void
669daemon_init()
670{
671 SPF_response_t *spf_response = NULL;
672 SPF_errcode_t err;
673
674 memset(&spfd_state, 0, sizeof(spfd_state));
675
676 spf_server = SPF_server_new(SPF_DNS_CACHE, spfd_config.debug);
677
678 if (spfd_config.rec_dom) {
680 spfd_config.rec_dom)) {
681 DIE("Failed to set receiving domain name");
682 }
683 }
684
685 if (spfd_config.sanitize) {
687 spfd_config.sanitize)) {
688 DIE("Failed to set server sanitize flag");
689 }
690 }
691
692 if (spfd_config.max_lookup) {
693 UNLESS(SPF_server_set_max_dns_mech(spf_server,
694 spfd_config.max_lookup)){
695 DIE("Failed to set maximum DNS requests");
696 }
697 }
698
699 if (spfd_config.localpolicy) {
701 spfd_config.localpolicy,
702 spfd_config.use_trusted,
703 &spf_response)){
704 response_print_errors("Compiling local policy",
705 spf_response, err);
706 DIE("Failed to set local policy");
707 }
708 FREE_RESPONSE(spf_response);
709 }
710
711 if (spfd_config.explanation) {
713 spfd_config.explanation,
714 &spf_response)){
715 response_print_errors("Setting default explanation",
716 spf_response, err);
717 DIE("Failed to set default explanation");
718 }
719 FREE_RESPONSE(spf_response);
720 }
721
722 if (spfd_config.udpport)
723 spfd_state.sock_udp = daemon_bind_inet_udp();
724 if (spfd_config.tcpport)
725 spfd_state.sock_tcp = daemon_bind_inet_tcp();
726 if (spfd_config.path)
727 spfd_state.sock_unix = daemon_bind_unix();
728 /* XXX Die if none of the above. */
729}
730
731/* This has a return value so we can decide whether to malloc and/or
732 * free in the caller. */
733static char **
734find_field(request_t *req, const char *key)
735{
736#define STREQ(a, b) (strcmp((a), (b)) == 0)
737
738 if (STREQ(key, "ip"))
739 return &req->ip;
740 if (STREQ(key, "helo"))
741 return &req->helo;
742 if (STREQ(key, "sender"))
743 return &req->sender;
744 if (STREQ(key, "rcpt"))
745 return &req->rcpt_to;
746 fprintf(stderr, "Invalid key %s\n", key);
747 return NULL;
748}
749
750/* This is called with req->data malloc'd */
751static void *
752handle_datagram(void *arg)
753{
754 request_t *req;
755 char **fp;
756 char *key;
757 char *value;
758 char *end;
759 int err;
760
761 req = (request_t *)arg;
762 key = req->data;
763
764 // printf("req: %s\n", key);
765
766 while (key < (req->data + req->datalen)) {
767 end = key + strcspn(key, "\r\n");
768 *end = '\0';
769 value = strchr(key, '=');
770
771 /* Did that line contain an '='? */
772 if (!value) /* XXX WARN */
773 continue;
774
775 *value++ = '\0';
776 fp = find_field(req, key);
777 if (fp != NULL)
778 *fp = value;
779 else
780 /* warned already */ ;
781
782 key = end + 1;
783 while (key < (req->data + req->datalen)) {
784 if (strchr("\r\n", *key))
785 key++;
786 else
787 break;
788 }
789 }
790
791 request_handle(req);
792
793#ifdef DEBUG
794 printf("Target address length is %d: %s:%d\n", req->addrlen,
795 inet_ntoa(req->addr.in.sin_addr),
796 req->addr.in.sin_port);
797#endif
798
799 printf("- %s\n", req->sender); fflush(stdout);
800 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
801 (struct sockaddr *)(&req->addr.in), req->addrlen);
802 if (err == -1)
803 perror("sendto");
804
807
808 FREE_STRING(req->data);
809 free(arg);
810 return NULL;
811}
812
813/* Only req is malloc'd in this. */
814static void *
815handle_stream(void *arg)
816{
817 request_t *req;
818 char **fp;
819 FILE *stream;
820 char key[BUFSIZ];
821 char *value;
822 char *end;
823
824 req = (request_t *)arg;
825 stream = fdopen(req->sock, "r");
826
827 do {
828 while (fgets(key, BUFSIZ, stream) != NULL) {
829 key[strcspn(key, "\r\n")] = '\0';
830
831 /* Break on a blank line and permit another query */
832 if (*key == '\0')
833 break;
834
835 end = key + strcspn(key, "\r\n");
836 *end = '\0';
837 value = strchr(key, '=');
838
839 if (!value) /* XXX WARN */
840 continue;
841
842 *value++ = '\0';
843 fp = find_field(req, key);
844 if (fp != NULL)
845 *fp = strdup(value);
846 else
847 /* warned already */ ;
848 }
849
850 request_handle(req);
851
852 printf("- %s\n", req->sender); fflush(stdout);
853 send(req->sock, req->fmt, req->fmtlen, 0);
854
855 FREE_STRING(req->ip);
856 FREE_STRING(req->helo);
857 FREE_STRING(req->sender);
858 FREE_STRING(req->rcpt_to);
859 } while (! (spfd_config.onerequest || feof(stream)));
860
861 shutdown(req->sock, SHUT_RDWR);
862 fclose(stream);
863
864 free(arg);
865 return NULL;
866}
867
868static void
869daemon_main()
870{
871 pthread_attr_t attr;
872 pthread_t th;
873
874 request_t *req;
875 char buf[4096];
876 fd_set rfd;
877 fd_set sfd;
878 int maxfd;
879
880
881 pthread_attr_init(&attr);
882 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
883
884 FD_ZERO(&rfd);
885 maxfd = 0;
886
887 if (spfd_state.sock_udp) {
888 // printf("UDP socket is %d\n", spfd_state.sock_udp);
889 FD_SET(spfd_state.sock_udp, &rfd);
890 if (spfd_state.sock_udp > maxfd)
891 maxfd = spfd_state.sock_udp;
892 }
893 if (spfd_state.sock_tcp) {
894 // printf("TCP socket is %d\n", spfd_state.sock_tcp);
895 FD_SET(spfd_state.sock_tcp, &rfd);
896 if (spfd_state.sock_tcp > maxfd)
897 maxfd = spfd_state.sock_tcp;
898 }
899 if (spfd_state.sock_unix) {
900 // printf("UNIX socket is %d\n", spfd_state.sock_unix);
901 FD_SET(spfd_state.sock_unix, &rfd);
902 if (spfd_state.sock_unix > maxfd)
903 maxfd = spfd_state.sock_unix;
904 }
905 // printf("MaxFD is %d\n", maxfd);
906
907#define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
908
909 for (;;) {
910 memcpy(&sfd, &rfd, sizeof(rfd));
911 if (select(maxfd + 1, &sfd, NULL, NULL, NULL) == -1)
912 break;
913
914 if (spfd_state.sock_udp) {
915 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
916 req = NEW_REQUEST;
917 req->addrlen = sizeof(req->addr);
918 // printf("UDP\n");
919 req->sock = spfd_state.sock_udp;
920 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
921 (struct sockaddr *)(&req->addr.in), &req->addrlen);
922 if (req->datalen >= 0) {
923 buf[req->datalen] = '\0';
924 req->data = strdup(buf);
925 pthread_create(&th, &attr, handle_datagram, req);
926 }
927 else {
928 free(req);
929 }
930 }
931 }
932 if (spfd_state.sock_tcp) {
933 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
934 req = NEW_REQUEST;
935 req->addrlen = sizeof(req->addr);
936 // printf("TCP\n");
937 req->sock = accept(spfd_state.sock_tcp,
938 (struct sockaddr *)(&req->addr.in), &req->addrlen);
939 if (req->sock >= 0)
940 pthread_create(&th, &attr, handle_stream, req);
941 else
942 free(req);
943 }
944 }
945 if (spfd_state.sock_unix) {
946 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
947 req = NEW_REQUEST;
948 req->addrlen = sizeof(req->addr);
949 // printf("UNIX\n");
950 req->sock = accept(spfd_state.sock_unix,
951 (struct sockaddr *)(&req->addr.un), &req->addrlen);
952 if (req->sock >= 0)
953 pthread_create(&th, &attr, handle_stream, req);
954 else
955 free(req);
956 }
957 }
958 }
959
960 pthread_attr_destroy(&attr);
961}
962
963int
964main(int argc, char *argv[])
965{
966 daemon_config(argc, argv);
967 daemon_init();
968 daemon_main();
969 return 0;
970}
#define FREE_STRING(x)
Definition spfd.c:127
int main(int argc, char *argv[])
Definition spfd.c:964
#define FREE_RESPONSE(x)
Definition spfd.c:126
#define WARN(x, r)
#define FAIL(x)
#define NEW_REQUEST
#define FREE_REQUEST(x)
Definition spfd.c:125
#define DIE(x)
Definition spfd.c:465
void usage(void)
Definition spfd.c:442
#define STREQ(a, b)
#define UNLESS(x)
SPF_server_t * SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
Definition spf_server.c:132
@ SPF_DNS_CACHE
Definition spf_server.h:73
SPF_errcode_t SPF_server_set_explanation(SPF_server_t *sp, const char *exp, SPF_response_t **spf_responsep)
Definition spf_server.c:235
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
Definition spf_server.c:228
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
Definition spf_server.c:267
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
Definition spf_server.c:215
@ SPF_RESULT_PASS
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
const char * SPF_response_get_header_comment(SPF_response_t *rp)
const char * SPF_error_message(SPF_error_t *err)
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
int SPF_response_messages(SPF_response_t *rp)
char SPF_error_errorp(SPF_error_t *err)
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
SPF_errcode_t
@ SPF_E_SUCCESS
SPF_result_t SPF_response_result(SPF_response_t *rp)
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
Definition spf_request.c:41
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
Definition spf_request.c:95
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
#define NULL
A testing layer for DNS.
const char * SPF_strerror(SPF_errcode_t spf_err)
const char * SPF_strresult(SPF_result_t result)
Definition spf_utils.c:81
const char * SPF_strreason(SPF_reason_t reason)
Definition spf_utils.c:128
bool sec_mx
Definition spfd.c:149
int tcpport
Definition spfd.c:131
int udpport
Definition spfd.c:132
char * rec_dom
Definition spfd.c:152
char * fallback
Definition spfd.c:150
bool use_trusted
Definition spfd.c:156
char * localpolicy
Definition spfd.c:155
char * explanation
Definition spfd.c:157
char * path
Definition spfd.c:133
bool sanitize
Definition spfd.c:153
int pathmode
Definition spfd.c:140
int debug
Definition spfd.c:148
int max_lookup
Definition spfd.c:154
bool onerequest
Definition spfd.c:158
SPF_response_t * spf_response
Definition spfd.c:179
int sock
Definition spfd.c:163
char * ip
Definition spfd.c:172
int datalen
Definition spfd.c:170
int fmtlen
Definition spfd.c:182
char fmt[4096]
Definition spfd.c:181
union request_t::@0 addr
char * sender
Definition spfd.c:174
char * rcpt_to
Definition spfd.c:175
SPF_request_t * spf_request
Definition spfd.c:178
struct sockaddr_un un
Definition spfd.c:166
struct sockaddr_in in
Definition spfd.c:165
char * data
Definition spfd.c:169
SPF_errcode_t spf_err
Definition spfd.c:177
socklen_t addrlen
Definition spfd.c:168
char * helo
Definition spfd.c:173
int sock_unix
Definition spfd.c:189
int sock_tcp
Definition spfd.c:188
int sock_udp
Definition spfd.c:187