hostapd: Add global control interface

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Shan Palanisamy 2011-12-20 17:10:47 +02:00 committed by Jouni Malinen
parent 3776ac73b2
commit c90fd48514
4 changed files with 236 additions and 2 deletions

View file

@ -1092,6 +1092,191 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
} }
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
char buf[256];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
char reply[24];
int reply_len;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
perror("recvfrom(ctrl_iface)");
return;
}
buf[res] = '\0';
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
} else {
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
"ignored");
reply_len = -1;
}
if (reply_len < 0) {
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
}
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
}
static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
{
char *buf;
size_t len;
if (interface->global_iface_path == NULL)
return NULL;
len = os_strlen(interface->global_iface_path) +
os_strlen(interface->global_iface_name) + 2;
buf = os_malloc(len);
if (buf == NULL)
return NULL;
os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
interface->global_iface_name);
buf[len - 1] = '\0';
return buf;
}
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
{
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
if (interface->global_iface_path == NULL) {
wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
return 0;
}
if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
if (errno == EEXIST) {
wpa_printf(MSG_DEBUG, "Using existing control "
"interface directory.");
} else {
perror("mkdir[ctrl_interface]");
goto fail;
}
}
if (os_strlen(interface->global_iface_path) + 1 +
os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
goto fail;
s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket(PF_UNIX)");
goto fail;
}
os_memset(&addr, 0, sizeof(addr));
#ifdef __FreeBSD__
addr.sun_len = sizeof(addr);
#endif /* __FreeBSD__ */
addr.sun_family = AF_UNIX;
fname = hostapd_global_ctrl_iface_path(interface);
if (fname == NULL)
goto fail;
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
strerror(errno));
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
" allow connections - assuming it was left"
"over from forced program termination");
if (unlink(fname) < 0) {
perror("unlink[ctrl_iface]");
wpa_printf(MSG_ERROR, "Could not unlink "
"existing ctrl_iface socket '%s'",
fname);
goto fail;
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
perror("bind(PF_UNIX)");
goto fail;
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
"ctrl_iface socket '%s'", fname);
} else {
wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
"be in use - cannot override it");
wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
"not used anymore", fname);
os_free(fname);
fname = NULL;
goto fail;
}
}
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
perror("chmod[ctrl_interface/ifname]");
goto fail;
}
os_free(fname);
interface->global_ctrl_sock = s;
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
return 0;
fail:
if (s >= 0)
close(s);
if (fname) {
unlink(fname);
os_free(fname);
}
return -1;
}
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
{
char *fname = NULL;
if (interfaces->global_ctrl_sock > -1) {
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
close(interfaces->global_ctrl_sock);
interfaces->global_ctrl_sock = -1;
fname = hostapd_global_ctrl_iface_path(interfaces);
if (fname) {
unlink(fname);
os_free(fname);
}
if (interfaces->global_iface_path &&
rmdir(interfaces->global_iface_path) < 0) {
if (errno == ENOTEMPTY) {
wpa_printf(MSG_DEBUG, "Control interface "
"directory not empty - leaving it "
"behind");
} else {
perror("rmdir[ctrl_interface]");
}
}
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
}
}
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
const char *buf, size_t len) const char *buf, size_t len)
{ {

View file

@ -12,6 +12,8 @@
#ifndef CONFIG_NO_CTRL_IFACE #ifndef CONFIG_NO_CTRL_IFACE
int hostapd_ctrl_iface_init(struct hostapd_data *hapd); int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
#else /* CONFIG_NO_CTRL_IFACE */ #else /* CONFIG_NO_CTRL_IFACE */
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd) static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{ {
@ -21,6 +23,17 @@ static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
{ {
} }
static inline int
hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
{
return 0;
}
static inline void
hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
{
}
#endif /* CONFIG_NO_CTRL_IFACE */ #endif /* CONFIG_NO_CTRL_IFACE */
#endif /* CTRL_IFACE_H */ #endif /* CTRL_IFACE_H */

View file

@ -494,13 +494,15 @@ static void usage(void)
fprintf(stderr, fprintf(stderr,
"\n" "\n"
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] " "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"<configuration file(s)>\n" "\\\n"
" [-g <global ctrl_iface>] <configuration file(s)>\n"
"\n" "\n"
"options:\n" "options:\n"
" -h show this usage\n" " -h show this usage\n"
" -d show more debug messages (-dd for even more)\n" " -d show more debug messages (-dd for even more)\n"
" -B run daemon in the background\n" " -B run daemon in the background\n"
" -e entropy file\n" " -e entropy file\n"
" -g global control interface path\n"
" -P PID file\n" " -P PID file\n"
" -K include key data in debug messages\n" " -K include key data in debug messages\n"
#ifdef CONFIG_DEBUG_FILE #ifdef CONFIG_DEBUG_FILE
@ -522,6 +524,28 @@ static const char * hostapd_msg_ifname_cb(void *ctx)
} }
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
const char *path)
{
char *pos;
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = os_strdup(path);
if (interfaces->global_iface_path == NULL)
return -1;
pos = os_strrchr(interfaces->global_iface_path, '/');
if (pos == NULL) {
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
return -1;
}
*pos = '\0';
interfaces->global_iface_name = pos + 1;
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct hapd_interfaces interfaces; struct hapd_interfaces interfaces;
@ -541,9 +565,12 @@ int main(int argc, char *argv[])
interfaces.for_each_interface = hostapd_for_each_interface; interfaces.for_each_interface = hostapd_for_each_interface;
interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
for (;;) { for (;;) {
c = getopt(argc, argv, "Bde:f:hKP:tv"); c = getopt(argc, argv, "Bde:f:hKP:tvg:");
if (c < 0) if (c < 0)
break; break;
switch (c) { switch (c) {
@ -578,6 +605,9 @@ int main(int argc, char *argv[])
show_version(); show_version();
exit(1); exit(1);
break; break;
case 'g':
hostapd_get_global_ctrl_iface(&interfaces, optarg);
break;
default: default:
usage(); usage();
@ -613,12 +643,15 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) if (hostapd_global_run(&interfaces, daemonize, pid_file))
goto out; goto out;
ret = 0; ret = 0;
out: out:
hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */ /* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++) for (i = 0; i < interfaces.count; i++)
hostapd_interface_deinit_free(interfaces.iface[i]); hostapd_interface_deinit_free(interfaces.iface[i]);

View file

@ -35,6 +35,9 @@ struct hapd_interfaces {
void *ctx), void *ctx); void *ctx), void *ctx);
size_t count; size_t count;
int global_ctrl_sock;
char *global_iface_path;
char *global_iface_name;
struct hostapd_iface **iface; struct hostapd_iface **iface;
}; };