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>
32 #include <linux/netlink.h>
33 #include <linux/rtnetlink.h>
42 connman_rtnl_link_cb_t newlink;
46 static GSList *watch_list = NULL;
47 static unsigned int watch_id = 0;
50 * connman_rtnl_add_newlink_watch:
51 * @index: network device index
52 * @callback: callback function
53 * @user_data: callback data;
55 * Add a new RTNL watch for newlink events
57 * Returns: %0 on failure and a unique id on success
59 unsigned int connman_rtnl_add_newlink_watch(int index,
60 connman_rtnl_link_cb_t callback, void *user_data)
62 struct watch_data *watch;
64 watch = g_try_new0(struct watch_data, 1);
68 watch->id = ++watch_id;
71 watch->newlink = callback;
72 watch->user_data = user_data;
74 watch_list = g_slist_prepend(watch_list, watch);
76 DBG("id %d", watch->id);
82 * connman_rtnl_remove_watch:
83 * @id: watch identifier
85 * Remove the RTNL watch for the identifier
87 void connman_rtnl_remove_watch(unsigned int id)
96 for (list = watch_list; list; list = list->next) {
97 struct watch_data *watch = list->data;
99 if (watch->id == id) {
100 watch_list = g_slist_remove(watch_list, watch);
107 static GSList *rtnl_list = NULL;
109 static gint compare_priority(gconstpointer a, gconstpointer b)
111 const struct connman_rtnl *rtnl1 = a;
112 const struct connman_rtnl *rtnl2 = b;
114 return rtnl2->priority - rtnl1->priority;
118 * connman_rtnl_register:
121 * Register a new RTNL module
123 * Returns: %0 on success
125 int connman_rtnl_register(struct connman_rtnl *rtnl)
127 DBG("rtnl %p name %s", rtnl, rtnl->name);
129 rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
136 * connman_rtnl_unregister:
139 * Remove a previously registered RTNL module
141 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
143 DBG("rtnl %p name %s", rtnl, rtnl->name);
145 rtnl_list = g_slist_remove(rtnl_list, rtnl);
148 static void process_newlink(unsigned short type, int index,
149 unsigned flags, unsigned change)
153 for (list = rtnl_list; list; list = list->next) {
154 struct connman_rtnl *rtnl = list->data;
157 rtnl->newlink(type, index, flags, change);
160 for (list = watch_list; list; list = list->next) {
161 struct watch_data *watch = list->data;
163 if (watch->index != index)
167 watch->newlink(flags, change, watch->user_data);
171 static void process_dellink(unsigned short type, int index,
172 unsigned flags, unsigned change)
176 for (list = rtnl_list; list; list = list->next) {
177 struct connman_rtnl *rtnl = list->data;
180 rtnl->dellink(type, index, flags, change);
184 static char *extract_gateway(struct rtmsg *msg, int bytes, int *index)
186 char *gateway = NULL;
190 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
191 attr = RTA_NEXT(attr, bytes)) {
192 switch (attr->rta_type) {
194 addr = *((struct in_addr *) RTA_DATA(attr));
196 gateway = g_strdup(inet_ntoa(addr));
199 *index = *((int *) RTA_DATA(attr));
207 static void process_newgateway(struct rtmsg *msg, int bytes)
213 gateway = extract_gateway(msg, bytes, &index);
214 if (gateway == NULL || index < 0)
217 for (list = rtnl_list; list; list = list->next) {
218 struct connman_rtnl *rtnl = list->data;
220 if (rtnl->newgateway)
221 rtnl->newgateway(index, gateway);
227 static void process_delgateway(struct rtmsg *msg, int bytes)
233 gateway = extract_gateway(msg, bytes, &index);
234 if (gateway == NULL || index < 0)
237 for (list = rtnl_list; list; list = list->next) {
238 struct connman_rtnl *rtnl = list->data;
240 if (rtnl->delgateway)
241 rtnl->delgateway(index, gateway);
247 static void extract_addr(struct ifaddrmsg *msg, int bytes,
249 struct in_addr *local,
250 struct in_addr *address,
251 struct in_addr *broadcast)
255 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
256 attr = RTA_NEXT(attr, bytes)) {
257 switch (attr->rta_type) {
260 *address = *((struct in_addr *) RTA_DATA(attr));
264 *local = *((struct in_addr *) RTA_DATA(attr));
267 if (broadcast != NULL)
268 *broadcast = *((struct in_addr *) RTA_DATA(attr));
272 *label = RTA_DATA(attr);
278 static GSList *ipconfig_list = NULL;
280 static void process_newaddr(int family, int prefixlen, int index,
281 struct ifaddrmsg *msg, int bytes)
285 struct in_addr address;
287 if (family != AF_INET)
290 for (list = ipconfig_list; list; list = list->next) {
291 struct connman_ipconfig *ipconfig = list->data;
293 if (__connman_ipconfig_get_index(ipconfig) != index)
296 extract_addr(msg, bytes, &label, &address, NULL, NULL);
297 __connman_ipconfig_add_address(ipconfig, label, prefixlen,
298 inet_ntoa(address), NULL);
302 static void process_deladdr(int family, int prefixlen, int index,
303 struct ifaddrmsg *msg, int bytes)
307 struct in_addr address;
309 if (family != AF_INET)
312 for (list = ipconfig_list; list; list = list->next) {
313 struct connman_ipconfig *ipconfig = list->data;
315 if (__connman_ipconfig_get_index(ipconfig) != index)
318 extract_addr(msg, bytes, &label, &address, NULL, NULL);
319 __connman_ipconfig_del_address(ipconfig, label, prefixlen,
320 inet_ntoa(address), NULL);
324 int __connman_rtnl_register_ipconfig(struct connman_ipconfig *ipconfig)
326 DBG("ipconfig %p", ipconfig);
328 ipconfig_list = g_slist_append(ipconfig_list, ipconfig);
333 void __connman_rtnl_unregister_ipconfig(struct connman_ipconfig *ipconfig)
335 DBG("ipconfig %p", ipconfig);
337 ipconfig_list = g_slist_remove(ipconfig_list, ipconfig);
340 static inline void print_inet(struct rtattr *attr, const char *name, int family)
342 if (family == AF_INET) {
344 addr = *((struct in_addr *) RTA_DATA(attr));
345 DBG(" attr %s (len %d) %s\n", name,
346 (int) RTA_PAYLOAD(attr), inet_ntoa(addr));
348 DBG(" attr %s (len %d)\n", name, (int) RTA_PAYLOAD(attr));
351 static inline void print_char(struct rtattr *attr, const char *name)
353 DBG(" attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
354 (char *) RTA_DATA(attr));
357 static inline void print_byte(struct rtattr *attr, const char *name)
359 DBG(" attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
360 *((unsigned char *) RTA_DATA(attr)));
363 static inline void print_attr(struct rtattr *attr, const char *name)
366 DBG(" attr %s (len %d)\n", name, (int) RTA_PAYLOAD(attr));
368 DBG(" attr %d (len %d)\n",
369 attr->rta_type, (int) RTA_PAYLOAD(attr));
372 static void rtnl_link(struct nlmsghdr *hdr)
375 struct ifinfomsg *msg;
379 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
380 bytes = IFLA_PAYLOAD(hdr);
382 DBG("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
384 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
385 attr = RTA_NEXT(attr, bytes)) {
386 switch (attr->rta_type) {
388 print_attr(attr, "address");
391 print_attr(attr, "broadcast");
394 print_char(attr, "ifname");
397 print_attr(attr, "mtu");
400 print_attr(attr, "link");
403 print_attr(attr, "qdisc");
406 print_attr(attr, "stats");
409 print_attr(attr, "cost");
412 print_attr(attr, "priority");
415 print_attr(attr, "master");
418 print_attr(attr, "wireless");
421 print_attr(attr, "protinfo");
424 print_attr(attr, "txqlen");
427 print_attr(attr, "map");
430 print_attr(attr, "weight");
433 print_byte(attr, "operstate");
436 print_byte(attr, "linkmode");
439 print_attr(attr, NULL);
446 static void rtnl_newlink(struct nlmsghdr *hdr)
448 struct ifinfomsg *msg;
450 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
452 DBG("ifi_type %d ifi_index %d ifi_flags 0x%04x ifi_change 0x%04x",
453 msg->ifi_type, msg->ifi_index,
454 msg->ifi_flags, msg->ifi_change);
456 process_newlink(msg->ifi_type, msg->ifi_index,
457 msg->ifi_flags, msg->ifi_change);
462 static void rtnl_dellink(struct nlmsghdr *hdr)
464 struct ifinfomsg *msg;
466 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
468 DBG("ifi_type %d ifi_index %d ifi_flags 0x%04x ifi_change 0x%04x",
469 msg->ifi_type, msg->ifi_index,
470 msg->ifi_flags, msg->ifi_change);
472 process_dellink(msg->ifi_type, msg->ifi_index,
473 msg->ifi_flags, msg->ifi_change);
478 static void rtnl_addr(struct nlmsghdr *hdr)
481 struct ifaddrmsg *msg;
485 msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
486 bytes = IFA_PAYLOAD(hdr);
488 DBG("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
490 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
491 attr = RTA_NEXT(attr, bytes)) {
492 switch (attr->rta_type) {
494 print_inet(attr, "address", msg->ifa_family);
497 print_inet(attr, "local", msg->ifa_family);
500 print_char(attr, "label");
503 print_inet(attr, "broadcast", msg->ifa_family);
506 print_attr(attr, "anycast");
509 print_attr(attr, "cacheinfo");
512 print_attr(attr, "multicast");
515 print_attr(attr, NULL);
522 static void rtnl_newaddr(struct nlmsghdr *hdr)
524 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
526 DBG("ifa_family %d ifa_prefixlen %d ifa_index %d",
527 msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index);
529 process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
530 msg, IFA_PAYLOAD(hdr));
535 static void rtnl_deladdr(struct nlmsghdr *hdr)
537 struct ifaddrmsg *msg;
539 msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
541 DBG("ifa_family %d ifa_prefixlen %d ifa_index %d",
542 msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index);
544 process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
545 msg, IFA_PAYLOAD(hdr));
550 static void rtnl_route(struct nlmsghdr *hdr)
557 msg = (struct rtmsg *) NLMSG_DATA(hdr);
558 bytes = RTM_PAYLOAD(hdr);
560 DBG("rtm_family %d rtm_flags 0x%04x", msg->rtm_family, msg->rtm_flags);
562 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
563 attr = RTA_NEXT(attr, bytes)) {
564 switch (attr->rta_type) {
566 print_inet(attr, "dst", msg->rtm_family);
569 print_inet(attr, "src", msg->rtm_family);
572 print_char(attr, "iif");
575 print_attr(attr, "oif");
578 print_inet(attr, "gateway", msg->rtm_family);
581 print_attr(attr, "priority");
584 print_inet(attr, "prefsrc", msg->rtm_family);
587 print_attr(attr, "metrics");
590 print_attr(attr, "table");
593 print_attr(attr, NULL);
600 static void rtnl_newroute(struct nlmsghdr *hdr)
602 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
604 if (msg->rtm_type == RTN_UNICAST && msg->rtm_table == RT_TABLE_MAIN &&
605 msg->rtm_scope == RT_SCOPE_UNIVERSE) {
606 DBG("rtm_table %d rtm_scope %d rtm_type %d rtm_flags 0x%04x",
607 msg->rtm_table, msg->rtm_scope,
608 msg->rtm_type, msg->rtm_flags);
609 process_newgateway(msg, RTM_PAYLOAD(hdr));
615 static void rtnl_delroute(struct nlmsghdr *hdr)
617 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
619 if (msg->rtm_type == RTN_UNICAST && msg->rtm_table == RT_TABLE_MAIN &&
620 msg->rtm_scope == RT_SCOPE_UNIVERSE) {
621 DBG("rtm_table %d rtm_scope %d rtm_type %d rtm_flags 0x%04x",
622 msg->rtm_table, msg->rtm_scope,
623 msg->rtm_type, msg->rtm_flags);
624 process_delgateway(msg, RTM_PAYLOAD(hdr));
630 static const char *type2string(uint16_t type)
662 static GIOChannel *channel = NULL;
664 struct rtnl_request {
668 #define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
670 static GSList *request_list = NULL;
671 static guint32 request_seq = 0;
673 static struct rtnl_request *find_request(guint32 seq)
677 for (list = request_list; list; list = list->next) {
678 struct rtnl_request *req = list->data;
680 if (req->hdr.nlmsg_seq == seq)
687 static int send_request(struct rtnl_request *req)
689 struct sockaddr_nl addr;
692 DBG("%s len %d type %d flags 0x%04x seq %d",
693 type2string(req->hdr.nlmsg_type),
694 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
695 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
697 sk = g_io_channel_unix_get_fd(channel);
699 memset(&addr, 0, sizeof(addr));
700 addr.nl_family = AF_NETLINK;
702 return sendto(sk, req, req->hdr.nlmsg_len, 0,
703 (struct sockaddr *) &addr, sizeof(addr));
706 static int queue_request(struct rtnl_request *req)
708 request_list = g_slist_append(request_list, req);
710 if (g_slist_length(request_list) > 1)
713 return send_request(req);
716 static int process_response(guint32 seq)
718 struct rtnl_request *req;
722 req = find_request(seq);
724 request_list = g_slist_remove(request_list, req);
728 req = g_slist_nth_data(request_list, 0);
732 return send_request(req);
735 static void rtnl_message(void *buf, size_t len)
737 DBG("buf %p len %zd", buf, len);
740 struct nlmsghdr *hdr = buf;
741 struct nlmsgerr *err;
743 if (!NLMSG_OK(hdr, len))
746 DBG("%s len %d type %d flags 0x%04x seq %d",
747 type2string(hdr->nlmsg_type),
748 hdr->nlmsg_len, hdr->nlmsg_type,
749 hdr->nlmsg_flags, hdr->nlmsg_seq);
751 switch (hdr->nlmsg_type) {
756 process_response(hdr->nlmsg_seq);
759 err = NLMSG_DATA(hdr);
760 DBG("error %d (%s)", -err->error,
761 strerror(-err->error));
783 len -= hdr->nlmsg_len;
784 buf += hdr->nlmsg_len;
788 static gboolean netlink_event(GIOChannel *chan,
789 GIOCondition cond, gpointer data)
791 unsigned char buf[4096];
795 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
798 memset(buf, 0, sizeof(buf));
800 err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
802 if (err == G_IO_ERROR_AGAIN)
807 rtnl_message(buf, len);
812 int connman_rtnl_send_getlink(void)
814 struct rtnl_request *req;
818 req = g_try_malloc0(RTNL_REQUEST_SIZE);
822 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
823 req->hdr.nlmsg_type = RTM_GETLINK;
824 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
825 req->hdr.nlmsg_pid = 0;
826 req->hdr.nlmsg_seq = request_seq++;
827 req->msg.rtgen_family = AF_INET;
829 return queue_request(req);
832 static int send_getaddr(void)
834 struct rtnl_request *req;
838 req = g_try_malloc0(RTNL_REQUEST_SIZE);
842 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
843 req->hdr.nlmsg_type = RTM_GETADDR;
844 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
845 req->hdr.nlmsg_pid = 0;
846 req->hdr.nlmsg_seq = request_seq++;
847 req->msg.rtgen_family = AF_INET;
849 return queue_request(req);
852 int connman_rtnl_send_getroute(void)
854 struct rtnl_request *req;
858 req = g_try_malloc0(RTNL_REQUEST_SIZE);
862 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
863 req->hdr.nlmsg_type = RTM_GETROUTE;
864 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
865 req->hdr.nlmsg_pid = 0;
866 req->hdr.nlmsg_seq = request_seq++;
867 req->msg.rtgen_family = AF_INET;
869 return queue_request(req);
872 int __connman_rtnl_init(void)
874 struct sockaddr_nl addr;
879 sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
883 memset(&addr, 0, sizeof(addr));
884 addr.nl_family = AF_NETLINK;
885 addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
887 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
892 channel = g_io_channel_unix_new(sk);
893 g_io_channel_set_close_on_unref(channel, TRUE);
895 g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
896 netlink_event, NULL);
901 void __connman_rtnl_start(void)
908 void __connman_rtnl_cleanup(void)
914 g_slist_free(ipconfig_list);
915 ipconfig_list = NULL;
917 for (list = watch_list; list; list = list->next) {
918 struct watch_data *watch = list->data;
920 DBG("removing watch %d", watch->id);
926 g_slist_free(watch_list);
929 for (list = request_list; list; list = list->next) {
930 struct rtnl_request *req = list->data;
932 DBG("%s len %d type %d flags 0x%04x seq %d",
933 type2string(req->hdr.nlmsg_type),
934 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
935 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
941 g_slist_free(request_list);
944 g_io_channel_shutdown(channel, TRUE, NULL);
945 g_io_channel_unref(channel);