pike.git
/
lib
/
modules
/
Protocols.pmod
/
DNS.pmod
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Protocols.pmod/DNS.pmod:98:
//! Type - NAPTR (RFC 3403) T_NAPTR=35, //! Type - IPv6 address record (RFC 2874, incomplete support) T_A6=38, //! Type - SPF - Sender Policy Framework (RFC 4408) T_SPF=99, };
+
int safe_bind(Stdio.UDP udp, mixed ... args)
+
{
+
mixed err = catch {
+
udp->bind(@args);
+
return 1;
+
};
+
master()->handle_error(err);
+
return 0;
+
}
+
//! 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); }
pike.git/lib/modules/Protocols.pmod/DNS.pmod:605:
sscanf(s[next[0]..next[0]+3],"%2c%2c",m->qd[i]->type, m->qd[i]->cl); next[0]+=4; } m->an=decode_entries(s,m->ancount,next); m->ns=decode_entries(s,m->nscount,next); m->ar=decode_entries(s,m->arcount,next); return m; } };
+
protected string ANY;
+
+
protected void create()
+
{
+
// Check if IPv6 support is available.
+
catch {
+
// Note: Attempt to open a port on the IPv6 loopback (::1)
+
// rather than on IPv6 any (::), to make sure some
+
// IPv6 support is actually configured. This is needed
+
// since eg Solaris happily opens ports on :: even
+
// if no IPv6 interfaces are configured.
+
// Try IPv6 any (::) too for paranoia reasons.
+
Stdio.Port p = Stdio.Port();
+
if (p->bind(0, 0, "::1") && p->bind(0, 0, "::")) {
+
ANY = "::";
+
}
+
destruct(p);
+
};
+
}
+
//! Base class for implementing a Domain Name Service (DNS) server. //! //! This class is typically used by inheriting it, //! and overloading @[reply_query()] and @[handle_response()]. class server { //! inherit protocol; //inherit Stdio.UDP : udp;
pike.git/lib/modules/Protocols.pmod/DNS.pmod:743:
//! @decl void create() //! @decl void create(int port) //! @decl void create(string ip) //! @decl void create(string ip, int port) //! @decl void create(string ip, int port, string|int ... more) //! //! Open one or more new DNS server ports. //! //! @param ip
-
//! The IP to bind to. Defaults to @expr{0@} (ie ANY).
+
//! The IP to bind to. Defaults to
@expr{"::"@} or
@expr{0@} (ie ANY)
+
//! depending on whether IPv6 support is present or not
.
//! //! @param port //! The port number to bind to. Defaults to @expr{53@}. //! //! @param more //! Optional further DNS server ports to open. //! Must be a set of @[ip], @[port] argument pairs. protected void create(int|string|void arg1, string|int ... args) { if(!arg1 && !sizeof(args)) arg1 = 53; if(!sizeof(args)) { if(stringp(arg1)) args = ({ arg1, 53 }); else
-
args = ({
0
, arg1 });
+
args = ({
ANY
, 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]))
+
if (!
safe_
bind(
udp,
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]))
+
if(!
safe_
bind(
udp,
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}); } } protected void destory()
pike.git/lib/modules/Protocols.pmod/DNS.pmod:1042:
nameservers = ({ server }); if(arrayp(domain)) domains = domain; else if(stringp(domain)) domains = ({ domain }); } }
-
//! Perform a
syncronous
DNS query.
+
//! Perform a
synchronous
DNS query.
//! //! @param s //! Result of @[Protocols.DNS.protocol.mkquery] //! @returns //! mapping containing query result or 0 on failure/timeout //! //! @example //! @code //! // Perform a hostname lookup, results stored in r->an //! object d=Protocols.DNS.client(); //! mapping r=d->do_sync_query(d->mkquery("pike.lysator.liu.se", C_IN, T_A)); //! @endcode mapping do_sync_query(string s) { int i; object udp = Stdio.UDP(); // Attempt to randomize the source port. for (i = 0; i < RETRIES; i++) {
-
if (!
catch { udp->
bind(1024 + random(65536-1024),
"::");
}
) continue;
+
if (!
safe_
bind(
udp,
1024 + random(65536-1024),
ANY
)
)
continue;
}
-
if (i >= RETRIES)
udp->
bind(0,
"::"
) || udp->bind(0);
+
if (i >= RETRIES)
safe_
bind(
udp,
0,
ANY
) || udp->bind(0);
#if 0 werror("Protocols.DNS.client()->do_sync_query(%O)\n" "UDP Address: %s\n" "%s\n", s, udp->query_address(), describe_backtrace(backtrace())); #endif /* 0 */ mapping m; for (i=0; i < RETRIES; i++) { udp->send(nameservers[i % sizeof(nameservers)], 53, s); // upd->wait() can throw an error sometimes.
pike.git/lib/modules/Protocols.pmod/DNS.pmod:1575:
void close() { udp::close(); udp::set_read_callback(0); } //! protected void create(void|string|array(string) server, void|string|array(string) domain) {
-
if(!udp::bind(0))
+
int i;
+
// Attempt to randomize the source port.
+
for (i = 0; i < RETRIES; i++) {
+
if
(
safe_bind(udp::this, 1024 + random(65536-1024), ANY)) break;
+
}
+
if((i >= RETRIES) &&
+
!
safe_bind(
udp::
this, 0, ANY) &&
+
!safe_
bind(
udp::this,
0))
error( "DNS: failed to bind a port.\n" ); #if 0 werror("Protocols.DNS.async_client(%O, %O)\n" "UDP Address: %s\n" "%s\n", server, domain, udp::query_address(), describe_backtrace(backtrace())); #endif /* 0 */ udp::set_read_callback(rec_data); ::create(server,domain);