Annotation of embedaddon/dnsmasq/src/dbus.c, revision 1.1.1.1

1.1       misho       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>