3 * Copyright 2009 Roy Marples <roy@marples.name>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include "libdhcpcd.h"
36 #define HIST_MAX 10 /* Max history per ssid/bssid */
39 dhcpcd_wi_history_clear(DHCPCD_CONNECTION *con)
43 while (con->wi_history) {
44 h = con->wi_history->next;
45 free(con->wi_history);
51 dhcpcd_wi_scans_free(DHCPCD_WI_SCAN *wis)
62 static DHCPCD_WI_SCAN *
63 dhcpcd_scanresult_new(DHCPCD_CONNECTION *con, DBusMessageIter *array)
65 DBusMessageIter dict, entry, var;
71 wis = calloc(1, sizeof(*wis));
73 dhcpcd_error_set(con, NULL, errno);
77 dbus_message_iter_recurse(array, &dict);
79 dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY;
80 dbus_message_iter_next(&dict))
82 dbus_message_iter_recurse(&dict, &entry);
83 if (!dhcpcd_iter_get(con, &entry, DBUS_TYPE_STRING, &s))
85 if (dbus_message_iter_get_arg_type(&entry) !=
88 dbus_message_iter_recurse(&entry, &var);
89 if (strcmp(s, "BSSID") == 0) {
90 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
92 strlcpy(wis->bssid, s, sizeof(wis->bssid));
93 } else if (strcmp(s, "Frequency") == 0) {
94 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_INT32, &i32))
97 } else if (strcmp(s, "Quality") == 0) {
98 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_INT32, &i32))
100 wis->quality.value = i32;
101 } else if (strcmp(s, "Noise") == 0) {
102 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_INT32, &i32))
104 wis->noise.value = i32;
105 } else if (strcmp(s, "Level") == 0) {
106 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_INT32, &i32))
108 wis->level.value = i32;
109 } else if (strcmp(s, "Flags") == 0) {
110 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
112 strlcpy(wis->flags, s, sizeof(wis->flags));
113 } else if (strcmp(s, "SSID") == 0) {
114 if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
116 strlcpy(wis->ssid, s, sizeof(wis->ssid));
119 if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
120 if (con->errors == errors)
121 dhcpcd_error_set(con, NULL, EINVAL);
129 dhcpcd_wi_scans(DHCPCD_CONNECTION *con, DHCPCD_IF *i)
132 DBusMessageIter args, array;
133 DHCPCD_WI_SCAN *wis, *scans, *l;
134 DHCPCD_WI_HIST *h, *hl;
137 msg = dhcpcd_message_reply(con, "ScanResults", i->ifname);
140 if (!dbus_message_iter_init(msg, &args) ||
141 dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
143 dhcpcd_error_set(con, NULL, EINVAL);
148 errors = con->errors;
149 dbus_message_iter_recurse(&args, &array);
151 dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_ARRAY;
152 dbus_message_iter_next(&array))
154 wis = dhcpcd_scanresult_new(con, &array);
159 wis->quality.average = wis->quality.value;
160 wis->noise.average = wis->noise.value;
161 wis->level.average = wis->level.value;
162 for (h = con->wi_history; h; h = h->next) {
163 if (strcmp(h->ifname, i->ifname) == 0 &&
164 strcmp(h->bssid, wis->bssid) == 0)
166 wis->quality.average += h->quality;
167 wis->noise.average += h->noise;
168 wis->level.average += h->level;
169 if (++nh == HIST_MAX) {
178 wis->quality.average /= nh;
179 wis->noise.average /= nh;
180 wis->level.average /= nh;
182 h = malloc(sizeof(*h));
184 strlcpy(h->ifname, i->ifname, sizeof(h->ifname));
185 strlcpy(h->bssid, wis->bssid, sizeof(h->bssid));
186 h->quality = wis->quality.value;
187 h->noise = wis->noise.value;
188 h->level = wis->level.value;
189 h->next = con->wi_history;
199 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
200 if (con->errors == errors)
201 dhcpcd_error_set(con, NULL, EINVAL);
202 dhcpcd_wi_scans_free(scans);
205 dbus_message_unref(msg);
210 dhcpcd_wpa_find_network(DHCPCD_CONNECTION *con, DHCPCD_IF *i, const char *ssid)
213 DBusMessageIter args, array, entry;
218 msg = dhcpcd_message_reply(con, "ListNetworks", i->ifname);
221 if (!dbus_message_iter_init(msg, &args)) {
222 dhcpcd_error_set(con, NULL, EINVAL);
226 errors = con->errors;
228 dbus_message_iter_get_arg_type(&args) == DBUS_TYPE_ARRAY;
229 dbus_message_iter_next(&args))
231 dbus_message_iter_recurse(&args, &array);
233 dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT;
234 dbus_message_iter_next(&array))
236 dbus_message_iter_recurse(&array, &entry);
237 if (!dhcpcd_iter_get(con, &entry,
238 DBUS_TYPE_INT32, &id) ||
239 !dhcpcd_iter_get(con, &entry,
240 DBUS_TYPE_STRING, &s))
242 if (strcmp(s, ssid) == 0) {
243 dbus_message_unref(msg);
248 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INVALID &&
249 con->errors == errors)
250 dhcpcd_error_set(con, NULL, EINVAL);
251 dbus_message_unref(msg);
256 dhcpcd_wpa_add_network(DHCPCD_CONNECTION *con, DHCPCD_IF *i)
259 DBusMessageIter args;
263 msg = dhcpcd_message_reply(con, "AddNetwork", i->ifname);
267 if (dbus_message_iter_init(msg, &args)) {
268 if (dhcpcd_iter_get(con, &args, DBUS_TYPE_INT32, &id))
271 dhcpcd_error_set(con, NULL, EINVAL);
272 dbus_message_unref(msg);
277 dhcpcd_wpa_set_network(DHCPCD_CONNECTION *con, DHCPCD_IF *i, int id,
278 const char *opt, const char *val)
280 DBusMessage *msg, *reply;
281 DBusMessageIter args;
285 msg = dbus_message_new_method_call(DHCPCD_SERVICE, DHCPCD_PATH,
286 DHCPCD_SERVICE, "SetNetwork");
288 dhcpcd_error_set(con, 0, errno);
291 dbus_message_iter_init_append(msg, &args);
293 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &ifname);
294 dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &id);
295 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &opt);
296 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &val);
297 reply = dhcpcd_send_reply(con, msg);
298 dbus_message_unref(msg);
302 dbus_message_unref(reply);
309 dhcpcd_wpa_find_network_new(DHCPCD_CONNECTION *con, DHCPCD_IF *i,
317 len = strlen(ssid) + 3;
320 dhcpcd_error_set(con, 0, errno);
323 errors = con->errors;
324 id = dhcpcd_wpa_find_network(con, i, ssid);
325 if (id != -1 || con->errors != errors) {
329 id = dhcpcd_wpa_add_network(con, i);
334 snprintf(q, len, "\"%s\"", ssid);
335 retval = dhcpcd_wpa_set_network(con, i, id, "ssid", q);
341 dhcpcd_wpa_command(DHCPCD_CONNECTION *con, DHCPCD_IF *i,
342 const char *cmd, int id)
344 DBusMessage *msg, *reply;
345 DBusMessageIter args;
349 msg = dbus_message_new_method_call(DHCPCD_SERVICE, DHCPCD_PATH,
350 DHCPCD_SERVICE, cmd);
352 dhcpcd_error_set(con, 0, errno);
355 dbus_message_iter_init_append(msg, &args);
357 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &ifname);
359 dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &id);
360 reply = dhcpcd_send_reply(con, msg);
361 dbus_message_unref(msg);
365 dbus_message_unref(reply);