routingsocket.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, Boston, MA  02110-1301, USA.
00018 
00019 #include "config.hh"
00020 
00021 #ifndef QOLYESTER_ENABLE_VIRTUAL
00022 
00023 # ifndef QOLYESTER_DAEMON_SYS_LINUX_ROUTINGSOCKET_HXX
00024 #  define QOLYESTER_DAEMON_SYS_LINUX_ROUTINGSOCKET_HXX 1
00025 
00026 #  include <net/if.h>
00027 #  include <stdexcept>
00028 #  include <sstream>
00029 
00030 #  include "cst/constants.hh"
00031 #  include "sys/realinterfaceinfo.hh"
00032 
00033 #  include "routingsocket.hh"
00034 
00035 namespace olsr {
00036 
00037   namespace sys {
00038 
00039 #  ifdef DEBUG
00040 
00041     namespace netlink {
00042 
00043       RoutingTableVisitor::RoutingTableVisitor(std::ostream& os)
00044         : os_(os),
00045           is_via_(false),
00046           is_index_(false)
00047       {}
00048 
00049       RoutingTableVisitor::~RoutingTableVisitor() {}
00050 
00051       void
00052       RoutingTableVisitor::visit(const NLError& e) {
00053         os_ << "  Error: " << strerror(e.get_errno()) << " ("
00054             << e.get_errno() << ")\n";
00055       }
00056 
00057       void
00058       RoutingTableVisitor::visit(const NLNewRoute& e) {
00059 
00060         for (NLNewRoute::attrs_t::const_iterator i = e.attrs().begin();
00061              i != e.attrs().end(); ++i)
00062           (*i)->accept(*this);
00063 
00064         char    name[IFNAMSIZ];
00065 
00066         os_ << "  " << dst_ << '/' << (unsigned) e.dlen();
00067 
00068         if (is_via_)
00069           os_ << " via " << via_;
00070 
00071         if (is_index_)
00072           os_ << " dev " << if_indextoname(index_, name);
00073 
00074         os_ << " proto ";
00075         switch (e.proto()) {
00076         case RTPROT_UNSPEC:
00077           os_ << "unknown";
00078           break;
00079         case RTPROT_REDIRECT:
00080           os_ << "redirect";
00081           break;
00082         case RTPROT_KERNEL:
00083           os_ << "kernel";
00084           break;
00085         case RTPROT_BOOT:
00086           os_ << "boot";
00087           break;
00088         case RTPROT_STATIC:
00089           os_ << "static";
00090           break;
00091         default:
00092           os_ << (unsigned) e.proto();
00093         }
00094         os_ << " scope ";
00095         switch (e.scope()) {
00096         case RT_SCOPE_UNIVERSE:
00097           os_ << "universe";
00098           break;
00099         case RT_SCOPE_SITE:
00100           os_ << "site";
00101           break;
00102         case RT_SCOPE_LINK:
00103           os_ << "link";
00104           break;
00105         case RT_SCOPE_HOST:
00106           os_ << "host";
00107           break;
00108         case RT_SCOPE_NOWHERE:
00109           os_ << "nowhere";
00110           break;
00111         default:
00112           os_ << (unsigned) e.scope();
00113         }
00114         os_ << " table ";
00115         switch (e.table()) {
00116         case RT_TABLE_UNSPEC:
00117           os_ << "unspec";
00118           break;
00119         case RT_TABLE_DEFAULT:
00120           os_ << "default";
00121           break;
00122         case RT_TABLE_MAIN:
00123           os_ << "main";
00124           break;
00125         case RT_TABLE_LOCAL:
00126           os_ << "local";
00127           break;
00128         default:
00129           os_ << (unsigned) e.table();
00130         }
00131         os_ << '\n';
00132       }
00133 
00134       void
00135       RoutingTableVisitor::visit(const NLRouteAttrDestination& e) {
00136         dst_ = address_t(e.bytes(), e.length());
00137       }
00138 
00139       void
00140       RoutingTableVisitor::visit(const NLRouteAttrGateway& e) {
00141         via_ = address_t(e.bytes(), e.length());
00142         is_via_ = true;
00143       }
00144 
00145       void
00146       RoutingTableVisitor::visit(const NLRouteAttrOutInterface& e) {
00147         index_ = e.index();
00148         is_index_ = true;
00149       }
00150 
00151     } // namespace netlink
00152 
00153 #  endif // !DEBUG
00154 
00155     namespace internal {
00156 
00157       void
00158       RoutingSocket::print_kernel_routes() {
00159 #  ifdef DEBUG
00160         using netlink::NLSocket;
00161         using netlink::NLNewRoute;
00162         using netlink::NLGetRoute;
00163         using netlink::NLRouteAttrDestination;
00164         using netlink::NLAck;
00165         using netlink::NLError;
00166 
00167         // First, get the list of the routing table entries.
00168 
00169         NLGetRoute      m(address_t::family);
00170 
00171         _s.send(m);
00172 
00173         NLSocket::answer_t      resp = _s.receive();
00174 
00175         if (resp.size() == 0)
00176           throw std::runtime_error("print_kernel_routes(): "
00177                                    "response type mismatch");
00178 
00179         debug << up << "Routing table {\n";
00180 
00181         for (NLSocket::answer_t::iterator im = resp.begin();
00182              im != resp.end(); ++im) {
00183 
00184           netlink::RoutingTableVisitor  rtv(debug);
00185 
00186           (*im)->accept(rtv);
00187 
00188         }
00189 
00190         debug << '}' << std::endl << down;
00191 
00192         for (NLSocket::answer_t::iterator ix = resp.begin();
00193              ix != resp.end(); ++ix)
00194           delete *ix;
00195 #  endif // !DEBUG
00196       }
00197 
00198       void
00199       RoutingSocket::remove_old_routes() {
00200         using netlink::NLSocket;
00201         using netlink::NLNewRoute;
00202         using netlink::NLGetRoute;
00203         using netlink::NLDelRoute;
00204         using netlink::NLRouteAttrDestination;
00205         using netlink::NLAck;
00206         using netlink::NLError;
00207 
00208         // First, get the list of the routing table entries.
00209 
00210         NLGetRoute      m(address_t::family);
00211 
00212         _s.send(m);
00213 
00214         NLSocket::answer_t      resp = _s.receive();
00215 
00216         if (resp.size() == 0)
00217           throw std::runtime_error("remove_old_routes(): "
00218                                    "response type mismatch");
00219 
00220         for (NLSocket::answer_t::iterator im = resp.begin();
00221              im != resp.end(); ++im) {
00222 
00223           NLNewRoute*   nr = dynamic_cast<NLNewRoute*>(*im);
00224 
00225           if (nr == 0) {
00226             std::ostringstream  msg;
00227             msg << "remove_old_routes(): ";
00228             NLError*    e = dynamic_cast<NLError*>(*im);
00229             if (e == 0) {
00230               for (NLSocket::answer_t::iterator ix = resp.begin();
00231                    ix != resp.end(); ++ix)
00232                 delete *ix;
00233               msg << "unknown response";
00234               throw std::runtime_error(msg.str());
00235             }
00236             msg << strerror(e->get_errno());
00237             int err = e->get_errno();
00238             for (NLSocket::answer_t::iterator ix = resp.begin();
00239                  ix != resp.end(); ++ix)
00240               delete *ix;
00241             throw errnoexcept_t(msg.str(), err);
00242           }
00243 
00244           if (nr->proto() != RTPROT_OLSR)
00245             continue;
00246 
00247           NLDelRoute    m2(nr->family(), nr->dlen(), nr->slen(),
00248                            nr->tos(), nr->table(), nr->proto(),
00249                            nr->scope(), nr->type(), nr->flags());
00250 
00251           m2.attrs().swap(nr->attrs());
00252 
00253           _s.send(m2);
00254 
00255           NLSocket::answer_t    resp2 = _s.receive();
00256 
00257           if (resp2.size() != 1) {
00258             for (NLSocket::answer_t::iterator im = resp2.begin();
00259                  im != resp2.end(); ++im)
00260               delete *im;
00261             for (NLSocket::answer_t::iterator ix = resp.begin();
00262                  ix != resp.end(); ++ix)
00263               delete *ix;
00264             throw std::runtime_error("remove_old_routes(): "
00265                                      "response size mismatch");
00266           }
00267           if (dynamic_cast<NLAck*>(*resp2.begin()) == 0) {
00268             std::ostringstream  msg;
00269             msg << "remove_old_routes(): ";
00270             NLError*    e = dynamic_cast<NLError*>(*resp2.begin());
00271             if (e == 0) {
00272               delete *resp2.begin();
00273               for (NLSocket::answer_t::iterator ix = resp.begin();
00274                    ix != resp.end(); ++ix)
00275                 delete *ix;
00276               msg << "unknown response";
00277               throw std::runtime_error(msg.str());
00278             }
00279             msg << strerror(e->get_errno());
00280             int err = e->get_errno();
00281             delete *resp2.begin();
00282             for (NLSocket::answer_t::iterator ix = resp.begin();
00283                  ix != resp.end(); ++ix)
00284               delete *ix;
00285             throw errnoexcept_t(msg.str(), err);
00286           }
00287           delete *resp2.begin();
00288         }
00289 
00290         for (NLSocket::answer_t::iterator ix = resp.begin();
00291              ix != resp.end(); ++ix)
00292           delete *ix;
00293       }
00294 
00295       void
00296       RoutingSocket::add_local_route(const address_t& d, unsigned p,
00297                                      const sys::RealInterfaceInfo& i) {
00298         using netlink::NLSocket;
00299         using netlink::NLNewRoute;
00300         using netlink::NLRouteAttrDestination;
00301         using netlink::NLRouteAttrOutInterface;
00302         using netlink::NLAck;
00303         using netlink::NLError;
00304 
00305         NLNewRoute      m(address_t::family, p, 0, 0, RT_TABLE_MAIN,
00306                           RTPROT_OLSR, RT_SCOPE_LINK, RTN_UNICAST, 0);
00307 
00308         m.add_attr(new NLRouteAttrDestination(d.bytes(), ADDRESS_SIZE));
00309         m.add_attr(new NLRouteAttrOutInterface(i.index()));
00310 
00311         _s.send(m);
00312 
00313         NLSocket::answer_t      resp = _s.receive();
00314 
00315         if (resp.size() != 1) {
00316           for (NLSocket::answer_t::iterator im = resp.begin();
00317                im != resp.end(); ++im)
00318             delete *im;
00319           std::ostringstream    msg;
00320           msg << "add_local_route(): "
00321               << d.to_string() << '/' << p << " dev " << i.name()
00322               << " : response size mismatch";
00323           throw std::runtime_error(msg.str());
00324         }
00325         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00326           std::ostringstream    msg;
00327           msg << "add_local_route(): ";
00328           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00329           if (e == 0) {
00330             delete *resp.begin();
00331             msg << d.to_string() << '/' << p << " dev " << i.name()
00332                 << " : unknown response";
00333             throw std::runtime_error(msg.str());
00334           }
00335           msg << d.to_string() << '/' << p << " dev " << i.name()
00336               << " : " << strerror(e->get_errno());
00337           int   err = e->get_errno();
00338           delete *resp.begin();
00339           throw errnoexcept_t(msg.str(), err);
00340         }
00341         delete *resp.begin();
00342       }
00343 
00344       void
00345       RoutingSocket::add_remote_route(const address_t& d, unsigned p,
00346                                       const address_t& n) {
00347         using netlink::NLSocket;
00348         using netlink::NLNewRoute;
00349         using netlink::NLRouteAttrDestination;
00350         using netlink::NLRouteAttrGateway;
00351         using netlink::NLAck;
00352         using netlink::NLError;
00353 
00354         NLNewRoute      m(address_t::family, p, 0, 0, RT_TABLE_MAIN,
00355                           RTPROT_OLSR, RT_SCOPE_UNIVERSE, RTN_UNICAST, 0);
00356 
00357         m.add_attr(new NLRouteAttrDestination(d.bytes(), ADDRESS_SIZE));
00358         m.add_attr(new NLRouteAttrGateway(n.bytes(), ADDRESS_SIZE));
00359 
00360         _s.send(m);
00361 
00362         NLSocket::answer_t      resp = _s.receive();
00363 
00364         if (resp.size() != 1) {
00365           for (NLSocket::answer_t::iterator im = resp.begin();
00366                im != resp.end(); ++im)
00367             delete *im;
00368           std::ostringstream    msg;
00369           msg << "add_remote_route(): "
00370               << d.to_string() << '/' << p << " via " << n.to_string()
00371               << " : response size mismatch";
00372           throw std::runtime_error(msg.str());
00373         }
00374         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00375           std::ostringstream    msg;
00376           msg << "add_remote_route(): ";
00377           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00378           if (e == 0) {
00379             delete *resp.begin();
00380             msg << d.to_string() << '/' << p << " via " << n.to_string()
00381                 << " : unknown response";
00382             throw std::runtime_error(msg.str());
00383           }
00384           msg << d.to_string() << '/' << p << " via " << n.to_string()
00385               << " : " << strerror(e->get_errno());
00386           int err = e->get_errno();
00387           delete *resp.begin();
00388           throw errnoexcept_t(msg.str(), err);
00389         }
00390         delete *resp.begin();
00391       }
00392 
00393       void
00394       RoutingSocket::remove_local_route(const address_t& d, unsigned p,
00395                                         const sys::RealInterfaceInfo& i) {
00396         using netlink::NLSocket;
00397         using netlink::NLDelRoute;
00398         using netlink::NLRouteAttrDestination;
00399         using netlink::NLRouteAttrOutInterface;
00400         using netlink::NLRouteAttrGateway;
00401         using netlink::NLAck;
00402         using netlink::NLError;
00403 
00404         NLDelRoute      m(address_t::family, p, 0, 0, RT_TABLE_UNSPEC,
00405                           RTPROT_OLSR, RT_SCOPE_LINK, RTN_UNICAST, 0);
00406 
00407         m.add_attr(new NLRouteAttrDestination(d.bytes(), ADDRESS_SIZE));
00408         m.add_attr(new NLRouteAttrOutInterface(i.index()));
00409         m.add_attr(new NLRouteAttrGateway(address_t().bytes(), ADDRESS_SIZE));
00410 
00411         _s.send(m);
00412 
00413         NLSocket::answer_t      resp = _s.receive();
00414 
00415         if (resp.size() != 1) {
00416           for (NLSocket::answer_t::iterator im = resp.begin();
00417                im != resp.end(); ++im)
00418             delete *im;
00419           std::ostringstream    msg;
00420           msg << "remove_local_route(): "
00421               << d.to_string() << '/' << p << " dev " << i.name()
00422               << " : response size mismatch";
00423           throw std::runtime_error(msg.str());
00424         }
00425         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00426           std::ostringstream    msg;
00427           msg << "remove_local_route(): ";
00428           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00429           if (e == 0) {
00430             delete *resp.begin();
00431             msg << d.to_string() << '/' << p << " dev " << i.name()
00432                 << " : unknown response";
00433             throw std::runtime_error(msg.str());
00434           }
00435           msg << d.to_string() << '/' << p << " dev " << i.name()
00436               << " : " << strerror(e->get_errno());
00437           int err = e->get_errno();
00438           delete *resp.begin();
00439           throw errnoexcept_t(msg.str(), err);
00440         }
00441         delete *resp.begin();
00442       }
00443 
00444       void
00445       RoutingSocket::remove_remote_route(const address_t& d, unsigned p,
00446                                          const address_t& n) {
00447         using netlink::NLSocket;
00448         using netlink::NLDelRoute;
00449         using netlink::NLRouteAttrDestination;
00450         using netlink::NLRouteAttrGateway;
00451         using netlink::NLAck;
00452         using netlink::NLError;
00453 
00454         NLDelRoute      m(address_t::family, p, 0, 0, RT_TABLE_UNSPEC,
00455                           RTPROT_OLSR, RT_SCOPE_UNIVERSE, RTN_UNICAST, 0);
00456 
00457         m.add_attr(new NLRouteAttrDestination(d.bytes(), ADDRESS_SIZE));
00458         m.add_attr(new NLRouteAttrGateway(n.bytes(), ADDRESS_SIZE));
00459 
00460         _s.send(m);
00461 
00462         NLSocket::answer_t      resp = _s.receive();
00463 
00464         if (resp.size() != 1) {
00465           for (NLSocket::answer_t::iterator im = resp.begin();
00466                im != resp.end(); ++im)
00467             delete *im;
00468           std::ostringstream    msg;
00469           msg << "remove_remote_route(): "
00470               << d.to_string() << '/' << p << " via " << n.to_string()
00471               << " : response size mismatch";
00472           throw std::runtime_error(msg.str());
00473         }
00474         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00475           std::ostringstream    msg;
00476           msg << "remove_remote_route(): ";
00477           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00478           if (e == 0) {
00479             delete *resp.begin();
00480             msg << d.to_string() << '/' << p << " via " << n.to_string()
00481                 << " : unknown response";
00482             throw std::runtime_error(msg.str());
00483           }
00484           msg << d.to_string() << '/' << p << " via " << n.to_string()
00485               << " : " << strerror(e->get_errno());
00486           int err = e->get_errno();
00487           delete *resp.begin();
00488           throw errnoexcept_t(msg.str(), err);
00489         }
00490         delete *resp.begin();
00491       }
00492 
00493       void
00494       RoutingSocket::add_addr(unsigned i, const InterfaceAddress& a) {
00495         using netlink::NLSocket;
00496         using netlink::NLNewAddr;
00497         using netlink::NLAddrAttrAddress;
00498         using netlink::NLAddrAttrBroadcast;
00499         using netlink::NLAck;
00500         using netlink::NLError;
00501 
00502         NLNewAddr       m(address_t::family, a.prefix(), 0, a.scope(), i);
00503 
00504         m.add_attr(new NLAddrAttrAddress(a.address().bytes(),
00505                                          ADDRESS_SIZE));
00506         m.add_attr(new NLAddrAttrBroadcast(a.broadcast().bytes(),
00507                                            ADDRESS_SIZE));
00508 
00509         _s.send(m);
00510 
00511         NLSocket::answer_t      resp = _s.receive();
00512 
00513         if (resp.size() != 1) {
00514           for (NLSocket::answer_t::iterator im = resp.begin();
00515                im != resp.end(); ++im)
00516             delete *im;
00517           std::ostringstream    msg;
00518           msg << "add_addr(): "
00519               << a.address() << '/' << a.prefix()
00520               << " : response size mismatch";
00521           throw std::runtime_error(msg.str());
00522         }
00523         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00524           std::ostringstream    msg;
00525           msg << "add_addr(): ";
00526           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00527           if (e == 0) {
00528             delete *resp.begin();
00529             msg << a.address() << '/' << a.prefix()
00530                 << " : unknown response";
00531             throw std::runtime_error(msg.str());
00532           }
00533           msg << a.address() << '/' << a.prefix()
00534               << " : " << strerror(e->get_errno());
00535           int err = e->get_errno();
00536           delete *resp.begin();
00537           throw errnoexcept_t(msg.str(), err);
00538         }
00539         delete *resp.begin();
00540       }
00541 
00542       void
00543       RoutingSocket::del_addr(unsigned i, const InterfaceAddress& a) {
00544         using netlink::NLSocket;
00545         using netlink::NLDelAddr;
00546         using netlink::NLAddrAttrAddress;
00547         using netlink::NLAddrAttrBroadcast;
00548         using netlink::NLAck;
00549         using netlink::NLError;
00550 
00551         NLDelAddr       m(address_t::family, a.prefix(), 0, a.scope(), i);
00552 
00553         m.add_attr(new NLAddrAttrAddress(a.address().bytes(),
00554                                          ADDRESS_SIZE));
00555         m.add_attr(new NLAddrAttrBroadcast(a.broadcast().bytes(),
00556                                            ADDRESS_SIZE));
00557 
00558         _s.send(m);
00559 
00560         NLSocket::answer_t      resp = _s.receive();
00561 
00562         if (resp.size() != 1) {
00563           for (NLSocket::answer_t::iterator im = resp.begin();
00564                im != resp.end(); ++im)
00565             delete *im;
00566           std::ostringstream    msg;
00567           msg << "del_addr(): "
00568               << a.address() << '/' << a.prefix()
00569               << " : response size mismatch";
00570           throw std::runtime_error(msg.str());
00571         }
00572         if (dynamic_cast<NLAck*>(*resp.begin()) == 0) {
00573           std::ostringstream    msg;
00574           msg << "del_addr(): ";
00575           NLError*      e = dynamic_cast<NLError*>(*resp.begin());
00576           if (e == 0) {
00577             delete *resp.begin();
00578             msg << a.address() << '/' << a.prefix()
00579                 << " : unknown response";
00580             throw std::runtime_error(msg.str());
00581           }
00582           msg << a.address() << '/' << a.prefix()
00583               << " : " << strerror(e->get_errno());
00584           int err = e->get_errno();
00585           delete *resp.begin();
00586           throw errnoexcept_t(msg.str(), err);
00587         }
00588         delete *resp.begin();
00589       }
00590 
00591     } // namespace internal
00592 
00593   } // namespace sys
00594 
00595 } // namespace olsr
00596 
00597 # endif // ! QOLYESTER_DAEMON_SYS_LINUX_ROUTINGSOCKET_HXX
00598 
00599 #endif // ! QOLYESTER_ENABLE_VIRTUAL

Generated on Mon Sep 4 00:02:16 2006 for Qolyester daemon by  doxygen 1.4.6