inet.cc revision 10252
12SN/A/* 29955SGeoffrey.Blake@arm.com * Copyright (c) 2013 ARM Limited 39955SGeoffrey.Blake@arm.com * All rights reserved 49955SGeoffrey.Blake@arm.com * 59955SGeoffrey.Blake@arm.com * The license below extends only to copyright in the software and shall 69955SGeoffrey.Blake@arm.com * not be construed as granting a license to any other intellectual 79955SGeoffrey.Blake@arm.com * property including but not limited to intellectual property relating 89955SGeoffrey.Blake@arm.com * to a hardware implementation of the functionality of the software 99955SGeoffrey.Blake@arm.com * licensed hereunder. You may use the software subject to the license 109955SGeoffrey.Blake@arm.com * terms below provided that you ensure that this notice is replicated 119955SGeoffrey.Blake@arm.com * unmodified and in its entirety in all distributions of the software, 129955SGeoffrey.Blake@arm.com * modified or unmodified, in source code or in binary form. 139955SGeoffrey.Blake@arm.com * 141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 157778Sgblack@eecs.umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc. 162SN/A * All rights reserved. 172SN/A * 182SN/A * Redistribution and use in source and binary forms, with or without 192SN/A * modification, are permitted provided that the following conditions are 202SN/A * met: redistributions of source code must retain the above copyright 212SN/A * notice, this list of conditions and the following disclaimer; 222SN/A * redistributions in binary form must reproduce the above copyright 232SN/A * notice, this list of conditions and the following disclaimer in the 242SN/A * documentation and/or other materials provided with the distribution; 252SN/A * neither the name of the copyright holders nor the names of its 262SN/A * contributors may be used to endorse or promote products derived from 272SN/A * this software without specific prior written permission. 282SN/A * 292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402665Ssaidi@eecs.umich.edu * 412665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 427778Sgblack@eecs.umich.edu * Gabe Black 439955SGeoffrey.Blake@arm.com * Geoffrey Blake 442SN/A */ 452SN/A 468607Sgblack@eecs.umich.edu#include <cstddef> 476712Snate@binkert.org#include <cstdio> 482SN/A#include <sstream> 492SN/A#include <string> 502SN/A 5156SN/A#include "base/cprintf.hh" 526216Snate@binkert.org#include "base/inet.hh" 536214Snate@binkert.org#include "base/types.hh" 542SN/A 551078SN/Ausing namespace std; 561114SN/Anamespace Net { 571114SN/A 581114SN/AEthAddr::EthAddr() 591114SN/A{ 601114SN/A memset(data, 0, ETH_ADDR_LEN); 611114SN/A} 621114SN/A 631114SN/AEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 641114SN/A{ 6510251Satgutier@umich.edu for (int i = 0; i < ETH_ADDR_LEN; ++i) 6610251Satgutier@umich.edu data[i] = ea[i]; 671114SN/A} 681114SN/A 691114SN/AEthAddr::EthAddr(const eth_addr &ea) 701114SN/A{ 7110251Satgutier@umich.edu for (int i = 0; i < ETH_ADDR_LEN; ++i) 7210251Satgutier@umich.edu data[i] = ea.data[i]; 731114SN/A} 741114SN/A 751114SN/AEthAddr::EthAddr(const std::string &addr) 761114SN/A{ 771114SN/A parse(addr); 781114SN/A} 791114SN/A 801114SN/Aconst EthAddr & 811114SN/AEthAddr::operator=(const eth_addr &ea) 821114SN/A{ 831114SN/A *data = *ea.data; 841114SN/A return *this; 851114SN/A} 861114SN/A 871114SN/Aconst EthAddr & 881114SN/AEthAddr::operator=(const std::string &addr) 891114SN/A{ 901114SN/A parse(addr); 911114SN/A return *this; 921114SN/A} 931114SN/A 941114SN/Avoid 951114SN/AEthAddr::parse(const std::string &addr) 961114SN/A{ 971114SN/A // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 981114SN/A // the sscanf function won't work. 991114SN/A int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 1001114SN/A if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 1011114SN/A &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 1021114SN/A memset(data, 0xff, ETH_ADDR_LEN); 1031114SN/A return; 1041114SN/A } 1051114SN/A 1061114SN/A for (int i = 0; i < ETH_ADDR_LEN; ++i) { 1071114SN/A if (bytes[i] & ~0xff) { 1081114SN/A memset(data, 0xff, ETH_ADDR_LEN); 1091114SN/A return; 1101114SN/A } 1111114SN/A 1121114SN/A data[i] = bytes[i]; 1131114SN/A } 1141114SN/A} 1151114SN/A 1162SN/Astring 1171114SN/AEthAddr::string() const 1182SN/A{ 1192SN/A stringstream stream; 1201114SN/A stream << *this; 1212SN/A return stream.str(); 1222SN/A} 1232SN/A 1241114SN/Abool 1251114SN/Aoperator==(const EthAddr &left, const EthAddr &right) 1262SN/A{ 12710252Satgutier@umich.edu return !memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 1281114SN/A} 1291114SN/A 1301114SN/Aostream & 1311114SN/Aoperator<<(ostream &stream, const EthAddr &ea) 1321114SN/A{ 1331114SN/A const uint8_t *a = ea.addr(); 1341114SN/A ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 1351114SN/A return stream; 1362SN/A} 1372SN/A 1387777Sgblack@eecs.umich.edustring 1397777Sgblack@eecs.umich.eduIpAddress::string() const 1407777Sgblack@eecs.umich.edu{ 1417777Sgblack@eecs.umich.edu stringstream stream; 1427777Sgblack@eecs.umich.edu stream << *this; 1437777Sgblack@eecs.umich.edu return stream.str(); 1447777Sgblack@eecs.umich.edu} 1457777Sgblack@eecs.umich.edu 1467777Sgblack@eecs.umich.edubool 1477777Sgblack@eecs.umich.eduoperator==(const IpAddress &left, const IpAddress &right) 1487777Sgblack@eecs.umich.edu{ 1497777Sgblack@eecs.umich.edu return left.ip() == right.ip(); 1507777Sgblack@eecs.umich.edu} 1517777Sgblack@eecs.umich.edu 1527777Sgblack@eecs.umich.eduostream & 1537777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpAddress &ia) 1547777Sgblack@eecs.umich.edu{ 1557777Sgblack@eecs.umich.edu uint32_t ip = ia.ip(); 1567777Sgblack@eecs.umich.edu ccprintf(stream, "%x.%x.%x.%x", 1577814Sgblack@eecs.umich.edu (uint8_t)(ip >> 24), (uint8_t)(ip >> 16), 1587814Sgblack@eecs.umich.edu (uint8_t)(ip >> 8), (uint8_t)(ip >> 0)); 1597777Sgblack@eecs.umich.edu return stream; 1607777Sgblack@eecs.umich.edu} 1617777Sgblack@eecs.umich.edu 1627777Sgblack@eecs.umich.edustring 1637777Sgblack@eecs.umich.eduIpNetmask::string() const 1647777Sgblack@eecs.umich.edu{ 1657777Sgblack@eecs.umich.edu stringstream stream; 1667777Sgblack@eecs.umich.edu stream << *this; 1677777Sgblack@eecs.umich.edu return stream.str(); 1687777Sgblack@eecs.umich.edu} 1697777Sgblack@eecs.umich.edu 1707777Sgblack@eecs.umich.edubool 1717777Sgblack@eecs.umich.eduoperator==(const IpNetmask &left, const IpNetmask &right) 1727777Sgblack@eecs.umich.edu{ 1737777Sgblack@eecs.umich.edu return (left.ip() == right.ip()) && 1747777Sgblack@eecs.umich.edu (left.netmask() == right.netmask()); 1757777Sgblack@eecs.umich.edu} 1767777Sgblack@eecs.umich.edu 1777777Sgblack@eecs.umich.eduostream & 1787777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpNetmask &in) 1797777Sgblack@eecs.umich.edu{ 1807777Sgblack@eecs.umich.edu ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask()); 1817777Sgblack@eecs.umich.edu return stream; 1827777Sgblack@eecs.umich.edu} 1837777Sgblack@eecs.umich.edu 1847777Sgblack@eecs.umich.edustring 1857777Sgblack@eecs.umich.eduIpWithPort::string() const 1867777Sgblack@eecs.umich.edu{ 1877777Sgblack@eecs.umich.edu stringstream stream; 1887777Sgblack@eecs.umich.edu stream << *this; 1897777Sgblack@eecs.umich.edu return stream.str(); 1907777Sgblack@eecs.umich.edu} 1917777Sgblack@eecs.umich.edu 1927777Sgblack@eecs.umich.edubool 1937777Sgblack@eecs.umich.eduoperator==(const IpWithPort &left, const IpWithPort &right) 1947777Sgblack@eecs.umich.edu{ 1957777Sgblack@eecs.umich.edu return (left.ip() == right.ip()) && (left.port() == right.port()); 1967777Sgblack@eecs.umich.edu} 1977777Sgblack@eecs.umich.edu 1987777Sgblack@eecs.umich.eduostream & 1997777Sgblack@eecs.umich.eduoperator<<(ostream &stream, const IpWithPort &iwp) 2007777Sgblack@eecs.umich.edu{ 2017777Sgblack@eecs.umich.edu ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port()); 2027777Sgblack@eecs.umich.edu return stream; 2037777Sgblack@eecs.umich.edu} 2047777Sgblack@eecs.umich.edu 2051078SN/Auint16_t 2061114SN/Acksum(const IpPtr &ptr) 2071078SN/A{ 2081114SN/A int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 2091114SN/A return ip_cksum_carry(sum); 2101078SN/A} 2111114SN/A 2121114SN/Auint16_t 2131114SN/A__tu_cksum(const IpPtr &ip) 2141114SN/A{ 2151114SN/A int tcplen = ip->len() - ip->hlen(); 2161114SN/A int sum = ip_cksum_add(ip->payload(), tcplen, 0); 2171114SN/A sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 2181114SN/A sum += htons(ip->ip_p + tcplen); 2191114SN/A return ip_cksum_carry(sum); 2201114SN/A} 2211114SN/A 2221114SN/Auint16_t 2239955SGeoffrey.Blake@arm.com__tu_cksum6(const Ip6Ptr &ip6) 2249955SGeoffrey.Blake@arm.com{ 2259955SGeoffrey.Blake@arm.com int tcplen = ip6->plen() - ip6->extensionLength(); 2269955SGeoffrey.Blake@arm.com int sum = ip_cksum_add(ip6->payload(), tcplen, 0); 2279955SGeoffrey.Blake@arm.com sum = ip_cksum_add(ip6->src(), 32, sum); 2289955SGeoffrey.Blake@arm.com sum += htons(ip6->proto() + tcplen); 2299955SGeoffrey.Blake@arm.com return ip_cksum_carry(sum); 2309955SGeoffrey.Blake@arm.com} 2319955SGeoffrey.Blake@arm.com 2329955SGeoffrey.Blake@arm.comuint16_t 2331114SN/Acksum(const TcpPtr &tcp) 2349955SGeoffrey.Blake@arm.com{ 2359955SGeoffrey.Blake@arm.com if (IpPtr(tcp.packet())) { 2369955SGeoffrey.Blake@arm.com return __tu_cksum(IpPtr(tcp.packet())); 2379955SGeoffrey.Blake@arm.com } else if (Ip6Ptr(tcp.packet())) { 2389955SGeoffrey.Blake@arm.com return __tu_cksum6(Ip6Ptr(tcp.packet())); 2399955SGeoffrey.Blake@arm.com } else { 2409955SGeoffrey.Blake@arm.com assert(0); 2419955SGeoffrey.Blake@arm.com } 2429955SGeoffrey.Blake@arm.com // Should never reach here 2439955SGeoffrey.Blake@arm.com return 0; 2449955SGeoffrey.Blake@arm.com} 2451114SN/A 2461114SN/Auint16_t 2471114SN/Acksum(const UdpPtr &udp) 2489955SGeoffrey.Blake@arm.com{ 2499955SGeoffrey.Blake@arm.com if (IpPtr(udp.packet())) { 2509955SGeoffrey.Blake@arm.com return __tu_cksum(IpPtr(udp.packet())); 2519955SGeoffrey.Blake@arm.com } else if (Ip6Ptr(udp.packet())) { 2529955SGeoffrey.Blake@arm.com return __tu_cksum6(Ip6Ptr(udp.packet())); 2539955SGeoffrey.Blake@arm.com } else { 2549955SGeoffrey.Blake@arm.com assert(0); 2559955SGeoffrey.Blake@arm.com } 2569955SGeoffrey.Blake@arm.com return 0; 2579955SGeoffrey.Blake@arm.com} 2581114SN/A 2591114SN/Abool 2601114SN/AIpHdr::options(vector<const IpOpt *> &vec) const 2611114SN/A{ 2621114SN/A vec.clear(); 2631114SN/A 2641114SN/A const uint8_t *data = bytes() + sizeof(struct ip_hdr); 2651114SN/A int all = hlen() - sizeof(struct ip_hdr); 2661114SN/A while (all > 0) { 2671114SN/A const IpOpt *opt = (const IpOpt *)data; 2681114SN/A int len = opt->len(); 2691114SN/A if (all < len) 2701114SN/A return false; 2711114SN/A 2721114SN/A vec.push_back(opt); 2731114SN/A all -= len; 2741114SN/A data += len; 2751114SN/A } 2761114SN/A 2771114SN/A return true; 2781114SN/A} 2791114SN/A 2809955SGeoffrey.Blake@arm.com#define IP6_EXTENSION(nxt) (nxt == IP_PROTO_HOPOPTS) ? true : \ 2819955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_ROUTING) ? true : \ 2829955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_FRAGMENT) ? true : \ 2839955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_AH) ? true : \ 2849955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_ESP) ? true: \ 2859955SGeoffrey.Blake@arm.com (nxt == IP_PROTO_DSTOPTS) ? true : false 2869955SGeoffrey.Blake@arm.com 2879955SGeoffrey.Blake@arm.com/* Scan the IP6 header for all header extensions 2889955SGeoffrey.Blake@arm.com * and return the number of headers found 2899955SGeoffrey.Blake@arm.com */ 2909955SGeoffrey.Blake@arm.comint 2919955SGeoffrey.Blake@arm.comIp6Hdr::extensionLength() const 2929955SGeoffrey.Blake@arm.com{ 2939955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 2949955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 2959955SGeoffrey.Blake@arm.com int len = 0; 2969955SGeoffrey.Blake@arm.com int all = plen(); 2979955SGeoffrey.Blake@arm.com 2989955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 2999955SGeoffrey.Blake@arm.com const Ip6Opt *ext = (const Ip6Opt *)data; 3009955SGeoffrey.Blake@arm.com nxt = ext->nxt(); 3019955SGeoffrey.Blake@arm.com len += ext->len(); 3029955SGeoffrey.Blake@arm.com data += ext->len(); 3039955SGeoffrey.Blake@arm.com all -= ext->len(); 3049955SGeoffrey.Blake@arm.com assert(all >= 0); 3059955SGeoffrey.Blake@arm.com } 3069955SGeoffrey.Blake@arm.com return len; 3079955SGeoffrey.Blake@arm.com} 3089955SGeoffrey.Blake@arm.com 3099955SGeoffrey.Blake@arm.com/* Scan the IP6 header for a particular extension 3109955SGeoffrey.Blake@arm.com * header type and return a pointer to it if it 3119955SGeoffrey.Blake@arm.com * exists, otherwise return NULL 3129955SGeoffrey.Blake@arm.com */ 3139955SGeoffrey.Blake@arm.comconst Ip6Opt* 3149955SGeoffrey.Blake@arm.comIp6Hdr::getExt(uint8_t ext_type) const 3159955SGeoffrey.Blake@arm.com{ 3169955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 3179955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 3189955SGeoffrey.Blake@arm.com Ip6Opt* opt = NULL; 3199955SGeoffrey.Blake@arm.com int all = plen(); 3209955SGeoffrey.Blake@arm.com 3219955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 3229955SGeoffrey.Blake@arm.com opt = (Ip6Opt *)data; 3239955SGeoffrey.Blake@arm.com if (nxt == ext_type) { 3249955SGeoffrey.Blake@arm.com break; 3259955SGeoffrey.Blake@arm.com } 3269955SGeoffrey.Blake@arm.com nxt = opt->nxt(); 3279955SGeoffrey.Blake@arm.com data += opt->len(); 3289955SGeoffrey.Blake@arm.com all -= opt->len(); 3299955SGeoffrey.Blake@arm.com opt = NULL; 3309955SGeoffrey.Blake@arm.com assert(all >= 0); 3319955SGeoffrey.Blake@arm.com } 3329955SGeoffrey.Blake@arm.com return (const Ip6Opt*)opt; 3339955SGeoffrey.Blake@arm.com} 3349955SGeoffrey.Blake@arm.com 3359955SGeoffrey.Blake@arm.com/* Scan the IP6 header and any extension headers 3369955SGeoffrey.Blake@arm.com * to find what type of Layer 4 header exists 3379955SGeoffrey.Blake@arm.com * after this header 3389955SGeoffrey.Blake@arm.com */ 3399955SGeoffrey.Blake@arm.comuint8_t 3409955SGeoffrey.Blake@arm.comIp6Hdr::proto() const 3419955SGeoffrey.Blake@arm.com{ 3429955SGeoffrey.Blake@arm.com const uint8_t *data = bytes() + IP6_HDR_LEN; 3439955SGeoffrey.Blake@arm.com uint8_t nxt = ip6_nxt; 3449955SGeoffrey.Blake@arm.com int all = plen(); 3459955SGeoffrey.Blake@arm.com 3469955SGeoffrey.Blake@arm.com while (IP6_EXTENSION(nxt)) { 3479955SGeoffrey.Blake@arm.com const Ip6Opt *ext = (const Ip6Opt *)data; 3489955SGeoffrey.Blake@arm.com nxt = ext->nxt(); 3499955SGeoffrey.Blake@arm.com data += ext->len(); 3509955SGeoffrey.Blake@arm.com all -= ext->len(); 3519955SGeoffrey.Blake@arm.com assert(all >= 0); 3529955SGeoffrey.Blake@arm.com } 3539955SGeoffrey.Blake@arm.com return nxt; 3549955SGeoffrey.Blake@arm.com} 3559955SGeoffrey.Blake@arm.com 3561114SN/Abool 3571114SN/ATcpHdr::options(vector<const TcpOpt *> &vec) const 3581114SN/A{ 3591114SN/A vec.clear(); 3601114SN/A 3611114SN/A const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 3621114SN/A int all = off() - sizeof(struct tcp_hdr); 3631114SN/A while (all > 0) { 3641114SN/A const TcpOpt *opt = (const TcpOpt *)data; 3651114SN/A int len = opt->len(); 3661114SN/A if (all < len) 3671114SN/A return false; 3681114SN/A 3691114SN/A vec.push_back(opt); 3701114SN/A all -= len; 3711114SN/A data += len; 3721114SN/A } 3731114SN/A 3741114SN/A return true; 3751114SN/A} 3761114SN/A 3775782Ssaidi@eecs.umich.eduint 3785782Ssaidi@eecs.umich.eduhsplit(const EthPacketPtr &ptr) 3795782Ssaidi@eecs.umich.edu{ 3805782Ssaidi@eecs.umich.edu int split_point = 0; 3815782Ssaidi@eecs.umich.edu 3825782Ssaidi@eecs.umich.edu IpPtr ip(ptr); 3839955SGeoffrey.Blake@arm.com Ip6Ptr ip6(ptr); 3845782Ssaidi@eecs.umich.edu if (ip) { 3855782Ssaidi@eecs.umich.edu split_point = ip.pstart(); 3865782Ssaidi@eecs.umich.edu 3875782Ssaidi@eecs.umich.edu TcpPtr tcp(ip); 3885782Ssaidi@eecs.umich.edu if (tcp) 3895782Ssaidi@eecs.umich.edu split_point = tcp.pstart(); 3905782Ssaidi@eecs.umich.edu 3915782Ssaidi@eecs.umich.edu UdpPtr udp(ip); 3925782Ssaidi@eecs.umich.edu if (udp) 3935782Ssaidi@eecs.umich.edu split_point = udp.pstart(); 3949955SGeoffrey.Blake@arm.com } else if (ip6) { 3959955SGeoffrey.Blake@arm.com split_point = ip6.pstart(); 3969955SGeoffrey.Blake@arm.com 3979955SGeoffrey.Blake@arm.com TcpPtr tcp(ip6); 3989955SGeoffrey.Blake@arm.com if (tcp) 3999955SGeoffrey.Blake@arm.com split_point = tcp.pstart(); 4009955SGeoffrey.Blake@arm.com UdpPtr udp(ip6); 4019955SGeoffrey.Blake@arm.com if (udp) 4029955SGeoffrey.Blake@arm.com split_point = udp.pstart(); 4035782Ssaidi@eecs.umich.edu } 4045782Ssaidi@eecs.umich.edu return split_point; 4055782Ssaidi@eecs.umich.edu} 4065782Ssaidi@eecs.umich.edu 4075782Ssaidi@eecs.umich.edu 4087811Ssteve.reinhardt@amd.com} // namespace Net 409