1582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* 2582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * Copyright (c) 2017, The Linux Foundation. All rights reserved. 3582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 4582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * Redistribution and use in source and binary forms, with or without 5582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * modification, are permitted provided that the following conditions are 6582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * met: 7582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * * Redistributions of source code must retain the above copyright 8582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * notice, this list of conditions and the following disclaimer. 9582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * * Redistributions in binary form must reproduce the above 10582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * copyright notice, this list of conditions and the following 11582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * disclaimer in the documentation and/or other materials provided 12582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * with the distribution. 13582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * * Neither the name of The Linux Foundation nor the names of its 14582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * contributors may be used to endorse or promote products derived 15582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * from this software without specific prior written permission. 16582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 17582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 29582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* External Includes */ 30582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <arpa/inet.h> 31582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <netinet/in.h> 32582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <netinet/ip.h> 33582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <string.h> 34582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <sys/socket.h> 35582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <sys/types.h> 36582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include <vector> 37582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 38582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* Internal Includes */ 39582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include "IOffloadManager.h" 40582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel#include "PrefixParser.h" 41582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 42582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* Avoiding namespace pollution */ 43582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelusing IP_FAM = ::IOffloadManager::IP_FAM; 44582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelusing Prefix = ::IOffloadManager::Prefix; 45582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 46582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelusing ::std::string; 47582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelusing ::std::vector; 48582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 49582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 50582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* ------------------------------ PUBLIC ------------------------------------ */ 51582b9e5c388f74eeafad876c81492c81bf1f3945Thierry StrudelPrefixParser::PrefixParser() { 52582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "No Err"; 53582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* PrefixParser */ 54582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 55582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::add(vector<string> in) { 56582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return add(in, IP_FAM::INVALID); 57582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* add */ 58582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 59582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::add(string in) { 60582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return add(in, IP_FAM::INVALID); 61582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* add */ 62582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 63582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::addV4(string in) { 64582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return add(in, IP_FAM::V4); 65582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* addV4 */ 66582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 67582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::addV4(vector<string> in) { 68582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return add(in, IP_FAM::V4); 69582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* addV4 */ 70582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 71582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::addV6(string in) { 72582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return add(in, IP_FAM::V6); 73582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* addV6 */ 74582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 75582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::addV6(vector<string> in) { 76582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (size_t i = 0; i < in.size(); i++) { 77582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (!addV6(in[i])) 78582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 79582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 80582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 81582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* addV6 */ 82582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 83582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelint PrefixParser::size() { 84582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return mPrefixes.size(); 85582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* size */ 86582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 87582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::allAreFullyQualified() { 88582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (size_t i = 0; i < mPrefixes.size(); i++) { 89582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (mPrefixes[i].fam == IP_FAM::V4) { 90582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel uint32_t masked = mPrefixes[i].v4Addr & mPrefixes[i].v4Mask; 91582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (masked != mPrefixes[i].v4Addr) 92582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 93582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else { 94582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel uint32_t masked[4]; 95582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel masked[0] = mPrefixes[i].v6Addr[0] & mPrefixes[i].v6Mask[0]; 96582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel masked[1] = mPrefixes[i].v6Addr[1] & mPrefixes[i].v6Mask[1]; 97582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel masked[2] = mPrefixes[i].v6Addr[2] & mPrefixes[i].v6Mask[2]; 98582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel masked[3] = mPrefixes[i].v6Addr[3] & mPrefixes[i].v6Mask[3]; 99582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (int j = 0; j < 4; j++) { 100582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (masked[j] != mPrefixes[i].v6Addr[j]) 101582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 102582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 103582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 104582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 105582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 106582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* allAreFullyQualified */ 107582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 108582b9e5c388f74eeafad876c81492c81bf1f3945Thierry StrudelPrefix PrefixParser::getFirstPrefix() { 109582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (size() >= 1) 110582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return mPrefixes[0]; 111582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return makeBlankPrefix(IP_FAM::INVALID); 112582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* getFirstPrefix */ 113582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 114582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelstring PrefixParser::getLastErrAsStr() { 115582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return mLastErr; 116582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* getLastErrAsStr */ 117582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 118582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 119582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* ------------------------------ PRIVATE ----------------------------------- */ 120582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::add(vector<string> in, IP_FAM famHint) { 121e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar if (in.size() == 0) 122e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar return false; 123e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar 124582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (size_t i = 0; i < in.size(); i++) { 125582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (!add(in[i], famHint)) 126582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 127582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 128582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 129582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* add */ 130582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 131582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::add(string in, IP_FAM famHint) { 132e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar if (in.length() == 0) { 133e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar mLastErr = "Failed to parse string, length = 0..."; 134e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar return false; 135e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar } 136e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar 137582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (famHint == IP_FAM::INVALID) 138582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel famHint = guessIPFamily(in); 139582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 140582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel string subnet; 141582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel string addr; 142582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 143582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (!splitIntoAddrAndMask(in, addr, subnet)) { 144582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed to split into Address and Mask(" + in + ")"; 145582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 146582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 147582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 148582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel int mask = parseSubnetMask(subnet, famHint); 149e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar if (!isMaskValid(mask, famHint)) { 150e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar mLastErr = "Invalid mask"; 151582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 152e549f669e0b541e30de78dc8b3db78b07407955eNiranjan Pendharkar } 153582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 154582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel Prefix pre = makeBlankPrefix(famHint); 155582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 156582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (famHint == IP_FAM::V4) { 157582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (!parseV4Addr(addr, pre)) { 158582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed to parse V4 Address(" + addr + ")"; 159582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 160582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 161582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (!parseV6Addr(addr, pre)) { 162582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed to parse V6 Address(" + addr + ")"; 163582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 164582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 165582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 166582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (famHint == IP_FAM::V4 && !populateV4Mask(mask, pre)) { 167582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed to populate IPv4 Mask(" + std::to_string(mask) 168582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel + ", " + addr + ")"; 169582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 170582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (!populateV6Mask(mask, pre)) { 171582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed to populate IPv6 Mask(" + std::to_string(mask) 172582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel + ", " + addr + ")"; 173582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 174582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 175582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 176582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mPrefixes.push_back(pre); 177582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 178582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* add */ 179582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 180582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel/* Assumption (based on man inet_pton) 181582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 182582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * X represents a hex character 183582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * d represents a base 10 digit 184582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * / represents the start of the subnet mask 185582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * (assume that it can be left off of all below combinations) 186582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 187582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * IPv4 Addresses always look like the following: 188582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * ddd.ddd.ddd.ddd/dd 189582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 190582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * IPv6 Addresses can look a few different ways: 191582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * x:x:x:x:x:x:x:x/ddd 192582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * x::x/ddd 193582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * x:x:x:x:x:x:d.d.d.d/ddd 194582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 195582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * Therefore, if a presentation of an IP Address contains a colon, then it 196582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * may not be a valid IPv6, but, it is definitely not valid IPv4. If a 197582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * presentation of an IP Address does not contain a colon, then it may not be 198582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * a valid IPv4, but, it is definitely not IPv6. 199582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 200582b9e5c388f74eeafad876c81492c81bf1f3945Thierry StrudelIP_FAM PrefixParser::guessIPFamily(string in) { 201582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel size_t found = in.find(":"); 202582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (found != string::npos) 203582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return IP_FAM::V6; 204582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return IP_FAM::V4; 205582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* guessIPFamily */ 206582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 207582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::splitIntoAddrAndMask(string in, string &addr, string &mask) { 208582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel size_t pos = in.find("/"); 209582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 210582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (pos != string::npos && pos >= 1) { 211582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* addr is now everything up until the first / */ 212582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel addr = in.substr(0, pos); 213582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (pos == string::npos) { 214582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* There is no /, so the entire input is an address */ 215582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel addr = in; 216582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else { 217582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* There was nothing before the /, not recoverable */ 218582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 219582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 220582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 221582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (pos != string::npos && pos < in.size()) { 222582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* There is a / and it is not the last character. Everything after / 223582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * must be the subnet. 224582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 225582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mask = in.substr(pos + 1); 226582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (pos != string::npos && pos == in.size()) { 227582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* There is a /, but it is the last character. This is garbage, but, 228582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * we may still be able to interpret the address so we will throw it 229582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * out. 230582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 231582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mask = ""; 232582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (pos == string::npos) { 233582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* There is no /, therefore, there is no subnet */ 234582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mask = ""; 235582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else { 236582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* This really shouldn't be possible because it would imply that find 237582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * returned a position larger than the size of the input. Just 238582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * preserving sanity that mask is always initialized. 239582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 240582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mask = ""; 241582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 242582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 243582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 244582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* splitIntoAddrAndMask */ 245582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 246582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelint PrefixParser::parseSubnetMask(string in, IP_FAM famHint) { 247582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (in.empty()) 248582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* Treat no subnet mask as fully qualified */ 249582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return (famHint == IP_FAM::V6) ? 128 : 32; 250582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return atoi(in.c_str()); 251582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* parseSubnetMask */ 252582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 253582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::parseV4Addr(string in, Prefix &out) { 254582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel struct sockaddr_in sa; 255582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 256582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel int ret = inet_pton(AF_INET, in.c_str(), &(sa.sin_addr)); 257582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 258582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (ret < 0) { 259582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* errno would be valid */ 260582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 261582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (ret == 0) { 262582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* input was not a valid IP address */ 263582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 264582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 265582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 266582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* Address in network byte order */ 267582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v4Addr = htonl(sa.sin_addr.s_addr); 268582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 269582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* parseV4Addr */ 270582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 271582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::parseV6Addr(string in, Prefix &out) { 272582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel struct sockaddr_in6 sa; 273582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 274582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel int ret = inet_pton(AF_INET6, in.c_str(), &(sa.sin6_addr)); 275582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 276582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (ret < 0) { 277582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* errno would be valid */ 278582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 279582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (ret == 0) { 280582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* input was not a valid IP address */ 281582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 282582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 283582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 284582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel /* Translate unsigned chars to unsigned ints to match IPA 285582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * 286582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * TODO there must be a better way to do this beyond bit fiddling 287582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * Maybe a Union since we've already made the assumption that the data 288582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel * structures match? 289582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel */ 290582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v6Addr[0] = (sa.sin6_addr.s6_addr[0] << 24) | 291582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[1] << 16) | 292582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[2] << 8) | 293582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[3]); 294582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v6Addr[1] = (sa.sin6_addr.s6_addr[4] << 24) | 295582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[5] << 16) | 296582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[6] << 8) | 297582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[7]); 298582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v6Addr[2] = (sa.sin6_addr.s6_addr[8] << 24) | 299582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[9] << 16) | 300582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[10] << 8) | 301582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[11]); 302582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v6Addr[3] = (sa.sin6_addr.s6_addr[12] << 24) | 303582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[13] << 16) | 304582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[14] << 8) | 305582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel (sa.sin6_addr.s6_addr[15]); 306582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 307582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* parseV6Addr */ 308582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 309582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::populateV4Mask(int mask, Prefix &out) { 310582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (mask < 0 || mask > 32) 311582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 312582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v4Mask = createMask(mask); 313582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 314582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* populateV4Mask */ 315582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 316582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::populateV6Mask(int mask, Prefix &out) { 317582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (mask < 0 || mask > 128) 318582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 319582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 320582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (int i = 0; i < 4; i++) { 321582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel out.v6Mask[i] = createMask(mask); 322582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mask = (mask > 32) ? mask - 32 : 0; 323582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 324582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 325582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 326582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* populateV6Mask */ 327582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 328582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudeluint32_t PrefixParser::createMask(int mask) { 329582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel uint32_t ret = 0; 330582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 331582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (mask >= 32) { 332582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret = ~ret; 333582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return ret; 334582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 335582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 336582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel for (int i = 0; i < 32; i++) { 337582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (i < mask) 338582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret = (ret << 1) | 1; 339582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel else 340582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret = (ret << 1); 341582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 342582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 343582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return ret; 344582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* createMask */ 345582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 346582b9e5c388f74eeafad876c81492c81bf1f3945Thierry StrudelPrefix PrefixParser::makeBlankPrefix(IP_FAM famHint) { 347582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel Prefix ret; 348582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 349582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.fam = famHint; 350582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 351582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v4Addr = 0; 352582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v4Mask = 0; 353582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 354582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Addr[0] = 0; 355582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Addr[1] = 0; 356582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Addr[2] = 0; 357582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Addr[3] = 0; 358582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 359582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Mask[0] = 0; 360582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Mask[1] = 0; 361582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Mask[2] = 0; 362582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel ret.v6Mask[3] = 0; 363582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 364582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return ret; 365582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* makeBlankPrefix */ 366582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 367582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudelbool PrefixParser::isMaskValid(int mask, IP_FAM fam) { 368582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel if (mask < 0) { 369582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Failed parse subnet mask(" + std::to_string(mask) + ")"; 370582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 371582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (mask == 0) { 372582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Subnet mask cannot be 0(" + std::to_string(mask) + ")"; 373582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 374582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (fam == IP_FAM::V4 && mask > 32) { 375582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Interpreted address as V4 but mask was too large(" 376582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel + std::to_string(mask) + ")"; 377582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 378582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } else if (fam == IP_FAM::V6 && mask > 128) { 379582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel mLastErr = "Interpreted address as V6 but mask was too large(" 380582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel + std::to_string(mask) + ")"; 381582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return false; 382582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel } 383582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel 384582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel return true; 385582b9e5c388f74eeafad876c81492c81bf1f3945Thierry Strudel} /* isMaskValid */ 386