/*
* WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <grp.h>
#include <stddef.h>
-#include "common.h"
-#include "eloop.h"
-#include "config.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/list.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "config.h"
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
* ctrl_iface_unix.c and should not be touched directly from other files.
*/
struct wpa_ctrl_dst {
- struct wpa_ctrl_dst *next;
+ struct dl_list list;
struct sockaddr_un addr;
socklen_t addrlen;
int debug_level;
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
int sock;
- struct wpa_ctrl_dst *ctrl_dst;
+ struct dl_list ctrl_dst;
};
os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
- dst->next = priv->ctrl_dst;
- priv->ctrl_dst = dst;
+ dl_list_add(&priv->ctrl_dst, &dst->list);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
(u8 *) from->sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path));
struct sockaddr_un *from,
socklen_t fromlen)
{
- struct wpa_ctrl_dst *dst, *prev = NULL;
+ struct wpa_ctrl_dst *dst;
- dst = priv->ctrl_dst;
- while (dst) {
+ dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
if (fromlen == dst->addrlen &&
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
== 0) {
- if (prev == NULL)
- priv->ctrl_dst = dst->next;
- else
- prev->next = dst->next;
+ dl_list_del(&dst->list);
os_free(dst);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
(u8 *) from->sun_path,
offsetof(struct sockaddr_un, sun_path));
return 0;
}
- prev = dst;
- dst = dst->next;
}
return -1;
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
- dst = priv->ctrl_dst;
- while (dst) {
+ dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
if (fromlen == dst->addrlen &&
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
dst->debug_level = atoi(level);
return 0;
}
- dst = dst->next;
}
return -1;
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct ctrl_iface_priv *priv = sock_ctx;
- char buf[256];
+ char buf[4096];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
+ dl_list_init(&priv->ctrl_dst);
priv->wpa_s = wpa_s;
priv->sock = -1;
}
os_memset(&addr, 0, sizeof(addr));
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
char *fname;
char *buf, *dir = NULL, *gid_str = NULL;
eloop_unregister_read_sock(priv->sock);
- if (priv->ctrl_dst) {
+ if (!dl_list_empty(&priv->ctrl_dst)) {
/*
* Wait a second before closing the control socket if
* there are any attached monitors in order to allow
}
free_dst:
- dst = priv->ctrl_dst;
- while (dst) {
- prev = dst;
- dst = dst->next;
- os_free(prev);
- }
+ dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
+ list)
+ os_free(dst);
os_free(priv);
}
struct msghdr msg;
struct iovec io[2];
- dst = priv->ctrl_dst;
- if (priv->sock < 0 || dst == NULL)
+ if (priv->sock < 0 || dl_list_empty(&priv->ctrl_dst))
return;
res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
msg.msg_iovlen = 2;
idx = 0;
- while (dst) {
- next = dst->next;
+ dl_list_for_each_safe(dst, next, &priv->ctrl_dst, struct wpa_ctrl_dst,
+ list) {
if (level >= dst->debug_level) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
(u8 *) dst->addr.sun_path, dst->addrlen -
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
- if (dst->errors > 10 || _errno == ENOENT) {
+ if (dst->errors > 1000 ||
+ (_errno != ENOBUFS && dst->errors > 10) ||
+ _errno == ENOENT) {
wpa_supplicant_ctrl_iface_detach(
priv, &dst->addr,
dst->addrlen);
dst->errors = 0;
}
idx++;
- dst = next;
}
}
}
os_memset(&addr, 0, sizeof(addr));
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;