Diff for /embedaddon/dnsmasq/src/dbus.c between versions 1.1.1.1 and 1.1.1.5

version 1.1.1.1, 2013/07/29 19:37:40 version 1.1.1.5, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
Line 35  const char* introspection_xml_template = Line 35  const char* introspection_xml_template =
 "    <method name=\"GetVersion\">\n"  "    <method name=\"GetVersion\">\n"
 "      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"  "      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
 "    </method>\n"  "    </method>\n"
   #ifdef HAVE_LOOP
   "    <method name=\"GetLoopServers\">\n"
   "      <arg name=\"server\" direction=\"out\" type=\"as\"/>\n"
   "    </method>\n"
   #endif
 "    <method name=\"SetServers\">\n"  "    <method name=\"SetServers\">\n"
 "      <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"  "      <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
 "    </method>\n"  "    </method>\n"
Line 44  const char* introspection_xml_template = Line 49  const char* introspection_xml_template =
 "    <method name=\"SetServersEx\">\n"  "    <method name=\"SetServersEx\">\n"
 "      <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"  "      <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
 "    </method>\n"  "    </method>\n"
   "    <method name=\"SetFilterWin2KOption\">\n"
   "      <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
   "    </method>\n"
   "    <method name=\"SetLocaliseQueriesOption\">\n"
   "      <arg name=\"localise-queries\" direction=\"in\" type=\"b\"/>\n"
   "    </method>\n"
   "    <method name=\"SetBogusPrivOption\">\n"
   "      <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
   "    </method>\n"
 "    <signal name=\"DhcpLeaseAdded\">\n"  "    <signal name=\"DhcpLeaseAdded\">\n"
 "      <arg name=\"ipaddr\" type=\"s\"/>\n"  "      <arg name=\"ipaddr\" type=\"s\"/>\n"
 "      <arg name=\"hwaddr\" type=\"s\"/>\n"  "      <arg name=\"hwaddr\" type=\"s\"/>\n"
Line 59  const char* introspection_xml_template = Line 73  const char* introspection_xml_template =
 "      <arg name=\"hwaddr\" type=\"s\"/>\n"  "      <arg name=\"hwaddr\" type=\"s\"/>\n"
 "      <arg name=\"hostname\" type=\"s\"/>\n"  "      <arg name=\"hostname\" type=\"s\"/>\n"
 "    </signal>\n"  "    </signal>\n"
   #ifdef HAVE_DHCP
   "    <method name=\"AddDhcpLease\">\n"
   "       <arg name=\"ipaddr\" type=\"s\"/>\n"
   "       <arg name=\"hwaddr\" type=\"s\"/>\n"
   "       <arg name=\"hostname\" type=\"ay\"/>\n"
   "       <arg name=\"clid\" type=\"ay\"/>\n"
   "       <arg name=\"lease_duration\" type=\"u\"/>\n"
   "       <arg name=\"ia_id\" type=\"u\"/>\n"
   "       <arg name=\"is_temporary\" type=\"b\"/>\n"
   "    </method>\n"
   "    <method name=\"DeleteDhcpLease\">\n"
   "       <arg name=\"ipaddr\" type=\"s\"/>\n"
   "       <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
   "    </method>\n"
   #endif
   "    <method name=\"GetMetrics\">\n"
   "      <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
   "    </method>\n"
   "    <method name=\"GetServerMetrics\">\n"
   "      <arg name=\"metrics\" direction=\"out\" type=\"a{ss}\"/>\n"
   "    </method>\n"
   "    <method name=\"ClearMetrics\">\n"
   "    </method>\n"
 "  </interface>\n"  "  </interface>\n"
 "</node>\n";  "</node>\n";
   
Line 85  static dbus_bool_t add_watch(DBusWatch *watch, void *d Line 122  static dbus_bool_t add_watch(DBusWatch *watch, void *d
   w->next = daemon->watches;    w->next = daemon->watches;
   daemon->watches = w;    daemon->watches = w;
   
  w = data; /* no warning */  (void)data; /* no warning */
   return TRUE;    return TRUE;
 }  }
   
Line 105  static void remove_watch(DBusWatch *watch, void *data) Line 142  static void remove_watch(DBusWatch *watch, void *data)
         up = &(w->next);          up = &(w->next);
     }      }
   
  w = data; /* no warning */  (void)data; /* no warning */
 }  }
   
static void add_update_server(union mysockaddr *addr,static DBusMessage* dbus_read_servers(DBusMessage *message)
                              union mysockaddr *source_addr, 
                              const char *interface, 
                              const char *domain) 
 {  {
   struct server *serv;  
   
   /* See if there is a suitable candidate, and unmark */  
   for (serv = daemon->servers; serv; serv = serv->next)  
     if ((serv->flags & SERV_FROM_DBUS) &&  
        (serv->flags & SERV_MARK))  
       {  
         if (domain)  
           {  
             if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))  
               continue;  
           }  
         else  
           {  
             if (serv->flags & SERV_HAS_DOMAIN)  
               continue;  
           }  
           
         serv->flags &= ~SERV_MARK;  
   
         break;  
       }  
     
   if (!serv && (serv = whine_malloc(sizeof (struct server))))  
     {  
       /* Not found, create a new one. */  
       memset(serv, 0, sizeof(struct server));  
         
       if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))  
         {  
           free(serv);  
           serv = NULL;  
         }  
       else  
         {  
           serv->next = daemon->servers;  
           daemon->servers = serv;  
           serv->flags = SERV_FROM_DBUS;  
           if (domain)  
             {  
               strcpy(serv->domain, domain);  
               serv->flags |= SERV_HAS_DOMAIN;  
             }  
         }  
     }  
     
   if (serv)  
     {  
       if (interface)  
         strcpy(serv->interface, interface);  
       else  
         serv->interface[0] = 0;  
               
       if (source_addr->in.sin_family == AF_INET &&  
           addr->in.sin_addr.s_addr == 0 &&  
           serv->domain)  
         serv->flags |= SERV_NO_ADDR;  
       else  
         {  
           serv->flags &= ~SERV_NO_ADDR;  
           serv->addr = *addr;  
           serv->source_addr = *source_addr;  
         }  
     }  
 }  
   
 static void mark_dbus(void)  
 {  
   struct server *serv;  
   
   /* mark everything from DBUS */  
   for (serv = daemon->servers; serv; serv = serv->next)  
     if (serv->flags & SERV_FROM_DBUS)  
       serv->flags |= SERV_MARK;  
 }  
   
 static void cleanup_dbus()  
 {  
   struct server *serv, *tmp, **up;  
   
   /* unlink and free anything still marked. */  
   for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)   
     {  
       tmp = serv->next;  
       if (serv->flags & SERV_MARK)  
        {  
          server_gone(serv);  
          *up = serv->next;  
          if (serv->domain)  
            free(serv->domain);  
          free(serv);  
        }  
       else   
        up = &serv->next;  
     }  
 }  
   
 static void dbus_read_servers(DBusMessage *message)  
 {  
   DBusMessageIter iter;    DBusMessageIter iter;
   union  mysockaddr addr, source_addr;    union  mysockaddr addr, source_addr;
   char *domain;    char *domain;
       
  dbus_message_iter_init(message, &iter);  if (!dbus_message_iter_init(message, &iter))
     {
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Failed to initialize dbus message iter");
     }
   
  mark_dbus();  mark_servers(SERV_FROM_DBUS);
  
   while (1)    while (1)
     {      {
       int skip = 0;        int skip = 0;
Line 252  static void dbus_read_servers(DBusMessage *message) Line 191  static void dbus_read_servers(DBusMessage *message)
               dbus_message_iter_get_basic(&iter, &p[i]);                dbus_message_iter_get_basic(&iter, &p[i]);
               dbus_message_iter_next (&iter);                dbus_message_iter_next (&iter);
               if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)                if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
                break;                {
                   i++;
                   break;
                 }
             }              }
   
#ifndef HAVE_IPV6          if (i == sizeof(struct in6_addr))
          my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support")); 
#else 
          if (i == sizeof(struct in6_addr)-1) 
             {              {
               memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));                memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
 #ifdef HAVE_SOCKADDR_SA_LEN  #ifdef HAVE_SOCKADDR_SA_LEN
Line 272  static void dbus_read_servers(DBusMessage *message) Line 211  static void dbus_read_servers(DBusMessage *message)
               source_addr.in6.sin6_port = htons(daemon->query_port);                source_addr.in6.sin6_port = htons(daemon->query_port);
               skip = 0;                skip = 0;
             }              }
 #endif  
         }          }
       else        else
         /* At the end */          /* At the end */
Line 289  static void dbus_read_servers(DBusMessage *message) Line 227  static void dbus_read_servers(DBusMessage *message)
           domain = NULL;            domain = NULL;
                   
         if (!skip)          if (!skip)
          add_update_server(&addr, &source_addr, NULL, domain);          add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain, NULL);
             
       } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);         } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING); 
     }      }
         
   /* unlink and free anything still marked. */    /* unlink and free anything still marked. */
  cleanup_dbus();  cleanup_servers();
   return NULL;
 }  }
   
   #ifdef HAVE_LOOP
   static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
   {
     DBusMessageIter args, args_iter;
     struct server *serv;
     DBusMessage *reply = dbus_message_new_method_return(message);
      
     dbus_message_iter_init_append (reply, &args);
     dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING, &args_iter);
   
     for (serv = daemon->servers; serv; serv = serv->next)
       if (serv->flags & SERV_LOOP)
         {
           (void)prettyprint_addr(&serv->addr, daemon->addrbuff);
           dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
         }
     
     dbus_message_iter_close_container (&args, &args_iter);
   
     return reply;
   }
   #endif
   
 static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)  static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 {  {
   DBusMessageIter iter, array_iter, string_iter;    DBusMessageIter iter, array_iter, string_iter;
Line 305  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 267  static DBusMessage* dbus_read_servers_ex(DBusMessage *
   const char *addr_err;    const char *addr_err;
   char *dup = NULL;    char *dup = NULL;
       
   my_syslog(LOG_INFO, _("setting upstream servers from DBus"));  
     
   if (!dbus_message_iter_init(message, &iter))    if (!dbus_message_iter_init(message, &iter))
     {      {
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,        return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
Line 321  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 281  static DBusMessage* dbus_read_servers_ex(DBusMessage *
                                     strings ? "Expected array of string" : "Expected array of string arrays");                                      strings ? "Expected array of string" : "Expected array of string arrays");
      }       }
     
  mark_dbus();  mark_servers(SERV_FROM_DBUS);
   
   /* array_iter points to each "as" element in the outer array */    /* array_iter points to each "as" element in the outer array */
   dbus_message_iter_recurse(&iter, &array_iter);    dbus_message_iter_recurse(&iter, &array_iter);
Line 329  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 289  static DBusMessage* dbus_read_servers_ex(DBusMessage *
     {      {
       const char *str = NULL;        const char *str = NULL;
       union  mysockaddr addr, source_addr;        union  mysockaddr addr, source_addr;
         u16 flags = 0;
       char interface[IF_NAMESIZE];        char interface[IF_NAMESIZE];
       char *str_addr, *str_domain = NULL;        char *str_addr, *str_domain = NULL;
         struct server_details sdetails = { 0 };
         sdetails.addr = &addr;
         sdetails.source_addr = &source_addr;
         sdetails.interface = interface;
         sdetails.flags = &flags;
   
       if (strings)        if (strings)
         {          {
Line 413  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 379  static DBusMessage* dbus_read_servers_ex(DBusMessage *
           strcpy(str_addr, str);            strcpy(str_addr, str);
         }          }
   
       memset(&addr, 0, sizeof(addr));  
       memset(&source_addr, 0, sizeof(source_addr));  
       memset(&interface, 0, sizeof(interface));  
   
       /* parse the IP address */  
       addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL);  
   
       if (addr_err)  
         {  
           error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,  
                                                 "Invalid IP address '%s': %s",  
                                                 str, addr_err);  
           break;  
         }  
   
       if (strings)        if (strings)
         {          {
           char *p;            char *p;
Line 441  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 392  static DBusMessage* dbus_read_servers_ex(DBusMessage *
             else               else 
               p = NULL;                p = NULL;
                           
            add_update_server(&addr, &source_addr, interface, str_domain);             if (strings && strlen(str_addr) == 0)
                add_update_server(SERV_LITERAL_ADDRESS | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
              else
                {
                  if ((addr_err = parse_server(str_addr, &sdetails)))
                    {
                      error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                                            "Invalid IP address '%s': %s",
                                                            str, addr_err);
                      break;
                    }
                  
                  while (parse_server_next(&sdetails))
                    {
                      if ((addr_err = parse_server_addr(&sdetails)))
                        {
                          error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                                                "Invalid IP address '%s': %s",
                                                                str, addr_err);
                          break;
                        }
                      
                      add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
                    }
                }
           } while ((str_domain = p));            } while ((str_domain = p));
         }          }
       else        else
Line 455  static DBusMessage* dbus_read_servers_ex(DBusMessage * Line 430  static DBusMessage* dbus_read_servers_ex(DBusMessage *
             if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)              if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
               dbus_message_iter_get_basic(&string_iter, &str);                dbus_message_iter_get_basic(&string_iter, &str);
             dbus_message_iter_next (&string_iter);              dbus_message_iter_next (&string_iter);
   
               if ((addr_err = parse_server(str_addr, &sdetails)))
                 {
                   error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                                         "Invalid IP address '%s': %s",
                                                         str, addr_err);
                   break;
                 }
                           
            add_update_server(&addr, &source_addr, interface, str);            while (parse_server_next(&sdetails))
               {
                 if ((addr_err = parse_server_addr(&sdetails)))
                   {
                     error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                                           "Invalid IP address '%s': %s",
                                                           str, addr_err);
                     break;
                   }
                 
                 /* 0.0.0.0 for server address == NULL, for Dbus */
                 if (addr.in.sin_family == AF_INET &&
                     addr.in.sin_addr.s_addr == 0)
                   flags |= SERV_LITERAL_ADDRESS;
                 else
                   flags &= ~SERV_LITERAL_ADDRESS;
                 
                 add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
               }
           } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);            } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
         }          }
               
       if (sdetails.orig_hostinfo)
         freeaddrinfo(sdetails.orig_hostinfo);
       
       /* jump to next element in outer array */        /* jump to next element in outer array */
       dbus_message_iter_next(&array_iter);        dbus_message_iter_next(&array_iter);
     }      }
   
  cleanup_dbus();  cleanup_servers();
    
   if (dup)    if (dup)
     free(dup);      free(dup);
   
   return error;    return error;
 }  }
   
   static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
   {
     DBusMessageIter iter;
     dbus_bool_t enabled;
   
     if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected boolean argument");
     
     dbus_message_iter_get_basic(&iter, &enabled);
   
     if (enabled)
       { 
         my_syslog(LOG_INFO, _("Enabling --%s option from D-Bus"), name);
         set_option_bool(flag);
       }
     else
       {
         my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
         reset_option_bool(flag);
       }
   
     return NULL;
   }
   
   #ifdef HAVE_DHCP
   static DBusMessage *dbus_add_lease(DBusMessage* message)
   {
     struct dhcp_lease *lease;
     const char *ipaddr, *hwaddr, *hostname, *tmp;
     const unsigned char* clid;
     int clid_len, hostname_len, hw_len, hw_type;
     dbus_uint32_t expires, ia_id;
     dbus_bool_t is_temporary;
     union all_addr addr;
     time_t now = dnsmasq_time();
     unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
   
     DBusMessageIter iter, array_iter;
     if (!dbus_message_iter_init(message, &iter))
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Failed to initialize dbus message iter");
   
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected string as first argument");
   
     dbus_message_iter_get_basic(&iter, &ipaddr);
     dbus_message_iter_next(&iter);
   
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected string as second argument");
       
     dbus_message_iter_get_basic(&iter, &hwaddr);
     dbus_message_iter_next(&iter);
   
     if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
         (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected byte array as third argument");
       
     dbus_message_iter_recurse(&iter, &array_iter);
     dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
     tmp = memchr(hostname, '\0', hostname_len);
     if (tmp)
       {
         if (tmp == &hostname[hostname_len - 1])
           hostname_len--;
         else
           return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                         "Hostname contains an embedded NUL character");
       }
     dbus_message_iter_next(&iter);
   
     if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
         (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected byte array as fourth argument");
   
     dbus_message_iter_recurse(&iter, &array_iter);
     dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
     dbus_message_iter_next(&iter);
   
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected uint32 as fifth argument");
       
     dbus_message_iter_get_basic(&iter, &expires);
     dbus_message_iter_next(&iter);
   
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                       "Expected uint32 as sixth argument");
     
     dbus_message_iter_get_basic(&iter, &ia_id);
     dbus_message_iter_next(&iter);
   
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected uint32 as sixth argument");
   
     dbus_message_iter_get_basic(&iter, &is_temporary);
   
     if (inet_pton(AF_INET, ipaddr, &addr.addr4))
       {
         if (ia_id != 0 || is_temporary)
           return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                         "ia_id and is_temporary must be zero for IPv4 lease");
         
         if (!(lease = lease_find_by_addr(addr.addr4)))
           lease = lease4_allocate(addr.addr4);
       }
   #ifdef HAVE_DHCP6
     else if (inet_pton(AF_INET6, ipaddr, &addr.addr6))
       {
         if (!(lease = lease6_find_by_addr(&addr.addr6, 128, 0)))
           lease = lease6_allocate(&addr.addr6,
                                   is_temporary ? LEASE_TA : LEASE_NA);
         lease_set_iaid(lease, ia_id);
       }
   #endif
     else
       return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                            "Invalid IP address '%s'", ipaddr);
      
     hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
     if (hw_len < 0)
       return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                            "Invalid HW address '%s'", hwaddr);
   
     if (hw_type == 0 && hw_len != 0)
       hw_type = ARPHRD_ETHER;
     
     lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
                      clid_len, now, 0);
     lease_set_expires(lease, expires, now);
     if (hostname_len != 0)
       lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
     
     lease_update_file(now);
     lease_update_dns(0);
   
     return NULL;
   }
   
   static DBusMessage *dbus_del_lease(DBusMessage* message)
   {
     struct dhcp_lease *lease;
     DBusMessageIter iter;
     const char *ipaddr;
     DBusMessage *reply;
     union all_addr addr;
     dbus_bool_t ret = 1;
     time_t now = dnsmasq_time();
   
     if (!dbus_message_iter_init(message, &iter))
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Failed to initialize dbus message iter");
      
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                     "Expected string as first argument");
      
     dbus_message_iter_get_basic(&iter, &ipaddr);
   
     if (inet_pton(AF_INET, ipaddr, &addr.addr4))
       lease = lease_find_by_addr(addr.addr4);
   #ifdef HAVE_DHCP6
     else if (inet_pton(AF_INET6, ipaddr, &addr.addr6))
       lease = lease6_find_by_addr(&addr.addr6, 128, 0);
   #endif
     else
       return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                            "Invalid IP address '%s'", ipaddr);
       
     if (lease)
       {
         lease_prune(lease, now);
         lease_update_file(now);
         lease_update_dns(0);
       }
     else
       ret = 0;
     
     if ((reply = dbus_message_new_method_return(message)))
       dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
                                DBUS_TYPE_INVALID);
     
       
     return reply;
   }
   #endif
   
   static DBusMessage *dbus_get_metrics(DBusMessage* message)
   {
     DBusMessage *reply = dbus_message_new_method_return(message);
     DBusMessageIter array, dict, iter;
     int i;
   
     dbus_message_iter_init_append(reply, &iter);
     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
   
     for (i = 0; i < __METRIC_MAX; i++) {
       const char *key     = get_metric_name(i);
       dbus_uint32_t value = daemon->metrics[i];
   
       dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
       dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
       dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
       dbus_message_iter_close_container(&array, &dict);
     }
   
     dbus_message_iter_close_container(&iter, &array);
   
     return reply;
   }
   
   static void add_dict_entry(DBusMessageIter *container, const char *key, const char *val)
   {
     DBusMessageIter dict;
   
     dbus_message_iter_open_container(container, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
     dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
     dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &val);
     dbus_message_iter_close_container(container, &dict);
   }
   
   static void add_dict_int(DBusMessageIter *container, const char *key, const unsigned int val)
   {
     snprintf(daemon->namebuff, MAXDNAME, "%u", val);
     
     add_dict_entry(container, key, daemon->namebuff);
   }
   
   static DBusMessage *dbus_get_server_metrics(DBusMessage* message)
   {
     DBusMessage *reply = dbus_message_new_method_return(message);
     DBusMessageIter server_array, dict_array, server_iter;
     struct server *serv;
     
     dbus_message_iter_init_append(reply, &server_iter);
     dbus_message_iter_open_container(&server_iter, DBUS_TYPE_ARRAY, "a{ss}", &server_array);
   
     /* sum counts from different records for same server */
     for (serv = daemon->servers; serv; serv = serv->next)
       serv->flags &= ~SERV_MARK;
     
     for (serv = daemon->servers; serv; serv = serv->next)
       if (!(serv->flags & SERV_MARK))
         {
           unsigned int port;
           unsigned int queries = 0, failed_queries = 0, nxdomain_replies = 0, retrys = 0;
           unsigned int sigma_latency = 0, count_latency = 0;
           
           struct server *serv1;
   
           for (serv1 = serv; serv1; serv1 = serv1->next)
             if (!(serv1->flags & SERV_MARK) && sockaddr_isequal(&serv->addr, &serv1->addr))
               {
                 serv1->flags |= SERV_MARK;
                 queries += serv1->queries;
                 failed_queries += serv1->failed_queries;
                 nxdomain_replies += serv1->nxdomain_replies;
                 retrys += serv1->retrys;
                 sigma_latency += serv1->query_latency;
                 count_latency++;
               }
           
           dbus_message_iter_open_container(&server_array, DBUS_TYPE_ARRAY, "{ss}", &dict_array);
           
           port = prettyprint_addr(&serv->addr, daemon->namebuff);
           add_dict_entry(&dict_array, "address", daemon->namebuff);
           
           add_dict_int(&dict_array, "port", port);
           add_dict_int(&dict_array, "queries", serv->queries);
           add_dict_int(&dict_array, "failed_queries", serv->failed_queries);
           add_dict_int(&dict_array, "nxdomain", serv->nxdomain_replies);
           add_dict_int(&dict_array, "retries", serv->retrys);
           add_dict_int(&dict_array, "latency", sigma_latency/count_latency);
           
           dbus_message_iter_close_container(&server_array, &dict_array);
         }
     
     dbus_message_iter_close_container(&server_iter, &server_array);
     
     return reply;
   }
   
 DBusHandlerResult message_handler(DBusConnection *connection,   DBusHandlerResult message_handler(DBusConnection *connection, 
                                   DBusMessage *message,                                     DBusMessage *message, 
                                   void *user_data)                                    void *user_data)
 {  {
   char *method = (char *)dbus_message_get_member(message);    char *method = (char *)dbus_message_get_member(message);
   DBusMessage *reply = NULL;    DBusMessage *reply = NULL;
     int clear_cache = 0, new_servers = 0;
           
   if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))    if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
     {      {
Line 499  DBusHandlerResult message_handler(DBusConnection *conn Line 792  DBusHandlerResult message_handler(DBusConnection *conn
               
       dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);        dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
     }      }
   #ifdef HAVE_LOOP
     else if (strcmp(method, "GetLoopServers") == 0)
       {
         reply = dbus_reply_server_loop(message);
       }
   #endif
   else if (strcmp(method, "SetServers") == 0)    else if (strcmp(method, "SetServers") == 0)
     {      {
      my_syslog(LOG_INFO, _("setting upstream servers from DBus"));      reply = dbus_read_servers(message);
      dbus_read_servers(message);      new_servers = 1;
      check_servers(); 
     }      }
   else if (strcmp(method, "SetServersEx") == 0)    else if (strcmp(method, "SetServersEx") == 0)
     {      {
       reply = dbus_read_servers_ex(message, 0);        reply = dbus_read_servers_ex(message, 0);
      check_servers();      new_servers = 1;
     }      }
   else if (strcmp(method, "SetDomainServers") == 0)    else if (strcmp(method, "SetDomainServers") == 0)
     {      {
       reply = dbus_read_servers_ex(message, 1);        reply = dbus_read_servers_ex(message, 1);
      check_servers();      new_servers = 1;
     }      }
     else if (strcmp(method, "SetFilterWin2KOption") == 0)
       {
         reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
       }
     else if (strcmp(method, "SetLocaliseQueriesOption") == 0)
       {
         reply = dbus_set_bool(message, OPT_LOCALISE, "localise-queries");
       }
     else if (strcmp(method, "SetBogusPrivOption") == 0)
       {
         reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
       }
   #ifdef HAVE_DHCP
     else if (strcmp(method, "AddDhcpLease") == 0)
       {
         reply = dbus_add_lease(message);
       }
     else if (strcmp(method, "DeleteDhcpLease") == 0)
       {
         reply = dbus_del_lease(message);
       }
   #endif
     else if (strcmp(method, "GetMetrics") == 0)
       {
         reply = dbus_get_metrics(message);
       }
     else if (strcmp(method, "GetServerMetrics") == 0)
       {
         reply = dbus_get_server_metrics(message);
       }
     else if (strcmp(method, "ClearMetrics") == 0)
       {
         clear_metrics();
       }
   else if (strcmp(method, "ClearCache") == 0)    else if (strcmp(method, "ClearCache") == 0)
    clear_cache_and_reload(dnsmasq_time());    clear_cache = 1;
   else    else
     return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);      return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
      
     if (new_servers)
       {
         my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
         check_servers(0);
         if (option_bool(OPT_RELOAD))
           clear_cache = 1;
       }
   
     if (clear_cache)
       clear_cache_and_reload(dnsmasq_time());
       
  method = user_data; /* no warning */  (void)user_data; /* no warning */
   
   /* If no reply or no error, return nothing */    /* If no reply or no error, return nothing */
   if (!reply)    if (!reply)
Line 546  char *dbus_init(void) Line 889  char *dbus_init(void)
   
   dbus_error_init (&dbus_error);    dbus_error_init (&dbus_error);
   if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))    if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
    return NULL;    {
          dbus_error_free(&dbus_error);
       return NULL;
     }
   
   dbus_connection_set_exit_on_disconnect(connection, FALSE);    dbus_connection_set_exit_on_disconnect(connection, FALSE);
   dbus_connection_set_watch_functions(connection, add_watch, remove_watch,     dbus_connection_set_watch_functions(connection, add_watch, remove_watch, 
                                       NULL, NULL, NULL);                                        NULL, NULL, NULL);
Line 572  char *dbus_init(void) Line 918  char *dbus_init(void)
 }  }
     
   
void set_dbus_listeners(int *maxfdp,void set_dbus_listeners(void)
                        fd_set *rset, fd_set *wset, fd_set *eset) 
 {  {
   struct watch *w;    struct watch *w;
       
Line 583  void set_dbus_listeners(int *maxfdp, Line 928  void set_dbus_listeners(int *maxfdp,
         unsigned int flags = dbus_watch_get_flags(w->watch);          unsigned int flags = dbus_watch_get_flags(w->watch);
         int fd = dbus_watch_get_unix_fd(w->watch);          int fd = dbus_watch_get_unix_fd(w->watch);
                   
         bump_maxfd(fd, maxfdp);  
           
         if (flags & DBUS_WATCH_READABLE)          if (flags & DBUS_WATCH_READABLE)
          FD_SET(fd, rset);          poll_listen(fd, POLLIN);
                   
         if (flags & DBUS_WATCH_WRITABLE)          if (flags & DBUS_WATCH_WRITABLE)
          FD_SET(fd, wset);          poll_listen(fd, POLLOUT);
                   
        FD_SET(fd, eset);        poll_listen(fd, POLLERR);
       }        }
 }  }
   
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)void check_dbus_listeners()
 {  {
   DBusConnection *connection = (DBusConnection *)daemon->dbus;    DBusConnection *connection = (DBusConnection *)daemon->dbus;
   struct watch *w;    struct watch *w;
Line 606  void check_dbus_listeners(fd_set *rset, fd_set *wset,  Line 949  void check_dbus_listeners(fd_set *rset, fd_set *wset, 
         unsigned int flags = 0;          unsigned int flags = 0;
         int fd = dbus_watch_get_unix_fd(w->watch);          int fd = dbus_watch_get_unix_fd(w->watch);
                   
        if (FD_ISSET(fd, rset))        if (poll_check(fd, POLLIN))
           flags |= DBUS_WATCH_READABLE;            flags |= DBUS_WATCH_READABLE;
                   
        if (FD_ISSET(fd, wset))        if (poll_check(fd, POLLOUT))
           flags |= DBUS_WATCH_WRITABLE;            flags |= DBUS_WATCH_WRITABLE;
                   
        if (FD_ISSET(fd, eset))        if (poll_check(fd, POLLERR))
           flags |= DBUS_WATCH_ERROR;            flags |= DBUS_WATCH_ERROR;
   
         if (flags != 0)          if (flags != 0)
Line 647  void emit_dbus_signal(int action, struct dhcp_lease *l Line 990  void emit_dbus_signal(int action, struct dhcp_lease *l
    if (lease->flags & (LEASE_TA | LEASE_NA))     if (lease->flags & (LEASE_TA | LEASE_NA))
      {       {
        print_mac(mac, lease->clid, lease->clid_len);         print_mac(mac, lease->clid, lease->clid_len);
       inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);       inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
      }       }
    else     else
 #endif  #endif

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.5


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