mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
miracled: support managed wpa_supplicant
If miracled is spawned with --manage-wifi, we run our own copy of wpa_supplicant on managed devices. This is meant for testing purposes only. Hopefully, network-manages like NM or connman will provide a P2P API at some time so we can switch. Until then, we allow the user to control who is in charge of wpa_supplicant. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
5fb83c9159
commit
6a37cbe6b8
6 changed files with 277 additions and 11 deletions
|
@ -444,6 +444,25 @@ static int link_dbus_get_interface(sd_bus *bus,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_get_running(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct link *l = data;
|
||||
int r, val;
|
||||
|
||||
val = l->running;
|
||||
r = sd_bus_message_append_basic(reply, 'b', &val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_get_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
|
@ -503,6 +522,11 @@ static const sd_bus_vtable link_dbus_vtable[] = {
|
|||
link_dbus_get_interface,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Running",
|
||||
"b",
|
||||
link_dbus_get_running,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("Name",
|
||||
"s",
|
||||
link_dbus_get_name,
|
||||
|
|
|
@ -138,23 +138,17 @@ static void link_wifi_event_fn(struct wifi *w, void *data,
|
|||
}
|
||||
}
|
||||
|
||||
static int link_wifi_init(struct link *l)
|
||||
static int link_wifi_start(struct link *l)
|
||||
{
|
||||
_shl_cleanup_free_ char *path = NULL;
|
||||
struct wifi_dev *d;
|
||||
int r;
|
||||
char *path;
|
||||
|
||||
r = wifi_new(l->m->event, link_wifi_event_fn, l, &l->w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
path = shl_strcat("/run/wpa_supplicant/", l->interface);
|
||||
path = shl_strjoin(arg_wpa_rundir, "/", l->interface, NULL);
|
||||
if (!path)
|
||||
return log_ENOMEM();
|
||||
|
||||
r = wifi_open(l->w, path);
|
||||
free(path);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -168,8 +162,104 @@ static int link_wifi_init(struct link *l)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int link_wifi_child_fn(sd_event_source *source,
|
||||
const siginfo_t *si,
|
||||
void *data)
|
||||
{
|
||||
struct link *l = data;
|
||||
|
||||
log_error("wpa_supplicant died unexpectedly on link %s", l->name);
|
||||
|
||||
link_free(l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_wifi_startup_fn(sd_event_source *source,
|
||||
uint64_t usec,
|
||||
void *data)
|
||||
{
|
||||
struct link *l = data;
|
||||
int r;
|
||||
|
||||
r = link_wifi_start(l);
|
||||
if (r < 0) {
|
||||
if (wifi_is_open(l->w)) {
|
||||
log_error("cannot start wifi on link %s", l->name);
|
||||
link_free(l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reschedule timer */
|
||||
sd_event_source_set_time(source,
|
||||
now(CLOCK_MONOTONIC) + 200 * 1000);
|
||||
sd_event_source_set_enabled(source, SD_EVENT_ON);
|
||||
log_debug("wpa_supplicant startup still ongoing, reschedule..");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("wpa_supplicant startup finished on link %s", l->name);
|
||||
|
||||
sd_event_source_set_enabled(source, SD_EVENT_OFF);
|
||||
l->running = true;
|
||||
link_dbus_properties_changed(l, "Running", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_wifi_init(struct link *l)
|
||||
{
|
||||
_shl_cleanup_free_ char *path = NULL;
|
||||
int r;
|
||||
|
||||
r = wifi_new(l->m->event, link_wifi_event_fn, l, &l->w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!arg_manage_wifi) {
|
||||
r = link_wifi_start(l);
|
||||
if (r < 0)
|
||||
log_error("cannot open wpa_supplicant socket for link %s",
|
||||
l->name);
|
||||
else
|
||||
l->running = true;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
path = shl_strcat(arg_wpa_bindir, "/wpa_supplicant");
|
||||
if (!path)
|
||||
return log_ENOMEM();
|
||||
|
||||
r = wifi_spawn_supplicant(l->w, arg_wpa_rundir, path, l->interface);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_add_child(l->m->event,
|
||||
wifi_get_supplicant_pid(l->w),
|
||||
WEXITED,
|
||||
link_wifi_child_fn,
|
||||
l,
|
||||
&l->wpa_child_source);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_add_monotonic(l->m->event,
|
||||
now(CLOCK_MONOTONIC) + 200 * 1000,
|
||||
0,
|
||||
link_wifi_startup_fn,
|
||||
l,
|
||||
&l->wpa_startup_source);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void link_wifi_destroy(struct link *l)
|
||||
{
|
||||
sd_event_source_unref(l->wpa_startup_source);
|
||||
sd_event_source_unref(l->wpa_child_source);
|
||||
wifi_close(l->w);
|
||||
wifi_free(l->w);
|
||||
}
|
||||
|
@ -227,6 +317,7 @@ int link_new(struct manager *m,
|
|||
|
||||
switch (l->type) {
|
||||
case LINK_VIRTUAL:
|
||||
l->running = true;
|
||||
break;
|
||||
case LINK_WIFI:
|
||||
r = link_wifi_init(l);
|
||||
|
|
|
@ -76,6 +76,8 @@ struct wifi {
|
|||
char *reply_buf;
|
||||
size_t reply_buf_size;
|
||||
|
||||
pid_t wpa_pid;
|
||||
|
||||
struct wfd_wpa_ctrl *wpa;
|
||||
sd_event_source *wpa_source;
|
||||
struct shl_dlist devs;
|
||||
|
@ -784,10 +786,27 @@ error:
|
|||
|
||||
void wifi_free(struct wifi *w)
|
||||
{
|
||||
int r;
|
||||
pid_t rp;
|
||||
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
wifi_close(w);
|
||||
|
||||
if (w->wpa_pid > 0) {
|
||||
log_debug("killing wpa_supplicant pid:%d and waiting for exit..",
|
||||
w->wpa_pid);
|
||||
r = kill(w->wpa_pid, SIGTERM);
|
||||
if (r >= 0)
|
||||
rp = waitpid(w->wpa_pid, NULL, 0);
|
||||
if (r < 0 || rp != w->wpa_pid) {
|
||||
r = kill(w->wpa_pid, SIGKILL);
|
||||
if (r >= 0)
|
||||
waitpid(w->wpa_pid, &r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sd_event_source_unref(w->wpa_source);
|
||||
wfd_wpa_ctrl_unref(w->wpa);
|
||||
free(w->reply_buf);
|
||||
|
@ -832,6 +851,88 @@ static int wifi_read_all_peers(struct wifi *w)
|
|||
return (r == -EAGAIN) ? 0 : r;
|
||||
}
|
||||
|
||||
pid_t wifi_get_supplicant_pid(struct wifi *w)
|
||||
{
|
||||
if (!w)
|
||||
return 0;
|
||||
|
||||
return w->wpa_pid;
|
||||
}
|
||||
|
||||
static void wifi_run_supplicant(struct wifi *w,
|
||||
const char *rundir,
|
||||
const char *binary,
|
||||
const char *ifname)
|
||||
{
|
||||
char *argv[64];
|
||||
int i;
|
||||
sigset_t mask;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
|
||||
/* redirect stdout to stderr for wpa_supplicant */
|
||||
dup2(2, 1);
|
||||
|
||||
/* initialize wpa_supplicant args */
|
||||
i = 0;
|
||||
argv[i++] = (char*)binary;
|
||||
argv[i++] = "-Dnl80211";
|
||||
argv[i++] = "-qq";
|
||||
argv[i++] = "-C";
|
||||
argv[i++] = (char*)rundir;
|
||||
argv[i++] = "-i";
|
||||
argv[i++] = (char*)ifname;
|
||||
argv[i++] = "-p p2p_device=1";
|
||||
argv[i] = NULL;
|
||||
|
||||
/* execute wpa_supplicant; if it fails, the caller issues exit(1) */
|
||||
execve(argv[0], argv, environ);
|
||||
}
|
||||
|
||||
int wifi_spawn_supplicant(struct wifi *w,
|
||||
const char *rundir,
|
||||
const char *binary,
|
||||
const char *ifname)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
if (!w)
|
||||
return log_EINVAL();
|
||||
if (w->wpa_pid > 0)
|
||||
return 0;
|
||||
|
||||
if (access(binary, X_OK) < 0) {
|
||||
log_error("execution of wpa_supplicant-binary (%s) not allowed: %m",
|
||||
binary);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
return log_ERRNO();
|
||||
} else if (!pid) {
|
||||
wifi_run_supplicant(w, rundir, binary, ifname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
w->wpa_pid = pid;
|
||||
log_info("waiting for wpa_supplicant (pid: %d) startup on %s..",
|
||||
(int)pid, ifname);
|
||||
|
||||
/* Ouh, yeah.. waiting for wpa_supplicant to start up is.. awful..
|
||||
* We could use inotify on the ctrl-socket/dir, but these might be
|
||||
* left-overs from previous runs and thus might get destroyed first.
|
||||
* And there're some more races.. so lets just do nothing and fire
|
||||
* a 100ms timer repeatedly in the parent. This gives wpa_supplicant
|
||||
* enough time to start up and we can test the connection from time to
|
||||
* time.
|
||||
* We just need to make sure to catch SIGCHLD so we stop trying if
|
||||
* wpa_supplicant dies.. All done in the parent. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_open(struct wifi *w, const char *wpa_path)
|
||||
{
|
||||
int r;
|
||||
|
@ -845,7 +946,7 @@ int wifi_open(struct wifi *w, const char *wpa_path)
|
|||
|
||||
r = wfd_wpa_ctrl_open(w->wpa, wpa_path);
|
||||
if (r < 0) {
|
||||
log_error("cannot open wpa_supplicant socket %s: %d",
|
||||
log_debug("cannot open wpa_supplicant socket %s: %d",
|
||||
wpa_path, r);
|
||||
goto error;
|
||||
}
|
||||
|
@ -880,7 +981,6 @@ void wifi_close(struct wifi *w)
|
|||
}
|
||||
|
||||
wfd_wpa_ctrl_close(w->wpa);
|
||||
w->wpa = NULL;
|
||||
}
|
||||
|
||||
int wifi_set_discoverable(struct wifi *w, bool on)
|
||||
|
|
|
@ -97,6 +97,12 @@ void wifi_free(struct wifi *w);
|
|||
void wifi_set_data(struct wifi *w, void *data);
|
||||
void *wifi_get_data(struct wifi *w);
|
||||
|
||||
pid_t wifi_get_supplicant_pid(struct wifi *w);
|
||||
int wifi_spawn_supplicant(struct wifi *w,
|
||||
const char *rundir,
|
||||
const char *binary,
|
||||
const char *ifname);
|
||||
|
||||
bool wifi_is_open(struct wifi *w);
|
||||
int wifi_open(struct wifi *w, const char *wpa_path);
|
||||
void wifi_close(struct wifi *w);
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
#include "shl_log.h"
|
||||
#include "shl_util.h"
|
||||
|
||||
bool arg_manage_wifi = false;
|
||||
const char *arg_wpa_rundir = "/run/wpa_supplicant";
|
||||
const char *arg_wpa_bindir = "/usr/bin";
|
||||
|
||||
/*
|
||||
* Peer Handling
|
||||
*/
|
||||
|
@ -406,13 +410,26 @@ static int manager_run(struct manager *m)
|
|||
|
||||
static int help(void)
|
||||
{
|
||||
/*
|
||||
* 80-char barrier:
|
||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
*/
|
||||
printf("%s [OPTIONS...] ...\n\n"
|
||||
"Wifi-Display Daemon.\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --log-level <lvl> Maximum level for log messages\n"
|
||||
" --log-time Prefix log-messages with timestamp\n"
|
||||
"\n"
|
||||
" --manage-wifi Enable internal wifi-management via wpa_supplicant if\n"
|
||||
" they're not managed externally (like NetworkManager)\n"
|
||||
" --wpa-rundir <dir> wpa_supplicant runtime dir [/run/wpa_supplicant]\n"
|
||||
" --wpa-bindir <dir> wpa_supplicant binary dir [/usr/bin]\n"
|
||||
, program_invocation_short_name);
|
||||
/*
|
||||
* 80-char barrier:
|
||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -423,12 +440,20 @@ static int parse_argv(int argc, char *argv[])
|
|||
ARG_VERSION = 0x100,
|
||||
ARG_LOG_LEVEL,
|
||||
ARG_LOG_TIME,
|
||||
|
||||
ARG_MANAGE_WIFI,
|
||||
ARG_WPA_RUNDIR,
|
||||
ARG_WPA_BINDIR,
|
||||
};
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
||||
|
||||
{ "manage-wifi", no_argument, NULL, ARG_MANAGE_WIFI },
|
||||
{ "wpa-rundir", required_argument, NULL, ARG_WPA_RUNDIR },
|
||||
{ "wpa-bindir", required_argument, NULL, ARG_WPA_BINDIR },
|
||||
{}
|
||||
};
|
||||
int c;
|
||||
|
@ -446,6 +471,16 @@ static int parse_argv(int argc, char *argv[])
|
|||
case ARG_LOG_TIME:
|
||||
log_init_time();
|
||||
break;
|
||||
|
||||
case ARG_MANAGE_WIFI:
|
||||
arg_manage_wifi = true;
|
||||
break;
|
||||
case ARG_WPA_RUNDIR:
|
||||
arg_wpa_rundir = optarg;
|
||||
break;
|
||||
case ARG_WPA_BINDIR:
|
||||
arg_wpa_bindir = optarg;
|
||||
break;
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,10 @@ struct link {
|
|||
struct shl_dlist peers;
|
||||
|
||||
struct wifi *w;
|
||||
sd_event_source *wpa_child_source;
|
||||
sd_event_source *wpa_startup_source;
|
||||
|
||||
bool running : 1;
|
||||
};
|
||||
|
||||
#define link_from_htable(_l) \
|
||||
|
@ -166,4 +170,10 @@ void link_dbus_scan_stopped(struct link *l);
|
|||
void link_dbus_added(struct link *l);
|
||||
void link_dbus_removed(struct link *l);
|
||||
|
||||
/* cli arguments */
|
||||
|
||||
extern bool arg_manage_wifi;
|
||||
extern const char *arg_wpa_rundir;
|
||||
extern const char *arg_wpa_bindir;
|
||||
|
||||
#endif /* MIRACLED_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue