1/* dbus_mgr.c 2 * 3 * named module to provide dynamic forwarding zones in 4 * response to D-BUS dhcp events or commands. 5 * 6 * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005 7 * Modified by Adam Tkac, Red Hat Inc., 2007 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation at 12 * http://www.fsf.org/licensing/licenses/gpl.txt 13 * and included in this software distribution as the "LICENSE" file. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20#include <config.h> 21#include <isc/types.h> 22#include <isc/net.h> 23#include <isc/mem.h> 24#include <isc/magic.h> 25#include <isc/list.h> 26#include <isc/task.h> 27#include <isc/event.h> 28#include <isc/socket.h> 29#include <isc/timer.h> 30#include <isc/netaddr.h> 31#include <isc/sockaddr.h> 32#include <isc/buffer.h> 33#include <isc/log.h> 34 35#include <dns/name.h> 36#include <dns/acl.h> 37#include <dns/fixedname.h> 38#include <dns/view.h> 39#include <dns/forward.h> 40 41#include <named/types.h> 42#include <named/config.h> 43#include <named/server.h> 44#include <named/globals.h> 45#include <named/log.h> 46 47#include <named/dbus_service.h> 48#include <named/dbus_mgr.h> 49 50#include <string.h> 51#include <search.h> 52 53typedef void (*__free_fn_t) (void *__nodep); 54extern void tdestroy (void *__root, __free_fn_t __freefct); 55extern void free(void*); 56 57#ifdef ISC_USE_INTERNAL_MALLOC 58# if ISC_USE_INTERNAL_MALLOC 59# error dbus_mgr cannot be used if ISC_USE_INTERNAL_MALLOC==1 60# endif 61#endif 62 63#define DBUSMGR_DESTINATION "com.redhat.named" 64#define DBUSMGR_OBJECT_PATH "/com/redhat/named" 65#define DBUSMGR_INTERFACE "com.redhat.named" 66 67#define DBUSMGR_MAGIC ISC_MAGIC('D', 'B', 'U', 'S') 68 69struct ns_dbus_mgr 70{ 71 unsigned int magic; 72 isc_mem_t * mctx; /* Memory context. */ 73 isc_taskmgr_t * taskmgr; /* Task manager. */ 74 isc_socketmgr_t * socketmgr; /* Socket manager. */ 75 isc_timermgr_t * timermgr; /* Timer manager. */ 76 isc_task_t * task; /* task */ 77 isc_timer_t * timer; /* dbus_init retry */ 78 void * sockets; /* dbus fd tree */ 79 void * dhc_if; /* dhcp interface tree */ 80 void * ifwdt; /* initial forwarder tree */ 81 char * dhcdbd_name; /* dhcdbd destination */ 82 DBUS_SVC dbus; /* dbus handle */ 83}; 84 85typedef 86struct dbus_mgr_sock_s 87{ 88 int fd; 89 struct ns_dbus_mgr *mgr; 90 isc_socket_t *sock; 91 isc_socketevent_t *ser; 92 isc_socketevent_t *sew; 93 isc_socketevent_t *sel; 94} DBusMgrSocket; 95 96typedef 97enum dhc_state_e 98{ 99 DHC_NBI, /* no broadcast interfaces found */ 100 DHC_PREINIT, /* configuration started */ 101 DHC_BOUND, /* lease obtained */ 102 DHC_RENEW, /* lease renewed */ 103 DHC_REBOOT, /* have valid lease, but now obtained a different one */ 104 DHC_REBIND, /* new, different lease */ 105 DHC_STOP, /* remove old lease */ 106 DHC_MEDIUM, /* media selection begun */ 107 DHC_TIMEOUT, /* timed out contacting DHCP server */ 108 DHC_FAIL, /* all attempts to contact server timed out, sleeping */ 109 DHC_EXPIRE, /* lease has expired, renewing */ 110 DHC_RELEASE, /* releasing lease */ 111 DHC_START, /* sent when dhclient started OK */ 112 DHC_ABEND, /* dhclient exited abnormally */ 113 DHC_END, /* dhclient exited normally */ 114 DHC_END_OPTIONS, /* last option in subscription sent */ 115 DHC_INVALID=255 116} DHC_State; 117 118typedef ISC_LIST(dns_name_t) DNSNameList; 119 120typedef ISC_LIST(isc_sockaddr_t) SockAddrList; 121 122typedef struct dbm_fwdr_s 123{ 124 dns_fwdpolicy_t fwdpolicy; 125 dns_name_t dn; 126 SockAddrList sa; 127 ISC_LINK( struct dbm_fwdr_s ) link; 128} DBusMgrInitialFwdr; 129 130typedef 131struct dhc_if_s 132{ 133 char *if_name; 134 DHC_State dhc_state; 135 DHC_State previous_state; 136 struct in_addr ip; 137 struct in_addr subnet_mask; 138 DNSNameList dn; 139 SockAddrList dns; 140} DHC_IF; 141 142static void 143dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp ); 144 145static 146dbus_svc_HandlerResult 147dbus_mgr_message_handler 148( 149 DBusMsgHandlerArgs 150); 151 152static 153void dbus_mgr_close_socket( const void *p, const VISIT which, const int level); 154 155static 156void dbus_mgr_destroy_socket( void *p ); 157 158static 159void dbus_mgr_free_dhc( void *p ); 160 161static void 162dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev); 163 164static isc_result_t 165dbus_mgr_init_dbus(ns_dbus_mgr_t *); 166 167static isc_result_t 168dbus_mgr_record_initial_fwdtable(ns_dbus_mgr_t *); 169 170static 171dns_fwdtable_t *dbus_mgr_get_fwdtable(void); 172 173static void 174dbus_mgr_free_initial_fwdtable(ns_dbus_mgr_t *); 175 176static 177uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t * ); 178 179static 180void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t * ); 181 182static 183int dbus_mgr_log_err( const char *fmt, ...) 184{ 185 va_list va; 186 va_start(va, fmt); 187 isc_log_vwrite(ns_g_lctx, 188 NS_LOGCATEGORY_DBUS, 189 NS_LOGMODULE_DBUS, 190 ISC_LOG_NOTICE, 191 fmt, va 192 ); 193 va_end(va); 194 return 0; 195} 196 197static 198int dbus_mgr_log_dbg( const char *fmt, ...) 199{ 200 va_list va; 201 va_start(va, fmt); 202 isc_log_vwrite(ns_g_lctx, 203 NS_LOGCATEGORY_DBUS, 204 NS_LOGMODULE_DBUS, 205 ISC_LOG_DEBUG(80), 206 fmt, va 207 ); 208 va_end(va); 209 return 0; 210} 211 212static 213int dbus_mgr_log_info( const char *fmt, ...) 214{ 215 va_list va; 216 va_start(va, fmt); 217 isc_log_vwrite(ns_g_lctx, 218 NS_LOGCATEGORY_DBUS, 219 NS_LOGMODULE_DBUS, 220 ISC_LOG_DEBUG(1), 221 fmt, va 222 ); 223 va_end(va); 224 return 0; 225} 226 227isc_result_t 228dbus_mgr_create 229( isc_mem_t *mctx, 230 isc_taskmgr_t *taskmgr, 231 isc_socketmgr_t *socketmgr, 232 isc_timermgr_t *timermgr, 233 ns_dbus_mgr_t **dbus_mgr 234) 235{ 236 isc_result_t result; 237 ns_dbus_mgr_t *mgr; 238 239 *dbus_mgr = 0L; 240 241 mgr = isc_mem_get(mctx, sizeof(*mgr)); 242 if (mgr == NULL) 243 return (ISC_R_NOMEMORY); 244 245 mgr->magic = DBUSMGR_MAGIC; 246 mgr->mctx = mctx; 247 mgr->taskmgr = taskmgr; 248 mgr->socketmgr = socketmgr; 249 mgr->timermgr = timermgr; 250 mgr->task = 0L; 251 mgr->sockets = 0L; 252 mgr->timer = 0L; 253 mgr->dhc_if = 0L; 254 mgr->ifwdt = 0L; 255 mgr->dhcdbd_name = 0L; 256 257 if( (result = isc_task_create( taskmgr, 100, &(mgr->task))) 258 != ISC_R_SUCCESS 259 ) goto cleanup_mgr; 260 261 isc_task_setname( mgr->task, "dbusmgr", mgr ); 262 263 mgr->dbus = 0L; 264 265 if( (result = dbus_mgr_record_initial_fwdtable( mgr )) 266 != ISC_R_SUCCESS 267 ) goto cleanup_mgr; 268 269 if( (result = dbus_mgr_init_dbus( mgr )) 270 != ISC_R_SUCCESS 271 ) goto cleanup_mgr; 272 273 *dbus_mgr = mgr; 274 275 return ISC_R_SUCCESS; 276 277 cleanup_mgr: 278 if ( dbus_mgr_get_fwdtable() != NULL) 279 dbus_mgr_free_initial_fwdtable (mgr); 280 if( mgr->task != 0L ) 281 isc_task_detach(&(mgr->task)); 282 isc_mem_put(mctx, mgr, sizeof(*mgr)); 283 return (result); 284} 285 286static isc_result_t 287dbus_mgr_init_dbus(ns_dbus_mgr_t * mgr) 288{ 289 char destination[]=DBUSMGR_DESTINATION; 290 isc_result_t result; 291 292 if( mgr->sockets != 0L ) 293 { 294 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 295 twalk(mgr->sockets, dbus_mgr_close_socket); 296 tdestroy(mgr->sockets, dbus_mgr_destroy_socket); 297 mgr->sockets = 0L; 298 } 299 300 if( mgr->dbus != 0L ) 301 { 302 dbus_svc_shutdown(mgr->dbus); 303 mgr->dbus = 0L; 304 } 305 306 result = dbus_svc_init(DBUS_PRIVATE_SYSTEM, destination, &mgr->dbus, 307 dbus_mgr_watch_handler, 0L, 0L, mgr); 308 309 if(result != ISC_R_SUCCESS) 310 goto cleanup; 311 312 if( mgr->dbus == 0L ) 313 { 314 if( mgr->timer == 0L) 315 { 316 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 317 if( mgr->sockets != 0L ) 318 { 319 twalk(mgr->sockets, dbus_mgr_close_socket); 320 tdestroy(mgr->sockets, dbus_mgr_destroy_socket); 321 mgr->sockets = 0L; 322 } 323 dbus_mgr_dbus_shutdown_handler ( mgr ); 324 return ISC_R_SUCCESS; 325 } 326 goto cleanup; 327 } 328 329 if( !dbus_svc_add_filter 330 ( mgr->dbus, dbus_mgr_message_handler, mgr, 4, 331 "type=signal,path=/org/freedesktop/DBus,member=NameOwnerChanged", 332 "type=signal,path=/org/freedesktop/DBus/Local,member=Disconnected", 333 "type=signal,interface=com.redhat.dhcp.subscribe.binary", 334 "type=method_call,destination=com.redhat.named,path=/com/redhat/named" 335 ) 336 ) 337 { 338 dbus_mgr_log_err( "dbus_svc_add_filter failed" ); 339 goto cleanup; 340 } 341 342 if( mgr->timer != 0L ) 343 { 344 isc_timer_reset(mgr->timer, 345 isc_timertype_inactive, 346 NULL, NULL, ISC_TRUE 347 ); 348 } 349 350 if( !dbus_mgr_subscribe_to_dhcdbd( mgr ) ) 351 dbus_mgr_log_err("D-BUS dhcdbd subscription disabled."); 352 353 dbus_mgr_log_err("D-BUS service enabled."); 354 return ISC_R_SUCCESS; 355 356 cleanup: 357 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 358 twalk(mgr->sockets, dbus_mgr_close_socket); 359 tdestroy(mgr->sockets, dbus_mgr_destroy_socket); 360 mgr->sockets = 0L; 361 if( mgr->dbus ) 362 { 363 dbus_svc_shutdown(mgr->dbus); 364 mgr->dbus = 0L; 365 } 366 return ISC_R_FAILURE; 367} 368 369static 370uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t *mgr ) 371{ 372 DBUS_SVC dbus = mgr->dbus; 373 char subs[1024], path[1024], 374 dhcdbd_destination[]="com.redhat.dhcp", *ddp[1]={ &(dhcdbd_destination[0]) }, 375 *dhcdbd_name=0L; 376 const char *options[] = { "reason", "ip-address", "subnet-mask", 377 "domain-name", "domain-name-servers" 378 }; 379 dbus_svc_MessageHandle msg; 380 int i, n_opts = 5; 381 382 if( mgr->dhcdbd_name == 0L ) 383 { 384 msg = dbus_svc_call 385 ( dbus, 386 "org.freedesktop.DBus", 387 "/org/freedesktop/DBus", 388 "GetNameOwner", 389 "org.freedesktop.DBus", 390 TYPE_STRING, &ddp, 391 TYPE_INVALID 392 ); 393 if( msg == 0L ) 394 return 0; 395 396 if( !dbus_svc_get_args(dbus, msg, 397 TYPE_STRING, &(dhcdbd_name), 398 TYPE_INVALID 399 ) 400 ) return 0; 401 402 mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(dhcdbd_name) + 1); 403 if( mgr->dhcdbd_name == 0L ) 404 return 0; 405 406 strcpy(mgr->dhcdbd_name, dhcdbd_name); 407 408 } 409 410 sprintf(path,"/com/redhat/dhcp/subscribe"); 411 sprintf(subs,"com.redhat.dhcp.binary"); 412 413 for(i = 0; i < n_opts; i++) 414 { 415 msg = dbus_svc_call 416 ( dbus, 417 "com.redhat.dhcp", 418 path, 419 "binary", 420 subs, 421 TYPE_STRING, &(options[i]), 422 TYPE_INVALID 423 ); 424 if(msg == 0L) 425 return 0; 426 if ( dbus_svc_message_type( msg ) == ERROR ) 427 return 0; 428 } 429 dbus_mgr_log_err("D-BUS dhcdbd subscription enabled."); 430 return 1; 431} 432 433void 434dbus_mgr_shutdown 435( ns_dbus_mgr_t *mgr 436) 437{ 438 if( mgr->timer != 0L ) 439 isc_timer_detach(&(mgr->timer)); 440 if( mgr->dbus != 0L ) 441 { 442 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 443 if( mgr->sockets != 0L ) 444 { 445 twalk(mgr->sockets, dbus_mgr_close_socket); 446 tdestroy(mgr->sockets, dbus_mgr_destroy_socket); 447 mgr->sockets = 0L; 448 } 449 dbus_svc_shutdown(mgr->dbus); 450 } 451 if( mgr->dhc_if != 0L ) 452 tdestroy(mgr->dhc_if, dbus_mgr_free_dhc); 453 if( mgr->dhcdbd_name != 0L ) 454 isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1); 455 isc_task_detach(&(mgr->task)); 456 dbus_mgr_free_initial_fwdtable(mgr); 457 isc_mem_put(mgr->mctx, mgr, sizeof(ns_dbus_mgr_t)); 458} 459 460static 461void dbus_mgr_restart_dbus(isc_task_t *t, isc_event_t *ev) 462{ 463 ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg) ; 464 t=t; 465 isc_event_free(&ev); 466 dbus_mgr_log_dbg("attempting to connect to D-BUS"); 467 dbus_mgr_init_dbus( mgr ); 468} 469 470static 471void dbus_mgr_handle_dbus_shutdown_event(isc_task_t *t, isc_event_t *ev) 472{ 473 ns_dbus_mgr_t *mgr = ev->ev_arg; 474 isc_time_t tick={10,0}; 475 isc_interval_t tock={10,0}; 476 DBUS_SVC dbus = mgr->dbus; 477 t = t; 478 479 mgr->dbus = 0L; 480 481 isc_event_free(&ev); 482 483 if ( dbus != 0L ) 484 { 485 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 486 if( mgr->sockets != 0L ) 487 { 488 twalk(mgr->sockets, dbus_mgr_close_socket); 489 tdestroy(mgr->sockets, dbus_mgr_destroy_socket); 490 mgr->sockets = 0L; 491 } 492 dbus_svc_shutdown(dbus); 493 } 494 495 dbus_mgr_log_err( "D-BUS service disabled." ); 496 497 if( mgr->timer != 0L ) 498 { 499 isc_timer_reset(mgr->timer, 500 isc_timertype_ticker, 501 &tick, &tock, ISC_TRUE 502 ); 503 }else 504 if( isc_timer_create 505 ( mgr->timermgr, 506 isc_timertype_ticker, 507 &tick, &tock, 508 mgr->task, 509 dbus_mgr_restart_dbus, 510 mgr, 511 &(mgr->timer) 512 ) != ISC_R_SUCCESS 513 ) 514 { 515 dbus_mgr_log_err( "D-BUS service cannot be restored." ); 516 } 517} 518 519static 520void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t *mgr ) 521{ 522 isc_event_t *dbus_shutdown_event = 523 isc_event_allocate 524 ( mgr->mctx, 525 mgr->task, 526 1, 527 dbus_mgr_handle_dbus_shutdown_event, 528 mgr, 529 sizeof(isc_event_t) 530 ); 531 if( dbus_shutdown_event != 0L ) 532 { 533 isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L); 534 isc_task_send( mgr->task, &dbus_shutdown_event ); 535 }else 536 dbus_mgr_log_err("unable to allocate dbus shutdown event"); 537} 538 539static 540dns_view_t *dbus_mgr_get_localhost_view(void) 541{ 542 dns_view_t *view; 543 isc_netaddr_t localhost = { AF_INET, { { htonl( ( 127 << 24 ) | 1 ) } }, 0 }; 544 int match; 545 546 for (view = ISC_LIST_HEAD(ns_g_server->viewlist); 547 view != NULL; 548 view = ISC_LIST_NEXT(view, link) 549 ) 550 { 551 /* return first view matching "localhost" source and dest */ 552 553 if(( (view->matchclients != 0L ) /* 0L: accept "any" */ 554 &&(( dns_acl_match( &localhost, 555 NULL, /* unsigned queries */ 556 view->matchclients, 557 &(ns_g_server->aclenv), 558 &match, 559 NULL /* no match list */ 560 ) != ISC_R_SUCCESS 561 ) || (match <= 0) 562 ) 563 ) 564 ||( (view->matchdestinations != 0L ) /* 0L: accept "any" */ 565 &&(( dns_acl_match( &localhost, 566 NULL, /* unsigned queries */ 567 view->matchdestinations, 568 &(ns_g_server->aclenv), 569 &match, 570 NULL /* no match list */ 571 ) != ISC_R_SUCCESS 572 ) || (match <= 0) 573 ) 574 ) 575 ) continue; 576 577 break; 578 } 579 return view; 580} 581 582static 583dns_fwdtable_t *dbus_mgr_get_fwdtable(void) 584{ 585 dns_view_t *view = dbus_mgr_get_localhost_view(); 586 if( view != 0L ) 587 return view->fwdtable; 588 return 0L; 589} 590 591static 592dns_fwdtable_t *dbus_mgr_get_view_and_fwdtable( dns_view_t **viewp ) 593{ 594 *viewp = dbus_mgr_get_localhost_view(); 595 if( *viewp != 0L ) 596 return (*viewp)->fwdtable; 597 return 0L; 598} 599 600static int dbus_mgr_ifwdr_comparator( const void *p1, const void *p2 ) 601{ 602 char n1buf[ DNS_NAME_FORMATSIZE ]="", *n1p=&(n1buf[0]), 603 n2buf[ DNS_NAME_FORMATSIZE ]="", *n2p=&(n2buf[0]); 604 dns_name_t *dn1; 605 dns_name_t *dn2; 606 DE_CONST(&(((const DBusMgrInitialFwdr*)p1)->dn), dn1); 607 DE_CONST(&(((const DBusMgrInitialFwdr*)p2)->dn), dn2); 608 dns_name_format(dn1, n1p, DNS_NAME_FORMATSIZE ); 609 dns_name_format(dn2, n2p, DNS_NAME_FORMATSIZE ); 610 return strcmp(n1buf, n2buf); 611} 612 613static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 ); 614 615static void dbus_mgr_record_initial_forwarder( dns_name_t *name, dns_forwarders_t *fwdr, void *mp ) 616{ 617 ns_dbus_mgr_t *mgr = mp; 618 isc_sockaddr_t *sa, *nsa; 619 DBusMgrInitialFwdr *ifwdr; 620 621 if( ISC_LIST_HEAD(fwdr->addrs) == 0L) 622 return; 623 624 if( (ifwdr = isc_mem_get(mgr->mctx, sizeof(DBusMgrInitialFwdr))) == 0L) 625 return; 626 627 ifwdr->fwdpolicy = fwdr->fwdpolicy; 628 629 dns_name_init(&(ifwdr->dn), NULL); 630 if( dns_name_dupwithoffsets(name, mgr->mctx, &(ifwdr->dn)) != ISC_R_SUCCESS ) 631 goto namedup_err; 632 633 ISC_LIST_INIT(ifwdr->sa); 634 635 for( sa = ISC_LIST_HEAD(fwdr->addrs); 636 sa != 0L; 637 sa = ISC_LIST_NEXT(sa,link) 638 ) 639 { 640 nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 641 if( nsa == 0L ) 642 goto nsa_err; 643 *nsa = *sa; 644 ISC_LINK_INIT(nsa, link); 645 ISC_LIST_APPEND(ifwdr->sa, nsa, link); 646 } 647 ISC_LINK_INIT(ifwdr, link); 648 tsearch( ifwdr, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator); 649 650 return; 651 652nsa_err: 653 while ( (sa = ISC_LIST_HEAD (ifwdr->sa)) != NULL) { 654 ISC_LIST_UNLINK (ifwdr->sa, sa, link); 655 isc_mem_put (mgr->mctx, sa, sizeof (*sa)); 656 } 657 658namedup_err: 659 isc_mem_put (mgr->mctx, ifwdr, sizeof (*ifwdr)); 660 661 return; 662} 663 664static isc_result_t 665dbus_mgr_record_initial_fwdtable( ns_dbus_mgr_t *mgr ) 666{ 667 dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable(); 668 669 if( fwdtable == 0L ) 670 return ISC_R_SUCCESS; /* no initial fwdtable */ 671 dns_fwdtable_foreach( fwdtable, dbus_mgr_record_initial_forwarder, mgr); 672 return ISC_R_SUCCESS; 673} 674 675static void 676dbus_mgr_free_initial_forwarder( void *p ) 677{ 678 DBusMgrInitialFwdr *ifwdr = p; 679 isc_sockaddr_t *sa; 680 681 dns_name_free(&(ifwdr->dn), ns_g_mctx); 682 for( sa = ISC_LIST_HEAD( ifwdr->sa ); 683 sa != 0L; 684 sa = ISC_LIST_HEAD( ifwdr->sa ) 685 ) 686 { 687 if( ISC_LINK_LINKED(sa, link) ) 688 ISC_LIST_UNLINK(ifwdr->sa, sa, link); 689 isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t)); 690 } 691 isc_mem_put(ns_g_mctx, ifwdr, sizeof(DBusMgrInitialFwdr)); 692} 693 694static void 695dbus_mgr_free_initial_fwdtable( ns_dbus_mgr_t *mgr ) 696{ 697 tdestroy(mgr->ifwdt, dbus_mgr_free_initial_forwarder); 698 mgr->ifwdt = 0L; 699} 700 701static void 702dbus_mgr_log_forwarders( const char *pfx, dns_name_t *name, SockAddrList *saList) 703{ 704 isc_sockaddr_t *sa; 705 char nameP[DNS_NAME_FORMATSIZE], addrP[128]; 706 int s=0; 707 dns_name_format(name, nameP, DNS_NAME_FORMATSIZE ); 708 for( sa = ISC_LIST_HEAD(*saList); 709 sa != 0L; 710 sa = ISC_LIST_NEXT(sa,link) 711 ) 712 { 713 isc_sockaddr_format(sa, addrP, 128); 714 dbus_mgr_log_info("%s zone %s server %d: %s", pfx, nameP, s++, addrP); 715 } 716} 717 718static 719isc_result_t dbus_mgr_set_forwarders 720( 721 ns_dbus_mgr_t *mgr, 722 DNSNameList *nameList, 723 SockAddrList *saList, 724 dns_fwdpolicy_t fwdpolicy 725) 726{ 727 isc_result_t result = ISC_R_SUCCESS; 728 dns_fwdtable_t *fwdtable; 729 dns_view_t *view=0L; 730 dns_name_t *dnsName; 731 isc_sockaddr_t *sa, *nsa; 732 dns_forwarders_t *fwdr=0L; 733 734 fwdtable = dbus_mgr_get_view_and_fwdtable(&view); 735 736 if( fwdtable == 0L ) 737 { 738 if( ISC_LIST_HEAD(*saList) == 0L ) 739 return ISC_R_SUCCESS;/* deletion not required */ 740 741 view = dbus_mgr_get_localhost_view(); 742 if( view == 0L ) 743 return ISC_R_NOPERM; /* if configuration does not allow localhost clients, 744 * then we really shouldn't be creating a forwarding table. 745 */ 746 result = isc_task_beginexclusive(mgr->task); 747 748 if( result == ISC_R_SUCCESS ) 749 { 750 result = dns_fwdtable_create( mgr->mctx, &(view->fwdtable) ); 751 752 isc_task_endexclusive(mgr->task); 753 754 if( result != ISC_R_SUCCESS ) 755 return result; 756 757 if( view->fwdtable == 0L ) 758 return ISC_R_NOMEMORY; 759 760 if( isc_log_getdebuglevel(ns_g_lctx) >= 1 ) 761 dbus_mgr_log_info("Created forwarder table."); 762 } 763 } 764 765 for( dnsName = ISC_LIST_HEAD(*nameList); 766 dnsName != NULL; 767 dnsName = ISC_LIST_NEXT(dnsName,link) 768 ) 769 { 770 fwdr = 0L; 771 if( ( dns_fwdtable_find_exact( fwdtable, dnsName, &fwdr ) != ISC_R_SUCCESS ) 772 ||( fwdr == 0L ) 773 ) 774 { 775 if( ISC_LIST_HEAD( *saList ) == 0L ) 776 continue; 777 /* no forwarders for name - add forwarders */ 778 779 result = isc_task_beginexclusive(mgr->task); 780 781 if( result == ISC_R_SUCCESS ) 782 { 783 result = dns_fwdtable_add( fwdtable, dnsName, 784 (isc_sockaddrlist_t*)saList, 785 fwdpolicy 786 ) ; 787 788 if( view != 0L ) 789 dns_view_flushcache( view ); 790 791 isc_task_endexclusive(mgr->task); 792 793 if( result != ISC_R_SUCCESS ) 794 return result; 795 796 if( isc_log_getdebuglevel(ns_g_lctx) >= 1 ) 797 dbus_mgr_log_forwarders("Created forwarder",dnsName, saList); 798 } 799 continue; 800 } 801 802 if( ISC_LIST_HEAD( *saList ) == 0L ) 803 { /* empty forwarders list - delete forwarder entry */ 804 805 if( isc_log_getdebuglevel(ns_g_lctx) >= 1 ) 806 dbus_mgr_log_forwarders("Deleting forwarder", dnsName, (SockAddrList*)&(fwdr->addrs)); 807 808 result = isc_task_beginexclusive(mgr->task); 809 if( result == ISC_R_SUCCESS ) 810 { 811 result = dns_fwdtable_delete( fwdtable, dnsName ); 812 813 if( view != 0L ) 814 dns_view_flushcache( view ); 815 816 isc_task_endexclusive(mgr->task); 817 818 if( result != ISC_R_SUCCESS ) 819 return result; 820 } 821 continue; 822 } 823 824 result = isc_task_beginexclusive(mgr->task); 825 826 if( result == ISC_R_SUCCESS ) 827 { 828 fwdr->fwdpolicy = fwdpolicy; 829 830 if( isc_log_getdebuglevel(ns_g_lctx) >= 1 ) 831 dbus_mgr_log_forwarders("Removing forwarder", dnsName, (SockAddrList*)&(fwdr->addrs)); 832 833 for( sa = ISC_LIST_HEAD(fwdr->addrs); 834 sa != 0L ; 835 sa = ISC_LIST_HEAD(fwdr->addrs) 836 ) 837 { 838 if( ISC_LINK_LINKED(sa, link) ) 839 ISC_LIST_UNLINK(fwdr->addrs, sa, link); 840 isc_mem_put(mgr->mctx, sa, sizeof(isc_sockaddr_t)); 841 } 842 843 ISC_LIST_INIT( fwdr->addrs ); 844 845 for( sa = ISC_LIST_HEAD(*saList); 846 sa != 0L; 847 sa = ISC_LIST_NEXT(sa,link) 848 ) 849 { 850 nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 851 if( nsa == 0L ) 852 { 853 result = ISC_R_NOMEMORY; 854 break; 855 } 856 *nsa = *sa; 857 ISC_LINK_INIT( nsa, link ); 858 ISC_LIST_APPEND( fwdr->addrs, nsa, link ); 859 } 860 861 if( view != 0L ) 862 dns_view_flushcache( view ); 863 864 isc_task_endexclusive(mgr->task); 865 866 if( isc_log_getdebuglevel(ns_g_lctx) >= 1 ) 867 dbus_mgr_log_forwarders("Added forwarder", dnsName, (SockAddrList*)&(fwdr->addrs)); 868 869 }else 870 return result; 871 872 } 873 return (result); 874} 875 876static void 877dbus_mgr_get_name_list 878( 879 ns_dbus_mgr_t *mgr, 880 char *domains, 881 DNSNameList *nameList, 882 char *error_name, 883 char *error_message 884) 885{ 886 char *name, *endName, *endp; 887 dns_fixedname_t *fixedname; 888 dns_name_t *dnsName; 889 isc_buffer_t buffer; 890 isc_result_t result; 891 uint32_t total_length; 892 893 total_length = strlen(domains); 894 endp = domains + total_length; 895 896 ISC_LIST_INIT( *nameList ); 897 898 for( name = domains + strspn(domains," \t\n"), 899 endName = name + strcspn(name," \t\n"); 900 (name < endp) && (endName <= endp); 901 name = endName + 1 + strspn(endName+1," \t\n"), 902 endName = name + strcspn(name," \t\n") 903 ) 904 { /* name loop */ 905 *endName = '\0'; 906 907 isc_buffer_init( &buffer, name, endName - name ); 908 isc_buffer_add(&buffer, endName - name); 909 910 fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t )); 911 912 dns_fixedname_init(fixedname); 913 914 dnsName = dns_fixedname_name(fixedname); 915 916 result= dns_name_fromtext 917 ( dnsName, &buffer, ( *(endp-1) != '.') ? dns_rootname : NULL, 0, NULL 918 ); 919 920 if( result != ISC_R_SUCCESS ) 921 { 922 sprintf(error_name, "com.redhat.named.InvalidArgument"); 923 sprintf(error_message,"Invalid DNS name initial argument: %s", name); 924 925 isc_mem_put( mgr->mctx, fixedname, sizeof( dns_fixedname_t ) ); 926 927 for( dnsName = ISC_LIST_HEAD( *nameList ); 928 (dnsName != 0L); 929 dnsName = ISC_LIST_HEAD( *nameList ) 930 ) 931 { 932 if( ISC_LINK_LINKED(dnsName,link) ) 933 ISC_LIST_DEQUEUE( *nameList, dnsName, link ); 934 isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) ); 935 } 936 ISC_LIST_INIT(*nameList); 937 return; 938 } 939 ISC_LINK_INIT(dnsName, link); 940 ISC_LIST_ENQUEUE( *nameList, dnsName, link ); 941 } 942} 943 944static isc_result_t 945dbus_mgr_get_sa_list 946( 947 ns_dbus_mgr_t *mgr, 948 dbus_svc_MessageIterator iter, 949 SockAddrList *saList , 950 uint8_t *fwdpolicy, 951 char *error_name, 952 char *error_message 953) 954{ 955 DBUS_SVC dbus = mgr->dbus; 956 isc_sockaddr_t *nsSA=0L, *nsSA_Q=0L; 957 uint32_t argType = dbus_svc_message_next_arg_type( dbus, iter ), 958 length; 959 isc_result_t result; 960 in_port_t port; 961 char *ip; 962 uint8_t *iparray=0L; 963 964 ISC_LIST_INIT(*saList); 965 966 if( argType == TYPE_INVALID ) 967 return ISC_R_SUCCESS; /* address list "removal" */ 968 969 do 970 { 971 switch( argType ) 972 { 973 case TYPE_UINT32: 974 975 nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 976 if( nsSA != 0L ) 977 { 978 memset(nsSA,'\0', sizeof(isc_sockaddr_t)); 979 nsSA_Q = nsSA; 980 dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_addr.s_addr)); 981 nsSA->type.sa.sa_family = AF_INET; 982 nsSA->length = sizeof( nsSA->type.sin ); 983 } 984 break; 985 986 case TYPE_ARRAY: 987 988 argType = dbus_svc_message_element_type( dbus, iter ); 989 if( argType == TYPE_BYTE ) 990 { 991 iparray = 0L; 992 length = 0; 993 994 dbus_svc_message_get_elements(dbus, iter, &length, &iparray); 995 996 if( iparray != 0L ) 997 { 998 if (length == sizeof( struct in_addr )) 999 { 1000 nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 1001 if( nsSA != 0L ) 1002 { 1003 memset(nsSA,'\0', sizeof(isc_sockaddr_t)); 1004 nsSA_Q = nsSA; 1005 1006 memcpy(&(nsSA->type.sin.sin_addr), iparray, sizeof( struct in_addr )); 1007 nsSA->type.sa.sa_family = AF_INET; 1008 nsSA->length = sizeof( nsSA->type.sin ); 1009 } 1010 }else 1011 if (length == sizeof( struct in6_addr )) 1012 { 1013 nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 1014 if( nsSA != 0L ) 1015 { 1016 memset(nsSA,'\0', sizeof(isc_sockaddr_t)); 1017 nsSA_Q = nsSA; 1018 1019 memcpy(&(nsSA->type.sin6.sin6_addr), iparray, sizeof( struct in6_addr )); 1020 nsSA->type.sa.sa_family = AF_INET6; 1021 nsSA->length = sizeof( nsSA->type.sin6 ); 1022 } 1023 } 1024 } 1025 } 1026 break; 1027 1028 case TYPE_STRING: 1029 1030 ip = 0L; 1031 dbus_svc_message_next_arg(dbus, iter, &(ip)); 1032 if( ip != 0L ) 1033 { 1034 length = strlen(ip); 1035 if( strspn(ip, "0123456789.") == length ) 1036 { 1037 nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 1038 if( nsSA != 0L) 1039 { 1040 memset(nsSA,'\0', sizeof(isc_sockaddr_t)); 1041 if( inet_pton( AF_INET, ip, &(nsSA->type.sin.sin_addr)) ) 1042 { 1043 nsSA->type.sa.sa_family = AF_INET; 1044 nsSA->length = sizeof(nsSA->type.sin); 1045 nsSA_Q = nsSA; 1046 } 1047 } 1048 }else 1049 if( strspn(ip, "0123456789AaBbCcDdEeFf:.") == length) 1050 { 1051 nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 1052 if( nsSA != 0L ) 1053 { 1054 memset(nsSA,'\0', sizeof(isc_sockaddr_t)); 1055 if( inet_pton( AF_INET6, ip, &(nsSA->type.sin6.sin6_addr)) ) 1056 { 1057 nsSA->type.sa.sa_family = AF_INET6; 1058 nsSA->length = sizeof(nsSA->type.sin6); 1059 nsSA_Q = nsSA; 1060 } 1061 } 1062 } 1063 } 1064 break; 1065 1066 case TYPE_UINT16: 1067 1068 if( (nsSA == 0L) || (nsSA->type.sa.sa_family == AF_UNSPEC) ) 1069 break; 1070 else 1071 if( nsSA->type.sa.sa_family == AF_INET ) 1072 dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_port)); 1073 else 1074 if( nsSA->type.sa.sa_family == AF_INET6 ) 1075 dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin6.sin6_port)); 1076 break; 1077 1078 case TYPE_BYTE: 1079 1080 dbus_svc_message_next_arg(dbus, iter, fwdpolicy); 1081 if(*fwdpolicy > dns_fwdpolicy_only) 1082 *fwdpolicy = dns_fwdpolicy_only; 1083 break; 1084 1085 default: 1086 1087 if(nsSA != 0L) 1088 nsSA->type.sa.sa_family = AF_UNSPEC; 1089 sprintf(error_message,"Unhandled argument type: %c", argType); 1090 break; 1091 } 1092 1093 if( (nsSA != 0L) 1094 &&(nsSA->type.sa.sa_family == AF_UNSPEC) 1095 ) 1096 { 1097 sprintf(error_name, "com.redhat.named.InvalidArgument"); 1098 if( error_message[0]=='\0') 1099 { 1100 if( nsSA == 0L ) 1101 sprintf(error_message,"Missing IP Address Name Server argument"); 1102 else 1103 sprintf(error_message,"Bad IP Address Name Server argument"); 1104 } 1105 if( nsSA != 0L ) 1106 isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t)); 1107 nsSA = 0L; 1108 for( nsSA = ISC_LIST_HEAD( *saList ); 1109 (nsSA != 0L); 1110 nsSA = ISC_LIST_HEAD( *saList ) 1111 ) 1112 { 1113 if(ISC_LINK_LINKED(nsSA, link)) 1114 ISC_LIST_DEQUEUE( *saList, nsSA, link ); 1115 isc_mem_put( mgr->mctx, nsSA, sizeof( isc_sockaddr_t ) ); 1116 } 1117 ISC_LIST_INIT(*saList); 1118 return ISC_R_FAILURE; 1119 } 1120 1121 if( nsSA != 0L ) 1122 { 1123 if( nsSA->type.sin.sin_port == 0 ) 1124 { 1125 if( ns_g_port != 0L ) 1126 nsSA->type.sin.sin_port = htons(ns_g_port); 1127 else 1128 { 1129 result = ns_config_getport(ns_g_config, &(port) ); 1130 if( result != ISC_R_SUCCESS ) 1131 port = 53; 1132 nsSA->type.sin.sin_port = htons( port ); 1133 } 1134 } 1135 1136 if( nsSA_Q != 0L ) 1137 { 1138 ISC_LINK_INIT(nsSA,link); 1139 ISC_LIST_ENQUEUE(*saList, nsSA, link); 1140 nsSA_Q = 0L; 1141 } 1142 } 1143 1144 argType = dbus_svc_message_next_arg_type( dbus, iter ); 1145 1146 } while ( argType != TYPE_INVALID ); 1147 1148 return ISC_R_SUCCESS; 1149} 1150 1151static void 1152dbus_mgr_handle_set_forwarders 1153( 1154 ns_dbus_mgr_t *mgr, 1155 DBUS_SVC dbus, 1156 uint8_t reply_expected, 1157 uint32_t serial, 1158 const char *path, 1159 const char *member, 1160 const char *interface, 1161 const char *sender, 1162 dbus_svc_MessageHandle msg 1163) 1164{ 1165 dbus_svc_MessageIterator iter; 1166 char error_name[1024]="", error_message[1024]="", *domains=0L; 1167 uint32_t argType, new_serial; 1168 DNSNameList nameList; 1169 dns_name_t *dnsName; 1170 SockAddrList saList; 1171 isc_sockaddr_t *nsSA; 1172 isc_result_t result; 1173 uint8_t fwdpolicy = dns_fwdpolicy_only; 1174 1175 iter = dbus_svc_message_iterator_new( dbus, msg ); 1176 1177 if( iter == 0L ) 1178 { 1179 if( reply_expected ) 1180 { 1181 sprintf(error_name, "com.redhat.named.InvalidArguments"); 1182 sprintf(error_message,"SetForwarders requires DNS name and nameservers arguments."); 1183 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1184 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1185 ); 1186 } 1187 return; 1188 } 1189 1190 argType = dbus_svc_message_next_arg_type( dbus, iter ); 1191 1192 if( argType != TYPE_STRING ) 1193 { 1194 if( reply_expected ) 1195 { 1196 sprintf(error_name, "com.redhat.named.InvalidArguments"); 1197 sprintf(error_message,"SetForwarders requires DNS name string initial argument."); 1198 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1199 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1200 ); 1201 } 1202 return; 1203 } 1204 1205 dbus_svc_message_next_arg( dbus, iter, &domains ); 1206 1207 if( ( domains == 0L ) || (*domains == '\0') ) 1208 { 1209 if( reply_expected ) 1210 { 1211 sprintf(error_name, "com.redhat.named.InvalidArguments"); 1212 sprintf(error_message,"SetForwarders requires DNS name string initial argument."); 1213 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1214 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1215 ); 1216 } 1217 return; 1218 } 1219 1220 dbus_mgr_get_name_list( mgr, domains, &nameList, error_name, error_message ); 1221 1222 if( error_name[0] != '\0' ) 1223 { 1224 if( reply_expected ) 1225 { 1226 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1227 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1228 ); 1229 } 1230 return; 1231 } 1232 1233 if( ISC_LIST_HEAD( nameList ) == 0L ) 1234 return; 1235 1236 result = dbus_mgr_get_sa_list( mgr, iter, &saList , &fwdpolicy, error_name, error_message ); 1237 1238 if( result == ISC_R_SUCCESS ) 1239 { 1240 result = dbus_mgr_set_forwarders( mgr, &nameList, &saList, fwdpolicy ); 1241 1242 if( result != ISC_R_SUCCESS ) 1243 { 1244 if( reply_expected ) 1245 { 1246 sprintf(error_name, "com.redhat.named.Failure"); 1247 sprintf(error_message, isc_result_totext(result)); 1248 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1249 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1250 ); 1251 } 1252 }else 1253 if( reply_expected ) 1254 dbus_svc_send( dbus, RETURN, serial, &new_serial, sender, path, interface, member, 1255 TYPE_UINT32, &result, TYPE_INVALID 1256 ); 1257 }else 1258 { 1259 if( reply_expected ) 1260 { 1261 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1262 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1263 ); 1264 } 1265 } 1266 1267 for( dnsName = ISC_LIST_HEAD( nameList ); 1268 (dnsName != 0L) ; 1269 dnsName = ISC_LIST_HEAD( nameList ) 1270 ) 1271 { 1272 if( ISC_LINK_LINKED(dnsName,link) ) 1273 ISC_LIST_DEQUEUE( nameList, dnsName, link ); 1274 isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) ); 1275 } 1276 1277 for( nsSA = ISC_LIST_HEAD(saList); 1278 (nsSA != 0L) ; 1279 nsSA = ISC_LIST_HEAD(saList) 1280 ) 1281 { 1282 if( ISC_LINK_LINKED(nsSA,link) ) 1283 ISC_LIST_DEQUEUE( saList, nsSA, link ); 1284 isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t)); 1285 } 1286} 1287 1288static 1289int dbus_mgr_msg_append_dns_name 1290( DBUS_SVC dbus, 1291 dbus_svc_MessageHandle msg, 1292 dns_name_t *name 1293) 1294{ 1295 char nameBuf[ DNS_NAME_FORMATSIZE ]="", *nameP=&(nameBuf[0]); 1296 1297 dns_name_format(name, nameP, DNS_NAME_FORMATSIZE ); 1298 1299 if( *nameP == '\0' ) 1300 return 0; 1301 1302 return dbus_svc_message_append_args( dbus, msg, TYPE_STRING, &nameP, TYPE_INVALID ) > 0; 1303} 1304 1305typedef enum dbmoi_e 1306{ 1307 OUTPUT_BINARY, 1308 OUTPUT_TEXT 1309} DBusMgrOutputInterface; 1310 1311static 1312int dbus_mgr_msg_append_forwarders 1313( DBUS_SVC dbus, 1314 dbus_svc_MessageHandle msg, 1315 dns_forwarders_t *fwdr, 1316 DBusMgrOutputInterface outputType 1317) 1318{ 1319 isc_sockaddr_t *sa; 1320 char policyBuf[16]="", *pbp[1]={&(policyBuf[0])}, addressBuf[64]="", *abp[1]={&(addressBuf[0])}; 1321 uint8_t *byteArray[1]; 1322 1323 if( outputType == OUTPUT_BINARY ) 1324 { 1325 if(!dbus_svc_message_append_args 1326 ( dbus, msg, 1327 TYPE_BYTE, &(fwdr->fwdpolicy), 1328 TYPE_INVALID 1329 ) 1330 ) return 0; 1331 }else 1332 if( outputType == OUTPUT_TEXT ) 1333 { 1334 sprintf(policyBuf,"%s", 1335 (fwdr->fwdpolicy == dns_fwdpolicy_none) 1336 ? "none" 1337 : (fwdr->fwdpolicy == dns_fwdpolicy_first) 1338 ? "first" 1339 : "only" 1340 ); 1341 if(!dbus_svc_message_append_args 1342 ( dbus, msg, 1343 TYPE_STRING, pbp, 1344 TYPE_INVALID 1345 ) 1346 ) return 0; 1347 }else 1348 return 0; 1349 1350 for( sa = ISC_LIST_HEAD(fwdr->addrs); 1351 sa != 0L; 1352 sa = ISC_LIST_NEXT(sa, link) 1353 ) 1354 { 1355 if( outputType == OUTPUT_BINARY ) 1356 { 1357 if( sa->type.sa.sa_family == AF_INET ) 1358 { 1359 if(!dbus_svc_message_append_args 1360 ( dbus, msg, 1361 TYPE_UINT32, &(sa->type.sin.sin_addr.s_addr), 1362 TYPE_INVALID 1363 ) 1364 ) return 0; 1365 1366 if(!dbus_svc_message_append_args 1367 ( dbus, msg, 1368 TYPE_UINT16, &(sa->type.sin.sin_port), 1369 TYPE_INVALID 1370 ) 1371 ) return 0; 1372 }else 1373 if( sa->type.sa.sa_family == AF_INET6 ) 1374 { 1375 byteArray[0] = (uint8_t*)&(sa->type.sin6.sin6_addr); 1376 if(!dbus_svc_message_append_args 1377 ( dbus, msg, 1378 TYPE_ARRAY, TYPE_BYTE, &byteArray, sizeof(struct in6_addr), 1379 TYPE_INVALID 1380 ) 1381 ) return 0; 1382 1383 if(!dbus_svc_message_append_args 1384 ( dbus, msg, 1385 TYPE_UINT16, &(sa->type.sin6.sin6_port), 1386 TYPE_INVALID 1387 ) 1388 ) return 0; 1389 }else 1390 continue; 1391 }else 1392 if( outputType == OUTPUT_TEXT ) 1393 { 1394 if( sa->type.sa.sa_family == AF_INET ) 1395 { 1396 if( inet_ntop( AF_INET, &(sa->type.sin.sin_addr), addressBuf, sizeof(addressBuf)) == 0L ) 1397 continue; 1398 if(!dbus_svc_message_append_args 1399 ( dbus, msg, 1400 TYPE_STRING, abp, 1401 TYPE_INVALID 1402 ) 1403 ) return 0; 1404 sprintf(addressBuf, "%hu", ntohs( sa->type.sin.sin_port )); 1405 if(!dbus_svc_message_append_args 1406 ( dbus, msg, 1407 TYPE_STRING, abp, 1408 TYPE_INVALID 1409 ) 1410 ) return 0; 1411 }else 1412 if( sa->type.sa.sa_family == AF_INET6 ) 1413 { 1414 if( inet_ntop( AF_INET6, &(sa->type.sin6.sin6_addr), addressBuf, sizeof(addressBuf)) == 0L ) 1415 continue; 1416 if(!dbus_svc_message_append_args 1417 ( dbus, msg, 1418 TYPE_STRING, abp, 1419 TYPE_INVALID 1420 ) 1421 ) return 0; 1422 sprintf(addressBuf, "%hu", ntohs( sa->type.sin6.sin6_port )); 1423 if(!dbus_svc_message_append_args 1424 ( dbus, msg, 1425 TYPE_STRING, abp, 1426 TYPE_INVALID 1427 ) 1428 ) return 0; 1429 }else 1430 continue; 1431 }else 1432 return 0; 1433 } 1434 return 1; 1435} 1436 1437typedef struct dbm_m_s 1438{ 1439 DBUS_SVC dbus; 1440 dbus_svc_MessageHandle msg; 1441 DBusMgrOutputInterface outputType; 1442} DBusMgrMsg; 1443 1444static 1445void forwarders_to_msg( dns_name_t *name, dns_forwarders_t *fwdr, void *mp ) 1446{ 1447 DBusMgrMsg *m = mp; 1448 1449 if( (fwdr == 0L) || (name == 0L) || (mp == 0L)) 1450 return; 1451 dbus_mgr_msg_append_dns_name ( m->dbus, m->msg, name ); 1452 dbus_mgr_msg_append_forwarders( m->dbus, m->msg, fwdr, m->outputType ); 1453} 1454 1455static void 1456dbus_mgr_handle_list_forwarders 1457( 1458 DBUS_SVC dbus, 1459 uint8_t reply_expected, 1460 uint32_t serial, 1461 const char *path, 1462 const char *member, 1463 const char *interface, 1464 const char *sender, 1465 dbus_svc_MessageHandle msg 1466) 1467{ 1468 char error_name[1024], error_message[1024]; 1469 DBusMgrMsg m; 1470 uint32_t new_serial; 1471 dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable(); 1472 DBusMgrOutputInterface outputType = OUTPUT_BINARY; 1473 uint32_t length = strlen(interface); 1474 1475 if( !reply_expected ) 1476 return; 1477 1478 if( (length > 4) && (strcmp(interface + (length - 4), "text")==0)) 1479 outputType = OUTPUT_TEXT; 1480 1481 if( fwdtable == 0L ) 1482 { 1483 sprintf(error_name,"com.redhat.dbus.Failure"); 1484 sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM)); 1485 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1486 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1487 ); 1488 return; 1489 } 1490 1491 msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member); 1492 1493 m.dbus = dbus; 1494 m.msg = msg; 1495 m.outputType = outputType; 1496 1497 if( msg == 0L ) 1498 { 1499 sprintf(error_name,"com.redhat.dbus.OutOfMemory"); 1500 sprintf(error_message,"out of memory"); 1501 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1502 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1503 ); 1504 } 1505 1506 dns_fwdtable_foreach( fwdtable, forwarders_to_msg, &m ); 1507 1508 dbus_svc_send_message( dbus, msg, &new_serial ); 1509} 1510 1511static void 1512dbus_mgr_handle_get_forwarders 1513( 1514 DBUS_SVC dbus, 1515 uint8_t reply_expected, 1516 uint32_t serial, 1517 const char *path, 1518 const char *member, 1519 const char *interface, 1520 const char *sender, 1521 dbus_svc_MessageHandle msg 1522) 1523{ 1524 char error_name[1024], error_message[1024], *domain=0L; 1525 isc_result_t result; 1526 dns_fixedname_t fixedname; 1527 dns_name_t *dnsName; 1528 isc_buffer_t buffer; 1529 uint32_t length, new_serial; 1530 dns_fwdtable_t *fwdtable; 1531 dns_forwarders_t *fwdr=0L; 1532 dns_name_t *foundname; 1533 dns_fixedname_t fixedFoundName; 1534 DBusMgrOutputInterface outputType = OUTPUT_BINARY; 1535 1536 if( !reply_expected ) 1537 return; 1538 1539 length = strlen(interface); 1540 1541 if( (length > 4) && (strcmp(interface + (length - 4), "text")==0)) 1542 outputType = OUTPUT_TEXT; 1543 1544 if( (!dbus_svc_get_args( dbus, msg, TYPE_STRING, &domain, TYPE_INVALID)) 1545 ||(domain == 0L) 1546 ||(*domain == '\0') 1547 ) 1548 { 1549 1550 sprintf(error_name,"com.redhat.dbus.InvalidArguments"); 1551 sprintf(error_message,"domain name argument expected"); 1552 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1553 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1554 ); 1555 return; 1556 } 1557 1558 length = strlen( domain ); 1559 1560 isc_buffer_init( &buffer, domain, length); 1561 1562 isc_buffer_add(&buffer, length); 1563 1564 dns_fixedname_init(&fixedname); 1565 1566 dnsName = dns_fixedname_name(&fixedname); 1567 1568 result = dns_name_fromtext 1569 ( dnsName, &buffer, dns_rootname, 0, NULL 1570 ); 1571 1572 if( result != ISC_R_SUCCESS ) 1573 { 1574 sprintf(error_name,"com.redhat.dbus.InvalidArguments"); 1575 sprintf(error_message,"invalid domain name argument: %s", domain); 1576 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1577 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1578 ); 1579 return; 1580 } 1581 1582 msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member); 1583 1584 if( msg == 0L ) 1585 { 1586 sprintf(error_name,"com.redhat.dbus.OutOfMemory"); 1587 sprintf(error_message,"out of memory"); 1588 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1589 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1590 ); 1591 return; 1592 } 1593 1594 fwdtable = dbus_mgr_get_fwdtable(); 1595 1596 if( fwdtable == 0L ) 1597 { 1598 sprintf(error_name,"com.redhat.dbus.Failure"); 1599 sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM)); 1600 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1601 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1602 ); 1603 return; 1604 } 1605 1606 dns_fixedname_init(&fixedFoundName); 1607 foundname = dns_fixedname_name(&fixedFoundName); 1608 1609 if( ( dns_fwdtable_find_closest( fwdtable, dnsName, foundname, &fwdr ) == ISC_R_SUCCESS ) 1610 &&( fwdr != 0L ) 1611 ) 1612 { 1613 if( (!dbus_mgr_msg_append_dns_name( dbus, msg, foundname )) 1614 ||(!dbus_mgr_msg_append_forwarders( dbus, msg, fwdr, outputType )) 1615 ) 1616 { 1617 sprintf(error_name,"com.redhat.dbus.OutOfMemory"); 1618 sprintf(error_message,"out of memory"); 1619 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1620 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1621 ); 1622 return; 1623 } 1624 1625 }else 1626 { 1627 result = ISC_R_NOTFOUND; 1628 if( outputType == OUTPUT_BINARY ) 1629 { 1630 dbus_svc_message_append_args( dbus, msg, 1631 TYPE_UINT32, &(result), 1632 TYPE_INVALID 1633 ) ; 1634 }else 1635 { 1636 sprintf(error_name,"com.redhat.dbus.NotFound"); 1637 sprintf(error_message,"Not Found"); 1638 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 1639 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 1640 ); 1641 return; 1642 } 1643 } 1644 dbus_svc_send_message( dbus, msg, &new_serial ); 1645} 1646 1647static void 1648dbus_mgr_check_dhcdbd_state( ns_dbus_mgr_t *mgr, dbus_svc_MessageHandle msg ) 1649{ 1650 DBUS_SVC dbus = mgr->dbus; 1651 char *name_owned = 0L, 1652 *old_owner = 0L, 1653 *new_owner = 0L; 1654 1655 if( !dbus_svc_get_args( dbus, msg, 1656 TYPE_STRING, &name_owned, 1657 TYPE_STRING, &old_owner, 1658 TYPE_STRING, &new_owner, 1659 TYPE_INVALID 1660 ) 1661 ) return; 1662 1663 dbus_mgr_log_dbg("NameOwnerChanged: %s %s %s ( %s )", name_owned, old_owner, new_owner, mgr->dhcdbd_name); 1664 1665 if( (name_owned == 0L) || (new_owner == 0L) || (old_owner == 0L) ) 1666 return; 1667 1668 if( strcmp( name_owned, "com.redhat.dhcp" ) == 0 ) 1669 { 1670 if( *new_owner == '\0' ) 1671 { 1672 isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1); 1673 mgr->dhcdbd_name = 0L; 1674 dbus_mgr_log_err("D-BUS dhcdbd subscription disabled."); 1675 return; 1676 } 1677 if( (mgr->dhcdbd_name == 0L) 1678 ||( strcmp( mgr->dhcdbd_name, new_owner) != 0 ) 1679 ) 1680 { 1681 if( mgr->dhcdbd_name != 0L ) 1682 { 1683 isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name)+1); 1684 mgr->dhcdbd_name = 0L; 1685 } 1686 mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(new_owner) + 1); 1687 if( mgr->dhcdbd_name == 0L ) 1688 return; 1689 strcpy( mgr->dhcdbd_name, new_owner ); 1690 dbus_mgr_subscribe_to_dhcdbd( mgr ); 1691 } 1692 }else 1693 if( ( mgr->dhcdbd_name != 0L ) 1694 && ( strcmp(mgr->dhcdbd_name, name_owned) == 0L ) 1695 && ( *new_owner == '\0' ) 1696 ) 1697 { 1698 isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name)); 1699 mgr->dhcdbd_name = 0L; 1700 dbus_mgr_log_err("D-BUS dhcdbd subscription disabled."); 1701 } 1702} 1703 1704static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 ) 1705{ 1706 return( strcmp( ((const DHC_IF*)p1)->if_name, ((const DHC_IF*)p2)->if_name) ); 1707} 1708 1709static 1710dns_name_t *dbus_mgr_if_reverse_ip_name 1711( ns_dbus_mgr_t *mgr, 1712 struct in_addr ip_address, 1713 struct in_addr subnet_mask 1714) 1715{ 1716 dns_name_t *dns_name =0L; 1717 dns_fixedname_t *fixedname=0L; 1718 char name [ DNS_NAME_FORMATSIZE ], *p; 1719 uint32_t ip = (ntohl(ip_address.s_addr) & ntohl(subnet_mask.s_addr)), i; 1720 isc_buffer_t buffer; 1721 isc_result_t result; 1722 1723 if( (ip == 0) || (ip == 0xffffffff) ) 1724 return 0L; 1725 1726 for(i = 8, p = name; (i < 32); i += 8) 1727 if( ip & ( 0xff << i ) ) 1728 p += sprintf(p, "%u.", (((ip & ( 0xff << i )) >> i ) & 0xff) ); 1729 1730 if( p > name ) 1731 { 1732 p += sprintf(p, "in-addr.arpa"); 1733 isc_buffer_init( &buffer, name, p - name ); 1734 isc_buffer_add(&buffer, p - name); 1735 1736 fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t )); 1737 1738 dns_fixedname_init(fixedname); 1739 1740 dns_name = dns_fixedname_name(fixedname); 1741 1742 result= dns_name_fromtext 1743 ( dns_name, &buffer, dns_rootname, 0, NULL 1744 ); 1745 1746 ISC_LINK_INIT(dns_name, link); 1747 if( result == ISC_R_SUCCESS ) 1748 return dns_name; 1749 } 1750 return 0L; 1751} 1752 1753static void 1754dbus_mgr_free_dhc( void *p ) 1755{ 1756 DHC_IF *d_if = p; 1757 dns_name_t *dn; 1758 isc_sockaddr_t *sa; 1759 1760 isc_mem_put( ns_g_mctx, d_if->if_name, strlen(d_if->if_name) + 1); 1761 for( sa = ISC_LIST_HEAD( d_if->dns ); 1762 sa != NULL; 1763 sa = ISC_LIST_HEAD( d_if->dns ) 1764 ) 1765 { 1766 if( ISC_LINK_LINKED( sa, link ) ) 1767 ISC_LIST_UNLINK( d_if->dns, sa, link ); 1768 isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t)); 1769 } 1770 for( dn = ISC_LIST_HEAD( d_if->dn ); 1771 dn != NULL; 1772 dn = ISC_LIST_HEAD( d_if->dn ) 1773 ) 1774 { 1775 if( ISC_LINK_LINKED( dn, link ) ) 1776 ISC_LIST_UNLINK( d_if->dn, dn, link ); 1777 isc_mem_put( ns_g_mctx, dn, sizeof( dns_fixedname_t ) ); 1778 } 1779 isc_mem_put( ns_g_mctx, d_if, sizeof(DHC_IF)); 1780} 1781 1782static void 1783dbus_mgr_handle_dhcdbd_message 1784( 1785 ns_dbus_mgr_t *mgr, 1786 const char *path, 1787 const char *member, 1788 dbus_svc_MessageHandle msg 1789) 1790{ 1791 DBUS_SVC dbus = mgr->dbus; 1792 DHC_IF *d_if, *const*d_ifpp, dif; 1793 DHC_State dhc_state; 1794 char *if_name, *opt_name, error_name[1024]="", error_message[1024]=""; 1795 uint8_t *value=0L; 1796 uint32_t length; 1797 isc_result_t result; 1798 isc_sockaddr_t *sa = 0L; 1799 dns_name_t *dn = 0L; 1800 struct in_addr *ip; 1801 in_port_t port; 1802 char dnBuf[ DNS_NAME_FORMATSIZE ]; 1803 isc_buffer_t buffer; 1804 DBusMgrInitialFwdr *ifwdr, *const*ifwdpp, ifwd; 1805 ISC_LIST(DBusMgrInitialFwdr) ifwdrList; 1806 DNSNameList nameList; 1807 dbus_mgr_log_dbg("Got dhcdbd message: %s %s %p", path, member, msg ); 1808 1809 if( ( if_name = strrchr(path,'/') ) == 0L ) 1810 { 1811 dbus_mgr_log_err("bad path in dhcdbd message:", path); 1812 return; 1813 } 1814 1815 ++if_name; 1816 dif.if_name = if_name; 1817 1818 if( ((d_ifpp=tfind( &dif, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator)) == 0L) 1819 ||((d_if = *d_ifpp) == 0L) 1820 ) 1821 { 1822 d_if = isc_mem_get( mgr->mctx, sizeof(DHC_IF)); 1823 if( d_if == 0L ) 1824 { 1825 dbus_mgr_log_err("out of memory"); 1826 return; 1827 } 1828 memset(d_if, '\0', sizeof(DHC_IF)); 1829 if((d_if->if_name = isc_mem_get( mgr->mctx, strlen(if_name) + 1)) == 0L) 1830 { 1831 dbus_mgr_log_err("out of memory"); 1832 return; 1833 } 1834 strcpy(d_if->if_name, if_name); 1835 d_if->dhc_state = DHC_INVALID; 1836 d_if->previous_state = DHC_INVALID; 1837 ISC_LIST_INIT( d_if->dn ); 1838 ISC_LIST_INIT( d_if->dns ); 1839 if( tsearch( d_if, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator) == 0L ) 1840 { 1841 dbus_mgr_log_err("out of memory"); 1842 return; 1843 } 1844 } 1845 1846 if( strcmp(member, "reason") == 0 ) 1847 { 1848 if( (!dbus_svc_get_args( dbus, msg, 1849 TYPE_STRING, &opt_name, 1850 TYPE_ARRAY, TYPE_BYTE, &value, &length, 1851 TYPE_INVALID 1852 ) 1853 ) 1854 ||( value == 0L) 1855 ||( length != sizeof(uint32_t)) 1856 ||( *((uint32_t*)value) > DHC_END_OPTIONS) 1857 ) 1858 { 1859 dbus_mgr_log_err("Invalid DHC reason value received from dhcdbd"); 1860 return; 1861 } 1862 dhc_state = (DHC_State) *((uint32_t*)value); 1863 dbus_mgr_log_dbg("reason: %d %d %d", dhc_state, d_if->dhc_state, d_if->previous_state); 1864 switch( dhc_state ) 1865 { 1866 1867 case DHC_END_OPTIONS: 1868 switch( d_if->dhc_state ) 1869 { 1870 case DHC_END_OPTIONS: 1871 break; 1872 1873 case DHC_RENEW: 1874 case DHC_REBIND: 1875 if( ( d_if->previous_state != DHC_INVALID ) 1876 &&( d_if->previous_state != DHC_RELEASE ) 1877 ) break; 1878 /* DHC_RENEW means the same lease parameters were obtained. 1879 * Only do configuration if we started up with existing dhclient 1880 * which has now renewed - else we are already configured correctly. 1881 */ 1882 dbus_mgr_log_err("D-BUS: existing dhclient for interface %s RENEWed lease", if_name); 1883 1884 case DHC_REBOOT: 1885 case DHC_BOUND: 1886 d_if->previous_state = d_if->dhc_state; 1887 d_if->dhc_state = DHC_BOUND; 1888 if( (dn = dbus_mgr_if_reverse_ip_name(mgr, d_if->ip, d_if->subnet_mask )) != 0L ) 1889 { 1890 ISC_LIST_APPEND(d_if->dn, dn, link ); 1891 } 1892 if( ( ISC_LIST_HEAD( d_if->dn ) != NULL ) 1893 &&( ISC_LIST_HEAD( d_if->dns ) != NULL ) 1894 ) 1895 { 1896 dbus_mgr_log_err("D-BUS: dhclient for interface %s acquired new lease - creating forwarders.", 1897 if_name 1898 ); 1899 result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_only ); 1900 if( result != ISC_R_SUCCESS ) 1901 { 1902 dbus_mgr_log_err("D-BUS: forwarder configuration failed: %s", isc_result_totext(result)); 1903 } 1904 } 1905 break; 1906 1907 case DHC_STOP: 1908 case DHC_TIMEOUT: 1909 case DHC_FAIL: 1910 case DHC_EXPIRE: 1911 case DHC_RELEASE: 1912 d_if->previous_state = d_if->dhc_state; 1913 d_if->dhc_state = DHC_RELEASE; 1914 if( ISC_LIST_HEAD( d_if->dn ) != NULL ) 1915 { 1916 dbus_mgr_log_err("D-BUS: dhclient for interface %s released lease - removing forwarders.", 1917 if_name); 1918 for( sa = ISC_LIST_HEAD( d_if->dns ); 1919 sa != 0L; 1920 sa = ISC_LIST_HEAD( d_if->dns ) 1921 ) 1922 { 1923 if( ISC_LINK_LINKED( sa, link ) ) 1924 ISC_LIST_UNLINK( d_if->dns, sa, link ); 1925 isc_mem_put( mgr->mctx, sa, sizeof(isc_sockaddr_t)); 1926 } 1927 ISC_LIST_INIT( d_if->dns ); 1928 ISC_LIST_INIT( ifwdrList ); 1929 1930 for( dn = ISC_LIST_HEAD( d_if->dn ); 1931 dn != 0L; 1932 dn = ISC_LIST_NEXT( dn, link ) 1933 ) 1934 { 1935 dns_name_init( &(ifwd.dn), NULL ); 1936 isc_buffer_init( &buffer, dnBuf, DNS_NAME_FORMATSIZE); 1937 dns_name_setbuffer( &(ifwd.dn), &buffer); 1938 dns_name_copy(dn, &(ifwd.dn), NULL); 1939 if( ((ifwdpp = tfind(&ifwd, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator)) != 0L ) 1940 &&((ifwdr = *ifwdpp) != 0L) 1941 ) 1942 { 1943 ISC_LIST_APPEND( ifwdrList, ifwdr, link ); 1944 } 1945 } 1946 1947 result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_none ); 1948 if( result != ISC_R_SUCCESS ) 1949 { 1950 dbus_mgr_log_err("D-BUS: removal of forwarders failed: %s", isc_result_totext(result)); 1951 } 1952 1953 for( dn = ISC_LIST_HEAD( d_if->dn ); 1954 dn != 0L; 1955 dn = ISC_LIST_HEAD( d_if->dn ) 1956 ) 1957 { 1958 if( ISC_LINK_LINKED( dn, link ) ) 1959 ISC_LIST_UNLINK( d_if->dn, dn, link ); 1960 isc_mem_put( mgr->mctx, dn, sizeof( dns_fixedname_t ) ); 1961 } 1962 ISC_LIST_INIT( d_if->dn ); 1963 1964 for( ifwdr = ISC_LIST_HEAD( ifwdrList ); 1965 ifwdr != 0L; 1966 ifwdr = ISC_LIST_HEAD( ifwdrList ) 1967 ) 1968 { 1969 if( ISC_LINK_LINKED( ifwdr, link ) ) 1970 ISC_LIST_UNLINK( ifwdrList, ifwdr, link ); 1971 ISC_LINK_INIT(ifwdr, link); 1972 ISC_LIST_INIT(nameList); 1973 ISC_LINK_INIT(&(ifwdr->dn), link); 1974 ISC_LIST_APPEND( nameList, &(ifwdr->dn), link ); 1975 result = dbus_mgr_set_forwarders( mgr, &nameList, 1976 &(ifwdr->sa), 1977 ifwdr->fwdpolicy 1978 ); 1979 if( result != ISC_R_SUCCESS ) 1980 { 1981 dbus_mgr_log_err("D-BUS: restore of forwarders failed: %s", isc_result_totext(result)); 1982 } 1983 } 1984 } 1985 1986 case DHC_ABEND: 1987 case DHC_END: 1988 case DHC_NBI: 1989 case DHC_PREINIT: 1990 case DHC_MEDIUM: 1991 case DHC_START: 1992 case DHC_INVALID: 1993 default: 1994 break; 1995 } 1996 break; 1997 1998 case DHC_BOUND: 1999 case DHC_REBOOT: 2000 case DHC_REBIND: 2001 case DHC_RENEW: 2002 case DHC_STOP: 2003 case DHC_TIMEOUT: 2004 case DHC_FAIL: 2005 case DHC_EXPIRE: 2006 case DHC_RELEASE: 2007 d_if->previous_state = d_if->dhc_state; 2008 d_if->dhc_state = dhc_state; 2009 2010 case DHC_ABEND: 2011 case DHC_END: 2012 case DHC_NBI: 2013 case DHC_PREINIT: 2014 case DHC_MEDIUM: 2015 case DHC_START: 2016 case DHC_INVALID: 2017 default: 2018 break; 2019 } 2020 }else 2021 if( strcmp( member, "domain_name" ) == 0 ) 2022 { 2023 if( (!dbus_svc_get_args( dbus, msg, 2024 TYPE_STRING, &opt_name, 2025 TYPE_ARRAY, TYPE_BYTE, &value, &length, 2026 TYPE_INVALID 2027 ) 2028 ) 2029 ||( value == 0L) 2030 ||( length == 0) 2031 ) 2032 { 2033 dbus_mgr_log_err("Invalid domain_name value received from dhcdbd"); 2034 return; 2035 } 2036 dbus_mgr_log_dbg("domain-name %s", (char*)value); 2037 dbus_mgr_get_name_list( mgr, (char*)value, &(d_if->dn), error_name, error_message ); 2038 if( ( error_message[0] != '\0' ) || (ISC_LIST_HEAD(d_if->dn) == 0L )) 2039 { 2040 dbus_mgr_log_err("Bad domain_name value: %s", error_message ); 2041 } 2042 }else 2043 if( strcmp( member, "domain_name_servers") == 0 ) 2044 { 2045 if( (!dbus_svc_get_args( dbus, msg, 2046 TYPE_STRING, &opt_name, 2047 TYPE_ARRAY, TYPE_BYTE, &value, &length, 2048 TYPE_INVALID 2049 ) 2050 ) 2051 ||( value == 0L) 2052 ||( length == 0) 2053 ) 2054 { 2055 dbus_mgr_log_err("Invalid domain_name_servers value received from dhcdbd"); 2056 return; 2057 } 2058 for(ip = (struct in_addr*) value; ip < ((struct in_addr*)(value + length)); ip++) 2059 { 2060 dbus_mgr_log_dbg("domain-name-servers: %s", inet_ntop(AF_INET, value, error_name, 16)); 2061 sa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t)); 2062 memset(sa, '\0', sizeof(isc_sockaddr_t)); 2063 sa->type.sin.sin_addr = *ip; 2064 sa->type.sa.sa_family = AF_INET; 2065 sa->length = sizeof(sa->type.sin); 2066 result = ns_config_getport(ns_g_config, &(port) ); 2067 if( result != ISC_R_SUCCESS ) 2068 port = 53; 2069 sa->type.sin.sin_port = htons( port ); 2070 ISC_LIST_APPEND(d_if->dns, sa, link); 2071 } 2072 }else 2073 if( strcmp(member, "ip_address") == 0) 2074 { 2075 if( (!dbus_svc_get_args( dbus, msg, 2076 TYPE_STRING, &opt_name, 2077 TYPE_ARRAY, TYPE_BYTE, &value, &length, 2078 TYPE_INVALID 2079 ) 2080 ) 2081 ||( value == 0L) 2082 ||( length != sizeof(struct in_addr) ) 2083 ) 2084 { 2085 dbus_mgr_log_err("Invalid ip_address value received from dhcdbd"); 2086 return; 2087 } 2088 dbus_mgr_log_dbg("ip-address: %s", inet_ntop(AF_INET, value, error_name, 16)); 2089 d_if->ip = *((struct in_addr*)value); 2090 2091 }else 2092 if( strcmp(member, "subnet_mask") == 0 ) 2093 { 2094 if( (!dbus_svc_get_args( dbus, msg, 2095 TYPE_STRING, &opt_name, 2096 TYPE_ARRAY, TYPE_BYTE, &value, &length, 2097 TYPE_INVALID 2098 ) 2099 ) 2100 ||( value == 0L) 2101 ||( length != sizeof(struct in_addr) ) 2102 ) 2103 { 2104 dbus_mgr_log_err("Invalid subnet_mask value received from dhcdbd"); 2105 return; 2106 } 2107 dbus_mgr_log_dbg("subnet-mask: %s", inet_ntop(AF_INET, value, error_name, 16)); 2108 d_if->subnet_mask = *((struct in_addr*)value); 2109 } 2110} 2111 2112static 2113dbus_svc_HandlerResult 2114dbus_mgr_message_handler 2115( 2116 DBusMsgHandlerArgs 2117) 2118{ 2119 char error_name[1024], error_message[1024]; 2120 ns_dbus_mgr_t *mgr = object; 2121 uint32_t new_serial; 2122 2123 if_suffix = prefix = suffix = prefixObject = 0L; 2124 2125 dbus_mgr_log_dbg("D-BUS message: %u %u %u %s %s %s %s %s %s", 2126 type, reply_expected, serial, destination, path, member, interface, sender, signature 2127 ); 2128 2129 if ( ( type == SIGNAL ) 2130 &&( strcmp(path,"/org/freedesktop/DBus/Local") == 0 ) 2131 ) 2132 { 2133 if( strcmp(member,"Disconnected") == 0 ) 2134 dbus_mgr_dbus_shutdown_handler( mgr ); 2135 }else 2136 if( ( type == SIGNAL ) 2137 &&( strcmp(path,"/org/freedesktop/DBus") == 0 ) 2138 &&(strcmp(member,"NameOwnerChanged") == 0) 2139 &&(strcmp(signature, "sss") == 0) 2140 ) 2141 { 2142 dbus_mgr_check_dhcdbd_state( mgr, msg ); 2143 }else 2144 if( ( type == SIGNAL ) 2145 &&( (sender != 0L) && (mgr->dhcdbd_name != 0L) && (strcmp(sender,mgr->dhcdbd_name) == 0)) 2146 &&( strcmp(interface,"com.redhat.dhcp.subscribe.binary") == 0 ) 2147 ) 2148 { 2149 dbus_mgr_handle_dhcdbd_message( mgr, path, member, msg ); 2150 }else 2151 if( (type == CALL) 2152 &&( strcmp(destination, DBUSMGR_DESTINATION)==0) 2153 &&( strcmp(path, DBUSMGR_OBJECT_PATH)==0) 2154 ) 2155 { 2156 if( strcmp(member, "SetForwarders") == 0 ) 2157 dbus_mgr_handle_set_forwarders 2158 ( mgr, dbus, reply_expected, serial, path, member, interface, sender, msg ); 2159 else 2160 if( strcmp(member, "GetForwarders") == 0 ) 2161 { 2162 if( *signature != '\0' ) 2163 dbus_mgr_handle_get_forwarders 2164 ( dbus, reply_expected, serial, path, member, interface, sender, msg ); 2165 else 2166 dbus_mgr_handle_list_forwarders 2167 ( dbus, reply_expected, serial, path, member, interface, sender, msg ); 2168 }else 2169 if( reply_expected ) 2170 { 2171 sprintf(error_name, "InvalidOperation"); 2172 sprintf(error_message, "Unrecognized path / interface / member"); 2173 dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member, 2174 TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID 2175 ); 2176 } 2177 } 2178 return HANDLED; 2179} 2180 2181static void 2182dbus_mgr_read_watch_activated(isc_task_t *t, isc_event_t *ev) 2183{ 2184 DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg); 2185 t = t; 2186 isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size); 2187 dbus_mgr_log_dbg("watch %d READ",sfd->fd); 2188 isc_socket_fd_handle_reads( sfd->sock, sfd->ser ); 2189 dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_READ ); 2190} 2191 2192static void 2193dbus_mgr_write_watch_activated(isc_task_t *t, isc_event_t *ev) 2194{ 2195 DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg); 2196 t = t; 2197 isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size); 2198 dbus_mgr_log_dbg("watch %d WRITE",sfd->fd); 2199 isc_socket_fd_handle_writes( sfd->sock, sfd->ser ); 2200 dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_WRITE ); 2201} 2202 2203static void 2204dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev) 2205{ 2206 ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg); 2207 t = t; 2208 isc_mem_put(mgr->mctx, ev, ev->ev_size); 2209 if( ( mgr->dbus == 0L ) || (mgr->sockets == 0L)) 2210 { 2211 return; 2212 } 2213 dbus_mgr_log_dbg("watches selected"); 2214 dbus_svc_dispatch( mgr->dbus ); 2215 dbus_mgr_log_dbg("dispatch complete"); 2216} 2217 2218static int dbus_mgr_socket_comparator( const void *p1, const void *p2 ) 2219{ 2220 return( ( ((const DBusMgrSocket*)p1)->fd 2221 == ((const DBusMgrSocket*)p2)->fd 2222 ) ? 0 2223 : ( ((const DBusMgrSocket*)p1)->fd 2224 > ((const DBusMgrSocket*)p2)->fd 2225 ) ? 1 2226 : -1 2227 ); 2228} 2229 2230static void 2231dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp ) 2232{ 2233 ns_dbus_mgr_t *mgr = mgrp; 2234 DBusMgrSocket sockFd, *sfd=0L, *const*spp=0L; 2235 isc_result_t result=ISC_R_SUCCESS; 2236 isc_socketevent_t *sev; 2237 isc_event_t *pev[1]; 2238 2239 if(mgr == 0L) 2240 return; 2241 2242 if( (flags & 7) == WATCH_ERROR ) 2243 return; 2244 2245 sockFd.fd = fd; 2246 2247 dbus_mgr_log_dbg("watch handler: fd %d %d", fd, flags); 2248 2249 if( ((spp = tfind( &sockFd, &(mgr->sockets), dbus_mgr_socket_comparator) ) == 0L ) 2250 ||((sfd = *spp) == 0L ) 2251 ) 2252 { 2253 if( ( flags & WATCH_ENABLE ) == 0 ) 2254 return; 2255 2256 sfd = isc_mem_get(mgr->mctx, sizeof(DBusMgrSocket)); 2257 if( sfd == 0L ) 2258 { 2259 dbus_mgr_log_err("dbus_mgr: out of memory" ); 2260 return; 2261 } 2262 sfd->fd = fd; 2263 sfd->mgr = mgr; 2264 sfd->ser = sfd->sew = sfd->sel = 0L; 2265 2266 if( tsearch(sfd, &(mgr->sockets), dbus_mgr_socket_comparator) == 0L ) 2267 { 2268 dbus_mgr_log_err("dbus_mgr: out of memory" ); 2269 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2270 return; 2271 } 2272 sfd->sock = 0L; 2273 result = isc_socket_create( mgr->socketmgr, fd, isc_sockettype_fd, &(sfd->sock) ); 2274 if( result != ISC_R_SUCCESS ) 2275 { 2276 dbus_mgr_log_err("dbus_mgr: isc_socket_create failed: %s", 2277 isc_result_totext(result) 2278 ); 2279 tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator); 2280 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2281 return; 2282 } 2283 } 2284 2285 if( (flags & WATCH_ENABLE) == WATCH_ENABLE ) 2286 { 2287 if( (flags & WATCH_READ) == WATCH_READ ) 2288 { 2289 if( sfd->ser == 0L ) 2290 { 2291 sfd->ser = (isc_socketevent_t *) 2292 isc_event_allocate 2293 ( 2294 mgr->mctx, mgr->task, 2295 ISC_SOCKEVENT_READ_READY, 2296 dbus_mgr_read_watch_activated, 2297 sfd, 2298 sizeof(isc_socketevent_t) 2299 ); 2300 2301 if( sfd->ser == 0L ) 2302 { 2303 dbus_mgr_log_err("dbus_mgr: out of memory" ); 2304 tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator); 2305 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2306 return; 2307 } 2308 2309 sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser ); 2310 2311 }else 2312 { 2313 sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser ); 2314 } 2315 } 2316 if( (flags & WATCH_WRITE) == WATCH_WRITE ) 2317 { 2318 if( sfd->sew == 0L ) 2319 { 2320 sfd->sew = (isc_socketevent_t *) 2321 isc_event_allocate 2322 ( 2323 mgr->mctx, mgr->task, 2324 ISC_SOCKEVENT_WRITE_READY, 2325 dbus_mgr_write_watch_activated, 2326 sfd, 2327 sizeof(isc_socketevent_t) 2328 ); 2329 if( sfd->sew == 0L ) 2330 { 2331 dbus_mgr_log_err("dbus_mgr: out of memory" ); 2332 tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator); 2333 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2334 return; 2335 } 2336 2337 sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew ); 2338 2339 }else 2340 { 2341 sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew ); 2342 } 2343 } 2344 if( (sfd->ser != 0L) || (sfd->sew != 0L) ) 2345 { 2346 if( sfd->sel == 0L ) 2347 { 2348 sfd->sel = (isc_socketevent_t *) 2349 isc_event_allocate 2350 ( 2351 mgr->mctx, mgr->task, 2352 ISC_SOCKEVENT_SELECTED, 2353 dbus_mgr_watches_selected, 2354 mgr, 2355 sizeof(isc_socketevent_t) 2356 ); 2357 if( sfd->sel == 0L ) 2358 { 2359 dbus_mgr_log_err("dbus_mgr: out of memory" ); 2360 tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator); 2361 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2362 return; 2363 } 2364 2365 sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel ); 2366 2367 }else 2368 { 2369 sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel); 2370 } 2371 } 2372 }else 2373 { 2374 dbus_mgr_log_dbg("watch %d disabled",fd); 2375 if(flags & WATCH_READ) 2376 { 2377 sev = isc_socket_fd_handle_reads( sfd->sock, 0L ); 2378 if( sev != 0L ) 2379 { 2380 pev[0]=(isc_event_t*)sev; 2381 isc_event_free(pev); 2382 } 2383 sfd->ser = 0L; 2384 } 2385 2386 if( flags & WATCH_WRITE ) 2387 { 2388 sev = isc_socket_fd_handle_writes( sfd->sock, 0L ); 2389 if( sev != 0L ) 2390 { 2391 pev[0]=(isc_event_t*)sev; 2392 isc_event_free(pev); 2393 } 2394 sfd->sew = 0L; 2395 } 2396 2397 if( (sfd->ser == 0L) && (sfd->sew == 0L) ) 2398 { 2399 sev = isc_socket_fd_handle_selected( sfd->sock, 0L ); 2400 if( sev != 0L ) 2401 { 2402 pev[0]=(isc_event_t*)sev; 2403 isc_event_free(pev); 2404 } 2405 sfd->sel = 0L; 2406 2407 tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator); 2408 2409 isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket)); 2410 } 2411 } 2412} 2413 2414static 2415void dbus_mgr_close_socket( const void *p, const VISIT which, const int level) 2416{ 2417 DBusMgrSocket *const*spp=p, *sfd; 2418 isc_event_t *ev ; 2419 int i = level ? 0 :1; 2420 i &= i; 2421 2422 if( (spp==0L) || ((sfd = *spp)==0L) 2423 ||((which != leaf) && (which != postorder)) 2424 ) return; 2425 2426 if( sfd->ser != 0L ) 2427 { 2428 ev = (isc_event_t *)isc_socket_fd_handle_reads(sfd->sock, 0); 2429 if( ev != 0L ) 2430 isc_event_free((isc_event_t **)&ev); 2431 sfd->ser = 0L; 2432 } 2433 2434 if( sfd->sew != 0L ) 2435 { 2436 ev = (isc_event_t *)isc_socket_fd_handle_writes(sfd->sock, 0); 2437 if( ev != 0L ) 2438 isc_event_free((isc_event_t **)&ev); 2439 sfd->sew = 0L; 2440 } 2441 2442 if( sfd->sel != 0L ) 2443 { 2444 ev = (isc_event_t *)isc_socket_fd_handle_selected(sfd->sock, 0); 2445 if( ev != 0L ) 2446 isc_event_free((isc_event_t **)&ev); 2447 sfd->sel = 0L; 2448 dbus_mgr_log_dbg("CLOSED socket %d", sfd->fd); 2449 } 2450} 2451 2452static 2453void dbus_mgr_destroy_socket( void *p ) 2454{ 2455 DBusMgrSocket *sfd = p; 2456 2457 isc_mem_put( sfd->mgr->mctx, sfd, sizeof(DBusMgrSocket) ); 2458} 2459