Packets/80221Bundle: fixed MIH message validation unit test @ ubuntu hardy
[senf.git] / senf / Packets / 80221Bundle / TLVParser.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Thorsten Horstmann <tho@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief TLVParser non-inline non-template implementation */
25
26 #include "TLVParser.hh"
27 //#include "TLVParser.ih"
28
29 // Custom includes
30 #include <senf/Utils/hexdump.hh>
31 #include <senf/Utils/Format.hh>
32 #include <senf/Utils/String.hh>
33
34 #define prefix_
35 //-/////////////////////////////////////////////////////////////////////////////////////////////////
36
37 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFSrcIdTLVParser );
38 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFDstIdTLVParser );
39 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHStatusTLVParser );
40 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHValidTimeIntervalTLVParser );
41
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43 // MIHBaseTLVParser
44
45 prefix_ std::pair<bool, std::string> senf::MIHBaseTLVParser::validateTL(boost::uint8_t expectedType, MIHTLVLengthParser::value_type expectedLength)
46     const
47 {
48     if (! check( 1 + senf::bytes(length_()) + length()) )
49         return std::make_pair(false, "truncated TLV. Type: " + senf::str(type()));
50     if (type() != expectedType)
51         return std::make_pair(false, "invalid TLV type: " + senf::str(type()));
52     if (length() != expectedLength)
53         return std::make_pair(false, "invalid length in TLV. Type: " + senf::str(type()));
54     return std::make_pair(true, "");
55 }
56
57 //-/////////////////////////////////////////////////////////////////////////////////////////////////
58 // senf::MIHBaseListTLVParser
59
60 prefix_ void senf::MIHBaseListTLVParser::maxListSize(MIHTLVLengthParser::value_type maxl)
61     const
62 {
63     protect(), listSize_().capacity( maxl);
64     maxLength( maxl + senf::bytes(listSize_()));
65 }
66
67
68 //-/////////////////////////////////////////////////////////////////////////////////////////////////
69 // senf::MIHFIdTLVParser
70
71 prefix_ void senf::MIHFIdTLVParser::dump(std::ostream & os)
72     const
73 {
74     senf::format::IndentHelper indent;
75     os << indent << "type:   " << unsigned (type()) << std::endl
76        << indent << "length: " << unsigned (length()) << std::endl
77        << indent << "value:\n";
78     std::string src_mihfId (valueAsString());
79     hexdump(src_mihfId.begin(), src_mihfId.end(), os);
80 }
81
82 prefix_ void senf::MIHFIdTLVParser::finalize()
83 {
84     protect(), idLength_().finalize();
85     length_() << idLength() + senf::bytes(idLength_());
86     MIHBaseTLVParser::finalize();
87 }
88
89 prefix_ void senf::MIHFIdTLVParser::maxIdLength(boost::uint8_t maxl)
90     const
91 {
92     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
93     if (maxl > 253)
94         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
95     protect(), idLength_().capacity( maxl);
96     maxLength( maxl + senf::bytes(idLength_()));
97 }
98
99 prefix_ senf::safe_data_iterator senf::MIHFIdTLVParser::resizeValueField(
100         MIHTLVLengthParser::value_type size)
101 {
102     MIHTLVLengthParser::value_type current_length ( idLength());
103     idLength_() << size;
104     length_() << size + idLength_().bytes();
105
106     safe_data_iterator si (data(), valueBegin());
107     if (current_length > size)
108         data().erase( si, boost::next(si, current_length-size));
109     else
110         data().insert( si, size-current_length, 0);
111     return si;
112 }
113
114 prefix_ void senf::MIHFIdTLVParser::value(std::string const & id)
115 {
116     size_type str_size (id.size());
117     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
118     if (str_size > 253)
119         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
120     safe_data_iterator si = resizeValueField( str_size);
121     std::copy( id.begin(), id.end(), si);
122 }
123
124 prefix_ void senf::MIHFIdTLVParser::value(senf::MACAddress const & addr)
125 {
126     safe_data_iterator si = resizeValueField(6*2);
127     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
128 }
129
130 prefix_ void senf::MIHFIdTLVParser::value(senf::INet4Address const & addr)
131 {
132     safe_data_iterator si = resizeValueField(4*2);
133     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
134 }
135
136 prefix_ void senf::MIHFIdTLVParser::value(senf::INet6Address const & addr)
137 {
138     safe_data_iterator si = resizeValueField(16*2);
139     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
140 }
141
142 prefix_ void senf::MIHFIdTLVParser::value(senf::EUI64 const & addr)
143 {
144     safe_data_iterator si = resizeValueField(8*2);
145     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
146 }
147
148 prefix_ void senf::MIHFIdTLVParser::value( MIHFId const & id)
149 {
150     boost::apply_visitor( ValueSetterVisitor(*this), id);
151 }
152
153 prefix_ senf::MIHFId senf::MIHFIdTLVParser::valueAs(MIHFId::Type type)
154     const
155 {
156     if (length() == 0) return MIHFId();
157     switch (type) {
158     case MIHFId::MulticastType:
159         return MIHFId();
160     case MIHFId::MACAddress:
161         return MIHFId( valueAsMACAddress());
162     case MIHFId::INet4Address:
163         return MIHFId( valueAsINet4Address());
164     case MIHFId::INet6Address:
165         return MIHFId( valueAsINet6Address());
166     case MIHFId::String:
167         return MIHFId( valueAsString());
168     case MIHFId::EUI64:
169         return MIHFId( valueAsEUI64());
170     }
171     return MIHFId();
172 }
173
174
175 //-/////////////////////////////////////////////////////////////////////////////////////////////////
176 // senf::MIHFSrcIdTLVParser
177
178 prefix_ void senf::MIHFSrcIdTLVParser::dump(std::ostream & os)
179     const
180 {
181     senf::format::IndentHelper indent;
182     os << indent << "source MIHF_Id TLV:\n";
183     MIHFIdTLVParser::dump(os);
184 }
185
186 prefix_ std::pair<bool, std::string> senf::MIHFSrcIdTLVParser::validate()
187     const
188 {
189     if (! check( 1 + senf::bytes(length_()) + length()) )
190         return std::make_pair(false, "truncated TLV. Type: " + senf::str(type()));
191     if (type() != typeId)
192         return std::make_pair(false, "invalid TLV type: " + senf::str(type()));
193     return std::make_pair(true, "");
194 }
195
196
197 //-/////////////////////////////////////////////////////////////////////////////////////////////////
198 // senf::MIHFDstIdTLVParser
199
200 prefix_ void senf::MIHFDstIdTLVParser::dump(std::ostream & os)
201     const
202 {
203     senf::format::IndentHelper indent;
204     os << indent << "destination MIHF_Id TLV:\n";
205     MIHFIdTLVParser::dump(os);
206 }
207
208 prefix_ std::pair<bool, std::string> senf::MIHFDstIdTLVParser::validate()
209     const
210 {
211     if (! check( 1 + senf::bytes(length_()) + length()) )
212         return std::make_pair(false, "truncated TLV. Type: " + senf::str(type()));
213     if (type() != typeId)
214         return std::make_pair(false, "invalid TLV type: " + senf::str(type()));
215     return std::make_pair(true, "");
216 }
217
218 //-/////////////////////////////////////////////////////////////////////////////////////////////////
219 // senf::MIHStatusTLVParser
220
221 prefix_ void senf::MIHStatusTLVParser::dump(std::ostream & os)
222     const
223 {
224     senf::format::IndentHelper indent;
225     os << indent << "Status TLV:" << std::endl;
226     indent.increase();
227     os << indent <<   "type:   " << unsigned( type()) << std::endl
228        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
229        << indent <<   "value:  " << unsigned( value());
230     switch (value()) {
231     case Success:
232         os << " (Success)" << std::endl;
233         return;
234     case UnspecifiedFailure:
235         os << " (Unspecified Failure)" << std::endl;
236         return;
237     case Rejected:
238         os << " (Rejected)" << std::endl;
239         return;
240     case AuthorizationFailure:
241         os << " (Authorization Failure)" << std::endl;
242         return;
243     case NetworkError:
244         os << " (Network Error)" << std::endl;
245         return;
246     }
247     os << " (???; invalid value!)" << std::endl;
248 }
249
250 prefix_ std::pair<bool, std::string> senf::MIHStatusTLVParser::validate()
251     const
252 {
253     if (! validateTL( typeId, 1).first)
254         return validateTL( typeId, 1);
255     if (value() >= 4)
256         return std::make_pair(false, "invalid value in MIHStatusTLV " + senf::str(value()));
257     return std::make_pair(true, "");
258 }
259
260 //-/////////////////////////////////////////////////////////////////////////////////////////////////
261 // senf::MIHRegisterReqCodeTLVParser
262
263 prefix_ void senf::MIHRegisterReqCodeTLVParser::dump(std::ostream & os)
264     const
265 {
266     senf::format::IndentHelper indent;
267     os << indent << "Register Request Code TLV:" << std::endl;
268     indent.increase();
269     os << indent <<   "type:   " << unsigned( type()) << std::endl
270        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
271        << indent <<   "value:  " << unsigned( value());
272     switch (value()) {
273     case Registration:
274         os << " (Registration)" << std::endl;
275         return;
276     case ReRegistration:
277         os << " (Re-Registration)" << std::endl;
278         return;
279     }
280     os << " (???; invalid value!)" << std::endl;
281 }
282
283 prefix_ std::pair<bool, std::string> senf::MIHRegisterReqCodeTLVParser::validate()
284     const
285 {
286     if (! validateTL( typeId, 1).first)
287         return validateTL( typeId, 1);
288     if (value() >= 2)
289         return std::make_pair(false, "invalid value in MIHRegisterReqCodeTLV " + senf::str(value()));
290     return std::make_pair(true, "");
291 }
292
293 //-/////////////////////////////////////////////////////////////////////////////////////////////////
294 // senf::MIHValidTimeIntervalTLVParser
295
296 prefix_ void senf::MIHValidTimeIntervalTLVParser::dump(std::ostream & os)
297     const
298 {
299     senf::format::IndentHelper indent;
300     os << indent << "Valid Time Interval TLV:" << std::endl;
301     indent.increase();
302     os << indent <<   "type:   " << unsigned( type()) << std::endl
303        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
304        << indent <<   "value:  " << unsigned( value())
305        << ( value()==0 ? " (infinite)" : " seconds") << std::endl;
306 }
307
308 prefix_ std::pair<bool, std::string> senf::MIHValidTimeIntervalTLVParser::validate()
309     const
310 {
311     if (! validateTL( typeId, 4).first) return validateTL( typeId, 4);
312     return std::make_pair(true, "");
313 }
314
315 //-/////////////////////////////////////////////////////////////////////////////////////////////////
316 // senf::MIHTLVLengthParser
317
318 prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() const
319 {
320     switch (bytes() ) {
321     case 1:
322         return length_field().value();
323     case 2:
324         return parse<UInt8Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
325     case 3:
326         return parse<UInt16Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
327     case 4:
328         return parse<UInt24Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
329     case 5:
330         return parse<UInt32Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
331     default:
332         throw( MIHTLVLengthException());
333     };
334 }
335
336 prefix_ void senf::MIHTLVLengthParser::value(value_type const & v)
337 {
338     switch (bytes() ) {
339     case 1:
340         if (v > 128) throw( MIHTLVLengthException());
341         length_field() = v;
342         return;
343     case 2:
344         if (v > UInt8Parser::max_value + 128) throw( MIHTLVLengthException());
345         parse<UInt8Parser>(1) = v - (v>128 ? 128 : 0);
346         break;
347     case 3:
348         if (v > UInt16Parser::max_value + 128) throw( MIHTLVLengthException());
349         parse<UInt16Parser>(1) = v - (v>128 ? 128 : 0);
350         break;;
351     case 4:
352         if (v > UInt24Parser::max_value + 128) throw( MIHTLVLengthException());
353         parse<UInt24Parser>(1) = v - (v>128 ? 128 : 0);
354         break;
355     case 5:
356         parse<UInt32Parser>(1) = v - (v>128 ? 128 : 0);
357         break;
358     default:
359         throw( MIHTLVLengthException());
360     };
361     underflow_flag() = (v <= 128);
362 }
363
364 prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::capacity()
365     const
366 {
367     switch (bytes() ) {
368     case 1:
369         return 128;
370     case 2:
371         return UInt8Parser::max_value + 128;
372     case 3:
373         return UInt16Parser::max_value + 128;
374     case 4:
375         return UInt24Parser::max_value + 128;
376     case 5:
377         return UInt32Parser::max_value;
378     default:
379         throw( MIHTLVLengthException());
380     };
381 }
382
383 prefix_ senf::MIHTLVLengthParser const & senf::MIHTLVLengthParser::operator= (value_type other)
384 {
385     value(other);
386     return *this;
387 }
388
389 prefix_ void senf::MIHTLVLengthParser::init() const
390 {
391     defaultInit();
392     extended_length_flag() = false;
393 }
394
395 prefix_ void senf::MIHTLVLengthParser::finalize()
396 {
397     value_type v = value();
398     size_type b = bytes();
399     if (v <= 128) {
400         if (b != 1) resize_(1);
401         return;
402     }
403     if (v <= UInt8Parser::max_value + 128) {
404         if (b != 2) resize_(2);
405         return;
406     }
407     if (v <= UInt16Parser::max_value + 128) {
408         if (b != 3) resize_(3);
409         return;
410     }
411     if (v <= UInt24Parser::max_value + 128 ) {
412         if (b != 4) resize_(4);
413         return;
414     }
415     if (b != 5) resize_(5);
416 }
417
418 prefix_ void senf::MIHTLVLengthParser::capacity(MIHTLVLengthParser::value_type v)
419 {
420     if (v <= 128)
421         return;
422     size_type b = bytes();
423     if (v <= UInt8Parser::max_value + 128) {
424         if (b < 2) resize_(2);
425         return;
426     }
427     if (v <= UInt16Parser::max_value + 128) {
428         if (b < 3) resize_(3);
429         return;
430     }
431     if (v <= UInt24Parser::max_value + 128) {
432         if (b < 4) resize_(4);
433         return;
434     }
435     if (b < 5) resize_(5);
436 }
437
438 prefix_ void senf::MIHTLVLengthParser::resize_(size_type size)
439 {
440     value_type v = value();
441     resize(bytes(), size);
442     if (size > 1) {
443         extended_length_flag() = true;
444         fixed_length_field() = size - 1;
445     } else {
446         extended_length_flag() = false;
447     }
448     value(v);
449 }
450
451
452 //-/////////////////////////////////////////////////////////////////////////////////////////////////
453 #undef prefix_
454
455 \f
456 // Local Variables:
457 // mode: c++
458 // fill-column: 100
459 // c-file-style: "senf"
460 // indent-tabs-mode: nil
461 // ispell-local-dictionary: "american"
462 // compile-command: "scons -u test"
463 // comment-column: 40
464 // End: