~ubuntu-branches/ubuntu/raring/maradns/raring

« back to all changes in this revision

Viewing changes to server/MaraDNS.c

  • Committer: Bazaar Package Importer
  • Author(s): Kai Hendry
  • Date: 2010-01-24 12:17:40 UTC
  • mfrom: (1.1.13 upstream) (10.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20100124121740-a4e1fjobwaouz443
Tags: 1.4.02-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2007 Sam Trenholme
 
1
/* Copyright (c) 2002-2009 Sam Trenholme
2
2
 *
3
3
 * TERMS
4
4
 *
44
44
#ifndef DARWIN
45
45
#endif
46
46
#ifndef MINGW32
 
47
#include <sys/time.h>
47
48
#include <sys/resource.h>
48
49
#include <sys/wait.h>
49
50
#include <sys/socket.h>
147
148
 
148
149
int dns_records_served = 0; /* The number of DNS records we are serving */
149
150
 
 
151
js_string *notthere_ip = 0; /* The Class + TTL (0) + Rdlength (4)
 
152
                             * + IP (The IP the user wants) for synthetic
 
153
                             * IPs when they mistype a domain name or some
 
154
                             * such (Sponsored by XeroBank). */
 
155
 
 
156
int recursion_enabled = 0; /* Whether we have recursion */
 
157
 
150
158
/* A list of who is and who is not allowed to make recursive DNS queries */
151
159
ipv4pair recurse_acl[512];
152
160
/* A list of the ipv4 IP addresses we bind MaraDNS to (the netmask portion is
353
361
    exit(3);
354
362
    }
355
363
 
 
364
/* This function returns an appropriate RA (Recursion available) value.
 
365
 * If the user has not set "recursive_acl", this will always return 0.
 
366
 * If the argument give to this is 0, return zero.  Otherwise, return 1
 
367
 */
 
368
 
 
369
int calc_ra_value(int want_ra) {
 
370
#ifdef AUTHONLY
 
371
        return 0;
 
372
#else /* AUTHONLY */
 
373
        if(recursion_enabled == 0) {
 
374
                return 0;
 
375
        }
 
376
        return want_ra;
 
377
#endif /* AUTHONLY */
 
378
}
 
379
 
 
380
/* This function prepares the notthere_ip string so that it we can quickly
 
381
 * make synthetic IPs.  Basically, the string is most of the DNS header and
 
382
 * data for the generated synthetic IP, in this form:
 
383
 *
 
384
 * Dname: 2-byte compression pointer to question (0xc00c)
 
385
 * Class (16-bit): 1 (Internet)
 
386
 * TTL: 0 (Not to be cached)
 
387
 * Rdlength: 4 (4-byte IP)
 
388
 * Rddata: The dotted-decimal IP given to the function converted in to raw
 
389
 *         binary form.
 
390
 *
 
391
 * Input: A js_string containing the dotted-decimal IP we will convert
 
392
 * Output: A js_string containing the above raw data
 
393
 */
 
394
 
 
395
js_string *make_notthere_ip(js_string *ddip) {
 
396
        js_string *out = 0;
 
397
        js_string *ip = 0;
 
398
        out = js_create(19,1);
 
399
        if(out == 0) {
 
400
                return 0;
 
401
        }
 
402
        ip = js_create(10,1);
 
403
        if(ip == 0) {
 
404
                js_destroy(out);
 
405
                return 0;
 
406
        }
 
407
        if(js_adduint16(out,0xc00c) == JS_ERROR || /* Hostname (compressed) */
 
408
           js_adduint16(out,1) == JS_ERROR || /* TYPE (A) */
 
409
           js_adduint16(out,1) == JS_ERROR || /* CLASS */
 
410
           js_adduint16(out,0) == JS_ERROR || /* TTL pt. 1 */
 
411
           js_adduint16(out,0) == JS_ERROR || /* TTL pt. 2 */
 
412
           js_adduint16(out,4) == JS_ERROR) { /* Rdlength */
 
413
                js_destroy(out);
 
414
                js_destroy(ip);
 
415
                return 0;
 
416
        }
 
417
        if(ddip_2_ip(ddip,ip,0) == JS_ERROR) {
 
418
                js_destroy(out);
 
419
                js_destroy(ip);
 
420
                return 0;
 
421
        }
 
422
        if(js_append(ip,out) == JS_ERROR) {
 
423
                js_destroy(out);
 
424
                js_destroy(ip);
 
425
                return 0;
 
426
        }
 
427
        js_destroy(ip);
 
428
        return out;
 
429
}
 
430
 
356
431
/* Calculate the TTL age given the expire time (absolute time) and
357
432
   the ttl (relative time)
358
433
   Input: Exprire time, TTL in question
1717
1792
 
1718
1793
    }
1719
1794
 
 
1795
/* Create a bogus 0-TTL ip answer if we give out these answers instead
 
1796
 * of SOA answers/NXDOMAINS for non-existant addresses */
 
1797
 
 
1798
int make_notthere_reply(int id, int sock, struct sockaddr_in *client,
 
1799
                        js_string *query, int rd_val, conn *ect) {
 
1800
        js_string *most;
 
1801
        q_header header;
 
1802
        int len_inet = sizeof(struct sockaddr);
 
1803
 
 
1804
        init_header(&header);
 
1805
        header.rd = rd_val; /* RDBUG make_notthere_reply */
 
1806
        header.id = id;
 
1807
        header.qr = 1;
 
1808
        header.opcode = 0;
 
1809
        header.tc = 0;
 
1810
        header.ra = calc_ra_value(rd_val);
 
1811
        header.z = 0;
 
1812
        header.rcode = 0; /* We "found" something */
 
1813
        /* We return just a single 0-ttl IP */
 
1814
        header.qdcount = 1; /* Echo the question in the answer */
 
1815
        header.ancount = 1;
 
1816
        header.nscount = 0;
 
1817
        header.arcount = 0;
 
1818
        if((most = js_create(520,1)) == 0) {
 
1819
                return JS_ERROR;
 
1820
        }
 
1821
        make_hdr(&header,most);
 
1822
        /* Question */
 
1823
        js_append(query,most);
 
1824
        js_adduint16(most,1); /* Class: 1 */
 
1825
        /* Answer */
 
1826
        js_append(notthere_ip,most);
 
1827
 
 
1828
        /* Send answer over UDP */
 
1829
        if(ect == 0) {
 
1830
                sendto(sock,most->string,most->unit_count,0,
 
1831
                        (struct sockaddr *)client,len_inet);
 
1832
        } else {
 
1833
                mara_send(ect,sock,most);
 
1834
        }
 
1835
 
 
1836
        js_destroy(most);
 
1837
        return JS_SUCCESS;
 
1838
}
 
1839
 
1720
1840
/* If we have a NXDOMAIN, deliver that record on the udp packet.
1721
1841
 *        Input: where: A pointer to the rr in question (the SOA record),
1722
1842
 *
1771
1891
        always_not_there = 4;
1772
1892
    }
1773
1893
 
 
1894
    if(js_has_sanity(query) == JS_ERROR) {
 
1895
        return JS_ERROR;
 
1896
        }
 
1897
    first_rr_type = get_rtype(query);
 
1898
 
 
1899
    /* See if notthere_ip is set, they are using recursion, and
 
1900
     * that they want an IP */
 
1901
    if(notthere_ip != 0 && (recursive_call & 1) == 1 && first_rr_type == 1) {
 
1902
                /* If so, give them a synthetic IP reply */
 
1903
                return make_notthere_reply(id, sock, client, query, rd_val,
 
1904
                                           ect);
 
1905
    }
 
1906
 
1774
1907
    /* Initialize the js_string objects */
1775
1908
    if((most = js_create(1024,1)) == 0)
1776
1909
        return JS_ERROR;
1803
1936
    if(js_has_sanity(where->data) == JS_ERROR) {
1804
1937
        goto giveerror;
1805
1938
        }
1806
 
    if(js_has_sanity(query) == JS_ERROR) {
1807
 
        goto giveerror;
1808
 
        }
1809
 
    first_rr_type = get_rtype(query);
 
1939
 
1810
1940
 
1811
1941
    /* We have to add this header here--authoritative depends on the
1812
1942
       authorative status of the first record we find */
1893
2023
    header.opcode = 0;
1894
2024
    header.tc = 0; /* To do: truncation handling */
1895
2025
    header.rd = rd_val; /* RDBUG udpnotfound */
1896
 
    header.ra = rd_val;
 
2026
    header.ra = calc_ra_value(rd_val);
1897
2027
    header.z = 0;
1898
2028
    /* Code that verifies that this host does not exist in
1899
2029
       any class.  If so, then we give them a rcode of NXDOMAIN_RCODE.
3762
3892
    int cache_size;
3763
3893
    int min_ttl_n = 300, min_ttl_c = 300;
3764
3894
    int timestamp_type = 5; /* Type of timestamp */
3765
 
    int recursion_enabled = 0; /* Whether we have recursion */
3766
3895
#ifndef AUTHONLY
3767
3896
    int max_glueless; /* Maximum allowed glueless level */
3768
3897
    int max_q_total; /* Maximum total queries in attempt to resolve hostname */
3785
3914
    int verbose_query = 0;
3786
3915
    struct sockaddr client;
3787
3916
    struct sockaddr_in *clin = 0; /* So we can log the IP */
3788
 
#ifndef DARWIN
3789
3917
#ifndef MINGW32
3790
3918
    struct rlimit rlim;
3791
3919
#endif /* MINGW32 */
3792
 
#endif /* DARWIN */
3793
3920
    int have_ipv6_address = 0;
3794
3921
    int default_dos_level = 78; /* 78: Recursive-only; 0: default when
3795
3922
                                 * there is one or more zonefiles */
3926
4053
    init_rlog_level(log_level);
3927
4054
#endif
3928
4055
 
 
4056
    /* If they want a synthetic IP given when the recursive resolver would
 
4057
     * otherwise give a SOA "not there" record (or when it's impossible to
 
4058
     * contact an upstream_server if handle_noreply is appropriately set),
 
4059
     * prepare most of the synthetic answer we will give them. */
 
4060
    verbstr = read_string_kvar("notthere_ip");
 
4061
    if(verbstr != 0) {
 
4062
        notthere_ip = make_notthere_ip(verbstr);
 
4063
        js_destroy(verbstr);
 
4064
    }
 
4065
    verbstr = 0;
 
4066
 
3929
4067
    /* Determine if we will handle star records the way BIND does:
3930
4068
       . If a non-A record for foo.example.com exists
3931
4069
       . And an A record for *.example.com exists
4040
4178
        exit(1);
4041
4179
    }
4042
4180
 
4043
 
 
4044
4181
    /* Get the values for the synthetic SOA serial and the synthetic SOA
4045
4182
       origin (called MNAME in RFC1035) */
4046
4183
    synth_soa_serial = read_numeric_kvar("synth_soa_serial",1);
4268
4405
            harderror(L_CHROOT_NT); /* "Problem making chroot nt string.\nMake sure the chroot directory is 200 chars or less" */
4269
4406
        if(chdir((char *)chroot_zt) != 0)
4270
4407
            sys_harderror(L_CHROOT_CHANGE); /* "Problem changing to chroot dir.\nMake sure chroot_dir points to a valid directory" */
4271
 
#ifndef __CYGWIN__
 
4408
#if ! (defined __CYGWIN__ || defined QNX)
4272
4409
        if(chroot((char *)chroot_zt) != 0)
4273
4410
            sys_harderror(L_CHROOT_DO);  /* "Problem changing the root directory." */
4274
4411
#endif