]>
Commit | Line | Data |
---|---|---|
697b4f04 MT |
1 | From c6d82c9ba64cdd50f76c9079dd06c48cca4fc39b Mon Sep 17 00:00:00 2001 |
2 | From: Nicolas Cavallari <nicolas.cavallari@green-communications.fr> | |
3 | Date: Tue, 9 Jun 2015 20:42:20 +0100 | |
4 | Subject: [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 | ||
12 | diff --git a/CHANGELOG b/CHANGELOG | |
13 | index 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 | |
26 | diff --git a/dbus/DBus-interface b/dbus/DBus-interface | |
27 | index 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 | |
111 | diff --git a/src/dbus.c b/src/dbus.c | |
112 | index 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 | -- | |
328 | 2.1.0 | |
329 |