1 //
2 // Copyright (C) 2008-2011 Institute of Telematics, Karlsruhe Institute of Technology (KIT)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18
19 #include "EthernetPacket.h"
20
21 AnonPrimitive* EthernetPacket::anonSourceMac = NULL;
22 AnonPrimitive* EthernetPacket::anonDestMac = NULL;
23 AnonPrimitive* EthernetPacket::anonType = NULL;
24
EthernetPacket(void)25 EthernetPacket::EthernetPacket(void)
26 {
27 protocol = Packet::PROTO_ETHERNET;
28 memset (&header, 0, sizeof (ETHERNET_HEADER));
29 }
30
~EthernetPacket(void)31 EthernetPacket::~EthernetPacket(void)
32 {
33 }
34
parsePacket()35 bool EthernetPacket::parsePacket()
36 {
37 if (buffer == NULL) return false;
38
39 if ((uint32_t)size < sizeof (ETHERNET_HEADER)) {
40 cerr << "packet too small to contain ethernet header (" << size << "bytes)" << std::endl;
41 return false;
42 }
43
44 memcpy (&header, buffer, sizeof (ETHERNET_HEADER));
45 header.type = swap16 (header.type);
46
47 switch (header.type) {
48 case ETHERTYPE_IP: nextProtocol = Packet::PROTO_IP; break;
49 case ETHERTYPE_ARP: nextProtocol = Packet::PROTO_ARP; break;
50 case ETHERTYPE_IPV6: nextProtocol = Packet::PROTO_IPV6; break;
51 case ETHERTYPE_VLAN: nextProtocol = Packet::PROTO_VLAN; break;
52 case ETHERTYPE_UNKNOWN:
53 default: nextProtocol = Packet::PROTO_DATA_PAYLOAD; break;
54 }
55
56 layersize = sizeof (ETHERNET_HEADER);
57 return true;
58 }
59
getSourceMac()60 MAC_ADDR EthernetPacket::getSourceMac ()
61 {
62 MAC_ADDR ret = {{0}};
63 memcpy (&ret, &header.sourcehost, ETHER_ADDR_LEN);
64 return ret;
65 }
66
getDestMac()67 MAC_ADDR EthernetPacket::getDestMac ()
68 {
69 MAC_ADDR ret = {{0}};
70 memcpy (&ret, &header.desthost, ETHER_ADDR_LEN);
71 return ret;
72 }
73
getType()74 uint16_t EthernetPacket::getType ()
75 {
76 return header.type;
77 }
78
setSourceMac(MAC_ADDR mac)79 void EthernetPacket::setSourceMac (MAC_ADDR mac)
80 {
81 memcpy (&header.sourcehost, &mac, ETHER_ADDR_LEN);
82 }
83
setDestMac(MAC_ADDR mac)84 void EthernetPacket::setDestMac (MAC_ADDR mac)
85 {
86 memcpy (&header.desthost, &mac, ETHER_ADDR_LEN);
87 }
88
setType(uint16_t tp)89 void EthernetPacket::setType (uint16_t tp)
90 {
91 header.type = tp;
92 }
93
assemblePacket()94 void EthernetPacket::assemblePacket()
95 {
96 if (nextPacket != NULL)
97 nextPacket->assemblePacket ();
98
99 int thissize = sizeof(ETHERNET_HEADER);
100 int nextsize = nextPacket != NULL ? nextPacket->getSize() : 0;
101
102 //
103 // ethernet needs a minimum data of 46 bytes
104 // if this is not the case we will add padding.
105 // this can make the output trace different from the
106 // original trace because small packets that are
107 // sent from the capture machine are not already
108 // padded when they are captured. The padding is mostly
109 // done by the ethernet nic. But we want rfc friendly
110 // packets as output so we do pad.
111 // http://www.ethereal.com/lists/ethereal-users/200304/msg00104.html
112 //
113
114 int padding = (nextsize < 46 ? 46 - nextsize : 0);
115
116 //
117 // allocate the buffer
118 //
119
120 setSize (thissize + nextsize + padding);
121 memset (buffer, 0, getSize ());
122
123 if (nextPacket != NULL)
124 memcpy (buffer + thissize, nextPacket->getBuffer(), nextsize);
125
126 header.type = swap16 (header.type);
127 memcpy (buffer, &header, sizeof(ETHERNET_HEADER));
128 header.type = swap16 (header.type);
129 }
130
toString()131 string EthernetPacket::toString ()
132 {
133 ostringstream out;
134
135 out << "Ethernet packet" << std::endl
136 << "\tsource mac: \t" << getSourceMac().toString() << std::endl
137 << "\tdest mac: \t" << getDestMac().toString() << std::endl
138 << "\ttype: \t\t0x" << std::hex << std::setw (4) << std::setfill ('0') << getType();
139
140 return out.str ();
141 }
142
getMinProtocolSize()143 uint32_t EthernetPacket::getMinProtocolSize ()
144 {
145 return sizeof (ETHERNET_HEADER);
146 }
147