pike.git / lib / modules / Protocols.pmod / DNS.pmod

version» Context lines:

pike.git/lib/modules/Protocols.pmod/DNS.pmod:1: - // $Id: DNS.pmod,v 1.95 2008/03/10 13:41:11 grubba Exp $ + // $Id: DNS.pmod,v 1.96 2008/06/28 16:36:56 nilsson Exp $   // Not yet finished -- Fredrik Hubinette      //! Domain Name System   //! RFC 1035      #pike __REAL_VERSION__      constant NOERROR=0;   constant FORMERR=1;   constant SERVFAIL=2;
pike.git/lib/modules/Protocols.pmod/DNS.pmod:104:   //! Low level DNS protocol   class protocol   {    string mklabel(string s)    {    if(sizeof(s)>63)    error("Too long component in domain name.\n");    return sprintf("%c%s",sizeof(s),s);    }    -  static private string mkname(string|array(string) labels, int pos, +  protected private string mkname(string|array(string) labels, int pos,    mapping(string:int) comp)    {    if(stringp(labels))    labels = labels/"."-({""});    if(!labels || !sizeof(labels))    return "\0";    string n = labels*".";    if(comp[n])    return sprintf("%2c", comp[n]|0xc000);    else {    if(pos<0x4000)    comp[n]=pos;    string l = mklabel(labels[0]);    return l + mkname(labels[1..], pos+sizeof(l), comp);    }    }    -  static string make_raw_addr6(string addr6) +  protected string make_raw_addr6(string addr6)    {    if(!addr6) return "\0"*16;    if(has_value(addr6, "::")) {    int parts = sizeof((addr6/":")-({""}));    if(has_value(addr6, ".")) parts++;    addr6 = replace(addr6, "::", ":"+"0:"*(8-parts));    sscanf(addr6, ":%s", addr6);    }    if(has_value(addr6, "."))    return sprintf("%2c%2c%2c%2c%2c%2c%1c%1c%1c%1c",    @array_sscanf(addr6, "%x:%x:%x:%x:%x:%x:%x.%x.%x.%x"));    else    return sprintf("%@2c",    array_sscanf(addr6, "%x:%x:%x:%x:%x:%x:%x:%x"));    }    -  static private string mkrdata(mapping entry, int pos, mapping(string:int) c) +  protected private string mkrdata(mapping entry, int pos, mapping(string:int) c)    {    switch(entry->type) {    case T_CNAME:    return mkname(entry->cname, pos, c);    case T_PTR:    return mkname(entry->ptr, pos, c);    case T_NS:    return mkname(entry->ns, pos, c);    case T_MD:    return mkname(entry->md, pos, c);
pike.git/lib/modules/Protocols.pmod/DNS.pmod:199:    lambda(string t) {    return sprintf("%1c%s", sizeof(t), t);    })*"";    case T_LOC:    // FIXME: Not implemented yet.    default:    return "";    }    }    -  static private string encode_entries(array(mapping) entries, int pos, +  protected private string encode_entries(array(mapping) entries, int pos,    mapping(string:int) comp)    {    string res="";    foreach(entries, mapping entry) {    string e = mkname(entry->name, pos, comp)+    sprintf("%2c%2c%4c", entry->type, entry->cl, entry->ttl);    pos += sizeof(e)+2;    string rd = entry->rdata || mkrdata(entry, pos, comp);    res += e + sprintf("%2c", sizeof(rd)) + rd;    pos += sizeof(rd);
pike.git/lib/modules/Protocols.pmod/DNS.pmod:488:    return m;    }   };      //! Implements a Domain Name Service (DNS) server.   class server   {    inherit protocol;    inherit Stdio.UDP : udp;    -  static void send_reply(mapping r, mapping q, mapping m) +  protected void send_reply(mapping r, mapping q, mapping m)    {    // FIXME: Needs to handle truncation somehow.    if(!r)    r = (["rcode":4]);    r->id = q->id;    r->qr = 1;    r->opcode = q->opcode;    r->rd = q->rd;    r->qd = r->qd || q->qd;    string s = mkquery(r);
pike.git/lib/modules/Protocols.pmod/DNS.pmod:529:    //! @mapping    //! @member string|array(string) "name"    //! @member int "type"    //! @member int "cl"    //! @endmapping    //! @endarray    //! @member array|void "an"    //! @member array|void "ns"    //! @member array|void "ar"    //! @endmapping -  static mapping reply_query(mapping query, mapping udp_data) +  protected mapping reply_query(mapping query, mapping udp_data)    {    // Override this function.    //    // Return mapping may contain:    // aa, ra, {ad, cd,} rcode, an, ns, ar       return 0;    }    -  static void handle_query(mapping q, mapping m) +  protected void handle_query(mapping q, mapping m)    {    mapping r = reply_query(q, m);    send_reply(r, q, m);    }    -  static void handle_response(mapping r, mapping m) +  protected void handle_response(mapping r, mapping m)    {    // This is a stub intended to simplify servers which allow recursion    }    -  static private void rec_data(mapping m) +  protected private void rec_data(mapping m)    {    mixed err;    mapping q;    if (err = catch {    q=decode_res(m->data);    }) {    werror("DNS: Failed to read UDP packet.\n%s\n",    describe_backtrace(err));    if(m && m->data && sizeof(m->data)>=2)    send_reply((["rcode":1]),
pike.git/lib/modules/Protocols.pmod/DNS.pmod:629: Inside #if defined(__NT__) and #if constant(RegGetKeyNames)
   "Parameters\\Interfaces\\" + key, val) });    };    }    };   #endif    return sizeof(res) ? res : ({ fallbackvalue });    }      #else /* !__NT__ */    -  static private mapping(string:string) etc_hosts; +  protected private mapping(string:string) etc_hosts;    -  static private int is_ip(string ip) +  protected private int is_ip(string ip)    {    // FIXME: Doesn't work with IPv6    return (replace(ip, "0123456789."/1, allocate(11,"")) == "");    }    -  static private string read_etc_file(string fname) +  protected private string read_etc_file(string fname)    {    array(string) paths;    string res;   #ifdef __NT__    paths = get_tcpip_param("DataBasePath");   #else    paths = ({ "/etc", "/amitcp/db" });   #endif    foreach(paths, string path) {    string raw = Stdio.read_file(path + "/" + fname);
pike.git/lib/modules/Protocols.pmod/DNS.pmod:663:    }    res += raw;    } else {    res = raw;    }    }    }    return res;    }    -  static private string match_etc_hosts(string host) +  protected private string match_etc_hosts(string host)    {    if (!etc_hosts) {    etc_hosts = ([ "localhost":"127.0.0.1" ]);       string raw = read_etc_file("hosts");       if (raw && sizeof(raw)) {    foreach(raw/"\n"-({""}), string line) {    // Handle comments, and split the line on white-space    line = lower_case(replace((line/"#")[0], "\t", " "));
pike.git/lib/modules/Protocols.pmod/DNS.pmod:877:    return decode_res(m->data);    }    };    }    };    }    // Failure.    return 0;    }    -  static mapping low_gethostbyname(string s, int type) +  protected mapping low_gethostbyname(string s, int type)    {    mapping m;    if(sizeof(domains) && s[-1] != '.' && sizeof(s/".") < 3) {    mapping m = do_sync_query(mkquery(s, C_IN, type));    if(!m || !m->an || !sizeof(m->an))    foreach(domains, string domain)    {    m = do_sync_query(mkquery(s+"."+domain, C_IN, type));    if(m && m->an && sizeof(m->an))    break;
pike.git/lib/modules/Protocols.pmod/DNS.pmod:1180:    string req;    string domain;    function callback;    int retries;    int timestamp;    array args;    };       mapping requests=([]);    -  static private void remove(object(Request) r) +  protected private void remove(object(Request) r)    {    if(!r) return;    sscanf(r->req,"%2c",int id);    m_delete(requests,id);    r->callback(r->domain,0,@r->args);    destruct(r);    }       void retry(object(Request) r, void|int nsno)    {
pike.git/lib/modules/Protocols.pmod/DNS.pmod:1240:    /* We failed miserably to find a request id to use,    * so we create a second UDP port to be able to have more    * requests 'in the air'. /Hubbe    */    if(!next_client)    next_client=async_client(nameservers,domains);       next_client->do_query(domain, cl, type, callback, @args);    }    -  static private void rec_data(mapping m) +  protected private void rec_data(mapping m)    {    mixed err;    if (err = catch {    if(m->port != 53 || !has_value(nameservers, m->ip)) return;    sscanf(m->data,"%2c",int id);    object r=requests[id];    if(!r) return;    m_delete(requests,id);    r->callback(r->domain,decode_res(m->data),@r->args);    destruct(r);    }) {    werror("DNS: Failed to read UDP packet. Connection refused?\n%s\n",    describe_backtrace(err));    }    }    -  static private void generic_get(string d, +  protected private void generic_get(string d,    mapping answer,    int multi,    int all,    int type,    string field,    string domain,    function callback,    mixed ... args)    {    if(!answer || !answer->an || !sizeof(answer->an))