inet.cc revision 6712
12SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292SN/A */ 302SN/A 316712Snate@binkert.org#include <cstdio> 322SN/A#include <sstream> 332SN/A#include <string> 342SN/A 3556SN/A#include "base/cprintf.hh" 366216Snate@binkert.org#include "base/inet.hh" 376214Snate@binkert.org#include "base/types.hh" 382SN/A 391078SN/Ausing namespace std; 401114SN/Anamespace Net { 411114SN/A 421114SN/AEthAddr::EthAddr() 431114SN/A{ 441114SN/A memset(data, 0, ETH_ADDR_LEN); 451114SN/A} 461114SN/A 471114SN/AEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 481114SN/A{ 491114SN/A *data = *ea; 501114SN/A} 511114SN/A 521114SN/AEthAddr::EthAddr(const eth_addr &ea) 531114SN/A{ 541114SN/A *data = *ea.data; 551114SN/A} 561114SN/A 571114SN/AEthAddr::EthAddr(const std::string &addr) 581114SN/A{ 591114SN/A parse(addr); 601114SN/A} 611114SN/A 621114SN/Aconst EthAddr & 631114SN/AEthAddr::operator=(const eth_addr &ea) 641114SN/A{ 651114SN/A *data = *ea.data; 661114SN/A return *this; 671114SN/A} 681114SN/A 691114SN/Aconst EthAddr & 701114SN/AEthAddr::operator=(const std::string &addr) 711114SN/A{ 721114SN/A parse(addr); 731114SN/A return *this; 741114SN/A} 751114SN/A 761114SN/Avoid 771114SN/AEthAddr::parse(const std::string &addr) 781114SN/A{ 791114SN/A // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 801114SN/A // the sscanf function won't work. 811114SN/A int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 821114SN/A if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 831114SN/A &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 841114SN/A memset(data, 0xff, ETH_ADDR_LEN); 851114SN/A return; 861114SN/A } 871114SN/A 881114SN/A for (int i = 0; i < ETH_ADDR_LEN; ++i) { 891114SN/A if (bytes[i] & ~0xff) { 901114SN/A memset(data, 0xff, ETH_ADDR_LEN); 911114SN/A return; 921114SN/A } 931114SN/A 941114SN/A data[i] = bytes[i]; 951114SN/A } 961114SN/A} 971114SN/A 982SN/Astring 991114SN/AEthAddr::string() const 1002SN/A{ 1012SN/A stringstream stream; 1021114SN/A stream << *this; 1032SN/A return stream.str(); 1042SN/A} 1052SN/A 1061114SN/Abool 1071114SN/Aoperator==(const EthAddr &left, const EthAddr &right) 1082SN/A{ 1091114SN/A return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 1101114SN/A} 1111114SN/A 1121114SN/Aostream & 1131114SN/Aoperator<<(ostream &stream, const EthAddr &ea) 1141114SN/A{ 1151114SN/A const uint8_t *a = ea.addr(); 1161114SN/A ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 1171114SN/A return stream; 1182SN/A} 1192SN/A 1201078SN/Auint16_t 1211114SN/Acksum(const IpPtr &ptr) 1221078SN/A{ 1231114SN/A int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 1241114SN/A return ip_cksum_carry(sum); 1251078SN/A} 1261114SN/A 1271114SN/Auint16_t 1281114SN/A__tu_cksum(const IpPtr &ip) 1291114SN/A{ 1301114SN/A int tcplen = ip->len() - ip->hlen(); 1311114SN/A int sum = ip_cksum_add(ip->payload(), tcplen, 0); 1321114SN/A sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 1331114SN/A sum += htons(ip->ip_p + tcplen); 1341114SN/A return ip_cksum_carry(sum); 1351114SN/A} 1361114SN/A 1371114SN/Auint16_t 1381114SN/Acksum(const TcpPtr &tcp) 1391114SN/A{ return __tu_cksum(IpPtr(tcp.packet())); } 1401114SN/A 1411114SN/Auint16_t 1421114SN/Acksum(const UdpPtr &udp) 1431114SN/A{ return __tu_cksum(IpPtr(udp.packet())); } 1441114SN/A 1451114SN/Abool 1461114SN/AIpHdr::options(vector<const IpOpt *> &vec) const 1471114SN/A{ 1481114SN/A vec.clear(); 1491114SN/A 1501114SN/A const uint8_t *data = bytes() + sizeof(struct ip_hdr); 1511114SN/A int all = hlen() - sizeof(struct ip_hdr); 1521114SN/A while (all > 0) { 1531114SN/A const IpOpt *opt = (const IpOpt *)data; 1541114SN/A int len = opt->len(); 1551114SN/A if (all < len) 1561114SN/A return false; 1571114SN/A 1581114SN/A vec.push_back(opt); 1591114SN/A all -= len; 1601114SN/A data += len; 1611114SN/A } 1621114SN/A 1631114SN/A return true; 1641114SN/A} 1651114SN/A 1661114SN/Abool 1671114SN/ATcpHdr::options(vector<const TcpOpt *> &vec) const 1681114SN/A{ 1691114SN/A vec.clear(); 1701114SN/A 1711114SN/A const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 1721114SN/A int all = off() - sizeof(struct tcp_hdr); 1731114SN/A while (all > 0) { 1741114SN/A const TcpOpt *opt = (const TcpOpt *)data; 1751114SN/A int len = opt->len(); 1761114SN/A if (all < len) 1771114SN/A return false; 1781114SN/A 1791114SN/A vec.push_back(opt); 1801114SN/A all -= len; 1811114SN/A data += len; 1821114SN/A } 1831114SN/A 1841114SN/A return true; 1851114SN/A} 1861114SN/A 1871114SN/Abool 1881114SN/ATcpOpt::sack(vector<SackRange> &vec) const 1891114SN/A{ 1901114SN/A vec.clear(); 1911114SN/A 1921114SN/A const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 1931114SN/A int all = len() - offsetof(tcp_opt, opt_data.sack); 1941114SN/A while (all > 0) { 1951114SN/A const uint16_t *sack = (const uint16_t *)data; 1961114SN/A int len = sizeof(uint16_t) * 2; 1971114SN/A if (all < len) { 1981114SN/A vec.clear(); 1991114SN/A return false; 2001114SN/A } 2011114SN/A 2021114SN/A vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1]))); 2031114SN/A all -= len; 2041114SN/A data += len; 2051114SN/A } 2061114SN/A 2071114SN/A return false; 2081114SN/A} 2091114SN/A 2105782Ssaidi@eecs.umich.eduint 2115782Ssaidi@eecs.umich.eduhsplit(const EthPacketPtr &ptr) 2125782Ssaidi@eecs.umich.edu{ 2135782Ssaidi@eecs.umich.edu int split_point = 0; 2145782Ssaidi@eecs.umich.edu 2155782Ssaidi@eecs.umich.edu IpPtr ip(ptr); 2165782Ssaidi@eecs.umich.edu if (ip) { 2175782Ssaidi@eecs.umich.edu split_point = ip.pstart(); 2185782Ssaidi@eecs.umich.edu 2195782Ssaidi@eecs.umich.edu TcpPtr tcp(ip); 2205782Ssaidi@eecs.umich.edu if (tcp) 2215782Ssaidi@eecs.umich.edu split_point = tcp.pstart(); 2225782Ssaidi@eecs.umich.edu 2235782Ssaidi@eecs.umich.edu UdpPtr udp(ip); 2245782Ssaidi@eecs.umich.edu if (udp) 2255782Ssaidi@eecs.umich.edu split_point = udp.pstart(); 2265782Ssaidi@eecs.umich.edu } 2275782Ssaidi@eecs.umich.edu return split_point; 2285782Ssaidi@eecs.umich.edu} 2295782Ssaidi@eecs.umich.edu 2305782Ssaidi@eecs.umich.edu 2311114SN/A/* namespace Net */ } 232