Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

netlink.hxx

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

Generated on Thu Jul 28 21:21:48 2005 for Qolyester daemon by  doxygen 1.4.1