mirror of
https://github.com/albfan/miraclecast.git
synced 2025-02-12 16:11:54 +00:00
Add new miracle-wifid daemon
The miracle-wifid daemon is a rewrite of the wifi-related parts of miracled. Unlike miracled, we no longer integrate the wifi-part directly into the core daemon. This way, we can easily replace the wifi-bridge with other network managers once they gain P2P capabilities. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
b0b53f986c
commit
18a5094bc0
9 changed files with 4512 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,6 +22,7 @@ configure
|
|||
libtool
|
||||
m4/
|
||||
miracle-dhcp
|
||||
miracle-wifid
|
||||
miraclectl
|
||||
miracled
|
||||
stamp-h1
|
||||
|
|
21
Makefile.am
21
Makefile.am
|
@ -86,6 +86,27 @@ libmiracle_shared_la_CPPFLAGS = $(AM_CPPFLAGS)
|
|||
libmiracle_shared_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
libmiracle_shared_la_LIBADD = $(AM_LIBADD)
|
||||
|
||||
#
|
||||
# miracle-wifid
|
||||
#
|
||||
|
||||
bin_PROGRAMS += miracle-wifid
|
||||
|
||||
miracle_wifid_SOURCES = \
|
||||
src/wifi/wifid.h \
|
||||
src/wifi/wifid.c \
|
||||
src/wifi/wifid-dbus.c \
|
||||
src/wifi/wifid-link.c \
|
||||
src/wifi/wifid-peer.c \
|
||||
src/wifi/wifid-supplicant.c
|
||||
miracle_wifid_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(DEPS_CFLAGS)
|
||||
miracle_wifid_LDADD = \
|
||||
libmiracle-shared.la \
|
||||
$(DEPS_LIBS)
|
||||
miracle_wifid_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
#
|
||||
# miraclectl
|
||||
#
|
||||
|
|
|
@ -10,31 +10,48 @@
|
|||
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.miracle"/>
|
||||
<allow own="org.freedesktop.miracle.wifi"/>
|
||||
<allow send_destination="org.freedesktop.miracle"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"/>
|
||||
<allow receive_sender="org.freedesktop.miracle"/>
|
||||
<allow receive_sender="org.freedesktop.miracle.wifi"/>
|
||||
</policy>
|
||||
|
||||
<policy context="default">
|
||||
<deny send_destination="org.freedesktop.miracle"/>
|
||||
<deny send_destination="org.freedesktop.miracle.wifi"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.miracle"
|
||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"
|
||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.miracle"
|
||||
send_interface="org.freedesktop.DBus.Peer"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"
|
||||
send_interface="org.freedesktop.DBus.Peer"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.miracle"
|
||||
send_interface="org.freedesktop.DBus.ObjectManager"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"
|
||||
send_interface="org.freedesktop.DBus.ObjectManager"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.miracle"
|
||||
send_interface="org.freedesktop.DBus.Properties"
|
||||
send_member="Get"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"
|
||||
send_interface="org.freedesktop.DBus.Properties"
|
||||
send_member="Get"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.miracle"
|
||||
send_interface="org.freedesktop.DBus.Properties"
|
||||
send_member="GetAll"/>
|
||||
<allow send_destination="org.freedesktop.miracle.wifi"
|
||||
send_interface="org.freedesktop.DBus.Properties"
|
||||
send_member="GetAll"/>
|
||||
|
||||
<allow receive_sender="org.freedesktop.miracle"/>
|
||||
<allow receive_sender="org.freedesktop.miracle.wifi"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
||||
|
|
835
src/wifi/wifid-dbus.c
Normal file
835
src/wifi/wifid-dbus.c
Normal file
|
@ -0,0 +1,835 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define LOG_SUBSYSTEM "dbus"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "shl_log.h"
|
||||
#include "shl_util.h"
|
||||
#include "util.h"
|
||||
#include "wifid.h"
|
||||
|
||||
static char *peer_dbus_get_path(struct peer *p)
|
||||
{
|
||||
char buf[128], *node;
|
||||
int r;
|
||||
|
||||
sprintf(buf, "%s@%u", p->p2p_mac, p->l->ifindex);
|
||||
|
||||
r = sd_bus_path_encode("/org/freedesktop/miracle/wifi/peer",
|
||||
buf,
|
||||
&node);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static char *link_dbus_get_path(struct link *l)
|
||||
{
|
||||
char buf[128], *node;
|
||||
int r;
|
||||
|
||||
sprintf(buf, "%u", l->ifindex);
|
||||
|
||||
r = sd_bus_path_encode("/org/freedesktop/miracle/wifi/link",
|
||||
buf,
|
||||
&node);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peer DBus
|
||||
*/
|
||||
|
||||
static int peer_dbus_connect(sd_bus *bus, sd_bus_message *msg,
|
||||
void *data, sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
const char *prov, *pin;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(msg, "ss", &prov, &pin);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!*prov || !strcmp(prov, "auto"))
|
||||
prov = NULL;
|
||||
if (!*pin)
|
||||
pin = NULL;
|
||||
|
||||
r = peer_connect(p, prov, pin);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(msg, NULL);
|
||||
}
|
||||
|
||||
static int peer_dbus_disconnect(sd_bus *bus, sd_bus_message *msg,
|
||||
void *data, sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
|
||||
peer_disconnect(p);
|
||||
return sd_bus_reply_method_return(msg, NULL);
|
||||
}
|
||||
|
||||
static int peer_dbus_get_link(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
node = link_dbus_get_path(p->l);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
r = sd_bus_message_append_basic(reply, 'o', node);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_p2p_mac(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append_basic(reply, 's', p->p2p_mac);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_friendly_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
name = peer_get_friendly_name(p);
|
||||
if (!name)
|
||||
name = "<unknown>";
|
||||
|
||||
r = sd_bus_message_append_basic(reply, 's', name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_connected(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append(reply, "b", p->connected);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_interface(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append(reply, "s", peer_get_interface(p));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_local_address(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append(reply, "s", peer_get_local_address(p));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peer_dbus_get_remote_address(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct peer *p = data;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append(reply, "s", peer_get_remote_address(p));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable peer_dbus_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("Connect",
|
||||
"ss",
|
||||
NULL,
|
||||
peer_dbus_connect,
|
||||
0),
|
||||
SD_BUS_METHOD("Disconnect",
|
||||
NULL,
|
||||
NULL,
|
||||
peer_dbus_disconnect,
|
||||
0),
|
||||
SD_BUS_PROPERTY("Link",
|
||||
"o",
|
||||
peer_dbus_get_link,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("P2PMac",
|
||||
"s",
|
||||
peer_dbus_get_p2p_mac,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FriendlyName",
|
||||
"s",
|
||||
peer_dbus_get_friendly_name,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Connected",
|
||||
"b",
|
||||
peer_dbus_get_connected,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Interface",
|
||||
"s",
|
||||
peer_dbus_get_interface,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("LocalAddress",
|
||||
"s",
|
||||
peer_dbus_get_local_address,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("RemoteAddress",
|
||||
"s",
|
||||
peer_dbus_get_remote_address,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static int peer_dbus_find(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *data,
|
||||
void **found,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
_shl_free_ char *label = NULL;
|
||||
struct manager *m = data;
|
||||
struct link *l;
|
||||
struct peer *p;
|
||||
char *sep;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode(path,
|
||||
"/org/freedesktop/miracle/wifi/peer",
|
||||
&label);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
sep = strchr(label, '@');
|
||||
if (sep) {
|
||||
*sep = 0;
|
||||
l = manager_find_link_by_label(m, sep + 1);
|
||||
if (!l || !l->public)
|
||||
return 0;
|
||||
|
||||
p = link_find_peer_by_label(l, label);
|
||||
if (!p || !p->public)
|
||||
return 0;
|
||||
} else {
|
||||
p = NULL;
|
||||
|
||||
MANAGER_FOREACH_LINK(l, m) {
|
||||
if (!l->public)
|
||||
continue;
|
||||
|
||||
p = link_find_peer_by_label(l, label);
|
||||
if (p)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p || !p->public)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*found = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void peer_dbus_properties_changed(struct peer *p, const char *prop, ...)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
char **strv;
|
||||
int r;
|
||||
|
||||
if (!p->public)
|
||||
return;
|
||||
|
||||
node = peer_dbus_get_path(p);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
strv = strv_from_stdarg_alloca(prop);
|
||||
r = sd_bus_emit_properties_changed_strv(p->l->m->bus,
|
||||
node,
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
strv);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
void peer_dbus_provision_discovery(struct peer *p,
|
||||
const char *type,
|
||||
const char *pin)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
int r;
|
||||
|
||||
if (!type)
|
||||
return;
|
||||
if (!pin)
|
||||
pin = "";
|
||||
|
||||
node = peer_dbus_get_path(p);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
r = sd_bus_emit_signal(p->l->m->bus,
|
||||
node,
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
"ProvisionDiscovery",
|
||||
"ss", type, pin);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
void peer_dbus_added(struct peer *p)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
int r;
|
||||
|
||||
node = peer_dbus_get_path(p);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
r = sd_bus_emit_interfaces_added(p->l->m->bus,
|
||||
node,
|
||||
/*
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"org.freedesktop.DBus.Introspectable",
|
||||
*/
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
NULL);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
void peer_dbus_removed(struct peer *p)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
int r;
|
||||
|
||||
node = peer_dbus_get_path(p);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
r = sd_bus_emit_interfaces_removed(p->l->m->bus,
|
||||
node,
|
||||
/*
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"org.freedesktop.DBus.Introspectable",
|
||||
*/
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
NULL);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Link DBus
|
||||
*/
|
||||
|
||||
static int link_dbus_get_interface_index(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;
|
||||
|
||||
r = sd_bus_message_append_basic(reply, 'u', &l->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_get_interface_name(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;
|
||||
|
||||
r = sd_bus_message_append_basic(reply, 's', l->ifname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_get_friendly_name(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;
|
||||
|
||||
r = sd_bus_message_append(reply, "s", link_get_friendly_name(l));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_set_friendly_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *value,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct link *l = data;
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(value, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!name || !*name)
|
||||
return -EINVAL;
|
||||
|
||||
return link_set_friendly_name(l, name);
|
||||
}
|
||||
|
||||
static int link_dbus_get_p2p_scanning(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;
|
||||
|
||||
r = sd_bus_message_append(reply, "b", link_get_p2p_scanning(l));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_dbus_set_p2p_scanning(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *value,
|
||||
void *data,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct link *l = data;
|
||||
bool val;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(value, "b", &val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return link_set_p2p_scanning(l, val);
|
||||
}
|
||||
|
||||
static const sd_bus_vtable link_dbus_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("InterfaceIndex",
|
||||
"u",
|
||||
link_dbus_get_interface_index,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("InterfaceName",
|
||||
"s",
|
||||
link_dbus_get_interface_name,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("FriendlyName",
|
||||
"s",
|
||||
link_dbus_get_friendly_name,
|
||||
link_dbus_set_friendly_name,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("P2PScanning",
|
||||
"b",
|
||||
link_dbus_get_p2p_scanning,
|
||||
link_dbus_set_p2p_scanning,
|
||||
0,
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static int link_dbus_find(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *data,
|
||||
void **found,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
_shl_free_ char *label = NULL;
|
||||
struct manager *m = data;
|
||||
struct link *l;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode(path,
|
||||
"/org/freedesktop/miracle/wifi/link",
|
||||
&label);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
l = manager_find_link_by_label(m, label);
|
||||
if (!l || !l->public)
|
||||
return 0;
|
||||
|
||||
*found = l;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void link_dbus_properties_changed(struct link *l, const char *prop, ...)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
char **strv;
|
||||
int r;
|
||||
|
||||
if (!l->public)
|
||||
return;
|
||||
|
||||
node = link_dbus_get_path(l);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
strv = strv_from_stdarg_alloca(prop);
|
||||
r = sd_bus_emit_properties_changed_strv(l->m->bus,
|
||||
node,
|
||||
"org.freedesktop.miracle.wifi.Link",
|
||||
strv);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
void link_dbus_added(struct link *l)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
int r;
|
||||
|
||||
node = link_dbus_get_path(l);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
r = sd_bus_emit_interfaces_added(l->m->bus,
|
||||
node,
|
||||
/*
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"org.freedesktop.DBus.Introspectable",
|
||||
*/
|
||||
"org.freedesktop.miracle.wifi.Link",
|
||||
NULL);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
void link_dbus_removed(struct link *l)
|
||||
{
|
||||
_shl_free_ char *node = NULL;
|
||||
int r;
|
||||
|
||||
node = link_dbus_get_path(l);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
r = sd_bus_emit_interfaces_removed(l->m->bus,
|
||||
node,
|
||||
/*
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"org.freedesktop.DBus.Introspectable",
|
||||
*/
|
||||
"org.freedesktop.miracle.wifi.Link",
|
||||
NULL);
|
||||
if (r < 0)
|
||||
log_vERR(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Manager DBus
|
||||
*/
|
||||
|
||||
static const sd_bus_vtable manager_dbus_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static int manager_dbus_enumerate(sd_bus *bus,
|
||||
const char *path,
|
||||
void *data,
|
||||
char ***out,
|
||||
sd_bus_error *err)
|
||||
{
|
||||
struct manager *m = data;
|
||||
struct link *l;
|
||||
struct peer *p;
|
||||
size_t i, peer_cnt;
|
||||
char **nodes, *node;
|
||||
int r;
|
||||
|
||||
peer_cnt = 0;
|
||||
MANAGER_FOREACH_LINK(l, m)
|
||||
if (l->public)
|
||||
peer_cnt += l->peer_cnt;
|
||||
|
||||
nodes = malloc(sizeof(*nodes) * (m->link_cnt + peer_cnt + 2));
|
||||
if (!nodes)
|
||||
return log_ENOMEM();
|
||||
|
||||
i = 0;
|
||||
MANAGER_FOREACH_LINK(l, m) {
|
||||
if (i >= m->link_cnt + peer_cnt) {
|
||||
log_warning("overflow: skipping link %s",
|
||||
l->ifname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!l->public)
|
||||
continue;
|
||||
|
||||
node = link_dbus_get_path(l);
|
||||
if (!node)
|
||||
goto error;
|
||||
|
||||
nodes[i++] = node;
|
||||
|
||||
LINK_FOREACH_PEER(p, l) {
|
||||
if (i >= m->link_cnt + peer_cnt) {
|
||||
log_warning("overflow: skipping peer %s",
|
||||
p->p2p_mac);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!p->public)
|
||||
continue;
|
||||
|
||||
node = peer_dbus_get_path(p);
|
||||
if (!node)
|
||||
goto error;
|
||||
|
||||
nodes[i++] = node;
|
||||
}
|
||||
}
|
||||
|
||||
node = strdup("/org/freedesktop/miracle/wifi");
|
||||
if (!node) {
|
||||
r = log_ENOMEM();
|
||||
goto error;
|
||||
}
|
||||
|
||||
nodes[i++] = node;
|
||||
nodes[i] = NULL;
|
||||
*out = nodes;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
while (i--)
|
||||
free(nodes[i]);
|
||||
free(nodes);
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_dbus_connect(struct manager *m)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = sd_bus_add_object_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi",
|
||||
"org.freedesktop.miracle.wifi.Manager",
|
||||
manager_dbus_vtable,
|
||||
m);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_add_node_enumerator(m->bus,
|
||||
"/org/freedesktop/miracle/wifi",
|
||||
manager_dbus_enumerate,
|
||||
m);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_add_fallback_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi/link",
|
||||
"org.freedesktop.miracle.wifi.Link",
|
||||
link_dbus_vtable,
|
||||
link_dbus_find,
|
||||
m);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_add_fallback_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi/peer",
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
peer_dbus_vtable,
|
||||
peer_dbus_find,
|
||||
m);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_add_object_manager(m->bus, "/org/freedesktop/miracle/wifi");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.miracle.wifi", 0);
|
||||
if (r < 0) {
|
||||
log_error("cannot claim org.freedesktop.miracle.wifi bus-name: %d",
|
||||
r);
|
||||
goto error_silent;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
log_ERR(r);
|
||||
error_silent:
|
||||
manager_dbus_disconnect(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
void manager_dbus_disconnect(struct manager *m)
|
||||
{
|
||||
if (!m || !m->bus)
|
||||
return;
|
||||
|
||||
sd_bus_release_name(m->bus, "org.freedesktop.miracle.wifi");
|
||||
sd_bus_remove_object_manager(m->bus, "/org/freedesktop/miracle/wifi");
|
||||
sd_bus_remove_fallback_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi/peer",
|
||||
"org.freedesktop.miracle.wifi.Peer",
|
||||
peer_dbus_vtable,
|
||||
peer_dbus_find,
|
||||
m);
|
||||
sd_bus_remove_fallback_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi/link",
|
||||
"org.freedesktop.miracle.wifi.Link",
|
||||
link_dbus_vtable,
|
||||
link_dbus_find,
|
||||
m);
|
||||
sd_bus_remove_node_enumerator(m->bus,
|
||||
"/org/freedesktop/miracle/wifi",
|
||||
manager_dbus_enumerate,
|
||||
m);
|
||||
sd_bus_remove_object_vtable(m->bus,
|
||||
"/org/freedesktop/miracle/wifi",
|
||||
"org.freedesktop.miracle.wifi.Manager",
|
||||
manager_dbus_vtable,
|
||||
m);
|
||||
}
|
262
src/wifi/wifid-link.c
Normal file
262
src/wifi/wifid-link.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define LOG_SUBSYSTEM "link"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include "shl_dlist.h"
|
||||
#include "shl_log.h"
|
||||
#include "shl_util.h"
|
||||
#include "util.h"
|
||||
#include "wifid.h"
|
||||
|
||||
/*
|
||||
* Link Handling
|
||||
*/
|
||||
|
||||
struct peer *link_find_peer(struct link *l, const char *p2p_mac)
|
||||
{
|
||||
char **elem;
|
||||
bool res;
|
||||
|
||||
res = shl_htable_lookup_str(&l->peers, p2p_mac, NULL, &elem);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
return peer_from_htable(elem);
|
||||
}
|
||||
|
||||
struct peer *link_find_peer_by_label(struct link *l, const char *label)
|
||||
{
|
||||
char mac[MAC_STRLEN];
|
||||
|
||||
reformat_mac(mac, label);
|
||||
|
||||
return link_find_peer(l, mac);
|
||||
}
|
||||
|
||||
int link_new(struct manager *m,
|
||||
unsigned int ifindex,
|
||||
const char *ifname,
|
||||
struct link **out)
|
||||
{
|
||||
struct link *l;
|
||||
int r;
|
||||
|
||||
if (!m || !ifindex || !ifname)
|
||||
return log_EINVAL();
|
||||
|
||||
if (shl_htable_lookup_uint(&m->links, ifindex, NULL))
|
||||
return -EALREADY;
|
||||
|
||||
log_debug("new link: %s (%u)", ifname, ifindex);
|
||||
|
||||
l = calloc(1, sizeof(*l));
|
||||
if (!l)
|
||||
return log_ENOMEM();
|
||||
|
||||
l->m = m;
|
||||
l->ifindex = ifindex;
|
||||
shl_htable_init_str(&l->peers);
|
||||
|
||||
l->ifname = strdup(ifname);
|
||||
if (!l->ifname) {
|
||||
r = log_ENOMEM();
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = supplicant_new(l, &l->s);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = shl_htable_insert_uint(&m->links, &l->ifindex);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
++m->link_cnt;
|
||||
log_info("add link: %s", l->ifname);
|
||||
|
||||
if (out)
|
||||
*out = l;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
link_free(l);
|
||||
return r;
|
||||
}
|
||||
|
||||
void link_free(struct link *l)
|
||||
{
|
||||
if (!l)
|
||||
return;
|
||||
|
||||
log_debug("free link: %s (%u)", l->ifname, l->ifindex);
|
||||
|
||||
link_set_managed(l, false);
|
||||
|
||||
if (shl_htable_remove_uint(&l->m->links, l->ifindex, NULL)) {
|
||||
log_info("remove link: %s", l->ifname);
|
||||
--l->m->link_cnt;
|
||||
}
|
||||
|
||||
supplicant_free(l->s);
|
||||
|
||||
/* link_set_managed(l, false) already removed all peers */
|
||||
shl_htable_clear_str(&l->peers, NULL, NULL);
|
||||
|
||||
free(l->friendly_name);
|
||||
free(l->ifname);
|
||||
free(l);
|
||||
}
|
||||
|
||||
void link_set_managed(struct link *l, bool set)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!l)
|
||||
return log_vEINVAL();
|
||||
if (l->managed == set)
|
||||
return;
|
||||
|
||||
if (set) {
|
||||
log_info("manage link %s", l->ifname);
|
||||
|
||||
r = supplicant_start(l->s);
|
||||
if (r < 0) {
|
||||
log_error("cannot start supplicant on %s", l->ifname);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log_info("link %s no longer managed", l->ifname);
|
||||
supplicant_stop(l->s);
|
||||
}
|
||||
|
||||
l->managed = set;
|
||||
}
|
||||
|
||||
int link_renamed(struct link *l, const char *ifname)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (!l || !ifname)
|
||||
return log_EINVAL();
|
||||
if (!strcmp(l->ifname, ifname))
|
||||
return 0;
|
||||
|
||||
log_info("link %s (%u) was renamed to %s",
|
||||
l->ifname, l->ifindex, ifname);
|
||||
|
||||
t = strdup(ifname);
|
||||
if (!t)
|
||||
return log_ENOMEM();
|
||||
|
||||
free(l->ifname);
|
||||
l->ifname = t;
|
||||
|
||||
link_dbus_properties_changed(l, "InterfaceName", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_set_friendly_name(struct link *l, const char *name)
|
||||
{
|
||||
char *t;
|
||||
int r;
|
||||
|
||||
if (!l || !name || !*name)
|
||||
return log_EINVAL();
|
||||
|
||||
t = strdup(name);
|
||||
if (!t)
|
||||
return log_ENOMEM();
|
||||
|
||||
if (supplicant_is_ready(l->s)) {
|
||||
r = supplicant_set_friendly_name(l->s, name);
|
||||
if (r < 0) {
|
||||
free(t);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
free(l->friendly_name);
|
||||
l->friendly_name = t;
|
||||
link_dbus_properties_changed(l, "FriendlyName", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *link_get_friendly_name(struct link *l)
|
||||
{
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
return l->friendly_name;
|
||||
}
|
||||
|
||||
int link_set_p2p_scanning(struct link *l, bool set)
|
||||
{
|
||||
if (!l)
|
||||
return log_EINVAL();
|
||||
|
||||
if (set) {
|
||||
return supplicant_p2p_start_scan(l->s);
|
||||
} else {
|
||||
supplicant_p2p_stop_scan(l->s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool link_get_p2p_scanning(struct link *l)
|
||||
{
|
||||
return l && supplicant_p2p_scanning(l->s);
|
||||
}
|
||||
|
||||
void link_supplicant_started(struct link *l)
|
||||
{
|
||||
if (!l || l->public)
|
||||
return;
|
||||
|
||||
log_debug("link %s started", l->ifname);
|
||||
l->public = true;
|
||||
link_dbus_added(l);
|
||||
}
|
||||
|
||||
void link_supplicant_stopped(struct link *l)
|
||||
{
|
||||
if (!l || !l->public)
|
||||
return;
|
||||
|
||||
log_debug("link %s stopped", l->ifname);
|
||||
link_dbus_removed(l);
|
||||
l->public = false;
|
||||
}
|
||||
|
||||
void link_supplicant_p2p_scan_changed(struct link *l, bool new_value)
|
||||
{
|
||||
if (!l)
|
||||
return;
|
||||
|
||||
link_dbus_properties_changed(l, "P2PScanning", NULL);
|
||||
}
|
198
src/wifi/wifid-peer.c
Normal file
198
src/wifi/wifid-peer.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define LOG_SUBSYSTEM "peer"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include "shl_dlist.h"
|
||||
#include "shl_log.h"
|
||||
#include "shl_util.h"
|
||||
#include "util.h"
|
||||
#include "wifid.h"
|
||||
|
||||
/*
|
||||
* Peer Handling
|
||||
*/
|
||||
|
||||
int peer_new(struct link *l,
|
||||
const char *p2p_mac,
|
||||
struct peer **out)
|
||||
{
|
||||
char mac[MAC_STRLEN];
|
||||
struct peer *p;
|
||||
int r;
|
||||
|
||||
if (!l || !p2p_mac)
|
||||
return log_EINVAL();
|
||||
|
||||
reformat_mac(mac, p2p_mac);
|
||||
|
||||
if (shl_htable_lookup_str(&l->peers, mac, NULL, NULL))
|
||||
return -EALREADY;
|
||||
|
||||
log_debug("new peer: %s @ %s", mac, l->ifname);
|
||||
|
||||
p = calloc(1, sizeof(*p));
|
||||
if (!p)
|
||||
return log_ENOMEM();
|
||||
|
||||
p->l = l;
|
||||
p->p2p_mac = calloc(1, MAC_STRLEN);
|
||||
if (!p->p2p_mac) {
|
||||
r = log_ENOMEM();
|
||||
goto error;
|
||||
}
|
||||
strncpy(p->p2p_mac, mac, MAC_STRLEN - 1);
|
||||
|
||||
r = shl_htable_insert_str(&l->peers, &p->p2p_mac, NULL);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
++l->peer_cnt;
|
||||
log_info("add peer: %s", p->p2p_mac);
|
||||
|
||||
if (out)
|
||||
*out = p;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
peer_free(p);
|
||||
return r;
|
||||
}
|
||||
|
||||
void peer_free(struct peer *p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
log_debug("free peer: %s @ %s", p->p2p_mac, p->l->ifname);
|
||||
|
||||
if (shl_htable_remove_str(&p->l->peers, p->p2p_mac, NULL, NULL)) {
|
||||
log_info("remove peer: %s", p->p2p_mac);
|
||||
--p->l->peer_cnt;
|
||||
}
|
||||
|
||||
free(p->p2p_mac);
|
||||
free(p);
|
||||
}
|
||||
|
||||
const char *peer_get_friendly_name(struct peer *p)
|
||||
{
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
return supplicant_peer_get_friendly_name(p->sp);
|
||||
}
|
||||
|
||||
const char *peer_get_interface(struct peer *p)
|
||||
{
|
||||
if (!p || !p->connected)
|
||||
return NULL;
|
||||
|
||||
return supplicant_peer_get_interface(p->sp);
|
||||
}
|
||||
|
||||
const char *peer_get_local_address(struct peer *p)
|
||||
{
|
||||
if (!p || !p->connected)
|
||||
return NULL;
|
||||
|
||||
return supplicant_peer_get_local_address(p->sp);
|
||||
}
|
||||
|
||||
const char *peer_get_remote_address(struct peer *p)
|
||||
{
|
||||
if (!p || !p->connected)
|
||||
return NULL;
|
||||
|
||||
return supplicant_peer_get_remote_address(p->sp);
|
||||
}
|
||||
|
||||
int peer_connect(struct peer *p, const char *prov, const char *pin)
|
||||
{
|
||||
if (!p)
|
||||
return log_EINVAL();
|
||||
|
||||
return supplicant_peer_connect(p->sp, prov, pin);
|
||||
}
|
||||
|
||||
void peer_disconnect(struct peer *p)
|
||||
{
|
||||
if (!p)
|
||||
return log_vEINVAL();
|
||||
|
||||
supplicant_peer_disconnect(p->sp);
|
||||
}
|
||||
|
||||
void peer_supplicant_started(struct peer *p)
|
||||
{
|
||||
if (!p || p->public)
|
||||
return;
|
||||
|
||||
log_debug("peer %s @ %s started", p->p2p_mac, p->l->ifname);
|
||||
p->public = true;
|
||||
peer_dbus_added(p);
|
||||
}
|
||||
|
||||
void peer_supplicant_stopped(struct peer *p)
|
||||
{
|
||||
if (!p || !p->public)
|
||||
return;
|
||||
|
||||
log_debug("peer %s @ %s stopped", p->p2p_mac, p->l->ifname);
|
||||
peer_dbus_removed(p);
|
||||
p->public = false;
|
||||
}
|
||||
|
||||
void peer_supplicant_friendly_name_changed(struct peer *p)
|
||||
{
|
||||
if (!p || !p->public)
|
||||
return;
|
||||
|
||||
peer_dbus_properties_changed(p, "FriendlyName", NULL);
|
||||
}
|
||||
|
||||
void peer_supplicant_provision_discovery(struct peer *p,
|
||||
const char *prov,
|
||||
const char *pin)
|
||||
{
|
||||
if (!p || !p->public)
|
||||
return;
|
||||
|
||||
peer_dbus_provision_discovery(p, prov, pin);
|
||||
}
|
||||
|
||||
void peer_supplicant_connected_changed(struct peer *p, bool connected)
|
||||
{
|
||||
if (!p || p->connected == connected)
|
||||
return;
|
||||
|
||||
p->connected = connected;
|
||||
peer_dbus_properties_changed(p, "Connected",
|
||||
"Interface",
|
||||
"LocalAddress",
|
||||
"RemoteAddress",
|
||||
NULL);
|
||||
}
|
2440
src/wifi/wifid-supplicant.c
Normal file
2440
src/wifi/wifid-supplicant.c
Normal file
File diff suppressed because it is too large
Load diff
544
src/wifi/wifid.c
Normal file
544
src/wifi/wifid.c
Normal file
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libudev.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-daemon.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "shl_htable.h"
|
||||
#include "shl_macro.h"
|
||||
#include "shl_log.h"
|
||||
#include "shl_util.h"
|
||||
#include "util.h"
|
||||
#include "wifid.h"
|
||||
|
||||
const char *arg_wpa_bindir = "/usr/bin";
|
||||
unsigned int arg_wpa_loglevel = LOG_NOTICE;
|
||||
|
||||
/*
|
||||
* Manager Handling
|
||||
*/
|
||||
|
||||
struct link *manager_find_link(struct manager *m, unsigned int ifindex)
|
||||
{
|
||||
unsigned int *elem;
|
||||
bool res;
|
||||
|
||||
res = shl_htable_lookup_uint(&m->links, ifindex, &elem);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
return link_from_htable(elem);
|
||||
}
|
||||
|
||||
struct link *manager_find_link_by_label(struct manager *m, const char *label)
|
||||
{
|
||||
const char *next;
|
||||
unsigned int idx;
|
||||
int r;
|
||||
|
||||
r = shl_atoi_u(label, 10, &next, &idx);
|
||||
if (r < 0 || *next)
|
||||
return NULL;
|
||||
|
||||
return manager_find_link(m, idx);
|
||||
}
|
||||
|
||||
static void manager_add_udev_link(struct manager *m,
|
||||
struct udev_device *d)
|
||||
{
|
||||
struct link *l;
|
||||
unsigned int ifindex;
|
||||
const char *ifname;
|
||||
int r;
|
||||
|
||||
ifindex = ifindex_from_udev_device(d);
|
||||
if (!ifindex)
|
||||
return;
|
||||
|
||||
ifname = udev_device_get_property_value(d, "INTERFACE");
|
||||
if (!ifname)
|
||||
return;
|
||||
|
||||
/* ignore dynamic p2p interfaces */
|
||||
if (shl_startswith(ifname, "p2p-"))
|
||||
return;
|
||||
|
||||
r = link_new(m, ifindex, ifname, &l);
|
||||
if (r < 0)
|
||||
return;
|
||||
|
||||
link_set_friendly_name(l, m->friendly_name);
|
||||
|
||||
if (udev_device_has_tag(d, "miracle"))
|
||||
link_set_managed(l, true);
|
||||
}
|
||||
|
||||
static int manager_udev_fn(sd_event_source *source,
|
||||
int fd,
|
||||
uint32_t mask,
|
||||
void *data)
|
||||
{
|
||||
_cleanup_udev_device_ struct udev_device *d = NULL;
|
||||
struct manager *m = data;
|
||||
const char *action, *ifname;
|
||||
unsigned int ifindex;
|
||||
struct link *l;
|
||||
|
||||
d = udev_monitor_receive_device(m->udev_mon);
|
||||
if (!d)
|
||||
return 0;
|
||||
|
||||
ifindex = ifindex_from_udev_device(d);
|
||||
if (!ifindex)
|
||||
return 0;
|
||||
|
||||
l = manager_find_link(m, ifindex);
|
||||
|
||||
action = udev_device_get_action(d);
|
||||
if (action && !strcmp(action, "remove")) {
|
||||
if (l)
|
||||
link_free(l);
|
||||
} else if (l) {
|
||||
if (action && !strcmp(action, "move")) {
|
||||
ifname = udev_device_get_property_value(d, "INTERFACE");
|
||||
if (ifname)
|
||||
link_renamed(l, ifname);
|
||||
}
|
||||
|
||||
if (udev_device_has_tag(d, "miracle"))
|
||||
link_set_managed(l, true);
|
||||
else
|
||||
link_set_managed(l, false);
|
||||
} else {
|
||||
manager_add_udev_link(m, d);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_signal_fn(sd_event_source *source,
|
||||
const struct signalfd_siginfo *ssi,
|
||||
void *data)
|
||||
{
|
||||
struct manager *m = data;
|
||||
|
||||
if (ssi->ssi_signo == SIGCHLD) {
|
||||
log_debug("caught SIGCHLD for %ld, reaping child", (long)ssi->ssi_pid);
|
||||
waitid(P_PID, ssi->ssi_pid, NULL, WNOHANG|WEXITED);
|
||||
return 0;
|
||||
} else if (ssi->ssi_signo == SIGPIPE) {
|
||||
/* ignore SIGPIPE */
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_notice("caught signal %d, exiting..", (int)ssi->ssi_signo);
|
||||
sd_event_exit(m->event, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_free(struct manager *m)
|
||||
{
|
||||
unsigned int i;
|
||||
struct link *l;
|
||||
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
while ((l = MANAGER_FIRST_LINK(m)))
|
||||
link_free(l);
|
||||
|
||||
manager_dbus_disconnect(m);
|
||||
|
||||
shl_htable_clear_uint(&m->links, NULL, NULL);
|
||||
|
||||
sd_event_source_unref(m->udev_mon_source);
|
||||
udev_monitor_unref(m->udev_mon);
|
||||
udev_unref(m->udev);
|
||||
|
||||
for (i = 0; m->sigs[i]; ++i)
|
||||
sd_event_source_unref(m->sigs[i]);
|
||||
|
||||
sd_bus_unref(m->bus);
|
||||
sd_event_unref(m->event);
|
||||
|
||||
free(m->friendly_name);
|
||||
free(m);
|
||||
}
|
||||
|
||||
static int manager_new(struct manager **out)
|
||||
{
|
||||
struct manager *m;
|
||||
static const int sigs[] = {
|
||||
SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0
|
||||
};
|
||||
unsigned int i;
|
||||
sigset_t mask;
|
||||
int r;
|
||||
|
||||
m = calloc(1, sizeof(*m));
|
||||
if (!m)
|
||||
return log_ENOMEM();
|
||||
|
||||
shl_htable_init_uint(&m->links);
|
||||
|
||||
r = sd_event_default(&m->event);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_event_set_watchdog(m->event, true);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_default_system(&m->bus);
|
||||
if (r < 0) {
|
||||
log_error("cannot connect to system bus: %d", r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; sigs[i]; ++i) {
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, sigs[i]);
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
r = sd_event_add_signal(m->event,
|
||||
&m->sigs[i],
|
||||
sigs[i],
|
||||
manager_signal_fn,
|
||||
m);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* low-priority to allow others to handle it first */
|
||||
sd_event_source_set_priority(m->sigs[i], 100);
|
||||
}
|
||||
|
||||
m->udev = udev_new();
|
||||
if (!m->udev) {
|
||||
r = log_ENOMEM();
|
||||
goto error;
|
||||
}
|
||||
|
||||
m->udev_mon = udev_monitor_new_from_netlink(m->udev, "udev");
|
||||
if (!m->udev_mon) {
|
||||
r = log_ENOMEM();
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_mon,
|
||||
"net",
|
||||
"wlan");
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = udev_monitor_enable_receiving(m->udev_mon);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_event_add_io(m->event,
|
||||
&m->udev_mon_source,
|
||||
udev_monitor_get_fd(m->udev_mon),
|
||||
EPOLLHUP | EPOLLERR | EPOLLIN,
|
||||
manager_udev_fn,
|
||||
m);
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = manager_dbus_connect(m);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
if (out)
|
||||
*out = m;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
manager_free(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void manager_read_name(struct manager *m)
|
||||
{
|
||||
_cleanup_sd_bus_error_ sd_bus_error err = SD_BUS_ERROR_NULL;
|
||||
_cleanup_sd_bus_message_ sd_bus_message *rep = NULL;
|
||||
const char *name;
|
||||
char *str;
|
||||
int r;
|
||||
|
||||
r = sd_bus_call_method(m->bus,
|
||||
"org.freedesktop.hostname1",
|
||||
"/org/freedesktop/hostname1",
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get",
|
||||
&err,
|
||||
&rep,
|
||||
"ss", "org.freedesktop.hostname1", "Hostname");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_message_enter_container(rep, 'v', "s");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_message_read(rep, "s", &name);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
if (shl_isempty(name)) {
|
||||
log_warning("no hostname set on systemd.hostname1, using: %s",
|
||||
m->friendly_name);
|
||||
return;
|
||||
}
|
||||
|
||||
str = strdup(name);
|
||||
if (!str)
|
||||
return log_vENOMEM();
|
||||
|
||||
free(m->friendly_name);
|
||||
m->friendly_name = str;
|
||||
log_debug("friendly-name from local hostname: %s", str);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
log_warning("cannot read hostname from systemd.hostname1: %s",
|
||||
bus_error_message(&err, r));
|
||||
}
|
||||
|
||||
static void manager_read_links(struct manager *m)
|
||||
{
|
||||
_cleanup_udev_enumerate_ struct udev_enumerate *e = NULL;
|
||||
struct udev_list_entry *l;
|
||||
struct udev_device *d;
|
||||
int r;
|
||||
|
||||
e = udev_enumerate_new(m->udev);
|
||||
if (!e)
|
||||
goto error;
|
||||
|
||||
r = udev_enumerate_add_match_subsystem(e, "net");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = udev_enumerate_add_match_property(e, "DEVTYPE", "wlan");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = udev_enumerate_add_match_is_initialized(e);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = udev_enumerate_scan_devices(e);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
udev_list_entry_foreach(l, udev_enumerate_get_list_entry(e)) {
|
||||
d = udev_device_new_from_syspath(m->udev,
|
||||
udev_list_entry_get_name(l));
|
||||
if (!d)
|
||||
goto error;
|
||||
|
||||
manager_add_udev_link(m, d);
|
||||
udev_device_unref(d);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
log_warning("cannot enumerate links via udev");
|
||||
}
|
||||
|
||||
static int manager_startup(struct manager *m)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = shl_mkdir_p_prefix("/run", "/run/miracle", 0755);
|
||||
if (r >= 0)
|
||||
r = shl_mkdir_p_prefix("/run/miracle",
|
||||
"/run/miracle/wifi",
|
||||
0700);
|
||||
if (r < 0) {
|
||||
log_error("cannot create maintenance directories in /run: %d",
|
||||
r);
|
||||
return r;
|
||||
}
|
||||
|
||||
manager_read_name(m);
|
||||
manager_read_links(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_run(struct manager *m)
|
||||
{
|
||||
return sd_event_loop(m->event);
|
||||
}
|
||||
|
||||
static int help(void)
|
||||
{
|
||||
/*
|
||||
* 80-char barrier:
|
||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
*/
|
||||
printf("%s [OPTIONS...] ...\n\n"
|
||||
"Wifi Management 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"
|
||||
" --wpa-bindir <dir> wpa_supplicant binary dir [/usr/bin]\n"
|
||||
" --wpa-loglevel <lvl> wpa_supplicant log-level\n"
|
||||
, program_invocation_short_name);
|
||||
/*
|
||||
* 80-char barrier:
|
||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[])
|
||||
{
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_LOG_LEVEL,
|
||||
ARG_LOG_TIME,
|
||||
|
||||
ARG_WPA_BINDIR,
|
||||
ARG_WPA_LOGLEVEL,
|
||||
};
|
||||
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 },
|
||||
|
||||
{ "wpa-bindir", required_argument, NULL, ARG_WPA_BINDIR },
|
||||
{ "wpa-loglevel", required_argument, NULL, ARG_WPA_LOGLEVEL },
|
||||
{}
|
||||
};
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
return help();
|
||||
case ARG_VERSION:
|
||||
puts(PACKAGE_STRING);
|
||||
return 0;
|
||||
case ARG_LOG_LEVEL:
|
||||
log_max_sev = atoi(optarg);
|
||||
break;
|
||||
case ARG_LOG_TIME:
|
||||
log_init_time();
|
||||
break;
|
||||
|
||||
case ARG_WPA_BINDIR:
|
||||
arg_wpa_bindir = optarg;
|
||||
break;
|
||||
case ARG_WPA_LOGLEVEL:
|
||||
arg_wpa_loglevel = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
log_error("unparsed remaining arguments starting with: %s",
|
||||
argv[optind]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_format(LOG_DEFAULT_BASE, NULL, LOG_INFO,
|
||||
"miracle-wifid - revision %s %s %s",
|
||||
"some-rev-TODO-xyz", __DATE__, __TIME__);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct manager *m = NULL;
|
||||
int r;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r < 0)
|
||||
return EXIT_FAILURE;
|
||||
if (!r)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
r = manager_new(&m);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = manager_startup(m);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_notify(false, "READY=1\n"
|
||||
"STATUS=Running..");
|
||||
if (r < 0) {
|
||||
log_vERR(r);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = manager_run(m);
|
||||
|
||||
finish:
|
||||
sd_notify(false, "STATUS=Exiting..");
|
||||
manager_free(m);
|
||||
|
||||
log_debug("exiting..");
|
||||
return abs(r);
|
||||
}
|
194
src/wifi/wifid.h
Normal file
194
src/wifi/wifid.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <libudev.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "shl_dlist.h"
|
||||
#include "shl_htable.h"
|
||||
|
||||
#ifndef WIFID_H
|
||||
#define WIFID_H
|
||||
|
||||
struct manager;
|
||||
struct link;
|
||||
struct peer;
|
||||
struct supplicant;
|
||||
struct supplicant_peer;
|
||||
|
||||
/* supplicant */
|
||||
|
||||
int supplicant_new(struct link *l,
|
||||
struct supplicant **out);
|
||||
void supplicant_free(struct supplicant *s);
|
||||
|
||||
int supplicant_start(struct supplicant *s);
|
||||
void supplicant_stop(struct supplicant *s);
|
||||
bool supplicant_is_running(struct supplicant *s);
|
||||
bool supplicant_is_ready(struct supplicant *s);
|
||||
|
||||
int supplicant_set_friendly_name(struct supplicant *s, const char *name);
|
||||
int supplicant_p2p_start_scan(struct supplicant *s);
|
||||
void supplicant_p2p_stop_scan(struct supplicant *s);
|
||||
bool supplicant_p2p_scanning(struct supplicant *s);
|
||||
|
||||
/* supplicant peer */
|
||||
|
||||
const char *supplicant_peer_get_friendly_name(struct supplicant_peer *sp);
|
||||
const char *supplicant_peer_get_interface(struct supplicant_peer *sp);
|
||||
const char *supplicant_peer_get_local_address(struct supplicant_peer *sp);
|
||||
const char *supplicant_peer_get_remote_address(struct supplicant_peer *sp);
|
||||
int supplicant_peer_connect(struct supplicant_peer *sp,
|
||||
const char *prov_type,
|
||||
const char *pin);
|
||||
void supplicant_peer_disconnect(struct supplicant_peer *sp);
|
||||
|
||||
/* peer */
|
||||
|
||||
struct peer {
|
||||
struct link *l;
|
||||
char *p2p_mac;
|
||||
struct supplicant_peer *sp;
|
||||
|
||||
bool public : 1;
|
||||
bool connected : 1;
|
||||
};
|
||||
|
||||
#define peer_from_htable(_p) \
|
||||
shl_htable_offsetof((_p), struct peer, p2p_mac)
|
||||
|
||||
int peer_new(struct link *l,
|
||||
const char *p2p_mac,
|
||||
struct peer **out);
|
||||
void peer_free(struct peer *p);
|
||||
|
||||
const char *peer_get_friendly_name(struct peer *p);
|
||||
const char *peer_get_interface(struct peer *p);
|
||||
const char *peer_get_local_address(struct peer *p);
|
||||
const char *peer_get_remote_address(struct peer *p);
|
||||
int peer_connect(struct peer *p, const char *prov, const char *pin);
|
||||
void peer_disconnect(struct peer *p);
|
||||
|
||||
int peer_allow(struct peer *p);
|
||||
void peer_reject(struct peer *p);
|
||||
|
||||
void peer_supplicant_started(struct peer *p);
|
||||
void peer_supplicant_stopped(struct peer *p);
|
||||
void peer_supplicant_friendly_name_changed(struct peer *p);
|
||||
void peer_supplicant_provision_discovery(struct peer *p,
|
||||
const char *prov,
|
||||
const char *pin);
|
||||
void peer_supplicant_connected_changed(struct peer *p, bool connected);
|
||||
|
||||
_shl_sentinel_
|
||||
void peer_dbus_properties_changed(struct peer *p, const char *prop, ...);
|
||||
void peer_dbus_provision_discovery(struct peer *p,
|
||||
const char *prov,
|
||||
const char *pin);
|
||||
void peer_dbus_added(struct peer *p);
|
||||
void peer_dbus_removed(struct peer *p);
|
||||
|
||||
/* link */
|
||||
|
||||
struct link {
|
||||
struct manager *m;
|
||||
unsigned int ifindex;
|
||||
struct supplicant *s;
|
||||
|
||||
char *ifname;
|
||||
char *friendly_name;
|
||||
|
||||
size_t peer_cnt;
|
||||
struct shl_htable peers;
|
||||
|
||||
bool managed : 1;
|
||||
bool public : 1;
|
||||
};
|
||||
|
||||
#define link_from_htable(_l) \
|
||||
shl_htable_offsetof((_l), struct link, ifindex)
|
||||
#define LINK_FIRST_PEER(_l) \
|
||||
SHL_HTABLE_FIRST_MACRO(&(_l)->peers, peer_from_htable)
|
||||
#define LINK_FOREACH_PEER(_i, _l) \
|
||||
SHL_HTABLE_FOREACH_MACRO(_i, &(_l)->peers, peer_from_htable)
|
||||
|
||||
struct peer *link_find_peer(struct link *l, const char *p2p_mac);
|
||||
struct peer *link_find_peer_by_label(struct link *l, const char *label);
|
||||
|
||||
int link_new(struct manager *m,
|
||||
unsigned int ifindex,
|
||||
const char *ifname,
|
||||
struct link **out);
|
||||
void link_free(struct link *l);
|
||||
|
||||
void link_set_managed(struct link *l, bool set);
|
||||
int link_renamed(struct link *l, const char *ifname);
|
||||
|
||||
int link_set_friendly_name(struct link *l, const char *name);
|
||||
const char *link_get_friendly_name(struct link *l);
|
||||
int link_set_p2p_scanning(struct link *l, bool set);
|
||||
bool link_get_p2p_scanning(struct link *l);
|
||||
|
||||
void link_supplicant_started(struct link *l);
|
||||
void link_supplicant_stopped(struct link *l);
|
||||
void link_supplicant_p2p_scan_changed(struct link *l, bool new_value);
|
||||
|
||||
_shl_sentinel_
|
||||
void link_dbus_properties_changed(struct link *l, const char *prop, ...);
|
||||
void link_dbus_added(struct link *l);
|
||||
void link_dbus_removed(struct link *l);
|
||||
|
||||
/* manager */
|
||||
|
||||
struct manager {
|
||||
sd_event *event;
|
||||
sd_bus *bus;
|
||||
sd_event_source *sigs[_NSIG];
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_mon;
|
||||
sd_event_source *udev_mon_source;
|
||||
|
||||
char *friendly_name;
|
||||
|
||||
size_t link_cnt;
|
||||
struct shl_htable links;
|
||||
};
|
||||
|
||||
#define MANAGER_FIRST_LINK(_m) \
|
||||
SHL_HTABLE_FIRST_MACRO(&(_m)->links, link_from_htable)
|
||||
#define MANAGER_FOREACH_LINK(_i, _m) \
|
||||
SHL_HTABLE_FOREACH_MACRO(_i, &(_m)->links, link_from_htable)
|
||||
|
||||
struct link *manager_find_link(struct manager *m, unsigned int ifindex);
|
||||
struct link *manager_find_link_by_label(struct manager *m, const char *label);
|
||||
|
||||
/* dbus */
|
||||
|
||||
int manager_dbus_connect(struct manager *m);
|
||||
void manager_dbus_disconnect(struct manager *m);
|
||||
|
||||
/* cli arguments */
|
||||
|
||||
extern const char *arg_wpa_bindir;
|
||||
extern unsigned int arg_wpa_loglevel;
|
||||
|
||||
#endif /* WIFID_H */
|
Loading…
Reference in a new issue