]> code.citadel.org Git - citadel.git/blobdiff - citadel/domain.c
* Use syslog-compatible logging levels in lprintf(); the loglevel chosen
[citadel.git] / citadel / domain.c
index ccf62f7c795753d9d09e65f2b7eb035b903eb11d..8af3bc37b573c699f43b941e0ac62e277507d0b5 100644 (file)
@@ -5,13 +5,21 @@
  *
  */
 
+#include "sysdep.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <stdio.h>
+
+#ifdef HAVE_RESOLV_H
 #include <arpa/nameser.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
 #include <resolv.h>
+#endif
+
 #include "sysdep_decls.h"
 #include "citadel.h"
 #include "domain.h"
 
 
 /*
- * get_smarthosts() checks the Internet configuration for "smarthost"
+ * get_hosts() checks the Internet configuration for various types of
  * entries and returns them in the same format as getmx() does -- fill the
  * buffer with a delimited list of hosts and return the number of hosts.
+ * 
+ * This is used to fetch MX smarthosts, SpamAssassin hosts, etc.
  */
-int get_smarthosts(char *mxbuf) {
+int get_hosts(char *mxbuf, char *rectype) {
        int config_lines;
        int i;
        char buf[SIZ];
@@ -41,7 +51,7 @@ int get_smarthosts(char *mxbuf) {
                extract_token(host, buf, 0, '|');
                extract_token(type, buf, 1, '|');
 
-               if (!strcasecmp(type, "smarthost")) {
+               if (!strcasecmp(type, rectype)) {
                        strcat(mxbuf, host);
                        strcat(mxbuf, "|");
                        ++total_smarthosts;
@@ -52,36 +62,30 @@ int get_smarthosts(char *mxbuf) {
 }
 
 
-
-
 /*
- * sort_mxrecs()
- *
- * Sort a pile of MX records (struct mx, definted in domain.h) by preference
- *
+ * Compare the preference of two MX records.  First check by the actual
+ * number listed in the MX record.  If they're identical, randomize the
+ * result.
  */
-void sort_mxrecs(struct mx *mxrecs, int num_mxrecs) {
-       int a, b;
-       struct mx hold1, hold2;
-
-       if (num_mxrecs < 2) return;
+int mx_compare_pref(const void *mx1, const void *mx2) {
+       int pref1;
+       int pref2;
 
-       /* do the sort */
-       for (a = num_mxrecs - 2; a >= 0; --a) {
-               for (b = 0; b <= a; ++b) {
-                       if (mxrecs[b].pref > mxrecs[b+1].pref) {
+       pref1 = ((const struct mx *)mx1)->pref;
+       pref2 = ((const struct mx *)mx2)->pref;
 
-                               memcpy(&hold1, &mxrecs[b], sizeof(struct mx));
-                               memcpy(&hold2, &mxrecs[b+1], sizeof(struct mx));
-                               memcpy(&mxrecs[b], &hold2, sizeof(struct mx));
-                               memcpy(&mxrecs[b+1], &hold1, sizeof(struct mx));
-                       }
-               }
+       if (pref1 > pref2) {
+               return(1);
+       }
+       else if (pref1 < pref2) {
+               return(0);
+       }
+       else {
+               return(rand() % 2);
        }
 }
 
 
-
 /* 
  * getmx()
  *
@@ -93,13 +97,22 @@ void sort_mxrecs(struct mx *mxrecs, int num_mxrecs) {
  *
  */
 int getmx(char *mxbuf, char *dest) {
-       char answer[1024];
+
+#ifdef HAVE_RESOLV_H
+       union {
+                       u_char bytes[1024];
+                       HEADER header;
+    } answer;
+#else
+       char buf[SIZ];
+       FILE *fp;
+#endif
+
        int ret;
        unsigned char *startptr, *endptr, *ptr;
        char expanded_buf[1024];
        unsigned short pref, type;
        int n = 0;
-       HEADER *hp;
        int qdcount;
 
        struct mx *mxrecs = NULL;
@@ -108,15 +121,34 @@ int getmx(char *mxbuf, char *dest) {
        /* If we're configured to send all mail to a smart-host, then our
         * job here is really easy.
         */
-       n = get_smarthosts(mxbuf);
+       n = get_hosts(mxbuf, "smarthost");
        if (n > 0) return(n);
 
        /*
         * No smart-host?  Look up the best MX for a site.
         */
+
+#ifndef HAVE_RESOLV_H
+
+       /*
+        * On systems with b0rken or non-standard resolver libraries, learn
+        * the MX records by calling "nslookup" from the command line.
+        *
+        * Someday.
+        *
+        */
+
+       return(0);
+
+#else /* HAVE_RESOLV_H */
+
+       /*
+        * Make a call to the standard resolver library.
+        */
+
        ret = res_query(
                dest,
-               C_IN, T_MX, (unsigned char *)answer, sizeof(answer)  );
+               C_IN, T_MX, (unsigned char *)answer.bytes, sizeof(answer)  );
 
        if (ret < 0) {
                mxrecs = mallok(sizeof(struct mx));
@@ -130,14 +162,13 @@ int getmx(char *mxbuf, char *dest) {
                if (ret > sizeof(answer))
                        ret = sizeof(answer);
        
-               hp = (HEADER *)&answer[0];
-               startptr = &answer[0];          /* start and end of buffer */
-               endptr = &answer[ret];
+               startptr = &answer.bytes[0];            /* start and end of buffer */
+               endptr = &answer.bytes[ret];
                ptr = startptr + HFIXEDSZ;      /* advance past header */
        
-               for (qdcount = ntohs(hp->qdcount); qdcount--; ptr += ret + QFIXEDSZ) {
+               for (qdcount = ntohs(answer.header.qdcount); qdcount--; ptr += ret + QFIXEDSZ) {
                        if ((ret = dn_skipname(ptr, endptr)) < 0) {
-                               lprintf(9, "dn_skipname error\n");
+                               lprintf(CTDL_DEBUG, "dn_skipname error\n");
                                return(0);
                        }
                }
@@ -186,8 +217,12 @@ int getmx(char *mxbuf, char *dest) {
                        }
                }
        }
+#endif /* HAVE_RESOLV_H */
 
-       sort_mxrecs(mxrecs, num_mxrecs);
+       /* Sort the MX records by preference */
+       if (num_mxrecs > 1) {
+               qsort(mxrecs, num_mxrecs, sizeof(struct mx), mx_compare_pref);
+       }
 
        strcpy(mxbuf, "");
        for (n=0; n<num_mxrecs; ++n) {