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

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

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