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