inet.cc revision 1762
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <cstdio> 30#include <sstream> 31#include <string> 32 33#include "base/cprintf.hh" 34#include "sim/host.hh" 35#include "base/inet.hh" 36 37using namespace std; 38namespace Net { 39 40EthAddr::EthAddr() 41{ 42 memset(data, 0, ETH_ADDR_LEN); 43} 44 45EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 46{ 47 *data = *ea; 48} 49 50EthAddr::EthAddr(const eth_addr &ea) 51{ 52 *data = *ea.data; 53} 54 55EthAddr::EthAddr(const std::string &addr) 56{ 57 parse(addr); 58} 59 60const EthAddr & 61EthAddr::operator=(const eth_addr &ea) 62{ 63 *data = *ea.data; 64 return *this; 65} 66 67const EthAddr & 68EthAddr::operator=(const std::string &addr) 69{ 70 parse(addr); 71 return *this; 72} 73 74void 75EthAddr::parse(const std::string &addr) 76{ 77 // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 78 // the sscanf function won't work. 79 int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 80 if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 81 &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 82 memset(data, 0xff, ETH_ADDR_LEN); 83 return; 84 } 85 86 for (int i = 0; i < ETH_ADDR_LEN; ++i) { 87 if (bytes[i] & ~0xff) { 88 memset(data, 0xff, ETH_ADDR_LEN); 89 return; 90 } 91 92 data[i] = bytes[i]; 93 } 94} 95 96string 97EthAddr::string() const 98{ 99 stringstream stream; 100 stream << *this; 101 return stream.str(); 102} 103 104bool 105operator==(const EthAddr &left, const EthAddr &right) 106{ 107 return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 108} 109 110ostream & 111operator<<(ostream &stream, const EthAddr &ea) 112{ 113 const uint8_t *a = ea.addr(); 114 ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 115 return stream; 116} 117 118uint16_t 119cksum(const IpPtr &ptr) 120{ 121 int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 122 return ip_cksum_carry(sum); 123} 124 125uint16_t 126__tu_cksum(const IpPtr &ip) 127{ 128 int tcplen = ip->len() - ip->hlen(); 129 int sum = ip_cksum_add(ip->payload(), tcplen, 0); 130 sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 131 sum += htons(ip->ip_p + tcplen); 132 return ip_cksum_carry(sum); 133} 134 135uint16_t 136cksum(const TcpPtr &tcp) 137{ return __tu_cksum(IpPtr(tcp.packet())); } 138 139uint16_t 140cksum(const UdpPtr &udp) 141{ return __tu_cksum(IpPtr(udp.packet())); } 142 143bool 144IpHdr::options(vector<const IpOpt *> &vec) const 145{ 146 vec.clear(); 147 148 const uint8_t *data = bytes() + sizeof(struct ip_hdr); 149 int all = hlen() - sizeof(struct ip_hdr); 150 while (all > 0) { 151 const IpOpt *opt = (const IpOpt *)data; 152 int len = opt->len(); 153 if (all < len) 154 return false; 155 156 vec.push_back(opt); 157 all -= len; 158 data += len; 159 } 160 161 return true; 162} 163 164bool 165TcpHdr::options(vector<const TcpOpt *> &vec) const 166{ 167 vec.clear(); 168 169 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 170 int all = off() - sizeof(struct tcp_hdr); 171 while (all > 0) { 172 const TcpOpt *opt = (const TcpOpt *)data; 173 int len = opt->len(); 174 if (all < len) 175 return false; 176 177 vec.push_back(opt); 178 all -= len; 179 data += len; 180 } 181 182 return true; 183} 184 185bool 186TcpOpt::sack(vector<SackRange> &vec) const 187{ 188 vec.clear(); 189 190 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 191 int all = len() - offsetof(tcp_opt, opt_data.sack); 192 while (all > 0) { 193 const uint16_t *sack = (const uint16_t *)data; 194 int len = sizeof(uint16_t) * 2; 195 if (all < len) { 196 vec.clear(); 197 return false; 198 } 199 200 vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1]))); 201 all -= len; 202 data += len; 203 } 204 205 return false; 206} 207 208/* namespace Net */ } 209