dbus_mgr.c

来自「非常好的dns解析软件」· C语言 代码 · 共 2,442 行 · 第 1/5 页

C
2,442
字号
/* dbus_mgr.c * *  named module to provide dynamic forwarding zones in  *  response to D-BUS dhcp events or commands. * *  Copyright(C) Jason Vas Dias, Red Hat Inc., 2005 * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation at  *           http://www.fsf.org/licensing/licenses/gpl.txt *  and included in this software distribution as the "LICENSE" file. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. */#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;		/* Memory context. */    isc_taskmgr_t     * taskmgr;	/* Task manager.   */    isc_socketmgr_t   *	socketmgr;	/* Socket manager. */       isc_timermgr_t    *	timermgr;	/* Timer manager.  */       isc_task_t        * task;           /* task            */    isc_timer_t       * timer;          /* dbus_init retry */    void              * sockets;        /* dbus fd tree    */     void              * dhc_if;         /* dhcp interface tree */    void              * ifwdt;          /* initial forwarder tree */    char              * dhcdbd_name;    /* dhcdbd destination  */    DBUS_SVC            dbus;	        /* dbus handle */};typedefstruct 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;typedefenum dhc_state_e{   DHC_NBI,         	/* no broadcast interfaces found */   DHC_PREINIT, 	/* configuration started   */   DHC_BOUND, 		/* lease obtained          */   DHC_RENEW, 		/* lease renewed           */   DHC_REBOOT,	        /* have valid lease, but now obtained a different one */   DHC_REBIND, 		/* new, different lease */   DHC_STOP,  		/* remove old lease */   DHC_MEDIUM, 		/* media selection begun */   DHC_TIMEOUT, 	/* timed out contacting DHCP server */   DHC_FAIL, 		/* all attempts to contact server timed out, sleeping */   DHC_EXPIRE, 		/* lease has expired, renewing */   DHC_RELEASE, 	/* releasing lease */   DHC_START,           /* sent when dhclient started OK */   DHC_ABEND,  		/* dhclient exited abnormally    */   DHC_END, 		/* dhclient exited normally      */   DHC_END_OPTIONS,     /* last option in subscription sent */   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;typedefstruct 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 );staticdbus_svc_HandlerResult dbus_mgr_message_handler(      DBusMsgHandlerArgs);staticvoid dbus_mgr_close_socket( const void *p, const VISIT which, const int level);staticvoid dbus_mgr_destroy_socket( void *p );staticvoid dbus_mgr_free_dhc( void *p );static voiddbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev);static isc_result_tdbus_mgr_init_dbus(ns_dbus_mgr_t *);static isc_result_tdbus_mgr_record_initial_fwdtable(ns_dbus_mgr_t *);static voiddbus_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 * );staticint 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;}staticint 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;}staticint 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_tdbus_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 );}staticvoid 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);        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?