summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/iface.h5
-rw-r--r--src/connman.h2
-rw-r--r--src/dhcp.c3
-rw-r--r--src/iface.c50
-rw-r--r--src/main.c8
-rw-r--r--src/rtnl.c162
6 files changed, 142 insertions, 88 deletions
diff --git a/include/iface.h b/include/iface.h
index d4eb2134..a128e062 100644
--- a/include/iface.h
+++ b/include/iface.h
@@ -117,6 +117,11 @@ extern int connman_iface_update(struct connman_iface *iface,
extern void connman_iface_indicate_carrier(struct connman_iface *iface,
int carrier);
+extern int connman_iface_get_ipv4(struct connman_iface *iface,
+ struct connman_ipv4 *ipv4);
+extern int connman_iface_set_ipv4(struct connman_iface *iface,
+ struct connman_ipv4 *ipv4);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/connman.h b/src/connman.h
index 6f361c86..fdb9fa83 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -55,6 +55,8 @@ void __connman_iface_list(DBusMessageIter *iter);
int __connman_rtnl_init(void);
void __connman_rtnl_cleanup(void);
+int __connman_rtnl_send(const void *buf, size_t len);
+
#include <connman/dhcp.h>
int __connman_dhcp_request(struct connman_iface *iface);
diff --git a/src/dhcp.c b/src/dhcp.c
index b4e921e3..2fa3f1fe 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -64,6 +64,9 @@ int connman_dhcp_update(struct connman_iface *iface,
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);
diff --git a/src/iface.c b/src/iface.c
index a641bf33..be7f261e 100644
--- a/src/iface.c
+++ b/src/iface.c
@@ -26,6 +26,9 @@
#include <string.h>
#include <arpa/inet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
#include <glib.h>
#include <gdbus.h>
@@ -101,7 +104,7 @@ int connman_iface_update(struct connman_iface *iface,
default:
break;
- }
+ }
iface->state = state;
@@ -113,6 +116,43 @@ void connman_iface_indicate_carrier(struct connman_iface *iface, int carrier)
DBG("iface %p carrier %d", iface, carrier);
}
+int connman_iface_get_ipv4(struct connman_iface *iface,
+ struct connman_ipv4 *ipv4)
+{
+ struct {
+ struct nlmsghdr hdr;
+ struct rtgenmsg msg;
+ } req;
+
+ if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
+ return -1;
+
+ DBG("iface %p ipv4 %p", iface, ipv4);
+
+ memset(&req, 0, sizeof(req));
+ req.hdr.nlmsg_len = sizeof(req);
+ req.hdr.nlmsg_type = RTM_GETADDR;
+ req.hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ req.hdr.nlmsg_pid = 0;
+ req.hdr.nlmsg_seq = 4711;
+ req.msg.rtgen_family = AF_INET;
+
+ __connman_rtnl_send(&req, sizeof(req));
+
+ return 0;
+}
+
+int connman_iface_set_ipv4(struct connman_iface *iface,
+ struct connman_ipv4 *ipv4)
+{
+ if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
+ return -1;
+
+ DBG("iface %p ipv4 %p", iface, ipv4);
+
+ return 0;
+}
+
static DBusMessage *enable_iface(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -246,9 +286,11 @@ static int probe_device(LibHalContext *ctx,
interfaces = g_slist_append(interfaces, iface);
- if ((iface->flags & CONNMAN_IFACE_FLAG_IPV4) &&
- driver->get_ipv4) {
- driver->get_ipv4(iface, &iface->ipv4);
+ 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);
DBG("address %s", inet_ntoa(iface->ipv4.address));
}
diff --git a/src/main.c b/src/main.c
index 21a0513f..14198cd4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -61,10 +61,10 @@ int main(int argc, char *argv[])
__connman_plugin_init();
- __connman_iface_init(conn);
-
__connman_rtnl_init();
+ __connman_iface_init(conn);
+
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_term;
sigaction(SIGINT, &sa, NULL);
@@ -72,10 +72,10 @@ int main(int argc, char *argv[])
g_main_loop_run(main_loop);
- __connman_rtnl_cleanup();
-
__connman_iface_cleanup();
+ __connman_rtnl_cleanup();
+
__connman_plugin_cleanup();
__connman_manager_cleanup();
diff --git a/src/rtnl.c b/src/rtnl.c
index 33031ffc..d678aa70 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -37,6 +37,17 @@
#include "connman.h"
+static inline void print_inet(struct rtattr *attr, const char *name, int family)
+{
+ if (family == AF_INET) {
+ struct in_addr addr;
+ addr = *((struct in_addr *) RTA_DATA(attr));
+ printf(" attr %s (len %d) %s\n",
+ name, RTA_PAYLOAD(attr), inet_ntoa(addr));
+ } else
+ printf(" attr %s (len %d)\n", name, RTA_PAYLOAD(attr));
+}
+
static inline void print_char(struct rtattr *attr, const char *name)
{
printf(" attr %s (len %d) %s\n", name, RTA_PAYLOAD(attr),
@@ -171,31 +182,16 @@ static void rtnl_addr(struct nlmsghdr *hdr)
attr = RTA_NEXT(attr, bytes)) {
switch (attr->rta_type) {
case IFA_ADDRESS:
- print_attr(attr, "address");
- if (msg->ifa_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "address", msg->ifa_family);
break;
case IFA_LOCAL:
- print_attr(attr, "local");
- if (msg->ifa_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "local", msg->ifa_family);
break;
case IFA_LABEL:
print_char(attr, "label");
break;
case IFA_BROADCAST:
- print_attr(attr, "broadcast");
- if (msg->ifa_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "broadcast", msg->ifa_family);
break;
case IFA_ANYCAST:
print_attr(attr, "anycast");
@@ -228,20 +224,10 @@ static void rtnl_route(struct nlmsghdr *hdr)
attr = RTA_NEXT(attr, bytes)) {
switch (attr->rta_type) {
case RTA_DST:
- print_attr(attr, "dst");
- if (msg->rtm_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "dst", msg->rtm_family);
break;
case RTA_SRC:
- print_attr(attr, "src");
- if (msg->rtm_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "src", msg->rtm_family);
break;
case RTA_IIF:
print_char(attr, "iif");
@@ -250,23 +236,13 @@ static void rtnl_route(struct nlmsghdr *hdr)
print_attr(attr, "oif");
break;
case RTA_GATEWAY:
- print_attr(attr, "gateway");
- if (msg->rtm_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "gateway", msg->rtm_family);
break;
case RTA_PRIORITY:
print_attr(attr, "priority");
break;
case RTA_PREFSRC:
- print_attr(attr, "prefsrc");
- if (msg->rtm_family == AF_INET) {
- struct in_addr addr;
- addr = *((struct in_addr *) RTA_DATA(attr));
- DBG(" address %s", inet_ntoa(addr));
- }
+ print_inet(attr, "prefsrc", msg->rtm_family);
break;
case RTA_METRICS:
print_attr(attr, "metrics");
@@ -281,47 +257,57 @@ static void rtnl_route(struct nlmsghdr *hdr)
}
}
-static void rtnl_message(unsigned char *buf, size_t size)
+static void rtnl_message(void *buf, size_t len)
{
- struct nlmsghdr *hdr = (void *) buf;
+ DBG("buf %p len %d", buf, len);
- if (!NLMSG_OK(hdr, size))
- return;
+ while (len > 0) {
+ struct nlmsghdr *hdr = buf;
- switch (hdr->nlmsg_type) {
- case NLMSG_DONE:
- DBG("done");
- return;
- case NLMSG_NOOP:
- DBG("noop");
- return;
- case NLMSG_OVERRUN:
- DBG("overrun");
- return;
- case NLMSG_ERROR:
- DBG("error");
- return;
- case RTM_NEWLINK:
- rtnl_link(hdr);
- break;
- case RTM_DELLINK:
- rtnl_link(hdr);
- break;
- case RTM_NEWADDR:
- rtnl_addr(hdr);
- break;
- case RTM_DELADDR:
- rtnl_addr(hdr);
- break;
- case RTM_NEWROUTE:
- rtnl_route(hdr);
- break;
- case RTM_DELROUTE:
- rtnl_route(hdr);
- break;
- default:
- DBG("type %d", hdr->nlmsg_type);
- break;
+ if (!NLMSG_OK(hdr, len))
+ break;
+
+ DBG("len %d type %d flags 0x%04x",
+ hdr->nlmsg_len, hdr->nlmsg_type, hdr->nlmsg_flags);
+
+ switch (hdr->nlmsg_type) {
+ case NLMSG_DONE:
+ DBG("done");
+ return;
+ case NLMSG_NOOP:
+ DBG("noop");
+ return;
+ case NLMSG_OVERRUN:
+ DBG("overrun");
+ return;
+ case NLMSG_ERROR:
+ DBG("error");
+ return;
+ case RTM_NEWLINK:
+ rtnl_link(hdr);
+ break;
+ case RTM_DELLINK:
+ rtnl_link(hdr);
+ break;
+ case RTM_NEWADDR:
+ rtnl_addr(hdr);
+ break;
+ case RTM_DELADDR:
+ rtnl_addr(hdr);
+ break;
+ case RTM_NEWROUTE:
+ rtnl_route(hdr);
+ break;
+ case RTM_DELROUTE:
+ rtnl_route(hdr);
+ break;
+ default:
+ DBG("type %d", hdr->nlmsg_type);
+ break;
+ }
+
+ len -= hdr->nlmsg_len;
+ buf += hdr->nlmsg_len;
}
}
@@ -354,6 +340,22 @@ static gboolean netlink_event(GIOChannel *chan,
static GIOChannel *channel = NULL;
+int __connman_rtnl_send(const void *buf, size_t len)
+{
+ struct sockaddr_nl addr;
+ int sk;
+
+ DBG("buf %p len %d", buf, len);
+
+ sk = g_io_channel_unix_get_fd(channel);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+
+ return sendto(sk, buf, len, 0,
+ (struct sockaddr *) &addr, sizeof(addr));
+}
+
int __connman_rtnl_init(void)
{
struct sockaddr_nl addr;