]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/0104-Add-Dbus-methods-to-create-and-delete-DHCP-leases.patch
squid: Apply fix for Squid Advisory SQUID-2015:2
[ipfire-2.x.git] / src / patches / dnsmasq / 0104-Add-Dbus-methods-to-create-and-delete-DHCP-leases.patch
CommitLineData
697b4f04
MT
1From c6d82c9ba64cdd50f76c9079dd06c48cca4fc39b Mon Sep 17 00:00:00 2001
2From: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
3Date: Tue, 9 Jun 2015 20:42:20 +0100
4Subject: [PATCH 104/113] Add Dbus methods to create and delete DHCP leases.
5
6---
7 CHANGELOG | 3 +
8 dbus/DBus-interface | 74 ++++++++++++++++++++
9 src/dbus.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 268 insertions(+)
11
12diff --git a/CHANGELOG b/CHANGELOG
13index 9e1b5a5ab0b8..a5bd4dc02701 100644
14--- a/CHANGELOG
15+++ b/CHANGELOG
16@@ -125,6 +125,9 @@ version 2.73
17 in the correct subnet, even of not in dynamic address
18 allocation range. Thanks to Steve Hirsch for spotting
19 the problem.
20+
21+ Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
22+ to Nicolas Cavallari for the patch.
23
24
25 version 2.72
26diff --git a/dbus/DBus-interface b/dbus/DBus-interface
27index 9a895eb24a61..2db5c30b2eaa 100644
28--- a/dbus/DBus-interface
29+++ b/dbus/DBus-interface
30@@ -169,6 +169,80 @@ Return an array of strings, each string is the IP address of an upstream
31 server which has been found to loop queries back to this dnsmasq instance, and
32 it therefore not being used.
33
34+AddDhcpLease
35+------------
36+
37+Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
38+database, as if a client requested and obtained a lease.
39+
40+If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
41+
42+Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
43+D-Bus signal and will run the configured DHCP lease script accordingly.
44+
45+This function takes many arguments which are the lease parameters:
46+- A string with the textual representation of the IPv4 or IPv6 address of the
47+ client.
48+
49+ Examples:
50+ "192.168.1.115"
51+ "1003:1234:abcd::1%eth0"
52+ "2001:db8:abcd::1"
53+
54+- A string representing the hardware address of the client, using the same
55+ format as the one used in the lease database.
56+
57+ Examples:
58+
59+ "00:23:45:67:89:ab"
60+ "06-00:20:e0:3b:13:af" (token ring)
61+
62+- The hostname of the client, as an array of bytes (so there is no problem
63+ with non-ASCII character encoding). May be empty.
64+
65+ Example (for "hostname.or.fqdn"):
66+ [104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
67+
68+- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
69+ empty.
70+
71+ Examples:
72+
73+ DHCPv6 DUID:
74+ [0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
75+ DHCPv4 client identifier:
76+ [255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
77+
78+- The duration of the lease, in seconds. If the lease is updated, then
79+ the duration replaces the previous duration.
80+
81+ Example:
82+
83+ 7200
84+
85+- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
86+ byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
87+
88+ Example (for IPv6):
89+
90+ 203569230
91+
92+- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
93+ address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
94+ (IA_NA). For DHCPv4 leases, this must be set to false.
95+
96+RemoveDhcpLease
97+---------------
98+
99+Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
100+database, as if a client sent a release message to abandon a lease.
101+
102+This function takes only one parameter: the text representation of the
103+IPv4 or IPv6 address of the lease to remove.
104+
105+Note that this function will trigger the DhcpLeaseRemoved signal and the
106+configured DHCP lease script will be run with the "del" action.
107+
108
109
110 2. SIGNALS
111diff --git a/src/dbus.c b/src/dbus.c
112index 5b69de518beb..801d4825001b 100644
113--- a/src/dbus.c
114+++ b/src/dbus.c
115@@ -70,6 +70,21 @@ const char* introspection_xml_template =
116 " <arg name=\"hwaddr\" type=\"s\"/>\n"
117 " <arg name=\"hostname\" type=\"s\"/>\n"
118 " </signal>\n"
119+#ifdef HAVE_DHCP
120+" <method name=\"AddDhcpLease\">\n"
121+" <arg name=\"ipaddr\" type=\"s\"/>\n"
122+" <arg name=\"hwaddr\" type=\"s\"/>\n"
123+" <arg name=\"hostname\" type=\"ay\"/>\n"
124+" <arg name=\"clid\" type=\"ay\"/>\n"
125+" <arg name=\"lease_duration\" type=\"u\"/>\n"
126+" <arg name=\"ia_id\" type=\"u\"/>\n"
127+" <arg name=\"is_temporary\" type=\"b\"/>\n"
128+" </method>\n"
129+" <method name=\"DeleteDhcpLease\">\n"
130+" <arg name=\"ipaddr\" type=\"s\"/>\n"
131+" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
132+" </method>\n"
133+#endif
134 " </interface>\n"
135 "</node>\n";
136
137@@ -433,6 +448,172 @@ static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
138 return NULL;
139 }
140
141+#ifdef HAVE_DHCP
142+static DBusMessage *dbus_add_lease(DBusMessage* message)
143+{
144+ struct dhcp_lease *lease;
145+ const char *ipaddr, *hwaddr, *hostname, *tmp;
146+ const unsigned char* clid;
147+ int clid_len, hostname_len, hw_len, hw_type;
148+ dbus_uint32_t expires, ia_id;
149+ dbus_bool_t is_temporary;
150+ struct all_addr addr;
151+ time_t now = dnsmasq_time();
152+ unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
153+
154+ DBusMessageIter iter, array_iter;
155+ if (!dbus_message_iter_init(message, &iter))
156+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
157+ "Failed to initialize dbus message iter");
158+
159+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
160+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
161+ "Expected string as first argument");
162+
163+ dbus_message_iter_get_basic(&iter, &ipaddr);
164+ dbus_message_iter_next(&iter);
165+
166+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
167+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
168+ "Expected string as second argument");
169+
170+ dbus_message_iter_get_basic(&iter, &hwaddr);
171+ dbus_message_iter_next(&iter);
172+
173+ if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
174+ (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
175+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
176+ "Expected byte array as third argument");
177+
178+ dbus_message_iter_recurse(&iter, &array_iter);
179+ dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
180+ tmp = memchr(hostname, '\0', hostname_len);
181+ if (tmp)
182+ {
183+ if (tmp == &hostname[hostname_len - 1])
184+ hostname_len--;
185+ else
186+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
187+ "Hostname contains an embedded NUL character");
188+ }
189+ dbus_message_iter_next(&iter);
190+
191+ if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
192+ (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
193+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
194+ "Expected byte array as fourth argument");
195+
196+ dbus_message_iter_recurse(&iter, &array_iter);
197+ dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
198+ dbus_message_iter_next(&iter);
199+
200+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
201+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
202+ "Expected uint32 as fifth argument");
203+
204+ dbus_message_iter_get_basic(&iter, &expires);
205+ dbus_message_iter_next(&iter);
206+
207+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
208+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
209+ "Expected uint32 as sixth argument");
210+
211+ dbus_message_iter_get_basic(&iter, &ia_id);
212+ dbus_message_iter_next(&iter);
213+
214+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
215+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
216+ "Expected uint32 as sixth argument");
217+
218+ dbus_message_iter_get_basic(&iter, &is_temporary);
219+
220+ if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
221+ {
222+ if (ia_id != 0 || is_temporary)
223+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
224+ "ia_id and is_temporary must be zero for IPv4 lease");
225+
226+ if (!(lease = lease_find_by_addr(addr.addr.addr4)))
227+ lease = lease4_allocate(addr.addr.addr4);
228+ }
229+#ifdef HAVE_DHCP6
230+ else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
231+ {
232+ if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
233+ lease = lease6_allocate(&addr.addr.addr6,
234+ is_temporary ? LEASE_TA : LEASE_NA);
235+ lease_set_iaid(lease, ia_id);
236+ }
237+#endif
238+ else
239+ return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
240+ "Invalid IP address '%s'", ipaddr);
241+
242+ hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
243+ &hw_type);
244+ if (hw_type == 0 && hw_len != 0)
245+ hw_type = ARPHRD_ETHER;
246+
247+ lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
248+ clid_len, now, 0);
249+ lease_set_expires(lease, expires, now);
250+ if (hostname_len != 0)
251+ lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
252+
253+ lease_update_file(now);
254+ lease_update_dns(0);
255+
256+ return NULL;
257+}
258+
259+static DBusMessage *dbus_del_lease(DBusMessage* message)
260+{
261+ struct dhcp_lease *lease;
262+ DBusMessageIter iter;
263+ const char *ipaddr;
264+ DBusMessage *reply;
265+ struct all_addr addr;
266+ dbus_bool_t ret = 1;
267+ time_t now = dnsmasq_time();
268+
269+ if (!dbus_message_iter_init(message, &iter))
270+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
271+ "Failed to initialize dbus message iter");
272+
273+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
274+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
275+ "Expected string as first argument");
276+
277+ dbus_message_iter_get_basic(&iter, &ipaddr);
278+
279+ if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
280+ lease = lease_find_by_addr(addr.addr.addr4);
281+#ifdef HAVE_DHCP6
282+ else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
283+ lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
284+#endif
285+ else
286+ return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
287+ "Invalid IP address '%s'", ipaddr);
288+
289+ if (lease)
290+ {
291+ lease_prune(lease, now);
292+ lease_update_file(now);
293+ lease_update_dns(0);
294+ }
295+ else
296+ ret = 0;
297+
298+ if ((reply = dbus_message_new_method_return(message)))
299+ dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
300+ DBUS_TYPE_INVALID);
301+
302+
303+ return reply;
304+}
305+#endif
306+
307 DBusHandlerResult message_handler(DBusConnection *connection,
308 DBusMessage *message,
309 void *user_data)
310@@ -490,6 +671,16 @@ DBusHandlerResult message_handler(DBusConnection *connection,
311 {
312 reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
313 }
314+#ifdef HAVE_DHCP
315+ else if (strcmp(method, "AddDhcpLease") == 0)
316+ {
317+ reply = dbus_add_lease(message);
318+ }
319+ else if (strcmp(method, "DeleteDhcpLease") == 0)
320+ {
321+ reply = dbus_del_lease(message);
322+ }
323+#endif
324 else if (strcmp(method, "ClearCache") == 0)
325 clear_cache = 1;
326 else
327--
3282.1.0
329