<commit_before>/*
Copyright (c) 2003, 2004 by <NAME>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "polipo.h"

#ifndef NO_STANDARD_RESOLVER
#ifndef NO_FANCY_RESOLVER
int dnsUseGethostbyname = 1;
#else 
const int dnsUseGethostbyname = 3;
#endif
#else
#ifndef NO_FANCY_RESOLVER
const int dnsUseGethostbyname = 0;
#else
#error use no resolver at all?
#endif
#endif

#ifndef NO_FANCY_RESOLVER
AtomPtr dnsNameServer = NULL;
int dnsMaxTimeout = 60;
#endif

#ifndef NO_STANDARD_RESOLVER
int dnsGethostbynameTtl = 1200;
#endif

int dnsNegativeTtl = 120;

#ifdef HAVE_IPv6
int dnsQueryIPv6 = 2;
#else
const int dnsQueryIPv6 = 0;
#endif

typedef struct _DnsQuery {
    unsigned id;
    AtomPtr name;
    ObjectPtr object;
    AtomPtr inet4, inet6;
    time_t ttl4, ttl6;
    time_t time;
    int timeout;
    TimeEventHandlerPtr timeout_handler;
    struct _DnsQuery *next;
} DnsQueryRec, *DnsQueryPtr;

union {
    struct sockaddr sa;
    struct sockaddr_in sin;
#ifdef HAVE_IPv6
    struct sockaddr_in6 sin6;
#endif
} nameserverAddress_storage;

#ifndef NO_FANCY_RESOLVER
#define nameserverAddress nameserverAddress_storage.sa

static DnsQueryPtr inFlightDnsQueries;
static DnsQueryPtr inFlightDnsQueriesLast;
#endif

static int really_do_gethostbyname(AtomPtr name, ObjectPtr object);
static int really_do_dns(AtomPtr name, ObjectPtr object);

#ifndef NO_FANCY_RESOLVER
static int stringToLabels(char *buf, int offset, int n, char *string);
static int labelsToString(char *buf, int offset, int n, char *d, 
                          int m, int *j_return);
static int dnsBuildQuery(int id, char *buf, int offset, int n,
                         AtomPtr name, int af);
static int dnsReplyHandler(int abort, FdEventHandlerPtr event);
static int dnsReplyId(char *buf, int offset, int n, int *id_return);
static int dnsDecodeReply(char *buf, int offset, int n,
                          int *id_return,
                          AtomPtr *name_return, AtomPtr *value_return,
                          int *af_return, unsigned *ttl_return);
static int dnsHandler(int status, ObjectHandlerPtr ohandler);
static int dnsGethostbynameFallback(int id, AtomPtr message);
static int sendQuery(DnsQueryPtr query);

static int idSeed;
#endif

#ifndef NO_FANCY_RESOLVER
static int
parseResolvConf(char *filename)
{
    FILE *f;
    char buf[512];
    char *p, *q;
    int n;
    AtomPtr nameserver = NULL;

    f = fopen(filename, "r");
    if(f == NULL) {
        do_log_error(L_ERROR, -errno, "DNS: couldn't open %s", filename);
        goto done;
    }

    while(1) {
        p = fgets(buf, 512, f);
        if(p == NULL)
            break;

        n = strlen(buf);
        if(buf[n - 1] != '\n') {
            int c;
            do_log(L_WARN, "DNS: overly long line in %s -- skipping.\n",
                   filename);
            do {
                c = fgetc(f);
                if(c == EOF)
                    break;
            } while(c != '\n');
            if(c == EOF)
                break;
        }
        
        while(*p == ' ' || *p == '\t')
            p++;
        if(strcasecmp_n("nameserver", p, 10) != 0)
            continue;
        p += 10;
        while(*p == ' ' || *p == '\t')
            p++;
        q = p;
        while(*q == '.' || *q == ':' || digit(*q) || letter(*q))
            q++;
        if(*q != ' ' && *q != '\t' && *q != '\r' && *q != '\n') {
            do_log(L_WARN, "DNS: couldn't parse line in %s -- skipping.\n",
                   filename);
            continue;
        }
        nameserver = internAtomLowerN(p, q - p);
        break;
    }

 done:
    fclose(f);
    if(nameserver) {
        dnsNameServer = nameserver;
        return 1;
    } else {
        return 0;
    }
}
#endif

void
preinitDns()
{
#ifdef HAVE_IPv6
    int fd;
#endif

    assert(sizeof(struct in_addr) == 4);
#ifdef HAVE_IPv6
    assert(sizeof(struct in6_addr) == 16);
#endif

#ifndef NO_STANDARD_RESOLVER
    CONFIG_VARIABLE(dnsGethostbynameTtl, CONFIG_TIME,
                    "TTL for gethostbyname addresses.");
#endif<commit_msg>Fix crash when there is no resolv.conf.<commit_after>/*
Copyright (c) 2003, 2004 by <NAME>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "polipo.h"

#ifndef NO_STANDARD_RESOLVER
#ifndef NO_FANCY_RESOLVER
int dnsUseGethostbyname = 1;
#else 
const int dnsUseGethostbyname = 3;
#endif
#else
#ifndef NO_FANCY_RESOLVER
const int dnsUseGethostbyname = 0;
#else
#error use no resolver at all?
#endif
#endif

#ifndef NO_FANCY_RESOLVER
AtomPtr dnsNameServer = NULL;
int dnsMaxTimeout = 60;
#endif

#ifndef NO_STANDARD_RESOLVER
int dnsGethostbynameTtl = 1200;
#endif

int dnsNegativeTtl = 120;

#ifdef HAVE_IPv6
int dnsQueryIPv6 = 2;
#else
const int dnsQueryIPv6 = 0;
#endif

typedef struct _DnsQuery {
    unsigned id;
    AtomPtr name;
    ObjectPtr object;
    AtomPtr inet4, inet6;
    time_t ttl4, ttl6;
    time_t time;
    int timeout;
    TimeEventHandlerPtr timeout_handler;
    struct _DnsQuery *next;
} DnsQueryRec, *DnsQueryPtr;

union {
    struct sockaddr sa;
    struct sockaddr_in sin;
#ifdef HAVE_IPv6
    struct sockaddr_in6 sin6;
#endif
} nameserverAddress_storage;

#ifndef NO_FANCY_RESOLVER
#define nameserverAddress nameserverAddress_storage.sa

static DnsQueryPtr inFlightDnsQueries;
static DnsQueryPtr inFlightDnsQueriesLast;
#endif

static int really_do_gethostbyname(AtomPtr name, ObjectPtr object);
static int really_do_dns(AtomPtr name, ObjectPtr object);

#ifndef NO_FANCY_RESOLVER
static int stringToLabels(char *buf, int offset, int n, char *string);
static int labelsToString(char *buf, int offset, int n, char *d, 
                          int m, int *j_return);
static int dnsBuildQuery(int id, char *buf, int offset, int n,
                         AtomPtr name, int af);
static int dnsReplyHandler(int abort, FdEventHandlerPtr event);
static int dnsReplyId(char *buf, int offset, int n, int *id_return);
static int dnsDecodeReply(char *buf, int offset, int n,
                          int *id_return,
                          AtomPtr *name_return, AtomPtr *value_return,
                          int *af_return, unsigned *ttl_return);
static int dnsHandler(int status, ObjectHandlerPtr ohandler);
static int dnsGethostbynameFallback(int id, AtomPtr message);
static int sendQuery(DnsQueryPtr query);

static int idSeed;
#endif

#ifndef NO_FANCY_RESOLVER
static int
parseResolvConf(char *filename)
{
    FILE *f;
    char buf[512];
    char *p, *q;
    int n;
    AtomPtr nameserver = NULL;

    f = fopen(filename, "r");
    if(f == NULL) {
        do_log_error(L_ERROR, errno, "DNS: couldn't open %s", filename);
        return 0;
    }

    while(1) {
        p = fgets(buf, 512, f);
        if(p == NULL)
            break;

        n = strlen(buf);
        if(buf[n - 1] != '\n') {
            int c;
            do_log(L_WARN, "DNS: overly long line in %s -- skipping.\n",
                   filename);
            do {
                c = fgetc(f);
                if(c == EOF)
                    break;
            } while(c != '\n');
            if(c == EOF)
                break;
        }
        
        while(*p == ' ' || *p == '\t')
            p++;
        if(strcasecmp_n("nameserver", p, 10) != 0)
            continue;
        p += 10;
        while(*p == ' ' || *p == '\t')
            p++;
        q = p;
        while(*q == '.' || *q == ':' || digit(*q) || letter(*q))
            q++;
        if(*q != ' ' && *q != '\t' && *q != '\r' && *q != '\n') {
            do_log(L_WARN, "DNS: couldn't parse line in %s -- skipping.\n",
                   filename);
            continue;
        }
        nameserver = internAtomLowerN(p, q - p);
        break;
    }

    fclose(f);
    if(nameserver) {
        dnsNameServer = nameserver;
        return 1;
    } else {
        return 0;
    }
}
#endif

void
preinitDns()
{
#ifdef HAVE_IPv6
    int fd;
#endif

    assert(sizeof(struct in_addr) == 4);
#ifdef HAVE_IPv6
    assert(sizeof(struct in6_addr) == 16);
#endif

#ifndef NO_STANDARD_RESOLVER
    CONFIG_VARIABLE(dnsGethostbynameTtl, CONFIG_TIME,
                    "TTL for gethostbyname addresses.");
#endif
{'fraction_non_alphanumeric': 0.09709699791935004, 'fraction_numerical': 0.010601406915684137, 'mean_word_length': 2.7137601177336275, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3323102', 'n_tokens_mistral': 3404, 'n_tokens_neox': 3257, 'n_words': 1072}