5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/socket.h>
29 #include <arpa/inet.h>
30 #include <netinet/ether.h>
31 #include <net/if_arp.h>
33 #include <linux/netlink.h>
34 #include <linux/rtnetlink.h>
40 #define print(arg...) do { } while (0)
41 //#define print(arg...) connman_info(arg)
46 connman_rtnl_operstate_cb_t operstate;
47 connman_rtnl_link_cb_t newlink;
51 static GSList *watch_list = NULL;
52 static unsigned int watch_id = 0;
55 * connman_rtnl_add_operstate_watch:
56 * @index: network device index
57 * @callback: callback function
58 * @user_data: callback data;
60 * Add a new RTNL watch for operation state events
62 * Returns: %0 on failure and a unique id on success
64 unsigned int connman_rtnl_add_operstate_watch(int index,
65 connman_rtnl_operstate_cb_t callback, void *user_data)
67 struct watch_data *watch;
69 watch = g_try_new0(struct watch_data, 1);
73 watch->id = ++watch_id;
76 watch->operstate = callback;
77 watch->user_data = user_data;
79 watch_list = g_slist_prepend(watch_list, watch);
81 DBG("id %d", watch->id);
84 unsigned char operstate = 0;
87 callback(operstate, user_data);
94 * connman_rtnl_add_newlink_watch:
95 * @index: network device index
96 * @callback: callback function
97 * @user_data: callback data;
99 * Add a new RTNL watch for newlink events
101 * Returns: %0 on failure and a unique id on success
103 unsigned int connman_rtnl_add_newlink_watch(int index,
104 connman_rtnl_link_cb_t callback, void *user_data)
106 struct watch_data *watch;
108 watch = g_try_new0(struct watch_data, 1);
112 watch->id = ++watch_id;
113 watch->index = index;
115 watch->newlink = callback;
116 watch->user_data = user_data;
118 watch_list = g_slist_prepend(watch_list, watch);
120 DBG("id %d", watch->id);
123 unsigned int flags = __connman_ipconfig_get_flags(index);
126 callback(flags, 0, user_data);
133 * connman_rtnl_remove_watch:
134 * @id: watch identifier
136 * Remove the RTNL watch for the identifier
138 void connman_rtnl_remove_watch(unsigned int id)
147 for (list = watch_list; list; list = list->next) {
148 struct watch_data *watch = list->data;
150 if (watch->id == id) {
151 watch_list = g_slist_remove(watch_list, watch);
158 static void trigger_rtnl(int index, void *user_data)
160 struct connman_rtnl *rtnl = user_data;
163 unsigned short type = __connman_ipconfig_get_type(index);
164 unsigned int flags = __connman_ipconfig_get_flags(index);
166 rtnl->newlink(type, index, flags, 0);
169 if (rtnl->newgateway) {
170 const char *gateway = __connman_ipconfig_get_gateway(index);
173 rtnl->newgateway(index, gateway);
177 static GSList *rtnl_list = NULL;
179 static gint compare_priority(gconstpointer a, gconstpointer b)
181 const struct connman_rtnl *rtnl1 = a;
182 const struct connman_rtnl *rtnl2 = b;
184 return rtnl2->priority - rtnl1->priority;
188 * connman_rtnl_register:
191 * Register a new RTNL module
193 * Returns: %0 on success
195 int connman_rtnl_register(struct connman_rtnl *rtnl)
197 DBG("rtnl %p name %s", rtnl, rtnl->name);
199 rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
202 __connman_ipconfig_foreach(trigger_rtnl, rtnl);
208 * connman_rtnl_unregister:
211 * Remove a previously registered RTNL module
213 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
215 DBG("rtnl %p name %s", rtnl, rtnl->name);
217 rtnl_list = g_slist_remove(rtnl_list, rtnl);
220 static const char *operstate2str(unsigned char operstate)
223 case IF_OPER_UNKNOWN:
225 case IF_OPER_NOTPRESENT:
226 return "NOT-PRESENT";
229 case IF_OPER_LOWERLAYERDOWN:
230 return "LOWER-LAYER-DOWN";
231 case IF_OPER_TESTING:
233 case IF_OPER_DORMANT:
242 static void extract_link(struct ifinfomsg *msg, int bytes,
243 const char **ifname, unsigned char *operstate)
245 struct rtnl_link_stats stats;
248 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
249 attr = RTA_NEXT(attr, bytes)) {
250 switch (attr->rta_type) {
253 *ifname = RTA_DATA(attr);
256 if (operstate != NULL)
257 *operstate = *((unsigned char *) RTA_DATA(attr));
262 memcpy(&stats, RTA_DATA(attr),
263 sizeof(struct rtnl_link_stats));
264 connman_info("%s {RX} %d packets %d bytes", *ifname,
265 stats.rx_packets, stats.rx_bytes);
266 connman_info("%s {TX} %d packets %d bytes", *ifname,
267 stats.tx_packets, stats.tx_bytes);
273 static void process_newlink(unsigned short type, int index, unsigned flags,
274 unsigned change, struct ifinfomsg *msg, int bytes)
276 unsigned char operstate = 0xff;
277 const char *ifname = NULL;
282 case ARPHRD_LOOPBACK:
284 __connman_ipconfig_newlink(index, type, flags);
288 extract_link(msg, bytes, &ifname, &operstate);
290 if (operstate != 0xff)
291 connman_info("%s {newlink} index %d operstate %d <%s>",
292 ifname, index, operstate,
293 operstate2str(operstate));
295 for (list = rtnl_list; list; list = list->next) {
296 struct connman_rtnl *rtnl = list->data;
299 rtnl->newlink(type, index, flags, change);
302 for (list = watch_list; list; list = list->next) {
303 struct watch_data *watch = list->data;
305 if (watch->index != index)
308 if (operstate != 0xff && watch->operstate)
309 watch->operstate(operstate, watch->user_data);
312 watch->newlink(flags, change, watch->user_data);
316 static void process_dellink(unsigned short type, int index, unsigned flags,
317 unsigned change, struct ifinfomsg *msg, int bytes)
319 unsigned char operstate = 0xff;
320 const char *ifname = NULL;
323 extract_link(msg, bytes, &ifname, &operstate);
325 if (operstate != 0xff)
326 connman_info("%s {dellink} index %d operstate %d <%s>",
327 ifname, index, operstate,
328 operstate2str(operstate));
330 for (list = watch_list; list; list = list->next) {
331 struct watch_data *watch = list->data;
333 if (watch->index != index)
336 if (operstate != 0xff && watch->operstate)
337 watch->operstate(operstate, watch->user_data);
340 for (list = rtnl_list; list; list = list->next) {
341 struct connman_rtnl *rtnl = list->data;
344 rtnl->dellink(type, index, flags, change);
349 case ARPHRD_LOOPBACK:
351 __connman_ipconfig_dellink(index);
356 static void extract_addr(struct ifaddrmsg *msg, int bytes,
358 struct in_addr *local,
359 struct in_addr *address,
360 struct in_addr *broadcast)
364 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
365 attr = RTA_NEXT(attr, bytes)) {
366 switch (attr->rta_type) {
369 *address = *((struct in_addr *) RTA_DATA(attr));
373 *local = *((struct in_addr *) RTA_DATA(attr));
376 if (broadcast != NULL)
377 *broadcast = *((struct in_addr *) RTA_DATA(attr));
381 *label = RTA_DATA(attr);
387 static void process_newaddr(unsigned char family, unsigned char prefixlen,
388 int index, struct ifaddrmsg *msg, int bytes)
390 struct in_addr address = { INADDR_ANY };
391 const char *label = NULL;
393 if (family != AF_INET)
396 extract_addr(msg, bytes, &label, &address, NULL, NULL);
398 __connman_ipconfig_newaddr(index, label,
399 prefixlen, inet_ntoa(address));
402 static void process_deladdr(unsigned char family, unsigned char prefixlen,
403 int index, struct ifaddrmsg *msg, int bytes)
405 struct in_addr address = { INADDR_ANY };
406 const char *label = NULL;
408 if (family != AF_INET)
411 extract_addr(msg, bytes, &label, &address, NULL, NULL);
413 __connman_ipconfig_deladdr(index, label,
414 prefixlen, inet_ntoa(address));
417 static void extract_route(struct rtmsg *msg, int bytes, int *index,
419 struct in_addr *gateway)
423 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
424 attr = RTA_NEXT(attr, bytes)) {
425 switch (attr->rta_type) {
428 *dst = *((struct in_addr *) RTA_DATA(attr));
432 *gateway = *((struct in_addr *) RTA_DATA(attr));
436 *index = *((int *) RTA_DATA(attr));
442 static void process_newroute(unsigned char family, unsigned char scope,
443 struct rtmsg *msg, int bytes)
446 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
447 char dststr[16], gatewaystr[16];
450 if (family != AF_INET)
453 extract_route(msg, bytes, &index, &dst, &gateway);
455 inet_ntop(family, &dst, dststr, sizeof(dststr));
456 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
458 __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
460 if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
463 for (list = rtnl_list; list; list = list->next) {
464 struct connman_rtnl *rtnl = list->data;
466 if (rtnl->newgateway)
467 rtnl->newgateway(index, gatewaystr);
471 static void process_delroute(unsigned char family, unsigned char scope,
472 struct rtmsg *msg, int bytes)
475 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
476 char dststr[16], gatewaystr[16];
479 if (family != AF_INET)
482 extract_route(msg, bytes, &index, &dst, &gateway);
484 inet_ntop(family, &dst, dststr, sizeof(dststr));
485 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
487 __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
489 if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
492 for (list = rtnl_list; list; list = list->next) {
493 struct connman_rtnl *rtnl = list->data;
495 if (rtnl->delgateway)
496 rtnl->delgateway(index, gatewaystr);
500 static inline void print_ether(struct rtattr *attr, const char *name)
502 int len = (int) RTA_PAYLOAD(attr);
504 if (len == ETH_ALEN) {
505 struct ether_addr eth;
506 memcpy(ð, RTA_DATA(attr), ETH_ALEN);
507 print(" attr %s (len %d) %s\n", name, len, ether_ntoa(ð));
509 print(" attr %s (len %d)\n", name, len);
512 static inline void print_inet(struct rtattr *attr, const char *name,
513 unsigned char family)
515 int len = (int) RTA_PAYLOAD(attr);
517 if (family == AF_INET && len == sizeof(struct in_addr)) {
519 addr = *((struct in_addr *) RTA_DATA(attr));
520 print(" attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
522 print(" attr %s (len %d)\n", name, len);
525 static inline void print_string(struct rtattr *attr, const char *name)
527 print(" attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
528 (char *) RTA_DATA(attr));
531 static inline void print_byte(struct rtattr *attr, const char *name)
533 print(" attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
534 *((unsigned char *) RTA_DATA(attr)));
537 static inline void print_integer(struct rtattr *attr, const char *name)
539 print(" attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
540 *((int *) RTA_DATA(attr)));
543 static inline void print_attr(struct rtattr *attr, const char *name)
545 int len = (int) RTA_PAYLOAD(attr);
548 print(" attr %s (len %d)\n", name, len);
550 print(" attr %d (len %d)\n", attr->rta_type, len);
553 static void rtnl_link(struct nlmsghdr *hdr)
555 struct ifinfomsg *msg;
559 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
560 bytes = IFLA_PAYLOAD(hdr);
562 print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
564 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
565 attr = RTA_NEXT(attr, bytes)) {
566 switch (attr->rta_type) {
568 print_ether(attr, "address");
571 print_ether(attr, "broadcast");
574 print_string(attr, "ifname");
577 print_integer(attr, "mtu");
580 print_attr(attr, "link");
583 print_attr(attr, "qdisc");
586 print_attr(attr, "stats");
589 print_attr(attr, "cost");
592 print_attr(attr, "priority");
595 print_attr(attr, "master");
598 print_attr(attr, "wireless");
601 print_attr(attr, "protinfo");
604 print_integer(attr, "txqlen");
607 print_attr(attr, "map");
610 print_attr(attr, "weight");
613 print_byte(attr, "operstate");
616 print_byte(attr, "linkmode");
619 print_attr(attr, NULL);
625 static void rtnl_newlink(struct nlmsghdr *hdr)
627 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
631 process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
632 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
635 static void rtnl_dellink(struct nlmsghdr *hdr)
637 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
641 process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
642 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
645 static void rtnl_addr(struct nlmsghdr *hdr)
647 struct ifaddrmsg *msg;
651 msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
652 bytes = IFA_PAYLOAD(hdr);
654 print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
656 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
657 attr = RTA_NEXT(attr, bytes)) {
658 switch (attr->rta_type) {
660 print_inet(attr, "address", msg->ifa_family);
663 print_inet(attr, "local", msg->ifa_family);
666 print_string(attr, "label");
669 print_inet(attr, "broadcast", msg->ifa_family);
672 print_attr(attr, "anycast");
675 print_attr(attr, "cacheinfo");
678 print_attr(attr, "multicast");
681 print_attr(attr, NULL);
687 static void rtnl_newaddr(struct nlmsghdr *hdr)
689 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
693 process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
694 msg, IFA_PAYLOAD(hdr));
697 static void rtnl_deladdr(struct nlmsghdr *hdr)
699 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
703 process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
704 msg, IFA_PAYLOAD(hdr));
707 static void rtnl_route(struct nlmsghdr *hdr)
713 msg = (struct rtmsg *) NLMSG_DATA(hdr);
714 bytes = RTM_PAYLOAD(hdr);
716 print("rtm_family %d rtm_table %d rtm_protocol %d",
717 msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
718 print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
719 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
721 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
722 attr = RTA_NEXT(attr, bytes)) {
723 switch (attr->rta_type) {
725 print_inet(attr, "dst", msg->rtm_family);
728 print_inet(attr, "src", msg->rtm_family);
731 print_string(attr, "iif");
734 print_integer(attr, "oif");
737 print_inet(attr, "gateway", msg->rtm_family);
740 print_attr(attr, "priority");
743 print_inet(attr, "prefsrc", msg->rtm_family);
746 print_attr(attr, "metrics");
749 print_integer(attr, "table");
752 print_attr(attr, NULL);
758 static void rtnl_newroute(struct nlmsghdr *hdr)
760 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
764 if (msg->rtm_table == RT_TABLE_MAIN &&
765 msg->rtm_protocol == RTPROT_BOOT &&
766 msg->rtm_type == RTN_UNICAST)
767 process_newroute(msg->rtm_family, msg->rtm_scope,
768 msg, RTM_PAYLOAD(hdr));
771 static void rtnl_delroute(struct nlmsghdr *hdr)
773 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
777 if (msg->rtm_table == RT_TABLE_MAIN &&
778 msg->rtm_protocol == RTPROT_BOOT &&
779 msg->rtm_type == RTN_UNICAST)
780 process_delroute(msg->rtm_family, msg->rtm_scope,
781 msg, RTM_PAYLOAD(hdr));
784 static const char *type2string(uint16_t type)
816 static GIOChannel *channel = NULL;
818 struct rtnl_request {
822 #define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
824 static GSList *request_list = NULL;
825 static guint32 request_seq = 0;
827 static struct rtnl_request *find_request(guint32 seq)
831 for (list = request_list; list; list = list->next) {
832 struct rtnl_request *req = list->data;
834 if (req->hdr.nlmsg_seq == seq)
841 static int send_request(struct rtnl_request *req)
843 struct sockaddr_nl addr;
846 DBG("%s len %d type %d flags 0x%04x seq %d",
847 type2string(req->hdr.nlmsg_type),
848 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
849 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
851 sk = g_io_channel_unix_get_fd(channel);
853 memset(&addr, 0, sizeof(addr));
854 addr.nl_family = AF_NETLINK;
856 return sendto(sk, req, req->hdr.nlmsg_len, 0,
857 (struct sockaddr *) &addr, sizeof(addr));
860 static int queue_request(struct rtnl_request *req)
862 request_list = g_slist_append(request_list, req);
864 if (g_slist_length(request_list) > 1)
867 return send_request(req);
870 static int process_response(guint32 seq)
872 struct rtnl_request *req;
876 req = find_request(seq);
878 request_list = g_slist_remove(request_list, req);
882 req = g_slist_nth_data(request_list, 0);
886 return send_request(req);
889 static void rtnl_message(void *buf, size_t len)
891 DBG("buf %p len %zd", buf, len);
894 struct nlmsghdr *hdr = buf;
895 struct nlmsgerr *err;
897 if (!NLMSG_OK(hdr, len))
900 DBG("%s len %d type %d flags 0x%04x seq %d",
901 type2string(hdr->nlmsg_type),
902 hdr->nlmsg_len, hdr->nlmsg_type,
903 hdr->nlmsg_flags, hdr->nlmsg_seq);
905 switch (hdr->nlmsg_type) {
910 process_response(hdr->nlmsg_seq);
913 err = NLMSG_DATA(hdr);
914 DBG("error %d (%s)", -err->error,
915 strerror(-err->error));
937 len -= hdr->nlmsg_len;
938 buf += hdr->nlmsg_len;
942 static gboolean netlink_event(GIOChannel *chan,
943 GIOCondition cond, gpointer data)
945 unsigned char buf[4096];
949 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
952 memset(buf, 0, sizeof(buf));
954 err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
956 if (err == G_IO_ERROR_AGAIN)
961 rtnl_message(buf, len);
966 static int send_getlink(void)
968 struct rtnl_request *req;
972 req = g_try_malloc0(RTNL_REQUEST_SIZE);
976 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
977 req->hdr.nlmsg_type = RTM_GETLINK;
978 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
979 req->hdr.nlmsg_pid = 0;
980 req->hdr.nlmsg_seq = request_seq++;
981 req->msg.rtgen_family = AF_INET;
983 return queue_request(req);
986 static int send_getaddr(void)
988 struct rtnl_request *req;
992 req = g_try_malloc0(RTNL_REQUEST_SIZE);
996 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
997 req->hdr.nlmsg_type = RTM_GETADDR;
998 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
999 req->hdr.nlmsg_pid = 0;
1000 req->hdr.nlmsg_seq = request_seq++;
1001 req->msg.rtgen_family = AF_INET;
1003 return queue_request(req);
1006 static int send_getroute(void)
1008 struct rtnl_request *req;
1012 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1016 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1017 req->hdr.nlmsg_type = RTM_GETROUTE;
1018 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1019 req->hdr.nlmsg_pid = 0;
1020 req->hdr.nlmsg_seq = request_seq++;
1021 req->msg.rtgen_family = AF_INET;
1023 return queue_request(req);
1026 int __connman_rtnl_init(void)
1028 struct sockaddr_nl addr;
1033 sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1037 memset(&addr, 0, sizeof(addr));
1038 addr.nl_family = AF_NETLINK;
1039 addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1041 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1046 channel = g_io_channel_unix_new(sk);
1047 g_io_channel_set_close_on_unref(channel, TRUE);
1049 g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1050 netlink_event, NULL);
1055 void __connman_rtnl_start(void)
1064 void __connman_rtnl_cleanup(void)
1070 for (list = watch_list; list; list = list->next) {
1071 struct watch_data *watch = list->data;
1073 DBG("removing watch %d", watch->id);
1079 g_slist_free(watch_list);
1082 for (list = request_list; list; list = list->next) {
1083 struct rtnl_request *req = list->data;
1085 DBG("%s len %d type %d flags 0x%04x seq %d",
1086 type2string(req->hdr.nlmsg_type),
1087 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1088 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1094 g_slist_free(request_list);
1095 request_list = NULL;
1097 g_io_channel_shutdown(channel, TRUE, NULL);
1098 g_io_channel_unref(channel);