Remove obsolete file.
[connman] / src / rtnl.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <string.h>
28 #include <sys/socket.h>
29 #include <arpa/inet.h>
30
31 #include <linux/if.h>
32 #include <linux/netlink.h>
33 #include <linux/rtnetlink.h>
34
35 #include <glib.h>
36
37 #include "connman.h"
38
39 struct watch_data {
40         unsigned int id;
41         int index;
42         connman_rtnl_link_cb_t newlink;
43         void *user_data;
44 };
45
46 static GSList *watch_list = NULL;
47 static unsigned int watch_id = 0;
48
49 /**
50  * connman_rtnl_add_newlink_watch:
51  * @index: network device index
52  * @callback: callback function
53  * @user_data: callback data;
54  *
55  * Add a new RTNL watch for newlink events
56  *
57  * Returns: %0 on failure and a unique id on success
58  */
59 unsigned int connman_rtnl_add_newlink_watch(int index,
60                         connman_rtnl_link_cb_t callback, void *user_data)
61 {
62         struct watch_data *watch;
63
64         watch = g_try_new0(struct watch_data, 1);
65         if (watch == NULL)
66                 return 0;
67
68         watch->id = ++watch_id;
69         watch->index = index;
70
71         watch->newlink = callback;
72         watch->user_data = user_data;
73
74         watch_list = g_slist_prepend(watch_list, watch);
75
76         DBG("id %d", watch->id);
77
78         return watch->id;
79 }
80
81 /**
82  * connman_rtnl_remove_watch:
83  * @id: watch identifier
84  *
85  * Remove the RTNL watch for the identifier
86  */
87 void connman_rtnl_remove_watch(unsigned int id)
88 {
89         GSList *list;
90
91         DBG("id %d", id);
92
93         if (id == 0)
94                 return;
95
96         for (list = watch_list; list; list = list->next) {
97                 struct watch_data *watch = list->data;
98
99                 if (watch->id  == id) {
100                         watch_list = g_slist_remove(watch_list, watch);
101                         g_free(watch);
102                         break;
103                 }
104         }
105 }
106
107 static GSList *rtnl_list = NULL;
108
109 static gint compare_priority(gconstpointer a, gconstpointer b)
110 {
111         const struct connman_rtnl *rtnl1 = a;
112         const struct connman_rtnl *rtnl2 = b;
113
114         return rtnl2->priority - rtnl1->priority;
115 }
116
117 /**
118  * connman_rtnl_register:
119  * @rtnl: RTNL module
120  *
121  * Register a new RTNL module
122  *
123  * Returns: %0 on success
124  */
125 int connman_rtnl_register(struct connman_rtnl *rtnl)
126 {
127         DBG("rtnl %p name %s", rtnl, rtnl->name);
128
129         rtnl_list = g_slist_insert_sorted(rtnl_list, rtnl,
130                                                         compare_priority);
131
132         return 0;
133 }
134
135 /**
136  * connman_rtnl_unregister:
137  * @rtnl: RTNL module
138  *
139  * Remove a previously registered RTNL module
140  */
141 void connman_rtnl_unregister(struct connman_rtnl *rtnl)
142 {
143         DBG("rtnl %p name %s", rtnl, rtnl->name);
144
145         rtnl_list = g_slist_remove(rtnl_list, rtnl);
146 }
147
148 static void process_newlink(unsigned short type, int index,
149                                         unsigned flags, unsigned change)
150 {
151         GSList *list;
152
153         for (list = rtnl_list; list; list = list->next) {
154                 struct connman_rtnl *rtnl = list->data;
155
156                 if (rtnl->newlink)
157                         rtnl->newlink(type, index, flags, change);
158         }
159
160         for (list = watch_list; list; list = list->next) {
161                 struct watch_data *watch = list->data;
162
163                 if (watch->index != index)
164                         continue;
165
166                 if (watch->newlink)
167                         watch->newlink(flags, change, watch->user_data);
168         }
169 }
170
171 static void process_dellink(unsigned short type, int index,
172                                         unsigned flags, unsigned change)
173 {
174         GSList *list;
175
176         for (list = rtnl_list; list; list = list->next) {
177                 struct connman_rtnl *rtnl = list->data;
178
179                 if (rtnl->dellink)
180                         rtnl->dellink(type, index, flags, change);
181         }
182 }
183
184 static char *extract_gateway(struct rtmsg *msg, int bytes, int *index)
185 {
186         char *gateway = NULL;
187         struct in_addr addr;
188         struct rtattr *attr;
189
190         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
191                                         attr = RTA_NEXT(attr, bytes)) {
192                 switch (attr->rta_type) {
193                 case RTA_GATEWAY:
194                         addr = *((struct in_addr *) RTA_DATA(attr));
195                         g_free(gateway);
196                         gateway = g_strdup(inet_ntoa(addr));
197                         break;
198                 case RTA_OIF:
199                         *index = *((int *) RTA_DATA(attr));
200                         break;
201                 }
202         }
203
204         return gateway;
205 }
206
207 static void process_newgateway(struct rtmsg *msg, int bytes)
208 {
209         int index = -1;
210         char *gateway;
211         GSList *list;
212
213         gateway = extract_gateway(msg, bytes, &index);
214         if (gateway == NULL || index < 0)
215                 return;
216
217         for (list = rtnl_list; list; list = list->next) {
218                 struct connman_rtnl *rtnl = list->data;
219
220                 if (rtnl->newgateway)
221                         rtnl->newgateway(index, gateway);
222         }
223
224         g_free(gateway);
225 }
226
227 static void process_delgateway(struct rtmsg *msg, int bytes)
228 {
229         int index = -1;
230         char *gateway;
231         GSList *list;
232
233         gateway = extract_gateway(msg, bytes, &index);
234         if (gateway == NULL || index < 0)
235                 return;
236
237         for (list = rtnl_list; list; list = list->next) {
238                 struct connman_rtnl *rtnl = list->data;
239
240                 if (rtnl->delgateway)
241                         rtnl->delgateway(index, gateway);
242         }
243
244         g_free(gateway);
245 }
246
247 static inline void print_inet(struct rtattr *attr, const char *name, int family)
248 {
249         if (family == AF_INET) {
250                 struct in_addr addr;
251                 addr = *((struct in_addr *) RTA_DATA(attr));
252                 DBG("  attr %s (len %d) %s\n", name,
253                                 (int) RTA_PAYLOAD(attr), inet_ntoa(addr));
254         } else
255                 DBG("  attr %s (len %d)\n", name, (int) RTA_PAYLOAD(attr));
256 }
257
258 static inline void print_char(struct rtattr *attr, const char *name)
259 {
260         DBG("  attr %s (len %d) %s\n", name, (int) RTA_PAYLOAD(attr),
261                                                 (char *) RTA_DATA(attr));
262 }
263
264 static inline void print_byte(struct rtattr *attr, const char *name)
265 {
266         DBG("  attr %s (len %d) 0x%02x\n", name, (int) RTA_PAYLOAD(attr),
267                                         *((unsigned char *) RTA_DATA(attr)));
268 }
269
270 static inline void print_attr(struct rtattr *attr, const char *name)
271 {
272         if (name)
273                 DBG("  attr %s (len %d)\n", name, (int) RTA_PAYLOAD(attr));
274         else
275                 DBG("  attr %d (len %d)\n",
276                                 attr->rta_type, (int) RTA_PAYLOAD(attr));
277 }
278
279 static void rtnl_link(struct nlmsghdr *hdr)
280 {
281 #if 0
282         struct ifinfomsg *msg;
283         struct rtattr *attr;
284         int bytes;
285
286         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
287         bytes = IFLA_PAYLOAD(hdr);
288
289         DBG("ifi_index %d ifi_flags 0x%04x", msg->ifi_index, msg->ifi_flags);
290
291         for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
292                                         attr = RTA_NEXT(attr, bytes)) {
293                 switch (attr->rta_type) {
294                 case IFLA_ADDRESS:
295                         print_attr(attr, "address");
296                         break;
297                 case IFLA_BROADCAST:
298                         print_attr(attr, "broadcast");
299                         break;
300                 case IFLA_IFNAME:
301                         print_char(attr, "ifname");
302                         break;
303                 case IFLA_MTU:
304                         print_attr(attr, "mtu");
305                         break;
306                 case IFLA_LINK:
307                         print_attr(attr, "link");
308                         break;
309                 case IFLA_QDISC:
310                         print_attr(attr, "qdisc");
311                         break;
312                 case IFLA_STATS:
313                         print_attr(attr, "stats");
314                         break;
315                 case IFLA_COST:
316                         print_attr(attr, "cost");
317                         break;
318                 case IFLA_PRIORITY:
319                         print_attr(attr, "priority");
320                         break;
321                 case IFLA_MASTER:
322                         print_attr(attr, "master");
323                         break;
324                 case IFLA_WIRELESS:
325                         print_attr(attr, "wireless");
326                         break;
327                 case IFLA_PROTINFO:
328                         print_attr(attr, "protinfo");
329                         break;
330                 case IFLA_TXQLEN:
331                         print_attr(attr, "txqlen");
332                         break;
333                 case IFLA_MAP:
334                         print_attr(attr, "map");
335                         break;
336                 case IFLA_WEIGHT:
337                         print_attr(attr, "weight");
338                         break;
339                 case IFLA_OPERSTATE:
340                         print_byte(attr, "operstate");
341                         break;
342                 case IFLA_LINKMODE:
343                         print_byte(attr, "linkmode");
344                         break;
345                 default:
346                         print_attr(attr, NULL);
347                         break;
348                 }
349         }
350 #endif
351 }
352
353 static void rtnl_newlink(struct nlmsghdr *hdr)
354 {
355         struct ifinfomsg *msg;
356
357         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
358
359         DBG("ifi_type %d ifi_index %d ifi_flags 0x%04x ifi_change 0x%04x",
360                                         msg->ifi_type, msg->ifi_index,
361                                         msg->ifi_flags, msg->ifi_change);
362
363         process_newlink(msg->ifi_type, msg->ifi_index,
364                                         msg->ifi_flags, msg->ifi_change);
365
366         rtnl_link(hdr);
367 }
368
369 static void rtnl_dellink(struct nlmsghdr *hdr)
370 {
371         struct ifinfomsg *msg;
372
373         msg = (struct ifinfomsg *) NLMSG_DATA(hdr);
374
375         DBG("ifi_type %d ifi_index %d ifi_flags 0x%04x ifi_change 0x%04x",
376                                         msg->ifi_type, msg->ifi_index,
377                                         msg->ifi_flags, msg->ifi_change);
378
379         process_dellink(msg->ifi_type, msg->ifi_index,
380                                         msg->ifi_flags, msg->ifi_change);
381
382         rtnl_link(hdr);
383 }
384
385 static void rtnl_addr(struct nlmsghdr *hdr)
386 {
387         struct ifaddrmsg *msg;
388         struct rtattr *attr;
389         int bytes;
390
391         msg = (struct ifaddrmsg *) NLMSG_DATA(hdr);
392         bytes = IFA_PAYLOAD(hdr);
393
394         DBG("ifa_family %d ifa_index %d", msg->ifa_family, msg->ifa_index);
395
396         for (attr = IFA_RTA(msg); RTA_OK(attr, bytes);
397                                         attr = RTA_NEXT(attr, bytes)) {
398                 switch (attr->rta_type) {
399                 case IFA_ADDRESS:
400                         print_inet(attr, "address", msg->ifa_family);
401                         break;
402                 case IFA_LOCAL:
403                         print_inet(attr, "local", msg->ifa_family);
404                         break;
405                 case IFA_LABEL:
406                         print_char(attr, "label");
407                         break;
408                 case IFA_BROADCAST:
409                         print_inet(attr, "broadcast", msg->ifa_family);
410                         break;
411                 case IFA_ANYCAST:
412                         print_attr(attr, "anycast");
413                         break;
414                 case IFA_CACHEINFO:
415                         print_attr(attr, "cacheinfo");
416                         break;
417                 case IFA_MULTICAST:
418                         print_attr(attr, "multicast");
419                         break;
420                 default:
421                         print_attr(attr, NULL);
422                         break;
423                 }
424         }
425 }
426
427 static void rtnl_route(struct nlmsghdr *hdr)
428 {
429 #if 0
430         struct rtmsg *msg;
431         struct rtattr *attr;
432         int bytes;
433
434         msg = (struct rtmsg *) NLMSG_DATA(hdr);
435         bytes = RTM_PAYLOAD(hdr);
436
437         DBG("rtm_family %d rtm_flags 0x%04x", msg->rtm_family, msg->rtm_flags);
438
439         for (attr = RTM_RTA(msg); RTA_OK(attr, bytes);
440                                         attr = RTA_NEXT(attr, bytes)) {
441                 switch (attr->rta_type) {
442                 case RTA_DST:
443                         print_inet(attr, "dst", msg->rtm_family);
444                         break;
445                 case RTA_SRC:
446                         print_inet(attr, "src", msg->rtm_family);
447                         break;
448                 case RTA_IIF:
449                         print_char(attr, "iif");
450                         break;
451                 case RTA_OIF:
452                         print_attr(attr, "oif");
453                         break;
454                 case RTA_GATEWAY:
455                         print_inet(attr, "gateway", msg->rtm_family);
456                         break;
457                 case RTA_PRIORITY:
458                         print_attr(attr, "priority");
459                         break;
460                 case RTA_PREFSRC:
461                         print_inet(attr, "prefsrc", msg->rtm_family);
462                         break;
463                 case RTA_METRICS:
464                         print_attr(attr, "metrics");
465                         break;
466                 case RTA_TABLE:
467                         print_attr(attr, "table");
468                         break;
469                 default:
470                         print_attr(attr, NULL);
471                         break;
472                 }
473         }
474 #endif
475 }
476
477 static void rtnl_newroute(struct nlmsghdr *hdr)
478 {
479         struct rtmsg *msg;
480
481         msg = (struct rtmsg *) NLMSG_DATA(hdr);
482
483         if (msg->rtm_type == RTN_UNICAST && msg->rtm_table == RT_TABLE_MAIN &&
484                                         msg->rtm_scope == RT_SCOPE_UNIVERSE) {
485                 DBG("rtm_table %d rtm_scope %d rtm_type %d rtm_flags 0x%04x",
486                                         msg->rtm_table, msg->rtm_scope,
487                                         msg->rtm_type, msg->rtm_flags);
488                 process_newgateway(msg, RTM_PAYLOAD(hdr));
489         }
490
491         rtnl_route(hdr);
492 }
493
494 static void rtnl_delroute(struct nlmsghdr *hdr)
495 {
496         struct rtmsg *msg;
497
498         msg = (struct rtmsg *) NLMSG_DATA(hdr);
499
500         if (msg->rtm_type == RTN_UNICAST && msg->rtm_table == RT_TABLE_MAIN &&
501                                         msg->rtm_scope == RT_SCOPE_UNIVERSE) {
502                 DBG("rtm_table %d rtm_scope %d rtm_type %d rtm_flags 0x%04x",
503                                         msg->rtm_table, msg->rtm_scope,
504                                         msg->rtm_type, msg->rtm_flags);
505                 process_delgateway(msg, RTM_PAYLOAD(hdr));
506         }
507
508         rtnl_route(hdr);
509 }
510
511 static const char *type2string(uint16_t type)
512 {
513         switch (type) {
514         case NLMSG_NOOP:
515                 return "NOOP";
516         case NLMSG_ERROR:
517                 return "ERROR";
518         case NLMSG_DONE:
519                 return "DONE";
520         case NLMSG_OVERRUN:
521                 return "OVERRUN";
522         case RTM_GETLINK:
523                 return "GETLINK";
524         case RTM_NEWLINK:
525                 return "NEWLINK";
526         case RTM_DELLINK:
527                 return "DELLINK";
528         case RTM_NEWADDR:
529                 return "NEWADDR";
530         case RTM_DELADDR:
531                 return "DELADDR";
532         case RTM_GETROUTE:
533                 return "GETROUTE";
534         case RTM_NEWROUTE:
535                 return "NEWROUTE";
536         case RTM_DELROUTE:
537                 return "DELROUTE";
538         default:
539                 return "UNKNOWN";
540         }
541 }
542
543 static GIOChannel *channel = NULL;
544
545 struct rtnl_request {
546         struct nlmsghdr hdr;
547         struct rtgenmsg msg;
548 };
549 #define RTNL_REQUEST_SIZE  (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg))
550
551 static GSList *request_list = NULL;
552 static guint32 request_seq = 0;
553
554 static struct rtnl_request *find_request(guint32 seq)
555 {
556         GSList *list;
557
558         for (list = request_list; list; list = list->next) {
559                 struct rtnl_request *req = list->data;
560
561                 if (req->hdr.nlmsg_seq == seq)
562                         return req;
563         }
564
565         return NULL;
566 }
567
568 static int send_request(struct rtnl_request *req)
569 {
570         struct sockaddr_nl addr;
571         int sk;
572
573         DBG("%s len %d type %d flags 0x%04x seq %d",
574                                 type2string(req->hdr.nlmsg_type),
575                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
576                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
577
578         sk = g_io_channel_unix_get_fd(channel);
579
580         memset(&addr, 0, sizeof(addr));
581         addr.nl_family = AF_NETLINK;
582
583         return sendto(sk, req, req->hdr.nlmsg_len, 0,
584                                 (struct sockaddr *) &addr, sizeof(addr));
585 }
586
587 static int queue_request(struct rtnl_request *req)
588 {
589         request_list = g_slist_append(request_list, req);
590
591         if (g_slist_length(request_list) > 1)
592                 return 0;
593
594         return send_request(req);
595 }
596
597 static int process_response(guint32 seq)
598 {
599         struct rtnl_request *req;
600
601         DBG("seq %d", seq);
602
603         req = find_request(seq);
604         if (req != NULL) {
605                 request_list = g_slist_remove(request_list, req);
606                 g_free(req);
607         }
608
609         req = g_slist_nth_data(request_list, 0);
610         if (req == NULL)
611                 return 0;
612
613         return send_request(req);
614 }
615
616 static void rtnl_message(void *buf, size_t len)
617 {
618         DBG("buf %p len %zd", buf, len);
619
620         while (len > 0) {
621                 struct nlmsghdr *hdr = buf;
622                 struct nlmsgerr *err;
623
624                 if (!NLMSG_OK(hdr, len))
625                         break;
626
627                 DBG("%s len %d type %d flags 0x%04x seq %d",
628                                         type2string(hdr->nlmsg_type),
629                                         hdr->nlmsg_len, hdr->nlmsg_type,
630                                         hdr->nlmsg_flags, hdr->nlmsg_seq);
631
632                 switch (hdr->nlmsg_type) {
633                 case NLMSG_NOOP:
634                 case NLMSG_OVERRUN:
635                         return;
636                 case NLMSG_DONE:
637                         process_response(hdr->nlmsg_seq);
638                         return;
639                 case NLMSG_ERROR:
640                         err = NLMSG_DATA(hdr);
641                         DBG("error %d (%s)", -err->error,
642                                                 strerror(-err->error));
643                         return;
644                 case RTM_NEWLINK:
645                         rtnl_newlink(hdr);
646                         break;
647                 case RTM_DELLINK:
648                         rtnl_dellink(hdr);
649                         break;
650                 case RTM_NEWADDR:
651                 case RTM_DELADDR:
652                         rtnl_addr(hdr);
653                         break;
654                 case RTM_NEWROUTE:
655                         rtnl_newroute(hdr);
656                         break;
657                 case RTM_DELROUTE:
658                         rtnl_delroute(hdr);
659                         break;
660                 }
661
662                 len -= hdr->nlmsg_len;
663                 buf += hdr->nlmsg_len;
664         }
665 }
666
667 static gboolean netlink_event(GIOChannel *chan,
668                                 GIOCondition cond, gpointer data)
669 {
670         unsigned char buf[4096];
671         gsize len;
672         GIOError err;
673
674         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
675                 return FALSE;
676
677         memset(buf, 0, sizeof(buf));
678
679         err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
680         if (err) {
681                 if (err == G_IO_ERROR_AGAIN)
682                         return TRUE;
683                 return FALSE;
684         }
685
686         rtnl_message(buf, len);
687
688         return TRUE;
689 }
690
691 int connman_rtnl_send_getlink(void)
692 {
693         struct rtnl_request *req;
694
695         DBG("");
696
697         req = g_try_malloc0(RTNL_REQUEST_SIZE);
698         if (req == NULL)
699                 return -ENOMEM;
700
701         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
702         req->hdr.nlmsg_type = RTM_GETLINK;
703         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
704         req->hdr.nlmsg_pid = 0;
705         req->hdr.nlmsg_seq = request_seq++;
706         req->msg.rtgen_family = AF_INET;
707
708         return queue_request(req);
709 }
710
711 int connman_rtnl_send_getroute(void)
712 {
713         struct rtnl_request *req;
714
715         DBG("");
716
717         req = g_try_malloc0(RTNL_REQUEST_SIZE);
718         if (req == NULL)
719                 return -ENOMEM;
720
721         req->hdr.nlmsg_len = RTNL_REQUEST_SIZE;
722         req->hdr.nlmsg_type = RTM_GETROUTE;
723         req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
724         req->hdr.nlmsg_pid = 0;
725         req->hdr.nlmsg_seq = request_seq++;
726         req->msg.rtgen_family = AF_INET;
727
728         return queue_request(req);
729 }
730
731 int __connman_rtnl_init(void)
732 {
733         struct sockaddr_nl addr;
734         int sk;
735
736         DBG("");
737
738         sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
739         if (sk < 0)
740                 return -1;
741
742         memset(&addr, 0, sizeof(addr));
743         addr.nl_family = AF_NETLINK;
744         addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE;
745         //addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
746         //addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
747
748         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
749                 close(sk);
750                 return -1;
751         }
752
753         channel = g_io_channel_unix_new(sk);
754         g_io_channel_set_close_on_unref(channel, TRUE);
755
756         g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
757                                                         netlink_event, NULL);
758
759         return 0;
760 }
761
762 void __connman_rtnl_cleanup(void)
763 {
764         GSList *list;
765
766         DBG("");
767
768         for (list = watch_list; list; list = list->next) {
769                 struct watch_data *watch = list->data;
770
771                 DBG("removing watch %d", watch->id);
772
773                 g_free(watch);
774                 list->data = NULL;
775         }
776
777         g_slist_free(watch_list);
778         watch_list = NULL;
779
780         for (list = request_list; list; list = list->next) {
781                 struct rtnl_request *req = list->data;
782
783                 DBG("%s len %d type %d flags 0x%04x seq %d",
784                                 type2string(req->hdr.nlmsg_type),
785                                 req->hdr.nlmsg_len, req->hdr.nlmsg_type,
786                                 req->hdr.nlmsg_flags, req->hdr.nlmsg_seq);
787
788                 g_free(req);
789                 list->data = NULL;
790         }
791
792         g_slist_free(request_list);
793         request_list = NULL;
794
795         g_io_channel_shutdown(channel, TRUE, NULL);
796         g_io_channel_unref(channel);
797
798         channel = NULL;
799 }