inet.cc revision 7778:6a7207241112
112922Sgabeblack@google.com/* 212922Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 312922Sgabeblack@google.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 412922Sgabeblack@google.com * All rights reserved. 512922Sgabeblack@google.com * 612922Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 712922Sgabeblack@google.com * modification, are permitted provided that the following conditions are 812922Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 912922Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 1012922Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1112922Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1212922Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1312922Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1412922Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1512922Sgabeblack@google.com * this software without specific prior written permission. 1612922Sgabeblack@google.com * 1712922Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1812922Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1912922Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2012922Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2112922Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2212922Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2312922Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2412922Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2512922Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2612922Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2712922Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2812922Sgabeblack@google.com * 2912922Sgabeblack@google.com * Authors: Nathan Binkert 3012922Sgabeblack@google.com * Gabe Black 3112922Sgabeblack@google.com */ 3212922Sgabeblack@google.com 3312922Sgabeblack@google.com#include <cstdio> 3412922Sgabeblack@google.com#include <sstream> 3512922Sgabeblack@google.com#include <string> 3612922Sgabeblack@google.com 3712922Sgabeblack@google.com#include "base/cprintf.hh" 3812922Sgabeblack@google.com#include "base/inet.hh" 3912922Sgabeblack@google.com#include "base/types.hh" 4012922Sgabeblack@google.com 4112922Sgabeblack@google.comusing namespace std; 4212922Sgabeblack@google.comnamespace Net { 4312922Sgabeblack@google.com 4412922Sgabeblack@google.comEthAddr::EthAddr() 4512922Sgabeblack@google.com{ 4612922Sgabeblack@google.com memset(data, 0, ETH_ADDR_LEN); 4712922Sgabeblack@google.com} 4812922Sgabeblack@google.com 4912922Sgabeblack@google.comEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 5012922Sgabeblack@google.com{ 5112922Sgabeblack@google.com *data = *ea; 5212922Sgabeblack@google.com} 5312922Sgabeblack@google.com 5412922Sgabeblack@google.comEthAddr::EthAddr(const eth_addr &ea) 5512922Sgabeblack@google.com{ 5612922Sgabeblack@google.com *data = *ea.data; 5712922Sgabeblack@google.com} 5812922Sgabeblack@google.com 5912922Sgabeblack@google.comEthAddr::EthAddr(const std::string &addr) 6012922Sgabeblack@google.com{ 6112922Sgabeblack@google.com parse(addr); 6212922Sgabeblack@google.com} 6312922Sgabeblack@google.com 6412922Sgabeblack@google.comconst EthAddr & 6512922Sgabeblack@google.comEthAddr::operator=(const eth_addr &ea) 6612922Sgabeblack@google.com{ 6712922Sgabeblack@google.com *data = *ea.data; 6812922Sgabeblack@google.com return *this; 6912922Sgabeblack@google.com} 7012922Sgabeblack@google.com 7112922Sgabeblack@google.comconst EthAddr & 7212922Sgabeblack@google.comEthAddr::operator=(const std::string &addr) 7312922Sgabeblack@google.com{ 7412922Sgabeblack@google.com parse(addr); 7512922Sgabeblack@google.com return *this; 7612922Sgabeblack@google.com} 7712922Sgabeblack@google.com 7812922Sgabeblack@google.comvoid 7912922Sgabeblack@google.comEthAddr::parse(const std::string &addr) 8012922Sgabeblack@google.com{ 8112922Sgabeblack@google.com // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 8212922Sgabeblack@google.com // the sscanf function won't work. 8312922Sgabeblack@google.com int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 8412922Sgabeblack@google.com if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 8512922Sgabeblack@google.com &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 8612922Sgabeblack@google.com memset(data, 0xff, ETH_ADDR_LEN); 8712922Sgabeblack@google.com return; 8812922Sgabeblack@google.com } 8912922Sgabeblack@google.com 9012922Sgabeblack@google.com for (int i = 0; i < ETH_ADDR_LEN; ++i) { 9112922Sgabeblack@google.com if (bytes[i] & ~0xff) { 9212922Sgabeblack@google.com memset(data, 0xff, ETH_ADDR_LEN); 9312922Sgabeblack@google.com return; 9412922Sgabeblack@google.com } 9512922Sgabeblack@google.com 9612922Sgabeblack@google.com data[i] = bytes[i]; 9712922Sgabeblack@google.com } 9812922Sgabeblack@google.com} 9912922Sgabeblack@google.com 10012922Sgabeblack@google.comstring 10112922Sgabeblack@google.comEthAddr::string() const 10212922Sgabeblack@google.com{ 10312922Sgabeblack@google.com stringstream stream; 10412922Sgabeblack@google.com stream << *this; 10512922Sgabeblack@google.com return stream.str(); 10612922Sgabeblack@google.com} 10712922Sgabeblack@google.com 10812922Sgabeblack@google.combool 10912922Sgabeblack@google.comoperator==(const EthAddr &left, const EthAddr &right) 11012922Sgabeblack@google.com{ 11112922Sgabeblack@google.com return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 11212922Sgabeblack@google.com} 11312922Sgabeblack@google.com 11412922Sgabeblack@google.comostream & 11512922Sgabeblack@google.comoperator<<(ostream &stream, const EthAddr &ea) 11612922Sgabeblack@google.com{ 11712922Sgabeblack@google.com const uint8_t *a = ea.addr(); 11812922Sgabeblack@google.com ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 11912922Sgabeblack@google.com return stream; 12012922Sgabeblack@google.com} 12112922Sgabeblack@google.com 12212922Sgabeblack@google.comstring 12312922Sgabeblack@google.comIpAddress::string() const 12412922Sgabeblack@google.com{ 12512922Sgabeblack@google.com stringstream stream; 12612922Sgabeblack@google.com stream << *this; 12712922Sgabeblack@google.com return stream.str(); 12812922Sgabeblack@google.com} 12912922Sgabeblack@google.com 13012922Sgabeblack@google.combool 13112922Sgabeblack@google.comoperator==(const IpAddress &left, const IpAddress &right) 13212922Sgabeblack@google.com{ 13312922Sgabeblack@google.com return left.ip() == right.ip(); 13412922Sgabeblack@google.com} 13512922Sgabeblack@google.com 13612922Sgabeblack@google.comostream & 13712922Sgabeblack@google.comoperator<<(ostream &stream, const IpAddress &ia) 13812922Sgabeblack@google.com{ 13912922Sgabeblack@google.com uint32_t ip = ia.ip(); 14012922Sgabeblack@google.com ccprintf(stream, "%x.%x.%x.%x", 14112922Sgabeblack@google.com (uint8_t)(ip >> 0), (uint8_t)(ip >> 8), 14212922Sgabeblack@google.com (uint8_t)(ip >> 16), (uint8_t)(ip >> 24)); 14312922Sgabeblack@google.com return stream; 14412922Sgabeblack@google.com} 14512922Sgabeblack@google.com 14612922Sgabeblack@google.comstring 14712922Sgabeblack@google.comIpNetmask::string() const 14812922Sgabeblack@google.com{ 14912922Sgabeblack@google.com stringstream stream; 15012922Sgabeblack@google.com stream << *this; 15112922Sgabeblack@google.com return stream.str(); 15212922Sgabeblack@google.com} 15312922Sgabeblack@google.com 15412922Sgabeblack@google.combool 15512922Sgabeblack@google.comoperator==(const IpNetmask &left, const IpNetmask &right) 15612922Sgabeblack@google.com{ 15712922Sgabeblack@google.com return (left.ip() == right.ip()) && 15812922Sgabeblack@google.com (left.netmask() == right.netmask()); 15912922Sgabeblack@google.com} 16012922Sgabeblack@google.com 16112922Sgabeblack@google.comostream & 16212922Sgabeblack@google.comoperator<<(ostream &stream, const IpNetmask &in) 16312922Sgabeblack@google.com{ 16412922Sgabeblack@google.com ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask()); 16512922Sgabeblack@google.com return stream; 16612922Sgabeblack@google.com} 16712922Sgabeblack@google.com 16812922Sgabeblack@google.comstring 16912922Sgabeblack@google.comIpWithPort::string() const 17012922Sgabeblack@google.com{ 17112922Sgabeblack@google.com stringstream stream; 17212922Sgabeblack@google.com stream << *this; 17312922Sgabeblack@google.com return stream.str(); 17412922Sgabeblack@google.com} 17512922Sgabeblack@google.com 17612922Sgabeblack@google.combool 17712922Sgabeblack@google.comoperator==(const IpWithPort &left, const IpWithPort &right) 17812922Sgabeblack@google.com{ 17912922Sgabeblack@google.com return (left.ip() == right.ip()) && (left.port() == right.port()); 18012922Sgabeblack@google.com} 18112922Sgabeblack@google.com 18212922Sgabeblack@google.comostream & 18312922Sgabeblack@google.comoperator<<(ostream &stream, const IpWithPort &iwp) 18412922Sgabeblack@google.com{ 18512922Sgabeblack@google.com ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port()); 18612922Sgabeblack@google.com return stream; 18712922Sgabeblack@google.com} 18812922Sgabeblack@google.com 18912922Sgabeblack@google.comuint16_t 19012922Sgabeblack@google.comcksum(const IpPtr &ptr) 19112922Sgabeblack@google.com{ 19212922Sgabeblack@google.com int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 19312922Sgabeblack@google.com return ip_cksum_carry(sum); 19412922Sgabeblack@google.com} 19512922Sgabeblack@google.com 19612922Sgabeblack@google.comuint16_t 19712922Sgabeblack@google.com__tu_cksum(const IpPtr &ip) 19812922Sgabeblack@google.com{ 19912922Sgabeblack@google.com int tcplen = ip->len() - ip->hlen(); 20012922Sgabeblack@google.com int sum = ip_cksum_add(ip->payload(), tcplen, 0); 20112922Sgabeblack@google.com sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 20212922Sgabeblack@google.com sum += htons(ip->ip_p + tcplen); 20312922Sgabeblack@google.com return ip_cksum_carry(sum); 20412922Sgabeblack@google.com} 20512922Sgabeblack@google.com 20612922Sgabeblack@google.comuint16_t 20712922Sgabeblack@google.comcksum(const TcpPtr &tcp) 20812922Sgabeblack@google.com{ return __tu_cksum(IpPtr(tcp.packet())); } 20912922Sgabeblack@google.com 21012922Sgabeblack@google.comuint16_t 21112922Sgabeblack@google.comcksum(const UdpPtr &udp) 21212922Sgabeblack@google.com{ return __tu_cksum(IpPtr(udp.packet())); } 21312922Sgabeblack@google.com 21412922Sgabeblack@google.combool 21512922Sgabeblack@google.comIpHdr::options(vector<const IpOpt *> &vec) const 21612922Sgabeblack@google.com{ 21712922Sgabeblack@google.com vec.clear(); 21812922Sgabeblack@google.com 21912922Sgabeblack@google.com const uint8_t *data = bytes() + sizeof(struct ip_hdr); 22012922Sgabeblack@google.com int all = hlen() - sizeof(struct ip_hdr); 22112922Sgabeblack@google.com while (all > 0) { 22212922Sgabeblack@google.com const IpOpt *opt = (const IpOpt *)data; 22312922Sgabeblack@google.com int len = opt->len(); 22412922Sgabeblack@google.com if (all < len) 22512922Sgabeblack@google.com return false; 22612922Sgabeblack@google.com 22712922Sgabeblack@google.com vec.push_back(opt); 22812922Sgabeblack@google.com all -= len; 22912922Sgabeblack@google.com data += len; 23012922Sgabeblack@google.com } 23112922Sgabeblack@google.com 23212922Sgabeblack@google.com return true; 23312922Sgabeblack@google.com} 23412922Sgabeblack@google.com 23512922Sgabeblack@google.combool 23612922Sgabeblack@google.comTcpHdr::options(vector<const TcpOpt *> &vec) const 23712922Sgabeblack@google.com{ 23812922Sgabeblack@google.com vec.clear(); 23912922Sgabeblack@google.com 24012922Sgabeblack@google.com const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 24112922Sgabeblack@google.com int all = off() - sizeof(struct tcp_hdr); 24212922Sgabeblack@google.com while (all > 0) { 24312922Sgabeblack@google.com const TcpOpt *opt = (const TcpOpt *)data; 24412922Sgabeblack@google.com int len = opt->len(); 24512922Sgabeblack@google.com if (all < len) 24612922Sgabeblack@google.com return false; 24712922Sgabeblack@google.com 24812922Sgabeblack@google.com vec.push_back(opt); 24912922Sgabeblack@google.com all -= len; 25012922Sgabeblack@google.com data += len; 25112922Sgabeblack@google.com } 25212922Sgabeblack@google.com 25312922Sgabeblack@google.com return true; 25412922Sgabeblack@google.com} 25512922Sgabeblack@google.com 25612922Sgabeblack@google.combool 25712922Sgabeblack@google.comTcpOpt::sack(vector<SackRange> &vec) const 25812922Sgabeblack@google.com{ 25912922Sgabeblack@google.com vec.clear(); 26012922Sgabeblack@google.com 26112922Sgabeblack@google.com const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 26212922Sgabeblack@google.com int all = len() - offsetof(tcp_opt, opt_data.sack); 26312922Sgabeblack@google.com while (all > 0) { 26412922Sgabeblack@google.com const uint16_t *sack = (const uint16_t *)data; 26512922Sgabeblack@google.com int len = sizeof(uint16_t) * 2; 26612922Sgabeblack@google.com if (all < len) { 26712922Sgabeblack@google.com vec.clear(); 26812922Sgabeblack@google.com return false; 26912922Sgabeblack@google.com } 27012922Sgabeblack@google.com 27112922Sgabeblack@google.com vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1]))); 27212922Sgabeblack@google.com all -= len; 27312922Sgabeblack@google.com data += len; 27412922Sgabeblack@google.com } 27512922Sgabeblack@google.com 27612922Sgabeblack@google.com return false; 27712922Sgabeblack@google.com} 27812922Sgabeblack@google.com 27912922Sgabeblack@google.comint 28012922Sgabeblack@google.comhsplit(const EthPacketPtr &ptr) 28112922Sgabeblack@google.com{ 28212922Sgabeblack@google.com int split_point = 0; 28312922Sgabeblack@google.com 28412922Sgabeblack@google.com IpPtr ip(ptr); 28512922Sgabeblack@google.com if (ip) { 28612922Sgabeblack@google.com split_point = ip.pstart(); 28712922Sgabeblack@google.com 28812922Sgabeblack@google.com TcpPtr tcp(ip); 28912922Sgabeblack@google.com if (tcp) 29012922Sgabeblack@google.com split_point = tcp.pstart(); 29112922Sgabeblack@google.com 29212922Sgabeblack@google.com UdpPtr udp(ip); 29312922Sgabeblack@google.com if (udp) 29412922Sgabeblack@google.com split_point = udp.pstart(); 29512922Sgabeblack@google.com } 29612922Sgabeblack@google.com return split_point; 29712922Sgabeblack@google.com} 29812922Sgabeblack@google.com 29912922Sgabeblack@google.com 30012922Sgabeblack@google.com/* namespace Net */ } 30112922Sgabeblack@google.com