inet.cc revision 7778:6a7207241112
112922Sgabeblack@google.com/*
212922Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
312922Sgabeblack@google.com * Copyright (c) 2010 Advanced Micro Devices, Inc.
412922Sgabeblack@google.com * All rights reserved.
512922Sgabeblack@google.com *
612922Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
712922Sgabeblack@google.com * modification, are permitted provided that the following conditions are
812922Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
912922Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1012922Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1112922Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1212922Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1312922Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1412922Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1512922Sgabeblack@google.com * this software without specific prior written permission.
1612922Sgabeblack@google.com *
1712922Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1812922Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1912922Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2012922Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2112922Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2212922Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2312922Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2412922Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2512922Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2612922Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2712922Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2812922Sgabeblack@google.com *
2912922Sgabeblack@google.com * Authors: Nathan Binkert
3012922Sgabeblack@google.com *          Gabe Black
3112922Sgabeblack@google.com */
3212922Sgabeblack@google.com
3312922Sgabeblack@google.com#include <cstdio>
3412922Sgabeblack@google.com#include <sstream>
3512922Sgabeblack@google.com#include <string>
3612922Sgabeblack@google.com
3712922Sgabeblack@google.com#include "base/cprintf.hh"
3812922Sgabeblack@google.com#include "base/inet.hh"
3912922Sgabeblack@google.com#include "base/types.hh"
4012922Sgabeblack@google.com
4112922Sgabeblack@google.comusing namespace std;
4212922Sgabeblack@google.comnamespace Net {
4312922Sgabeblack@google.com
4412922Sgabeblack@google.comEthAddr::EthAddr()
4512922Sgabeblack@google.com{
4612922Sgabeblack@google.com    memset(data, 0, ETH_ADDR_LEN);
4712922Sgabeblack@google.com}
4812922Sgabeblack@google.com
4912922Sgabeblack@google.comEthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
5012922Sgabeblack@google.com{
5112922Sgabeblack@google.com    *data = *ea;
5212922Sgabeblack@google.com}
5312922Sgabeblack@google.com
5412922Sgabeblack@google.comEthAddr::EthAddr(const eth_addr &ea)
5512922Sgabeblack@google.com{
5612922Sgabeblack@google.com    *data = *ea.data;
5712922Sgabeblack@google.com}
5812922Sgabeblack@google.com
5912922Sgabeblack@google.comEthAddr::EthAddr(const std::string &addr)
6012922Sgabeblack@google.com{
6112922Sgabeblack@google.com    parse(addr);
6212922Sgabeblack@google.com}
6312922Sgabeblack@google.com
6412922Sgabeblack@google.comconst EthAddr &
6512922Sgabeblack@google.comEthAddr::operator=(const eth_addr &ea)
6612922Sgabeblack@google.com{
6712922Sgabeblack@google.com    *data = *ea.data;
6812922Sgabeblack@google.com    return *this;
6912922Sgabeblack@google.com}
7012922Sgabeblack@google.com
7112922Sgabeblack@google.comconst EthAddr &
7212922Sgabeblack@google.comEthAddr::operator=(const std::string &addr)
7312922Sgabeblack@google.com{
7412922Sgabeblack@google.com    parse(addr);
7512922Sgabeblack@google.com    return *this;
7612922Sgabeblack@google.com}
7712922Sgabeblack@google.com
7812922Sgabeblack@google.comvoid
7912922Sgabeblack@google.comEthAddr::parse(const std::string &addr)
8012922Sgabeblack@google.com{
8112922Sgabeblack@google.com    // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
8212922Sgabeblack@google.com    // the sscanf function won't work.
8312922Sgabeblack@google.com    int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
8412922Sgabeblack@google.com    if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
8512922Sgabeblack@google.com               &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
8612922Sgabeblack@google.com        memset(data, 0xff, ETH_ADDR_LEN);
8712922Sgabeblack@google.com        return;
8812922Sgabeblack@google.com    }
8912922Sgabeblack@google.com
9012922Sgabeblack@google.com    for (int i = 0; i < ETH_ADDR_LEN; ++i) {
9112922Sgabeblack@google.com        if (bytes[i] & ~0xff) {
9212922Sgabeblack@google.com            memset(data, 0xff, ETH_ADDR_LEN);
9312922Sgabeblack@google.com            return;
9412922Sgabeblack@google.com        }
9512922Sgabeblack@google.com
9612922Sgabeblack@google.com        data[i] = bytes[i];
9712922Sgabeblack@google.com    }
9812922Sgabeblack@google.com}
9912922Sgabeblack@google.com
10012922Sgabeblack@google.comstring
10112922Sgabeblack@google.comEthAddr::string() const
10212922Sgabeblack@google.com{
10312922Sgabeblack@google.com    stringstream stream;
10412922Sgabeblack@google.com    stream << *this;
10512922Sgabeblack@google.com    return stream.str();
10612922Sgabeblack@google.com}
10712922Sgabeblack@google.com
10812922Sgabeblack@google.combool
10912922Sgabeblack@google.comoperator==(const EthAddr &left, const EthAddr &right)
11012922Sgabeblack@google.com{
11112922Sgabeblack@google.com    return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
11212922Sgabeblack@google.com}
11312922Sgabeblack@google.com
11412922Sgabeblack@google.comostream &
11512922Sgabeblack@google.comoperator<<(ostream &stream, const EthAddr &ea)
11612922Sgabeblack@google.com{
11712922Sgabeblack@google.com    const uint8_t *a = ea.addr();
11812922Sgabeblack@google.com    ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
11912922Sgabeblack@google.com    return stream;
12012922Sgabeblack@google.com}
12112922Sgabeblack@google.com
12212922Sgabeblack@google.comstring
12312922Sgabeblack@google.comIpAddress::string() const
12412922Sgabeblack@google.com{
12512922Sgabeblack@google.com    stringstream stream;
12612922Sgabeblack@google.com    stream << *this;
12712922Sgabeblack@google.com    return stream.str();
12812922Sgabeblack@google.com}
12912922Sgabeblack@google.com
13012922Sgabeblack@google.combool
13112922Sgabeblack@google.comoperator==(const IpAddress &left, const IpAddress &right)
13212922Sgabeblack@google.com{
13312922Sgabeblack@google.com    return left.ip() == right.ip();
13412922Sgabeblack@google.com}
13512922Sgabeblack@google.com
13612922Sgabeblack@google.comostream &
13712922Sgabeblack@google.comoperator<<(ostream &stream, const IpAddress &ia)
13812922Sgabeblack@google.com{
13912922Sgabeblack@google.com    uint32_t ip = ia.ip();
14012922Sgabeblack@google.com    ccprintf(stream, "%x.%x.%x.%x",
14112922Sgabeblack@google.com            (uint8_t)(ip >> 0),  (uint8_t)(ip >> 8),
14212922Sgabeblack@google.com            (uint8_t)(ip >> 16), (uint8_t)(ip >> 24));
14312922Sgabeblack@google.com    return stream;
14412922Sgabeblack@google.com}
14512922Sgabeblack@google.com
14612922Sgabeblack@google.comstring
14712922Sgabeblack@google.comIpNetmask::string() const
14812922Sgabeblack@google.com{
14912922Sgabeblack@google.com    stringstream stream;
15012922Sgabeblack@google.com    stream << *this;
15112922Sgabeblack@google.com    return stream.str();
15212922Sgabeblack@google.com}
15312922Sgabeblack@google.com
15412922Sgabeblack@google.combool
15512922Sgabeblack@google.comoperator==(const IpNetmask &left, const IpNetmask &right)
15612922Sgabeblack@google.com{
15712922Sgabeblack@google.com    return (left.ip() == right.ip()) &&
15812922Sgabeblack@google.com        (left.netmask() == right.netmask());
15912922Sgabeblack@google.com}
16012922Sgabeblack@google.com
16112922Sgabeblack@google.comostream &
16212922Sgabeblack@google.comoperator<<(ostream &stream, const IpNetmask &in)
16312922Sgabeblack@google.com{
16412922Sgabeblack@google.com    ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
16512922Sgabeblack@google.com    return stream;
16612922Sgabeblack@google.com}
16712922Sgabeblack@google.com
16812922Sgabeblack@google.comstring
16912922Sgabeblack@google.comIpWithPort::string() const
17012922Sgabeblack@google.com{
17112922Sgabeblack@google.com    stringstream stream;
17212922Sgabeblack@google.com    stream << *this;
17312922Sgabeblack@google.com    return stream.str();
17412922Sgabeblack@google.com}
17512922Sgabeblack@google.com
17612922Sgabeblack@google.combool
17712922Sgabeblack@google.comoperator==(const IpWithPort &left, const IpWithPort &right)
17812922Sgabeblack@google.com{
17912922Sgabeblack@google.com    return (left.ip() == right.ip()) && (left.port() == right.port());
18012922Sgabeblack@google.com}
18112922Sgabeblack@google.com
18212922Sgabeblack@google.comostream &
18312922Sgabeblack@google.comoperator<<(ostream &stream, const IpWithPort &iwp)
18412922Sgabeblack@google.com{
18512922Sgabeblack@google.com    ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
18612922Sgabeblack@google.com    return stream;
18712922Sgabeblack@google.com}
18812922Sgabeblack@google.com
18912922Sgabeblack@google.comuint16_t
19012922Sgabeblack@google.comcksum(const IpPtr &ptr)
19112922Sgabeblack@google.com{
19212922Sgabeblack@google.com    int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
19312922Sgabeblack@google.com    return ip_cksum_carry(sum);
19412922Sgabeblack@google.com}
19512922Sgabeblack@google.com
19612922Sgabeblack@google.comuint16_t
19712922Sgabeblack@google.com__tu_cksum(const IpPtr &ip)
19812922Sgabeblack@google.com{
19912922Sgabeblack@google.com    int tcplen = ip->len() - ip->hlen();
20012922Sgabeblack@google.com    int sum = ip_cksum_add(ip->payload(), tcplen, 0);
20112922Sgabeblack@google.com    sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
20212922Sgabeblack@google.com    sum += htons(ip->ip_p + tcplen);
20312922Sgabeblack@google.com    return ip_cksum_carry(sum);
20412922Sgabeblack@google.com}
20512922Sgabeblack@google.com
20612922Sgabeblack@google.comuint16_t
20712922Sgabeblack@google.comcksum(const TcpPtr &tcp)
20812922Sgabeblack@google.com{ return __tu_cksum(IpPtr(tcp.packet())); }
20912922Sgabeblack@google.com
21012922Sgabeblack@google.comuint16_t
21112922Sgabeblack@google.comcksum(const UdpPtr &udp)
21212922Sgabeblack@google.com{ return __tu_cksum(IpPtr(udp.packet())); }
21312922Sgabeblack@google.com
21412922Sgabeblack@google.combool
21512922Sgabeblack@google.comIpHdr::options(vector<const IpOpt *> &vec) const
21612922Sgabeblack@google.com{
21712922Sgabeblack@google.com    vec.clear();
21812922Sgabeblack@google.com
21912922Sgabeblack@google.com    const uint8_t *data = bytes() + sizeof(struct ip_hdr);
22012922Sgabeblack@google.com    int all = hlen() - sizeof(struct ip_hdr);
22112922Sgabeblack@google.com    while (all > 0) {
22212922Sgabeblack@google.com        const IpOpt *opt = (const IpOpt *)data;
22312922Sgabeblack@google.com        int len = opt->len();
22412922Sgabeblack@google.com        if (all < len)
22512922Sgabeblack@google.com            return false;
22612922Sgabeblack@google.com
22712922Sgabeblack@google.com        vec.push_back(opt);
22812922Sgabeblack@google.com        all -= len;
22912922Sgabeblack@google.com        data += len;
23012922Sgabeblack@google.com    }
23112922Sgabeblack@google.com
23212922Sgabeblack@google.com    return true;
23312922Sgabeblack@google.com}
23412922Sgabeblack@google.com
23512922Sgabeblack@google.combool
23612922Sgabeblack@google.comTcpHdr::options(vector<const TcpOpt *> &vec) const
23712922Sgabeblack@google.com{
23812922Sgabeblack@google.com    vec.clear();
23912922Sgabeblack@google.com
24012922Sgabeblack@google.com    const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
24112922Sgabeblack@google.com    int all = off() - sizeof(struct tcp_hdr);
24212922Sgabeblack@google.com    while (all > 0) {
24312922Sgabeblack@google.com        const TcpOpt *opt = (const TcpOpt *)data;
24412922Sgabeblack@google.com        int len = opt->len();
24512922Sgabeblack@google.com        if (all < len)
24612922Sgabeblack@google.com            return false;
24712922Sgabeblack@google.com
24812922Sgabeblack@google.com        vec.push_back(opt);
24912922Sgabeblack@google.com        all -= len;
25012922Sgabeblack@google.com        data += len;
25112922Sgabeblack@google.com    }
25212922Sgabeblack@google.com
25312922Sgabeblack@google.com    return true;
25412922Sgabeblack@google.com}
25512922Sgabeblack@google.com
25612922Sgabeblack@google.combool
25712922Sgabeblack@google.comTcpOpt::sack(vector<SackRange> &vec) const
25812922Sgabeblack@google.com{
25912922Sgabeblack@google.com    vec.clear();
26012922Sgabeblack@google.com
26112922Sgabeblack@google.com    const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
26212922Sgabeblack@google.com    int all = len() - offsetof(tcp_opt, opt_data.sack);
26312922Sgabeblack@google.com    while (all > 0) {
26412922Sgabeblack@google.com        const uint16_t *sack = (const uint16_t *)data;
26512922Sgabeblack@google.com        int len = sizeof(uint16_t) * 2;
26612922Sgabeblack@google.com        if (all < len) {
26712922Sgabeblack@google.com            vec.clear();
26812922Sgabeblack@google.com            return false;
26912922Sgabeblack@google.com        }
27012922Sgabeblack@google.com
27112922Sgabeblack@google.com        vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
27212922Sgabeblack@google.com        all -= len;
27312922Sgabeblack@google.com        data += len;
27412922Sgabeblack@google.com    }
27512922Sgabeblack@google.com
27612922Sgabeblack@google.com    return false;
27712922Sgabeblack@google.com}
27812922Sgabeblack@google.com
27912922Sgabeblack@google.comint
28012922Sgabeblack@google.comhsplit(const EthPacketPtr &ptr)
28112922Sgabeblack@google.com{
28212922Sgabeblack@google.com    int split_point = 0;
28312922Sgabeblack@google.com
28412922Sgabeblack@google.com    IpPtr ip(ptr);
28512922Sgabeblack@google.com    if (ip) {
28612922Sgabeblack@google.com        split_point = ip.pstart();
28712922Sgabeblack@google.com
28812922Sgabeblack@google.com        TcpPtr tcp(ip);
28912922Sgabeblack@google.com        if (tcp)
29012922Sgabeblack@google.com            split_point = tcp.pstart();
29112922Sgabeblack@google.com
29212922Sgabeblack@google.com        UdpPtr udp(ip);
29312922Sgabeblack@google.com        if (udp)
29412922Sgabeblack@google.com            split_point = udp.pstart();
29512922Sgabeblack@google.com    }
29612922Sgabeblack@google.com    return split_point;
29712922Sgabeblack@google.com}
29812922Sgabeblack@google.com
29912922Sgabeblack@google.com
30012922Sgabeblack@google.com/* namespace Net */ }
30112922Sgabeblack@google.com