+2007-02-25 Michael Poole <mdpoole@troilus.org>
+
+ * doc/example.conf: Document new options for General block.
+
+ * include/res.h (clear_nameservers): Declare new function.
+ (add_nameserver): Declare previously static function.
+
+ * include/s_bsd.h (VirtualHost_dns_v4): Declare.
+ (VirtualHost_dns_v6): Likewise.
+
+ * ircd/ircd_lexer.l (DNS): Recognize new token.
+
+ * ircd/ircd_parser.y (DNS): Declare new token.
+ (generalitem): Allow new items for dns vhost(s) and dns servers.
+ (generaldnsvhost): New production.
+ (generaldnsserver): New production.
+
+ * ircd/ircd_res.c (VirtualHost_dns_v4): New variable.
+ (VirtualHost_dns_v6): Likewise.
+ (clear_nameservers): New function.
+ (restart_resolver): Scan specified servers so we only try to open
+ DNS client sockets that we need.
+
+ * ircd/ircd_reslib.c (irc_nscount): Remove redundant initializer.
+ (irc_res_init): Only read the resolver config file if there are no
+ nameservers provided.
+ (add_nameserver): Make non-static. Remove off-by-one check
+ against IRCD_MAXNS.
+
+ * ircd/s_conf.c (read_configuration_file): Clear nameserver list
+ before reading the config file.
+
2007-01-27 Jeannot Langlois <jeannot12@linuxmail.org>
* doc/example.conf (Features): Illustrate URLREG feature.
# vhost = "ipv6vhost";
# description = "description";
# numeric = numericnumber;
+# dns vhost = "ipv4vhost";
+# dns vhost = "ipv6vhost";
+# dns server = "ipaddress";
+# dns server = "ipaddress2";
# };
#
# If present, <virtual host> must contain a valid address in dotted
#
# Note that <server numeric> has to be unique on the network your server
# is running on, must be between 0 and 4095, and is not updated on a rehash.
+#
+# The two DNS lines allow you to specify the local IP address to use
+# for DNS lookups ("dns vhost") and one or more DNS server addresses
+# to use. If the vhost is ambiguous for some reason, you may list
+# IPV4 and/or IPV6 between the equals sign and the address string.
+# The default DNS vhost is to let the operating system assign the
+# address, and the default DNS servers are read from /etc/resolv.conf.
+# In most cases, you do not need to specify either the dns vhost or
+# the dns server.
General {
name = "London.UK.Eu.UnderNet.org";
description = "University of London, England";
} HEADER;
extern void restart_resolver(void);
+extern void clear_nameservers(void);
+extern void add_nameserver(const char *ipaddr);
extern void add_local_domain(char *hname, size_t size);
extern size_t cres_mem(struct Client* cptr);
extern void delete_resolver_queries(const void *vptr);
extern struct Client* LocalClientArray[MAXCONNECTIONS];
extern struct irc_sockaddr VirtualHost_v4;
extern struct irc_sockaddr VirtualHost_v6;
+extern struct irc_sockaddr VirtualHost_dns_v4;
+extern struct irc_sockaddr VirtualHost_dns_v6;
/*
* Proto types
TOKEN(FAST),
TOKEN(AUTOCONNECT),
TOKEN(PROGRAM),
+ TOKEN(DNS),
#undef TOKEN
{ "administrator", ADMIN },
{ "apass_opmode", TPRIV_APASS_OPMODE },
%token AUTOCONNECT
%token PROGRAM
%token TOK_IPV4 TOK_IPV6
+%token DNS
/* and now a lot of privileges... */
%token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
%token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
parse_error("Your General block must contain a numeric (between 1 and 4095).");
};
generalitems: generalitem generalitems | generalitem;
-generalitem: generalnumeric | generalname | generalvhost | generaldesc;
+generalitem: generalnumeric | generalname | generalvhost | generaldesc
+ | generaldnsvhost | generaldnsserver;
+
generalnumeric: NUMERIC '=' NUMBER ';'
{
if (localConf.numeric == 0)
MyFree(vhost);
};
+generaldnsvhost: DNS VHOST '=' address_family QSTRING ';'
+{
+ struct irc_in_addr addr;
+ int families = $4;
+ char *vhost = $5;
+
+ if (!strcmp(vhost, "*")) {
+ /* Let the operating system assign the default. */
+ } else if (!ircd_aton(&addr, vhost))
+ parse_error("Invalid DNS virtual host '%s'.", vhost);
+ else
+ {
+ if ((families & USE_IPV4)
+ || (!families && irc_in_addr_is_ipv4(&addr)))
+ memcpy(&VirtualHost_dns_v4.addr, &addr, sizeof(addr));
+ if ((families & USE_IPV6)
+ || (!families && !irc_in_addr_is_ipv4(&addr)))
+ memcpy(&VirtualHost_dns_v6.addr, &addr, sizeof(addr));
+ }
+ MyFree(vhost);
+};
+
+generaldnsserver: DNS SERVER '=' QSTRING ';'
+{
+ char *server = $4;
+
+ add_nameserver(server);
+ MyFree(server);
+};
+
adminblock: ADMIN
{
MyFree(localConf.location1);
static struct Socket res_socket_v6;
/** Next DNS lookup timeout. */
static struct Timer res_timeout;
+/** Local address for IPv4 DNS lookups. */
+struct irc_sockaddr VirtualHost_dns_v4;
+/** Local address for IPv6 DNS lookups. */
+struct irc_sockaddr VirtualHost_dns_v6;
/** Check for whether the resolver has been initialized yet. */
#define resolver_started() (request_list.next != NULL)
extern int irc_nscount;
extern char irc_domain[HOSTLEN];
+/** Prepare the resolver library to (optionally) accept a list of
+ * DNS servers through add_dns_server().
+ */
+void clear_nameservers(void)
+{
+ irc_nscount = 0;
+ memset(&VirtualHost_dns_v4, 0, sizeof(VirtualHost_dns_v4));
+ memset(&VirtualHost_dns_v6, 0, sizeof(VirtualHost_dns_v6));
+}
+
/** Check whether \a inp is a nameserver we use.
* @param[in] inp Nameserver address.
* @return Non-zero if we trust \a inp; zero if not.
void
restart_resolver(void)
{
+ int need_v4;
+ int need_v6;
+ int ns;
+
irc_res_init();
if (!request_list.next)
request_list.next = request_list.prev = &request_list;
- if (!s_active(&res_socket_v4))
+ /* Check which address family (or families) our nameservers use. */
+ for (need_v4 = need_v6 = ns = 0; ns < irc_nscount; ns++)
+ {
+ if (irc_in_addr_is_ipv4(&irc_nsaddr_list[ns].addr))
+ need_v4 = 1;
+ else
+ need_v6 = 1;
+ }
+
+ /* If we need an IPv4 socket, and don't have one, open it. */
+ if (need_v4 && !s_active(&res_socket_v4))
{
- int fd = os_socket(&VirtualHost_v4, SOCK_DGRAM, "Resolver UDPv4 socket", AF_INET);
+ int fd = os_socket(&VirtualHost_dns_v4, SOCK_DGRAM, "Resolver UDPv4 socket", AF_INET);
if (fd >= 0)
socket_add(&res_socket_v4, res_readreply, NULL,
SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
}
#ifdef AF_INET6
- if (!s_active(&res_socket_v6))
+ /* If we need an IPv6 socket, and don't have one, open it. */
+ if (need_v6 && !s_active(&res_socket_v6))
{
- int fd = os_socket(&VirtualHost_v6, SOCK_DGRAM, "Resolver UDPv6 socket", AF_INET6);
+ int fd = os_socket(&VirtualHost_dns_v6, SOCK_DGRAM, "Resolver UDPv6 socket", AF_INET6);
if (fd >= 0)
socket_add(&res_socket_v6, res_readreply, NULL,
SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
/** Array of nameserver addresses. */
struct irc_sockaddr irc_nsaddr_list[IRCD_MAXNS];
/** Number of nameservers in #irc_nsaddr_list. */
-int irc_nscount = 0;
+int irc_nscount;
/** Local domain to use as a search suffix. */
char irc_domain[HOSTLEN + 1];
};
static int parse_resvconf(void);
-static void add_nameserver(char *arg);
/** Array of decimal digits, indexed by value. */
static const char digits[] = "0123456789";
int
irc_res_init(void)
{
- irc_nscount = 0;
- return(parse_resvconf());
+ return (irc_nscount == 0) ? parse_resvconf() : 0;
}
/** Read resolver configuration file for domain and nameserver lines.
/** Add a resolver to #irc_nsaddr_list.
* @param[in] arg Dotted quad or IPv6 text form of nameserver address.
*/
-static void
-add_nameserver(char *arg)
+void
+add_nameserver(const char *arg)
{
struct irc_sockaddr res;
/* Done max number of nameservers? */
- if ((irc_nscount + 1) >= IRCD_MAXNS)
+ if (irc_nscount >= IRCD_MAXNS)
return;
/* Failure converting from numeric string? */
{
conf_error = 0;
feature_unmark(); /* unmark all features for resetting later */
+ clear_nameservers(); /* clear previous list of DNS servers */
/* Now just open an fd. The buffering isn't really needed... */
init_lexer();
yyparse();