Imported Upstream version 0.3
[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-2008 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 version 3 as
21  *  published by the Free Software Foundation.
22  *
23  *  Anytun is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.
30  */
31
32 #include <stdexcept>
33 #include <iostream>
34 #include "datatypes.h"
35 #include "endian.h"
36 #include "plainPacket.h"
37 #include "anytunError.h"
38
39 PlainPacket::PlainPacket(u_int32_t payload_length, bool allow_realloc) : Buffer(payload_length + sizeof(payload_type_t), allow_realloc)
40 {
41   payload_type_ = reinterpret_cast<payload_type_t*>(buf_);
42   payload_ = buf_ + sizeof(payload_type_t);
43   *payload_type_ = 0;
44 }
45
46 u_int32_t PlainPacket::getHeaderLength()
47 {
48   return sizeof(payload_type_t);
49 }
50
51 payload_type_t PlainPacket::getPayloadType() const
52 {
53   if(payload_type_)
54     return PAYLOAD_TYPE_T_NTOH(*payload_type_);
55
56   return 0;
57 }
58
59 void PlainPacket::setPayloadType(payload_type_t payload_type)
60 {
61   if(!payload_type_)
62     return;
63   
64   if(payload_type == PAYLOAD_TYPE_TUN) {
65     if(!payload_) {
66       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN);
67       return;
68     }
69
70     char * ip_version_ptr = reinterpret_cast<char *>(payload_);
71                 char ip_version = ip_version_ptr[0];
72                 ip_version >>=4;
73     if(ip_version == 4)
74       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN4);
75     else if(ip_version == 6)
76       *payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN6);
77   }
78   else
79     *payload_type_ = PAYLOAD_TYPE_T_HTON(payload_type);
80 }
81
82 u_int32_t PlainPacket::getPayloadLength() const
83 {
84   if(!payload_)
85     return 0;
86
87   return (length_ > sizeof(payload_type_t)) ? (length_ - sizeof(payload_type_t)) : 0;
88 }
89     
90 void PlainPacket::setPayloadLength(u_int32_t payload_length)
91 {
92   Buffer::setLength(payload_length + sizeof(payload_type_t));
93       // depending on allow_realloc buf_ may point to another address
94       // therefore in this case reinit() gets called by Buffer::setLength()
95 }
96
97 void PlainPacket::reinit()
98 {
99   payload_type_ = reinterpret_cast<payload_type_t*>(buf_);
100   payload_ = buf_ + sizeof(payload_type_t);
101
102   if(length_ <= (sizeof(payload_type_t)))
103     payload_ = NULL;
104
105   if(length_ < (sizeof(payload_type_t))) {
106     payload_type_ = NULL;
107     AnytunError::throwErr() << "plain packet can't be initialized, buffer is too small"; 
108   }
109
110 }
111
112 u_int8_t* PlainPacket::getPayload()
113 {
114   return payload_;
115 }
116
117 /*
118 NetworkAddress PlainPacket::getSrcAddr() const
119 {
120   if(!payload_type_ || !payload_)
121     return NetworkAddress();
122
123   payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
124
125   if(type == PAYLOAD_TYPE_TAP) // Ehternet
126   {
127         // TODO
128     return NetworkAddress();
129   }
130   else if(type == PAYLOAD_TYPE_TUN4) // IPv4
131   {
132     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip)))
133       return NetworkAddress();
134     struct ip* hdr = reinterpret_cast<struct ip*>(payload_);
135     return NetworkAddress(hdr->ip_src);
136   }
137   else if(type == PAYLOAD_TYPE_TUN6) // IPv6
138   {
139     if(length_ < (sizeof(payload_type_t)+sizeof(struct ip6_hdr)))
140       return NetworkAddress();
141     struct ip6_hdr* hdr = reinterpret_cast<struct ip6_hdr*>(payload_);
142     return NetworkAddress(hdr->ip6_src);
143   }
144   return NetworkAddress();
145 }*/
146
147 NetworkAddress PlainPacket::getDstAddr() const
148 {
149         if(!payload_type_ || !payload_)
150                 return NetworkAddress();
151
152         payload_type_t type = PAYLOAD_TYPE_T_NTOH(*payload_type_);
153
154         if(type == PAYLOAD_TYPE_TAP) // Ehternet
155         {
156                 // TODO
157                 return NetworkAddress();
158         }
159         else if(type == PAYLOAD_TYPE_TUN4) // IPv4
160         {
161                 if(length_ < (sizeof(payload_type_t)+5*4))
162                         return NetworkAddress();
163                 char * hdr = reinterpret_cast<char *>(payload_);
164                 boost::asio::ip::address_v4::bytes_type ip_octets;
165                 for (int i=0; i<4;i++)
166                         ip_octets[i]=hdr[4*4+i];
167                 return NetworkAddress(boost::asio::ip::address_v4(ip_octets));
168         }
169         else if(type == PAYLOAD_TYPE_TUN6) // IPv6
170         {
171                 if(length_ < (sizeof(payload_type_t)+2*16+2*4))
172                         return NetworkAddress();
173                 char * hdr = reinterpret_cast<char *>(payload_);
174                 boost::asio::ip::address_v6::bytes_type ip_octets;
175                 for (int i=0; i<16;i++)
176                         ip_octets[i]=hdr[2*4+16+i];
177                 return NetworkAddress(boost::asio::ip::address_v6(ip_octets));
178         }
179         return NetworkAddress();
180 }