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