inet.cc revision 2632:1bb2f91485ea
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 <sstream> 30#include <string> 31 32#include "base/cprintf.hh" 33#include "sim/host.hh" 34#include "base/inet.hh" 35 36using namespace std; 37namespace Net { 38 39EthAddr::EthAddr() 40{ 41 memset(data, 0, ETH_ADDR_LEN); 42} 43 44EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 45{ 46 *data = *ea; 47} 48 49EthAddr::EthAddr(const eth_addr &ea) 50{ 51 *data = *ea.data; 52} 53 54EthAddr::EthAddr(const std::string &addr) 55{ 56 parse(addr); 57} 58 59const EthAddr & 60EthAddr::operator=(const eth_addr &ea) 61{ 62 *data = *ea.data; 63 return *this; 64} 65 66const EthAddr & 67EthAddr::operator=(const std::string &addr) 68{ 69 parse(addr); 70 return *this; 71} 72 73void 74EthAddr::parse(const std::string &addr) 75{ 76 // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 77 // the sscanf function won't work. 78 int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 79 if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 80 &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 81 memset(data, 0xff, ETH_ADDR_LEN); 82 return; 83 } 84 85 for (int i = 0; i < ETH_ADDR_LEN; ++i) { 86 if (bytes[i] & ~0xff) { 87 memset(data, 0xff, ETH_ADDR_LEN); 88 return; 89 } 90 91 data[i] = bytes[i]; 92 } 93} 94 95string 96EthAddr::string() const 97{ 98 stringstream stream; 99 stream << *this; 100 return stream.str(); 101} 102 103bool 104operator==(const EthAddr &left, const EthAddr &right) 105{ 106 return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 107} 108 109ostream & 110operator<<(ostream &stream, const EthAddr &ea) 111{ 112 const uint8_t *a = ea.addr(); 113 ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 114 return stream; 115} 116 117uint16_t 118cksum(const IpPtr &ptr) 119{ 120 int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 121 return ip_cksum_carry(sum); 122} 123 124uint16_t 125__tu_cksum(const IpPtr &ip) 126{ 127 int tcplen = ip->len() - ip->hlen(); 128 int sum = ip_cksum_add(ip->payload(), tcplen, 0); 129 sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 130 sum += htons(ip->ip_p + tcplen); 131 return ip_cksum_carry(sum); 132} 133 134uint16_t 135cksum(const TcpPtr &tcp) 136{ return __tu_cksum(IpPtr(tcp.packet())); } 137 138uint16_t 139cksum(const UdpPtr &udp) 140{ return __tu_cksum(IpPtr(udp.packet())); } 141 142bool 143IpHdr::options(vector<const IpOpt *> &vec) const 144{ 145 vec.clear(); 146 147 const uint8_t *data = bytes() + sizeof(struct ip_hdr); 148 int all = hlen() - sizeof(struct ip_hdr); 149 while (all > 0) { 150 const IpOpt *opt = (const IpOpt *)data; 151 int len = opt->len(); 152 if (all < len) 153 return false; 154 155 vec.push_back(opt); 156 all -= len; 157 data += len; 158 } 159 160 return true; 161} 162 163bool 164TcpHdr::options(vector<const TcpOpt *> &vec) const 165{ 166 vec.clear(); 167 168 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 169 int all = off() - sizeof(struct tcp_hdr); 170 while (all > 0) { 171 const TcpOpt *opt = (const TcpOpt *)data; 172 int len = opt->len(); 173 if (all < len) 174 return false; 175 176 vec.push_back(opt); 177 all -= len; 178 data += len; 179 } 180 181 return true; 182} 183 184bool 185TcpOpt::sack(vector<SackRange> &vec) const 186{ 187 vec.clear(); 188 189 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 190 int all = len() - offsetof(tcp_opt, opt_data.sack); 191 while (all > 0) { 192 const uint16_t *sack = (const uint16_t *)data; 193 int len = sizeof(uint16_t) * 2; 194 if (all < len) { 195 vec.clear(); 196 return false; 197 } 198 199 vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1]))); 200 all -= len; 201 data += len; 202 } 203 204 return false; 205} 206 207/* namespace Net */ } 208