diff -up bind-9.3.6-P1/bin/named/include/named/globals.h.dbus bind-9.3.6-P1/bin/named/include/named/globals.h --- bind-9.3.6-P1/bin/named/include/named/globals.h.dbus 2009-02-23 13:53:04.000000000 +0100 +++ bind-9.3.6-P1/bin/named/include/named/globals.h 2009-02-23 13:53:04.000000000 +0100 @@ -113,6 +113,8 @@ EXTERN const char * ns_g_username INIT EXTERN int ns_g_listen INIT(3); +EXTERN int ns_g_dbus INIT(0); + #undef EXTERN #undef INIT diff -up bind-9.3.6-P1/bin/named/include/named/log.h.dbus bind-9.3.6-P1/bin/named/include/named/log.h --- bind-9.3.6-P1/bin/named/include/named/log.h.dbus 2007-08-28 09:19:08.000000000 +0200 +++ bind-9.3.6-P1/bin/named/include/named/log.h 2009-02-23 13:53:04.000000000 +0100 @@ -34,6 +34,7 @@ #define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4]) #define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5]) #define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6]) +#define NS_LOGCATEGORY_DBUS (&ns_g_categories[7]) /* * Backwards compatibility. @@ -51,6 +52,7 @@ #define NS_LOGMODULE_NOTIFY (&ns_g_modules[8]) #define NS_LOGMODULE_CONTROL (&ns_g_modules[9]) #define NS_LOGMODULE_LWRESD (&ns_g_modules[10]) +#define NS_LOGMODULE_DBUS (&ns_g_modules[11]) isc_result_t ns_log_init(isc_boolean_t safe); diff -up bind-9.3.6-P1/bin/named/include/named/server.h.dbus bind-9.3.6-P1/bin/named/include/named/server.h --- bind-9.3.6-P1/bin/named/include/named/server.h.dbus 2006-03-02 01:37:20.000000000 +0100 +++ bind-9.3.6-P1/bin/named/include/named/server.h 2009-02-23 13:53:04.000000000 +0100 @@ -91,7 +91,8 @@ struct ns_server { ns_controls_t * controls; /* Control channels */ unsigned int dispatchgen; ns_dispatchlist_t dispatches; - + + ns_dbus_mgr_t * dbus_mgr; }; #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') diff -up bind-9.3.6-P1/bin/named/include/named/types.h.dbus bind-9.3.6-P1/bin/named/include/named/types.h --- bind-9.3.6-P1/bin/named/include/named/types.h.dbus 2004-03-06 11:21:26.000000000 +0100 +++ bind-9.3.6-P1/bin/named/include/named/types.h 2009-02-23 13:53:04.000000000 +0100 @@ -38,4 +38,6 @@ typedef struct ns_controls ns_controls_ typedef struct ns_dispatch ns_dispatch_t; typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t; +typedef struct ns_dbus_mgr ns_dbus_mgr_t ; + #endif /* NAMED_TYPES_H */ diff -up bind-9.3.6-P1/bin/named/log.c.dbus bind-9.3.6-P1/bin/named/log.c --- bind-9.3.6-P1/bin/named/log.c.dbus 2007-08-28 09:19:08.000000000 +0200 +++ bind-9.3.6-P1/bin/named/log.c 2009-02-23 13:53:04.000000000 +0100 @@ -41,6 +41,7 @@ static isc_logcategory_t categories[] = { "queries", 0 }, { "unmatched", 0 }, { "update-security", 0 }, + { "dbus", 0 }, { NULL, 0 } }; @@ -60,6 +61,7 @@ static isc_logmodule_t modules[] = { { "notify", 0 }, { "control", 0 }, { "lwresd", 0 }, + { "dbus", 0 }, { NULL, 0 } }; diff -up bind-9.3.6-P1/bin/named/main.c.dbus bind-9.3.6-P1/bin/named/main.c --- bind-9.3.6-P1/bin/named/main.c.dbus 2008-10-24 03:28:55.000000000 +0200 +++ bind-9.3.6-P1/bin/named/main.c 2009-02-23 14:38:23.000000000 +0100 @@ -241,7 +241,8 @@ usage(void) { "usage: named [-4|-6] [-c conffile] [-d debuglevel] " "[-f|-g] [-n number_of_cpus]\n" " [-p port] [-s] [-t chrootdir] [-u username]\n" - " [-m {usage|trace|record}]\n"); + " [-m {usage|trace|record}]\n" + " [-D ]\n"); } static void @@ -348,7 +349,7 @@ parse_command_line(int argc, char *argv[ isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "46c:C:d:fgi:lm:n:N:p:P:" - "sS:t:u:vx:")) != -1) { + "sS:t:u:vx:D")) != -1) { switch (ch) { case '4': if (disable4) @@ -441,6 +442,9 @@ parse_command_line(int argc, char *argv[ case 'v': printf("BIND %s\n", ns_g_version); exit(0); + case 'D': + ns_g_dbus = 1; + break; case '?': usage(); ns_main_earlyfatal("unknown option '-%c'", diff -up bind-9.3.6-P1/bin/named/Makefile.in.dbus bind-9.3.6-P1/bin/named/Makefile.in --- bind-9.3.6-P1/bin/named/Makefile.in.dbus 2009-02-23 13:53:04.000000000 +0100 +++ bind-9.3.6-P1/bin/named/Makefile.in 2009-02-23 13:53:04.000000000 +0100 @@ -35,7 +35,8 @@ CINCLUDES = -I${srcdir}/include -I${srcd ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ ${DBDRIVER_INCLUDES} - +DBUS_INCLUDES = \ + -I/usr/lib/dbus-1.0/include -I/usr/include/dbus-1.0 CDEFINES = CWARNINGS = @@ -52,6 +53,7 @@ ISCCCDEPLIBS = ../../lib/isccc/libisccc. ISCDEPLIBS = ../../lib/isc/libisc.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ +DBUSLIBS= -ldbus-1 DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS} @@ -70,7 +72,8 @@ OBJS = aclconf.o builtin.o client.o con tkeyconf.o tsigconf.o update.o xfrout.o \ zoneconf.o \ lwaddr.o lwresd.o lwdclient.o lwderror.o lwdgabn.o \ - lwdgnba.o lwdgrbn.o lwdnoop.o lwsearch.o \ + lwdgnba.o lwdgrbn.o lwdnoop.o lwsearch.o \ + dbus_service.o dbus_mgr.o \ $(DBDRIVER_OBJS) UOBJS = unix/os.o @@ -83,6 +86,7 @@ SRCS = aclconf.c builtin.c client.c con zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ + dbus_service.c dbus_mgr.c \ $(DBDRIVER_SRCS) MANPAGES = named.8 lwresd.8 named.conf.5 @@ -111,9 +115,14 @@ config.o: config.c -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -c ${srcdir}/config.c +dbus_service.o: dbus_service.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + ${DBUS_INCLUDES} \ + -c ${srcdir}/dbus_service.c + named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - ${OBJS} ${UOBJS} ${LIBS} + ${OBJS} ${UOBJS} ${LIBS} ${DBUSLIBS} lwresd@EXEEXT@: named@EXEEXT@ rm -f lwresd@EXEEXT@ diff -up bind-9.3.6-P1/bin/named/named.8.dbus bind-9.3.6-P1/bin/named/named.8 --- bind-9.3.6-P1/bin/named/named.8.dbus 2008-08-22 03:21:36.000000000 +0200 +++ bind-9.3.6-P1/bin/named/named.8 2009-02-23 14:37:36.000000000 +0100 @@ -33,7 +33,7 @@ named \- Internet domain name server .SH "SYNOPSIS" .HP 6 -\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] +\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] [\fB\-D\fR] .SH "DESCRIPTION" .PP \fBnamed\fR @@ -196,6 +196,13 @@ into the cache of the default view. This option must not be used. It is only of interest to BIND 9 developers and may be removed or changed in a future release. .RE .RE +.sp +.TP +\fB\-D\fR +Enable dynamic management of the forwarding table with D-BUS +messages. This option is required for Red Hat NetworkManager +support. See doc/README.DBUS . +.sp .SH "SIGNALS" .PP In routine operation, signals should not be used to control the nameserver; @@ -219,6 +226,73 @@ The \fBnamed\fR configuration file is too complex to describe in detail here. A complete description is provided in the BIND 9 Administrator Reference Manual. +.PP +.SH "NOTES" +.PP +.TP +\fBRed Hat SELinux BIND Security Profile:\fR +.PP +By default, Red Hat ships BIND with the most secure SELinux policy +that will not prevent normal BIND operation and will prevent exploitation +of all known BIND security vulnerabilities . See the selinux(8) man page +for information about SElinux. +.PP +It is not necessary to run named in a chroot environment if the Red Hat +SELinux policy for named is enabled. When enabled, this policy is far +more secure than a chroot environment. +.PP +With this extra security comes some restrictions: +.br +By default, the SELinux policy does not allow named to write any master +zone database files. Only the root user may create files in the $ROOTDIR/var/named +zone database file directory (the options { "directory" } option), where +$ROOTDIR is set in /etc/sysconfig/named. +.br +The "named" group must be granted read privelege to +these files in order for named to be enabled to read them. +.br +Any file created in the zone database file directory is automatically assigned +the SELinux file context named_zone_t . +.br +By default, SELinux prevents any role from modifying named_zone_t files; this +means that files in the zone database directory cannot be modified by dynamic +DNS (DDNS) updates or zone transfers. +.br +The Red Hat BIND distribution and SELinux policy creates two directories where +named is allowed to create and modify files: $ROOTDIR/var/named/slaves and +$ROOTDIR/var/named/data. By placing files you want named to modify, such as +slave or DDNS updateable zone files and database / statistics dump files in +these directories, named will work normally and no further operator action is +required. Files in these directories are automatically assigned the 'named_cache_t' +file context, which SELinux allows named to write. +.br +You can enable the named_t domain to write and create named_zone_t files by use +of the SELinux tunable boolean variable "named_write_master_zones", using the +setsebool(8) command or the system-config-security GUI . If you do this, you +must also set the ENABLE_ZONE_WRITE variable in /etc/sysconfig/named to +1 / yes to set the ownership of files in the $ROOTDIR/var/named directory +to named:named in order for named to be allowed to write them. +.PP +\fBRed Hat BIND named_sdb SDB support:\fR +.PP +Red Hat ships the bind-sdb RPM that provides the /usr/sbin/named_sdb program, +which is named compiled with the Simplified Database Backend modules that ISC +provides in the "contrib/sdb" directory. +.br +The SDB modules for LDAP, PostGreSQL and DirDB are compiled into named_sdb. +.br +To run named_sdb, set the ENABLE_SDB variable in /etc/sysconfig/named to 1 or "yes", +and then the "service named start" named initscript will run named_sdb instead +of named . +.br +See the documentation for the various SDB modules in /usr/share/doc/bind-sdb-*/ . +.PP +\fBRed Hat system-config-bind:\fR +.PP +Red Hat provides the system-config-bind GUI to configure named.conf and zone +database files. Run the "system-config-bind" command and access the manual +by selecting the Help menu. +.PP .SH "FILES" .PP \fI/etc/named.conf\fR diff -up bind-9.3.6-P1/bin/named/server.c.dbus bind-9.3.6-P1/bin/named/server.c --- bind-9.3.6-P1/bin/named/server.c.dbus 2009-02-23 13:53:04.000000000 +0100 +++ bind-9.3.6-P1/bin/named/server.c 2009-02-23 13:53:04.000000000 +0100 @@ -89,6 +89,8 @@ #include <stdlib.h> #endif +#include <named/dbus_mgr.h> + /* * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. @@ -1525,12 +1527,12 @@ configure_forward(const cfg_obj_t *confi if (result != ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(origin, namebuf, sizeof(namebuf)); - cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, - "could not set up forwarding for domain '%s': %s", + cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_NOTICE, + "setting up forwarding failed for domain '%s': %s", namebuf, isc_result_totext(result)); goto cleanup; } - + result = ISC_R_SUCCESS; cleanup: @@ -3036,6 +3038,20 @@ run_server(isc_task_t *task, isc_event_t CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones"); + server->dbus_mgr = 0L; + if( ns_g_dbus ) + if( dbus_mgr_create + ( ns_g_mctx, ns_g_taskmgr, ns_g_socketmgr, ns_g_timermgr, + &server->dbus_mgr + ) != ISC_R_SUCCESS + ) + { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "dbus_mgr initialization failed. D-BUS service is disabled." + ); + } + ns_os_started(); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "running"); @@ -3098,6 +3114,9 @@ shutdown_server(isc_task_t *task, isc_ev dns_db_detach(&server->in_roothints); + if( server->dbus_mgr != 0L ) + dbus_mgr_shutdown(server->dbus_mgr); + isc_task_endexclusive(server->task); isc_task_detach(&server->task); diff -up bind-9.3.6-P1/lib/dns/forward.c.dbus bind-9.3.6-P1/lib/dns/forward.c --- bind-9.3.6-P1/lib/dns/forward.c.dbus 2005-03-17 04:58:30.000000000 +0100 +++ bind-9.3.6-P1/lib/dns/forward.c 2009-02-23 13:53:04.000000000 +0100 @@ -200,3 +200,89 @@ auto_detach(void *data, void *arg) { } isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t)); } + +/*** + *** new D-BUS Dynamic Forwarding Zones functions: + ***/ +isc_result_t +dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name ) +{ + isc_result_t result; + + REQUIRE(VALID_FWDTABLE(fwdtable)); + + RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + + result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE); + + RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + + return (result); +} + +isc_result_t +dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable, + dns_name_t *name, + dns_name_t *foundname, + dns_forwarders_t **forwardersp) +{ + isc_result_t result; + + REQUIRE(VALID_FWDTABLE(fwdtable)); + + RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read); + + result = dns_rbt_findname(fwdtable->table, name, 0, foundname, + (void **)forwardersp); + + if(result == DNS_R_PARTIALMATCH) + result = ISC_R_SUCCESS; + + RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read); + + return (result); +} + +isc_result_t +dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name, + dns_forwarders_t **forwardersp) +{ + isc_result_t result; + + REQUIRE(VALID_FWDTABLE(fwdtable)); + + REQUIRE(forwardersp != 0L); + + RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read); + + result = dns_rbt_findname(fwdtable->table, name, 0, NULL, + (void **)forwardersp); + + if( result != ISC_R_SUCCESS ) + *forwardersp = 0L; + + RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read); + + return (result); +} + +static +void dns_fwdtable_traverse +( + dns_name_t *name, + void *node_data, + void *cbp, + void *cb_arg +) +{ + dns_fwdtable_callback_t cb = (dns_fwdtable_callback_t) cbp; + + (*cb)( name, node_data, cb_arg); +} + +void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void *cb_arg ) +{ + REQUIRE(VALID_FWDTABLE(fwdtable)); + + dns_rbt_traverse( fwdtable->table, dns_fwdtable_traverse, cb, cb_arg ); +} diff -up bind-9.3.6-P1/lib/dns/include/dns/forward.h.dbus bind-9.3.6-P1/lib/dns/include/dns/forward.h --- bind-9.3.6-P1/lib/dns/include/dns/forward.h.dbus 2005-03-17 04:58:31.000000000 +0100 +++ bind-9.3.6-P1/lib/dns/include/dns/forward.h 2009-02-23 13:53:04.000000000 +0100 @@ -98,6 +98,37 @@ dns_fwdtable_destroy(dns_fwdtable_t **fw * all memory associated with the forwarding table is freed. */ + +/* These are ONLY used by dbus_mgr : + */ + +isc_result_t +dns_fwdtable_delete( dns_fwdtable_t *fwdtable, dns_name_t *name ); +/* + * Removes an entry from the forwarding table. + */ + +isc_result_t +dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name, + dns_forwarders_t **forwardersp); +/* + * Finds an exact match for "name" in the forwarding table. + */ + +isc_result_t +dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_name_t *foundname, + dns_forwarders_t **forwardersp); +/* + * Finds the closest match for "*name" in the forwarding table, returning + * the actual name matching in *name if different to *name passed in. + */ + +typedef void (*dns_fwdtable_callback_t)( dns_name_t *, dns_forwarders_t *, void *); +void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void * ); +/* Invoke cb for each member of fwdtable + */ + + ISC_LANG_ENDDECLS #endif /* DNS_FORWARD_H */ diff -up bind-9.3.6-P1/lib/dns/include/dns/rbt.h.dbus bind-9.3.6-P1/lib/dns/include/dns/rbt.h --- bind-9.3.6-P1/lib/dns/include/dns/rbt.h.dbus 2007-08-28 09:19:14.000000000 +0200 +++ bind-9.3.6-P1/lib/dns/include/dns/rbt.h 2009-02-23 13:53:04.000000000 +0100 @@ -833,6 +833,17 @@ dns_rbtnodechain_next(dns_rbtnodechain_t * <something_else> Any error result from dns_name_concatenate. */ + +typedef void (*dns_rbt_traverse_callback_t)( dns_name_t *name, + void *node_data, + void *cb_arg1, + void *cb_arg2); + +void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 ); +/* tree traversal function (only used by D-BUS dynamic forwarding dbus_mgr at + * the moment) + */ + ISC_LANG_ENDDECLS #endif /* DNS_RBT_H */ diff -up bind-9.3.6-P1/lib/dns/rbt.c.dbus bind-9.3.6-P1/lib/dns/rbt.c --- bind-9.3.6-P1/lib/dns/rbt.c.dbus 2008-04-18 21:03:00.000000000 +0200 +++ bind-9.3.6-P1/lib/dns/rbt.c 2009-02-23 13:53:04.000000000 +0100 @@ -2169,6 +2169,47 @@ dns_rbt_printall(dns_rbt_t *rbt) { dns_rbt_printtree(rbt->root, NULL, 0); } +static void +dns_rbt_traverse_tree(dns_rbtnode_t *root, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 ) { +/* + * This is used ONLY to traverse the forward table by dbus_mgr at the moment. + * Since the forward table is not likely to be large, this can be recursive. + */ + dns_name_t name; + dns_offsets_t offsets; + char buf[DNS_NAME_MAXWIRE]; + isc_buffer_t buffer; + + if (root != NULL) { + + if (DOWN(root)) + dns_rbt_traverse_tree(DOWN(root), cb, cb_arg1, cb_arg2); + + if( LEFT(root) != NULL ) + dns_rbt_traverse_tree(LEFT(root), cb, cb_arg1, cb_arg2); + + if( RIGHT(root) != NULL ) + dns_rbt_traverse_tree(RIGHT(root), cb, cb_arg1, cb_arg2); + + if( DATA(root) == 0L ) + return; + + dns_name_init(&name, offsets); + isc_buffer_init(&buffer, buf, DNS_NAME_MAXWIRE); + dns_name_setbuffer( &name, &buffer); + dns_rbt_fullnamefromnode(root, &name); + + (*cb)(&name, DATA(root), cb_arg1, cb_arg2); + } +} + +void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 ) +{ + REQUIRE(VALID_RBT(rbt)); + + dns_rbt_traverse_tree( rbt->root, cb, cb_arg1, cb_arg2 ); +} + /* * Chain Functions */ diff -up bind-9.3.6-P1/lib/isc/include/isc/socket.h.dbus bind-9.3.6-P1/lib/isc/include/isc/socket.h --- bind-9.3.6-P1/lib/isc/include/isc/socket.h.dbus 2008-09-11 08:14:46.000000000 +0200 +++ bind-9.3.6-P1/lib/isc/include/isc/socket.h 2009-02-23 14:29:07.000000000 +0100 @@ -143,6 +143,10 @@ struct isc_socket_connev { #define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3) #define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4) +#define ISC_SOCKEVENT_READ_READY (ISC_EVENTCLASS_SOCKET + 5) +#define ISC_SOCKEVENT_WRITE_READY (ISC_EVENTCLASS_SOCKET + 6) +#define ISC_SOCKEVENT_SELECTED (ISC_EVENTCLASS_SOCKET + 7) + /* * Internal events. */ @@ -151,7 +155,8 @@ struct isc_socket_connev { typedef enum { isc_sockettype_udp = 1, - isc_sockettype_tcp = 2 + isc_sockettype_tcp = 2, + isc_sockettype_fd = 8 } isc_sockettype_t; /* @@ -781,6 +786,30 @@ isc__socketmgr_setreserved(isc_socketmgr * Temporary. For use by named only. */ +isc_socketevent_t* +isc_socket_fd_handle_reads( isc_socket_t *sock, isc_socketevent_t *dev ); +/* register the "dev" event to be sent when the isc_sockettype_fd sock + * was select()-ed for read. If there is already an event registered, it + * is returned, otherwise 0 is returned. If dev is 0, removes any existing + * registered event. + */ + +isc_socketevent_t* +isc_socket_fd_handle_writes( isc_socket_t *sock, isc_socketevent_t *dev ); +/* register the "dev" event to be sent when the isc_sockettype_fd sock + * was select()-ed for write. If there is already an event registered, it + * is returned, otherwise 0 is returned. If dev is 0, removes any existing + * registered event. + */ + +isc_socketevent_t* +isc_socket_fd_handle_selected( isc_socket_t *sock, isc_socketevent_t *dev ); +/* register the "dev" event to be sent when ALL isc_sockettype_fd sockets + * have been select()-ed . If there is already an event registered, it + * is returned, otherwise 0 is returned. If dev is 0, removes any existing + * registered event. + */ + ISC_LANG_ENDDECLS #endif /* ISC_SOCKET_H */ diff -up bind-9.3.6-P1/lib/isc/unix/socket.c.dbus bind-9.3.6-P1/lib/isc/unix/socket.c --- bind-9.3.6-P1/lib/isc/unix/socket.c.dbus 2008-11-20 01:07:38.000000000 +0100 +++ bind-9.3.6-P1/lib/isc/unix/socket.c 2009-02-23 14:27:41.000000000 +0100 @@ -285,6 +285,11 @@ struct isc_socket { ISC_LIST(isc_socketevent_t) recv_list; ISC_LIST(isc_socket_newconnev_t) accept_list; isc_socket_connev_t *connect_ev; + + /* these are used only by isc_sockettype_fd sockets:*/ + isc_socketevent_t *read_ready_event; + isc_socketevent_t *write_ready_event; + isc_socketevent_t *selected_event; /* * Internal events. Posted when a descriptor is readable or @@ -1727,6 +1732,9 @@ allocate_socket(isc_socketmgr_t *manager sock->connected = 0; sock->connecting = 0; sock->bound = 0; + sock->read_ready_event = 0L; + sock->write_ready_event = 0L; + sock->selected_event = 0L; /* * initialize the lock @@ -1861,6 +1869,8 @@ opensocket(isc_socketmgr_t *manager, isc case isc_sockettype_tcp: sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); break; + case isc_sockettype_fd: + sock->fd = sock->pf; } if (sock->fd == -1 && errno == EINTR && tries++ < 42) goto again; @@ -1937,7 +1947,8 @@ opensocket(isc_socketmgr_t *manager, isc } } - if (make_nonblock(sock->fd) != ISC_R_SUCCESS) { + if ((sock->type != isc_sockettype_fd) && + (make_nonblock(sock->fd) != ISC_R_SUCCESS)) { (void)close(sock->fd); return (ISC_R_UNEXPECTED); } @@ -2361,6 +2372,38 @@ dispatch_connect(isc_socket_t *sock) { isc_task_send(ev->ev_sender, (isc_event_t **)&iev); } +static +isc_event_t *dispatch_read_ready(isc_socketmgr_t *manager, isc_socket_t *sock) +{ + isc_event_t *dev = (isc_event_t*)sock->read_ready_event, *ev; + + ev = isc_mem_get(manager->mctx, dev->ev_size); + memcpy(ev,dev,dev->ev_size); + ISC_LINK_INIT(ev,ev_link); + isc_task_send(dev->ev_sender, &ev ); + return (isc_event_t *)sock->selected_event; +} + +static +isc_event_t *dispatch_write_ready(isc_socketmgr_t *manager,isc_socket_t *sock) +{ + isc_event_t *dev = (isc_event_t*)sock->write_ready_event, *ev; + ev = isc_mem_get(manager->mctx, dev->ev_size); + memcpy(ev,dev,dev->ev_size); + ISC_LINK_INIT(ev,ev_link); + isc_task_send(dev->ev_sender, &ev ); + return (isc_event_t *)sock->selected_event; +} + +static +void dispatch_selected(isc_socketmgr_t *manager, isc_event_t *dev) +{ isc_event_t *ev; + ev = isc_mem_get(manager->mctx, dev->ev_size); + memcpy(ev,dev,dev->ev_size); + ISC_LINK_INIT(ev,ev_link); + isc_task_send(dev->ev_sender, &ev ); +} + /* * Dequeue an item off the given socket's read queue, set the result code * in the done event to the one provided, and send it to the task it was @@ -2789,6 +2832,7 @@ process_fd(isc_socketmgr_t *manager, int isc_socket_t *sock; isc_boolean_t unlock_sock; int lockid = FDLOCK_ID(fd); + isc_event_t *sock_selected = NULL; /* * If the socket is going to be closed, don't do more I/O. @@ -2813,10 +2857,15 @@ process_fd(isc_socketmgr_t *manager, int unlock_sock = ISC_TRUE; LOCK(&sock->lock); if (!SOCK_DEAD(sock)) { - if (sock->listener) - dispatch_accept(sock); - else - dispatch_recv(sock); + if (sock->type != isc_sockettype_fd) { + if (sock->listener) + dispatch_accept(sock); + else + dispatch_recv(sock); + } else { + sock_selected = dispatch_read_ready(manager, + sock); + } } (void)unwatch_fd(manager, fd, SELECT_POKE_READ); } @@ -2831,15 +2880,24 @@ check_write: LOCK(&sock->lock); } if (!SOCK_DEAD(sock)) { - if (sock->connecting) - dispatch_connect(sock); - else - dispatch_send(sock); + if (sock->type != isc_sockettype_fd) { + if (sock->connecting) + dispatch_connect(sock); + else + dispatch_send(sock); + } else { + sock_selected = dispatch_write_ready(manager, + sock); + } } (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); } if (unlock_sock) UNLOCK(&sock->lock); + + if (sock_selected != NULL) { + dispatch_selected(manager, sock_selected); + } } #ifdef USE_KQUEUE @@ -4793,3 +4851,52 @@ isc__socketmgr_dispatch(isc_socketwait_t #endif } #endif /* ISC_PLATFORM_USETHREADS */ + +isc_socketevent_t* +isc_socket_fd_handle_reads (isc_socket_t *sock, isc_socketevent_t *dev) { + REQUIRE(VALID_SOCKET(sock)); + + if (dev != NULL) { + sock->references = 1; + sock->read_ready_event = dev; + select_poke(sock->manager, sock->fd, SELECT_POKE_READ); + } else { + dev = sock->read_ready_event; + sock->read_ready_event = NULL; + } + + return dev; +} + +isc_socketevent_t* +isc_socket_fd_handle_writes (isc_socket_t *sock, isc_socketevent_t *dev) { + REQUIRE(VALID_SOCKET(sock)); + + if (dev != NULL) { + sock->references = 1; + sock->write_ready_event = dev; + select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE); + } else { + dev = sock->write_ready_event; + sock->write_ready_event = NULL; + } + + return dev; +} + +isc_socketevent_t* +isc_socket_fd_handle_selected (isc_socket_t *sock, isc_socketevent_t *dev) { + REQUIRE(VALID_SOCKET(sock)); + + if (dev != NULL) { + sock->references = 1; + sock->selected_event = dev; + } else { + dev = sock->selected_event; + sock->selected_event = NULL; + sock->references = 0; + destroy(&sock); + } + + return dev; +}