/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /** * Copyright (c) 2017 Alexander Afanasyev * * This program is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version * 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. * If not, see . */ #include "routing-table.hpp" #include "core/utils.hpp" #include #include #include #include #include namespace simple_router { ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // IMPLEMENT THIS METHOD RoutingTableEntry RoutingTable::lookup(uint32_t ip) const { // FILL THIS IN uint32_t longest_mask = 0; const RoutingTableEntry *selected = NULL; for (const auto &entry : m_entries) { auto masked_dest = entry.dest & entry.mask; auto masked_ip = ip & entry.mask; if (masked_dest == masked_ip){ auto re_mask = ntohl(entry.mask); if (longest_mask < re_mask || (!selected)) { longest_mask = re_mask; selected = &entry; } } } if(selected){ return *selected; } throw std::runtime_error("Routing entry not found"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // You should not need to touch the rest of this code. bool RoutingTable::load(const std::string& file) { FILE* fp; char line[BUFSIZ]; char dest[32]; char gw[32]; char mask[32]; char iface[32]; struct in_addr dest_addr; struct in_addr gw_addr; struct in_addr mask_addr; if (access(file.c_str(), R_OK) != 0) { perror("access"); return false; } fp = fopen(file.c_str(), "r"); while (fgets(line, BUFSIZ, fp) != 0) { sscanf(line,"%s %s %s %s", dest, gw, mask, iface); if (inet_aton(dest, &dest_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", dest); return false; } if (inet_aton(gw, &gw_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", gw); return false; } if (inet_aton(mask, &mask_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", mask); return false; } addEntry({dest_addr.s_addr, gw_addr.s_addr, mask_addr.s_addr, iface}); } return true; } void RoutingTable::addEntry(RoutingTableEntry entry) { m_entries.push_back(std::move(entry)); } std::ostream& operator<<(std::ostream& os, const RoutingTableEntry& entry) { os << ipToString(entry.dest) << "\t\t" << ipToString(entry.gw) << "\t" << ipToString(entry.mask) << "\t" << entry.ifName; return os; } std::ostream& operator<<(std::ostream& os, const RoutingTable& table) { os << "Destination\tGateway\t\tMask\tIface\n"; for (const auto& entry : table.m_entries) { os << entry << "\n"; } return os; } } // namespace simple_router