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;
56 * connman_rtnl_add_operstate_watch:
57 * @index: network device index
58 * @callback: callback function
59 * @user_data: callback data;
61 * Add a new RTNL watch for operation state events
63 * Returns: %0 on failure and a unique id on success
65 unsigned int connman_rtnl_add_operstate_watch(int index,
66 connman_rtnl_operstate_cb_t callback, void *user_data)
68 struct watch_data *watch;
70 watch = g_try_new0(struct watch_data, 1);
74 watch->id = ++watch_id;
77 watch->operstate = callback;
78 watch->user_data = user_data;
80 watch_list = g_slist_prepend(watch_list, watch);
82 DBG("id %d", watch->id);
85 unsigned char operstate = 0;
88 callback(operstate, user_data);
95 * connman_rtnl_add_newlink_watch:
96 * @index: network device index
97 * @callback: callback function
98 * @user_data: callback data;
100 * Add a new RTNL watch for newlink events
102 * Returns: %0 on failure and a unique id on success
104 unsigned int connman_rtnl_add_newlink_watch(int index,
105 connman_rtnl_link_cb_t callback, void *user_data)
107 struct watch_data *watch;
109 watch = g_try_new0(struct watch_data, 1);
113 watch->id = ++watch_id;
114 watch->index = index;
116 watch->newlink = callback;
117 watch->user_data = user_data;
119 watch_list = g_slist_prepend(watch_list, watch);
121 DBG("id %d", watch->id);
124 unsigned int flags = __connman_ipconfig_get_flags(index);
127 callback(flags, 0, user_data);
134 * connman_rtnl_remove_watch:
135 * @id: watch identifier
137 * Remove the RTNL watch for the identifier
139 void connman_rtnl_remove_watch(unsigned int id)
148 for (list = watch_list; list; list = list->next) {
149 struct watch_data *watch = list->data;
151 if (watch->id == id) {
152 watch_list = g_slist_remove(watch_list, watch);
159 static void trigger_rtnl(int index, void *user_data)
161 struct connman_rtnl *rtnl = user_data;
164 unsigned short type = __connman_ipconfig_get_type(index);
165 unsigned int flags = __connman_ipconfig_get_flags(index);
167 rtnl->newlink(type, index, flags, 0);
170 if (rtnl->newgateway) {
171 const char *gateway = __connman_ipconfig_get_gateway(index);
174 rtnl->newgateway(index, gateway);
178 static GSList *rtnl_list = NULL;
180 static gint compare_priority(gconstpointer a, gconstpointer b)
182 const struct connman_rtnl *rtnl1 = a;
183 const struct connman_rtnl *rtnl2 = b;
185 return rtnl2->priority - rtnl1->priority;
189 * connman_rtnl_register:
192 * Register a new RTNL module
194 * Returns: %0 on success
196 int connman_rtnl_register(struct connman_rtnl *rtnl)
198 DBG("rtnl %p name %s", rtnl, rtnl->name);
200 rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
203 __connman_ipconfig_foreach(trigger_rtnl, rtnl);
209 * connman_rtnl_unregister:
212 * Remove a previously registered RTNL module
214 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
216 DBG("rtnl %p name %s", rtnl, rtnl->name);
218 rtnl_list = g_slist_remove(rtnl_list, rtnl);
221 static const char *operstate2str(unsigned char operstate)
224 case IF_OPER_UNKNOWN:
226 case IF_OPER_NOTPRESENT:
227 return "NOT-PRESENT";
230 case IF_OPER_LOWERLAYERDOWN:
231 return "LOWER-LAYER-DOWN";
232 case IF_OPER_TESTING:
234 case IF_OPER_DORMANT:
243 static void extract_link(struct ifinfomsg *msg, int bytes,
244 struct ether_addr *address, const char **ifname,
245 unsigned int *mtu, unsigned char *operstate)
247 struct rtnl_link_stats stats;
250 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
251 attr = RTA_NEXT(attr, bytes)) {
252 switch (attr->rta_type) {
255 memcpy(address, RTA_DATA(attr), ETH_ALEN);
259 *ifname = RTA_DATA(attr);
263 *mtu = *((unsigned int *) RTA_DATA(attr));
266 memcpy(&stats, RTA_DATA(attr),
267 sizeof(struct rtnl_link_stats));
268 connman_info("%s {RX} %d packets %d bytes", *ifname,
269 stats.rx_packets, stats.rx_bytes);
270 connman_info("%s {TX} %d packets %d bytes", *ifname,
271 stats.tx_packets, stats.tx_bytes);
274 if (operstate != NULL)
275 *operstate = *((unsigned char *) RTA_DATA(attr));
283 static void process_newlink(unsigned short type, int index, unsigned flags,
284 unsigned change, struct ifinfomsg *msg, int bytes)
286 struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
287 struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }};
288 unsigned char operstate = 0xff;
289 const char *ifname = NULL;
290 unsigned int mtu = 0;
294 extract_link(msg, bytes, &address, &ifname, &mtu, &operstate);
296 snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
297 address.ether_addr_octet[0],
298 address.ether_addr_octet[1],
299 address.ether_addr_octet[2],
300 address.ether_addr_octet[3],
301 address.ether_addr_octet[4],
302 address.ether_addr_octet[5]);
306 case ARPHRD_LOOPBACK:
308 __connman_ipconfig_newlink(index, type, flags, str, mtu);
312 if (memcmp(&address, &compare, ETH_ALEN) != 0)
313 connman_info("%s {newlink} index %d address %s mtu %u",
314 ifname, index, str, mtu);
316 if (operstate != 0xff)
317 connman_info("%s {newlink} index %d operstate %u <%s>",
318 ifname, index, operstate,
319 operstate2str(operstate));
321 for (list = rtnl_list; list; list = list->next) {
322 struct connman_rtnl *rtnl = list->data;
325 rtnl->newlink(type, index, flags, change);
328 for (list = watch_list; list; list = list->next) {
329 struct watch_data *watch = list->data;
331 if (watch->index != index)
334 if (operstate != 0xff && watch->operstate)
335 watch->operstate(operstate, watch->user_data);
338 watch->newlink(flags, change, watch->user_data);
342 static void process_dellink(unsigned short type, int index, unsigned flags,
343 unsigned change, struct ifinfomsg *msg, int bytes)
345 unsigned char operstate = 0xff;
346 const char *ifname = NULL;
349 extract_link(msg, bytes, NULL, &ifname, NULL, &operstate);
351 if (operstate != 0xff)
352 connman_info("%s {dellink} index %d operstate %u <%s>",
353 ifname, index, operstate,
354 operstate2str(operstate));
356 for (list = watch_list; list; list = list->next) {
357 struct watch_data *watch = list->data;
359 if (watch->index != index)
362 if (operstate != 0xff && watch->operstate)
363 watch->operstate(operstate, watch->user_data);
366 for (list = rtnl_list; list; list = list->next) {
367 struct connman_rtnl *rtnl = list->data;
370 rtnl->dellink(type, index, flags, change);
375 case ARPHRD_LOOPBACK:
377 __connman_ipconfig_dellink(index);
382 static void extract_addr(struct ifaddrmsg *msg, int bytes,
384 struct in_addr *local,
385 struct in_addr *address,
386 struct in_addr *broadcast)
390 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
391 attr = RTA_NEXT(attr, bytes)) {
392 switch (attr->rta_type) {
395 *address = *((struct in_addr *) RTA_DATA(attr));
399 *local = *((struct in_addr *) RTA_DATA(attr));
402 if (broadcast != NULL)
403 *broadcast = *((struct in_addr *) RTA_DATA(attr));
407 *label = RTA_DATA(attr);
413 static void process_newaddr(unsigned char family, unsigned char prefixlen,
414 int index, struct ifaddrmsg *msg, int bytes)
416 struct in_addr address = { INADDR_ANY };
417 const char *label = NULL;
419 if (family != AF_INET)
422 extract_addr(msg, bytes, &label, &address, NULL, NULL);
424 __connman_ipconfig_newaddr(index, label,
425 prefixlen, inet_ntoa(address));
428 static void process_deladdr(unsigned char family, unsigned char prefixlen,
429 int index, struct ifaddrmsg *msg, int bytes)
431 struct in_addr address = { INADDR_ANY };
432 const char *label = NULL;
434 if (family != AF_INET)
437 extract_addr(msg, bytes, &label, &address, NULL, NULL);
439 __connman_ipconfig_deladdr(index, label,
440 prefixlen, inet_ntoa(address));
443 static void extract_route(struct rtmsg *msg, int bytes, int *index,
445 struct in_addr *gateway)
449 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
450 attr = RTA_NEXT(attr, bytes)) {
451 switch (attr->rta_type) {
454 *dst = *((struct in_addr *) RTA_DATA(attr));
458 *gateway = *((struct in_addr *) RTA_DATA(attr));
462 *index = *((int *) RTA_DATA(attr));
468 static void process_newroute(unsigned char family, unsigned char scope,
469 struct rtmsg *msg, int bytes)
472 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
473 char dststr[16], gatewaystr[16];
476 if (family != AF_INET)
479 extract_route(msg, bytes, &index, &dst, &gateway);
481 inet_ntop(family, &dst, dststr, sizeof(dststr));
482 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
484 __connman_ipconfig_newroute(index, scope, dststr, gatewaystr);
486 if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
489 for (list = rtnl_list; list; list = list->next) {
490 struct connman_rtnl *rtnl = list->data;
492 if (rtnl->newgateway)
493 rtnl->newgateway(index, gatewaystr);
497 static void process_delroute(unsigned char family, unsigned char scope,
498 struct rtmsg *msg, int bytes)
501 struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY };
502 char dststr[16], gatewaystr[16];
505 if (family != AF_INET)
508 extract_route(msg, bytes, &index, &dst, &gateway);
510 inet_ntop(family, &dst, dststr, sizeof(dststr));
511 inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr));
513 __connman_ipconfig_delroute(index, scope, dststr, gatewaystr);
515 if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY)
518 for (list = rtnl_list; list; list = list->next) {
519 struct connman_rtnl *rtnl = list->data;
521 if (rtnl->delgateway)
522 rtnl->delgateway(index, gatewaystr);
526 static inline void print_ether(struct rtattr *attr, const char *name)
528 int len = (int) RTA_PAYLOAD(attr);
530 if (len == ETH_ALEN) {
531 struct ether_addr eth;
532 memcpy(ð, RTA_DATA(attr), ETH_ALEN);
533 print(" attr %s (len %d) %s\n", name, len, ether_ntoa(ð));
535 print(" attr %s (len %d)\n", name, len);
538 static inline void print_inet(struct rtattr *attr, const char *name,
539 unsigned char family)
541 int len = (int) RTA_PAYLOAD(attr);
543 if (family == AF_INET && len == sizeof(struct in_addr)) {
545 addr = *((struct in_addr *) RTA_DATA(attr));
546 print(" attr %s (len %d) %s\n", name, len, inet_ntoa(addr));
548 print(" attr %s (len %d)\n", name, len);
551 static inline void print_string(struct rtattr *attr, const char *name)
553 print(" attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
554 (char *) RTA_DATA(attr));
557 static inline void print_byte(struct rtattr *attr, const char *name)
559 print(" attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
560 *((unsigned char *) RTA_DATA(attr)));
563 static inline void print_integer(struct rtattr *attr, const char *name)
565 print(" attr %s (len %d) %d\n", name, (int) RTA_PAYLOAD(attr),
566 *((int *) RTA_DATA(attr)));
569 static inline void print_attr(struct rtattr *attr, const char *name)
571 int len = (int) RTA_PAYLOAD(attr);
574 print(" attr %s (len %d)\n", name, len);
576 print(" attr %d (len %d)\n", attr->rta_type, len);
579 static void rtnl_link(struct nlmsghdr *hdr)
581 struct ifinfomsg *msg;
585 msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
586 bytes = IFLA_PAYLOAD(hdr);
588 print("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
590 for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
591 attr = RTA_NEXT(attr, bytes)) {
592 switch (attr->rta_type) {
594 print_ether(attr, "address");
597 print_ether(attr, "broadcast");
600 print_string(attr, "ifname");
603 print_integer(attr, "mtu");
606 print_attr(attr, "link");
609 print_attr(attr, "qdisc");
612 print_attr(attr, "stats");
615 print_attr(attr, "cost");
618 print_attr(attr, "priority");
621 print_attr(attr, "master");
624 print_attr(attr, "wireless");
627 print_attr(attr, "protinfo");
630 print_integer(attr, "txqlen");
633 print_attr(attr, "map");
636 print_attr(attr, "weight");
639 print_byte(attr, "operstate");
642 print_byte(attr, "linkmode");
645 print_attr(attr, NULL);
651 static void rtnl_newlink(struct nlmsghdr *hdr)
653 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
657 process_newlink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
658 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
661 static void rtnl_dellink(struct nlmsghdr *hdr)
663 struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
667 process_dellink(msg->ifi_type, msg->ifi_index, msg->ifi_flags,
668 msg->ifi_change, msg, IFA_PAYLOAD(hdr));
671 static void rtnl_addr(struct nlmsghdr *hdr)
673 struct ifaddrmsg *msg;
677 msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
678 bytes = IFA_PAYLOAD(hdr);
680 print("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
682 for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
683 attr = RTA_NEXT(attr, bytes)) {
684 switch (attr->rta_type) {
686 print_inet(attr, "address", msg->ifa_family);
689 print_inet(attr, "local", msg->ifa_family);
692 print_string(attr, "label");
695 print_inet(attr, "broadcast", msg->ifa_family);
698 print_attr(attr, "anycast");
701 print_attr(attr, "cacheinfo");
704 print_attr(attr, "multicast");
707 print_attr(attr, NULL);
713 static void rtnl_newaddr(struct nlmsghdr *hdr)
715 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
719 process_newaddr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
720 msg, IFA_PAYLOAD(hdr));
723 static void rtnl_deladdr(struct nlmsghdr *hdr)
725 struct ifaddrmsg *msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
729 process_deladdr(msg->ifa_family, msg->ifa_prefixlen, msg->ifa_index,
730 msg, IFA_PAYLOAD(hdr));
733 static void rtnl_route(struct nlmsghdr *hdr)
739 msg = (struct rtmsg *) NLMSG_DATA(hdr);
740 bytes = RTM_PAYLOAD(hdr);
742 print("rtm_family %d rtm_table %d rtm_protocol %d",
743 msg->rtm_family, msg->rtm_table, msg->rtm_protocol);
744 print("rtm_scope %d rtm_type %d rtm_flags 0x%04x",
745 msg->rtm_scope, msg->rtm_type, msg->rtm_flags);
747 for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
748 attr = RTA_NEXT(attr, bytes)) {
749 switch (attr->rta_type) {
751 print_inet(attr, "dst", msg->rtm_family);
754 print_inet(attr, "src", msg->rtm_family);
757 print_string(attr, "iif");
760 print_integer(attr, "oif");
763 print_inet(attr, "gateway", msg->rtm_family);
766 print_attr(attr, "priority");
769 print_inet(attr, "prefsrc", msg->rtm_family);
772 print_attr(attr, "metrics");
775 print_integer(attr, "table");
778 print_attr(attr, NULL);
784 static void rtnl_newroute(struct nlmsghdr *hdr)
786 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
790 if (msg->rtm_table == RT_TABLE_MAIN &&
791 msg->rtm_protocol == RTPROT_BOOT &&
792 msg->rtm_type == RTN_UNICAST)
793 process_newroute(msg->rtm_family, msg->rtm_scope,
794 msg, RTM_PAYLOAD(hdr));
797 static void rtnl_delroute(struct nlmsghdr *hdr)
799 struct rtmsg *msg = (struct rtmsg *) NLMSG_DATA(hdr);
803 if (msg->rtm_table == RT_TABLE_MAIN &&
804 msg->rtm_protocol == RTPROT_BOOT &&
805 msg->rtm_type == RTN_UNICAST)
806 process_delroute(msg->rtm_family, msg->rtm_scope,
807 msg, RTM_PAYLOAD(hdr));
810 static const char *type2string(uint16_t type)
842 static GIOChannel *channel = NULL;
844 struct rtnl_request {
848 #define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
850 static GSList *request_list = NULL;
851 static guint32 request_seq = 0;
853 static struct rtnl_request *find_request(guint32 seq)
857 for (list = request_list; list; list = list->next) {
858 struct rtnl_request *req = list->data;
860 if (req->hdr.nlmsg_seq == seq)
867 static int send_request(struct rtnl_request *req)
869 struct sockaddr_nl addr;
872 DBG("%s len %d type %d flags 0x%04x seq %d",
873 type2string(req->hdr.nlmsg_type),
874 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
875 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
877 sk = g_io_channel_unix_get_fd(channel);
879 memset(&addr, 0, sizeof(addr));
880 addr.nl_family = AF_NETLINK;
882 return sendto(sk, req, req->hdr.nlmsg_len, 0,
883 (struct sockaddr *) &addr, sizeof(addr));
886 static int queue_request(struct rtnl_request *req)
888 request_list = g_slist_append(request_list, req);
890 if (g_slist_length(request_list) > 1)
893 return send_request(req);
896 static int process_response(guint32 seq)
898 struct rtnl_request *req;
902 req = find_request(seq);
904 request_list = g_slist_remove(request_list, req);
908 req = g_slist_nth_data(request_list, 0);
912 return send_request(req);
915 static void rtnl_message(void *buf, size_t len)
917 DBG("buf %p len %zd", buf, len);
920 struct nlmsghdr *hdr = buf;
921 struct nlmsgerr *err;
923 if (!NLMSG_OK(hdr, len))
926 DBG("%s len %d type %d flags 0x%04x seq %d",
927 type2string(hdr->nlmsg_type),
928 hdr->nlmsg_len, hdr->nlmsg_type,
929 hdr->nlmsg_flags, hdr->nlmsg_seq);
931 switch (hdr->nlmsg_type) {
936 process_response(hdr->nlmsg_seq);
939 err = NLMSG_DATA(hdr);
940 DBG("error %d (%s)", -err->error,
941 strerror(-err->error));
963 len -= hdr->nlmsg_len;
964 buf += hdr->nlmsg_len;
968 static gboolean netlink_event(GIOChannel *chan,
969 GIOCondition cond, gpointer data)
971 unsigned char buf[4096];
975 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
978 memset(buf, 0, sizeof(buf));
980 err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
982 if (err == G_IO_ERROR_AGAIN)
987 rtnl_message(buf, len);
992 static int send_getlink(void)
994 struct rtnl_request *req;
998 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1002 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1003 req->hdr.nlmsg_type = RTM_GETLINK;
1004 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1005 req->hdr.nlmsg_pid = 0;
1006 req->hdr.nlmsg_seq = request_seq++;
1007 req->msg.rtgen_family = AF_INET;
1009 return queue_request(req);
1012 static int send_getaddr(void)
1014 struct rtnl_request *req;
1018 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1022 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1023 req->hdr.nlmsg_type = RTM_GETADDR;
1024 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1025 req->hdr.nlmsg_pid = 0;
1026 req->hdr.nlmsg_seq = request_seq++;
1027 req->msg.rtgen_family = AF_INET;
1029 return queue_request(req);
1032 static int send_getroute(void)
1034 struct rtnl_request *req;
1038 req = g_try_malloc0(RTNL_REQUEST_SIZE);
1042 req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
1043 req->hdr.nlmsg_type = RTM_GETROUTE;
1044 req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1045 req->hdr.nlmsg_pid = 0;
1046 req->hdr.nlmsg_seq = request_seq++;
1047 req->msg.rtgen_family = AF_INET;
1049 return queue_request(req);
1052 int __connman_rtnl_init(void)
1054 struct sockaddr_nl addr;
1059 sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
1063 memset(&addr, 0, sizeof(addr));
1064 addr.nl_family = AF_NETLINK;
1065 addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
1067 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1072 channel = g_io_channel_unix_new(sk);
1073 g_io_channel_set_close_on_unref(channel, TRUE);
1075 g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
1076 netlink_event, NULL);
1081 void __connman_rtnl_start(void)
1090 void __connman_rtnl_cleanup(void)
1096 for (list = watch_list; list; list = list->next) {
1097 struct watch_data *watch = list->data;
1099 DBG("removing watch %d", watch->id);
1105 g_slist_free(watch_list);
1108 for (list = request_list; list; list = list->next) {
1109 struct rtnl_request *req = list->data;
1111 DBG("%s len %d type %d flags 0x%04x seq %d",
1112 type2string(req->hdr.nlmsg_type),
1113 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
1114 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
1120 g_slist_free(request_list);
1121 request_list = NULL;
1123 g_io_channel_shutdown(channel, TRUE, NULL);
1124 g_io_channel_unref(channel);