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