#include <config.h>
#include <isc/types.h>
#include <isc/net.h>
#include <isc/mem.h>
#include <isc/magic.h>
#include <isc/list.h>
#include <isc/task.h>
#include <isc/event.h>
#include <isc/socket.h>
#include <isc/timer.h>
#include <isc/netaddr.h>
#include <isc/sockaddr.h>
#include <isc/buffer.h>
#include <isc/log.h>
#include <dns/name.h>
#include <dns/acl.h>
#include <dns/fixedname.h>
#include <dns/view.h>
#include <dns/forward.h>
#include <named/types.h>
#include <named/config.h>
#include <named/server.h>
#include <named/globals.h>
#include <named/log.h>
#include <named/dbus_service.h>
#include <named/dbus_mgr.h>
#include <string.h>
#include <search.h>
typedef void (*__free_fn_t) (void *__nodep);
extern void tdestroy (void *__root, __free_fn_t __freefct);
extern void free(void*);
#ifdef ISC_USE_INTERNAL_MALLOC
# if ISC_USE_INTERNAL_MALLOC
# error dbus_mgr cannot be used if ISC_USE_INTERNAL_MALLOC==1
# endif
#endif
#define DBUSMGR_DESTINATION "com.redhat.named"
#define DBUSMGR_OBJECT_PATH "/com/redhat/named"
#define DBUSMGR_INTERFACE "com.redhat.named"
#define DBUSMGR_MAGIC ISC_MAGIC('D', 'B', 'U', 'S')
struct ns_dbus_mgr
{
unsigned int magic;
isc_mem_t * mctx;
isc_taskmgr_t * taskmgr;
isc_socketmgr_t * socketmgr;
isc_timermgr_t * timermgr;
isc_task_t * task;
isc_timer_t * timer;
void * sockets;
void * dhc_if;
void * ifwdt;
char * dhcdbd_name;
DBUS_SVC dbus;
};
typedef
struct dbus_mgr_sock_s
{
int fd;
struct ns_dbus_mgr *mgr;
isc_socket_t *sock;
isc_socketevent_t *ser;
isc_socketevent_t *sew;
isc_socketevent_t *sel;
} DBusMgrSocket;
typedef
enum dhc_state_e
{
DHC_NBI,
DHC_PREINIT,
DHC_BOUND,
DHC_RENEW,
DHC_REBOOT,
DHC_REBIND,
DHC_STOP,
DHC_MEDIUM,
DHC_TIMEOUT,
DHC_FAIL,
DHC_EXPIRE,
DHC_RELEASE,
DHC_START,
DHC_ABEND,
DHC_END,
DHC_END_OPTIONS,
DHC_INVALID=255
} DHC_State;
typedef ISC_LIST(dns_name_t) DNSNameList;
typedef ISC_LIST(isc_sockaddr_t) SockAddrList;
typedef struct dbm_fwdr_s
{
dns_fwdpolicy_t fwdpolicy;
dns_name_t dn;
SockAddrList sa;
ISC_LINK( struct dbm_fwdr_s ) link;
} DBusMgrInitialFwdr;
typedef
struct dhc_if_s
{
char *if_name;
DHC_State dhc_state;
DHC_State previous_state;
struct in_addr ip;
struct in_addr subnet_mask;
DNSNameList dn;
SockAddrList dns;
} DHC_IF;
static void
dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp );
static
dbus_svc_HandlerResult
dbus_mgr_message_handler
(
DBusMsgHandlerArgs
);
static
void dbus_mgr_close_socket( const void *p, const VISIT which, const int level);
static
void dbus_mgr_destroy_socket( void *p );
static
void dbus_mgr_free_dhc( void *p );
static void
dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev);
static isc_result_t
dbus_mgr_init_dbus(ns_dbus_mgr_t *);
static isc_result_t
dbus_mgr_record_initial_fwdtable(ns_dbus_mgr_t *);
static void
dbus_mgr_free_initial_fwdtable(ns_dbus_mgr_t *);
static
uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t * );
static
void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t * );
static
int dbus_mgr_log_err( const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
isc_log_vwrite(ns_g_lctx,
NS_LOGCATEGORY_DBUS,
NS_LOGMODULE_DBUS,
ISC_LOG_NOTICE,
fmt, va
);
va_end(va);
return 0;
}
static
int dbus_mgr_log_dbg( const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
isc_log_vwrite(ns_g_lctx,
NS_LOGCATEGORY_DBUS,
NS_LOGMODULE_DBUS,
ISC_LOG_DEBUG(80),
fmt, va
);
va_end(va);
return 0;
}
static
int dbus_mgr_log_info( const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
isc_log_vwrite(ns_g_lctx,
NS_LOGCATEGORY_DBUS,
NS_LOGMODULE_DBUS,
ISC_LOG_DEBUG(1),
fmt, va
);
va_end(va);
return 0;
}
isc_result_t
dbus_mgr_create
( isc_mem_t *mctx,
isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
ns_dbus_mgr_t **dbus_mgr
)
{
isc_result_t result;
ns_dbus_mgr_t *mgr;
*dbus_mgr = 0L;
mgr = isc_mem_get(mctx, sizeof(*mgr));
if (mgr == NULL)
return (ISC_R_NOMEMORY);
mgr->magic = DBUSMGR_MAGIC;
mgr->mctx = mctx;
mgr->taskmgr = taskmgr;
mgr->socketmgr = socketmgr;
mgr->timermgr = timermgr;
mgr->task = 0L;
mgr->sockets = 0L;
mgr->timer = 0L;
mgr->dhc_if = 0L;
mgr->ifwdt = 0L;
mgr->dhcdbd_name = 0L;
if( (result = isc_task_create( taskmgr, 100, &(mgr->task)))
!= ISC_R_SUCCESS
) goto cleanup_mgr;
isc_task_setname( mgr->task, "dbusmgr", mgr );
mgr->dbus = 0L;
if( (result = dbus_mgr_record_initial_fwdtable( mgr ))
!= ISC_R_SUCCESS
) goto cleanup_mgr;
if( (result = dbus_mgr_init_dbus( mgr ))
!= ISC_R_SUCCESS
) goto cleanup_mgr;
*dbus_mgr = mgr;
return ISC_R_SUCCESS;
cleanup_mgr:
if( mgr->task != 0L )
isc_task_detach(&(mgr->task));
isc_mem_put(mctx, mgr, sizeof(*mgr));
return (result);
}
static isc_result_t
dbus_mgr_init_dbus(ns_dbus_mgr_t * mgr)
{
char destination[]=DBUSMGR_DESTINATION;
if( mgr->sockets != 0L )
{
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
twalk(mgr->sockets, dbus_mgr_close_socket);
tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
mgr->sockets = 0L;
}
if( mgr->dbus != 0L )
{
dbus_svc_shutdown(mgr->dbus);
mgr->dbus = 0L;
}
mgr->dbus =
dbus_svc_init
( DBUS_PRIVATE_SYSTEM,
destination,
dbus_mgr_watch_handler,
0L, 0L,
mgr
);
if( mgr->dbus == 0L )
{
if( mgr->timer == 0L)
{
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
if( mgr->sockets != 0L )
{
twalk(mgr->sockets, dbus_mgr_close_socket);
tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
mgr->sockets = 0L;
}
dbus_mgr_dbus_shutdown_handler ( mgr );
return ISC_R_SUCCESS;
}
goto cleanup;
}
if( !dbus_svc_add_filter
( mgr->dbus, dbus_mgr_message_handler, mgr, 4,
"type=signal,path=/org/freedesktop/DBus,member=NameOwnerChanged",
"type=signal,path=/org/freedesktop/DBus/Local,member=Disconnected",
"type=signal,interface=com.redhat.dhcp.subscribe.binary",
"type=method_call,destination=com.redhat.named,path=/com/redhat/named"
)
)
{
dbus_mgr_log_err( "dbus_svc_add_filter failed" );
goto cleanup;
}
if( mgr->timer != 0L )
{
isc_timer_reset(mgr->timer,
isc_timertype_inactive,
NULL, NULL, ISC_TRUE
);
}
if( !dbus_mgr_subscribe_to_dhcdbd( mgr ) )
dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
dbus_mgr_log_err("D-BUS service enabled.");
return ISC_R_SUCCESS;
cleanup:
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
twalk(mgr->sockets, dbus_mgr_close_socket);
tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
mgr->sockets = 0L;
if( mgr->dbus )
{
dbus_svc_shutdown(mgr->dbus);
mgr->dbus = 0L;
}
return ISC_R_FAILURE;
}
static
uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t *mgr )
{
DBUS_SVC dbus = mgr->dbus;
char subs[1024], path[1024],
dhcdbd_destination[]="com.redhat.dhcp", *ddp[1]={ &(dhcdbd_destination[0]) },
*dhcdbd_name=0L;
const char *options[] = { "reason", "ip-address", "subnet-mask",
"domain-name", "domain-name-servers"
};
dbus_svc_MessageHandle msg;
int i, n_opts = 5;
if( mgr->dhcdbd_name == 0L )
{
msg = dbus_svc_call
( dbus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"GetNameOwner",
"org.freedesktop.DBus",
TYPE_STRING, &ddp,
TYPE_INVALID
);
if( msg == 0L )
return 0;
if( !dbus_svc_get_args(dbus, msg,
TYPE_STRING, &(dhcdbd_name),
TYPE_INVALID
)
) return 0;
mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(dhcdbd_name) + 1);
if( mgr->dhcdbd_name == 0L )
return 0;
strcpy(mgr->dhcdbd_name, dhcdbd_name);
}
sprintf(path,"/com/redhat/dhcp/subscribe");
sprintf(subs,"com.redhat.dhcp.binary");
for(i = 0; i < n_opts; i++)
{
msg = dbus_svc_call
( dbus,
"com.redhat.dhcp",
path,
"binary",
subs,
TYPE_STRING, &(options[i]),
TYPE_INVALID
);
if(msg == 0L)
return 0;
if ( dbus_svc_message_type( msg ) == ERROR )
return 0;
}
dbus_mgr_log_err("D-BUS dhcdbd subscription enabled.");
return 1;
}
void
dbus_mgr_shutdown
( ns_dbus_mgr_t *mgr
)
{
if( mgr->timer != 0L )
isc_timer_detach(&(mgr->timer));
if( mgr->dbus != 0L )
{
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
if( mgr->sockets != 0L )
{
twalk(mgr->sockets, dbus_mgr_close_socket);
tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
mgr->sockets = 0L;
}
dbus_svc_shutdown(mgr->dbus);
}
if( mgr->dhc_if != 0L )
tdestroy(mgr->dhc_if, dbus_mgr_free_dhc);
if( mgr->dhcdbd_name != 0L )
isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1);
isc_task_detach(&(mgr->task));
dbus_mgr_free_initial_fwdtable(mgr);
isc_mem_put(mgr->mctx, mgr, sizeof(ns_dbus_mgr_t));
}
static
void dbus_mgr_restart_dbus(isc_task_t *t, isc_event_t *ev)
{
ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg) ;
t=t;
isc_event_free(&ev);
dbus_mgr_log_dbg("attempting to connect to D-BUS");
dbus_mgr_init_dbus( mgr );
}
static
void dbus_mgr_handle_dbus_shutdown_event(isc_task_t *t, isc_event_t *ev)
{
ns_dbus_mgr_t *mgr = ev->ev_arg;
isc_time_t tick={10,0};
isc_interval_t tock={10,0};
DBUS_SVC dbus = mgr->dbus;
t = t;
mgr->dbus = 0L;
isc_event_free(&ev);
if ( dbus != 0L )
{
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
if( mgr->sockets != 0L )
{
twalk(mgr->sockets, dbus_mgr_close_socket);
tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
mgr->sockets = 0L;
}
dbus_svc_shutdown(dbus);
}
dbus_mgr_log_err( "D-BUS service disabled." );
if( mgr->timer != 0L )
{
isc_timer_reset(mgr->timer,
isc_timertype_ticker,
&tick, &tock, ISC_TRUE
);
}else
if( isc_timer_create
( mgr->timermgr,
isc_timertype_ticker,
&tick, &tock,
mgr->task,
dbus_mgr_restart_dbus,
mgr,
&(mgr->timer)
) != ISC_R_SUCCESS
)
{
dbus_mgr_log_err( "D-BUS service cannot be restored." );
}
}
static
void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t *mgr )
{
isc_event_t *dbus_shutdown_event =
isc_event_allocate
( mgr->mctx,
mgr->task,
1,
dbus_mgr_handle_dbus_shutdown_event,
mgr,
sizeof(isc_event_t)
);
if( dbus_shutdown_event != 0L )
{
isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
isc_task_send( mgr->task, &dbus_shutdown_event );
}else
dbus_mgr_log_err("unable to allocate dbus shutdown event");
}
static
dns_view_t *dbus_mgr_get_localhost_view(void)
{
dns_view_t *view;
isc_netaddr_t localhost = { AF_INET, { { htonl( ( 127 << 24 ) | 1 ) } }, 0 };
int match;
for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link)
)
{
if(( (view->matchclients != 0L )
&&(( dns_acl_match( &localhost,
NULL,
view->matchclients,
&(ns_g_server->aclenv),
&match,
NULL
) != ISC_R_SUCCESS
) || (match <= 0)
)
)
||( (view->matchdestinations != 0L )
&&(( dns_acl_match( &localhost,
NULL,
view->matchdestinations,
&(ns_g_server->aclenv),
&match,
NULL
) != ISC_R_SUCCESS
) || (match <= 0)
)
)
) continue;
break;
}
return view;
}
static
dns_fwdtable_t *dbus_mgr_get_fwdtable(void)
{
dns_view_t *view = dbus_mgr_get_localhost_view();
if( view != 0L )
return view->fwdtable;
return 0L;
}
static
dns_fwdtable_t *dbus_mgr_get_view_and_fwdtable( dns_view_t **viewp )
{
*viewp = dbus_mgr_get_localhost_view();
if( *viewp != 0L )
return (*viewp)->fwdtable;
return 0L;
}
static int dbus_mgr_ifwdr_comparator( const void *p1, const void *p2 )
{
char n1buf[ DNS_NAME_FORMATSIZE ]="", *n1p=&(n1buf[0]),
n2buf[ DNS_NAME_FORMATSIZE ]="", *n2p=&(n2buf[0]);
dns_name_t *dn1;
dns_name_t *dn2;
DE_CONST(&(((const DBusMgrInitialFwdr*)p1)->dn), dn1);
DE_CONST(&(((const DBusMgrInitialFwdr*)p2)->dn), dn2);
dns_name_format(dn1, n1p, DNS_NAME_FORMATSIZE );
dns_name_format(dn2, n2p, DNS_NAME_FORMATSIZE );
return strcmp(n1buf, n2buf);
}
static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 );
static void dbus_mgr_record_initial_forwarder( dns_name_t *name, dns_forwarders_t *fwdr, void *mp )
{
ns_dbus_mgr_t *mgr = mp;
isc_sockaddr_t *sa, *nsa;
DBusMgrInitialFwdr *ifwdr;
if( ISC_LIST_HEAD(fwdr->addrs) == 0L)
return;
if( (ifwdr = isc_mem_get(mgr->mctx, sizeof(DBusMgrInitialFwdr))) == 0L)
return;
ifwdr->fwdpolicy = fwdr->fwdpolicy;
dns_name_init(&(ifwdr->dn), NULL);
if( dns_name_dupwithoffsets(name, mgr->mctx, &(ifwdr->dn)) != ISC_R_SUCCESS )
return;
ISC_LIST_INIT(ifwdr->sa);
for( sa = ISC_LIST_HEAD(fwdr->addrs);
sa != 0L;
sa = ISC_LIST_NEXT(sa,link)
)
{
nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsa == 0L )
return;
*nsa = *sa;
ISC_LINK_INIT(nsa, link);
ISC_LIST_APPEND(ifwdr->sa, nsa, link);
}
ISC_LINK_INIT(ifwdr, link);
tsearch( ifwdr, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator);
}
static isc_result_t
dbus_mgr_record_initial_fwdtable( ns_dbus_mgr_t *mgr )
{
dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable();
if( fwdtable == 0L )
return ISC_R_SUCCESS;
dns_fwdtable_foreach( fwdtable, dbus_mgr_record_initial_forwarder, mgr);
return ISC_R_SUCCESS;
}
static void
dbus_mgr_free_initial_forwarder( void *p )
{
DBusMgrInitialFwdr *ifwdr = p;
isc_sockaddr_t *sa;
dns_name_free(&(ifwdr->dn), ns_g_mctx);
for( sa = ISC_LIST_HEAD( ifwdr->sa );
sa != 0L;
sa = ISC_LIST_HEAD( ifwdr->sa )
)
{
if( ISC_LINK_LINKED(sa, link) )
ISC_LIST_UNLINK(ifwdr->sa, sa, link);
isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t));
}
isc_mem_put(ns_g_mctx, ifwdr, sizeof(DBusMgrInitialFwdr));
}
static void
dbus_mgr_free_initial_fwdtable( ns_dbus_mgr_t *mgr )
{
tdestroy(mgr->ifwdt, dbus_mgr_free_initial_forwarder);
mgr->ifwdt = 0L;
}
static void
dbus_mgr_log_forwarders( const char *pfx, dns_name_t *name, SockAddrList *saList)
{
isc_sockaddr_t *sa;
char nameP[DNS_NAME_FORMATSIZE], addrP[128];
int s=0;
dns_name_format(name, nameP, DNS_NAME_FORMATSIZE );
for( sa = ISC_LIST_HEAD(*saList);
sa != 0L;
sa = ISC_LIST_NEXT(sa,link)
)
{
isc_sockaddr_format(sa, addrP, 128);
dbus_mgr_log_info("%s zone %s server %d: %s", pfx, nameP, s++, addrP);
}
}
static
isc_result_t dbus_mgr_set_forwarders
(
ns_dbus_mgr_t *mgr,
DNSNameList *nameList,
SockAddrList *saList,
dns_fwdpolicy_t fwdpolicy
)
{
isc_result_t result = ISC_R_SUCCESS;
dns_fwdtable_t *fwdtable;
dns_view_t *view=0L;
dns_name_t *dnsName;
isc_sockaddr_t *sa, *nsa;
dns_forwarders_t *fwdr=0L;
fwdtable = dbus_mgr_get_view_and_fwdtable(&view);
if( fwdtable == 0L )
{
if( ISC_LIST_HEAD(*saList) == 0L )
return ISC_R_SUCCESS;
view = dbus_mgr_get_localhost_view();
if( view == 0L )
return ISC_R_NOPERM;
result = isc_task_beginexclusive(mgr->task);
if( result == ISC_R_SUCCESS )
{
result = dns_fwdtable_create( mgr->mctx, &(view->fwdtable) );
isc_task_endexclusive(mgr->task);
if( result != ISC_R_SUCCESS )
return result;
if( view->fwdtable == 0L )
return ISC_R_NOMEMORY;
if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
dbus_mgr_log_info("Created forwarder table.");
}
}
for( dnsName = ISC_LIST_HEAD(*nameList);
dnsName != NULL;
dnsName = ISC_LIST_NEXT(dnsName,link)
)
{
fwdr = 0L;
if( ( dns_fwdtable_find_exact( fwdtable, dnsName, &fwdr ) != ISC_R_SUCCESS )
||( fwdr == 0L )
)
{
if( ISC_LIST_HEAD( *saList ) == 0L )
continue;
result = isc_task_beginexclusive(mgr->task);
if( result == ISC_R_SUCCESS )
{
result = dns_fwdtable_add( fwdtable, dnsName,
(isc_sockaddrlist_t*)saList,
fwdpolicy
) ;
if( view != 0L )
dns_view_flushcache( view );
isc_task_endexclusive(mgr->task);
if( result != ISC_R_SUCCESS )
return result;
if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
dbus_mgr_log_forwarders("Created forwarder",dnsName, saList);
}
continue;
}
if( ISC_LIST_HEAD( *saList ) == 0L )
{
if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
dbus_mgr_log_forwarders("Deleting forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
result = isc_task_beginexclusive(mgr->task);
if( result == ISC_R_SUCCESS )
{
result = dns_fwdtable_delete( fwdtable, dnsName );
if( view != 0L )
dns_view_flushcache( view );
isc_task_endexclusive(mgr->task);
if( result != ISC_R_SUCCESS )
return result;
}
continue;
}
result = isc_task_beginexclusive(mgr->task);
if( result == ISC_R_SUCCESS )
{
fwdr->fwdpolicy = fwdpolicy;
if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
dbus_mgr_log_forwarders("Removing forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
for( sa = ISC_LIST_HEAD(fwdr->addrs);
sa != 0L ;
sa = ISC_LIST_HEAD(fwdr->addrs)
)
{
if( ISC_LINK_LINKED(sa, link) )
ISC_LIST_UNLINK(fwdr->addrs, sa, link);
isc_mem_put(mgr->mctx, sa, sizeof(isc_sockaddr_t));
}
ISC_LIST_INIT( fwdr->addrs );
for( sa = ISC_LIST_HEAD(*saList);
sa != 0L;
sa = ISC_LIST_NEXT(sa,link)
)
{
nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsa == 0L )
{
result = ISC_R_NOMEMORY;
break;
}
*nsa = *sa;
ISC_LINK_INIT( nsa, link );
ISC_LIST_APPEND( fwdr->addrs, nsa, link );
}
if( view != 0L )
dns_view_flushcache( view );
isc_task_endexclusive(mgr->task);
if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
dbus_mgr_log_forwarders("Added forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
}else
return result;
}
return (result);
}
static void
dbus_mgr_get_name_list
(
ns_dbus_mgr_t *mgr,
char *domains,
DNSNameList *nameList,
char *error_name,
char *error_message
)
{
char *name, *endName, *endp;
dns_fixedname_t *fixedname;
dns_name_t *dnsName;
isc_buffer_t buffer;
isc_result_t result;
uint32_t total_length;
total_length = strlen(domains);
endp = domains + total_length;
ISC_LIST_INIT( *nameList );
for( name = domains + strspn(domains," \t\n"),
endName = name + strcspn(name," \t\n");
(name < endp) && (endName <= endp);
name = endName + 1 + strspn(endName+1," \t\n"),
endName = name + strcspn(name," \t\n")
)
{
*endName = '\0';
isc_buffer_init( &buffer, name, endName - name );
isc_buffer_add(&buffer, endName - name);
fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t ));
dns_fixedname_init(fixedname);
dnsName = dns_fixedname_name(fixedname);
result= dns_name_fromtext
( dnsName, &buffer, ( *(endp-1) != '.') ? dns_rootname : NULL, ISC_FALSE, NULL
);
if( result != ISC_R_SUCCESS )
{
sprintf(error_name, "com.redhat.named.InvalidArgument");
sprintf(error_message,"Invalid DNS name initial argument: %s", name);
isc_mem_put( mgr->mctx, fixedname, sizeof( dns_fixedname_t ) );
for( dnsName = ISC_LIST_HEAD( *nameList );
(dnsName != 0L);
dnsName = ISC_LIST_HEAD( *nameList )
)
{
if( ISC_LINK_LINKED(dnsName,link) )
ISC_LIST_DEQUEUE( *nameList, dnsName, link );
isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) );
}
ISC_LIST_INIT(*nameList);
return;
}
ISC_LINK_INIT(dnsName, link);
ISC_LIST_ENQUEUE( *nameList, dnsName, link );
}
}
static isc_result_t
dbus_mgr_get_sa_list
(
ns_dbus_mgr_t *mgr,
dbus_svc_MessageIterator iter,
SockAddrList *saList ,
uint8_t *fwdpolicy,
char *error_name,
char *error_message
)
{
DBUS_SVC dbus = mgr->dbus;
isc_sockaddr_t *nsSA=0L, *nsSA_Q=0L;
uint32_t argType = dbus_svc_message_next_arg_type( dbus, iter ),
length;
isc_result_t result;
in_port_t port;
char *ip;
uint8_t *iparray=0L;
ISC_LIST_INIT(*saList);
if( argType == TYPE_INVALID )
return ISC_R_SUCCESS;
do
{
switch( argType )
{
case TYPE_UINT32:
nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsSA != 0L )
{
memset(nsSA,'\0', sizeof(isc_sockaddr_t));
nsSA_Q = nsSA;
dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_addr.s_addr));
nsSA->type.sa.sa_family = AF_INET;
nsSA->length = sizeof( nsSA->type.sin );
}
break;
case TYPE_ARRAY:
argType = dbus_svc_message_element_type( dbus, iter );
if( argType == TYPE_BYTE )
{
iparray = 0L;
length = 0;
dbus_svc_message_get_elements(dbus, iter, &length, &iparray);
if( iparray != 0L )
{
if (length == sizeof( struct in_addr ))
{
nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsSA != 0L )
{
memset(nsSA,'\0', sizeof(isc_sockaddr_t));
nsSA_Q = nsSA;
memcpy(&(nsSA->type.sin.sin_addr), iparray, sizeof( struct in_addr ));
nsSA->type.sa.sa_family = AF_INET;
nsSA->length = sizeof( nsSA->type.sin );
}
}else
if (length == sizeof( struct in6_addr ))
{
nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsSA != 0L )
{
memset(nsSA,'\0', sizeof(isc_sockaddr_t));
nsSA_Q = nsSA;
memcpy(&(nsSA->type.sin6.sin6_addr), iparray, sizeof( struct in6_addr ));
nsSA->type.sa.sa_family = AF_INET6;
nsSA->length = sizeof( nsSA->type.sin6 );
}
}
}
}
break;
case TYPE_STRING:
ip = 0L;
dbus_svc_message_next_arg(dbus, iter, &(ip));
if( ip != 0L )
{
length = strlen(ip);
if( strspn(ip, "0123456789.") == length )
{
nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsSA != 0L)
{
memset(nsSA,'\0', sizeof(isc_sockaddr_t));
if( inet_pton( AF_INET, ip, &(nsSA->type.sin.sin_addr)) )
{
nsSA->type.sa.sa_family = AF_INET;
nsSA->length = sizeof(nsSA->type.sin);
nsSA_Q = nsSA;
}
}
}else
if( strspn(ip, "0123456789AaBbCcDdEeFf:.") == length)
{
nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
if( nsSA != 0L )
{
memset(nsSA,'\0', sizeof(isc_sockaddr_t));
if( inet_pton( AF_INET6, ip, &(nsSA->type.sin6.sin6_addr)) )
{
nsSA->type.sa.sa_family = AF_INET6;
nsSA->length = sizeof(nsSA->type.sin6);
nsSA_Q = nsSA;
}
}
}
}
break;
case TYPE_UINT16:
if( (nsSA == 0L) || (nsSA->type.sa.sa_family == AF_UNSPEC) )
break;
else
if( nsSA->type.sa.sa_family == AF_INET )
dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_port));
else
if( nsSA->type.sa.sa_family == AF_INET6 )
dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin6.sin6_port));
break;
case TYPE_BYTE:
dbus_svc_message_next_arg(dbus, iter, fwdpolicy);
if(*fwdpolicy > dns_fwdpolicy_only)
*fwdpolicy = dns_fwdpolicy_only;
break;
default:
if(nsSA != 0L)
nsSA->type.sa.sa_family = AF_UNSPEC;
sprintf(error_message,"Unhandled argument type: %c", argType);
break;
}
if( (nsSA != 0L)
&&(nsSA->type.sa.sa_family == AF_UNSPEC)
)
{
sprintf(error_name, "com.redhat.named.InvalidArgument");
if( error_message[0]=='\0')
{
if( nsSA == 0L )
sprintf(error_message,"Missing IP Address Name Server argument");
else
sprintf(error_message,"Bad IP Address Name Server argument");
}
if( nsSA != 0L )
isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t));
nsSA = 0L;
for( nsSA = ISC_LIST_HEAD( *saList );
(nsSA != 0L);
nsSA = ISC_LIST_HEAD( *saList )
)
{
if(ISC_LINK_LINKED(nsSA, link))
ISC_LIST_DEQUEUE( *saList, nsSA, link );
isc_mem_put( mgr->mctx, nsSA, sizeof( isc_sockaddr_t ) );
}
ISC_LIST_INIT(*saList);
return ISC_R_FAILURE;
}
if( nsSA != 0L )
{
if( nsSA->type.sin.sin_port == 0 )
{
if( ns_g_port != 0L )
nsSA->type.sin.sin_port = htons(ns_g_port);
else
{
result = ns_config_getport(ns_g_config, &(port) );
if( result != ISC_R_SUCCESS )
port = 53;
nsSA->type.sin.sin_port = htons( port );
}
}
if( nsSA_Q != 0L )
{
ISC_LINK_INIT(nsSA,link);
ISC_LIST_ENQUEUE(*saList, nsSA, link);
nsSA_Q = 0L;
}
}
argType = dbus_svc_message_next_arg_type( dbus, iter );
} while ( argType != TYPE_INVALID );
return ISC_R_SUCCESS;
}
static void
dbus_mgr_handle_set_forwarders
(
ns_dbus_mgr_t *mgr,
DBUS_SVC dbus,
uint8_t reply_expected,
uint32_t serial,
const char *path,
const char *member,
const char *interface,
const char *sender,
dbus_svc_MessageHandle msg
)
{
dbus_svc_MessageIterator iter;
char error_name[1024]="", error_message[1024]="", *domains=0L;
uint32_t argType, new_serial;
DNSNameList nameList;
dns_name_t *dnsName;
SockAddrList saList;
isc_sockaddr_t *nsSA;
isc_result_t result;
uint8_t fwdpolicy = dns_fwdpolicy_only;
iter = dbus_svc_message_iterator_new( dbus, msg );
if( iter == 0L )
{
if( reply_expected )
{
sprintf(error_name, "com.redhat.named.InvalidArguments");
sprintf(error_message,"SetForwarders requires DNS name and nameservers arguments.");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
return;
}
argType = dbus_svc_message_next_arg_type( dbus, iter );
if( argType != TYPE_STRING )
{
if( reply_expected )
{
sprintf(error_name, "com.redhat.named.InvalidArguments");
sprintf(error_message,"SetForwarders requires DNS name string initial argument.");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
return;
}
dbus_svc_message_next_arg( dbus, iter, &domains );
if( ( domains == 0L ) || (*domains == '\0') )
{
if( reply_expected )
{
sprintf(error_name, "com.redhat.named.InvalidArguments");
sprintf(error_message,"SetForwarders requires DNS name string initial argument.");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
return;
}
dbus_mgr_get_name_list( mgr, domains, &nameList, error_name, error_message );
if( error_name[0] != '\0' )
{
if( reply_expected )
{
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
return;
}
if( ISC_LIST_HEAD( nameList ) == 0L )
return;
result = dbus_mgr_get_sa_list( mgr, iter, &saList , &fwdpolicy, error_name, error_message );
if( result == ISC_R_SUCCESS )
{
result = dbus_mgr_set_forwarders( mgr, &nameList, &saList, fwdpolicy );
if( result != ISC_R_SUCCESS )
{
if( reply_expected )
{
sprintf(error_name, "com.redhat.named.Failure");
sprintf(error_message, isc_result_totext(result));
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
}else
if( reply_expected )
dbus_svc_send( dbus, RETURN, serial, &new_serial, sender, path, interface, member,
TYPE_UINT32, &result, TYPE_INVALID
);
}else
{
if( reply_expected )
{
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
}
for( dnsName = ISC_LIST_HEAD( nameList );
(dnsName != 0L) ;
dnsName = ISC_LIST_HEAD( nameList )
)
{
if( ISC_LINK_LINKED(dnsName,link) )
ISC_LIST_DEQUEUE( nameList, dnsName, link );
isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) );
}
for( nsSA = ISC_LIST_HEAD(saList);
(nsSA != 0L) ;
nsSA = ISC_LIST_HEAD(saList)
)
{
if( ISC_LINK_LINKED(nsSA,link) )
ISC_LIST_DEQUEUE( saList, nsSA, link );
isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t));
}
}
static
int dbus_mgr_msg_append_dns_name
( DBUS_SVC dbus,
dbus_svc_MessageHandle msg,
dns_name_t *name
)
{
char nameBuf[ DNS_NAME_FORMATSIZE ]="", *nameP=&(nameBuf[0]);
dns_name_format(name, nameP, DNS_NAME_FORMATSIZE );
if( *nameP == '\0' )
return 0;
return dbus_svc_message_append_args( dbus, msg, TYPE_STRING, &nameP, TYPE_INVALID ) > 0;
}
typedef enum dbmoi_e
{
OUTPUT_BINARY,
OUTPUT_TEXT
} DBusMgrOutputInterface;
static
int dbus_mgr_msg_append_forwarders
( DBUS_SVC dbus,
dbus_svc_MessageHandle msg,
dns_forwarders_t *fwdr,
DBusMgrOutputInterface outputType
)
{
isc_sockaddr_t *sa;
char policyBuf[16]="", *pbp[1]={&(policyBuf[0])}, addressBuf[64]="", *abp[1]={&(addressBuf[0])};
uint8_t *byteArray[1];
if( outputType == OUTPUT_BINARY )
{
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_BYTE, &(fwdr->fwdpolicy),
TYPE_INVALID
)
) return 0;
}else
if( outputType == OUTPUT_TEXT )
{
sprintf(policyBuf,"%s",
(fwdr->fwdpolicy == dns_fwdpolicy_none)
? "none"
: (fwdr->fwdpolicy == dns_fwdpolicy_first)
? "first"
: "only"
);
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_STRING, pbp,
TYPE_INVALID
)
) return 0;
}else
return 0;
for( sa = ISC_LIST_HEAD(fwdr->addrs);
sa != 0L;
sa = ISC_LIST_NEXT(sa, link)
)
{
if( outputType == OUTPUT_BINARY )
{
if( sa->type.sa.sa_family == AF_INET )
{
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_UINT32, &(sa->type.sin.sin_addr.s_addr),
TYPE_INVALID
)
) return 0;
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_UINT16, &(sa->type.sin.sin_port),
TYPE_INVALID
)
) return 0;
}else
if( sa->type.sa.sa_family == AF_INET6 )
{
byteArray[0] = (uint8_t*)&(sa->type.sin6.sin6_addr);
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_ARRAY, TYPE_BYTE, &byteArray, sizeof(struct in6_addr),
TYPE_INVALID
)
) return 0;
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_UINT16, &(sa->type.sin6.sin6_port),
TYPE_INVALID
)
) return 0;
}else
continue;
}else
if( outputType == OUTPUT_TEXT )
{
if( sa->type.sa.sa_family == AF_INET )
{
if( inet_ntop( AF_INET, &(sa->type.sin.sin_addr), addressBuf, sizeof(addressBuf)) == 0L )
continue;
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_STRING, abp,
TYPE_INVALID
)
) return 0;
sprintf(addressBuf, "%hu", ntohs( sa->type.sin.sin_port ));
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_STRING, abp,
TYPE_INVALID
)
) return 0;
}else
if( sa->type.sa.sa_family == AF_INET6 )
{
if( inet_ntop( AF_INET6, &(sa->type.sin6.sin6_addr), addressBuf, sizeof(addressBuf)) == 0L )
continue;
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_STRING, abp,
TYPE_INVALID
)
) return 0;
sprintf(addressBuf, "%hu", ntohs( sa->type.sin6.sin6_port ));
if(!dbus_svc_message_append_args
( dbus, msg,
TYPE_STRING, abp,
TYPE_INVALID
)
) return 0;
}else
continue;
}else
return 0;
}
return 1;
}
typedef struct dbm_m_s
{
DBUS_SVC dbus;
dbus_svc_MessageHandle msg;
DBusMgrOutputInterface outputType;
} DBusMgrMsg;
static
void forwarders_to_msg( dns_name_t *name, dns_forwarders_t *fwdr, void *mp )
{
DBusMgrMsg *m = mp;
if( (fwdr == 0L) || (name == 0L) || (mp == 0L))
return;
dbus_mgr_msg_append_dns_name ( m->dbus, m->msg, name );
dbus_mgr_msg_append_forwarders( m->dbus, m->msg, fwdr, m->outputType );
}
static void
dbus_mgr_handle_list_forwarders
(
DBUS_SVC dbus,
uint8_t reply_expected,
uint32_t serial,
const char *path,
const char *member,
const char *interface,
const char *sender,
dbus_svc_MessageHandle msg
)
{
char error_name[1024], error_message[1024];
DBusMgrMsg m;
uint32_t new_serial;
dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable();
DBusMgrOutputInterface outputType = OUTPUT_BINARY;
uint32_t length = strlen(interface);
if( !reply_expected )
return;
if( (length > 4) && (strcmp(interface + (length - 4), "text")==0))
outputType = OUTPUT_TEXT;
if( fwdtable == 0L )
{
sprintf(error_name,"com.redhat.dbus.Failure");
sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM));
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member);
m.dbus = dbus;
m.msg = msg;
m.outputType = outputType;
if( msg == 0L )
{
sprintf(error_name,"com.redhat.dbus.OutOfMemory");
sprintf(error_message,"out of memory");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
dns_fwdtable_foreach( fwdtable, forwarders_to_msg, &m );
dbus_svc_send_message( dbus, msg, &new_serial );
}
static void
dbus_mgr_handle_get_forwarders
(
DBUS_SVC dbus,
uint8_t reply_expected,
uint32_t serial,
const char *path,
const char *member,
const char *interface,
const char *sender,
dbus_svc_MessageHandle msg
)
{
char error_name[1024], error_message[1024], *domain=0L;
isc_result_t result;
dns_fixedname_t fixedname;
dns_name_t *dnsName;
isc_buffer_t buffer;
uint32_t length, new_serial;
dns_fwdtable_t *fwdtable;
dns_forwarders_t *fwdr=0L;
dns_name_t *foundname;
dns_fixedname_t fixedFoundName;
DBusMgrOutputInterface outputType = OUTPUT_BINARY;
if( !reply_expected )
return;
length = strlen(interface);
if( (length > 4) && (strcmp(interface + (length - 4), "text")==0))
outputType = OUTPUT_TEXT;
if( (!dbus_svc_get_args( dbus, msg, TYPE_STRING, &domain, TYPE_INVALID))
||(domain == 0L)
||(*domain == '\0')
)
{
sprintf(error_name,"com.redhat.dbus.InvalidArguments");
sprintf(error_message,"domain name argument expected");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
length = strlen( domain );
isc_buffer_init( &buffer, domain, length);
isc_buffer_add(&buffer, length);
dns_fixedname_init(&fixedname);
dnsName = dns_fixedname_name(&fixedname);
result = dns_name_fromtext
( dnsName, &buffer, dns_rootname, ISC_FALSE, NULL
);
if( result != ISC_R_SUCCESS )
{
sprintf(error_name,"com.redhat.dbus.InvalidArguments");
sprintf(error_message,"invalid domain name argument: %s", domain);
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member);
if( msg == 0L )
{
sprintf(error_name,"com.redhat.dbus.OutOfMemory");
sprintf(error_message,"out of memory");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
fwdtable = dbus_mgr_get_fwdtable();
if( fwdtable == 0L )
{
sprintf(error_name,"com.redhat.dbus.Failure");
sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM));
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
dns_fixedname_init(&fixedFoundName);
foundname = dns_fixedname_name(&fixedFoundName);
if( ( dns_fwdtable_find_closest( fwdtable, dnsName, foundname, &fwdr ) == ISC_R_SUCCESS )
&&( fwdr != 0L )
)
{
if( (!dbus_mgr_msg_append_dns_name( dbus, msg, foundname ))
||(!dbus_mgr_msg_append_forwarders( dbus, msg, fwdr, outputType ))
)
{
sprintf(error_name,"com.redhat.dbus.OutOfMemory");
sprintf(error_message,"out of memory");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
}else
{
result = ISC_R_NOTFOUND;
if( outputType == OUTPUT_BINARY )
{
dbus_svc_message_append_args( dbus, msg,
TYPE_UINT32, &(result),
TYPE_INVALID
) ;
}else
{
sprintf(error_name,"com.redhat.dbus.NotFound");
sprintf(error_message,"Not Found");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
return;
}
}
dbus_svc_send_message( dbus, msg, &new_serial );
}
static void
dbus_mgr_check_dhcdbd_state( ns_dbus_mgr_t *mgr, dbus_svc_MessageHandle msg )
{
DBUS_SVC dbus = mgr->dbus;
char *name_owned = 0L,
*old_owner = 0L,
*new_owner = 0L;
if( !dbus_svc_get_args( dbus, msg,
TYPE_STRING, &name_owned,
TYPE_STRING, &old_owner,
TYPE_STRING, &new_owner,
TYPE_INVALID
)
) return;
dbus_mgr_log_dbg("NameOwnerChanged: %s %s %s ( %s )", name_owned, old_owner, new_owner, mgr->dhcdbd_name);
if( (name_owned == 0L) || (new_owner == 0L) || (old_owner == 0L) )
return;
if( strcmp( name_owned, "com.redhat.dhcp" ) == 0 )
{
if( *new_owner == '\0' )
{
isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1);
mgr->dhcdbd_name = 0L;
dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
return;
}
if( (mgr->dhcdbd_name == 0L)
||( strcmp( mgr->dhcdbd_name, new_owner) != 0 )
)
{
if( mgr->dhcdbd_name != 0L )
{
isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name)+1);
mgr->dhcdbd_name = 0L;
}
mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(new_owner) + 1);
if( mgr->dhcdbd_name == 0L )
return;
strcpy( mgr->dhcdbd_name, new_owner );
dbus_mgr_subscribe_to_dhcdbd( mgr );
}
}else
if( ( mgr->dhcdbd_name != 0L )
&& ( strcmp(mgr->dhcdbd_name, name_owned) == 0L )
&& ( *new_owner == '\0' )
)
{
isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name));
mgr->dhcdbd_name = 0L;
dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
}
}
static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 )
{
return( strcmp( ((const DHC_IF*)p1)->if_name, ((const DHC_IF*)p2)->if_name) );
}
static
dns_name_t *dbus_mgr_if_reverse_ip_name
( ns_dbus_mgr_t *mgr,
struct in_addr ip_address,
struct in_addr subnet_mask
)
{
dns_name_t *dns_name =0L;
dns_fixedname_t *fixedname=0L;
char name [ DNS_NAME_FORMATSIZE ], *p;
uint32_t ip = (ntohl(ip_address.s_addr) & ntohl(subnet_mask.s_addr)), i;
isc_buffer_t buffer;
isc_result_t result;
if( (ip == 0) || (ip == 0xffffffff) )
return 0L;
for(i = 8, p = name; (i < 32); i += 8)
if( ip & ( 0xff << i ) )
p += sprintf(p, "%u.", (((ip & ( 0xff << i )) >> i ) & 0xff) );
if( p > name )
{
p += sprintf(p, "in-addr.arpa");
isc_buffer_init( &buffer, name, p - name );
isc_buffer_add(&buffer, p - name);
fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t ));
dns_fixedname_init(fixedname);
dns_name = dns_fixedname_name(fixedname);
result= dns_name_fromtext
( dns_name, &buffer, dns_rootname, ISC_FALSE, NULL
);
ISC_LINK_INIT(dns_name, link);
if( result == ISC_R_SUCCESS )
return dns_name;
}
return 0L;
}
static void
dbus_mgr_free_dhc( void *p )
{
DHC_IF *d_if = p;
dns_name_t *dn;
isc_sockaddr_t *sa;
isc_mem_put( ns_g_mctx, d_if->if_name, strlen(d_if->if_name) + 1);
for( sa = ISC_LIST_HEAD( d_if->dns );
sa != NULL;
sa = ISC_LIST_HEAD( d_if->dns )
)
{
if( ISC_LINK_LINKED( sa, link ) )
ISC_LIST_UNLINK( d_if->dns, sa, link );
isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t));
}
for( dn = ISC_LIST_HEAD( d_if->dn );
dn != NULL;
dn = ISC_LIST_HEAD( d_if->dn )
)
{
if( ISC_LINK_LINKED( dn, link ) )
ISC_LIST_UNLINK( d_if->dn, dn, link );
isc_mem_put( ns_g_mctx, dn, sizeof( dns_fixedname_t ) );
}
isc_mem_put( ns_g_mctx, d_if, sizeof(DHC_IF));
}
static void
dbus_mgr_handle_dhcdbd_message
(
ns_dbus_mgr_t *mgr,
const char *path,
const char *member,
dbus_svc_MessageHandle msg
)
{
DBUS_SVC dbus = mgr->dbus;
DHC_IF *d_if, *const*d_ifpp, dif;
DHC_State dhc_state;
char *if_name, *opt_name, error_name[1024]="", error_message[1024]="";
uint8_t *value=0L;
uint32_t length;
isc_result_t result;
isc_sockaddr_t *sa = 0L;
dns_name_t *dn = 0L;
struct in_addr *ip;
in_port_t port;
char dnBuf[ DNS_NAME_FORMATSIZE ];
isc_buffer_t buffer;
DBusMgrInitialFwdr *ifwdr, *const*ifwdpp, ifwd;
ISC_LIST(DBusMgrInitialFwdr) ifwdrList;
DNSNameList nameList;
dbus_mgr_log_dbg("Got dhcdbd message: %s %s %p", path, member, msg );
if( ( if_name = strrchr(path,'/') ) == 0L )
{
dbus_mgr_log_err("bad path in dhcdbd message:", path);
return;
}
++if_name;
dif.if_name = if_name;
if( ((d_ifpp=tfind( &dif, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator)) == 0L)
||((d_if = *d_ifpp) == 0L)
)
{
d_if = isc_mem_get( mgr->mctx, sizeof(DHC_IF));
if( d_if == 0L )
{
dbus_mgr_log_err("out of memory");
return;
}
memset(d_if, '\0', sizeof(DHC_IF));
if((d_if->if_name = isc_mem_get( mgr->mctx, strlen(if_name) + 1)) == 0L)
{
dbus_mgr_log_err("out of memory");
return;
}
strcpy(d_if->if_name, if_name);
d_if->dhc_state = DHC_INVALID;
d_if->previous_state = DHC_INVALID;
ISC_LIST_INIT( d_if->dn );
ISC_LIST_INIT( d_if->dns );
if( tsearch( d_if, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator) == 0L )
{
dbus_mgr_log_err("out of memory");
return;
}
}
if( strcmp(member, "reason") == 0 )
{
if( (!dbus_svc_get_args( dbus, msg,
TYPE_STRING, &opt_name,
TYPE_ARRAY, TYPE_BYTE, &value, &length,
TYPE_INVALID
)
)
||( value == 0L)
||( length != sizeof(uint32_t))
||( *((uint32_t*)value) > DHC_END_OPTIONS)
)
{
dbus_mgr_log_err("Invalid DHC reason value received from dhcdbd");
return;
}
dhc_state = (DHC_State) *((uint32_t*)value);
dbus_mgr_log_dbg("reason: %d %d %d", dhc_state, d_if->dhc_state, d_if->previous_state);
switch( dhc_state )
{
case DHC_END_OPTIONS:
switch( d_if->dhc_state )
{
case DHC_END_OPTIONS:
break;
case DHC_RENEW:
case DHC_REBIND:
if( ( d_if->previous_state != DHC_INVALID )
&&( d_if->previous_state != DHC_RELEASE )
) break;
dbus_mgr_log_err("D-BUS: existing dhclient for interface %s RENEWed lease", if_name);
case DHC_REBOOT:
case DHC_BOUND:
d_if->previous_state = d_if->dhc_state;
d_if->dhc_state = DHC_BOUND;
if( (dn = dbus_mgr_if_reverse_ip_name(mgr, d_if->ip, d_if->subnet_mask )) != 0L )
{
ISC_LIST_APPEND(d_if->dn, dn, link );
}
if( ( ISC_LIST_HEAD( d_if->dn ) != NULL )
&&( ISC_LIST_HEAD( d_if->dns ) != NULL )
)
{
dbus_mgr_log_err("D-BUS: dhclient for interface %s acquired new lease - creating forwarders.",
if_name
);
result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_only );
if( result != ISC_R_SUCCESS )
{
dbus_mgr_log_err("D-BUS: forwarder configuration failed: %s", isc_result_totext(result));
}
}
break;
case DHC_STOP:
case DHC_TIMEOUT:
case DHC_FAIL:
case DHC_EXPIRE:
case DHC_RELEASE:
d_if->previous_state = d_if->dhc_state;
d_if->dhc_state = DHC_RELEASE;
if( ISC_LIST_HEAD( d_if->dn ) != NULL )
{
dbus_mgr_log_err("D-BUS: dhclient for interface %s released lease - removing forwarders.",
if_name);
for( sa = ISC_LIST_HEAD( d_if->dns );
sa != 0L;
sa = ISC_LIST_HEAD( d_if->dns )
)
{
if( ISC_LINK_LINKED( sa, link ) )
ISC_LIST_UNLINK( d_if->dns, sa, link );
isc_mem_put( mgr->mctx, sa, sizeof(isc_sockaddr_t));
}
ISC_LIST_INIT( d_if->dns );
ISC_LIST_INIT( ifwdrList );
for( dn = ISC_LIST_HEAD( d_if->dn );
dn != 0L;
dn = ISC_LIST_NEXT( dn, link )
)
{
dns_name_init( &(ifwd.dn), NULL );
isc_buffer_init( &buffer, dnBuf, DNS_NAME_FORMATSIZE);
dns_name_setbuffer( &(ifwd.dn), &buffer);
dns_name_copy(dn, &(ifwd.dn), NULL);
if( ((ifwdpp = tfind(&ifwd, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator)) != 0L )
&&((ifwdr = *ifwdpp) != 0L)
)
{
ISC_LIST_APPEND( ifwdrList, ifwdr, link );
}
}
result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_none );
if( result != ISC_R_SUCCESS )
{
dbus_mgr_log_err("D-BUS: removal of forwarders failed: %s", isc_result_totext(result));
}
for( dn = ISC_LIST_HEAD( d_if->dn );
dn != 0L;
dn = ISC_LIST_HEAD( d_if->dn )
)
{
if( ISC_LINK_LINKED( dn, link ) )
ISC_LIST_UNLINK( d_if->dn, dn, link );
isc_mem_put( mgr->mctx, dn, sizeof( dns_fixedname_t ) );
}
ISC_LIST_INIT( d_if->dn );
for( ifwdr = ISC_LIST_HEAD( ifwdrList );
ifwdr != 0L;
ifwdr = ISC_LIST_HEAD( ifwdrList )
)
{
if( ISC_LINK_LINKED( ifwdr, link ) )
ISC_LIST_UNLINK( ifwdrList, ifwdr, link );
ISC_LINK_INIT(ifwdr, link);
ISC_LIST_INIT(nameList);
ISC_LINK_INIT(&(ifwdr->dn), link);
ISC_LIST_APPEND( nameList, &(ifwdr->dn), link );
result = dbus_mgr_set_forwarders( mgr, &nameList,
&(ifwdr->sa),
ifwdr->fwdpolicy
);
if( result != ISC_R_SUCCESS )
{
dbus_mgr_log_err("D-BUS: restore of forwarders failed: %s", isc_result_totext(result));
}
}
}
case DHC_ABEND:
case DHC_END:
case DHC_NBI:
case DHC_PREINIT:
case DHC_MEDIUM:
case DHC_START:
case DHC_INVALID:
default:
break;
}
break;
case DHC_BOUND:
case DHC_REBOOT:
case DHC_REBIND:
case DHC_RENEW:
case DHC_STOP:
case DHC_TIMEOUT:
case DHC_FAIL:
case DHC_EXPIRE:
case DHC_RELEASE:
d_if->previous_state = d_if->dhc_state;
d_if->dhc_state = dhc_state;
case DHC_ABEND:
case DHC_END:
case DHC_NBI:
case DHC_PREINIT:
case DHC_MEDIUM:
case DHC_START:
case DHC_INVALID:
default:
break;
}
}else
if( strcmp( member, "domain_name" ) == 0 )
{
if( (!dbus_svc_get_args( dbus, msg,
TYPE_STRING, &opt_name,
TYPE_ARRAY, TYPE_BYTE, &value, &length,
TYPE_INVALID
)
)
||( value == 0L)
||( length == 0)
)
{
dbus_mgr_log_err("Invalid domain_name value received from dhcdbd");
return;
}
dbus_mgr_log_dbg("domain-name %s", (char*)value);
dbus_mgr_get_name_list( mgr, (char*)value, &(d_if->dn), error_name, error_message );
if( ( error_message[0] != '\0' ) || (ISC_LIST_HEAD(d_if->dn) == 0L ))
{
dbus_mgr_log_err("Bad domain_name value: %s", error_message );
}
}else
if( strcmp( member, "domain_name_servers") == 0 )
{
if( (!dbus_svc_get_args( dbus, msg,
TYPE_STRING, &opt_name,
TYPE_ARRAY, TYPE_BYTE, &value, &length,
TYPE_INVALID
)
)
||( value == 0L)
||( length == 0)
)
{
dbus_mgr_log_err("Invalid domain_name_servers value received from dhcdbd");
return;
}
for(ip = (struct in_addr*) value; ip < ((struct in_addr*)(value + length)); ip++)
{
dbus_mgr_log_dbg("domain-name-servers: %s", inet_ntop(AF_INET, value, error_name, 16));
sa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
memset(sa, '\0', sizeof(isc_sockaddr_t));
sa->type.sin.sin_addr = *ip;
sa->type.sa.sa_family = AF_INET;
sa->length = sizeof(sa->type.sin);
result = ns_config_getport(ns_g_config, &(port) );
if( result != ISC_R_SUCCESS )
port = 53;
sa->type.sin.sin_port = htons( port );
ISC_LIST_APPEND(d_if->dns, sa, link);
}
}else
if( strcmp(member, "ip_address") == 0)
{
if( (!dbus_svc_get_args( dbus, msg,
TYPE_STRING, &opt_name,
TYPE_ARRAY, TYPE_BYTE, &value, &length,
TYPE_INVALID
)
)
||( value == 0L)
||( length != sizeof(struct in_addr) )
)
{
dbus_mgr_log_err("Invalid ip_address value received from dhcdbd");
return;
}
dbus_mgr_log_dbg("ip-address: %s", inet_ntop(AF_INET, value, error_name, 16));
d_if->ip = *((struct in_addr*)value);
}else
if( strcmp(member, "subnet_mask") == 0 )
{
if( (!dbus_svc_get_args( dbus, msg,
TYPE_STRING, &opt_name,
TYPE_ARRAY, TYPE_BYTE, &value, &length,
TYPE_INVALID
)
)
||( value == 0L)
||( length != sizeof(struct in_addr) )
)
{
dbus_mgr_log_err("Invalid subnet_mask value received from dhcdbd");
return;
}
dbus_mgr_log_dbg("subnet-mask: %s", inet_ntop(AF_INET, value, error_name, 16));
d_if->subnet_mask = *((struct in_addr*)value);
}
}
static
dbus_svc_HandlerResult
dbus_mgr_message_handler
(
DBusMsgHandlerArgs
)
{
char error_name[1024], error_message[1024];
ns_dbus_mgr_t *mgr = object;
uint32_t new_serial;
if_suffix = prefix = suffix = prefixObject = 0L;
dbus_mgr_log_dbg("D-BUS message: %u %u %u %s %s %s %s %s %s",
type, reply_expected, serial, destination, path, member, interface, sender, signature
);
if ( ( type == SIGNAL )
&&( strcmp(path,"/org/freedesktop/DBus/Local") == 0 )
)
{
if( strcmp(member,"Disconnected") == 0 )
dbus_mgr_dbus_shutdown_handler( mgr );
}else
if( ( type == SIGNAL )
&&( strcmp(path,"/org/freedesktop/DBus") == 0 )
&&(strcmp(member,"NameOwnerChanged") == 0)
&&(strcmp(signature, "sss") == 0)
)
{
dbus_mgr_check_dhcdbd_state( mgr, msg );
}else
if( ( type == SIGNAL )
&&( (sender != 0L) && (mgr->dhcdbd_name != 0L) && (strcmp(sender,mgr->dhcdbd_name) == 0))
&&( strcmp(interface,"com.redhat.dhcp.subscribe.binary") == 0 )
)
{
dbus_mgr_handle_dhcdbd_message( mgr, path, member, msg );
}else
if( (type == CALL)
&&( strcmp(destination, DBUSMGR_DESTINATION)==0)
&&( strcmp(path, DBUSMGR_OBJECT_PATH)==0)
)
{
if( strcmp(member, "SetForwarders") == 0 )
dbus_mgr_handle_set_forwarders
( mgr, dbus, reply_expected, serial, path, member, interface, sender, msg );
else
if( strcmp(member, "GetForwarders") == 0 )
{
if( *signature != '\0' )
dbus_mgr_handle_get_forwarders
( dbus, reply_expected, serial, path, member, interface, sender, msg );
else
dbus_mgr_handle_list_forwarders
( dbus, reply_expected, serial, path, member, interface, sender, msg );
}else
if( reply_expected )
{
sprintf(error_name, "InvalidOperation");
sprintf(error_message, "Unrecognized path / interface / member");
dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
);
}
}
return HANDLED;
}
static void
dbus_mgr_read_watch_activated(isc_task_t *t, isc_event_t *ev)
{
DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg);
t = t;
isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size);
dbus_mgr_log_dbg("watch %d READ",sfd->fd);
isc_socket_fd_handle_reads( sfd->sock, sfd->ser );
dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_READ );
}
static void
dbus_mgr_write_watch_activated(isc_task_t *t, isc_event_t *ev)
{
DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg);
t = t;
isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size);
dbus_mgr_log_dbg("watch %d WRITE",sfd->fd);
isc_socket_fd_handle_writes( sfd->sock, sfd->ser );
dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_WRITE );
}
static void
dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev)
{
ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg);
t = t;
isc_mem_put(mgr->mctx, ev, ev->ev_size);
if( ( mgr->dbus == 0L ) || (mgr->sockets == 0L))
{
return;
}
dbus_mgr_log_dbg("watches selected");
dbus_svc_dispatch( mgr->dbus );
dbus_mgr_log_dbg("dispatch complete");
}
static int dbus_mgr_socket_comparator( const void *p1, const void *p2 )
{
return( ( ((const DBusMgrSocket*)p1)->fd
== ((const DBusMgrSocket*)p2)->fd
) ? 0
: ( ((const DBusMgrSocket*)p1)->fd
> ((const DBusMgrSocket*)p2)->fd
) ? 1
: -1
);
}
static void
dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp )
{
ns_dbus_mgr_t *mgr = mgrp;
DBusMgrSocket sockFd, *sfd=0L, *const*spp=0L;
isc_result_t result=ISC_R_SUCCESS;
isc_socketevent_t *sev;
isc_event_t *pev[1];
if(mgr == 0L)
return;
if( (flags & 7) == WATCH_ERROR )
return;
sockFd.fd = fd;
dbus_mgr_log_dbg("watch handler: fd %d %d", fd, flags);
if( ((spp = tfind( &sockFd, &(mgr->sockets), dbus_mgr_socket_comparator) ) == 0L )
||((sfd = *spp) == 0L )
)
{
if( ( flags & WATCH_ENABLE ) == 0 )
return;
sfd = isc_mem_get(mgr->mctx, sizeof(DBusMgrSocket));
if( sfd == 0L )
{
dbus_mgr_log_err("dbus_mgr: out of memory" );
return;
}
sfd->fd = fd;
sfd->mgr = mgr;
sfd->ser = sfd->sew = sfd->sel = 0L;
if( tsearch(sfd, &(mgr->sockets), dbus_mgr_socket_comparator) == 0L )
{
dbus_mgr_log_err("dbus_mgr: out of memory" );
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
return;
}
sfd->sock = 0L;
result = isc_socket_create( mgr->socketmgr, fd, isc_sockettype_fd, &(sfd->sock) );
if( result != ISC_R_SUCCESS )
{
dbus_mgr_log_err("dbus_mgr: isc_socket_create failed: %s",
isc_result_totext(result)
);
tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
return;
}
}
if( (flags & WATCH_ENABLE) == WATCH_ENABLE )
{
if( (flags & WATCH_READ) == WATCH_READ )
{
if( sfd->ser == 0L )
{
sfd->ser = (isc_socketevent_t *)
isc_event_allocate
(
mgr->mctx, mgr->task,
ISC_SOCKEVENT_READ_READY,
dbus_mgr_read_watch_activated,
sfd,
sizeof(isc_socketevent_t)
);
if( sfd->ser == 0L )
{
dbus_mgr_log_err("dbus_mgr: out of memory" );
tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
return;
}
sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser );
}else
{
sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser );
}
}
if( (flags & WATCH_WRITE) == WATCH_WRITE )
{
if( sfd->sew == 0L )
{
sfd->sew = (isc_socketevent_t *)
isc_event_allocate
(
mgr->mctx, mgr->task,
ISC_SOCKEVENT_WRITE_READY,
dbus_mgr_write_watch_activated,
sfd,
sizeof(isc_socketevent_t)
);
if( sfd->sew == 0L )
{
dbus_mgr_log_err("dbus_mgr: out of memory" );
tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
return;
}
sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew );
}else
{
sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew );
}
}
if( (sfd->ser != 0L) || (sfd->sew != 0L) )
{
if( sfd->sel == 0L )
{
sfd->sel = (isc_socketevent_t *)
isc_event_allocate
(
mgr->mctx, mgr->task,
ISC_SOCKEVENT_SELECTED,
dbus_mgr_watches_selected,
mgr,
sizeof(isc_socketevent_t)
);
if( sfd->sel == 0L )
{
dbus_mgr_log_err("dbus_mgr: out of memory" );
tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
return;
}
sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel );
}else
{
sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel);
}
}
}else
{
dbus_mgr_log_dbg("watch %d disabled",fd);
if(flags & WATCH_READ)
{
sev = isc_socket_fd_handle_reads( sfd->sock, 0L );
if( sev != 0L )
{
pev[0]=(isc_event_t*)sev;
isc_event_free(pev);
}
sfd->ser = 0L;
}
if( flags & WATCH_WRITE )
{
sev = isc_socket_fd_handle_writes( sfd->sock, 0L );
if( sev != 0L )
{
pev[0]=(isc_event_t*)sev;
isc_event_free(pev);
}
sfd->sew = 0L;
}
if( (sfd->ser == 0L) && (sfd->sew == 0L) )
{
sev = isc_socket_fd_handle_selected( sfd->sock, 0L );
if( sev != 0L )
{
pev[0]=(isc_event_t*)sev;
isc_event_free(pev);
}
sfd->sel = 0L;
tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
}
}
}
static
void dbus_mgr_close_socket( const void *p, const VISIT which, const int level)
{
DBusMgrSocket *const*spp=p, *sfd;
isc_event_t *ev ;
int i = level ? 0 :1;
i &= i;
if( (spp==0L) || ((sfd = *spp)==0L)
||((which != leaf) && (which != postorder))
) return;
if( sfd->ser != 0L )
{
ev = (isc_event_t *)isc_socket_fd_handle_reads(sfd->sock, 0);
if( ev != 0L )
isc_event_free((isc_event_t **)&ev);
sfd->ser = 0L;
}
if( sfd->sew != 0L )
{
ev = (isc_event_t *)isc_socket_fd_handle_writes(sfd->sock, 0);
if( ev != 0L )
isc_event_free((isc_event_t **)&ev);
sfd->sew = 0L;
}
if( sfd->sel != 0L )
{
ev = (isc_event_t *)isc_socket_fd_handle_selected(sfd->sock, 0);
if( ev != 0L )
isc_event_free((isc_event_t **)&ev);
sfd->sel = 0L;
dbus_mgr_log_dbg("CLOSED socket %d", sfd->fd);
}
}
static
void dbus_mgr_destroy_socket( void *p )
{
DBusMgrSocket *sfd = p;
isc_mem_put( sfd->mgr->mctx, sfd, sizeof(DBusMgrSocket) );
}