From 352f418dd03cd3ac1aac6dc52d9f69209ba98744 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 1 Jan 2008 20:43:34 +0100 Subject: [PATCH] Add experimental IPv4 address retrieval over netlink --- include/iface.h | 5 ++ src/connman.h | 2 + src/dhcp.c | 3 ++ src/iface.c | 50 +++++++++++++++-- src/main.c | 8 +-- src/rtnl.c | 162 ++++++++++++++++++++++++++++---------------------------- 6 files changed, 142 insertions(+), 88 deletions(-) diff --git a/include/iface.h b/include/iface.h index d4eb213..a128e06 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 6f361c8..fdb9fa8 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 int __connman_dhcp_request(struct connman_iface *iface); diff --git a/src/dhcp.c b/src/dhcp.c index b4e921e..2fa3f1f 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 a641bf3..be7f261 100644 --- a/src/iface.c +++ b/src/iface.c @@ -26,6 +26,9 @@ #include #include +#include +#include + #include #include @@ -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 21a0513..14198cd 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 33031ff..d678aa7 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; -- 2.7.4