inet.cc revision 8607:5fb918115c07
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * Copyright (c) 2010 Advanced Micro Devices, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Nathan Binkert 30 * Gabe Black 31 */ 32 33#include <cstddef> 34#include <cstdio> 35#include <sstream> 36#include <string> 37 38#include "base/cprintf.hh" 39#include "base/inet.hh" 40#include "base/types.hh" 41 42using namespace std; 43namespace Net { 44 45EthAddr::EthAddr() 46{ 47 memset(data, 0, ETH_ADDR_LEN); 48} 49 50EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN]) 51{ 52 *data = *ea; 53} 54 55EthAddr::EthAddr(const eth_addr &ea) 56{ 57 *data = *ea.data; 58} 59 60EthAddr::EthAddr(const std::string &addr) 61{ 62 parse(addr); 63} 64 65const EthAddr & 66EthAddr::operator=(const eth_addr &ea) 67{ 68 *data = *ea.data; 69 return *this; 70} 71 72const EthAddr & 73EthAddr::operator=(const std::string &addr) 74{ 75 parse(addr); 76 return *this; 77} 78 79void 80EthAddr::parse(const std::string &addr) 81{ 82 // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise 83 // the sscanf function won't work. 84 int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1]; 85 if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1], 86 &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) { 87 memset(data, 0xff, ETH_ADDR_LEN); 88 return; 89 } 90 91 for (int i = 0; i < ETH_ADDR_LEN; ++i) { 92 if (bytes[i] & ~0xff) { 93 memset(data, 0xff, ETH_ADDR_LEN); 94 return; 95 } 96 97 data[i] = bytes[i]; 98 } 99} 100 101string 102EthAddr::string() const 103{ 104 stringstream stream; 105 stream << *this; 106 return stream.str(); 107} 108 109bool 110operator==(const EthAddr &left, const EthAddr &right) 111{ 112 return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN); 113} 114 115ostream & 116operator<<(ostream &stream, const EthAddr &ea) 117{ 118 const uint8_t *a = ea.addr(); 119 ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]); 120 return stream; 121} 122 123string 124IpAddress::string() const 125{ 126 stringstream stream; 127 stream << *this; 128 return stream.str(); 129} 130 131bool 132operator==(const IpAddress &left, const IpAddress &right) 133{ 134 return left.ip() == right.ip(); 135} 136 137ostream & 138operator<<(ostream &stream, const IpAddress &ia) 139{ 140 uint32_t ip = ia.ip(); 141 ccprintf(stream, "%x.%x.%x.%x", 142 (uint8_t)(ip >> 24), (uint8_t)(ip >> 16), 143 (uint8_t)(ip >> 8), (uint8_t)(ip >> 0)); 144 return stream; 145} 146 147string 148IpNetmask::string() const 149{ 150 stringstream stream; 151 stream << *this; 152 return stream.str(); 153} 154 155bool 156operator==(const IpNetmask &left, const IpNetmask &right) 157{ 158 return (left.ip() == right.ip()) && 159 (left.netmask() == right.netmask()); 160} 161 162ostream & 163operator<<(ostream &stream, const IpNetmask &in) 164{ 165 ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask()); 166 return stream; 167} 168 169string 170IpWithPort::string() const 171{ 172 stringstream stream; 173 stream << *this; 174 return stream.str(); 175} 176 177bool 178operator==(const IpWithPort &left, const IpWithPort &right) 179{ 180 return (left.ip() == right.ip()) && (left.port() == right.port()); 181} 182 183ostream & 184operator<<(ostream &stream, const IpWithPort &iwp) 185{ 186 ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port()); 187 return stream; 188} 189 190uint16_t 191cksum(const IpPtr &ptr) 192{ 193 int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0); 194 return ip_cksum_carry(sum); 195} 196 197uint16_t 198__tu_cksum(const IpPtr &ip) 199{ 200 int tcplen = ip->len() - ip->hlen(); 201 int sum = ip_cksum_add(ip->payload(), tcplen, 0); 202 sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination 203 sum += htons(ip->ip_p + tcplen); 204 return ip_cksum_carry(sum); 205} 206 207uint16_t 208cksum(const TcpPtr &tcp) 209{ return __tu_cksum(IpPtr(tcp.packet())); } 210 211uint16_t 212cksum(const UdpPtr &udp) 213{ return __tu_cksum(IpPtr(udp.packet())); } 214 215bool 216IpHdr::options(vector<const IpOpt *> &vec) const 217{ 218 vec.clear(); 219 220 const uint8_t *data = bytes() + sizeof(struct ip_hdr); 221 int all = hlen() - sizeof(struct ip_hdr); 222 while (all > 0) { 223 const IpOpt *opt = (const IpOpt *)data; 224 int len = opt->len(); 225 if (all < len) 226 return false; 227 228 vec.push_back(opt); 229 all -= len; 230 data += len; 231 } 232 233 return true; 234} 235 236bool 237TcpHdr::options(vector<const TcpOpt *> &vec) const 238{ 239 vec.clear(); 240 241 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 242 int all = off() - sizeof(struct tcp_hdr); 243 while (all > 0) { 244 const TcpOpt *opt = (const TcpOpt *)data; 245 int len = opt->len(); 246 if (all < len) 247 return false; 248 249 vec.push_back(opt); 250 all -= len; 251 data += len; 252 } 253 254 return true; 255} 256 257bool 258TcpOpt::sack(vector<SackRange> &vec) const 259{ 260 vec.clear(); 261 262 const uint8_t *data = bytes() + sizeof(struct tcp_hdr); 263 int all = len() - offsetof(tcp_opt, opt_data.sack); 264 while (all > 0) { 265 const uint16_t *sack = (const uint16_t *)data; 266 int len = sizeof(uint16_t) * 2; 267 if (all < len) { 268 vec.clear(); 269 return false; 270 } 271 272 vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1]))); 273 all -= len; 274 data += len; 275 } 276 277 return false; 278} 279 280int 281hsplit(const EthPacketPtr &ptr) 282{ 283 int split_point = 0; 284 285 IpPtr ip(ptr); 286 if (ip) { 287 split_point = ip.pstart(); 288 289 TcpPtr tcp(ip); 290 if (tcp) 291 split_point = tcp.pstart(); 292 293 UdpPtr udp(ip); 294 if (udp) 295 split_point = udp.pstart(); 296 } 297 return split_point; 298} 299 300 301} // namespace Net 302