1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // value.cc author Russ Combs <rucombs@cisco.com>
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "value.h"
25
26 #include <cassert>
27
28 #include "sfip/sf_cidr.h"
29
30 #ifdef UNIT_TEST
31 #include "catch/snort_catch.h"
32 #endif
33
34 using namespace snort;
35 using namespace std;
36
get_mac(uint8_t (& mac)[6]) const37 void Value::get_mac(uint8_t (&mac)[6]) const
38 {
39 if ( str.size() == sizeof(mac) )
40 str.copy((char*)mac, sizeof(mac));
41 else
42 memset(mac, 0, sizeof(mac));
43 }
44
get_ip4() const45 uint32_t Value::get_ip4() const
46 {
47 return (uint32_t)num;
48 }
49
get_addr(uint8_t (& addr)[16]) const50 void Value::get_addr(uint8_t (&addr)[16]) const
51 {
52 if ( str.size() <= sizeof(addr) )
53 str.copy((char*)addr, sizeof(addr));
54 else
55 memset(addr, 0, sizeof(addr));
56 }
57
get_addr_ip4(uint8_t (& addr)[4]) const58 void Value::get_addr_ip4(uint8_t (&addr)[4]) const
59 {
60 if ( str.size() == sizeof(addr) )
61 str.copy((char*)addr, sizeof(addr));
62 else
63 memset(addr, 0, sizeof(addr));
64 }
65
get_addr_ip6(uint8_t (& addr)[16]) const66 void Value::get_addr_ip6(uint8_t (&addr)[16]) const
67 {
68 if ( str.size() == sizeof(addr) )
69 str.copy((char*)addr, sizeof(addr));
70 else
71 memset(addr, 0, sizeof(addr));
72 }
73
get_addr(SfIp & addr) const74 void Value::get_addr(SfIp& addr) const
75 {
76 if ( str.size() == 4 )
77 addr.set(str.c_str(), AF_INET);
78
79 else if ( str.size() == 16 )
80 addr.set(str.c_str(), AF_INET6);
81
82 else
83 addr.clear();
84 }
85
get_addr(SfCidr & cidr) const86 void Value::get_addr(SfCidr& cidr) const
87 {
88 if ( str.size() == 4 )
89 cidr.set(str.c_str(), AF_INET);
90
91 else if ( str.size() == 16 )
92 cidr.set(str.c_str(), AF_INET6);
93
94 else
95 cidr.clear();
96 }
97
get_bits(PortBitSet & list) const98 void Value::get_bits(PortBitSet& list) const
99 {
100 list.reset();
101 std::size_t len = str.size();
102 assert(len == list.size());
103
104 for ( std::size_t n = 0; n < len; ++n )
105 {
106 if ( str[n] == '1' )
107 list.set(n);
108 }
109 }
110
get_bits(VlanBitSet & list) const111 void Value::get_bits(VlanBitSet& list) const
112 {
113 list.reset();
114 std::size_t len = str.size();
115 assert(len == list.size());
116
117 for ( std::size_t n = 0; n < len; ++n )
118 {
119 if ( str[n] == '1' )
120 list.set(n);
121 }
122 }
123
get_bits(ByteBitSet & list) const124 void Value::get_bits(ByteBitSet& list) const
125 {
126 list.reset();
127 std::size_t len = str.size();
128 assert(len == list.size());
129
130 for ( std::size_t n = 0; n < len; ++n )
131 {
132 if ( str[n] == '1' )
133 list.set(n);
134 }
135 }
136
set_first_token()137 void Value::set_first_token()
138 {
139 if ( ss )
140 delete ss;
141
142 ss = new stringstream(str);
143 }
144
get_next_token(string & tok)145 bool Value::get_next_token(string& tok)
146 {
147 return ss and ( *ss >> tok );
148 }
149
get_next_csv_token(string & tok)150 bool Value::get_next_csv_token(string& tok)
151 {
152 return ss and std::getline(*ss, tok, ',');
153 }
154
strtol(long & n) const155 bool Value::strtol(long& n) const
156 {
157 const char* s = str.c_str();
158
159 if ( !*s )
160 return false;
161
162 char* end = nullptr;
163
164 n = ::strtol(s, &end, 0);
165
166 if ( *end )
167 return false;
168
169 return true;
170 }
171
strtol(long & n,const std::string & tok) const172 bool Value::strtol(long& n, const std::string& tok) const
173 {
174 const char* s = tok.c_str();
175
176 if ( !*s )
177 return false;
178
179 char* end = nullptr;
180
181 n = ::strtol(s, &end, 0);
182
183 if ( *end )
184 return false;
185
186 return true;
187 }
188
get_as_string() const189 std::string Value::get_as_string() const
190 {
191 std::string value_str = str;
192 switch ( type )
193 {
194 case VT_BOOL:
195 value_str = num ? "true" : "false";
196 break;
197 case VT_NUM:
198 {
199 stringstream tmp;
200 tmp << std::fixed;
201 tmp << num;
202 value_str = tmp.str();
203 auto dot_pos = value_str.find('.');
204 auto pos = value_str.find_last_not_of("0");
205 if ( pos == dot_pos )
206 --pos;
207
208 value_str = value_str.substr(0, pos + 1);
209 break;
210 }
211 default:
212 break;
213 }
214 return value_str;
215 }
216
get_origin_string() const217 std::string Value::get_origin_string() const
218 {
219 if ( origin_str.empty() )
220 return "";
221
222 std::string value;
223 std::string token;
224
225 stringstream ss(origin_str);
226 while ( ss >> token )
227 {
228 value += token;
229 value += " ";
230 }
231 value.erase(value.size() - 1);
232
233 return value;
234 }
235
get_param_type() const236 Parameter::Type Value::get_param_type() const
237 {
238 if ( param )
239 return param->type;
240
241 return Parameter::PT_MAX;
242 }
243
update_mask(uint8_t & mask,uint8_t flag,bool invert)244 void Value::update_mask(uint8_t& mask, uint8_t flag, bool invert)
245 {
246 if ( get_bool() xor invert )
247 mask |= flag;
248 else
249 mask &= ~flag;
250 }
251
update_mask(uint16_t & mask,uint16_t flag,bool invert)252 void Value::update_mask(uint16_t& mask, uint16_t flag, bool invert)
253 {
254 if ( get_bool() xor invert )
255 mask |= flag;
256 else
257 mask &= ~flag;
258 }
259
update_mask(uint32_t & mask,uint32_t flag,bool invert)260 void Value::update_mask(uint32_t& mask, uint32_t flag, bool invert)
261 {
262 if ( get_bool() xor invert )
263 mask |= flag;
264 else
265 mask &= ~flag;
266 }
267
update_mask(uint64_t & mask,uint64_t flag,bool invert)268 void Value::update_mask(uint64_t& mask, uint64_t flag, bool invert)
269 {
270 if ( get_bool() xor invert )
271 mask |= flag;
272 else
273 mask &= ~flag;
274 }
275
276
277
278 //---------------------
279 // unit tests:
280 //---------------------
281
282 #ifdef UNIT_TEST
283
284 // The test strings used with some of the APIs below that return IP/MAC
285 // addrs are random character strings and not actual addresses. This is
286 // fine since there is no IP address specific processing or validation. The
287 // internal representation of the data is a C string and the purpose was to
288 // exercise the APIs to ensure things like length checks are done correctly
289 // and the string value/zero is returned based on the result etc.
290
291 TEST_CASE("mac addr negative test", "[Value]")
292 {
293 unsigned int num_chars;
294 uint8_t mac[6];
295 uint8_t zero[6];
296
297 memset(zero,0,6);
298 Value test_val("12345");
299
300 test_val.get_buffer(num_chars);
301 REQUIRE((num_chars == 5));
302
303 test_val.get_mac(mac);
304 CHECK(memcmp(mac,zero,6)==0);
305
306 }
307
308 TEST_CASE("get addr test", "[Value]")
309 {
310 unsigned int num_chars;
311 uint8_t addr[16];
312 uint8_t zero[16];
313
314 memset(zero,0,16);
315
316 SECTION("valid value")
317 {
318 Value test_val("1234567890123456");
319 const uint8_t* test_str = test_val.get_buffer(num_chars);
320 REQUIRE((num_chars == 16));
321
322 test_val.get_addr(addr);
323 CHECK(memcmp(addr,test_str,16)==0);
324 }
325 SECTION("invalid value")
326 {
327 Value test_val("12345678901234567890");
328 test_val.get_buffer(num_chars);
329 REQUIRE((num_chars == 20));
330
331 test_val.get_addr(addr);
332 CHECK(memcmp(addr,zero,16)==0);
333 }
334
335 }
336
337 TEST_CASE("get addr IPv4 test", "[Value]")
338 {
339 unsigned int num_chars;
340 uint8_t addr[4];
341 uint8_t zero[4];
342
343 memset(zero,0,4);
344
345 SECTION("valid value")
346 {
347 Value test_val("1234");
348 const uint8_t* test_str = test_val.get_buffer(num_chars);
349 REQUIRE((num_chars == 4));
350
351 test_val.get_addr_ip4(addr);
352 CHECK(memcmp(addr,test_str,4)==0);
353 }
354 SECTION("invalid value")
355 {
356 Value test_val("123456");
357 test_val.get_buffer(num_chars);
358 REQUIRE((num_chars == 6));
359
360 test_val.get_addr_ip4(addr);
361 CHECK(memcmp(addr,zero,4)==0);
362 }
363 }
364
365 TEST_CASE("get addr IPv6 test", "[Value]")
366 {
367 unsigned int num_chars;
368 uint8_t addr[16];
369 uint8_t zero[16];
370
371 memset(zero,0,16);
372
373 SECTION("valid value")
374 {
375 Value test_val("1234567890123456");
376 const uint8_t * test_str = test_val.get_buffer(num_chars);
377 REQUIRE((num_chars == 16));
378
379 test_val.get_addr_ip6(addr);
380 CHECK(memcmp(addr,test_str,16)==0);
381 }
382 SECTION("invalid value")
383 {
384 Value test_val("123456");
385 test_val.get_buffer(num_chars);
386 REQUIRE((num_chars == 6));
387
388 test_val.get_addr_ip6(addr);
389 CHECK(memcmp(addr,zero,16)==0);
390 }
391 }
392
393 TEST_CASE("token test", "[Value]")
394 {
395 string test_str;
396 const char * str_val;
397
398 Value test_val("123456");
399 test_val.set_first_token();
400 test_val.set("123456,abcdef");
401 test_val.set_first_token();
402
403
404 CHECK(test_val.get_next_csv_token(test_str));
405 str_val = (const char *)test_str.c_str();
406 REQUIRE(str_val != nullptr);
407 CHECK((strcmp(str_val,"123456")==0));
408 }
409
410 TEST_CASE("get as string", "[Value]")
411 {
412 bool bool_val = true;
413 double num_val = 6;
414
415 Value test_val(bool_val);
416 CHECK((strcmp(test_val.get_as_string().c_str(),"true") == 0));
417
418 test_val.set(num_val);
419 CHECK((strcmp(test_val.get_as_string().c_str(),"6") == 0));
420
421 test_val.set(1234.2);
422 CHECK((strcmp(test_val.get_as_string().c_str(),"1234.2") == 0));
423
424 test_val.set(123456.0893);
425 CHECK((strcmp(test_val.get_as_string().c_str(),"123456.0893") == 0));
426
427 test_val.set(0.0803);
428 CHECK((strcmp(test_val.get_as_string().c_str(),"0.0803") == 0));
429 }
430
431
432 TEST_CASE("update mask", "[Value]")
433 {
434 uint8_t mask8;
435 uint16_t mask16;
436 uint32_t mask32;
437 uint64_t mask64;
438 uint8_t flag8;
439 uint16_t flag16;
440 uint32_t flag32;
441 uint64_t flag64;
442 bool invert;
443
444 flag8 = 0x10;
445 flag16 = 0x1000;
446 flag32 = 0x10000000;
447 flag64 = 0x1000000000000000;
448
449 SECTION("val true")
450 {
451 Value test_val(true);
452
453 SECTION("invert true")
454 {
455 invert = true;
456
457 mask8 = 0x11;
458 test_val.update_mask(mask8, flag8, invert);
459 CHECK(mask8 == 0x01);
460
461 mask16 = 0x1100;
462 test_val.update_mask(mask16, flag16, invert);
463 CHECK((mask16 == 0x0100));
464
465 mask32 = 0x11000000;
466 test_val.update_mask(mask32, flag32, invert);
467 CHECK((mask32 == 0x01000000));
468
469 mask64 = 0x1100000000000000;
470 test_val.update_mask(mask64, flag64, invert);
471 CHECK((mask64 == 0x0100000000000000));
472 }
473
474 SECTION("invert false")
475 {
476 invert = false;
477 mask8 = 0x01;
478 test_val.update_mask(mask8, flag8, invert);
479 CHECK((mask8 == 0x11));
480
481 mask16 = 0x0100;
482 test_val.update_mask(mask16, flag16, invert);
483 CHECK((mask16 == 0x1100));
484
485 mask32 = 0x01000000;
486 test_val.update_mask(mask32, flag32, invert);
487 CHECK((mask32 == 0x11000000));
488
489 mask64 = 0x0100000000000000;
490 test_val.update_mask(mask64, flag64, invert);
491 CHECK((mask64 == 0x1100000000000000));
492 }
493 }
494
495 SECTION("val false")
496 {
497 Value test_val(true);
498
499 SECTION("invert false")
500 {
501 invert = true;
502
503 mask8 = 0x11;
504 test_val.update_mask(mask8, flag8, invert);
505 CHECK(mask8 == 0x01);
506
507 mask16 = 0x1100;
508 test_val.update_mask(mask16, flag16, invert);
509 CHECK((mask16 == 0x0100));
510
511 mask32 = 0x11000000;
512 test_val.update_mask(mask32, flag32, invert);
513 CHECK((mask32 == 0x01000000));
514
515 mask64 = 0x1100000000000000;
516 test_val.update_mask(mask64, flag64, invert);
517 CHECK((mask64 == 0x0100000000000000));
518 }
519
520 SECTION("invert true")
521 {
522 invert = false;
523 mask8 = 0x01;
524 test_val.update_mask(mask8, flag8, invert);
525 CHECK((mask8 == 0x11));
526
527 mask16 = 0x0100;
528 test_val.update_mask(mask16, flag16, invert);
529 CHECK((mask16 == 0x1100));
530
531 mask32 = 0x01000000;
532 test_val.update_mask(mask32, flag32, invert);
533 CHECK((mask32 == 0x11000000));
534
535 mask64 = 0x0100000000000000;
536 test_val.update_mask(mask64, flag64, invert);
537 CHECK((mask64 == 0x1100000000000000));
538 }
539 }
540 }
541
542 #endif
543
544
545