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