Imported Upstream version 0.3.4
[anytun.git] / src / buffer.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 <cstring>
34 #include <stdexcept>
35 #include <string>
36 #include <sstream>
37 #include <iostream>
38 #include <boost/archive/text_oarchive.hpp>
39 #include <boost/archive/text_iarchive.hpp>
40 #include "datatypes.h"
41 #include "buffer.h"
42
43 Buffer::Buffer(bool allow_realloc) : buf_(0), length_(0), real_length_(0), allow_realloc_(allow_realloc)
44 {
45 }
46
47 Buffer::Buffer(uint32_t length, bool allow_realloc) : length_(length), real_length_(length_ + Buffer::OVER_SIZE_),
48   allow_realloc_(allow_realloc)
49 {
50   buf_ = new uint8_t[real_length_];
51   if(!buf_) {
52     length_ = 0;
53     real_length_ = 0;
54     throw std::bad_alloc();
55   }
56   std::memset(buf_, 0, real_length_);
57 }
58
59 Buffer::Buffer(uint8_t* data, uint32_t length, bool allow_realloc) : length_(length), real_length_(length + Buffer::OVER_SIZE_),
60   allow_realloc_(allow_realloc)
61 {
62   if(!data) {
63     length_ = 0;
64     real_length_ = 0;
65     return;
66   }
67
68   buf_ = new uint8_t[real_length_];
69   if(!buf_) {
70     length_ = 0;
71     real_length_ = 0;
72     throw std::bad_alloc();
73   }
74   std::memcpy(buf_, data, length_);
75 }
76
77 Buffer::Buffer(std::string hex_data, bool allow_realloc) : length_(static_cast<uint32_t>(hex_data.size())/2),
78   real_length_(length_ + Buffer::OVER_SIZE_),
79   allow_realloc_(allow_realloc)
80 {
81   buf_ = new uint8_t[real_length_];
82   if(!buf_) {
83     length_ = 0;
84     real_length_ = 0;
85     throw std::bad_alloc();
86   }
87
88   for(uint32_t i=0; i<length_; ++i) {
89     uint32_t tmp;
90     std::istringstream ss(std::string(hex_data.c_str(), i*2, 2));
91     if(!(ss >> std::hex >> tmp)) { tmp = 0; }
92     buf_[i] = static_cast<uint8_t>(tmp);
93   }
94 }
95
96 Buffer::~Buffer()
97 {
98   if(buf_) {
99     delete[] buf_;
100   }
101 }
102
103 Buffer::Buffer(const Buffer& src) : length_(src.length_), real_length_(src.real_length_), allow_realloc_(src.allow_realloc_)
104 {
105   buf_ = new uint8_t[real_length_];
106   if(!buf_) {
107     length_ = 0;
108     real_length_ = 0;
109     throw std::bad_alloc();
110   }
111   std::memcpy(buf_, src.buf_, length_);
112 }
113
114 void Buffer::operator=(const Buffer& src)
115 {
116   if(buf_) {
117     delete[] buf_;
118   }
119
120   length_ = src.length_;
121   real_length_ = src.real_length_;
122   allow_realloc_ = src.allow_realloc_;
123
124   buf_ = new uint8_t[real_length_];
125   if(!buf_) {
126     length_ = 0;
127     real_length_ = 0;
128     throw std::bad_alloc();
129   }
130   std::memcpy(buf_, src.buf_, length_);
131 }
132
133 bool Buffer::operator==(const Buffer& cmp) const
134 {
135   if(length_ != cmp.length_) {
136     return false;
137   }
138
139   if(!std::memcmp(buf_, cmp.buf_, length_)) {
140     return true;
141   }
142
143   return false;
144 }
145
146 Buffer Buffer::operator^(const Buffer& xor_by) const
147 {
148   uint32_t res_length = (xor_by.length_ > length_) ? xor_by.length_ : length_;
149   uint32_t min_length = (xor_by.length_ < length_) ? xor_by.length_ : length_;
150   Buffer res(res_length);
151
152   for(uint32_t index = 0; index < min_length; index++) {
153     res[index] = buf_[index] ^ xor_by[index];
154   }
155
156   return res;
157 }
158
159 uint32_t Buffer::getLength() const
160 {
161   return length_;
162 }
163
164 void Buffer::setLength(uint32_t new_length)
165 {
166   if(new_length == length_) {
167     return;
168   }
169
170   if(new_length > real_length_) {
171     if(!allow_realloc_) {
172       throw std::out_of_range("buffer::setLength() - reallocation not allowed for this Buffer");
173     }
174
175     uint8_t* old_buf = buf_;
176     uint32_t old_length = length_;
177
178     length_ = new_length;
179     real_length_ = length_ + Buffer::OVER_SIZE_;
180
181     buf_ = new uint8_t[real_length_];
182     if(!buf_) {
183       length_ = 0;
184       real_length_ = 0;
185       if(old_buf) {
186         delete[] old_buf;
187       }
188
189       throw std::bad_alloc();
190     }
191     std::memcpy(buf_, old_buf, old_length);
192
193     if(old_buf) {
194       delete[] old_buf;
195     }
196
197     old_buf = &buf_[old_length];
198     std::memset(old_buf, 0, real_length_ - old_length);
199   } else {
200     length_ = new_length;
201   }
202
203   reinit();
204 }
205
206
207 uint8_t* Buffer::getBuf()
208 {
209   return buf_;
210 }
211
212 uint8_t& Buffer::operator[](uint32_t index)
213 {
214   if(index >= length_) {
215     throw std::out_of_range("buffer::operator[]");
216   }
217
218   return buf_[index];
219 }
220
221 uint8_t Buffer::operator[](uint32_t index) const
222 {
223   if(index >= length_) {
224     throw std::out_of_range("buffer::operator[] const");
225   }
226
227   return buf_[index];
228 }
229
230 Buffer::operator uint8_t*()
231 {
232   return buf_;
233 }
234
235 std::string Buffer::getHexDump() const
236 {
237   std::stringstream ss;
238   ss << "Length=" << length_ << std::endl << std::hex << std::uppercase;
239   for(uint32_t index = 0; index < length_; index++) {
240     ss << std::setw(2) << std::setfill('0') << uint32_t(buf_[index]) << " ";
241     if(!((index+1) % 16)) {
242       ss << std::endl;
243       continue;
244     }
245     if(!((index+1) % 8)) {
246       ss << " ";
247     }
248   }
249   return ss.str();
250 }
251
252 std::string Buffer::getHexDumpOneLine() const
253 {
254   std::stringstream ss;
255   ss << length_ << " Bytes,'" << std::hex << std::uppercase;
256   for(uint32_t index = 0; index < length_; index++) {
257     ss << std::setw(2) << std::setfill('0') << uint32_t(buf_[index]);
258   }
259   ss << "'";
260   return ss.str();
261 }
262
263 bool Buffer::isReallocAllowed() const
264 {
265   return allow_realloc_;
266 }