CONNMAN_IFACE_STATE_UNKNOWN = 0,
CONNMAN_IFACE_STATE_OFF = 1,
CONNMAN_IFACE_STATE_ENABLED = 2,
- CONNMAN_IFACE_STATE_CONNECT = 3,
- CONNMAN_IFACE_STATE_CONFIG = 4,
- CONNMAN_IFACE_STATE_CARRIER = 5,
- CONNMAN_IFACE_STATE_READY = 6,
- CONNMAN_IFACE_STATE_SHUTDOWN = 7,
+ CONNMAN_IFACE_STATE_SCANNING = 3,
+ CONNMAN_IFACE_STATE_CONNECT = 4,
+ CONNMAN_IFACE_STATE_CONNECTED = 5,
+ CONNMAN_IFACE_STATE_CARRIER = 6,
+ CONNMAN_IFACE_STATE_CONFIGURE = 7,
+ CONNMAN_IFACE_STATE_READY = 8,
+ CONNMAN_IFACE_STATE_SHUTDOWN = 9,
};
enum connman_iface_policy {
char *sysfs;
char *identifier;
int index;
- int carrier;
enum connman_iface_type type;
enum connman_iface_flags flags;
enum connman_iface_state state;
struct connman_iface_driver *driver;
void *driver_data;
+ void *rtnl_data;
+
struct {
char *driver;
char *vendor;
const char *capability;
int (*probe) (struct connman_iface *iface);
void (*remove) (struct connman_iface *iface);
- int (*activate) (struct connman_iface *iface);
- int (*shutdown) (struct connman_iface *iface);
- int (*get_ipv4) (struct connman_iface *iface,
- struct connman_ipv4 *ipv4);
- int (*set_ipv4) (struct connman_iface *iface,
- struct connman_ipv4 *ipv4);
+
int (*scan) (struct connman_iface *iface);
int (*connect) (struct connman_iface *iface,
struct connman_network *network);
iface->driver_data = data;
}
-extern int connman_iface_update(struct connman_iface *iface,
- enum connman_iface_state state);
-
-extern void connman_iface_indicate_carrier(struct connman_iface *iface,
- int carrier);
+extern void connman_iface_indicate_enabled(struct connman_iface *iface);
+extern void connman_iface_indicate_disabled(struct connman_iface *iface);
+extern void connman_iface_indicate_connected(struct connman_iface *iface);
+extern void connman_iface_indicate_carrier_on(struct connman_iface *iface);
+extern void connman_iface_indicate_carrier_off(struct connman_iface *iface);
+extern void connman_iface_indicate_configured(struct connman_iface *iface);
extern int connman_iface_get_ipv4(struct connman_iface *iface,
struct connman_ipv4 *ipv4);
if (g_str_has_prefix(buf + 3, "CTRL-EVENT-CONNECTED") == TRUE) {
printf("[SUPPLICANT] connected\n");
- connman_iface_update(task->iface,
- CONNMAN_IFACE_STATE_CARRIER);
+ connman_iface_indicate_connected(task->iface);
}
if (g_str_has_prefix(buf + 3, "CTRL-EVENT-DISCONNECTED") == TRUE) {
ipv4->method = CONNMAN_IPV4_METHOD_DHCP;
- if (iface->driver->set_ipv4) {
- iface->driver->set_ipv4(iface, ipv4);
- iface->ipv4 = *ipv4;
- } else {
- connman_iface_set_ipv4(iface, ipv4);
- iface->ipv4 = *ipv4;
- }
-
- connman_iface_update(iface, CONNMAN_IFACE_STATE_READY);
+ connman_iface_set_ipv4(iface, ipv4);
+ iface->ipv4 = *ipv4;
+
+ connman_iface_indicate_configured(iface);
}
return 0;
return "off";
case CONNMAN_IFACE_STATE_ENABLED:
return "enabled";
+ case CONNMAN_IFACE_STATE_SCANNING:
+ return "scanning";
case CONNMAN_IFACE_STATE_CONNECT:
return "connect";
- case CONNMAN_IFACE_STATE_CONFIG:
- return "config";
+ case CONNMAN_IFACE_STATE_CONNECTED:
+ return "connected";
case CONNMAN_IFACE_STATE_CARRIER:
return "carrier";
+ case CONNMAN_IFACE_STATE_CONFIGURE:
+ return "configure";
case CONNMAN_IFACE_STATE_READY:
return "ready";
case CONNMAN_IFACE_STATE_SHUTDOWN:
}
}
-int connman_iface_update(struct connman_iface *iface,
- enum connman_iface_state state)
+static void state_changed(struct connman_iface *iface)
{
- const char *str;
-
- iface->state = state;
+ const char *str = __connman_iface_state2string(iface->state);
+ enum connman_iface_state state = iface->state;
- str = __connman_iface_state2string(iface->state);
+ DBG("%s", str);
g_dbus_emit_signal(connection, iface->path,
CONNMAN_IFACE_INTERFACE, "StateChanged",
DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
- switch (state) {
+ switch (iface->state) {
case CONNMAN_IFACE_STATE_OFF:
__connman_dhcp_release(iface);
break;
case CONNMAN_IFACE_STATE_ENABLED:
if (iface->type == CONNMAN_IFACE_TYPE_80211) {
- if (iface->driver->connect)
+ state = CONNMAN_IFACE_STATE_SCANNING;
+ if (iface->driver->connect) {
iface->driver->connect(iface, NULL);
+ state = CONNMAN_IFACE_STATE_CONNECT;
+ }
}
break;
case CONNMAN_IFACE_STATE_CARRIER:
+ if (iface->policy == CONNMAN_IFACE_POLICY_AUTO)
+ state = CONNMAN_IFACE_STATE_CONFIGURE;
+ break;
+
+ case CONNMAN_IFACE_STATE_CONFIGURE:
__connman_dhcp_request(iface);
break;
case CONNMAN_IFACE_STATE_SHUTDOWN:
__connman_dhcp_release(iface);
- if (iface->driver->shutdown)
- iface->driver->shutdown(iface);
+ if (iface->driver->disconnect)
+ iface->driver->disconnect(iface);
+ if (iface->policy != CONNMAN_IFACE_POLICY_AUTO)
+ state = CONNMAN_IFACE_STATE_OFF;
break;
default:
break;
}
- return 0;
+ if (iface->state != state) {
+ iface->state = state;
+ state_changed(iface);
+ }
+}
+
+static void switch_policy(struct connman_iface *iface)
+{
+ DBG("iface %p", iface);
+
+ switch (iface->policy) {
+ case CONNMAN_IFACE_POLICY_OFF:
+ iface->state = CONNMAN_IFACE_STATE_SHUTDOWN;
+ state_changed(iface);
+ __connman_iface_down(iface);
+ break;
+
+ case CONNMAN_IFACE_POLICY_IGNORE:
+ break;
+
+ case CONNMAN_IFACE_POLICY_AUTO:
+ __connman_iface_up(iface);
+ break;
+
+ default:
+ break;
+ }
}
-void connman_iface_indicate_carrier(struct connman_iface *iface, int carrier)
+void connman_iface_indicate_enabled(struct connman_iface *iface)
{
- DBG("iface %p carrier %d", iface, carrier);
+ DBG("iface %p state %d", iface, iface->state);
+
+ switch (iface->state) {
+ case CONNMAN_IFACE_STATE_OFF:
+ iface->state = CONNMAN_IFACE_STATE_ENABLED;
+ state_changed(iface);
+ break;
+ default:
+ break;
+ }
+}
+
+void connman_iface_indicate_disabled(struct connman_iface *iface)
+{
+ DBG("iface %p state %d", iface, iface->state);
+
+ iface->state = CONNMAN_IFACE_STATE_SHUTDOWN;
+ state_changed(iface);
+}
+
+void connman_iface_indicate_connected(struct connman_iface *iface)
+{
+ DBG("iface %p state %d", iface, iface->state);
+
+ switch (iface->state) {
+ case CONNMAN_IFACE_STATE_CONNECT:
+ iface->state = CONNMAN_IFACE_STATE_CONNECTED;
+ state_changed(iface);
+ break;
+ default:
+ break;
+ }
+}
+
+void connman_iface_indicate_carrier_on(struct connman_iface *iface)
+{
+ DBG("iface %p state %d", iface, iface->state);
+
+ switch (iface->state) {
+ case CONNMAN_IFACE_STATE_ENABLED:
+ case CONNMAN_IFACE_STATE_CONNECT:
+ case CONNMAN_IFACE_STATE_CONNECTED:
+ iface->state = CONNMAN_IFACE_STATE_CARRIER;
+ state_changed(iface);
+ break;
+ default:
+ break;
+ }
+}
+
+void connman_iface_indicate_carrier_off(struct connman_iface *iface)
+{
+ DBG("iface %p state %d", iface, iface->state);
+
+ switch (iface->state) {
+ case CONNMAN_IFACE_STATE_CONFIGURE:
+ case CONNMAN_IFACE_STATE_READY:
+ iface->state = CONNMAN_IFACE_STATE_ENABLED;
+ state_changed(iface);
+ break;
+ default:
+ break;
+ }
+}
+
+void connman_iface_indicate_configured(struct connman_iface *iface)
+{
+ DBG("iface %p state %d", iface, iface->state);
+
+ switch (iface->state) {
+ case CONNMAN_IFACE_STATE_CONFIGURE:
+ iface->state = CONNMAN_IFACE_STATE_READY;
+ state_changed(iface);
+ break;
+ default:
+ break;
+ }
}
int connman_iface_get_ipv4(struct connman_iface *iface,
iface->policy = new_policy;
__connman_iface_store(iface);
- if (new_policy == CONNMAN_IFACE_POLICY_AUTO) {
- if (iface->driver->activate)
- iface->driver->activate(iface);
- } else
- connman_iface_update(iface,
- CONNMAN_IFACE_STATE_SHUTDOWN);
-
+ switch_policy(iface);
policy = __connman_iface_policy2string(new_policy);
g_dbus_emit_signal(conn, iface->path, CONNMAN_IFACE_INTERFACE,
interfaces = g_slist_append(interfaces, iface);
if (iface->flags & CONNMAN_IFACE_FLAG_IPV4) {
- if (driver->get_ipv4)
- driver->get_ipv4(iface, &iface->ipv4);
- else
- connman_iface_get_ipv4(iface, &iface->ipv4);
+ connman_iface_get_ipv4(iface, &iface->ipv4);
DBG("address %s", inet_ntoa(iface->ipv4.address));
}
DBUS_TYPE_OBJECT_PATH, &iface->path,
DBUS_TYPE_INVALID);
- if (iface->policy == CONNMAN_IFACE_POLICY_AUTO) {
- if (driver->activate)
- driver->activate(iface);
- }
+ switch_policy(iface);
return 0;
}
#include "connman.h"
+struct rtnl_data {
+ unsigned ifi_flags;
+};
+
+static struct rtnl_data *get_rtnl_data(struct connman_iface *iface)
+{
+ if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
+ return NULL;
+
+ if (iface->rtnl_data == NULL)
+ iface->rtnl_data = g_try_new0(struct rtnl_data, 1);
+
+ return iface->rtnl_data;
+}
+
static inline void print_inet(struct rtattr *attr, const char *name, int family)
{
if (family == AF_INET) {
static void rtnl_link(struct nlmsghdr *hdr)
{
struct connman_iface *iface;
+ struct rtnl_data *data;
struct ifinfomsg *msg;
struct rtattr *attr;
int bytes;
if (iface == NULL)
return;
- if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
+ data = get_rtnl_data(iface);
+ if (data == NULL)
return;
- if (iface->carrier != ((msg->ifi_flags & IFF_RUNNING) != 0)) {
- iface->carrier = ((msg->ifi_flags & IFF_RUNNING) != 0);
- if (iface->driver->rtnl_carrier)
- iface->driver->rtnl_carrier(iface, iface->carrier);
+ if ((data->ifi_flags & IFF_RUNNING) != (msg->ifi_flags & IFF_RUNNING)) {
+ if (msg->ifi_flags & IFF_RUNNING)
+ connman_iface_indicate_carrier_on(iface);
else
- connman_iface_indicate_carrier(iface, iface->carrier);
+ connman_iface_indicate_carrier_off(iface);
}
+ if ((data->ifi_flags & IFF_UP) != (msg->ifi_flags & IFF_UP)) {
+ if (msg->ifi_flags & IFF_UP)
+ connman_iface_indicate_enabled(iface);
+ else
+ connman_iface_indicate_disabled(iface);
+ }
+
+ data->ifi_flags = msg->ifi_flags;
+
for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
attr = RTA_NEXT(attr, bytes)) {
switch (attr->rta_type) {
static void rtnl_addr(struct nlmsghdr *hdr)
{
struct connman_iface *iface;
+ struct rtnl_data *data;
struct ifaddrmsg *msg;
struct rtattr *attr;
int bytes;
if (iface == NULL)
return;
- if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
+ data = get_rtnl_data(iface);
+ if (data == NULL)
return;
for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
gsize len;
GIOError err;
- if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
- g_io_channel_unref(chan);
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
return FALSE;
- }
memset(buf, 0, sizeof(buf));
if (err) {
if (err == G_IO_ERROR_AGAIN)
return TRUE;
- g_io_channel_unref(chan);
return FALSE;
}
G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
netlink_event, NULL);
- g_io_channel_unref(channel);
-
return 0;
}
{
DBG("");
+ g_io_channel_shutdown(channel, TRUE, NULL);
g_io_channel_unref(channel);
channel = NULL;