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
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 }
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
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
00152
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
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
00202
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 }
00582
00583 }
00584
00585 }
00586
00587 # endif // ! QOLYESTER_DAEMON_SYS_LINUX_ROUTINGSOCKET_HXX
00588
00589 #endif // ! QOLYESTER_ENABLE_VIRTUAL