Annotation of embedaddon/dnsmasq/src/dbus.c, revision 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>