diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2007-12-29 07:28:59 +0100 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2007-12-29 07:28:59 +0100 |
commit | c3a32686d0a50746e152967fd6f4912aec336f66 (patch) | |
tree | c86d3284786a5a346096ec1b470bc48d5b057007 /src | |
parent | 08647078e04d94f58155e4735fe0585fead881e3 (diff) | |
download | connman-c3a32686d0a50746e152967fd6f4912aec336f66.tar.gz connman-c3a32686d0a50746e152967fd6f4912aec336f66.tar.bz2 connman-c3a32686d0a50746e152967fd6f4912aec336f66.zip |
Add callback for wireless netlink events
Diffstat (limited to 'src')
-rw-r--r-- | src/connman.h | 1 | ||||
-rw-r--r-- | src/iface.c | 14 | ||||
-rw-r--r-- | src/rtnl.c | 158 |
3 files changed, 101 insertions, 72 deletions
diff --git a/src/connman.h b/src/connman.h index b5f0e48f..6f361c86 100644 --- a/src/connman.h +++ b/src/connman.h @@ -47,6 +47,7 @@ void __connman_plugin_cleanup(void); int __connman_iface_init(DBusConnection *conn); void __connman_iface_cleanup(void); +struct connman_iface *__connman_iface_find(int index); void __connman_iface_list(DBusMessageIter *iter); #include <connman/rtnl.h> diff --git a/src/iface.c b/src/iface.c index 31763b74..72bc142c 100644 --- a/src/iface.c +++ b/src/iface.c @@ -53,6 +53,20 @@ void connman_iface_unregister(struct connman_iface_driver *driver) static GSList *interfaces = NULL; +struct connman_iface *__connman_iface_find(int index) +{ + GSList *list; + + for (list = interfaces; list; list = list->next) { + struct connman_iface *iface = list->data; + + if (iface->index == index) + return iface; + } + + return NULL; +} + void __connman_iface_list(DBusMessageIter *iter) { GSList *list; @@ -36,8 +36,23 @@ #include "connman.h" -static void parse_link(struct nlmsghdr *hdr) +static inline void print_char(struct rtattr *attr, const char *name) { + printf(" attr %s (len %d) %s", name, RTA_PAYLOAD(attr), + (char *) RTA_DATA(attr)); +} + +static inline void print_attr(struct rtattr *attr, const char *name) +{ + if (name) + printf(" attr %s (len %d)", name, RTA_PAYLOAD(attr)); + else + printf(" attr %d (len %d)", attr->rta_type, RTA_PAYLOAD(attr)); +} + +static void rtnl_link(struct nlmsghdr *hdr) +{ + struct connman_iface *iface; struct ifinfomsg *msg; struct rtattr *attr; int bytes; @@ -47,78 +62,79 @@ static void parse_link(struct nlmsghdr *hdr) DBG("ifi_index %d ifi_flags %d", msg->ifi_index, msg->ifi_flags); + iface = __connman_iface_find(msg->ifi_index); + if (iface == NULL) + return; + + if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0) + return; + for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes); attr = RTA_NEXT(attr, bytes)) { - int len = RTA_PAYLOAD(attr); - switch (attr->rta_type) { case IFLA_ADDRESS: - DBG(" rta_type address len %d", len); + print_attr(attr, "address"); break; case IFLA_BROADCAST: - DBG(" rta_type broadcast len %d", len); + print_attr(attr, "broadcast"); break; case IFLA_IFNAME: - DBG(" rta_type ifname %s", (char *) RTA_DATA(attr)); + print_char(attr, "ifname"); break; case IFLA_MTU: - DBG(" rta_type mtu len %d", len); + print_attr(attr, "mtu"); break; case IFLA_LINK: - DBG(" rta_type link len %d", len); + print_attr(attr, "link"); break; case IFLA_QDISC: - DBG(" rta_type qdisc len %d", len); + print_attr(attr, "qdisc"); break; case IFLA_STATS: - DBG(" rta_type stats len %d", len); + print_attr(attr, "stats"); break; case IFLA_COST: - DBG(" rta_type cost len %d", len); + print_attr(attr, "cost"); break; case IFLA_PRIORITY: - DBG(" rta_type priority len %d", len); + print_attr(attr, "priority"); break; case IFLA_MASTER: - DBG(" rta_type master len %d", len); + print_attr(attr, "master"); break; case IFLA_WIRELESS: - DBG(" rta_type wireless len %d", len); - { - unsigned char *data = RTA_DATA(attr); - int i; - for (i = 0; i < len; i++) - printf(" %02x", data[i]); - printf("\n"); - } + if (iface->driver->rtnl_wireless) + iface->driver->rtnl_wireless(iface, + RTA_DATA(attr), RTA_PAYLOAD(attr)); break; case IFLA_PROTINFO: - DBG(" rta_type protinfo len %d", len); + print_attr(attr, "protinfo"); break; case IFLA_TXQLEN: - DBG(" rta_type txqlen len %d", len); + print_attr(attr, "txqlen"); break; case IFLA_MAP: - DBG(" rta_type map len %d", len); + print_attr(attr, "map"); break; case IFLA_WEIGHT: - DBG(" rta_type widght len %d", len); + print_attr(attr, "weight"); break; case IFLA_OPERSTATE: - DBG(" rta_type operstate len %d", len); + print_attr(attr, "operstate"); break; case IFLA_LINKMODE: - DBG(" rta_type linkmode len %d", len); + print_attr(attr, "linkmode"); break; default: - DBG(" rta_type %d len %d", attr->rta_type, len); + print_attr(attr, NULL); break; } } } -static void parse_addr(struct nlmsghdr *hdr) +static void rtnl_addr(struct nlmsghdr *hdr) { + struct connman_iface *iface; struct ifaddrmsg *msg; struct rtattr *attr; int bytes; @@ -128,13 +144,18 @@ static void parse_addr(struct nlmsghdr *hdr) DBG("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index); + iface = __connman_iface_find(msg->ifa_index); + if (iface == NULL) + return; + + if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0) + return; + for (attr = IFA_RTA(msg); RTA_OK(attr, bytes); attr = RTA_NEXT(attr, bytes)) { - int len = RTA_PAYLOAD(attr); - switch (attr->rta_type) { case IFA_ADDRESS: - DBG(" rta_type address len %d", len); + print_attr(attr, "address"); if (msg->ifa_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -142,7 +163,7 @@ static void parse_addr(struct nlmsghdr *hdr) } break; case IFA_LOCAL: - DBG(" rta_type local len %d", len); + print_attr(attr, "local"); if (msg->ifa_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -150,10 +171,10 @@ static void parse_addr(struct nlmsghdr *hdr) } break; case IFA_LABEL: - DBG(" rta_type label %s", (char *) RTA_DATA(attr)); + print_char(attr, "label"); break; case IFA_BROADCAST: - DBG(" rta_type broadcast len %d", len); + print_attr(attr, "broadcast"); if (msg->ifa_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -161,22 +182,22 @@ static void parse_addr(struct nlmsghdr *hdr) } break; case IFA_ANYCAST: - DBG(" rta_type anycast len %d", len); + print_attr(attr, "anycast"); break; case IFA_CACHEINFO: - DBG(" rta_type cacheinfo len %d", len); + print_attr(attr, "cacheinfo"); break; case IFA_MULTICAST: - DBG(" rta_type multicast len %d", len); + print_attr(attr, "multicast"); break; default: - DBG(" rta_type %d len %d", attr->rta_type, len); + print_attr(attr, NULL); break; } } } -static void parse_route(struct nlmsghdr *hdr) +static void rtnl_route(struct nlmsghdr *hdr) { struct rtmsg *msg; struct rtattr *attr; @@ -189,11 +210,9 @@ static void parse_route(struct nlmsghdr *hdr) for (attr = RTM_RTA(msg); RTA_OK(attr, bytes); attr = RTA_NEXT(attr, bytes)) { - int len = RTA_PAYLOAD(attr); - switch (attr->rta_type) { case RTA_DST: - DBG(" rta_type dst len %d", len); + print_attr(attr, "dst"); if (msg->rtm_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -201,7 +220,7 @@ static void parse_route(struct nlmsghdr *hdr) } break; case RTA_SRC: - DBG(" rta_type src len %d", len); + print_attr(attr, "src"); if (msg->rtm_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -209,13 +228,13 @@ static void parse_route(struct nlmsghdr *hdr) } break; case RTA_IIF: - DBG(" rta_type iff len %d", len); + print_char(attr, "iif"); break; case RTA_OIF: - DBG(" rta_type oif len %d", len); + print_attr(attr, "oif"); break; case RTA_GATEWAY: - DBG(" rta_type gateway len %d", len); + print_attr(attr, "gateway"); if (msg->rtm_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -223,10 +242,10 @@ static void parse_route(struct nlmsghdr *hdr) } break; case RTA_PRIORITY: - DBG(" rta_type priority len %d", len); + print_attr(attr, "priority"); break; case RTA_PREFSRC: - DBG(" rta_type prefsrc len %d", len); + print_attr(attr, "prefsrc"); if (msg->rtm_family == AF_INET) { struct in_addr addr; addr = *((struct in_addr *) RTA_DATA(attr)); @@ -234,19 +253,19 @@ static void parse_route(struct nlmsghdr *hdr) } break; case RTA_METRICS: - DBG(" rta_type metrics len %d", len); + print_attr(attr, "metrics"); break; case RTA_TABLE: - DBG(" rta_type table len %d", len); + print_attr(attr, "table"); break; default: - DBG(" rta_type %d len %d", attr->rta_type, len); + print_attr(attr, NULL); break; } } } -static void parse_message(unsigned char *buf, size_t size) +static void rtnl_message(unsigned char *buf, size_t size) { struct nlmsghdr *hdr = (void *) buf; @@ -255,43 +274,37 @@ static void parse_message(unsigned char *buf, size_t size) switch (hdr->nlmsg_type) { case NLMSG_DONE: - DBG("nlmsg_type done"); + DBG("done"); return; case NLMSG_NOOP: - DBG("nlmsg_type noop"); + DBG("noop"); return; case NLMSG_OVERRUN: - DBG("nlmsg_type overrun"); + DBG("overrun"); return; case NLMSG_ERROR: - DBG("nlmsg_type error"); + DBG("error"); return; case RTM_NEWLINK: - DBG("nlmsg_type RTM_NEWLINK"); - parse_link(hdr); + rtnl_link(hdr); break; case RTM_DELLINK: - DBG("nlmsg_type RTM_DELLINK"); - parse_link(hdr); + rtnl_link(hdr); break; case RTM_NEWADDR: - DBG("nlmsg_type RTM_NEWADDR"); - parse_addr(hdr); + rtnl_addr(hdr); break; case RTM_DELADDR: - DBG("nlmsg_type RTM_DELADDR"); - parse_addr(hdr); + rtnl_addr(hdr); break; case RTM_NEWROUTE: - DBG("nlmsg_type RTM_NEWROUTE"); - parse_route(hdr); + rtnl_route(hdr); break; case RTM_DELROUTE: - DBG("nlmsg_type RTM_DELROUTE"); - parse_route(hdr); + rtnl_route(hdr); break; default: - DBG("nlmsg_type %d", hdr->nlmsg_type); + DBG("type %d", hdr->nlmsg_type); break; } } @@ -318,7 +331,7 @@ static gboolean netlink_event(GIOChannel *chan, return FALSE; } - parse_message(buf, len); + rtnl_message(buf, len); return TRUE; } @@ -338,7 +351,8 @@ int __connman_rtnl_init(void) memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE; + addr.nl_groups = RTMGRP_LINK; + //addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE; addr.nl_pid = getpid(); if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { |