00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 }
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
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
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 }
00592
00593 }
00594
00595 }
00596
00597 # endif // ! QOLYESTER_DAEMON_SYS_LINUX_ROUTINGSOCKET_HXX
00598
00599 #endif // ! QOLYESTER_ENABLE_VIRTUAL