netlink.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003-2006 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018 // Boston, MA  02110-1301, USA.
00019 
00020 #ifndef QOLYESTER_SYS_LINUX_NETLINK_HXX
00021 # define QOLYESTER_SYS_LINUX_NETLINK_HXX 1
00022 
00023 # include <cstring>
00024 # include <asm/types.h>
00025 # include <sys/socket.h>
00026 # include <linux/rtnetlink.h>
00027 # include <linux/pkt_sched.h>
00028 # include <stdexcept>
00029 # include <cerrno>
00030 
00031 # include "netlink.hh"
00032 
00033 namespace olsr {
00034 
00035   namespace sys {
00036 
00037     namespace netlink {
00038 
00039       RequestVisitor::RequestVisitor()
00040         : _buffers(),
00041           _buffer(0),
00042           _length(0)
00043       {}
00044 
00045       RequestVisitor::~RequestVisitor() {
00046         for (buffers_t::iterator i = _buffers.begin();
00047              i != _buffers.end();
00048              ++i)
00049           delete[] (char*) i->iov_base;
00050         if (_buffer != 0)
00051           delete[] _buffer;
00052       }
00053 
00054 # define PREPARE_MESSAGE(Payload, Name)                         \
00055       nlmsghdr* nh;                                             \
00056       Payload * Name ;                                          \
00057       int       len = NLMSG_SPACE(sizeof ( Payload ));          \
00058       char*     r = new char[len];                              \
00059       memset(r, 0, len);                                        \
00060                                                                 \
00061       nh = reinterpret_cast<nlmsghdr*>(r);                      \
00062       Name = reinterpret_cast< Payload *>(NLMSG_DATA(nh));      \
00063                                                                 \
00064       nh->nlmsg_len = NLMSG_LENGTH(sizeof ( Payload ));         \
00065       nh->nlmsg_seq = RequestVisitor::seqnum++;                 \
00066       nh->nlmsg_pid = 0;
00067 
00068 # define PREPARE_MESSAGE_GET(Payload, Name)             \
00069       PREPARE_MESSAGE(Payload, Name);                   \
00070       nh->nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST
00071 
00072 # define PREPARE_MESSAGE_NEW(Payload, Name)             \
00073       PREPARE_MESSAGE(Payload, Name);                   \
00074       nh->nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL |     \
00075                         NLM_F_REQUEST | NLM_F_ACK
00076 
00077 # define PREPARE_MESSAGE_DEL(Payload, Name)             \
00078       PREPARE_MESSAGE(Payload, Name);                   \
00079       nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK
00080 
00081 # define SHIPOUT_MESSAGE                        \
00082       iovec     i = { r, len };                 \
00083       _buffers.push_back(i)
00084 
00085       void
00086       RequestVisitor::visit(const NLGetLink&) {
00087         PREPARE_MESSAGE_GET(ifinfomsg, ii);
00088 
00089         nh->nlmsg_type  = RTM_GETLINK;
00090 
00091         ii->ifi_family  = AF_UNSPEC;
00092 
00093         SHIPOUT_MESSAGE;
00094       }
00095 
00096       void
00097       RequestVisitor::visit(const NLNewAddr& e) {
00098         PREPARE_MESSAGE_NEW(ifaddrmsg, ia);
00099 
00100         nh->nlmsg_type  = RTM_NEWADDR;
00101 
00102         ia->ifa_family    = e.family();
00103         ia->ifa_prefixlen = e.prefixlen();
00104         ia->ifa_flags     = e.flags();
00105         ia->ifa_scope     = e.scope();
00106         ia->ifa_index     = e.index();
00107 
00108         SHIPOUT_MESSAGE;
00109 
00110         for (NLNewAddr::attrs_t::const_iterator i = e.attrs().begin();
00111              i != e.attrs().end(); ++i)
00112           (*i)->accept(*this);
00113       }
00114 
00115       void
00116       RequestVisitor::visit(const NLGetAddr& e) {
00117         PREPARE_MESSAGE_GET(ifaddrmsg, ia);
00118 
00119         nh->nlmsg_type  = RTM_GETADDR;
00120 
00121         ia->ifa_family  = e.family();
00122 
00123         SHIPOUT_MESSAGE;
00124       }
00125 
00126       void
00127       RequestVisitor::visit(const NLDelAddr& e) {
00128         PREPARE_MESSAGE_DEL(ifaddrmsg, ia);
00129 
00130         nh->nlmsg_type  = RTM_DELADDR;
00131 
00132         ia->ifa_family    = e.family();
00133         ia->ifa_prefixlen = e.prefixlen();
00134         ia->ifa_flags     = e.flags();
00135         ia->ifa_scope     = e.scope();
00136         ia->ifa_index     = e.index();
00137 
00138         SHIPOUT_MESSAGE;
00139 
00140         for (NLDelAddr::attrs_t::const_iterator i = e.attrs().begin();
00141              i != e.attrs().end(); ++i)
00142           (*i)->accept(*this);
00143       }
00144 
00145       void
00146       RequestVisitor::visit(const NLGetRoute& e) {
00147         PREPARE_MESSAGE_GET(rtmsg, rt);
00148 
00149         nh->nlmsg_type  = RTM_GETROUTE;
00150 
00151         rt->rtm_family  = e.family();
00152 
00153         SHIPOUT_MESSAGE;
00154       }
00155 
00156       void
00157       RequestVisitor::visit(const NLNewRoute& e) {
00158         PREPARE_MESSAGE_NEW(rtmsg, rt);
00159 
00160         nh->nlmsg_type  = RTM_NEWROUTE;
00161 
00162         rt->rtm_family   = e.family();
00163         rt->rtm_dst_len  = e.dlen();
00164         rt->rtm_src_len  = e.slen();
00165         rt->rtm_tos      = e.tos();
00166         rt->rtm_table    = e.table();
00167         rt->rtm_protocol = e.proto();
00168         rt->rtm_scope    = e.scope();
00169         rt->rtm_type     = e.type();
00170         rt->rtm_flags    = e.flags();
00171 
00172         SHIPOUT_MESSAGE;
00173 
00174         for (NLNewRoute::attrs_t::const_iterator i = e.attrs().begin();
00175              i != e.attrs().end(); ++i)
00176           (*i)->accept(*this);
00177       }
00178 
00179       void
00180       RequestVisitor::visit(const NLDelRoute& e) {
00181         PREPARE_MESSAGE_DEL(rtmsg, rt);
00182 
00183         nh->nlmsg_type  = RTM_DELROUTE;
00184 
00185         rt->rtm_family   = e.family();
00186         rt->rtm_dst_len  = e.dlen();
00187         rt->rtm_src_len  = e.slen();
00188         rt->rtm_tos      = e.tos();
00189         rt->rtm_table    = e.table();
00190         rt->rtm_protocol = e.proto();
00191         rt->rtm_scope    = e.scope();
00192         rt->rtm_type     = e.type();
00193         rt->rtm_flags    = e.flags();
00194 
00195         SHIPOUT_MESSAGE;
00196 
00197         for (NLDelRoute::attrs_t::const_iterator i = e.attrs().begin();
00198              i != e.attrs().end(); ++i)
00199           (*i)->accept(*this);
00200       }
00201 
00202       void
00203       RequestVisitor::visit(const NLAddrAttrAddress& e) {
00204         unsigned        len = RTA_SPACE(e.length());
00205         char*           buffer = new char[len];
00206         memset(buffer, 0, len);
00207 
00208         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00209         a->rta_len  = RTA_LENGTH(e.length());
00210         a->rta_type = IFA_ADDRESS;
00211         memcpy(RTA_DATA(a), e.bytes(), e.length());
00212 
00213         iovec           i = { buffer, len };
00214 
00215         _buffers.push_back(i);
00216 
00217         nlmsghdr*       h =
00218           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00219 
00220         h->nlmsg_len += NLMSG_ALIGN(len);
00221       }
00222 
00223       void
00224       RequestVisitor::visit(const NLAddrAttrLocal& e) {
00225         unsigned        len = RTA_SPACE(e.length());
00226         char*           buffer = new char[len];
00227         memset(buffer, 0, len);
00228 
00229         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00230         a->rta_len  = RTA_LENGTH(e.length());
00231         a->rta_type = IFA_LOCAL;
00232         memcpy(RTA_DATA(a), e.bytes(), e.length());
00233 
00234         iovec           i = { buffer, len };
00235 
00236         _buffers.push_back(i);
00237 
00238         nlmsghdr*       h =
00239           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00240 
00241         h->nlmsg_len += NLMSG_ALIGN(len);
00242       }
00243 
00244 //       void
00245 //       RequestVisitor::visit(const NLAddrAttrLabel& e) {
00246 //      unsigned        len = RTA_SPACE(e.label().length() + 1);
00247 //      char*           buffer = new char[len];
00248 //      memset(buffer, 0, len);
00249 
00250 //      rtattr*         a = (rtattr*) buffer;
00251 //      a->rta_len  = RTA_LENGTH(e.label().length() + 1);
00252 //      a->rta_type = IFA_LABEL;
00253 //      e.label().copy(RTA_DATA(a), e.label().length());
00254 
00255 //      iovec           i = { (void*) buffer, len };
00256 
00257 //      _buffers.push_back(i);
00258 
00259 //      nlmsghdr*       h =
00260 //        reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00261 
00262 //      h->nlmsg_len += NLMSG_ALIGN(len);
00263 //       }
00264 
00265       void
00266       RequestVisitor::visit(const NLAddrAttrBroadcast& e) {
00267         unsigned        len = RTA_SPACE(e.length());
00268         char*           buffer = new char[len];
00269         memset(buffer, 0, len);
00270 
00271         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00272         a->rta_len  = RTA_LENGTH(e.length());
00273         a->rta_type = IFA_BROADCAST;
00274         memcpy(RTA_DATA(a), e.bytes(), e.length());
00275 
00276         iovec           i = { buffer, len };
00277 
00278         _buffers.push_back(i);
00279 
00280         nlmsghdr*       h =
00281           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00282 
00283         h->nlmsg_len += NLMSG_ALIGN(len);
00284       }
00285 
00286       void
00287       RequestVisitor::visit(const NLAddrAttrAnycast& e) {
00288         unsigned        len = RTA_SPACE(e.length());
00289         char*           buffer = new char[len];
00290         memset(buffer, 0, len);
00291 
00292         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00293         a->rta_len  = RTA_LENGTH(e.length());
00294         a->rta_type = IFA_ANYCAST;
00295         memcpy(RTA_DATA(a), e.bytes(), e.length());
00296 
00297         iovec           i = { buffer, len };
00298 
00299         _buffers.push_back(i);
00300 
00301         nlmsghdr*       h =
00302           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00303 
00304         h->nlmsg_len += NLMSG_ALIGN(len);
00305       }
00306 
00307       void
00308       RequestVisitor::visit(const NLRouteAttrDestination& e) {
00309         unsigned        len = RTA_SPACE(e.length());
00310         char*           buffer = new char[len];
00311         memset(buffer, 0, len);
00312 
00313         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00314         a->rta_len  = RTA_LENGTH(e.length());
00315         a->rta_type = RTA_DST;
00316         memcpy(RTA_DATA(a), e.bytes(), e.length());
00317 
00318         iovec           i = { buffer, len };
00319         _buffers.push_back(i);
00320 
00321         nlmsghdr*       h =
00322           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00323 
00324         h->nlmsg_len += NLMSG_ALIGN(len);
00325       }
00326 
00327       void
00328       RequestVisitor::visit(const NLRouteAttrGateway& e) {
00329         unsigned        len = RTA_SPACE(e.length());
00330         char*           buffer = new char[len];
00331         memset(buffer, 0, len);
00332 
00333         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00334         a->rta_len  = RTA_LENGTH(e.length());
00335         a->rta_type = RTA_GATEWAY;
00336         memcpy(RTA_DATA(a), e.bytes(), e.length());
00337 
00338         iovec           i = { buffer, len };
00339         _buffers.push_back(i);
00340 
00341         nlmsghdr*       h =
00342           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00343 
00344         h->nlmsg_len += NLMSG_ALIGN(len);
00345       }
00346 
00347       void
00348       RequestVisitor::visit(const NLRouteAttrOutInterface& e) {
00349         unsigned        len = RTA_SPACE(sizeof (int));
00350         char*           buffer = new char[len];
00351         memset(buffer, 0, len);
00352 
00353         rtattr*         a = reinterpret_cast<rtattr*>(buffer);
00354         a->rta_len  = RTA_LENGTH(sizeof (int));
00355         a->rta_type = RTA_OIF;
00356         *(int*)RTA_DATA(a) = e.index();
00357 
00358         iovec           i = { buffer, len };
00359         _buffers.push_back(i);
00360 
00361         nlmsghdr*       h =
00362           reinterpret_cast<nlmsghdr*>(_buffers.begin()->iov_base);
00363 
00364         h->nlmsg_len += NLMSG_ALIGN(len);
00365       }
00366 
00367       const char*
00368       RequestVisitor::buffer() {
00369         if (_buffer != 0)
00370           return _buffer;
00371 
00372         _length = totalsize();
00373         _buffer = new char[_length];
00374         memset(_buffer, 0, _length);
00375 
00376         unsigned index = 0;
00377         for (buffers_t::const_iterator i = _buffers.begin();
00378              i != _buffers.end(); ++i) {
00379           memcpy(_buffer + index, i->iov_base, i->iov_len);
00380           index += NLMSG_ALIGN(i->iov_len);
00381         }
00382         return _buffer;
00383       }
00384 
00385       const unsigned
00386       RequestVisitor::length() {
00387         if (_buffer == 0)
00388           buffer();
00389         return _length;
00390       }
00391 
00392       unsigned
00393       RequestVisitor::totalsize() const {
00394         unsigned size = 0;
00395         for (buffers_t::const_iterator i = _buffers.begin();
00396              i != _buffers.end(); ++i)
00397           size += NLMSG_ALIGN(i->iov_len);
00398         return size;
00399       }
00400 
00401       unsigned RequestVisitor::seqnum = time(NULL);
00402 
00403       NLSocket::NLSocket()
00404         : _fd(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) {
00405         if (_fd < 0)
00406           throw std::runtime_error(strerror(errno));
00407         sockaddr_t      snl;
00408 
00409         snl.nl_family = AF_NETLINK;
00410         snl.nl_pad    = 0;
00411         snl.nl_pid    = 0;
00412         snl.nl_groups = 0;
00413 
00414         if (bind(_fd, (sockaddr*) &snl, sizeof snl) < 0)
00415           throw std::runtime_error(strerror(errno));
00416       }
00417 
00418       NLSocket::~NLSocket() {
00419         close(_fd);
00420       }
00421 
00422       void
00423       NLSocket::send(const NLMessage& m) {
00424         RequestVisitor  r;
00425 
00426         m.accept(r);
00427 
00428 
00429 
00430         int ret = ::send(_fd, r.buffer(), r.length(), 0);
00431 
00432         if (ret < 0 /* || (unsigned) ret != r.length()*/)
00433           throw std::runtime_error(strerror(errno));
00434       }
00435 
00436       void
00437       NLSocket::do_receive(char*& buffer, unsigned& length) {
00438         int ret;
00439 
00440         do {
00441           if (buffer != 0)
00442             delete[] buffer;
00443 
00444           length *= 2;
00445           buffer = new char[length];
00446 
00447           ret = recv(_fd, buffer, length, MSG_PEEK);
00448 
00449           if (ret < 0)
00450             throw std::runtime_error(strerror(errno));
00451 
00452         } while ((unsigned) ret == length);
00453 
00454         ret = recv(_fd, buffer, length, 0);
00455 
00456         if (ret < 0)
00457           throw std::runtime_error(strerror(errno));
00458 
00459         assert((unsigned) ret < length);
00460 
00461         length = ret;
00462       }
00463 
00464       std::list<NLMessage*>
00465       NLSocket::receive() {
00466         char*                   buffer = 0;
00467         unsigned                length = 2048;
00468         unsigned                size = 0;
00469         bool                    done = true;
00470         std::list<NLMessage*>   output;
00471 
00472         nlmsghdr*       nh = 0;
00473 
00474         try {
00475           do {
00476 
00477             try {
00478               do_receive(buffer, length);
00479             } catch (std::exception& e) {
00480               if (buffer != 0) {
00481                 delete[] buffer;
00482                 buffer = 0;
00483               }
00484               throw;
00485             }
00486 
00487             size = length;
00488 
00489             for (nh = (nlmsghdr*) buffer;
00490                  size > 0;
00491                  nh = NLMSG_NEXT(nh, size)) {
00492 
00493               if (!NLMSG_OK(nh, size))
00494                 throw std::runtime_error("Netlink message truncated");
00495 
00496               if (nh->nlmsg_flags & NLM_F_MULTI)
00497                 done = false;
00498 
00499               switch (nh->nlmsg_type) {
00500               case NLMSG_ERROR: {
00501                 nlmsgerr*               me = (nlmsgerr*) NLMSG_DATA(nh);
00502                 if (me->error == 0)
00503                   output.push_back(new NLAck);
00504                 else
00505                   output.push_back(new NLError(-me->error));
00506               }
00507                 break;
00508               case NLMSG_DONE:
00509                 done = true;
00510                 break;
00511               case RTM_NEWLINK: {
00512                 // FIXME: The following line is a dirty hack to
00513                 // workaround a kernel bug fixed in 2.6.13-rc1.  This
00514                 // should go away as soon as possible.
00515                 done = false;
00516 
00517                 ifinfomsg*      ih = (ifinfomsg*) NLMSG_DATA(nh);
00518                 unsigned        size = IFLA_PAYLOAD(nh);
00519 
00520                 NLNewLink*      m = new NLNewLink(ih->ifi_family,
00521                                                   ih->ifi_type,
00522                                                   ih->ifi_index,
00523                                                   ih->ifi_flags);
00524 
00525                 for (rtattr* rt = IFLA_RTA(ih);
00526                      size > 0;
00527                      rt = RTA_NEXT(rt, size)) {
00528 
00529                   if (!RTA_OK(rt, size)) {
00530                     delete m;
00531                     throw std::runtime_error("RTA truncated");
00532                   }
00533 
00534                   switch (rt->rta_type) {
00535                   case IFLA_IFNAME:
00536                     m->add_attr(new NLLinkAttrName((char*) RTA_DATA(rt)));
00537                     break;
00538                   case IFLA_MTU:
00539                     m->add_attr(new NLLinkAttrMTU(*(unsigned*)RTA_DATA(rt)));
00540                     break;
00541                   }
00542                 }
00543 
00544                 output.push_back(m);
00545               }
00546                 break;
00547 
00548               case RTM_NEWADDR: {
00549                 // FIXME: The following line is a dirty hack to
00550                 // workaround a kernel bug fixed in 2.6.13-rc1.  This
00551                 // should go away as soon as possible.
00552                 done = false;
00553 
00554                 ifaddrmsg*      ia = (ifaddrmsg*) NLMSG_DATA(nh);
00555                 unsigned        size = IFA_PAYLOAD(nh);
00556 
00557                 NLNewAddr*      m = new NLNewAddr(ia->ifa_family,
00558                                                   ia->ifa_prefixlen,
00559                                                   ia->ifa_flags,
00560                                                   ia->ifa_scope,
00561                                                   ia->ifa_index);
00562 
00563                 for (rtattr* rt = IFA_RTA(ia);
00564                      size > 0;
00565                      rt = RTA_NEXT(rt, size)) {
00566                   if (!RTA_OK(rt, size)) {
00567                     delete m;
00568                     throw std::runtime_error("RTA truncated");
00569                   }
00570 
00571                   switch (rt->rta_type) {
00572                   case IFA_ADDRESS:
00573                     m->add_attr(new NLAddrAttrAddress((unsigned char*)
00574                                                       RTA_DATA(rt),
00575                                                       RTA_PAYLOAD(rt)));
00576                     break;
00577                   case IFA_LOCAL:
00578                     m->add_attr(new NLAddrAttrLocal((unsigned char*)
00579                                                     RTA_DATA(rt),
00580                                                     RTA_PAYLOAD(rt)));
00581                     break;
00582                   case IFA_LABEL:
00583                     m->add_attr(new NLAddrAttrLabel((char*) RTA_DATA(rt)));
00584                     break;
00585                   case IFA_BROADCAST:
00586                     m->add_attr(new NLAddrAttrBroadcast((unsigned char*)
00587                                                         RTA_DATA(rt),
00588                                                         RTA_PAYLOAD(rt)));
00589                     break;
00590                   case IFA_ANYCAST:
00591                     m->add_attr(new NLAddrAttrAnycast((unsigned char*)
00592                                                       RTA_DATA(rt),
00593                                                       RTA_PAYLOAD(rt)));
00594                     break;
00595                   }
00596                 }
00597                 output.push_back(m);
00598               }
00599                 break;
00600               case RTM_NEWROUTE: {
00601                 // FIXME: The following line is a dirty hack to
00602                 // workaround a kernel bug fixed in 2.6.13-rc1.  This
00603                 // should go away as soon as possible.
00604                 done = false;
00605 
00606                 rtmsg*          rt = (rtmsg*) NLMSG_DATA(nh);
00607                 unsigned        size = RTM_PAYLOAD(nh);
00608 
00609                 NLNewRoute*     m = new NLNewRoute(rt->rtm_family,
00610                                                    rt->rtm_dst_len,
00611                                                    rt->rtm_src_len,
00612                                                    rt->rtm_tos,
00613                                                    rt->rtm_table,
00614                                                    rt->rtm_protocol,
00615                                                    rt->rtm_scope,
00616                                                    rt->rtm_type,
00617                                                    rt->rtm_flags);
00618 
00619                 for (rtattr* ra = RTM_RTA(rt); size > 0;
00620                      ra = RTA_NEXT(ra, size)) {
00621                   if (!RTA_OK(ra, size)) {
00622                     delete m;
00623                     throw std::runtime_error("RTA truncated");
00624                   }
00625 
00626                   switch (ra->rta_type) {
00627                   case RTA_DST:
00628                     m->add_attr(new NLRouteAttrDestination((unsigned char*)
00629                                                            RTA_DATA(ra),
00630                                                            RTA_PAYLOAD(ra)));
00631                     break;
00632                   case RTA_GATEWAY:
00633                     m->add_attr(new NLRouteAttrGateway((unsigned char*)
00634                                                        RTA_DATA(ra),
00635                                                        RTA_PAYLOAD(ra)));
00636                     break;
00637                   case RTA_OIF:
00638                     m->add_attr(new NLRouteAttrOutInterface(*(int*)
00639                                                             RTA_DATA(ra)));
00640                     break;
00641                   }
00642                 }
00643 
00644                 output.push_back(m);
00645               }
00646                 break;
00647               }
00648 
00649             }
00650 
00651           } while (!done);
00652 
00653         } catch (std::exception& e) {
00654           if (buffer != 0)
00655             delete[] buffer;
00656           for (std::list<NLMessage*>::iterator i = output.begin();
00657                i != output.end(); ++i)
00658             delete *i;
00659           throw;
00660         }
00661 
00662         if (buffer != 0)
00663           delete[] buffer;
00664 
00665         return output;
00666       }
00667 
00668     } // namespace netlink
00669 
00670   } // namespace sys
00671 
00672 } // namespace olsr
00673 
00674 #endif // ! QOLYESTER_SYS_LINUX_NETLINK_HXX

Generated on Mon Sep 10 17:02:12 2007 for Qolyester daemon by  doxygen 1.5.1