File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / dbus.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (11 years ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_66p0, v2_66, HEAD
dnsmasq

    1: /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
    2: 
    3:    This program is free software; you can redistribute it and/or modify
    4:    it under the terms of the GNU General Public License as published by
    5:    the Free Software Foundation; version 2 dated June, 1991, or
    6:    (at your option) version 3 dated 29 June, 2007.
    7:  
    8:    This program is distributed in the hope that it will be useful,
    9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11:    GNU General Public License for more details.
   12:      
   13:    You should have received a copy of the GNU General Public License
   14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   15: */
   16: 
   17: #include "dnsmasq.h"
   18: 
   19: #ifdef HAVE_DBUS
   20: 
   21: #include <dbus/dbus.h>
   22: 
   23: const char* introspection_xml_template =
   24: "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
   25: "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
   26: "<node name=\"" DNSMASQ_PATH "\">\n"
   27: "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
   28: "    <method name=\"Introspect\">\n"
   29: "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
   30: "    </method>\n"
   31: "  </interface>\n"
   32: "  <interface name=\"%s\">\n"
   33: "    <method name=\"ClearCache\">\n"
   34: "    </method>\n"
   35: "    <method name=\"GetVersion\">\n"
   36: "      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
   37: "    </method>\n"
   38: "    <method name=\"SetServers\">\n"
   39: "      <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
   40: "    </method>\n"
   41: "    <method name=\"SetDomainServers\">\n"
   42: "      <arg name=\"servers\" direction=\"in\" type=\"as\"/>\n"
   43: "    </method>\n"
   44: "    <method name=\"SetServersEx\">\n"
   45: "      <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
   46: "    </method>\n"
   47: "    <signal name=\"DhcpLeaseAdded\">\n"
   48: "      <arg name=\"ipaddr\" type=\"s\"/>\n"
   49: "      <arg name=\"hwaddr\" type=\"s\"/>\n"
   50: "      <arg name=\"hostname\" type=\"s\"/>\n"
   51: "    </signal>\n"
   52: "    <signal name=\"DhcpLeaseDeleted\">\n"
   53: "      <arg name=\"ipaddr\" type=\"s\"/>\n"
   54: "      <arg name=\"hwaddr\" type=\"s\"/>\n"
   55: "      <arg name=\"hostname\" type=\"s\"/>\n"
   56: "    </signal>\n"
   57: "    <signal name=\"DhcpLeaseUpdated\">\n"
   58: "      <arg name=\"ipaddr\" type=\"s\"/>\n"
   59: "      <arg name=\"hwaddr\" type=\"s\"/>\n"
   60: "      <arg name=\"hostname\" type=\"s\"/>\n"
   61: "    </signal>\n"
   62: "  </interface>\n"
   63: "</node>\n";
   64: 
   65: static char *introspection_xml = NULL;
   66: 
   67: struct watch {
   68:   DBusWatch *watch;      
   69:   struct watch *next;
   70: };
   71: 
   72: 
   73: static dbus_bool_t add_watch(DBusWatch *watch, void *data)
   74: {
   75:   struct watch *w;
   76: 
   77:   for (w = daemon->watches; w; w = w->next)
   78:     if (w->watch == watch)
   79:       return TRUE;
   80: 
   81:   if (!(w = whine_malloc(sizeof(struct watch))))
   82:     return FALSE;
   83: 
   84:   w->watch = watch;
   85:   w->next = daemon->watches;
   86:   daemon->watches = w;
   87: 
   88:   w = data; /* no warning */
   89:   return TRUE;
   90: }
   91: 
   92: static void remove_watch(DBusWatch *watch, void *data)
   93: {
   94:   struct watch **up, *w, *tmp;  
   95:   
   96:   for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
   97:     {
   98:       tmp = w->next;
   99:       if (w->watch == watch)
  100: 	{
  101: 	  *up = tmp;
  102: 	  free(w);
  103: 	}
  104:       else
  105: 	up = &(w->next);
  106:     }
  107: 
  108:   w = data; /* no warning */
  109: }
  110: 
  111: static void add_update_server(union mysockaddr *addr,
  112:                               union mysockaddr *source_addr,
  113: 			      const char *interface,
  114:                               const char *domain)
  115: {
  116:   struct server *serv;
  117: 
  118:   /* See if there is a suitable candidate, and unmark */
  119:   for (serv = daemon->servers; serv; serv = serv->next)
  120:     if ((serv->flags & SERV_FROM_DBUS) &&
  121:        (serv->flags & SERV_MARK))
  122:       {
  123: 	if (domain)
  124: 	  {
  125: 	    if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
  126: 	      continue;
  127: 	  }
  128: 	else
  129: 	  {
  130: 	    if (serv->flags & SERV_HAS_DOMAIN)
  131: 	      continue;
  132: 	  }
  133: 	
  134: 	serv->flags &= ~SERV_MARK;
  135: 
  136:         break;
  137:       }
  138:   
  139:   if (!serv && (serv = whine_malloc(sizeof (struct server))))
  140:     {
  141:       /* Not found, create a new one. */
  142:       memset(serv, 0, sizeof(struct server));
  143:       
  144:       if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
  145: 	{
  146: 	  free(serv);
  147:           serv = NULL;
  148:         }
  149:       else
  150:         {
  151: 	  serv->next = daemon->servers;
  152: 	  daemon->servers = serv;
  153: 	  serv->flags = SERV_FROM_DBUS;
  154: 	  if (domain)
  155: 	    {
  156: 	      strcpy(serv->domain, domain);
  157: 	      serv->flags |= SERV_HAS_DOMAIN;
  158: 	    }
  159: 	}
  160:     }
  161:   
  162:   if (serv)
  163:     {
  164:       if (interface)
  165: 	strcpy(serv->interface, interface);
  166:       else
  167: 	serv->interface[0] = 0;
  168:             
  169:       if (source_addr->in.sin_family == AF_INET &&
  170:           addr->in.sin_addr.s_addr == 0 &&
  171:           serv->domain)
  172:         serv->flags |= SERV_NO_ADDR;
  173:       else
  174:         {
  175:           serv->flags &= ~SERV_NO_ADDR;
  176:           serv->addr = *addr;
  177:           serv->source_addr = *source_addr;
  178:         }
  179:     }
  180: }
  181: 
  182: static void mark_dbus(void)
  183: {
  184:   struct server *serv;
  185: 
  186:   /* mark everything from DBUS */
  187:   for (serv = daemon->servers; serv; serv = serv->next)
  188:     if (serv->flags & SERV_FROM_DBUS)
  189:       serv->flags |= SERV_MARK;
  190: }
  191: 
  192: static void cleanup_dbus()
  193: {
  194:   struct server *serv, *tmp, **up;
  195: 
  196:   /* unlink and free anything still marked. */
  197:   for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) 
  198:     {
  199:       tmp = serv->next;
  200:       if (serv->flags & SERV_MARK)
  201:        {
  202:          server_gone(serv);
  203:          *up = serv->next;
  204:          if (serv->domain)
  205: 	   free(serv->domain);
  206: 	 free(serv);
  207:        }
  208:       else 
  209:        up = &serv->next;
  210:     }
  211: }
  212: 
  213: static void dbus_read_servers(DBusMessage *message)
  214: {
  215:   DBusMessageIter iter;
  216:   union  mysockaddr addr, source_addr;
  217:   char *domain;
  218:   
  219:   dbus_message_iter_init(message, &iter);
  220: 
  221:   mark_dbus();
  222: 
  223:   while (1)
  224:     {
  225:       int skip = 0;
  226: 
  227:       if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32)
  228: 	{
  229: 	  u32 a;
  230: 	  
  231: 	  dbus_message_iter_get_basic(&iter, &a);
  232: 	  dbus_message_iter_next (&iter);
  233: 	  
  234: #ifdef HAVE_SOCKADDR_SA_LEN
  235: 	  source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
  236: #endif
  237: 	  addr.in.sin_addr.s_addr = ntohl(a);
  238: 	  source_addr.in.sin_family = addr.in.sin_family = AF_INET;
  239: 	  addr.in.sin_port = htons(NAMESERVER_PORT);
  240: 	  source_addr.in.sin_addr.s_addr = INADDR_ANY;
  241: 	  source_addr.in.sin_port = htons(daemon->query_port);
  242: 	}
  243:       else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BYTE)
  244: 	{
  245: 	  unsigned char p[sizeof(struct in6_addr)];
  246: 	  unsigned int i;
  247: 
  248: 	  skip = 1;
  249: 
  250: 	  for(i = 0; i < sizeof(struct in6_addr); i++)
  251: 	    {
  252: 	      dbus_message_iter_get_basic(&iter, &p[i]);
  253: 	      dbus_message_iter_next (&iter);
  254: 	      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
  255: 		break;
  256: 	    }
  257: 
  258: #ifndef HAVE_IPV6
  259: 	  my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
  260: #else
  261: 	  if (i == sizeof(struct in6_addr)-1)
  262: 	    {
  263: 	      memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
  264: #ifdef HAVE_SOCKADDR_SA_LEN
  265:               source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
  266: #endif
  267:               source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
  268:               addr.in6.sin6_port = htons(NAMESERVER_PORT);
  269:               source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
  270: 	      source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0;
  271:               source_addr.in6.sin6_addr = in6addr_any;
  272:               source_addr.in6.sin6_port = htons(daemon->query_port);
  273: 	      skip = 0;
  274: 	    }
  275: #endif
  276: 	}
  277:       else
  278: 	/* At the end */
  279: 	break;
  280:       
  281:       /* process each domain */
  282:       do {
  283: 	if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
  284: 	  {
  285: 	    dbus_message_iter_get_basic(&iter, &domain);
  286: 	    dbus_message_iter_next (&iter);
  287: 	  }
  288: 	else
  289: 	  domain = NULL;
  290: 	
  291: 	if (!skip)
  292: 	  add_update_server(&addr, &source_addr, NULL, domain);
  293:      
  294:       } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING); 
  295:     }
  296:    
  297:   /* unlink and free anything still marked. */
  298:   cleanup_dbus();
  299: }
  300: 
  301: static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
  302: {
  303:   DBusMessageIter iter, array_iter, string_iter;
  304:   DBusMessage *error = NULL;
  305:   const char *addr_err;
  306:   char *dup = NULL;
  307:   
  308:   my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
  309:   
  310:   if (!dbus_message_iter_init(message, &iter))
  311:     {
  312:       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  313:                                     "Failed to initialize dbus message iter");
  314:     }
  315: 
  316:   /* check that the message contains an array of arrays */
  317:   if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
  318:       (dbus_message_iter_get_element_type(&iter) != (strings ? DBUS_TYPE_STRING : DBUS_TYPE_ARRAY)))
  319:     {
  320:       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  321:                                     strings ? "Expected array of string" : "Expected array of string arrays");
  322:      }
  323:  
  324:   mark_dbus();
  325: 
  326:   /* array_iter points to each "as" element in the outer array */
  327:   dbus_message_iter_recurse(&iter, &array_iter);
  328:   while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID)
  329:     {
  330:       const char *str = NULL;
  331:       union  mysockaddr addr, source_addr;
  332:       char interface[IF_NAMESIZE];
  333:       char *str_addr, *str_domain = NULL;
  334: 
  335:       if (strings)
  336: 	{
  337: 	  dbus_message_iter_get_basic(&array_iter, &str);
  338: 	  if (!str || !strlen (str))
  339: 	    {
  340: 	      error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  341: 					     "Empty string");
  342: 	      break;
  343: 	    }
  344: 	  
  345: 	  /* dup the string because it gets modified during parsing */
  346: 	  if (dup)
  347: 	    free(dup);
  348: 	  if (!(dup = str_domain = whine_malloc(strlen(str)+1)))
  349: 	    break;
  350: 	  
  351: 	  strcpy(str_domain, str);
  352: 
  353: 	  /* point to address part of old string for error message */
  354: 	  if ((str_addr = strrchr(str, '/')))
  355: 	    str = str_addr+1;
  356: 	  
  357: 	  if ((str_addr = strrchr(str_domain, '/')))
  358: 	    {
  359: 	      if (*str_domain != '/' || str_addr == str_domain)
  360: 		{
  361: 		  error = dbus_message_new_error_printf(message,
  362: 							DBUS_ERROR_INVALID_ARGS,
  363: 							"No domain terminator '%s'",
  364: 							str);
  365: 		  break;
  366: 		}
  367: 	      *str_addr++ = 0;
  368: 	      str_domain++;
  369: 	    }
  370: 	  else
  371: 	    {
  372: 	      str_addr = str_domain;
  373: 	      str_domain = NULL;
  374: 	    }
  375: 
  376: 	  
  377: 	}
  378:       else
  379: 	{
  380: 	  /* check the types of the struct and its elements */
  381: 	  if ((dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY) ||
  382: 	      (dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_STRING))
  383: 	    {
  384: 	      error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  385: 					     "Expected inner array of strings");
  386: 	      break;
  387: 	    }
  388: 	  
  389: 	  /* string_iter points to each "s" element in the inner array */
  390: 	  dbus_message_iter_recurse(&array_iter, &string_iter);
  391: 	  if (dbus_message_iter_get_arg_type(&string_iter) != DBUS_TYPE_STRING)
  392: 	    {
  393: 	      /* no IP address given */
  394: 	      error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  395: 					     "Expected IP address");
  396: 	      break;
  397: 	    }
  398: 	  
  399: 	  dbus_message_iter_get_basic(&string_iter, &str);
  400: 	  if (!str || !strlen (str))
  401: 	    {
  402: 	      error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  403: 					     "Empty IP address");
  404: 	      break;
  405: 	    }
  406: 	  
  407: 	  /* dup the string because it gets modified during parsing */
  408: 	  if (dup)
  409: 	    free(dup);
  410: 	  if (!(dup = str_addr = whine_malloc(strlen(str)+1)))
  411: 	    break;
  412: 	  
  413: 	  strcpy(str_addr, str);
  414: 	}
  415: 
  416:       memset(&addr, 0, sizeof(addr));
  417:       memset(&source_addr, 0, sizeof(source_addr));
  418:       memset(&interface, 0, sizeof(interface));
  419: 
  420:       /* parse the IP address */
  421:       addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL);
  422: 
  423:       if (addr_err)
  424:         {
  425:           error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
  426:                                                 "Invalid IP address '%s': %s",
  427:                                                 str, addr_err);
  428:           break;
  429:         }
  430: 
  431:       if (strings)
  432: 	{
  433: 	  char *p;
  434: 	  
  435: 	  do {
  436: 	    if (str_domain)
  437: 	      {
  438: 		if ((p = strchr(str_domain, '/')))
  439: 		  *p++ = 0;
  440: 	      }
  441: 	    else 
  442: 	      p = NULL;
  443: 	    
  444: 	    add_update_server(&addr, &source_addr, interface, str_domain);
  445: 	  } while ((str_domain = p));
  446: 	}
  447:       else
  448: 	{
  449: 	  /* jump past the address to the domain list (if any) */
  450: 	  dbus_message_iter_next (&string_iter);
  451: 	  
  452: 	  /* parse domains and add each server/domain pair to the list */
  453: 	  do {
  454: 	    str = NULL;
  455: 	    if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
  456: 	      dbus_message_iter_get_basic(&string_iter, &str);
  457: 	    dbus_message_iter_next (&string_iter);
  458: 	    
  459: 	    add_update_server(&addr, &source_addr, interface, str);
  460: 	  } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
  461: 	}
  462: 	 
  463:       /* jump to next element in outer array */
  464:       dbus_message_iter_next(&array_iter);
  465:     }
  466: 
  467:   cleanup_dbus();
  468: 
  469:   if (dup)
  470:     free(dup);
  471: 
  472:   return error;
  473: }
  474: 
  475: DBusHandlerResult message_handler(DBusConnection *connection, 
  476: 				  DBusMessage *message, 
  477: 				  void *user_data)
  478: {
  479:   char *method = (char *)dbus_message_get_member(message);
  480:   DBusMessage *reply = NULL;
  481:     
  482:   if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
  483:     {
  484:       /* string length: "%s" provides space for termination zero */
  485:       if (!introspection_xml && 
  486: 	  (introspection_xml = whine_malloc(strlen(introspection_xml_template) + strlen(daemon->dbus_name))))
  487: 	sprintf(introspection_xml, introspection_xml_template, daemon->dbus_name);
  488:     
  489:       if (introspection_xml)
  490: 	{
  491: 	  reply = dbus_message_new_method_return(message);
  492: 	  dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
  493: 	}
  494:     }
  495:   else if (strcmp(method, "GetVersion") == 0)
  496:     {
  497:       char *v = VERSION;
  498:       reply = dbus_message_new_method_return(message);
  499:       
  500:       dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
  501:     }
  502:   else if (strcmp(method, "SetServers") == 0)
  503:     {
  504:       my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
  505:       dbus_read_servers(message);
  506:       check_servers();
  507:     }
  508:   else if (strcmp(method, "SetServersEx") == 0)
  509:     {
  510:       reply = dbus_read_servers_ex(message, 0);
  511:       check_servers();
  512:     }
  513:   else if (strcmp(method, "SetDomainServers") == 0)
  514:     {
  515:       reply = dbus_read_servers_ex(message, 1);
  516:       check_servers();
  517:     }
  518:   else if (strcmp(method, "ClearCache") == 0)
  519:     clear_cache_and_reload(dnsmasq_time());
  520:   else
  521:     return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
  522:   
  523:   method = user_data; /* no warning */
  524: 
  525:   /* If no reply or no error, return nothing */
  526:   if (!reply)
  527:     reply = dbus_message_new_method_return(message);
  528: 
  529:   if (reply)
  530:     {
  531:       dbus_connection_send (connection, reply, NULL);
  532:       dbus_message_unref (reply);
  533:     }
  534: 
  535:   return (DBUS_HANDLER_RESULT_HANDLED);
  536: }
  537:  
  538: 
  539: /* returns NULL or error message, may fail silently if dbus daemon not yet up. */
  540: char *dbus_init(void)
  541: {
  542:   DBusConnection *connection = NULL;
  543:   DBusObjectPathVTable dnsmasq_vtable = {NULL, &message_handler, NULL, NULL, NULL, NULL };
  544:   DBusError dbus_error;
  545:   DBusMessage *message;
  546: 
  547:   dbus_error_init (&dbus_error);
  548:   if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
  549:     return NULL;
  550:     
  551:   dbus_connection_set_exit_on_disconnect(connection, FALSE);
  552:   dbus_connection_set_watch_functions(connection, add_watch, remove_watch, 
  553: 				      NULL, NULL, NULL);
  554:   dbus_error_init (&dbus_error);
  555:   dbus_bus_request_name (connection, daemon->dbus_name, 0, &dbus_error);
  556:   if (dbus_error_is_set (&dbus_error))
  557:     return (char *)dbus_error.message;
  558:   
  559:   if (!dbus_connection_register_object_path(connection,  DNSMASQ_PATH, 
  560: 					    &dnsmasq_vtable, NULL))
  561:     return _("could not register a DBus message handler");
  562:   
  563:   daemon->dbus = connection; 
  564:   
  565:   if ((message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, "Up")))
  566:     {
  567:       dbus_connection_send(connection, message, NULL);
  568:       dbus_message_unref(message);
  569:     }
  570: 
  571:   return NULL;
  572: }
  573:  
  574: 
  575: void set_dbus_listeners(int *maxfdp,
  576: 			fd_set *rset, fd_set *wset, fd_set *eset)
  577: {
  578:   struct watch *w;
  579:   
  580:   for (w = daemon->watches; w; w = w->next)
  581:     if (dbus_watch_get_enabled(w->watch))
  582:       {
  583: 	unsigned int flags = dbus_watch_get_flags(w->watch);
  584: 	int fd = dbus_watch_get_unix_fd(w->watch);
  585: 	
  586: 	bump_maxfd(fd, maxfdp);
  587: 	
  588: 	if (flags & DBUS_WATCH_READABLE)
  589: 	  FD_SET(fd, rset);
  590: 	
  591: 	if (flags & DBUS_WATCH_WRITABLE)
  592: 	  FD_SET(fd, wset);
  593: 	
  594: 	FD_SET(fd, eset);
  595:       }
  596: }
  597: 
  598: void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
  599: {
  600:   DBusConnection *connection = (DBusConnection *)daemon->dbus;
  601:   struct watch *w;
  602: 
  603:   for (w = daemon->watches; w; w = w->next)
  604:     if (dbus_watch_get_enabled(w->watch))
  605:       {
  606: 	unsigned int flags = 0;
  607: 	int fd = dbus_watch_get_unix_fd(w->watch);
  608: 	
  609: 	if (FD_ISSET(fd, rset))
  610: 	  flags |= DBUS_WATCH_READABLE;
  611: 	
  612: 	if (FD_ISSET(fd, wset))
  613: 	  flags |= DBUS_WATCH_WRITABLE;
  614: 	
  615: 	if (FD_ISSET(fd, eset))
  616: 	  flags |= DBUS_WATCH_ERROR;
  617: 
  618: 	if (flags != 0)
  619: 	  dbus_watch_handle(w->watch, flags);
  620:       }
  621: 
  622:   if (connection)
  623:     {
  624:       dbus_connection_ref (connection);
  625:       while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS);
  626:       dbus_connection_unref (connection);
  627:     }
  628: }
  629: 
  630: #ifdef HAVE_DHCP
  631: void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
  632: {
  633:   DBusConnection *connection = (DBusConnection *)daemon->dbus;
  634:   DBusMessage* message = NULL;
  635:   DBusMessageIter args;
  636:   char *action_str, *mac = daemon->namebuff;
  637:   unsigned char *p;
  638:   int i;
  639: 
  640:   if (!connection)
  641:     return;
  642:   
  643:   if (!hostname)
  644:     hostname = "";
  645:   
  646: #ifdef HAVE_DHCP6
  647:    if (lease->flags & (LEASE_TA | LEASE_NA))
  648:      {
  649:        print_mac(mac, lease->clid, lease->clid_len);
  650:        inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);
  651:      }
  652:    else
  653: #endif
  654:      {
  655:        p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
  656: 			   lease->hwaddr, lease->clid_len, lease->clid, &i);
  657:        print_mac(mac, p, i);
  658:        inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN);
  659:      }
  660: 
  661:   if (action == ACTION_DEL)
  662:     action_str = "DhcpLeaseDeleted";
  663:   else if (action == ACTION_ADD)
  664:     action_str = "DhcpLeaseAdded";
  665:   else if (action == ACTION_OLD)
  666:     action_str = "DhcpLeaseUpdated";
  667:   else
  668:     return;
  669: 
  670:   if (!(message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, action_str)))
  671:     return;
  672:   
  673:   dbus_message_iter_init_append(message, &args);
  674:   
  675:   if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &daemon->addrbuff) &&
  676:       dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
  677:       dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
  678:     dbus_connection_send(connection, message, NULL);
  679:   
  680:   dbus_message_unref(message);
  681: }
  682: #endif
  683: 
  684: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>