1e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan/*
2e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * dhcpcd - DHCP client daemon
3e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * All rights reserved
5e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
6e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * Redistribution and use in source and binary forms, with or without
7e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * modification, are permitted provided that the following conditions
8e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * are met:
9e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * 1. Redistributions of source code must retain the above copyright
10e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan *    notice, this list of conditions and the following disclaimer.
11e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright
12e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan *    notice, this list of conditions and the following disclaimer in the
13e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan *    documentation and/or other materials provided with the distribution.
14e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan *
15e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * SUCH DAMAGE.
26e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan */
27e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
28e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <errno.h>
29e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <poll.h>
30e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <signal.h>
31e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <stdio.h>
32e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <stdlib.h>
33e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <string.h>
34e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <syslog.h>
35e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <unistd.h>
36e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
37e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include <dbus/dbus.h>
38e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
39e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include "../config.h"
40e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include "../eloop.h"
41e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include "../dhcp.h"
428e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#ifdef INET6
438e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#include "../dhcp6.h"
448e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#endif
45e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include "../rpc-interface.h"
46e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#include "dbus-dict.h"
47e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
48e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#define SERVICE_NAME 	"org.chromium.dhcpcd"
49e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#define SERVICE_PATH    "/org/chromium/dhcpcd"
50e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#define S_EINVAL	SERVICE_NAME ".InvalidArgument"
51e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#define S_ARGS		"Not enough arguments"
52e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
53e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusConnection *connection;
54e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic struct dhcpcd_ctx *dhcpcd_ctx;
55e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
56e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic const char dhcpcd_introspection_xml[] =
57e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <method name=\"GetVersion\">\n"
58e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
59e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </method>\n"
60e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <method name=\"Rebind\">\n"
61e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"
62e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </method>\n"
63e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <method name=\"Release\">\n"
64e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"
65e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </method>\n"
66e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <method name=\"Stop\">\n"
67e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"
68e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </method>\n"
69e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <signal name=\"Event\">\n"
70e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"configuration\" type=\"usa{sv}\"/>\n"
71e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </signal>\n"
72e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <signal name=\"StatusChanged\">\n"
73e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"status\" type=\"us\"/>\n"
74e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </signal>\n";
75e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
76e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic const char service_watch_rule[] = "interface=" DBUS_INTERFACE_DBUS
77e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	",type=signal,member=NameOwnerChanged";
78e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
79e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic const char introspection_header_xml[] =
80e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "<!DOCTYPE node PUBLIC \"-//freedesktop//"
81e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "DTD D-BUS Object Introspection 1.0//EN\"\n"
82e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
83e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "<node name=\"" SERVICE_PATH "\">\n"
84e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
85e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    <method name=\"Introspect\">\n"
86e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
87e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "    </method>\n"
88e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "  </interface>\n"
89e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "  <interface name=\"" SERVICE_NAME "\">\n";
90e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
91e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic const char introspection_footer_xml[] =
92e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "  </interface>\n"
93e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    "</node>\n";
94e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
95e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic const struct o_dbus dhos[] = {
96e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ip_address=", DBUS_TYPE_UINT32, 0, "IPAddress" },
97e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "server_name=", DBUS_TYPE_STRING, 0, "ServerName"},
98e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "subnet_mask=", DBUS_TYPE_UINT32, 0, "SubnetMask" },
99e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "subnet_cidr=", DBUS_TYPE_BYTE, 0, "SubnetCIDR" },
100e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "network_number=", DBUS_TYPE_UINT32, 0, "NetworkNumber" },
101e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "classless_static_routes=", DBUS_TYPE_STRING, 0,
102e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "ClasslessStaticRoutes" },
103e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ms_classless_static_routes=", DBUS_TYPE_STRING, 0,
104e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "MSClasslessStaticRoutes" },
105e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "static_routes=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
106e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "StaticRoutes"} ,
107e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "routers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "Routers" },
108e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "time_offset=", DBUS_TYPE_UINT32, 0, "TimeOffset" },
109e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "time_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "TimeServers" },
110e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ien116_name_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
111e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "IEN116NameServers" },
112e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "domain_name_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
113e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DomainNameServers" },
114e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "log_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "LogServers" },
115e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "cookie_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
116e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "CookieServers" },
117e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "lpr_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "LPRServers" },
118e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "impress_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
119e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "ImpressServers" },
120e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "resource_location_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
121e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "ResourceLocationServers" },
122e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "host_name=", DBUS_TYPE_STRING, 0, "Hostname" },
123e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "boot_size=", DBUS_TYPE_UINT16, 0, "BootSize" },
124e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "merit_dump=", DBUS_TYPE_STRING, 0, "MeritDump" },
125e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "domain_name=", DBUS_TYPE_STRING, 0, "DomainName" },
126e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "swap_server=", DBUS_TYPE_UINT32, 0, "SwapServer" },
127e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "root_path=", DBUS_TYPE_STRING, 0, "RootPath" },
128e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "extensions_path=", DBUS_TYPE_STRING, 0, "ExtensionsPath" },
129e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ip_forwarding=", DBUS_TYPE_BOOLEAN, 0, "IPForwarding" },
130e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "non_local_source_routing=", DBUS_TYPE_BOOLEAN, 0,
131e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "NonLocalSourceRouting" },
132e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "policy_filter=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
133e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "PolicyFilter" },
134e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "max_dgram_reassembly=", DBUS_TYPE_INT16, 0,
135e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "MaxDatagramReassembly" },
136e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "default_ip_ttl=", DBUS_TYPE_UINT16, 0, "DefaultIPTTL" },
137e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "path_mtu_aging_timeout=", DBUS_TYPE_UINT32, 0,
138e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "PathMTUAgingTimeout" },
139e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "path_mtu_plateau_table=" ,DBUS_TYPE_ARRAY, DBUS_TYPE_UINT16,
140e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "PolicyFilter"} ,
141e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "interface_mtu=", DBUS_TYPE_UINT16, 0, "InterfaceMTU" },
142e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "all_subnets_local=", DBUS_TYPE_BOOLEAN, 0, "AllSubnetsLocal" },
143e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "broadcast_address=", DBUS_TYPE_UINT32, 0, "BroadcastAddress" },
144e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "perform_mask_discovery=", DBUS_TYPE_BOOLEAN, 0,
145e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "PerformMaskDiscovery" },
146e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "mask_supplier=", DBUS_TYPE_BOOLEAN, 0, "MaskSupplier" },
147e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "router_discovery=", DBUS_TYPE_BOOLEAN, 0, "RouterDiscovery" },
148e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "router_solicitiation_address=", DBUS_TYPE_UINT32, 0,
149e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "RouterSolicationAddress" },
150e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "trailer_encapsulation=", DBUS_TYPE_BOOLEAN, 0,
151e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "TrailerEncapsulation" },
152e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "arp_cache_timeout=", DBUS_TYPE_UINT32, 0, "ARPCacheTimeout" },
153e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ieee802_3_encapsulation=", DBUS_TYPE_UINT16, 0,
154e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "IEEE8023Encapsulation" },
155e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "default_tcp_ttl=", DBUS_TYPE_BYTE, 0, "DefaultTCPTTL" },
156e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "tcp_keepalive_interval=", DBUS_TYPE_UINT32, 0,
157e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "TCPKeepAliveInterval" },
158e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "tcp_keepalive_garbage=", DBUS_TYPE_BOOLEAN, 0,
159e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "TCPKeepAliveGarbage" },
160e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nis_domain=", DBUS_TYPE_STRING, 0, "NISDomain" },
161e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nis_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "NISServers" },
162e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "ntp_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "NTPServers" },
1639c993df942bba4476200aace0e69590bdf9a6a88Victor Dodon	{ "vendor_encapsulated_options=", DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
164e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "VendorEncapsulatedOptions" },
165e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netbios_name_servers=" ,DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
166e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "NetBIOSNameServers" },
167e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netbios_dd_server=", DBUS_TYPE_UINT32, 0, "NetBIOSDDServer" },
168e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netbios_node_type=", DBUS_TYPE_BYTE, 0, "NetBIOSNodeType" },
169e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netbios_scope=", DBUS_TYPE_STRING, 0, "NetBIOSScope" },
170e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "font_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "FontServers" },
171e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "x_display_manager=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
172e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "XDisplayManager" },
173e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_requested_address=", DBUS_TYPE_UINT32, 0,
174e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DHCPRequestedAddress" },
175e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_lease_time=", DBUS_TYPE_UINT32, 0, "DHCPLeaseTime" },
176e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_option_overload=", DBUS_TYPE_BOOLEAN, 0,
177e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DHCPOptionOverload" },
178e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_message_type=", DBUS_TYPE_BYTE, 0, "DHCPMessageType" },
179e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_server_identifier=", DBUS_TYPE_UINT32, 0,
180e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DHCPServerIdentifier" },
181e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_message=", DBUS_TYPE_STRING, 0, "DHCPMessage" },
182e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_max_message_size=", DBUS_TYPE_UINT16, 0,
183e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DHCPMaxMessageSize" },
184e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_renewal_time=", DBUS_TYPE_UINT32, 0, "DHCPRenewalTime" },
185e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "dhcp_rebinding_time=", DBUS_TYPE_UINT32, 0, "DHCPRebindingTime" },
186e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nisplus_domain=", DBUS_TYPE_STRING, 0, "NISPlusDomain" },
187e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nisplus_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
188e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "NISPlusServers" },
189e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "tftp_server_name=", DBUS_TYPE_STRING, 0, "TFTPServerName" },
190e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "bootfile_name=", DBUS_TYPE_STRING, 0, "BootFileName" },
191e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "mobile_ip_home_agent=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
192e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "MobileIPHomeAgent" },
193e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "smtp_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "SMTPServer" },
194e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "pop_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "POPServer" },
195e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nntp_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "NNTPServer" },
196e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "www_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "WWWServer" },
197e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "finger_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
198e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "FingerServer" },
199e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "irc_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "IRCServer" },
200e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "streettalk_server=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
201e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "StreetTalkServer" },
202e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "streettalk_directory_assistance_server=", DBUS_TYPE_ARRAY,
203e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  DBUS_TYPE_UINT32, "StreetTalkDirectoryAssistanceServer" },
204e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "user_class=", DBUS_TYPE_STRING, 0, "UserClass" },
205e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "new_fqdn_name=", DBUS_TYPE_STRING, 0, "FQDNName" },
206e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nds_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "NDSServers" },
207e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nds_tree_name=", DBUS_TYPE_STRING, 0, "NDSTreeName" },
208e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "nds_context=", DBUS_TYPE_STRING, 0, "NDSContext" },
209e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "bcms_controller_names=", DBUS_TYPE_STRING, 0,
210e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "BCMSControllerNames" },
211e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "client_last_transaction_time=", DBUS_TYPE_UINT32, 0,
212e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "ClientLastTransactionTime" },
213e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "associated_ip=", DBUS_TYPE_UINT32, 0, "AssociatedIP" },
214e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "uap_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, "UAPServers" },
215e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netinfo_server_address=", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
216e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "NetinfoServerAddress" },
217e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "netinfo_server_tag=", DBUS_TYPE_STRING, 0, "NetinfoServerTag" },
218e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "default_url=", DBUS_TYPE_STRING, 0, "DefaultURL" },
219e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "subnet_selection=", DBUS_TYPE_UINT32, 0, "SubnetSelection" },
220e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "domain_search=", DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
221e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	  "DomainSearch" },
222e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ "wpad_url=", DBUS_TYPE_STRING, 0, "WebProxyAutoDiscoveryUrl" },
2238e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#ifdef INET6
2248e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_server_id=", DBUS_TYPE_STRING, 0,
2258e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6ServerIdentifier" },
2268e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_ia_na1_ia_addr1=", DBUS_TYPE_STRING, 0, "DHCPv6Address" },
2278e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_ia_na1_ia_addr1_vltime=", DBUS_TYPE_UINT32, 0,
2288e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6AddressLeaseTime" },
2298e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_name_servers=", DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
2308e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6NameServers" },
2318e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_domain_search=", DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
2328e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6DomainSearch" },
2338e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_ia_pd1_prefix1=", DBUS_TYPE_STRING, 0,
2348e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6DelegatedPrefix" },
2358e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_ia_pd1_prefix1_length=", DBUS_TYPE_UINT32, 0,
2368e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6DelegatedPrefixLength" },
2378e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	{ "dhcp6_ia_pd1_prefix1_vltime=", DBUS_TYPE_UINT32, 0,
2388e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	  "DHCPv6DelegatedPrefixLeaseTime" },
2398e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#endif
240e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{ NULL, 0, 0, NULL }
241e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan};
242e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
243e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic int
244e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanappend_config(DBusMessageIter *iter,
245e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    const char *prefix, char **env, ssize_t elen)
246e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
247e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	char **eenv, *p;
248e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	const struct o_dbus *dhop;
249e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	size_t l, lp;
250e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int retval;
251e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
252e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	retval = 0;
253e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	lp = strlen(prefix);
254e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	for (eenv = env + elen; env < eenv; env++) {
255e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		p = env[0];
256e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		for (dhop = dhos; dhop->var; dhop++) {
257e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			l = strlen(dhop->var);
258e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			if (strncmp(p, dhop->var, l) == 0) {
259e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				retval = dict_append_config_item(iter,
260e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				    dhop, p + l);
261e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				break;
262e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			}
263e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			if (strncmp(p, prefix, lp) == 0 &&
264e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			    strncmp(p + lp, dhop->var, l) == 0)
265e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			{
266e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				retval = dict_append_config_item(iter,
267e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				    dhop, p + l + lp);
268e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				break;
269e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			}
270e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		}
271e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (retval == -1)
272e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			break;
273e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
274e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return retval;
275e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
276e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
277e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
278e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanget_dbus_error(DBusConnection *con, DBusMessage *msg,
279e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		  const char *name, const char *fmt, ...)
280e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
281e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	char buffer[1024];
282e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage *reply;
283e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	va_list args;
284e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
285e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	va_start(args, fmt);
286e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	vsnprintf(buffer, sizeof(buffer), fmt, args);
287e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	va_end(args);
288e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	reply = dbus_message_new_error(msg, name, buffer);
289e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_connection_send(con, reply, NULL);
290e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(reply);
291e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return DBUS_HANDLER_RESULT_HANDLED;
292e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
293e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
294e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic dbus_bool_t
295e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandbus_send_message(const struct interface *ifp, const char *reason,
296e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan    const char *prefix, struct dhcp_message *message)
297e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
298e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	const struct if_options *ifo = ifp->options;
299e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage* msg;
300e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessageIter args, dict;
301e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int pid = getpid();
302e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	char **env = NULL;
303e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	ssize_t e, elen;
304e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int retval;
305e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int success = FALSE;
306e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
307e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	syslog(LOG_INFO, "event %s on interface %s", reason, ifp->name);
308e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
309e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	msg = dbus_message_new_signal(SERVICE_PATH, SERVICE_NAME, "Event");
310e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (msg == NULL) {
311e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "failed to make a configure message");
312e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return FALSE;
313e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
314e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_init_append(msg, &args);
315e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &pid);
316e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &reason);
317e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY,
318e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
319e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_STRING_AS_STRING
320e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_VARIANT_AS_STRING
321e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
322e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    &dict);
323e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (prefix == NULL || message == NULL)
324e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		retval = 0;
325e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	else {
326e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		e = dhcp_env(NULL, NULL, message, ifp);
327e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (e > 0) {
328e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			char *config_prefix = strdup(prefix);
329e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			if (config_prefix == NULL) {
330e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				logger(dhcpcd_ctx, LOG_ERR,
331e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				       "Memory exhausted (strdup)");
332e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				eloop_exit(dhcpcd_ctx->eloop, EXIT_FAILURE);
333e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			}
334e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			char *p = config_prefix + strlen(config_prefix) - 1;
335e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			if (p >= config_prefix && *p == '_')
336e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				*p = '\0';
337e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			env = calloc(e + 1, sizeof(char *));
338e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			if (env == NULL) {
339e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				logger(dhcpcd_ctx, LOG_ERR,
340e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				       "Memory exhausted (calloc)");
341e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				eloop_exit(dhcpcd_ctx->eloop, EXIT_FAILURE);
342e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			}
343e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			elen = dhcp_env(env, config_prefix, message, ifp);
344e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			free(config_prefix);
345e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		}
346e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		retval = append_config(&dict, prefix, env, elen);
347e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
348e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
349e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	/* Release memory allocated for env. */
350e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (env) {
351e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		char **current = env;
352e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		while (*current)
353e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			free(*current++);
354e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		free(env);
355e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
356e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
357e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_close_container(&args, &dict);
358e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (retval == 0) {
359e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		success = dbus_connection_send(connection, msg, NULL);
360e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (!success)
361e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			syslog(LOG_ERR, "failed to send dhcp to dbus");
362e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else
363e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "failed to construct dbus message");
364e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(msg);
365e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
366e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return success;
367e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
368e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
3698e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#ifdef INET6
3708e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tanstatic dbus_bool_t
3718e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tandbus_send_dhcpv6_message(const struct interface *ifp, const char *reason,
3728e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan    const char *prefix, struct dhcp6_message *message, size_t length)
3738e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan{
3748e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	const struct if_options *ifo = ifp->options;
3758e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	DBusMessage* msg;
3768e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	DBusMessageIter args, dict;
3778e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	int pid = getpid();
3788e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	char **env = NULL;
3798e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	ssize_t e, elen;
3808e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	int retval;
3818e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	int success = FALSE;
3828e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
3838e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	syslog(LOG_INFO, "event %s on interface %s", reason, ifp->name);
3848e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
3858e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	msg = dbus_message_new_signal(SERVICE_PATH, SERVICE_NAME, "Event");
3868e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	if (msg == NULL) {
3878e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		syslog(LOG_ERR, "failed to make a configure message");
3888e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		return FALSE;
3898e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	}
3908e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_iter_init_append(msg, &args);
3918e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &pid);
3928e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &reason);
3938e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY,
3948e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	    DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3958e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	    DBUS_TYPE_STRING_AS_STRING
3968e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	    DBUS_TYPE_VARIANT_AS_STRING
3978e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	    DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
3988e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	    &dict);
3998e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	if (prefix == NULL || message == NULL)
4008e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		retval = 0;
4018e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	else {
4028e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		e = dhcp6_env(NULL, NULL, ifp, message, length);
4038e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		if (e > 0) {
4048e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			char *config_prefix = strdup(prefix);
4058e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			if (config_prefix == NULL) {
4068e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				logger(dhcpcd_ctx, LOG_ERR,
4078e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				       "Memory exhausted (strdup)");
4088e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				eloop_exit(dhcpcd_ctx->eloop, EXIT_FAILURE);
4098e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			}
4108e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			char *p = config_prefix + strlen(config_prefix) - 1;
4118e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			if (p >= config_prefix && *p == '_')
4128e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				*p = '\0';
4138e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			env = calloc(e + 1, sizeof(char *));
4148e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			if (env == NULL) {
4158e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				logger(dhcpcd_ctx, LOG_ERR,
4168e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				       "Memory exhausted (calloc)");
4178e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan				eloop_exit(dhcpcd_ctx->eloop, EXIT_FAILURE);
4188e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			}
4198e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			elen = dhcp6_env(env, "new", ifp, message, length);
4208e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			free(config_prefix);
4218e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		}
4228e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		retval = append_config(&dict, prefix, env, elen);
4238e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	}
4248e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
4258e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	/* Release memory allocated for env. */
4268e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	if (env) {
4278e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		char **current = env;
4288e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		while (*current)
4298e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			free(*current++);
4308e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		free(env);
4318e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	}
4328e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
4338e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_iter_close_container(&args, &dict);
4348e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	if (retval == 0) {
4358e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		success = dbus_connection_send(connection, msg, NULL);
4368e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		if (!success)
4378e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan			syslog(LOG_ERR, "failed to send dhcpv6 to dbus");
4388e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	} else
4398e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		syslog(LOG_ERR, "failed to construct dbus message");
4408e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	dbus_message_unref(msg);
4418e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
4428e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	return success;
4438e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan}
4448e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#endif
4458e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan
446e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
447e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanintrospect(DBusConnection *con, DBusMessage *msg)
448e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
449e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage *reply;
450e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	char *xml;
451e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	size_t len;
452e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
453e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	len = sizeof(introspection_header_xml) - 1
454e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    + sizeof(dhcpcd_introspection_xml) - 1
455e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    + sizeof(introspection_footer_xml) - 1
456e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    + 1; /* terminal \0 */
457e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	xml = malloc(len);
458e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (xml == NULL)
459e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return DBUS_HANDLER_RESULT_HANDLED;
460e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	snprintf(xml, len, "%s%s%s",
461e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    introspection_header_xml,
462e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    dhcpcd_introspection_xml,
463e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    introspection_footer_xml);
464e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	reply = dbus_message_new_method_return(msg);
465e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_append_args(reply,
466e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_STRING, &xml,
467e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_INVALID);
468e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_connection_send(con, reply, NULL);
469e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(reply);
470e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	free(xml);
471e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return DBUS_HANDLER_RESULT_HANDLED;
472e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
473e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
474e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
475e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanversion(DBusConnection *con, DBusMessage *msg, const char *ver)
476e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
477e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage *reply;
478e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
479e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	reply = dbus_message_new_method_return(msg);
480e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_append_args(reply,
481e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_STRING, &ver,
482e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    DBUS_TYPE_INVALID);
483e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_connection_send(con, reply, NULL);
484e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(reply);
485e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return DBUS_HANDLER_RESULT_HANDLED;
486e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
487e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
488e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
489e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandbus_ack(DBusConnection *con, DBusMessage *msg)
490e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
491e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage *reply;
492e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
493e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	reply = dbus_message_new_method_return(msg);
494e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_connection_send(con, reply, NULL);
495e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(reply);
496e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return DBUS_HANDLER_RESULT_HANDLED;
497e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
498e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
499e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
500e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanmsg_handler(DBusConnection *con, DBusMessage *msg, __unused void *data)
501e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
502e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#define	IsMethod(msg, method) \
503e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_is_method_call(msg, SERVICE_NAME, method)
504e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
505e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE,
506e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan					"Introspect")) {
507e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return introspect(con, msg);
508e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else if (IsMethod(msg, "GetVersion")) {
509e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return version(con, msg, VERSION);
510e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else if (IsMethod(msg, "Rebind")) {
511e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		const char *iface_name;
512e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (!dbus_message_get_args(msg, NULL,
513e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &iface_name,
514e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_INVALID)) {
515e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			logger(dhcpcd_ctx, LOG_ERR,
516e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			       "Invalid arguments for Rebind");
517e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			return get_dbus_error(con, msg, S_EINVAL, S_ARGS);
518e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		}
519e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dhcpcd_start_interface(dhcpcd_ctx, iface_name);
520e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return dbus_ack(con, msg);
521e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else if (IsMethod(msg, "Release")) {
522e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		const char *iface_name;
523e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (!dbus_message_get_args(msg, NULL,
524e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &iface_name,
525e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_INVALID)) {
526e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			logger(dhcpcd_ctx, LOG_ERR,
527e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			       "Invalid arguments for Release");
528e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			return get_dbus_error(con, msg, S_EINVAL, S_ARGS);
529e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		}
530e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dhcpcd_release_ipv4(dhcpcd_ctx, iface_name);
531e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return dbus_ack(con, msg);
532e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else if (IsMethod(msg, "Stop")) {
533e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		const char *iface_name;
534e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (!dbus_message_get_args(msg, NULL,
535e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &iface_name,
536e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_INVALID)) {
537e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			logger(dhcpcd_ctx, LOG_ERR,
538e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			       "Invalid arguments for Stop");
539e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			return get_dbus_error(con, msg, S_EINVAL, S_ARGS);
540e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		}
541e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dhcpcd_stop_interface(dhcpcd_ctx, iface_name);
542e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		(void) dbus_ack(con, msg);
543e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		exit(EXIT_FAILURE);
544e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else if (dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL,
545e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan					  "Disconnected")) {
546e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dhcpcd_stop_interfaces(dhcpcd_ctx);
547e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		exit(EXIT_FAILURE);
548e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
549e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return get_dbus_error(con, msg, S_EINVAL, S_ARGS);
550e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan#undef IsMethod
551e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
552e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
553e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic void
554e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandbus_handle_event(DBusWatch *watch, int flags)
555e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
556e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_watch_handle((DBusWatch *)watch, flags);
557e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
558e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (connection != NULL) {
559e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_connection_ref(connection);
560e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		while (dbus_connection_dispatch(connection) ==
561e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				DBUS_DISPATCH_DATA_REMAINS)
562e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				;
563e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_connection_unref(connection);
564e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
565e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
566e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
567e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic void
568e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandbus_read_event(void *watch)
569e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
570e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_handle_event((DBusWatch *)watch, DBUS_WATCH_READABLE);
571e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
572e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
573e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic void
574e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandbus_write_event(void *watch)
575e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
576e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_handle_event((DBusWatch *)watch, DBUS_WATCH_WRITABLE);
577e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
578e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
579e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic dbus_bool_t
580e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanadd_watch(DBusWatch *watch, __unused void *data)
581e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
582e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int fd, flags;
583e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	void (*read_event)(void *) = NULL;
584e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	void *read_arg = NULL;
585e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	void (*write_event)(void *) = NULL;
586e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	void *write_arg = NULL;
587e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
588e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	fd = dbus_watch_get_unix_fd(watch);
589e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	flags = dbus_watch_get_flags(watch);
590e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (flags & DBUS_WATCH_READABLE) {
591e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		read_event = dbus_read_event;
592e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		read_arg = watch;
593e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
594e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (flags & DBUS_WATCH_WRITABLE) {
595e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		write_event = dbus_write_event;
596e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		write_arg = watch;
597e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
598e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
599e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (eloop_event_add(dhcpcd_ctx->eloop, fd, read_event, read_arg,
600e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			    write_event, write_arg) == 0)
601e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return TRUE;
602e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return FALSE;
603e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
604e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
605e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic void
606e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanremove_watch(DBusWatch *watch, __unused void *data)
607e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
608e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int fd, flags;
609e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int write_only = 0;
610e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	fd = dbus_watch_get_unix_fd(watch);
611e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	flags = dbus_watch_get_flags(watch);
612e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!(flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE))
613e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		write_only = 1;
614e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	eloop_event_delete(dhcpcd_ctx->eloop, fd, write_only);
615e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
616e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
617e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanstatic DBusHandlerResult
618e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tandhcpcd_dbus_filter(DBusConnection *conn, DBusMessage *msg, void *user_data)
619e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
620e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	const char *service = NULL;
621e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	const char *old_owner = NULL;
622e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	const char *new_owner = NULL;
623e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
624e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS,
625e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				    "NameOwnerChanged"))
626e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
627e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
628e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!dbus_message_get_args(msg, NULL,
629e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &service,
630e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &old_owner,
631e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_STRING, &new_owner,
632e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan				   DBUS_TYPE_INVALID)) {
633e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR,
634e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		       "Invalid arguments for NameOwnerChanged signal");
635e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
636e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
637e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (strcmp(service, "org.chromium.flimflam") == 0 &&
638e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    strlen(new_owner) == 0) {
639e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_INFO, "exiting because flimflamd has died");
640e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dhcpcd_stop_interfaces(dhcpcd_ctx);
641e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		exit(EXIT_FAILURE);
642e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
643e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
644e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
645e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
646e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanint
647e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_init(struct dhcpcd_ctx *ctx)
648e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
649e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusObjectPathVTable vt = {
650e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		NULL, &msg_handler, NULL, NULL, NULL, NULL
651e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	};
652e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusError err;
653e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int ret;
654e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
655e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dhcpcd_ctx = ctx;
656e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
657e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_error_init(&err);
658e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
659e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (connection == NULL) {
660e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		if (dbus_error_is_set(&err))
661e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			syslog(LOG_ERR, "%s", err.message);
662e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		else
663e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan			syslog(LOG_ERR, "failed to get a dbus connection");
664e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return -1;
665e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
666e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	atexit(rpc_close);
667e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
668e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!dbus_connection_set_watch_functions(connection,
669e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		add_watch, remove_watch, NULL, NULL, NULL))
670e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{
671e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "dbus: failed to set watch functions");
672e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return -1;
673e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
674e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!dbus_connection_register_object_path(connection,
675e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		SERVICE_PATH, &vt, NULL))
676e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	{
677e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "dbus: failed to register object path");
678e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return -1;
679e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
680e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_connection_add_filter(connection, dhcpcd_dbus_filter, NULL, NULL);
681e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_bus_add_match(connection, service_watch_rule, &err);
682e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (dbus_error_is_set(&err)) {
683e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "Cannot add rule: %s", err.message);
684e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return -1;
685e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
686e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return 0;
687e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
688e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
689e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanvoid
690e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_close(void)
691e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
692e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (connection) {
693e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_bus_remove_match(connection, service_watch_rule, NULL);
694e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_connection_remove_filter(connection,
695e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan					      dhcpcd_dbus_filter,
696e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan					      NULL);
697e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_connection_unref(connection);
698e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		connection = NULL;
699e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
700e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
701e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
702e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanvoid
703e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_signal_status(const char *status)
704e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
705e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessage *msg;
706e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	DBusMessageIter args;
707e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	int pid = getpid();
708e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
709e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	syslog(LOG_INFO, "status changed to %s", status);
710e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
711e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	msg = dbus_message_new_signal(SERVICE_PATH, SERVICE_NAME,
712e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	    "StatusChanged");
713e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (msg == NULL) {
714e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "failed to make a status changed message");
715e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		return;
716e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
717e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_init_append(msg, &args);
718e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &pid);
719e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &status);
720e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (!dbus_connection_send(connection, msg, NULL))
721e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		syslog(LOG_ERR, "failed to send status to dbus");
722e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	dbus_message_unref(msg);
723e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
724e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
725e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
726e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanint
727e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_update_ipv4(struct interface *ifp)
728e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
729e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
730e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	if (state->new != NULL) {
731e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		/* push state over d-bus */
732e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		dbus_send_message(ifp, state->reason, "new_", state->new);
733e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		rpc_signal_status("Bound");
734e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	} else {
735e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan		rpc_signal_status("Release");
736e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	}
737e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return 0;
738e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
739e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
7408e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#ifdef INET6
741e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanint
742e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_update_ipv6(struct interface *ifp)
743e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan{
7448e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	struct dhcp6_state *state = D6_STATE(ifp);
7458e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	if (state->new != NULL) {
7468e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		/* push state over d-bus */
7478e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		dbus_send_dhcpv6_message(ifp, state->reason, "new_",
7488e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan					 state->new, state->new_len);
7498e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		rpc_signal_status("Bound6");
7508e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	} else {
7518e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan		rpc_signal_status("Release6");
7528e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan	}
753e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return 0;
754e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
7558e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan#endif
756e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan
757e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanint
758e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tanrpc_notify_unicast_arp(struct interface *ifp) {
759e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
760e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan	return dbus_send_message(ifp, "GATEWAY-ARP", "saved_", state->offer);
761e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan}
762