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.101 2009/03/16 14:09:54 grubba Exp $ + // $Id: DNS.pmod,v 1.102 2010/01/05 18:47:33 bill Exp $   // Not yet finished -- Fredrik Hubinette    - //! Domain Name System +  //inherit Stdio.UDP : udp;   //! RFC 1034, RFC 1035 and RFC 2308 - //! +  protected void send_reply(mapping r, mapping q, mapping m, Stdio.UDP udp);      #pike __REAL_VERSION__      final constant NOERROR=0;   final constant FORMERR=1;   final constant SERVFAIL=2;   final constant NXDOMAIN=3;   final constant NOTIMPL=4;   final constant REFUSED=5;   final constant NXRRSET=8;
pike.git/lib/modules/Protocols.pmod/DNS.pmod:616:    return m;    }   };      //! Implements a Domain Name Service (DNS) server.   class server   {    //!    inherit protocol;    -  inherit Stdio.UDP : udp; +  //inherit Stdio.UDP : udp;    -  protected void send_reply(mapping r, mapping q, mapping m) +  array(Stdio.UDP) ports = ({}); +  +  protected void send_reply(mapping r, mapping q, mapping m, Stdio.UDP udp)    {    // 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); -  udp::send(m->ip, m->port, s); +  udp->send(m->ip, m->port, s);    }       //! Reply to a query (stub).    //!    //! @param query    //! Parsed query.    //!    //! @param udp_data    //! Raw UDP data.    //! -  +  //! @param cb +  //! Callback you can call with the result instead of returning it. +  //! In that case, return @expr{0@} (zero). +  //! +  //!    //! Overload this function to implement the proper lookup.    //!    //! @returns    //! Returns @expr{0@} (zero) on failure, or a result mapping on success:    //! @mapping    //! @member int "rcode"    //! @member array(mapping(string:string|int))|void "an"    //! @array    //! @elem mapping(string:string|int) entry    //! @mapping    //! @member string|array(string) "name"    //! @member int "type"    //! @member int "cl"    //! @endmapping    //! @endarray    //! @member array|void "qd"    //! @member array|void "ns"    //! @member array|void "ar"    //! @endmapping -  protected mapping reply_query(mapping query, mapping udp_data) +  protected mapping reply_query(mapping query, mapping udp_data, +  function(mapping:void) cb)    {    // Override this function.    //    // Return mapping may contain:    // aa, ra, {ad, cd,} rcode, an, ns, ar       return 0;    }    -  protected void handle_query(mapping q, mapping m) +  protected void handle_query(mapping q, mapping m, Stdio.UDP udp)    { -  mapping r = reply_query(q, m); -  send_reply(r, q, m); +  int(0..1) result_available = 0; +  void _cb(mapping r) { +  if(result_available) +  error("DNS: you can either use the callback OR return the reply, not both.\n"); +  result_available = 1; +  send_reply(r, q, m, udp); +  }; +  mapping r = reply_query(q, m, _cb); +  if(r && result_available) +  error("DNS: you can either use the callback OR return the reply, not both.\n"); +  if(r) { +  result_available = 1; +  send_reply(r, q, m, udp);    } -  +  }    -  protected void handle_response(mapping r, mapping m) +  protected void handle_response(mapping r, mapping m, Stdio.UDP udp)    {    // This is a stub intended to simplify servers which allow recursion    }    -  protected private void rec_data(mapping m) +  protected private void rec_data(mapping m, Stdio.UDP udp)    {    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]), -  mkmapping(({"id"}), array_sscanf(m->data, "%2c")), m); +  mkmapping(({"id"}), array_sscanf(m->data, "%2c")), m, udp);    }    else if(q->qr) -  handle_response(q, m); +  handle_response(q, m, udp);    else -  handle_query(q, m); +  handle_query(q, m, udp);    }    -  void create(int|void port) +  void create(int|string|void arg1, string|int ... args)    { -  if(!port) -  port = 53; -  if(!udp::bind(port)) -  error("DNS: failed to bind port "+port+".\n"); - #if 0 -  werror("Protocols.DNS.server(%O)\n" -  "UDP Address: %s\n" -  "%s\n", port, udp::query_address(), -  describe_backtrace(backtrace())); - #endif /* 0 */ -  udp::set_read_callback(rec_data); +  if(!arg1 && !sizeof(args)) +  arg1 = 53; +  if(!sizeof(args)) +  { +  if(stringp(arg1)) +  args = ({ arg1, 53 }); +  else +  args = ({ 0, arg1 });    } -  +  else +  args = ({ arg1 }) + args; +  if(sizeof(args)&1) +  error("DNS: if you specify more than one argument, the number of " +  "arguments needs to be even (server(ip1, port1, ip2, port2, " +  "...)).\n"); +  for(int i;i<sizeof(args);i+=2) { +  Stdio.UDP udp = Stdio.UDP(); +  if(args[i]) { +  if (!udp->bind(args[i+1],args[i])) +  error("DNS: failed to bind host:port %s:%d.\n", args[i],args[i+1]); +  } else { +  if(!udp->bind(args[i+1])) +  error("DNS: failed to bind port %d.\n", args[i+1]); +  } +  udp->set_read_callback(rec_data, udp); +  // port objects are stored for destruction when the server object is destroyed. +  ports += ({udp}); +  }       }    -  +  static void destory() +  { +  if(sizeof(ports)) +  { +  foreach(ports;; Stdio.UDP port) +  destruct(port); +  } +  }    -  + } +  +    #define RETRIES 12   #define RETRY_DELAY 5      //! Synchronous DNS client.   class client   {    inherit protocol;      #ifdef __NT__    array(string) get_tcpip_param(string val, void|string fallbackvalue)