Imported Upstream version 0.3.4
[anytun.git] / src / plainPacket.cpp
1 /*
2  *  anytun
3  *
4  *  The secure anycast tunneling protocol (satp) defines a protocol used
5  *  for communication between any combination of unicast and anycast
6  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
7  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
8  *  ethernet, ip, arp ...). satp directly includes cryptography and
9  *  message authentication based on the methodes used by SRTP.  It is
10  *  intended to deliver a generic, scaleable and secure solution for
11  *  tunneling and relaying of packets of any protocol.
12  *
13  *
14  *  Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl,
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
19  *  Anytun is free software: you can redistribute it and/or modify
20  *  it under the terms of the GNU General Public License as published by
21  *  the Free Software Foundation, either version 3 of the License, or
22  *  any later version.
23  *
24  *  Anytun is distributed in the hope that it will be useful,
25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  *  GNU General Public License for more details.
28  *
29  *  You should have received a copy of the GNU General Public License
30  *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.
31  */
32
33 #include <stdexcept>
34 #include <iostream>
35 #include "datatypes.h"
36 #include "endian.h"
37 #include "plainPacket.h"
38 #include "anytunError.h"
39
40 PlainPacket::PlainPacket(uint32_t payload_length, bool allow_realloc) : Buffer(payload_length + sizeof(payload_type_t), allow_realloc)
41 {
42   payload_type_ = reinterpret_cast<payload_type_t*>(buf_);
43   payload_ = buf_ + sizeof(payload_type_t);
44   *payload_type_ = 0;
45 }
46
47 uint32_t PlainPacket::getHeaderLength()
48 {
49   return sizeof(payload_type_t);
50 }
51
52 payload_type_t PlainPacket::getPayloadType() const
53 {
54   if(payload_type_) {
55     return PAYLOAD_TYPE_T_NTOH(*payload_type_);
56   }
57
58   return 0;
59 }
60
61 void PlainPacket::setPayloadType(payload_type_t payload_type)
62 {
63   if(!payload_type_) {
64     return;
65   }
66
67   if(payload_type == PAYLOAD_TYPE_TUN) {
68     if(!payload_) {
69       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN);
70       return;
71     }
72
73     char* ip_version_ptr = reinterpret_cast<char*>(payload_);
74     char ip_version = ip_version_ptr[0];
75     ip_version >>=4;
76     if(ip_version == 4) {
77       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN4);
78     } else if(ip_version == 6) {
79       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN6);
80     }
81   } else {
82     *payload_type_ = PAYLOAD_TYPE_T_HTON(payload_type);
83   }
84 }
85
86 uint32_t PlainPacket::getPayloadLength() const
87 {
88   if(!payload_) {
89     return 0;
90   }
91
92   return (length_ > sizeof(payload_type_t)) ? (length_ - sizeof(payload_type_t)) : 0;
93 }
94
95 void PlainPacket::setPayloadLength(uint32_t payload_length)
96 {
97   Buffer::setLength(payload_length + sizeof(payload_type_t));
98   // depending on allow_realloc buf_ may point to another address
99   // therefore in this case reinit() gets called by Buffer::setLength()
100 }
101
102 void PlainPacket::reinit()
103 {
104   payload_type_ = reinterpret_cast<payload_type_t*>(buf_);
105   payload_ = buf_ + sizeof(payload_type_t);
106
107   if(length_ <= (sizeof(payload_type_t))) {
108     payload_ = NULL;
109   }
110
111   if(length_ < (sizeof(payload_type_t))) {
112     payload_type_ = NULL;
113     AnytunError::throwErr() << "plain packet can't be initialized, buffer is too small";
114   }
115
116 }
117
118 uint8_t* PlainPacket::getPayload()
119 {
120   return payload_;
121 }
122
123 /*
124 NetworkAddress PlainPacket::getSrcAddr() const
125 {
126   if(!payload_type_ || !payload_)
127     return NetworkAddress();
128
129   payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
130
131   if(type == PAYLOAD_TYPE_TAP) // Ehternet
132   {
133         // TODO
134     return NetworkAddress();
135   }
136   else if(type == PAYLOAD_TYPE_TUN4) // IPv4
137   {
138     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip)))
139       return NetworkAddress();
140     struct ip* hdr = reinterpret_cast<struct ip*>(payload_);
141     return NetworkAddress(hdr->ip_src);
142   }
143   else if(type == PAYLOAD_TYPE_TUN6) // IPv6
144   {
145     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip6_hdr)))
146       return NetworkAddress();
147     struct ip6_hdr* hdr = reinterpret_cast<struct ip6_hdr*>(payload_);
148     return NetworkAddress(hdr->ip6_src);
149   }
150   return NetworkAddress();
151 }*/
152
153 NetworkAddress PlainPacket::getDstAddr() const
154 {
155   if(!payload_type_ || !payload_) {
156     return NetworkAddress();
157   }
158
159   payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
160
161   if(type == PAYLOAD_TYPE_TAP) { // Ehternet
162     // TODO
163     return NetworkAddress();
164   } else if(type == PAYLOAD_TYPE_TUN4) { // IPv4
165     if(length_ < (sizeof(payload_type_t)+5*4)) {
166       return NetworkAddress();
167     }
168     char* hdr = reinterpret_cast<char*>(payload_);
169     boost::asio::ip::address_v4::bytes_type ip_octets;
170     for(int i=0; i<4; i++) {
171       ip_octets[i]=hdr[4*4+i];
172     }
173     return NetworkAddress(boost::asio::ip::address_v4(ip_octets));
174   } else if(type == PAYLOAD_TYPE_TUN6) { // IPv6
175     if(length_ < (sizeof(payload_type_t)+2*16+2*4)) {
176       return NetworkAddress();
177     }
178     char* hdr = reinterpret_cast<char*>(payload_);
179     boost::asio::ip::address_v6::bytes_type ip_octets;
180     for(int i=0; i<16; i++) {
181       ip_octets[i]=hdr[2*4+16+i];
182     }
183     return NetworkAddress(boost::asio::ip::address_v6(ip_octets));
184   }
185   return NetworkAddress();
186 }