"Fossies" - the Fresh Open Source Software Archive

Member "citadel/domain.c" (5 Jun 2021, 4698 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "domain.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 8.24_vs_9.01.

    1 /*
    2  * DNS lookup for SMTP sender
    3  *
    4  * Copyright (c) 1987-2021 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License, version 3.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  */
   14 
   15 #include "sysdep.h"
   16 #include <stdio.h>
   17 #include <syslog.h>
   18 #ifdef HAVE_RESOLV_H
   19 #include <arpa/nameser.h>
   20 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
   21 #include <arpa/nameser_compat.h>
   22 #endif
   23 #include <resolv.h>
   24 #endif
   25 #include <libcitadel.h>
   26 #include "sysdep_decls.h"
   27 #include "citadel.h"
   28 #include "domain.h"
   29 #include "internet_addressing.h"
   30 
   31 
   32 /*
   33  * get_hosts() checks the Internet configuration for various types of
   34  * entries and returns them in the same format as getmx() does -- fill the
   35  * buffer with a delimited list of hosts and return the number of hosts.
   36  * 
   37  * This is used to fetch MX smarthosts, SpamAssassin hosts, etc.
   38  */
   39 int get_hosts(char *mxbuf, char *rectype) {
   40     int config_lines;
   41     int i;
   42     char buf[256];
   43     char host[256], type[256];
   44     int total_smarthosts = 0;
   45 
   46     if (inetcfg == NULL) return(0);
   47     strcpy(mxbuf, "");
   48 
   49     config_lines = num_tokens(inetcfg, '\n');
   50     for (i=0; i<config_lines; ++i) {
   51         extract_token(buf, inetcfg, i, '\n', sizeof buf);
   52         extract_token(host, buf, 0, '|', sizeof host);
   53         extract_token(type, buf, 1, '|', sizeof type);
   54 
   55         if (!strcasecmp(type, rectype)) {
   56             strcat(mxbuf, host);
   57             strcat(mxbuf, "|");
   58             ++total_smarthosts;
   59         }
   60     }
   61 
   62     return(total_smarthosts);
   63 }
   64 
   65 
   66 /*
   67  * Compare the preference of two MX records.  First check by the actual
   68  * number listed in the MX record.  If they're identical, randomize the
   69  * result.
   70  */
   71 int mx_compare_pref(const void *mx1, const void *mx2) {
   72     int pref1;
   73     int pref2;
   74 
   75     pref1 = ((const struct mx *)mx1)->pref;
   76     pref2 = ((const struct mx *)mx2)->pref;
   77 
   78     if (pref1 > pref2) {
   79         return(1);
   80     }
   81     else if (pref1 < pref2) {
   82         return(0);
   83     }
   84     else {
   85         return(rand() % 2);
   86     }
   87 }
   88 
   89 
   90 /* 
   91  * getmx()
   92  *
   93  * Return one or more MX's for a mail destination.
   94  *
   95  * Upon success, it fills 'mxbuf' with one or more MX hosts, separated by
   96  * vertical bar characters, and returns the number of hosts as its return
   97  * value.  If no MX's are found, it returns 0.
   98  *
   99  */
  100 int getmx(char *mxbuf, char *dest) {
  101 
  102 #ifdef HAVE_RESOLV_H
  103     union {
  104             u_char bytes[1024];
  105             HEADER header;
  106     } answer;
  107 #endif
  108 
  109     int ret;
  110     unsigned char *startptr, *endptr, *ptr;
  111     char expanded_buf[1024];
  112     unsigned short pref, type;
  113     int n = 0;
  114     int qdcount;
  115     Array *mxrecords = NULL;
  116     struct mx mx;
  117 
  118     // If we're configured to send all mail to a smart-host, then our job here is really easy -- just return those.
  119     n = get_hosts(mxbuf, "smarthost");
  120     if (n > 0) {
  121         return(n);
  122     }
  123 
  124     mxrecords = array_new(sizeof(struct mx));
  125 
  126     // No smart-host?  Look up the best MX for a site.  Make a call to the resolver library.
  127     ret = res_query(dest, C_IN, T_MX, (unsigned char *)answer.bytes, sizeof(answer));
  128 
  129     if (ret < 0) {
  130         mx.pref = 0;
  131         strcpy(mx.host, dest);
  132         array_append(mxrecords, &mx);
  133     }
  134     else {
  135         if (ret > sizeof(answer)) {     // If we had to truncate, shrink the number to avoid fireworks
  136             ret = sizeof(answer);
  137         }
  138 
  139         startptr = &answer.bytes[0];        // start and end of buffer
  140         endptr = &answer.bytes[ret];
  141         ptr = startptr + HFIXEDSZ;      // advance past header
  142     
  143         for (qdcount = ntohs(answer.header.qdcount); qdcount--; ptr += ret + QFIXEDSZ) {
  144             if ((ret = dn_skipname(ptr, endptr)) < 0) {
  145                 syslog(LOG_DEBUG, "domain: dn_skipname error");
  146                 return(0);
  147             }
  148         }
  149     
  150         while(1) {
  151             memset(expanded_buf, 0, sizeof(expanded_buf));
  152             ret = dn_expand(startptr, endptr, ptr, expanded_buf, sizeof(expanded_buf));
  153             if (ret < 0) break;
  154             ptr += ret;
  155     
  156             GETSHORT(type, ptr);
  157             ptr += INT16SZ + INT32SZ;
  158             GETSHORT(n, ptr);
  159     
  160             if (type != T_MX) {
  161                 ptr += n;
  162             }
  163     
  164             else {
  165                 GETSHORT(pref, ptr);
  166                 ret = dn_expand(startptr, endptr, ptr, expanded_buf, sizeof(expanded_buf));
  167                 ptr += ret;
  168     
  169                 mx.pref = pref;
  170                 strcpy(mx.host, expanded_buf);
  171                 array_append(mxrecords, &mx);
  172             }
  173         }
  174     }
  175 
  176     // Sort the MX records by preference
  177     if (array_len(mxrecords) > 1) {
  178         array_sort(mxrecords, mx_compare_pref);
  179     }
  180 
  181     int num_mxrecs = array_len(mxrecords);
  182     strcpy(mxbuf, "");
  183     for (n=0; n<num_mxrecs; ++n) {
  184         strcat(mxbuf, ((struct mx *)array_get_element_at(mxrecords, n))->host);
  185         strcat(mxbuf, "|");
  186     }
  187     array_free(mxrecords);
  188 
  189     // Append any fallback smart hosts we have configured.
  190     num_mxrecs += get_hosts(&mxbuf[strlen(mxbuf)], "fallbackhost");
  191     return(num_mxrecs);
  192 }