Imported Upstream version 0.3.2
[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(u_int32_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 u_int32_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   return 0;
58 }
59
60 void PlainPacket::setPayloadType(payload_type_t payload_type)
61 {
62   if(!payload_type_)
63     return;
64   
65   if(payload_type == PAYLOAD_TYPE_TUN) {
66     if(!payload_) {
67       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN);
68       return;
69     }
70
71     char * ip_version_ptr = reinterpret_cast<char *>(payload_);
72                 char ip_version = ip_version_ptr[0];
73                 ip_version >>=4;
74     if(ip_version == 4)
75       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN4);
76     else if(ip_version == 6)
77       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN6);
78   }
79   else
80     *payload_type_ = PAYLOAD_TYPE_T_HTON(payload_type);
81 }
82
83 u_int32_t PlainPacket::getPayloadLength() const
84 {
85   if(!payload_)
86     return 0;
87
88   return (length_ > sizeof(payload_type_t)) ? (length_ - sizeof(payload_type_t)) : 0;
89 }
90     
91 void PlainPacket::setPayloadLength(u_int32_t payload_length)
92 {
93   Buffer::setLength(payload_length + sizeof(payload_type_t));
94       // depending on allow_realloc buf_ may point to another address
95       // therefore in this case reinit() gets called by Buffer::setLength()
96 }
97
98 void PlainPacket::reinit()
99 {
100   payload_type_ = reinterpret_cast<payload_type_t*>(buf_);
101   payload_ = buf_ + sizeof(payload_type_t);
102
103   if(length_ <= (sizeof(payload_type_t)))
104     payload_ = NULL;
105
106   if(length_ < (sizeof(payload_type_t))) {
107     payload_type_ = NULL;
108     AnytunError::throwErr() << "plain packet can't be initialized, buffer is too small"; 
109   }
110
111 }
112
113 u_int8_t* PlainPacket::getPayload()
114 {
115   return payload_;
116 }
117
118 /*
119 NetworkAddress PlainPacket::getSrcAddr() const
120 {
121   if(!payload_type_ || !payload_)
122     return NetworkAddress();
123
124   payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
125
126   if(type == PAYLOAD_TYPE_TAP) // Ehternet
127   {
128         // TODO
129     return NetworkAddress();
130   }
131   else if(type == PAYLOAD_TYPE_TUN4) // IPv4
132   {
133     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip)))
134       return NetworkAddress();
135     struct ip* hdr = reinterpret_cast<struct ip*>(payload_);
136     return NetworkAddress(hdr->ip_src);
137   }
138   else if(type == PAYLOAD_TYPE_TUN6) // IPv6
139   {
140     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip6_hdr)))
141       return NetworkAddress();
142     struct ip6_hdr* hdr = reinterpret_cast<struct ip6_hdr*>(payload_);
143     return NetworkAddress(hdr->ip6_src);
144   }
145   return NetworkAddress();
146 }*/
147
148 NetworkAddress PlainPacket::getDstAddr() const
149 {
150         if(!payload_type_ || !payload_)
151                 return NetworkAddress();
152
153         payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
154
155         if(type == PAYLOAD_TYPE_TAP) // Ehternet
156         {
157                 // TODO
158                 return NetworkAddress();
159         }
160         else if(type == PAYLOAD_TYPE_TUN4) // IPv4
161         {
162                 if(length_ < (sizeof(payload_type_t)+5*4))
163                         return NetworkAddress();
164                 char * hdr = reinterpret_cast<char *>(payload_);
165                 boost::asio::ip::address_v4::bytes_type ip_octets;
166                 for (int i=0; i<4;i++)
167                         ip_octets[i]=hdr[4*4+i];
168                 return NetworkAddress(boost::asio::ip::address_v4(ip_octets));
169         }
170         else if(type == PAYLOAD_TYPE_TUN6) // IPv6
171         {
172                 if(length_ < (sizeof(payload_type_t)+2*16+2*4))
173                         return NetworkAddress();
174                 char * hdr = reinterpret_cast<char *>(payload_);
175                 boost::asio::ip::address_v6::bytes_type ip_octets;
176                 for (int i=0; i<16;i++)
177                         ip_octets[i]=hdr[2*4+16+i];
178                 return NetworkAddress(boost::asio::ip::address_v6(ip_octets));
179         }
180         return NetworkAddress();
181 }