5 * Copyright (C) 2007-2010 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
29 #include <sys/socket.h>
30 #include <arpa/inet.h>
31 #include <netinet/ether.h>
32 #include <net/if_arp.h>
34 #include <linux/netlink.h>
35 #include <linux/rtnetlink.h>
41 #define print(arg...) do { } while (0)
42 //#define print(arg...) connman_info(arg)
47 connman_rtnl_operstate_cb_t operstate;
48 connman_rtnl_link_cb_t newlink;
52 static GSList *watch_list = NULL;
53 static unsigned int watch_id = 0;
55 static GSList *update_list = NULL;
56 static guint update_interval = G_MAXUINT;
57 static guint update_timeout = 0;
59 struct interface_data {
62 enum connman_service_type type;
65 static GHashTable *interface_list = NULL;
67 static void free_interface(gpointer data)
69 struct interface_data *interface = data;
71 __connman_technology_remove_interface(interface->type,
72 interface->index, interface->name);
74 g_free(interface->name);
78 static void read_uevent(struct interface_data *interface)
80 char *filename, line[128];
83 filename = g_strdup_printf("/sys/class/net/%s/uevent",
86 f = fopen(filename, "re");
90 while (fgets(line, sizeof(line), f)) {
93 pos = strchr(line, '\n');
98 if (strncmp(line, "DEVTYPE=", 8) != 0)
101 if (strcmp(line + 8, "wlan") == 0)
102 interface->type = CONNMAN_SERVICE_TYPE_WIFI;
103 else if (strcmp(line + 8, "wwan") == 0)
104 interface->type = CONNMAN_SERVICE_TYPE_CELLULAR;
105 else if (strcmp(line + 8, "bluetooth") == 0)
106 interface->type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
107 else if (strcmp(line + 8, "wimax") == 0)
108 interface->type = CONNMAN_SERVICE_TYPE_WIMAX;
115 * connman_rtnl_add_operstate_watch:
116 * @index: network device index
117 * @callback: callback function
118 * @user_data: callback data;
120 * Add a new RTNL watch for operation state events
122 * Returns: %0 on failure and a unique id on success
124 unsigned int connman_rtnl_add_operstate_watch(int index,
125 connman_rtnl_operstate_cb_t callback, void *user_data)
127 struct watch_data *watch;
129 watch = g_try_new0(struct watch_data, 1);
133 watch->id = ++watch_id;
134 watch->index = index;
136 watch->operstate = callback;
137 watch->user_data = user_data;
139 watch_list = g_slist_prepend(watch_list, watch);
141 DBG("id %d", watch->id);
144 unsigned char operstate = 0;
147 callback(operstate, user_data);
154 * connman_rtnl_add_newlink_watch:
155 * @index: network device index
156 * @callback: callback function
157 * @user_data: callback data;
159 * Add a new RTNL watch for newlink events
161 * Returns: %0 on failure and a unique id on success
163 unsigned int connman_rtnl_add_newlink_watch(int index,
164 connman_rtnl_link_cb_t callback, void *user_data)
166 struct watch_data *watch;
168 watch = g_try_new0(struct watch_data, 1);
172 watch->id = ++watch_id;
173 watch->index = index;
175 watch->newlink = callback;
176 watch->user_data = user_data;
178 watch_list = g_slist_prepend(watch_list, watch);
180 DBG("id %d", watch->id);
183 unsigned int flags = __connman_ipconfig_get_flags(index);
186 callback(flags, 0, user_data);
193 * connman_rtnl_remove_watch:
194 * @id: watch identifier
196 * Remove the RTNL watch for the identifier
198 void connman_rtnl_remove_watch(unsigned int id)
207 for (list = watch_list; list; list = list->next) {
208 struct watch_data *watch = list->data;
210 if (watch->id == id) {
211 watch_list = g_slist_remove(watch_list, watch);
218 static void trigger_rtnl(int index, void *user_data)
220 struct connman_rtnl *rtnl = user_data;
223 unsigned short type = __connman_ipconfig_get_type(index);
224 unsigned int flags = __connman_ipconfig_get_flags(index);
226 rtnl->newlink(type, index, flags, 0);
229 if (rtnl->newgateway) {
230 const char *gateway = __connman_ipconfig_get_gateway(index);
233 rtnl->newgateway(index, gateway);
237 static GSList *rtnl_list = NULL;
239 static gint compare_priority(gconstpointer a, gconstpointer b)
241 const struct connman_rtnl *rtnl1 = a;
242 const struct connman_rtnl *rtnl2 = b;
244 return rtnl2->priority - rtnl1->priority;
248 * connman_rtnl_register:
251 * Register a new RTNL module
253 * Returns: %0 on success
255 int connman_rtnl_register(struct connman_rtnl *rtnl)
257 DBG("rtnl %p name %s", rtnl, rtnl->name);
259 rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
262 __connman_ipconfig_foreach(trigger_rtnl, rtnl);
268 * connman_rtnl_unregister:
271 * Remove a previously registered RTNL module
273 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
275 DBG("rtnl %p name %s", rtnl, rtnl->name);
277 rtnl_list = g_slist_remove(rtnl_list, rtnl);
280 static const char *operstate2str(unsigned char operstate)
283 case IF_OPER_UNKNOWN:
285 case IF_OPER_NOTPRESENT:
286 return "NOT-PRESENT";
289 case IF_OPER_LOWERLAYERDOWN:
290 return "LOWER-LAYER-DOWN";
291 case IF_OPER_TESTING:
293 case IF_OPER_DORMANT:
302 static void extract_link(struct ifinfomsg *msg, int bytes,
303 struct ether_addr *address, const char **ifname,
304 unsigned int *mtu, unsigned char *operstate,
305 struct rtnl_link_stats *stats)
309 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
310 attr = RTA_NEXT(attr, bytes)) {
311 switch (attr->rta_type) {
314 memcpy(address, RTA_DATA(attr), ETH_ALEN);
318 *ifname = RTA_DATA(attr);
322 *mtu = *((unsigned int *) RTA_DATA(attr));
326 memcpy(stats, RTA_DATA(attr),
327 sizeof(struct rtnl_link_stats));
330 if (operstate != NULL)
331 *operstate = *((unsigned char *) RTA_DATA(attr));
339 static void process_newlink(unsigned short type, int index, unsigned flags,
340 unsigned change, struct ifinfomsg *msg, int bytes)
342 struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
343 struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }};
344 struct rtnl_link_stats stats;
345 unsigned char operstate = 0xff;
346 const char *ifname = NULL;
347 unsigned int mtu = 0;
351 memset(&stats, 0, sizeof(stats));
352 extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats);
354 snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
355 address.ether_addr_octet[0],
356 address.ether_addr_octet[1],
357 address.ether_addr_octet[2],
358 address.ether_addr_octet[3],
359 address.ether_addr_octet[4],
360 address.ether_addr_octet[5]);
364 case ARPHRD_LOOPBACK:
366 __connman_ipconfig_newlink(index, type, flags,
371 if (memcmp(&address, &compare, ETH_ALEN) != 0)
372 connman_info("%s {newlink} index %d address %s mtu %u",
373 ifname, index, str, mtu);
375 if (operstate != 0xff)
376 connman_info("%s {newlink} index %d operstate %u <%s>",
377 ifname, index, operstate,
378 operstate2str(operstate));
380 if (g_hash_table_lookup(interface_list, &index) == NULL) {
381 struct interface_data *interface;
383 interface = g_new0(struct interface_data, 1);
384 interface->index = index;
385 interface->name = g_strdup(ifname);
387 g_hash_table_insert(interface_list, &index, interface);
389 read_uevent(interface);
391 __connman_technology_add_interface(interface->type,
392 interface->index, interface->name);
395 for (list = rtnl_list; list; list = list->next) {
396 struct connman_rtnl *rtnl = list->data;
399 rtnl->newlink(type, index, flags, change);
402 for (list = watch_list; list; list = list->next) {
403 struct watch_data *watch = list->data;
405 if (watch->index != index)
408 if (operstate != 0xff && watch->operstate)
409 watch->operstate(operstate, watch->user_data);
412 watch->newlink(flags, change, watch->user_data);
416 static void process_dellink(unsigned short type, int index, unsigned flags,
417 unsigned change, struct ifinfomsg *msg, int bytes)
419 struct rtnl_link_stats stats;
420 unsigned char operstate = 0xff;
421 const char *ifname = NULL;
424 memset(&stats, 0, sizeof(stats));
425 extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats);
427 if (operstate != 0xff)
428 connman_info("%s {dellink} index %d operstate %u <%s>",
429 ifname, index, operstate,
430 operstate2str(operstate));
432 for (list = watch_list; list; list = list->next) {
433 struct watch_data *watch = list->data;
435 if (watch->index != index)
438 if (operstate != 0xff && watch->operstate)
439 watch->operstate(operstate, watch->user_data);
442 for (list = rtnl_list; list; list = list->next) {
443 struct connman_rtnl *rtnl = list->data;
446 rtnl->dellink(type, index, flags, change);
451 case ARPHRD_LOOPBACK:
453 __connman_ipconfig_dellink(index, &stats);
457 g_hash_table_remove(interface_list, &index);
460 static void extract_addr(struct ifaddrmsg *msg, int bytes,
462 struct in_addr *local,
463 struct in_addr *address,
464 struct in_addr *broadcast)
468 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
469 attr = RTA_NEXT(attr, bytes)) {
470 switch (attr->rta_type) {
473 *address = *((struct in_addr *) RTA_DATA(attr));
477 *local = *((struct in_addr *) RTA_DATA(attr));
480 if (broadcast != NULL)
481 *broadcast = *((struct in_addr *) RTA_DATA(attr));
485 *label = RTA_DATA(attr);
491 static void process_newaddr(unsigned char family, unsigned char prefixlen,
492 int index, struct ifaddrmsg *msg, int bytes)
494 struct in_addr address = { INADDR_ANY };
495 const char *label = NULL;
497 if (family != AF_INET)
500 extract_addr(msg, bytes, &label, &address, NULL, NULL);
502 __connman_ipconfig_newaddr(index, label,
503 prefixlen, inet_ntoa(address));
506 static void process_deladdr(unsigned char family, unsigned char prefixlen,
507 int index, struct ifaddrmsg *msg, int bytes)
509 struct in_addr address = { INADDR_ANY };
510 const char *label = NULL;
512 if (family != AF_INET)
515 extract_addr(msg, bytes, &label, &address, NULL, NULL);
517 __connman_ipconfig_deladdr(index, label,
518 prefixlen, inet_ntoa(address));
521 static void extract_route(struct rtmsg *msg, int bytes, int *index,
523 struct in_addr *gateway)
527 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
528 attr = RTA_NEXT(attr, bytes)) {
529 switch (attr->rta_type) {
532 *dst = *((struct in_addr *) RTA_DATA(attr));
536 *gateway = *((struct in_addr *) RTA_DATA(attr));
540 *index = *((int *) RTA_DATA(attr));
546 static void process_newroute(unsigned char family, unsigned char scope,
547 struct rtmsg *msg, int bytes)
550 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
551 char dststr[16], gatewaystr[16];
554 if (family != AF_INET)
557 extract_route(msg, bytes, &index, &dst, &gateway);
559 inet_ntop(family, &dst, dststr, sizeof(dststr));
560 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
562 __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
564 /* skip host specific routes */
565 if (scope != RT_SCOPE_UNIVERSE &&
566 !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
569 if (dst.s_addr != INADDR_ANY)
572 for (list = rtnl_list; list; list = list->next) {
573 struct connman_rtnl *rtnl = list->data;
575 if (rtnl->newgateway)
576 rtnl->newgateway(index, gatewaystr);
580 static void process_delroute(unsigned char family, unsigned char scope,
581 struct rtmsg *msg, int bytes)
584 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
585 char dststr[16], gatewaystr[16];
588 if (family != AF_INET)
591 extract_route(msg, bytes, &index, &dst, &gateway);
593 inet_ntop(family, &dst, dststr, sizeof(dststr));
594 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
596 __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
598 /* skip host specific routes */
599 if (scope != RT_SCOPE_UNIVERSE &&
600 !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY))
603 if (dst.s_addr != INADDR_ANY)
606 for (list = rtnl_list; list; list = list->next) {
607 struct connman_rtnl *rtnl = list->data;
609 if (rtnl->delgateway)
610 rtnl->delgateway(index, gatewaystr);
614 static inline void print_ether(struct rtattr *attr, const char *name)
616 int len = (int) RTA_PAYLOAD(attr);
618 if (len == ETH_ALEN) {
619 struct ether_addr eth;
620 memcpy(ð, RTA_DATA(attr), ETH_ALEN);
621 print(" attr %s (len %d) %s\n", name, len, ether_ntoa(ð));
623 print(" attr %s (len %d)\n", name, len);
626 static inline void print_inet(struct rtattr *attr, const char *name,
627 unsigned char family)
629 int len = (int) RTA_PAYLOAD(attr);
631 if (family == AF_INET && len == sizeof(struct in_addr)) {
633 addr = *((struct in_addr *) RTA_DATA(attr));
634 print(" attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
636 print(" attr %s (len %d)\n", name, len);
639 static inline void print_string(struct rtattr *attr, const char *name)
641 print(" attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
642 (char *) RTA_DATA(attr));
645 static inline void print_byte(struct rtattr *attr, const char *name)
647 print(" attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
648 *((unsigned char *) RTA_DATA(attr)));
651 static inline void print_integer(struct rtattr *attr, const char *name)
653 print(" attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
654 *((int *) RTA_DATA(attr)));
657 static inline void print_attr(struct rtattr *attr, const char *name)
659 int len = (int) RTA_PAYLOAD(attr);
662 print(" attr %s (len %d)\n", name, len);
664 print(" attr %d (len %d)\n", attr->rta_type, len);
667 static void rtnl_link(struct nlmsghdr *hdr)
669 struct ifinfomsg *msg;
673 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
674 bytes = IFLA_PAYLOAD(hdr);
676 print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
678 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
679 attr = RTA_NEXT(attr, bytes)) {
680 switch (attr->rta_type) {
682 print_ether(attr, "address");
685 print_ether(attr, "broadcast");
688 print_string(attr, "ifname");
691 print_integer(attr, "mtu");
694 print_attr(attr, "link");
697 print_attr(attr, "qdisc");
700 print_attr(attr, "stats");
703 print_attr(attr, "cost");
706 print_attr(attr, "priority");
709 print_attr(attr, "master");
712 print_attr(attr, "wireless");
715 print_attr(attr, "protinfo");
718 print_integer(attr, "txqlen");
721 print_attr(attr, "map");
724 print_attr(attr, "weight");
727 print_byte(attr, "operstate");
730 print_byte(attr, "linkmode");
733 print_attr(attr, NULL);
739 static void rtnl_newlink(struct nlmsghdr *hdr)
741 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
745 process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
746 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
749 static void rtnl_dellink(struct nlmsghdr *hdr)
751 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
755 process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
756 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
759 static void rtnl_addr(struct nlmsghdr *hdr)
761 struct ifaddrmsg *msg;
765 msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
766 bytes = IFA_PAYLOAD(hdr);
768 print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
770 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
771 attr = RTA_NEXT(attr, bytes)) {
772 switch (attr->rta_type) {
774 print_inet(attr, "address", msg->ifa_family);
777 print_inet(attr, "local", msg->ifa_family);
780 print_string(attr, "label");
783 print_inet(attr, "broadcast", msg->ifa_family);
786 print_attr(attr, "anycast");
789 print_attr(attr, "cacheinfo");
792 print_attr(attr, "multicast");
795 print_attr(attr, NULL);
801 static void rtnl_newaddr(struct nlmsghdr *hdr)
803 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
807 process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
808 msg, IFA_PAYLOAD(hdr));
811 static void rtnl_deladdr(struct nlmsghdr *hdr)
813 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
817 process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
818 msg, IFA_PAYLOAD(hdr));
821 static void rtnl_route(struct nlmsghdr *hdr)
827 msg = (struct rtmsg *) NLMSG_DATA(hdr);
828 bytes = RTM_PAYLOAD(hdr);
830 print("rtm_family %d rtm_table %d rtm_protocol %d",
831 msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
832 print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
833 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
835 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
836 attr = RTA_NEXT(attr, bytes)) {
837 switch (attr->rta_type) {
839 print_inet(attr, "dst", msg->rtm_family);
842 print_inet(attr, "src", msg->rtm_family);
845 print_string(attr, "iif");
848 print_integer(attr, "oif");
851 print_inet(attr, "gateway", msg->rtm_family);
854 print_attr(attr, "priority");
857 print_inet(attr, "prefsrc", msg->rtm_family);
860 print_attr(attr, "metrics");
863 print_integer(attr, "table");
866 print_attr(attr, NULL);
872 static connman_bool_t is_route_rtmsg(struct rtmsg *msg)
875 if (msg->rtm_table != RT_TABLE_MAIN)
878 if (msg->rtm_protocol != RTPROT_BOOT &&
879 msg->rtm_protocol != RTPROT_KERNEL)
882 if (msg->rtm_type != RTN_UNICAST)
888 static void rtnl_newroute(struct nlmsghdr *hdr)
890 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
894 if (is_route_rtmsg(msg))
895 process_newroute(msg->rtm_family, msg->rtm_scope,
896 msg, RTM_PAYLOAD(hdr));
899 static void rtnl_delroute(struct nlmsghdr *hdr)
901 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
905 if (is_route_rtmsg(msg))
906 process_delroute(msg->rtm_family, msg->rtm_scope,
907 msg, RTM_PAYLOAD(hdr));
910 static const char *type2string(uint16_t type)
942 static GIOChannel *channel = NULL;
944 struct rtnl_request {
948 #define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
950 static GSList *request_list = NULL;
951 static guint32 request_seq = 0;
953 static struct rtnl_request *find_request(guint32 seq)
957 for (list = request_list; list; list = list->next) {
958 struct rtnl_request *req = list->data;
960 if (req->hdr.nlmsg_seq == seq)
967 static int send_request(struct rtnl_request *req)
969 struct sockaddr_nl addr;
972 DBG("%s len %d type %d flags 0x%04x seq %d",
973 type2string(req->hdr.nlmsg_type),
974 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
975 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
977 sk = g_io_channel_unix_get_fd(channel);
979 memset(&addr, 0, sizeof(addr));
980 addr.nl_family = AF_NETLINK;
982 return sendto(sk, req, req->hdr.nlmsg_len, 0,
983 (struct sockaddr *) &addr, sizeof(addr));
986 static int queue_request(struct rtnl_request *req)
988 request_list = g_slist_append(request_list, req);
990 if (g_slist_length(request_list) > 1)
993 return send_request(req);
996 static int process_response(guint32 seq)
998 struct rtnl_request *req;
1002 req = find_request(seq);
1004 request_list = g_slist_remove(request_list, req);
1008 req = g_slist_nth_data(request_list, 0);
1012 return send_request(req);
1015 static void rtnl_message(void *buf, size_t len)
1017 DBG("buf %p len %zd", buf, len);
1020 struct nlmsghdr *hdr = buf;
1021 struct nlmsgerr *err;
1023 if (!NLMSG_OK(hdr, len))
1026 DBG("%s len %d type %d flags 0x%04x seq %d",
1027 type2string(hdr->nlmsg_type),
1028 hdr->nlmsg_len, hdr->nlmsg_type,
1029 hdr->nlmsg_flags, hdr->nlmsg_seq);
1031 switch (hdr->nlmsg_type) {
1036 process_response(hdr->nlmsg_seq);
1039 err = NLMSG_DATA(hdr);
1040 DBG("error %d (%s)", -err->error,
1041 strerror(-err->error));
1063 len -= hdr->nlmsg_len;
1064 buf += hdr->nlmsg_len;
1068 static gboolean netlink_event(GIOChannel *chan,
1069 GIOCondition cond, gpointer data)
1071 unsigned char buf[4096];
1075 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
1078 memset(buf, 0, sizeof(buf));
1080 err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
1082 if (err == G_IO_ERROR_AGAIN)
1087 rtnl_message(buf, len);
1092 static int send_getlink(void)
1094 struct rtnl_request *req;
1098 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1102 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1103 req->hdr.nlmsg_type = RTM_GETLINK;
1104 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1105 req->hdr.nlmsg_pid = 0;
1106 req->hdr.nlmsg_seq = request_seq++;
1107 req->msg.rtgen_family = AF_INET;
1109 return queue_request(req);
1112 static int send_getaddr(void)
1114 struct rtnl_request *req;
1118 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1122 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1123 req->hdr.nlmsg_type = RTM_GETADDR;
1124 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1125 req->hdr.nlmsg_pid = 0;
1126 req->hdr.nlmsg_seq = request_seq++;
1127 req->msg.rtgen_family = AF_INET;
1129 return queue_request(req);
1132 static int send_getroute(void)
1134 struct rtnl_request *req;
1138 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1142 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1143 req->hdr.nlmsg_type = RTM_GETROUTE;
1144 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1145 req->hdr.nlmsg_pid = 0;
1146 req->hdr.nlmsg_seq = request_seq++;
1147 req->msg.rtgen_family = AF_INET;
1149 return queue_request(req);
1152 static gboolean update_timeout_cb(gpointer user_data)
1154 __connman_rtnl_request_update();
1159 static void update_interval_callback(guint min)
1161 if (update_timeout > 0)
1162 g_source_remove(update_timeout);
1164 if (min < G_MAXUINT) {
1165 update_interval = min;
1166 update_timeout = g_timeout_add_seconds(update_interval,
1167 update_timeout_cb, NULL);
1170 update_interval = G_MAXUINT;
1174 static gint compare_interval(gconstpointer a, gconstpointer b)
1176 guint val_a = GPOINTER_TO_UINT(a);
1177 guint val_b = GPOINTER_TO_UINT(b);
1179 return val_a - val_b;
1182 unsigned int __connman_rtnl_update_interval_add(unsigned int interval)
1189 update_list = g_slist_insert_sorted(update_list,
1190 GUINT_TO_POINTER(interval), compare_interval);
1192 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1193 if (min < update_interval) {
1194 update_interval_callback(min);
1195 __connman_rtnl_request_update();
1198 return update_interval;
1201 unsigned int __connman_rtnl_update_interval_remove(unsigned int interval)
1203 guint min = G_MAXUINT;
1208 update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
1210 if (update_list != NULL)
1211 min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
1213 if (min > update_interval)
1214 update_interval_callback(min);
1219 int __connman_rtnl_request_update(void)
1221 return send_getlink();
1224 int __connman_rtnl_init(void)
1226 struct sockaddr_nl addr;
1231 interface_list = g_hash_table_new_full(g_int_hash, g_int_equal,
1232 NULL, free_interface);
1234 sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1238 memset(&addr, 0, sizeof(addr));
1239 addr.nl_family = AF_NETLINK;
1240 addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1242 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1247 channel = g_io_channel_unix_new(sk);
1248 g_io_channel_set_close_on_unref(channel, TRUE);
1250 g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1251 netlink_event, NULL);
1256 void __connman_rtnl_start(void)
1265 void __connman_rtnl_cleanup(void)
1271 for (list = watch_list; list; list = list->next) {
1272 struct watch_data *watch = list->data;
1274 DBG("removing watch %d", watch->id);
1280 g_slist_free(watch_list);
1283 g_slist_free(update_list);
1286 for (list = request_list; list; list = list->next) {
1287 struct rtnl_request *req = list->data;
1289 DBG("%s len %d type %d flags 0x%04x seq %d",
1290 type2string(req->hdr.nlmsg_type),
1291 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1292 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1298 g_slist_free(request_list);
1299 request_list = NULL;
1301 g_io_channel_shutdown(channel, TRUE, NULL);
1302 g_io_channel_unref(channel);
1306 g_hash_table_destroy(interface_list);