router.cpp
1 /* 2 EIBD eib bus access and management daemon 3 Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #include "router.h" 21 22 #include <iostream> 23 #include <math.h> 24 #include <sys/socket.h> 25 #include <typeinfo> 26 27 #include <ev++.h> 28 #ifdef HAVE_SYSTEMD 29 #include <systemd/sd-daemon.h> 30 #endif 31 32 #include "cm_tp1.h" 33 #ifdef HAVE_GROUPCACHE 34 #include "groupcacheclient.h" 35 #endif 36 #include "link.h" 37 #include "lowlevel.h" 38 #include "server.h" 39 #include "systemdserver.h" 40 #include "tcptunserver.h" 41 42 /** global filter adapter, sending end */ 43 class RouterHigh : public Driver 44 { 45 Router* router; 46 public: 47 RouterHigh(Router& r, const RouterLowPtr& rl); 48 virtual ~RouterHigh() = default; 49 50 virtual void recv_L_Data (LDataPtr l); 51 virtual void recv_L_Busmonitor (LBusmonPtr l); 52 53 virtual void send_L_Data (LDataPtr l) 54 { 55 router->send_L_Data(std::move(l)); 56 } 57 58 virtual bool checkAddress (eibaddr_t addr) const override 59 { 60 LinkConnectPtr link = nullptr; 61 return router->checkAddress(addr, link); 62 } 63 64 virtual bool checkGroupAddress (eibaddr_t addr) const override 65 { 66 LinkConnectPtr link = nullptr; 67 return router->checkGroupAddress(addr, link); 68 } 69 70 virtual bool hasAddress (eibaddr_t addr) const override 71 { 72 LinkConnectPtr link = nullptr; 73 return router->hasAddress(addr, link); 74 } 75 76 virtual void addAddress (eibaddr_t addr) override 77 { 78 if (addr != router->addr) 79 ERRORPRINTF (t, E_ERROR | 80, "%s filter: Trying to add address %s", router->main, FormatEIBAddr(addr)); 80 } 81 82 virtual void start() 83 { 84 router->start_(); 85 } 86 87 virtual void stop(bool err) 88 { 89 router->stop_(err); 90 } 91 92 /** prevent dup calls to started() */ 93 bool is_started = false; 94 virtual void started(); 95 virtual void stopped(bool err); 96 97 }; 98 99 /** global filter adapter, receiving end */ 100 class RouterLow : public LinkConnect_ 101 { 102 public: 103 Router* router; 104 RouterLow(Router& r); 105 virtual ~RouterLow() = default; 106 107 virtual void recv_L_Data (LDataPtr l) 108 { 109 router->queue_L_Data (std::move(l)); 110 } 111 virtual void recv_L_Busmonitor (LBusmonPtr l) 112 { 113 router->queue_L_Busmonitor (std::move(l)); 114 } 115 virtual void send_Next (); 116 117 virtual void start() 118 { 119 send->start(); 120 } 121 virtual void stop(bool err) 122 { 123 send->stop(err); 124 } 125 126 virtual void started() 127 { 128 router->started(); 129 } 130 virtual void stopped(bool err) 131 { 132 router->stopped(err); 133 } 134 }; 135 136 static Factory<Server> _servers; 137 static Factory<Driver> _drivers; 138 static Factory<Filter> _filters; 139 140 bool unseen_lister(void *user, const IniSection& section, const std::string& name, const std::string& value); 141 142 /** parses an EIB individual address */ 143 bool 144 Router::readaddr (const std::string& addr, eibaddr_t& parsed) 145 { 146 int a, b, c; 147 if (sscanf (addr.c_str(), "%d.%d.%d", &a, &b, &c) != 3) 148 { 149 ERRORPRINTF (t, E_ERROR | 81, "'%s' is not a device address. Use X.Y.Z format.", addr); 150 return false; 151 } 152 parsed = ((a & 0x0f) << 12) | ((b & 0x0f) << 8) | (c & 0xff); 153 return true; 154 } 155 156 bool 157 Router::readaddrblock (const std::string& addr, eibaddr_t& parsed, int &len) 158 { 159 int a, b, c; 160 if (sscanf (addr.c_str(), "%d.%d.%d:%d", &a, &b, &c, &len) != 4) 161 { 162 ERRORPRINTF (t, E_ERROR | 82, "An address block needs to look like X.Y.Z:N, not '%s'.", addr); 163 return false; 164 } 165 parsed = ((a & 0x0f) << 12) | ((b & 0x0f) << 8) | (c & 0xff); 166 return true; 167 } 168 169 Router::Router (IniData& d, std::string sn) : BaseRouter(d) 170 , servers(_servers.Instance()) 171 , filters(_filters.Instance()) 172 , drivers(_drivers.Instance()) 173 , main(sn) 174 { 175 IniSectionPtr s = ini[main]; 176 t = TracePtr(new Trace(s, s->value("name",""))); 177 servername = s->value("name","knxd"); 178 179 r_low = RouterLowPtr(new RouterLow(*this)); 180 r_high = RouterHighPtr(new RouterHigh(*this, r_low)); 181 r_low->set_driver(std::dynamic_pointer_cast<Driver>(r_high)); 182 183 trigger.set<Router, &Router::trigger_cb>(this); 184 mtrigger.set<Router, &Router::mtrigger_cb>(this); 185 state_trigger.set<Router, &Router::state_trigger_cb>(this); 186 trigger.start(); 187 mtrigger.start(); 188 state_trigger.start(); 189 190 TRACEPRINTF (t, 4, "initialized"); 191 } 192 193 bool 194 Router::setup() 195 { 196 std::string x; 197 IniSectionPtr s = ini[main]; 198 TRACEPRINTF (t, 4, "setting up"); 199 200 force_broadcast = s->value("force-broadcast", false); 201 unknown_ok = s->value("unknown-ok", false); 202 203 x = s->value("addr",""); 204 if (!x.size()) 205 { 206 ERRORPRINTF (t, E_ERROR | 84, "There is no KNX addr= in section '%s'.", main); 207 goto ex; 208 } 209 if (!readaddr(x,addr)) 210 goto ex; 211 212 x = s->value("client-addrs",""); 213 if (x.size()) 214 { 215 if (!readaddrblock(x,client_addrs_start,client_addrs_len)) 216 goto ex; 217 client_addrs_pos = client_addrs_len-1; 218 client_addrs.resize(client_addrs_len); 219 ITER(i,client_addrs) 220 *i = false; 221 } 222 223 #ifdef HAVE_GROUPCACHE 224 { 225 IniSectionPtr gc = s->sub("cache",false); 226 if (gc->name.size() > 0) 227 { 228 if (!CreateGroupCache(*this, gc)) 229 goto ex; 230 } 231 } 232 #endif 233 234 if (!r_low->setup()) 235 return false; 236 237 #ifdef HAVE_SYSTEMD 238 { 239 std::string sd_name_knxd = s->value("systemd",""); 240 std::string sd_name_tun = s->value("systemd_tcptunsrv",""); 241 if (sd_name_knxd.size() > 0 || sd_name_tun.size() > 0) 242 { 243 // IniSectionPtr sd = ini[sd_name]; 244 // set the section's "referenced" bit, for error checking 245 if (sd_name_knxd.size() > 0) 246 (void) ini[sd_name_knxd]; 247 if (sd_name_tun.size() > 0) 248 (void) ini[sd_name_tun]; 249 250 char** fd_names_c = nullptr; 251 int num_fds = sd_listen_fds_with_names(0, &fd_names_c); 252 if( num_fds < 0 ) 253 { 254 ERRORPRINTF (t, E_ERROR | 85, "Error getting fds from systemd."); 255 goto ex; 256 } 257 258 std::vector<std::string> fd_names; 259 if (fd_names_c) 260 { 261 for (char** name = fd_names_c; *name; name++) 262 { 263 fd_names.push_back(*name); 264 free(*name); 265 } 266 free(fd_names_c); 267 } 268 if (fd_names.size() < num_fds) 269 { 270 ERRORPRINTF (t, E_ERROR | 147, "Got too few fds names from systemd."); 271 goto ex; 272 } 273 274 // zero FDs from systemd is not a bug 275 for( int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+num_fds; ++fd ) 276 { 277 std::string name = fd_names[fd - SD_LISTEN_FDS_START]; 278 TRACEPRINTF (t, 4, "Got fd %d with name '%s'", fd, name); 279 std::string sd_name; 280 bool is_tun; 281 if (name == "knxnet") { 282 sd_name = sd_name_tun; 283 is_tun = true; 284 } else { 285 sd_name = sd_name_knxd; 286 is_tun = false; 287 } 288 289 IniSectionPtr sds = ini.add_auto(sd_name); 290 291 (*sds)["use"] = sd_name; 292 if( sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1) <= 0 ) 293 { 294 ERRORPRINTF (t, E_ERROR | 86, "systemd socket %d is not a socket.", fd); 295 goto ex; 296 } 297 298 ServerPtr sdp; 299 if (is_tun) { 300 sdp = ServerPtr(new TcpTunSystemdServer(*this, sds, fd)); 301 } else { 302 sdp = ServerPtr(new SystemdServer(*this, sds, fd)); 303 } 304 if (!sdp->setup()) 305 goto ex; 306 registerLink(sdp); 307 308 using_systemd = true; 309 } 310 } 311 } 312 313 #endif 314 315 x = s->value("connections",""); 316 { 317 size_t pos = 0; 318 size_t comma = 0; 319 while(true) 320 { 321 comma = x.find(',',pos); 322 std::string name = x.substr(pos,comma-pos); 323 if (name.size()) 324 { 325 LinkConnectPtr link = setup_link(name); 326 if (link == nullptr) 327 goto ex; 328 registerLink(link); 329 } 330 if (comma == std::string::npos) 331 break; 332 pos = comma+1; 333 } 334 } 335 336 if (links.size() == 0) 337 { 338 ERRORPRINTF (t, E_ERROR | 87, "No connections in section '%s'.", main); 339 goto ex; 340 } 341 if (links.size() == 1) 342 { 343 ERRORPRINTF (t, E_ERROR | 88, "Only one connection in section '%s'.", main); 344 goto ex; 345 } 346 347 if (ini.list_unseen(&unseen_lister, (void *)this)) 348 goto ex; 349 350 ITER(i,links) 351 ERRORPRINTF (t, E_INFO | 129, "Connected: %s.", i->second->info(2)); 352 353 TRACEPRINTF (t, 4, "setup OK"); 354 return true; 355 ex: 356 TRACEPRINTF (t, 4, "setup BROKEN"); 357 return false; 358 } 359 360 bool 361 unseen_lister(void *user, 362 const IniSection& section, const std::string& name, const std::string& value) 363 { 364 Router *r = (Router *)user; 365 ERRORPRINTF (r->t, (r->unknown_ok ? E_WARNING : E_FATAL) | 104, "Section '%s': unrecognized argument '%s = %s'", 366 section.name, name, value); 367 return !r->unknown_ok; 368 } 369 370 bool 371 Router::do_driver(LinkConnectPtr &link, IniSectionPtr& s, const std::string& drivername, bool quiet) 372 { 373 DriverPtr driver = nullptr; 374 375 link = LinkConnectPtr(new LinkConnect(*this, s, t)); 376 driver = DriverPtr(drivers.create(drivername, link, s)); 377 if (driver == nullptr) 378 { 379 if(!quiet) 380 ERRORPRINTF (t, E_ERROR | 89, "Driver '%s' not found.", drivername); 381 link = nullptr; 382 return false; 383 } 384 link->set_driver(driver); 385 if (!link->setup()) 386 link = nullptr; 387 return true; 388 } 389 390 391 FilterPtr 392 Router::get_filter(const LinkConnectPtr_& link, IniSectionPtr& s, const std::string& filtername) 393 { 394 return FilterPtr(filters.create(filtername, link, s)); 395 } 396 397 bool 398 Router::do_server(ServerPtr &link, IniSectionPtr& s, const std::string& servername, bool quiet) 399 { 400 link = ServerPtr(servers.create(servername, *this, s)); 401 if (link == nullptr) 402 { 403 if(!quiet) 404 ERRORPRINTF (t, E_ERROR | 90, "Server '%s' not found.", servername); 405 return false; 406 } 407 if (!link->setup()) 408 link = nullptr; 409 return true; 410 } 411 412 LinkConnectPtr 413 Router::setup_link(std::string& name) 414 { 415 IniSectionPtr s = ini[name]; 416 std::string servername = s->value("server",""); 417 std::string drivername = s->value("driver",""); 418 LinkConnectPtr link = nullptr; 419 ServerPtr server = nullptr; 420 421 if (servername.size() && do_server(server, s,servername)) 422 return server; 423 if (drivername.size() && do_driver(link, s,drivername)) 424 return link; 425 if (do_server(server, s,s->name, true)) 426 return server; 427 if (do_driver(link, s,s->name, true)) 428 return link; 429 ERRORPRINTF (t, E_ERROR | 91, "Section '%s' has no known server nor driver.", name); 430 return nullptr; 431 } 432 433 void 434 Router::start() 435 { 436 if (want_up) 437 return; 438 want_up = true; 439 440 TRACEPRINTF (t, 4, "trigger going up"); 441 r_low->start(); 442 } 443 444 void 445 Router::start_() 446 { 447 some_running = true; 448 bool seen = true; 449 450 in_link_loop += 1; 451 seq++; 452 while (seen) 453 { 454 seen = false; 455 links_changed = false; 456 ITER(i,links) 457 { 458 auto ii = i->second; 459 if (ii->ignore || ii->transient) 460 continue; 461 if (ii->seq >= seq) 462 continue; 463 seen = true; 464 ii->seq = seq; 465 TRACEPRINTF (ii->t, 3, "Start: %s", ii->info(0)); 466 ii->setState(L_going_up); 467 if (links_changed) 468 break; 469 } 470 } 471 in_link_loop -= 1; 472 TRACEPRINTF (t, 4, "going up triggered"); 473 } 474 475 void 476 Router::send_Next() 477 { 478 if (high_sending) 479 { 480 TRACEPRINTF (t, 6, "sending set"); 481 return; 482 } 483 if (high_send_more) 484 { 485 TRACEPRINTF (t, 6, "send_more set"); 486 return; 487 } 488 ITER(i,links) 489 { 490 auto ii = i->second; 491 if (ii->state != L_up) 492 { 493 TRACEPRINTF (ii->t, 6, "not up"); 494 continue; 495 } 496 if (!ii->send_more) 497 { 498 TRACEPRINTF (ii->t, 6, "still waiting"); 499 return; 500 } 501 TRACEPRINTF (ii->t, 6, "is OK"); 502 } 503 TRACEPRINTF (t, 6, "OK"); 504 high_send_more = true; 505 r_high->send_Next(); 506 } 507 508 void 509 Router::linkStateChanged(const LinkConnectPtr& link) 510 { 511 TRACEPRINTF (link->t, 4, "link state changed: %s", link->stateName()); 512 linkChanges.push(link); 513 state_trigger.send(); 514 } 515 516 void 517 Router::state_trigger_cb (ev::async &, int) 518 { 519 bool oarn = all_running; 520 bool osrn = some_running; 521 522 int n_up = 0; 523 int n_going = 0; 524 int n_down = 0; 525 int n_error = 0; 526 527 TRACEPRINTF (t, 4, "check start"); 528 529 while (!linkChanges.empty()) 530 { 531 LinkConnectPtr l = linkChanges.get(); 532 if (!want_up && l->state >= L_up) 533 l->setState(L_going_down); 534 } 535 536 ITER(i,links) 537 { 538 auto ii = i->second; 539 LConnState lcs = ii->state; 540 541 if (ii->transient) 542 { 543 if (!want_up && lcs >= L_up) 544 { 545 ii->setState(L_going_down); 546 n_going ++; 547 } 548 continue; 549 } 550 551 lcs = ii->state; 552 switch(lcs) 553 { 554 case L_down: 555 TRACEPRINTF (ii->t, 4, "is %s", ii->stateName()); 556 if (!ii->ignore) 557 n_down++; 558 break; 559 case L_error: 560 if (!ii->ignore) 561 { 562 n_down++; 563 n_error++; 564 } 565 break; 566 case L_up: 567 n_up++; 568 break; 569 default: 570 TRACEPRINTF (ii->t, 4, "state is %s", ii->stateName()); 571 n_going++; 572 } 573 } 574 575 if (!n_going && !n_down && n_up) 576 { 577 all_running = true; 578 some_running = true; 579 } 580 else if (!n_going && !n_up) 581 { 582 some_running = false; 583 all_running = false; 584 } 585 else 586 { 587 some_running = true; 588 all_running = false; 589 } 590 591 TRACEPRINTF (t, 4, "check end: want_up %d some %d>%d all %d>%d, going %d up %d down %d", want_up, osrn,some_running, oarn,all_running, n_going,n_up,n_down); 592 if (want_up && n_error) 593 { 594 // Hard report errors 595 ITER(i,links) 596 { 597 auto ii = i->second; 598 LConnState lcs = ii->state; 599 switch(lcs) 600 { 601 case L_error: 602 if (!ii->ignore) 603 ERRORPRINTF (ii->t, E_FATAL | 105, "Link down, terminating"); 604 } 605 } 606 exitcode = 1; 607 stop(true); 608 } 609 610 if (osrn && !some_running) 611 r_high->stopped(n_error > 0); 612 else if (!oarn && all_running) 613 r_high->started(); 614 } 615 616 void 617 Router::stop(bool err) 618 { 619 if (!want_up) 620 return; 621 want_up = false; 622 623 TRACEPRINTF (t, 4, "trigger Going down"); 624 r_low->stop(err); 625 } 626 627 void 628 Router::stop_(bool err) 629 { 630 all_running = false; 631 bool seen = true; 632 633 if (want_up) 634 { 635 // we get here when there's a failure to start the global filter chain 636 stop(err); 637 return; 638 } 639 640 in_link_loop += 1; 641 seq++; 642 while(seen) 643 { 644 links_changed = false; 645 seen = false; 646 ITER(i,links) 647 { 648 auto ii = i->second; 649 if (ii->seq >= seq) 650 continue; // already told it 651 TRACEPRINTF (ii->t, 4, "R Stopping"); 652 seen = true; 653 ii->seq = seq; 654 ii->setState(L_going_down); 655 if (links_changed) 656 break; 657 } 658 } 659 in_link_loop -= 1; 660 } 661 662 663 void 664 Router::started() 665 { 666 low_send_more = true; 667 high_send_more = true; 668 trigger.send(); 669 mtrigger.send(); 670 671 if (all_running && !running_signal) 672 { 673 running_signal = true; 674 TRACEPRINTF (t, 4, "all drivers up"); 675 #ifdef HAVE_SYSTEMD 676 sd_notify(0,"READY=1"); 677 #endif 678 } 679 680 TRACEPRINTF (t, 4, "up"); 681 } 682 683 void 684 Router::stopped(bool err) 685 { 686 TRACEPRINTF (t, 4, "down"); 687 if (want_up) 688 stop(err); 689 else 690 ev_break (EV_A_ EVBREAK_ALL); 691 } 692 693 Router::~Router() 694 { 695 TRACEPRINTF (t, 4, "deleting"); 696 cache = nullptr; 697 trigger.stop(); 698 mtrigger.stop(); 699 state_trigger.stop(); 700 701 R_ITER(i,vbusmonitor) 702 ERRORPRINTF (t, E_WARNING | 55, "VBusmonitor '%s' didn't de-register!", i->cb->name); 703 vbusmonitor.clear(); 704 705 R_ITER(i,busmonitor) 706 ERRORPRINTF (t, E_WARNING | 56, "Busmonitor '%s' didn't de-register!", i->cb->name); 707 busmonitor.clear(); 708 709 // ITER(i,links) 710 // delete i->second; 711 links.clear(); 712 713 TRACEPRINTF (t, 4, "deleted."); 714 } 715 716 void 717 Router::recv_L_Data (LDataPtr l, LinkConnect& link) 718 { 719 LinkConnectPtr l2x = nullptr; 720 721 if (l->address_type == IndividualAddress && l->destination_address == 0) 722 { 723 // Common problem with things that are not true gateways 724 ERRORPRINTF (link.t, E_WARNING | 57, "Message without destination. Use the single-node filter ('-B single')?"); 725 return; 726 } 727 728 // Unassigned source: set to link's, or our, address 729 if (l->source_address == 0) 730 { 731 l->source_address = link.addr; 732 if (l->source_address == 0) 733 l->source_address = addr; 734 } 735 736 if (l->source_address == addr) 737 { 738 // locally generated? 739 if (!link.is_local) 740 { 741 // Nope. Reject. 742 TRACEPRINTF (link.t, 3, "Packet not from us"); 743 return; 744 } 745 } 746 else if (hasAddress (l->source_address, l2x)) 747 { 748 // check if from the correct interface 749 if (&*l2x != &link) 750 { 751 TRACEPRINTF (link.t, 3, "Packet not from %d:%s: %s", l2x->t->seq, l2x->t->name, l->Decode (t)); 752 return; 753 } 754 } 755 else if (client_addrs_len && l->source_address >= client_addrs_start && l->source_address < client_addrs_start+client_addrs_len) 756 { 757 TRACEPRINTF (link.t, 3, "Packet originally from closed local interface"); 758 return; 759 } 760 else if (l->source_address != 0xFFFF) // don't assign the "unprogrammed" address 761 { 762 link.addAddress (l->source_address); 763 } 764 765 l->source = &link; 766 r_high->recv_L_Data(std::move(l)); 767 } 768 769 void 770 Router::recv_L_Busmonitor (LBusmonPtr l) 771 { 772 r_high->recv_L_Busmonitor(std::move(l)); 773 } 774 775 void 776 Router::queue_L_Data (LDataPtr l) 777 { 778 if (some_running || want_up) 779 { 780 buf.emplace (std::move(l)); 781 if (running_signal) 782 trigger.send(); 783 } 784 else 785 TRACEPRINTF (t, 9, "Queue: discard (not running) %s", l->Decode (t)); 786 } 787 788 void 789 Router::queue_L_Busmonitor (LBusmonPtr l) 790 { 791 if (some_running || want_up) 792 { 793 mbuf.push (std::move(l)); 794 if (running_signal) 795 mtrigger.send(); 796 } 797 else 798 TRACEPRINTF (t, 9, "MonQueue: discard (not running) %s", l->Decode (t)); 799 } 800 801 bool 802 Router::deregisterBusmonitor (L_Busmonitor_CallBack * c) 803 { 804 ITER(i, busmonitor) 805 if (i->cb == c) 806 { 807 busmonitor.erase(i); 808 TRACEPRINTF (t, 3, "deregisterBusmonitor"); 809 return true; 810 } 811 TRACEPRINTF (t, 3, "deregisterBusmonitor failed"); 812 return false; 813 } 814 815 bool 816 Router::deregisterVBusmonitor (L_Busmonitor_CallBack * c) 817 { 818 ITER(i,vbusmonitor) 819 if (i->cb == c) 820 { 821 TRACEPRINTF (t, 3, "deregisterVBusmonitor"); 822 vbusmonitor.erase(i); 823 return true; 824 } 825 TRACEPRINTF (t, 3, "deregisterVBusmonitor failed"); 826 return false; 827 } 828 829 bool 830 Router::registerBusmonitor (L_Busmonitor_CallBack * c) 831 { 832 busmonitor.push_back((Busmonitor_Info) 833 { 834 .cb=c 835 }); 836 TRACEPRINTF (t, 3, "registerBusmonitor"); 837 return true; 838 } 839 840 bool 841 Router::registerVBusmonitor (L_Busmonitor_CallBack * c) 842 { 843 vbusmonitor.push_back((Busmonitor_Info) 844 { 845 .cb=c 846 }); 847 TRACEPRINTF (t, 3, "registerVBusmonitor"); 848 return true; 849 } 850 851 bool 852 Router::registerLink(const LinkConnectPtr& link, bool transient) 853 { 854 const std::string& n = link->name(); 855 #if 1 // TODO tracing 856 link->pos = link->t->seq; 857 #else 858 static int pos = 0; 859 if (link->pos == 0) 860 link->pos = ++pos; 861 #endif 862 auto res = links.emplace(std::piecewise_construct, 863 std::forward_as_tuple(link->pos), 864 std::forward_as_tuple(link)); 865 if (! res.second) 866 { 867 ERRORPRINTF (link->t, E_ERROR | 93, "registerLink: %d:%s: already present", link->pos,n); 868 return false; 869 } 870 TRACEPRINTF (link->t, 3, "registerLink: %d:%s", link->pos,n); 871 links_changed = true; 872 if (transient) 873 link->transient = true; 874 if (want_up) 875 { 876 all_running = false; 877 TRACEPRINTF (link->t, 3, "Start: %s", link->info(0)); 878 link->seq = seq; 879 link->setState(L_going_up); 880 } 881 return true; 882 } 883 884 bool 885 Router::unregisterLink(const LinkConnectPtr& link) 886 { 887 const std::string& n = link->name(); 888 auto res = links.find(link->pos); 889 if (res == links.end()) 890 { 891 ERRORPRINTF (link->t, E_ERROR | 94, "unregisterLink: %d:%s: not present", link->pos,n); 892 return false; 893 } 894 links.erase(res); 895 TRACEPRINTF (link->t, 3, "unregisterLink: %s", n); 896 links_changed = true; 897 if (!in_link_loop) 898 state_trigger.send(); 899 return true; 900 } 901 902 bool 903 Router::hasAddress (eibaddr_t addr, LinkConnectPtr& link, bool quiet) const 904 { 905 if (addr == this->addr) 906 { 907 if (!quiet) 908 TRACEPRINTF (t, 8, "default addr %s", FormatEIBAddr (addr)); 909 return true; 910 } 911 912 if (link && link->hasAddress(addr)) 913 { 914 if (!quiet) 915 TRACEPRINTF (t, 8, "own addr %s", FormatEIBAddr (addr)); 916 return false; 917 } 918 919 C_ITER(i, links) 920 { 921 if (i->second == link) 922 continue; 923 if (i->second->hasAddress (addr)) 924 { 925 if (i->second == link) 926 { 927 if (!quiet) 928 TRACEPRINTF (link->t, 8, "local addr %s", FormatEIBAddr (addr)); 929 return false; 930 } 931 if (!quiet) 932 TRACEPRINTF (i->second->t, 8, "found addr %s", FormatEIBAddr (addr)); 933 link = i->second; 934 return true; 935 } 936 } 937 938 if (!quiet) 939 TRACEPRINTF (t, 8, "unknown addr %s", FormatEIBAddr (addr)); 940 return false; 941 } 942 943 bool 944 Router::checkAddress (eibaddr_t addr, LinkConnectPtr link) const 945 { 946 if (addr == 0) // always accept broadcast 947 return true; 948 949 C_ITER(i, links) 950 { 951 if (i->second == link) 952 continue; 953 if (i->second->checkAddress (addr)) 954 return true; 955 } 956 957 return false; 958 } 959 960 bool 961 Router::checkGroupAddress (eibaddr_t addr, LinkConnectPtr link) const 962 { 963 if (addr == 0) // always accept broadcast 964 return true; 965 966 C_ITER(i, links) 967 { 968 if (i->second == link) 969 continue; 970 if (i->second->checkGroupAddress (addr)) 971 return true; 972 } 973 974 return false; 975 } 976 977 eibaddr_t 978 Router::get_client_addr (TracePtr t) 979 { 980 /* 981 * Start allocating after the last-assigned address. 982 * This leaves a buffer for delayed replies so that they don't get sent 983 * to a new client. 984 * 985 * client_addrs_pos is set to len-1 in set_client_block() so that allocation 986 * still starts at the first free address when starting up. 987 */ 988 for (int i = 1; i <= client_addrs_len; i++) 989 { 990 unsigned int pos = (client_addrs_pos + i) % client_addrs_len; 991 if (client_addrs[pos]) 992 continue; 993 eibaddr_t a = client_addrs_start + pos; 994 LinkConnectPtr link = nullptr; 995 if (a != addr && !hasAddress (a, link, true)) 996 { 997 TRACEPRINTF (t, 3, "Allocate %s", FormatEIBAddr (a)); 998 /* remember for next pass */ 999 client_addrs_pos = pos; 1000 client_addrs[pos] = true; 1001 return a; 1002 } 1003 } 1004 1005 /* no more … */ 1006 ERRORPRINTF (t, E_WARNING | 59, "Allocate: no more free addresses!"); 1007 return 0; 1008 } 1009 1010 void 1011 Router::release_client_addr(eibaddr_t addr) 1012 { 1013 if (addr < client_addrs_start) 1014 { 1015 ERRORPRINTF (t, E_ERROR | 3, "Release BAD1 %s", FormatEIBAddr (addr)); 1016 return; 1017 } 1018 int pos = addr - client_addrs_start; 1019 if (pos >= client_addrs_len) 1020 { 1021 ERRORPRINTF (t, E_ERROR | 95, "Release BAD2 %s", FormatEIBAddr (addr)); 1022 return; 1023 } 1024 if (!client_addrs[pos]) 1025 { 1026 ERRORPRINTF (t, E_ERROR | 96, "Release free addr %s", FormatEIBAddr (addr)); 1027 return; 1028 } 1029 1030 TRACEPRINTF (t, 3, "Release %s", FormatEIBAddr (addr)); 1031 client_addrs[pos] = false; 1032 } 1033 1034 void 1035 Router::trigger_cb (ev::async &, int) 1036 { 1037 while (!buf.empty() && low_send_more) 1038 { 1039 LDataPtr l1 = buf.get (); 1040 1041 if (vbusmonitor.size()) 1042 { 1043 LBusmonPtr l2 = LBusmonPtr(new L_Busmon_PDU ()); 1044 l2->lpdu.set (L_Data_to_CM_TP1 (l1)); 1045 1046 ITER(i,vbusmonitor) 1047 i->cb->send_L_Busmonitor (LBusmonPtr(new L_Busmon_PDU (*l2))); 1048 } 1049 if (!l1->hop_count) 1050 { 1051 TRACEPRINTF (t, 3, "Hopcount zero: %s", l1->Decode (t)); 1052 goto next; 1053 } 1054 if (l1->hop_count < 7 || !force_broadcast) 1055 l1->hop_count--; 1056 1057 if (l1->repeated) 1058 { 1059 CArray d1 = L_Data_to_CM_TP1 (l1); 1060 ITER (i,ignore) 1061 if (d1 == i->data) 1062 { 1063 TRACEPRINTF (t, 9, "Drop: %s", l1->Decode (t)); 1064 goto next; 1065 } 1066 } 1067 l1->repeated = 1; 1068 ignore.push_back((IgnoreInfo) 1069 { 1070 .data = L_Data_to_CM_TP1 (l1), .end = getTime () + 1000000 1071 }); 1072 l1->repeated = 0; 1073 1074 if (l1->address_type == IndividualAddress 1075 && l1->destination_address == this->addr) 1076 l1->destination_address = 0; 1077 1078 low_send_more = false; 1079 r_low->send_L_Data(std::move(l1)); 1080 next: 1081 ; 1082 } 1083 1084 if (!low_send_more) 1085 TRACEPRINTF (t, 6, "wait L"); 1086 1087 // Timestamps are ordered, so we scan for the first 1088 timestamp_t tm = getTime (); 1089 ITER (i, ignore) 1090 if (i->end >= tm) 1091 { 1092 ignore.erase (ignore.begin(), i); 1093 break; 1094 } 1095 } 1096 1097 bool 1098 Router::has_send_more(LinkConnectPtr i) 1099 { 1100 if (i->send_more) 1101 return true; 1102 ERRORPRINTF (i->t, E_FATAL | 106, "internal error: send_more is not set"); 1103 return false; 1104 } 1105 1106 void 1107 Router::send_L_Data(LDataPtr l1) 1108 { 1109 assert(high_send_more); 1110 high_sending = true; 1111 high_send_more = false; 1112 1113 auto source = l1->source; 1114 l1->source = nullptr; 1115 1116 if (l1->address_type == GroupAddress) 1117 { 1118 // This is easy: send to all other L2 which subscribe to the 1119 // group. 1120 ITER(i, links) 1121 { 1122 auto ii = i->second; 1123 if (ii->state != L_up) 1124 continue; 1125 if ((l1->source_address == 0xFFFF) // programming 1126 ? &*ii == source 1127 : ii->hasAddress(l1->source_address)) 1128 continue; // don't return to same interface 1129 if(!has_send_more(ii)) 1130 continue; // internal error if not 1131 if (ii->checkGroupAddress(l1->destination_address)) 1132 ii->send_L_Data (LDataPtr(new L_Data_PDU (*l1))); 1133 } 1134 } 1135 else if (l1->address_type == IndividualAddress) 1136 { 1137 // we want to send to the interface on which the destination address 1138 // has appeared. If it hasn't been seen yet, we send to all 1139 // interfaces. 1140 // Address ~0 is special; it's used for programming 1141 // so can be on different interfaces. Always broadcast these. 1142 bool found = (l1->destination_address == this->addr); 1143 if (l1->destination_address != 0xFFFF) 1144 ITER(i, links) 1145 { 1146 auto ii = i->second; 1147 if (ii->hasAddress (l1->source_address)) 1148 continue; 1149 if (ii->hasAddress (l1->destination_address)) 1150 { 1151 found = true; 1152 break; 1153 } 1154 } 1155 ITER (i, links) 1156 { 1157 auto ii = i->second; 1158 if (ii->state != L_up) 1159 continue; 1160 if (ii->hasAddress (l1->source_address)) 1161 continue; // don't return to same interface 1162 if(!has_send_more(ii)) 1163 continue; // internal error if not 1164 if (l1->hop_count == 7 || found ? ii->hasAddress (l1->destination_address) : ii->checkAddress (l1->destination_address)) 1165 i->second->send_L_Data (LDataPtr(new L_Data_PDU (*l1))); 1166 } 1167 } 1168 high_sending = false; 1169 send_Next(); // check readiness 1170 } 1171 1172 void 1173 Router::mtrigger_cb (ev::async &, int) 1174 { 1175 while (!mbuf.empty()) 1176 { 1177 LBusmonPtr l1 = mbuf.get (); 1178 1179 TRACEPRINTF (t, 3, "RecvMon %s", l1->Decode (t)); 1180 ITER (i, busmonitor) 1181 i->cb->send_L_Busmonitor (LBusmonPtr(new L_Busmon_PDU (*l1))); 1182 } 1183 } 1184 1185 bool 1186 Router::checkStack(IniSectionPtr& cfg) 1187 { 1188 LinkConnectPtr conn = LinkConnectPtr(new LinkConnect(*this, cfg, t)); 1189 DriverPtr dummy = DriverPtr(drivers.create("dummy",conn,cfg)); 1190 if (dummy == nullptr) 1191 return false; 1192 conn->set_driver(dummy); 1193 if (!conn->setup()) 1194 return false; 1195 return true; 1196 } 1197 1198 bool 1199 Router::hasClientAddrs(bool complain) const 1200 { 1201 if (client_addrs_len > 0) 1202 return true; 1203 if (complain) 1204 ERRORPRINTF (t, E_ERROR | 51, "You need a client-addrs=X.Y.Z:N option in your %s section.", main); 1205 return false; 1206 1207 } 1208 1209 void 1210 RouterHigh::started() 1211 { 1212 if (is_started) 1213 return; 1214 is_started = true; 1215 Driver::started(); 1216 } 1217 1218 void 1219 RouterHigh::stopped(bool err) 1220 { 1221 is_started = false; 1222 Driver::stopped(err); 1223 } 1224 1225 void 1226 RouterHigh::recv_L_Data (LDataPtr l) 1227 { 1228 auto r = recv.lock(); 1229 if (r != nullptr) 1230 r->recv_L_Data(std::move(l)); 1231 } 1232 1233 void 1234 RouterHigh::recv_L_Busmonitor (LBusmonPtr l) 1235 { 1236 auto r = recv.lock(); 1237 if (r != nullptr) 1238 r->recv_L_Busmonitor(std::move(l)); 1239 } 1240 1241 RouterHigh::RouterHigh(Router& r, const RouterLowPtr& rl) 1242 : Driver(std::dynamic_pointer_cast<LinkConnect_>(rl), r.ini[r.main]), router(&r) 1243 { 1244 t->setAuxName("H"); 1245 } 1246 1247 RouterLow::RouterLow(Router& r) 1248 : LinkConnect_(r, r.ini[r.main], r.t), router(&r) 1249 { 1250 t->setAuxName("L"); 1251 } 1252 1253 void 1254 RouterLow::send_Next() 1255 { 1256 router->low_send_more = true; 1257 TRACEPRINTF (t, 6, "OK L"); 1258 router->trigger.send(); 1259 }