libspf2 1.2.10
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;
158} config_t;
159
160typedef
161struct _request_t {
162 int sock;
163 union {
164 struct sockaddr_in in;
165 struct sockaddr_un un;
166 } addr;
167 socklen_t addrlen;
168 char *data;
170
171 char *ip;
172 char *helo;
173 char *sender;
174 char *rcpt_to;
175
177 SPF_request_t *spf_request;
178 SPF_response_t *spf_response;
179
180 char fmt[4096];
182} request_t;
183
184typedef
185struct _state_t {
189} state_t;
190
191static SPF_server_t *spf_server;
192static config_t spfd_config;
193static state_t spfd_state;
194
195static void
196response_print_errors(const char *context,
197 SPF_response_t *spf_response, SPF_errcode_t err)
198{
199 SPF_error_t *spf_error;
200 int i;
201
202 if (context != NULL)
203 printf("Context: %s\n", context);
204 if (err != SPF_E_SUCCESS)
205 printf("ErrorCode: (%d) %s\n", err, SPF_strerror(err));
206
207 if (spf_response != NULL) {
208 for (i = 0; i < SPF_response_messages(spf_response); i++) {
209 spf_error = SPF_response_message(spf_response, i);
210 printf( "%s: %s%s\n",
211 SPF_error_errorp(spf_error) ? "Error" : "Warning",
212 ((SPF_error_errorp(spf_error) && (!err))
213 ? "[UNRETURNED] "
214 : ""),
215 SPF_error_message(spf_error) );
216 }
217 }
218 else {
219 printf("Error: libspf2 gave a NULL spf_response");
220 }
221}
222
223static void
224response_print(const char *context, SPF_response_t *spf_response)
225{
226 printf("--vv--\n");
227 printf("Context: %s\n", context);
228 if (spf_response == NULL) {
229 printf("NULL RESPONSE!\n");
230 }
231 else {
232 printf("Response result: %s\n",
233 SPF_strresult(SPF_response_result(spf_response)));
234 printf("Response reason: %s\n",
235 SPF_strreason(SPF_response_reason(spf_response)));
236 printf("Response err: %s\n",
237 SPF_strerror(SPF_response_errcode(spf_response)));
238 response_print_errors(NULL, spf_response,
239 SPF_response_errcode(spf_response));
240 }
241 printf("--^^--\n");
242}
243
244static const char *
245request_check(request_t *req)
246{
247 const char *msg = NULL;
248 if (!req->ip)
249 msg = "No IP address given";
250 else if (!req->sender)
251 msg = "No sender address given";
252 else
253 return NULL;
254 snprintf(req->fmt, 4095,
255 "result=unknown\n"
256 "reason=%s\n",
257 msg);
258 return msg;
259}
260
261static void
262request_query(request_t *req)
263{
264 SPF_request_t *spf_request = NULL;
265 SPF_response_t *spf_response = NULL;
266 SPF_response_t *spf_response_2mx = NULL;
267 SPF_errcode_t err;
268 char *p, *p_end;
269
270#define UNLESS(x) err = (x); if (err)
271// #define FAIL(x) do { response_print_errors((x), spf_response, err); goto fail; } while(0)
272#define FAIL(x) do { goto fail; } while(0)
273#define WARN(x, r) response_print_errors((x), (r), err)
274
275 spf_request = SPF_request_new(spf_server);
276
277 if (strchr(req->ip, ':')) {
278 UNLESS(SPF_request_set_ipv6_str(spf_request, req->ip)) {
279 FAIL("Setting IPv6 address");
280 }
281 }
282 else {
283 UNLESS(SPF_request_set_ipv4_str(spf_request, req->ip)) {
284 FAIL("Setting IPv4 address");
285 }
286 }
287
288 if (req->helo) {
289 UNLESS(SPF_request_set_helo_dom(spf_request, req->helo)) {
290 FAIL("Failed to set HELO domain");
291 }
292 /* XXX Set some flag saying to query on helo */
293 }
294
295 if (req->sender) {
296 UNLESS(SPF_request_set_env_from(spf_request, req->sender)) {
297 FAIL("Failed to set envelope-from address");
298 }
299 /* XXX Set some flag saying to query on sender */
300 }
301
302 /* XXX If flag not set, FAIL() */
303
304 UNLESS(SPF_request_query_mailfrom(spf_request, &spf_response)) {
305 FAIL("Failed to query based on mail-from address");
306 }
307
308 if (spfd_config.sec_mx) {
309 if (req->rcpt_to && *req->rcpt_to) {
310 p = req->rcpt_to;
311 p_end = p + strcspn(p, " ,;");
312 while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) {
313 if (*p_end)
314 *p_end = '\0';
315 else
316 p_end = NULL; /* Note this is last rcpt */
318 &spf_response_2mx, p)) {
319 WARN("Failed to query based on 2mx recipient",
320 spf_response_2mx);
321 FREE_RESPONSE(spf_response_2mx);
322 }
323 else {
324 spf_response = SPF_response_combine(spf_response,
325 spf_response_2mx);
326 spf_response_2mx = NULL; /* freed */
327 }
328
329 if (!p_end)
330 break;
331 p = p_end + 1;
332 }
333 }
334 }
335
336 if (spfd_config.fallback) {
338 &spf_response, spfd_config.fallback)) {
339 FAIL("Querying fallback record");
340 }
341 }
342
343 goto ok;
344
345fail:
346 req->spf_err = err;
347 FREE_RESPONSE(spf_response);
348 FREE_REQUEST(spf_request);
349
350ok:
351 // response_print("Result: ", spf_response);
352 (void)response_print;
353
354 req->spf_response = spf_response;
355 req->spf_request = spf_request;
356}
357
358/* This is needed on HP/UX, IIRC */
359static inline const char *
360W(const char *c)
361{
362 if (c)
363 return c;
364 return "(null)";
365}
366
367static void
368request_format(request_t *req)
369{
370 SPF_response_t *spf_response;
371
372 spf_response = req->spf_response;
373
374 if (spf_response) {
375 req->fmtlen = snprintf(req->fmt, 4095,
376 "ip=%s\n"
377 "sender=%s\n"
378 "result=%s\n"
379 "reason=%s\n"
380 "smtp_comment=%s\n"
381 "header_comment=%s\n"
382 "error=%s\n"
383 , req->ip, req->sender
384 , W(SPF_strresult(SPF_response_result(spf_response)))
385 , W(SPF_strreason(SPF_response_reason(spf_response)))
386 , W(SPF_response_get_smtp_comment(spf_response))
387 , W(SPF_response_get_header_comment(spf_response))
388 , W(SPF_strerror(SPF_response_errcode(spf_response)))
389 );
390 }
391 else {
392 req->fmtlen = snprintf(req->fmt, 4095,
393 "ip=%s\n"
394 "sender=%s\n"
395 "result=unknown\n"
396 "error=%s\n"
397 , req->ip, req->sender
398 , SPF_strerror(req->spf_err)
399 );
400 }
401
402 req->fmt[4095] = '\0';
403}
404
405static void
406request_handle(request_t *req)
407{
408 printf("| %s\n", req->sender); fflush(stdout);
409 if (!request_check(req)) {
410 request_query(req);
411 request_format(req);
412 }
413 // printf("==\n%s\n", req->fmt);
414}
415
416static const struct option longopts[] = {
417 { "debug", required_argument, NULL, 'd', },
418 { "tcpport", required_argument, NULL, 't', },
419 { "udpport", required_argument, NULL, 'p', },
420 { "path", required_argument, NULL, 'f', },
421#ifdef HAVE_PWD_H
422 { "pathuser", required_argument, NULL, 'x', },
423#endif
424#ifdef HAVE_GRP_H
425 { "pathgroup", required_argument, NULL, 'y', },
426#endif
427 { "pathmode", required_argument, NULL, 'm', },
428#ifdef HAVE_PWD_H
429 { "setuser", required_argument, NULL, 'u', },
430#endif
431#ifdef HAVE_GRP_H
432 { "setgroup", required_argument, NULL, 'g', },
433#endif
434 { "help", no_argument, NULL, 'h', },
435};
436
437static const char *shortopts = "d:t:p:f:x:y:m:u:g:h:";
438
439void usage (void) {
440 fprintf(stdout,"Flags\n");
441 fprintf(stdout,"\t-tcpport\n");
442 fprintf(stdout,"\t-udpport\n");
443 fprintf(stdout,"\t-path\n");
444#ifdef HAVE_PWD_H
445 fprintf(stdout,"\t-pathuser\n");
446#endif
447#ifdef HAVE_GRP_H
448 fprintf(stdout,"\t-pathgroup\n");
449#endif
450 fprintf(stdout,"\t-pathmode\n");
451#ifdef HAVE_PWD_H
452 fprintf(stdout,"\t-setuser\n");
453#endif
454#ifdef HAVE_GRP_H
455 fprintf(stdout,"\t-setgroup\n");
456#endif
457 fprintf(stdout,"\t-help\n");
458
459}
460
461#define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
462
463#ifdef HAVE_PWD_H
464static gid_t
465daemon_get_user(const char *arg)
466{
467 struct passwd *pwd;
468 if (isdigit(arg[0]))
469 pwd = getpwuid(atol(arg));
470 else
471 pwd = getpwnam(arg);
472 if (pwd == NULL) {
473 fprintf(stderr, "Failed to find user %s\n", arg);
474 DIE("Unknown user");
475 }
476 return pwd->pw_uid;
477}
478#endif
479
480#ifdef HAVE_GRP_H
481static gid_t
482daemon_get_group(const char *arg)
483{
484 struct group *grp;
485 if (isdigit(arg[0]))
486 grp = getgrgid(atol(arg));
487 else
488 grp = getgrnam(arg);
489 if (grp == NULL) {
490 fprintf(stderr, "Failed to find user %s\n", arg);
491 DIE("Unknown group");
492 }
493 return grp->gr_gid;
494}
495#endif
496
497static void
498daemon_config(int argc, char *argv[])
499{
500 int idx;
501 char c;
502
503 memset(&spfd_config, 0, sizeof(spfd_config));
504
505 while ((c =
506 getopt_long(argc, argv, shortopts, longopts, &idx)
507 ) != -1) {
508 switch (c) {
509 case 't':
510 spfd_config.tcpport = atol(optarg);
511 break;
512 case 'p':
513 spfd_config.udpport = atol(optarg);
514 break;
515 case 'f':
516 spfd_config.path = optarg;
517 break;
518
519 case 'd':
520 spfd_config.debug = atol(optarg);
521 break;
522
523#ifdef HAVE_PWD_H
524 case 'x':
525 spfd_config.pathuser = daemon_get_user(optarg);
526 break;
527#endif
528#ifdef HAVE_GRP_H
529 case 'y':
530 spfd_config.pathgroup = daemon_get_group(optarg);
531 break;
532#endif
533
534 case 'm':
535 spfd_config.pathmode = atol(optarg);
536 break;
537
538#ifdef HAVE_PWD_H
539 case 'u':
540 spfd_config.setuser = daemon_get_user(optarg);
541 break;
542#endif
543#ifdef HAVE_GRP_H
544 case 'g':
545 spfd_config.setgroup = daemon_get_group(optarg);
546 break;
547#endif
548
549 case 0:
550 case '?':
551 usage();
552 DIE("Invalid argument");
553 break;
554 case 'h' :
555 usage();
556 DIE("");
557 break;
558
559 default:
560 fprintf(stderr, "Error: getopt returned character code 0%o ??\n", c);
561 DIE("WHAT?");
562 }
563 }
564}
565
566static int
567daemon_bind_inet_udp()
568{
569 struct sockaddr_in addr;
570 int sock;
571
572 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
573 perror("socket");
574 DIE("Failed to create socket");
575 }
576 memset(&addr, 0, sizeof(addr));
577 addr.sin_family = AF_INET;
578 addr.sin_port = htons(spfd_config.udpport);
579 addr.sin_addr.s_addr = INADDR_ANY;
580 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
581 perror("bind");
582 DIE("Failed to bind socket");
583 }
584
585 fprintf(stderr, "Accepting datagrams on %d\n", spfd_config.udpport);
586
587 return sock;
588}
589
590static int
591daemon_bind_inet_tcp()
592{
593 struct sockaddr_in addr;
594 int sock;
595
596 int optval;
597 size_t optlen;
598
599 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
600 perror("socket");
601 DIE("Failed to create socket");
602 }
603
604 optval = 1;
605 optlen = sizeof(int);
606 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
607
608 memset(&addr, 0, sizeof(addr));
609 addr.sin_family = AF_INET;
610 addr.sin_port = htons(spfd_config.tcpport);
611 addr.sin_addr.s_addr = INADDR_ANY;
612 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
613 perror("bind");
614 DIE("Failed to bind socket");
615 }
616
617 if (listen(sock, 5) < 0) {
618 perror("listen");
619 DIE("Failed to listen on socket");
620 }
621
622 fprintf(stderr, "Accepting connections on %d\n", spfd_config.tcpport);
623
624 return sock;
625}
626
627static int
628daemon_bind_unix()
629{
630 struct sockaddr_un addr;
631 int sock;
632
633 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
634 perror("socket");
635 DIE("Failed to create socket");
636 }
637 memset(&addr, 0, sizeof(addr));
638 addr.sun_family = AF_UNIX;
639 strncpy(addr.sun_path, spfd_config.path, sizeof(addr.sun_path) - 1);
640 if (unlink(spfd_config.path) < 0) {
641 if (errno != ENOENT) {
642 perror("unlink");
643 DIE("Failed to unlink socket");
644 }
645 }
646 if (bind(sock, (struct sockaddr *)(&addr), sizeof(addr)) < 0) {
647 perror("bind");
648 DIE("Failed to bind socket");
649 }
650 if (listen(sock, 5) < 0) {
651 perror("listen");
652 DIE("Failed to listen on socket");
653 }
654
655 fprintf(stderr, "Accepting connections on %s\n", spfd_config.path);
656
657 return sock;
658}
659
660static void
661daemon_init()
662{
663 SPF_response_t *spf_response = NULL;
664 SPF_errcode_t err;
665
666 memset(&spfd_state, 0, sizeof(spfd_state));
667
668 spf_server = SPF_server_new(SPF_DNS_CACHE, spfd_config.debug);
669
670 if (spfd_config.rec_dom) {
672 spfd_config.rec_dom)) {
673 DIE("Failed to set receiving domain name");
674 }
675 }
676
677 if (spfd_config.sanitize) {
679 spfd_config.sanitize)) {
680 DIE("Failed to set server sanitize flag");
681 }
682 }
683
684 if (spfd_config.max_lookup) {
685 UNLESS(SPF_server_set_max_dns_mech(spf_server,
686 spfd_config.max_lookup)){
687 DIE("Failed to set maximum DNS requests");
688 }
689 }
690
691 if (spfd_config.localpolicy) {
693 spfd_config.localpolicy,
694 spfd_config.use_trusted,
695 &spf_response)){
696 response_print_errors("Compiling local policy",
697 spf_response, err);
698 DIE("Failed to set local policy");
699 }
700 FREE_RESPONSE(spf_response);
701 }
702
703 if (spfd_config.explanation) {
705 spfd_config.explanation,
706 &spf_response)){
707 response_print_errors("Setting default explanation",
708 spf_response, err);
709 DIE("Failed to set default explanation");
710 }
711 FREE_RESPONSE(spf_response);
712 }
713
714 if (spfd_config.udpport)
715 spfd_state.sock_udp = daemon_bind_inet_udp();
716 if (spfd_config.tcpport)
717 spfd_state.sock_tcp = daemon_bind_inet_tcp();
718 if (spfd_config.path)
719 spfd_state.sock_unix = daemon_bind_unix();
720 /* XXX Die if none of the above. */
721}
722
723/* This has a return value so we can decide whether to malloc and/or
724 * free in the caller. */
725static char **
726find_field(request_t *req, const char *key)
727{
728#define STREQ(a, b) (strcmp((a), (b)) == 0)
729
730 if (STREQ(key, "ip"))
731 return &req->ip;
732 if (STREQ(key, "helo"))
733 return &req->helo;
734 if (STREQ(key, "sender"))
735 return &req->sender;
736 if (STREQ(key, "rcpt"))
737 return &req->rcpt_to;
738 fprintf(stderr, "Invalid key %s\n", key);
739 return NULL;
740}
741
742/* This is called with req->data malloc'd */
743static void *
744handle_datagram(void *arg)
745{
746 request_t *req;
747 char **fp;
748 char *key;
749 char *value;
750 char *end;
751 int err;
752
753 req = (request_t *)arg;
754 key = req->data;
755
756 // printf("req: %s\n", key);
757
758 while (key < (req->data + req->datalen)) {
759 end = key + strcspn(key, "\r\n");
760 *end = '\0';
761 value = strchr(key, '=');
762
763 /* Did that line contain an '='? */
764 if (!value) /* XXX WARN */
765 continue;
766
767 *value++ = '\0';
768 fp = find_field(req, key);
769 if (fp != NULL)
770 *fp = value;
771 else
772 /* warned already */ ;
773
774 key = end + 1;
775 while (key < (req->data + req->datalen)) {
776 if (strchr("\r\n", *key))
777 key++;
778 else
779 break;
780 }
781 }
782
783 request_handle(req);
784
785#ifdef DEBUG
786 printf("Target address length is %d: %s:%d\n", req->addrlen,
787 inet_ntoa(req->addr.in.sin_addr),
788 req->addr.in.sin_port);
789#endif
790
791 printf("- %s\n", req->sender); fflush(stdout);
792 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
793 (struct sockaddr *)(&req->addr.in), req->addrlen);
794 if (err == -1)
795 perror("sendto");
796
799
800 FREE_STRING(req->data);
801 free(arg);
802 return NULL;
803}
804
805/* Only req is malloc'd in this. */
806static void *
807handle_stream(void *arg)
808{
809 request_t *req;
810 char **fp;
811 FILE *stream;
812 char key[BUFSIZ];
813 char *value;
814 char *end;
815
816 req = (request_t *)arg;
817 stream = fdopen(req->sock, "r");
818
819 do {
820 while (fgets(key, BUFSIZ, stream) != NULL) {
821 key[strcspn(key, "\r\n")] = '\0';
822
823 /* Break on a blank line and permit another query */
824 if (*key == '\0')
825 break;
826
827 end = key + strcspn(key, "\r\n");
828 *end = '\0';
829 value = strchr(key, '=');
830
831 if (!value) /* XXX WARN */
832 continue;
833
834 *value++ = '\0';
835 fp = find_field(req, key);
836 if (fp != NULL)
837 *fp = strdup(value);
838 else
839 /* warned already */ ;
840 }
841
842 request_handle(req);
843
844 printf("- %s\n", req->sender); fflush(stdout);
845 send(req->sock, req->fmt, req->fmtlen, 0);
846
847 FREE_STRING(req->ip);
848 FREE_STRING(req->helo);
849 FREE_STRING(req->sender);
850 FREE_STRING(req->rcpt_to);
851 } while (!feof(stream));
852
853 free(arg);
854 return NULL;
855}
856
857static void
858daemon_main()
859{
860 pthread_attr_t attr;
861 pthread_t th;
862
863 request_t *req;
864 char buf[4096];
865 fd_set rfd;
866 fd_set sfd;
867 int maxfd;
868
869
870 pthread_attr_init(&attr);
871 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
872
873 FD_ZERO(&rfd);
874 maxfd = 0;
875
876 if (spfd_state.sock_udp) {
877 // printf("UDP socket is %d\n", spfd_state.sock_udp);
878 FD_SET(spfd_state.sock_udp, &rfd);
879 if (spfd_state.sock_udp > maxfd)
880 maxfd = spfd_state.sock_udp;
881 }
882 if (spfd_state.sock_tcp) {
883 // printf("TCP socket is %d\n", spfd_state.sock_tcp);
884 FD_SET(spfd_state.sock_tcp, &rfd);
885 if (spfd_state.sock_tcp > maxfd)
886 maxfd = spfd_state.sock_tcp;
887 }
888 if (spfd_state.sock_unix) {
889 // printf("UNIX socket is %d\n", spfd_state.sock_unix);
890 FD_SET(spfd_state.sock_unix, &rfd);
891 if (spfd_state.sock_unix > maxfd)
892 maxfd = spfd_state.sock_unix;
893 }
894 // printf("MaxFD is %d\n", maxfd);
895
896#define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
897
898 for (;;) {
899 memcpy(&sfd, &rfd, sizeof(rfd));
900 if (select(maxfd + 1, &sfd, NULL, NULL, NULL) == -1)
901 break;
902
903 if (spfd_state.sock_udp) {
904 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
905 req = NEW_REQUEST;
906 req->addrlen = sizeof(req->addr);
907 // printf("UDP\n");
908 req->sock = spfd_state.sock_udp;
909 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
910 (struct sockaddr *)(&req->addr.in), &req->addrlen);
911 if (req->datalen >= 0) {
912 buf[req->datalen] = '\0';
913 req->data = strdup(buf);
914 pthread_create(&th, &attr, handle_datagram, req);
915 }
916 else {
917 free(req);
918 }
919 }
920 }
921 if (spfd_state.sock_tcp) {
922 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
923 req = NEW_REQUEST;
924 req->addrlen = sizeof(req->addr);
925 // printf("TCP\n");
926 req->sock = accept(spfd_state.sock_tcp,
927 (struct sockaddr *)(&req->addr.in), &req->addrlen);
928 if (req->sock >= 0)
929 pthread_create(&th, &attr, handle_stream, req);
930 else
931 free(req);
932 }
933 }
934 if (spfd_state.sock_unix) {
935 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
936 req = NEW_REQUEST;
937 req->addrlen = sizeof(req->addr);
938 // printf("UNIX\n");
939 req->sock = accept(spfd_state.sock_unix,
940 (struct sockaddr *)(&req->addr.un), &req->addrlen);
941 if (req->sock >= 0)
942 pthread_create(&th, &attr, handle_stream, req);
943 else
944 free(req);
945 }
946 }
947 }
948
949 pthread_attr_destroy(&attr);
950}
951
952int
953main(int argc, char *argv[])
954{
955 daemon_config(argc, argv);
956 daemon_init();
957 daemon_main();
958 return 0;
959}
#define FREE_STRING(x)
Definition spfd.c:127
int main(int argc, char *argv[])
Definition spfd.c:953
#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:461
void usage(void)
Definition spfd.c:439
#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
SPF_response_t * spf_response
Definition spfd.c:178
int sock
Definition spfd.c:162
char * ip
Definition spfd.c:171
int datalen
Definition spfd.c:169
int fmtlen
Definition spfd.c:181
char fmt[4096]
Definition spfd.c:180
union request_t::@0 addr
char * sender
Definition spfd.c:173
char * rcpt_to
Definition spfd.c:174
SPF_request_t * spf_request
Definition spfd.c:177
struct sockaddr_un un
Definition spfd.c:165
struct sockaddr_in in
Definition spfd.c:164
char * data
Definition spfd.c:168
SPF_errcode_t spf_err
Definition spfd.c:176
socklen_t addrlen
Definition spfd.c:167
char * helo
Definition spfd.c:172
int sock_unix
Definition spfd.c:188
int sock_tcp
Definition spfd.c:187
int sock_udp
Definition spfd.c:186