Branch data Line data Source code
1 : : // $Id: Val.cc 6945 2009-11-27 19:25:10Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <sys/types.h>
8 : : #include <sys/param.h>
9 : :
10 : : #include <netinet/in.h>
11 : : #include <netdb.h>
12 : : #include <unistd.h>
13 : :
14 : : #include <stdio.h>
15 : : #include <stdlib.h>
16 : :
17 : : #include "Val.h"
18 : : #include "Net.h"
19 : : #include "File.h"
20 : : #include "Func.h"
21 : : #include "RE.h"
22 : : #include "Scope.h"
23 : : #include "NetVar.h"
24 : : #include "Expr.h"
25 : : #include "Serializer.h"
26 : : #include "RemoteSerializer.h"
27 : : #include "PrefixTable.h"
28 : : #include "Conn.h"
29 : : #include "Logger.h"
30 : :
31 : :
32 : 1686 : Val::Val(Func* f)
33 : : {
34 : 1686 : val.func_val = f;
35 : 1686 : type = f->FType()->Ref();
36 : 1686 : attribs = 0;
37 : : #ifdef DEBUG
38 : 1686 : bound_id = 0;
39 : : #endif
40 : 1686 : }
41 : :
42 : 54 : Val::Val(BroFile* f)
43 : : {
44 : : static FileType* string_file_type = 0;
45 [ + + # # ]: 54 : if ( ! string_file_type )
46 : 2 : string_file_type = new FileType(base_type(TYPE_STRING));
47 : :
48 : 54 : val.file_val = f;
49 : :
50 [ - + ][ # # ]: 54 : assert(f->FType()->Tag() == TYPE_STRING);
51 : 54 : type = string_file_type->Ref();
52 : :
53 : 54 : attribs = 0;
54 : : #ifdef DEBUG
55 : 54 : bound_id = 0;
56 : : #endif
57 : 54 : }
58 : :
59 : 824265 : Val::~Val()
60 : : {
61 [ - + ][ # # ]: 824265 : if ( type->InternalType() == TYPE_INTERNAL_STRING )
[ + + ]
62 [ # # ][ # # ]: 184294 : delete val.string_val;
[ + - ]
63 : :
64 [ + + ][ # # ]: 639971 : else if ( type->Tag() == TYPE_FILE )
[ - + ]
65 : 5 : Unref(val.file_val);
66 : :
67 : 824265 : Unref(type);
68 : : #ifdef DEBUG
69 : 824265 : Unref(bound_id);
70 : : #endif
71 [ + - ][ # # ]: 824265 : }
[ - + ]
72 : :
73 : 0 : Val* Val::Clone() const
74 : : {
75 : 0 : SerializationFormat* form = new BinarySerializationFormat();
76 : 0 : form->StartWrite();
77 : :
78 : 0 : CloneSerializer ss(form);
79 : 0 : SerialInfo sinfo(&ss);
80 : 0 : sinfo.cache = false;
81 : :
82 : 0 : this->Serialize(&sinfo);
83 : : char* data;
84 : 0 : uint32 len = form->EndWrite(&data);
85 : 0 : form->StartRead(data, len);
86 : :
87 : 0 : UnserialInfo uinfo(&ss);
88 : 0 : uinfo.cache = false;
89 : 0 : Val* clone = Unserialize(&uinfo, type);
90 : :
91 [ # # ]: 0 : delete [] data;
92 : :
93 : 0 : return clone;
94 : : }
95 : :
96 : 7 : bool Val::Serialize(SerialInfo* info) const
97 : : {
98 : 7 : return SerialObj::Serialize(info);
99 : : }
100 : :
101 : 0 : Val* Val::Unserialize(UnserialInfo* info, TypeTag type, const BroType* exact_type)
102 : : {
103 : 0 : Val* v = (Val*) SerialObj::Unserialize(info, SER_VAL);
104 [ # # ]: 0 : if ( ! v )
105 : 0 : return 0;
106 : :
107 [ # # ][ # # ]: 0 : if ( type != TYPE_ANY && (v->Type()->Tag() != type
[ # # ][ # # ]
[ # # ]
108 : : || (exact_type && ! same_type(exact_type, v->Type()))) )
109 : : {
110 : 0 : info->s->Error("type mismatch for value");
111 : 0 : Unref(v);
112 : 0 : return 0;
113 : : }
114 : :
115 : : // For MutableVals, we may get a value which, by considering the
116 : : // globally unique ID, we already know. To keep references correct,
117 : : // we have to bind to the local version. (FIXME: This is not the
118 : : // nicest solution. Ideally, DoUnserialize() should be able to pass
119 : : // us an alternative ptr to the correct object.)
120 [ # # ]: 0 : if ( v->IsMutableVal() )
121 : : {
122 : 0 : MutableVal* mv = v->AsMutableVal();
123 [ # # ]: 0 : if ( mv->HasUniqueID() )
124 : : {
125 : : ID* current =
126 : 0 : global_scope()->Lookup(mv->UniqueID()->Name());
127 : :
128 [ # # # # ]: 0 : if ( current && current != mv->UniqueID() )
[ # # ]
129 : : {
130 : 0 : DBG_LOG(DBG_STATE, "binding to already existing ID %s\n", current->Name());
131 [ # # ]: 0 : assert(current->ID_Val());
132 : :
133 : : // Need to unset the ID here. Otherwise,
134 : : // when the SerializationCache destroys
135 : : // the value, the global name will disappear.
136 : 0 : mv->SetID(0);
137 : 0 : Unref(v);
138 : 0 : return current->ID_Val()->Ref();
139 : : }
140 : : }
141 : : }
142 : :
143 : : // An enum may be bound to a different internal number remotely than we
144 : : // do for the same identifier. Check if this is the case, and, if yes,
145 : : // rebind to our value.
146 [ # # ]: 0 : if ( v->Type()->Tag() == TYPE_ENUM )
147 : : {
148 : 0 : int rv = v->AsEnum();
149 : 0 : EnumType* rt = v->Type()->AsEnumType();
150 : :
151 : 0 : const char* name = rt->Lookup(rv);
152 [ # # ]: 0 : if ( name )
153 : : {
154 : : // See if we know the enum locally.
155 : 0 : ID* local = global_scope()->Lookup(name);
156 [ # # # # ]: 0 : if ( local && local->IsEnumConst() )
[ # # ]
157 : : {
158 : 0 : EnumType* lt = local->Type()->AsEnumType();
159 : : int lv = lt->Lookup(local->ModuleName(),
160 : 0 : local->Name());
161 : :
162 : : // Compare.
163 [ # # ]: 0 : if ( rv != lv )
164 : : {
165 : : // Different, so let's bind the val
166 : : // to the local type.
167 : 0 : v->val.int_val = lv;
168 : 0 : Unref(rt);
169 : 0 : v->type = lt;
170 : 0 : ::Ref(lt);
171 : : }
172 : : }
173 : : }
174 : :
175 : : }
176 : :
177 : 0 : return v;
178 : : }
179 : :
180 : 9 : IMPLEMENT_SERIAL(Val, SER_VAL);
181 : :
182 : 7 : bool Val::DoSerialize(SerialInfo* info) const
183 : : {
184 [ + + ][ - + ]: 7 : DO_SERIALIZE(SER_VAL, BroObj);
185 : :
186 [ - + ]: 7 : if ( ! type->Serialize(info) )
187 : 0 : return false;
188 : :
189 [ - + ][ # # ]: 7 : SERIALIZE_OPTIONAL(attribs);
[ # # ][ # # ]
[ # # ][ - + ]
190 : :
191 [ - - + + - : 7 : switch ( type->InternalType() ) {
- - + - - ]
192 : : case TYPE_INTERNAL_VOID:
193 : 0 : info->s->Error("type is void");
194 : 0 : return false;
195 : :
196 : : case TYPE_INTERNAL_INT:
197 : 0 : return SERIALIZE(val.int_val);
198 : :
199 : : case TYPE_INTERNAL_UNSIGNED:
200 : 3 : return SERIALIZE(val.uint_val);
201 : :
202 : : case TYPE_INTERNAL_DOUBLE:
203 : 3 : return SERIALIZE(val.double_val);
204 : :
205 : : case TYPE_INTERNAL_STRING:
206 : 0 : return SERIALIZE_STR((const char*) val.string_val->Bytes(),
207 : : val.string_val->Len());
208 : :
209 : : case TYPE_INTERNAL_ADDR:
210 : : return SERIALIZE(NUM_ADDR_WORDS)
211 : : #ifdef BROv6
212 : : && SERIALIZE(uint32(ntohl(val.addr_val[0])))
213 : : && SERIALIZE(uint32(ntohl(val.addr_val[1])))
214 : : && SERIALIZE(uint32(ntohl(val.addr_val[2])))
215 : : && SERIALIZE(uint32(ntohl(val.addr_val[3])));
216 : : #else
217 [ # # ][ # # ]: 0 : && SERIALIZE(uint32(ntohl(val.addr_val)));
218 : : #endif
219 : :
220 : : case TYPE_INTERNAL_SUBNET:
221 : : return info->s->WriteOpenTag("subnet")
222 : : && SERIALIZE(NUM_ADDR_WORDS)
223 : : #ifdef BROv6
224 : : && SERIALIZE(uint32(ntohl(val.subnet_val.net[0])))
225 : : && SERIALIZE(uint32(ntohl(val.subnet_val.net[1])))
226 : : && SERIALIZE(uint32(ntohl(val.subnet_val.net[2])))
227 : : && SERIALIZE(uint32(ntohl(val.subnet_val.net[3])))
228 : : #else
229 : : && SERIALIZE(uint32(ntohl(val.subnet_val.net)))
230 : : #endif
231 : : && SERIALIZE(val.subnet_val.width)
232 [ # # ][ # # ]: 0 : && info->s->WriteCloseTag("subnet");
[ # # ][ # # ]
[ # # ]
233 : :
234 : : case TYPE_INTERNAL_OTHER:
235 : : // Derived classes are responsible for this.
236 : : // Exception: Functions and files. There aren't any derived
237 : : // classes.
238 [ - + ]: 1 : if ( type->Tag() == TYPE_FUNC )
239 [ # # ]: 0 : if ( ! AsFunc()->Serialize(info) )
240 : 0 : return false;
241 : :
242 [ - + ]: 1 : if ( type->Tag() == TYPE_FILE )
243 [ # # ]: 0 : if ( ! AsFile()->Serialize(info) )
244 : 0 : return false;
245 : 1 : return true;
246 : :
247 : : case TYPE_INTERNAL_ERROR:
248 : 0 : info->s->Error("type is error");
249 : 0 : return false;
250 : :
251 : : default:
252 : 0 : info->s->Error("type is out of range");
253 : 0 : return false;
254 : : }
255 : :
256 : : internal_error("should not be reached");
257 : 7 : return false;
258 : : }
259 : :
260 : 0 : bool Val::DoUnserialize(UnserialInfo* info)
261 : : {
262 [ # # ]: 0 : DO_UNSERIALIZE(BroObj);
263 : :
264 [ # # ]: 0 : if ( type )
265 : 0 : Unref(type);
266 : :
267 [ # # ]: 0 : if ( ! (type = BroType::Unserialize(info)) )
268 : 0 : return false;
269 : :
270 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(attribs,
[ # # ]
271 : : (RecordVal*) Val::Unserialize(info, TYPE_RECORD));
272 : :
273 [ # # # # # : 0 : switch ( type->InternalType() ) {
# # # # # ]
274 : : case TYPE_INTERNAL_VOID:
275 : 0 : info->s->Error("type is void");
276 : 0 : return false;
277 : :
278 : : case TYPE_INTERNAL_INT:
279 : 0 : return UNSERIALIZE(&val.int_val);
280 : :
281 : : case TYPE_INTERNAL_UNSIGNED:
282 : 0 : return UNSERIALIZE(&val.uint_val);
283 : :
284 : : case TYPE_INTERNAL_DOUBLE:
285 : 0 : return UNSERIALIZE(&val.double_val);
286 : :
287 : : case TYPE_INTERNAL_STRING:
288 : : const char* str;
289 : : int len;
290 [ # # ]: 0 : if ( ! UNSERIALIZE_STR(&str, &len) )
291 : 0 : return false;
292 : :
293 : 0 : val.string_val = new BroString((u_char*) str, len, 1);
294 [ # # ]: 0 : delete [] str;
295 : 0 : return true;
296 : :
297 : : case TYPE_INTERNAL_ADDR:
298 : : {
299 : : int num_words;
300 [ # # ]: 0 : if ( ! UNSERIALIZE(&num_words) )
301 : 0 : return false;
302 : :
303 [ # # ][ # # ]: 0 : if ( num_words != 1 && num_words != 4 )
304 : : {
305 : 0 : info->s->Error("bad address type");
306 : 0 : return false;
307 : : }
308 : :
309 : : uint32 a[4]; // big enough to hold either
310 : :
311 [ # # ]: 0 : for ( int i = 0; i < num_words; ++i )
312 : : {
313 [ # # ]: 0 : if ( ! UNSERIALIZE(&a[i]) )
314 : 0 : return false;
315 : :
316 : 0 : a[i] = htonl(a[i]);
317 : : }
318 : :
319 : : #ifndef BROv6
320 [ # # ]: 0 : if ( num_words == 4 )
321 : : {
322 [ # # ][ # # ]: 0 : if ( a[0] || a[1] || a[2] )
[ # # ]
323 : 0 : info->s->Warning("received IPv6 address, ignoring");
324 : 0 : ((AddrVal*) this)->Init(a[3]);
325 : : }
326 : : else
327 : 0 : ((AddrVal*) this)->Init(a[0]);
328 : : #else
329 : : if ( num_words == 1 )
330 : : ((AddrVal*) this)->Init(a[0]);
331 : : else
332 : : ((AddrVal*) this)->Init(a);
333 : : #endif
334 : : }
335 : 0 : return true;
336 : :
337 : : case TYPE_INTERNAL_SUBNET:
338 : : {
339 : : int num_words;
340 [ # # ]: 0 : if ( ! UNSERIALIZE(&num_words) )
341 : 0 : return false;
342 : :
343 [ # # ][ # # ]: 0 : if ( num_words != 1 && num_words != 4 )
344 : : {
345 : 0 : info->s->Error("bad subnet type");
346 : 0 : return false;
347 : : }
348 : :
349 : : uint32 a[4]; // big enough to hold either
350 : :
351 [ # # ]: 0 : for ( int i = 0; i < num_words; ++i )
352 : : {
353 [ # # ]: 0 : if ( ! UNSERIALIZE(&a[i]) )
354 : 0 : return false;
355 : :
356 : 0 : a[i] = htonl(a[i]);
357 : : }
358 : :
359 : : int width;
360 [ # # ]: 0 : if ( ! UNSERIALIZE(&width) )
361 : 0 : return false;
362 : :
363 : : #ifdef BROv6
364 : : if ( num_words == 1 )
365 : : {
366 : : a[3] = a[0];
367 : : a[0] = a[1] = a[2] = 0;
368 : : }
369 : :
370 : : ((SubNetVal*) this)->Init(a, width);
371 : :
372 : : #else
373 [ # # ]: 0 : if ( num_words == 4 )
374 : : {
375 [ # # ][ # # ]: 0 : if ( a[0] || a[1] || a[2] )
[ # # ]
376 : 0 : info->s->Warning("received IPv6 subnet, ignoring");
377 : 0 : a[0] = a[3];
378 : :
379 [ # # ]: 0 : if ( width > 32 )
380 : 0 : width -= 96;
381 : : }
382 : :
383 : 0 : ((SubNetVal*) this)->Init(a[0], width);
384 : : #endif
385 : : }
386 : 0 : return true;
387 : :
388 : : case TYPE_INTERNAL_OTHER:
389 : : // Derived classes are responsible for this.
390 : : // Exception: Functions and files. There aren't any derived
391 : : // classes.
392 [ # # ]: 0 : if ( type->Tag() == TYPE_FUNC )
393 : : {
394 : 0 : val.func_val = Func::Unserialize(info);
395 : 0 : return val.func_val != 0;
396 : : }
397 [ # # ]: 0 : else if ( type->Tag() == TYPE_FILE )
398 : : {
399 : 0 : val.file_val = BroFile::Unserialize(info);
400 : 0 : return val.file_val != 0;
401 : : }
402 : 0 : return true;
403 : :
404 : : case TYPE_INTERNAL_ERROR:
405 : 0 : info->s->Error("type is error");
406 : 0 : return false;
407 : :
408 : : default:
409 : 0 : info->s->Error("type out of range");
410 : 0 : return false;
411 : : }
412 : :
413 : : internal_error("should not be reached");
414 : 0 : return false;
415 : : }
416 : :
417 : 0 : RecordVal* Val::GetAttribs(bool instantiate)
418 : : {
419 [ # # ][ # # ]: 0 : if ( ! instantiate || attribs )
420 : 0 : return attribs;
421 : :
422 : 0 : attribs = new RecordVal(type->AttributesType());
423 : 0 : return attribs;
424 : : }
425 : :
426 : 275751 : int Val::IsZero() const
427 : : {
428 [ + + + - ]: 275751 : switch ( type->InternalType() ) {
429 : 275743 : case TYPE_INTERNAL_INT: return val.int_val == 0;
430 : 5 : case TYPE_INTERNAL_UNSIGNED: return val.uint_val == 0;
431 : 3 : case TYPE_INTERNAL_DOUBLE: return val.double_val == 0.0;
432 : :
433 : 275751 : default: return 0;
434 : : }
435 : : }
436 : :
437 : 0 : int Val::IsOne() const
438 : : {
439 [ # # # # ]: 0 : switch ( type->InternalType() ) {
440 : 0 : case TYPE_INTERNAL_INT: return val.int_val == 1;
441 : 0 : case TYPE_INTERNAL_UNSIGNED: return val.uint_val == 1;
442 : 0 : case TYPE_INTERNAL_DOUBLE: return val.double_val == 1.0;
443 : :
444 : 0 : default: return 0;
445 : : }
446 : : }
447 : :
448 : 86756 : bro_int_t Val::InternalInt() const
449 : : {
450 [ + + ]: 86756 : if ( type->InternalType() == TYPE_INTERNAL_INT )
451 : 86720 : return val.int_val;
452 [ + - ]: 36 : else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED )
453 : : // ### should check here for overflow
454 : 36 : return static_cast<bro_int_t>(val.uint_val);
455 : : else
456 : 0 : InternalWarning("bad request for InternalInt");
457 : :
458 : 86756 : return 0;
459 : : }
460 : :
461 : 81542 : bro_uint_t Val::InternalUnsigned() const
462 : : {
463 [ + - ]: 81542 : if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED )
464 : 81542 : return val.uint_val;
465 : : else
466 : 0 : InternalWarning("bad request for InternalUnsigned");
467 : :
468 : 81542 : return 0;
469 : : }
470 : :
471 : 1750 : double Val::InternalDouble() const
472 : : {
473 [ + - ]: 1750 : if ( type->InternalType() == TYPE_INTERNAL_DOUBLE )
474 : 1750 : return val.double_val;
475 : : else
476 : 0 : InternalWarning("bad request for InternalDouble");
477 : :
478 : 1750 : return 0.0;
479 : : }
480 : :
481 : 4784 : bro_int_t Val::CoerceToInt() const
482 : : {
483 [ + + ]: 4784 : if ( type->InternalType() == TYPE_INTERNAL_INT )
484 : 1042 : return val.int_val;
485 [ + - ]: 3742 : else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED )
486 : 3742 : return static_cast<bro_int_t>(val.uint_val);
487 [ # # ]: 0 : else if ( type->InternalType() == TYPE_INTERNAL_DOUBLE )
488 : 0 : return static_cast<bro_int_t>(val.double_val);
489 : : else
490 : 0 : InternalWarning("bad request for CoerceToInt");
491 : :
492 : 4784 : return 0;
493 : : }
494 : :
495 : 33026 : bro_uint_t Val::CoerceToUnsigned() const
496 : : {
497 [ + + ]: 33026 : if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED )
498 : 10962 : return val.uint_val;
499 [ + - ]: 22064 : else if ( type->InternalType() == TYPE_INTERNAL_INT )
500 : 22064 : return static_cast<bro_uint_t>(val.int_val);
501 [ # # ]: 0 : else if ( type->InternalType() == TYPE_INTERNAL_DOUBLE )
502 : 0 : return static_cast<bro_uint_t>(val.double_val);
503 : : else
504 : 0 : InternalWarning("bad request for CoerceToUnsigned");
505 : :
506 : 33026 : return 0;
507 : : }
508 : :
509 : 7717 : double Val::CoerceToDouble() const
510 : : {
511 [ + + ]: 7717 : if ( type->InternalType() == TYPE_INTERNAL_DOUBLE )
512 : 6333 : return val.double_val;
513 [ - + ]: 1384 : else if ( type->InternalType() == TYPE_INTERNAL_INT )
514 : 0 : return static_cast<double>(val.int_val);
515 [ + - ]: 1384 : else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED )
516 : 1384 : return static_cast<double>(val.uint_val);
517 : : else
518 : 0 : InternalWarning("bad request for CoerceToDouble");
519 : :
520 : 7717 : return 0.0;
521 : : }
522 : :
523 : 0 : Val* Val::SizeVal() const
524 : : {
525 [ # # # # : 0 : switch ( type->InternalType() ) {
# ]
526 : : case TYPE_INTERNAL_INT:
527 : 0 : return new Val(llabs(val.int_val), TYPE_COUNT);
528 : :
529 : : case TYPE_INTERNAL_UNSIGNED:
530 : 0 : return new Val(val.uint_val, TYPE_COUNT);
531 : :
532 : : case TYPE_INTERNAL_DOUBLE:
533 : 0 : return new Val(fabs(val.double_val), TYPE_DOUBLE);
534 : :
535 : : case TYPE_INTERNAL_OTHER:
536 [ # # ]: 0 : if ( type->Tag() == TYPE_FUNC )
537 : 0 : return new Val(val.func_val->FType()->ArgTypes()->Types()->length(), TYPE_COUNT);
538 : :
539 [ # # ]: 0 : if ( type->Tag() == TYPE_FILE )
540 : 0 : return new Val(val.file_val->Size(), TYPE_DOUBLE);
541 : : break;
542 : :
543 : : default:
544 : : break;
545 : : }
546 : :
547 : 0 : return new Val(0, TYPE_COUNT);
548 : : }
549 : :
550 : 0 : unsigned int Val::MemoryAllocation() const
551 : : {
552 : 0 : return padded_sizeof(*this);
553 : : }
554 : :
555 : 0 : int Val::AddTo(Val* v, int is_first_init) const
556 : : {
557 : 0 : Error("+= initializer only applies to aggregate values");
558 : 0 : return 0;
559 : : }
560 : :
561 : 0 : int Val::RemoveFrom(Val* v) const
562 : : {
563 : 0 : Error("-= initializer only applies to aggregate values");
564 : 0 : return 0;
565 : : }
566 : :
567 : 140490 : void Val::Describe(ODesc* d) const
568 : : {
569 [ + - ][ - + ]: 140490 : if ( d->IsBinary() || d->IsPortable() )
[ - + ]
570 : : {
571 : 0 : type->Describe(d);
572 : 0 : d->SP();
573 : : }
574 : :
575 [ + - ]: 140490 : if ( d->IsReadable() )
576 : 140490 : ValDescribe(d);
577 : : else
578 : 0 : Val::ValDescribe(d);
579 : 140490 : }
580 : :
581 : 10310 : void Val::ValDescribe(ODesc* d) const
582 : : {
583 [ + - ][ - + ]: 10310 : if ( d->IsReadable() && type->Tag() == TYPE_BOOL )
[ - + ]
584 : : {
585 [ # # ]: 0 : d->Add(CoerceToInt() ? "T" : "F");
586 : 10310 : return;
587 : : }
588 : :
589 [ - + - - + : 10310 : switch ( type->InternalType() ) {
- - - - - ]
590 : 0 : case TYPE_INTERNAL_INT: d->Add(val.int_val); break;
591 : 356 : case TYPE_INTERNAL_UNSIGNED: d->Add(val.uint_val); break;
592 : 0 : case TYPE_INTERNAL_DOUBLE: d->Add(val.double_val); break;
593 : 0 : case TYPE_INTERNAL_STRING: d->AddBytes(val.string_val); break;
594 : 9954 : case TYPE_INTERNAL_ADDR: d->Add(dotted_addr(val.addr_val)); break;
595 : :
596 : : case TYPE_INTERNAL_SUBNET:
597 : 0 : d->Add(dotted_addr(val.subnet_val.net));
598 : 0 : d->Add("/");
599 : 0 : d->Add(val.subnet_val.width);
600 : 0 : break;
601 : :
602 : 0 : case TYPE_INTERNAL_ERROR: d->AddCS("error"); break;
603 : : case TYPE_INTERNAL_OTHER:
604 [ # # ]: 0 : if ( type->Tag() == TYPE_FUNC )
605 : 0 : AsFunc()->Describe(d);
606 [ # # ]: 0 : else if ( type->Tag() == TYPE_FILE )
607 : 0 : AsFile()->Describe(d);
608 : : else
609 : 0 : d->Add("<no value description>");
610 : 0 : break;
611 : :
612 : : case TYPE_INTERNAL_VOID:
613 : 0 : d->Add("<void value description>");
614 : 0 : break;
615 : :
616 : : default:
617 : : // Don't call Internal(), that'll loop!
618 : 0 : internal_error("Val description unavailable");
619 : : }
620 : : }
621 : :
622 : 52549 : MutableVal::~MutableVal()
623 : : {
624 [ # # ][ # # ]: 52549 : for ( list<ID*>::iterator i = aliases.begin(); i != aliases.end(); ++i )
[ - + ]
625 : : {
626 : 0 : global_scope()->Remove((*i)->Name());
627 : 0 : (*i)->ClearVal(); // just to make sure.
628 : 0 : Unref((*i));
629 : : }
630 : :
631 [ # # ][ # # ]: 52549 : if ( id )
[ - + ]
632 : : {
633 : 0 : global_scope()->Remove(id->Name());
634 : 0 : id->ClearVal(); // just to make sure.
635 : 0 : Unref(id);
636 : : }
637 [ # # ][ # # ]: 52549 : }
[ - + ]
638 : :
639 : 619 : bool MutableVal::AddProperties(Properties arg_props)
640 : : {
641 [ + + ]: 619 : if ( (props | arg_props) == props )
642 : : // No change.
643 : 601 : return false;
644 : :
645 : 18 : props |= arg_props;
646 : :
647 [ + - ]: 18 : if ( ! id )
648 : 18 : Bind();
649 : :
650 : 619 : return true;
651 : : }
652 : :
653 : :
654 : 0 : bool MutableVal::RemoveProperties(Properties arg_props)
655 : : {
656 [ # # ]: 0 : if ( (props & ~arg_props) == props )
657 : : // No change.
658 : 0 : return false;
659 : :
660 : 0 : props &= ~arg_props;
661 : :
662 : 0 : return true;
663 : : }
664 : :
665 : 18 : ID* MutableVal::Bind() const
666 : : {
667 : : static bool initialized = false;
668 : :
669 [ - + ]: 18 : assert(!id);
670 : :
671 : : static unsigned int id_counter = 0;
672 : : static const int MAX_NAME_SIZE = 128;
673 : : static char name[MAX_NAME_SIZE];
674 : : static char* end_of_static_str = 0;
675 : :
676 [ + + ]: 18 : if ( ! initialized )
677 : : {
678 : : // Get local IP.
679 : : char host[MAXHOSTNAMELEN];
680 : 2 : strcpy(host, "localhost");
681 : 2 : gethostname(host, MAXHOSTNAMELEN);
682 : 2 : host[MAXHOSTNAMELEN-1] = '\0';
683 : : #if 0
684 : : // We ignore errors.
685 : : struct hostent* ent = gethostbyname(host);
686 : :
687 : : uint32 ip;
688 : : if ( ent && ent->h_addr_list[0] )
689 : : ip = *(uint32*) ent->h_addr_list[0];
690 : : else
691 : : ip = htonl(0x7f000001); // 127.0.0.1
692 : :
693 : : safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#",
694 : : dotted_addr(ip), getpid());
695 : : #else
696 : 2 : safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#", host, getpid());
697 : : #endif
698 : :
699 : 2 : end_of_static_str = name + strlen(name);
700 : :
701 : 2 : initialized = true;
702 : : }
703 : :
704 : : safe_snprintf(end_of_static_str, MAX_NAME_SIZE - (end_of_static_str - name),
705 : 18 : "%u", ++id_counter);
706 : 18 : name[MAX_NAME_SIZE-1] = '\0';
707 : :
708 : : // DBG_LOG(DBG_STATE, "new unique ID %s", name);
709 : :
710 : 18 : id = new ID(name, SCOPE_GLOBAL, true);
711 : 18 : id->SetType(const_cast<MutableVal*>(this)->Type()->Ref());
712 : :
713 : 18 : global_scope()->Insert(name, id);
714 : :
715 : 18 : id->SetVal(const_cast<MutableVal*>(this), OP_NONE, true);
716 : :
717 : 18 : return id;
718 : : }
719 : :
720 : 0 : void MutableVal::TransferUniqueID(MutableVal* mv)
721 : : {
722 : 0 : const char* new_name = mv->UniqueID()->Name();
723 : :
724 [ # # ]: 0 : if ( ! id )
725 : 0 : Bind();
726 : :
727 : 0 : DBG_LOG(DBG_STATE, "transfering ID (new %s, old/alias %s)", new_name, id->Name());
728 : :
729 : : // Keep old name as alias.
730 : 0 : aliases.push_back(id);
731 : :
732 : 0 : id = new ID(new_name, SCOPE_GLOBAL, true);
733 : 0 : id->SetType(const_cast<MutableVal*>(this)->Type()->Ref());
734 : 0 : global_scope()->Insert(new_name, id);
735 : 0 : id->SetVal(const_cast<MutableVal*>(this), OP_NONE, true);
736 : :
737 : 0 : Unref(mv->id);
738 : 0 : mv->id = 0;
739 : 0 : }
740 : :
741 : 3 : IMPLEMENT_SERIAL(MutableVal, SER_MUTABLE_VAL);
742 : :
743 : 1 : bool MutableVal::DoSerialize(SerialInfo* info) const
744 : : {
745 [ - + ][ - + ]: 1 : DO_SERIALIZE(SER_MUTABLE_VAL, Val);
746 : :
747 [ - + ]: 1 : if ( ! SERIALIZE(props) )
748 : 0 : return false;
749 : :
750 : : // Don't use ID::Serialize here, that would loop. All we
751 : : // need is the name, anyway.
752 [ + - ]: 1 : const char* name = id ? id->Name() : "";
753 [ - + ]: 1 : if ( ! SERIALIZE(name) )
754 : 0 : return false;
755 : :
756 : 1 : return true;
757 : : }
758 : :
759 : 0 : bool MutableVal::DoUnserialize(UnserialInfo* info)
760 : : {
761 [ # # ]: 0 : DO_UNSERIALIZE(Val);
762 : :
763 [ # # ]: 0 : if ( ! UNSERIALIZE(&props) )
764 : 0 : return false;
765 : :
766 : 0 : id = 0;
767 : :
768 : : const char* name;
769 [ # # ]: 0 : if ( ! UNSERIALIZE_STR(&name, 0) )
770 : 0 : return false;
771 : :
772 [ # # ]: 0 : if ( *name )
773 : : {
774 : 0 : id = new ID(name, SCOPE_GLOBAL, true);
775 : 0 : id->SetVal(this, OP_NONE, true);
776 : :
777 : 0 : ID* current = global_scope()->Lookup(name);
778 [ # # ]: 0 : if ( ! current )
779 : : {
780 : 0 : global_scope()->Insert(name, id);
781 : 0 : DBG_LOG(DBG_STATE, "installed formerly unknown ID %s", id->Name());
782 : : }
783 : : else
784 : : {
785 : 0 : DBG_LOG(DBG_STATE, "got already known ID %s", current->Name());
786 : : // This means that we already know the value and
787 : : // that in fact we should bind to the local value.
788 : : // Val::Unserialize() will take care of this.
789 : : }
790 : : }
791 : :
792 [ # # ]: 0 : delete [] name;
793 : 0 : return true;
794 : : }
795 : :
796 : 332 : IntervalVal::IntervalVal(double quantity, double units) :
797 : 332 : Val(quantity * units, TYPE_INTERVAL)
798 : : {
799 : 332 : }
800 : :
801 : 0 : void IntervalVal::ValDescribe(ODesc* d) const
802 : : {
803 : 0 : double v = val.double_val;
804 : :
805 [ # # ]: 0 : if ( v == 0.0 )
806 : : {
807 : 0 : d->Add("0 secs");
808 : 0 : return;
809 : : }
810 : :
811 : 0 : int did_one = 0;
812 : :
813 : : #define DO_UNIT(unit, name) \
814 : : if ( v >= unit || v <= -unit ) \
815 : : { \
816 : : double num = double(int(v / unit)); \
817 : : if ( num != 0.0 ) \
818 : : { \
819 : : if ( did_one++ ) \
820 : : d->SP(); \
821 : : d->Add(num); \
822 : : d->SP(); \
823 : : d->Add(name); \
824 : : if ( num != 1.0 && num != -1.0 ) \
825 : : d->Add("s"); \
826 : : v -= num * unit; \
827 : : } \
828 : : }
829 : :
830 [ # # ][ # # ]: 0 : DO_UNIT(Days, "day")
[ # # ][ # # ]
[ # # ][ # # ]
831 [ # # ][ # # ]: 0 : DO_UNIT(Hours, "hr")
[ # # ][ # # ]
[ # # ][ # # ]
832 [ # # ][ # # ]: 0 : DO_UNIT(Minutes, "min")
[ # # ][ # # ]
[ # # ][ # # ]
833 [ # # ][ # # ]: 0 : DO_UNIT(Seconds, "sec")
[ # # ][ # # ]
[ # # ][ # # ]
834 [ # # ][ # # ]: 0 : DO_UNIT(Milliseconds, "msec")
[ # # ][ # # ]
[ # # ][ # # ]
835 [ # # ][ # # ]: 0 : DO_UNIT(Microseconds, "usec")
[ # # ][ # # ]
[ # # ][ # # ]
836 : : }
837 : :
838 : 9 : IMPLEMENT_SERIAL(IntervalVal, SER_INTERVAL_VAL);
839 : :
840 : 3 : bool IntervalVal::DoSerialize(SerialInfo* info) const
841 : : {
842 [ + - ][ - + ]: 3 : DO_SERIALIZE(SER_INTERVAL_VAL, Val);
843 : 3 : return true;
844 : : }
845 : :
846 : 0 : bool IntervalVal::DoUnserialize(UnserialInfo* info)
847 : : {
848 [ # # ]: 0 : DO_UNSERIALIZE(Val);
849 : 0 : return true;
850 : : }
851 : :
852 : 5111 : PortVal::PortVal(uint32 p, TransportProto port_type) : Val(TYPE_PORT)
853 : : {
854 : : // Note, for ICMP one-way connections:
855 : : // src_port = icmp_type, dst_port = icmp_code.
856 : :
857 [ - + # # ]: 5111 : if ( p >= 65536 )
858 : : {
859 : 0 : InternalWarning("bad port number");
860 : 0 : p = 0;
861 : : }
862 : :
863 [ + + + - ]: 5111 : switch ( port_type ) {
[ # # # # ]
864 : : case TRANSPORT_TCP:
865 : 3661 : p |= TCP_PORT_MASK;
866 : 3661 : break;
867 : :
868 : : case TRANSPORT_UDP:
869 : 1434 : p |= UDP_PORT_MASK;
870 : 1434 : break;
871 : :
872 : : case TRANSPORT_ICMP:
873 : 16 : p |= ICMP_PORT_MASK;
874 : : break;
875 : :
876 : : default:
877 : : break; // "other"
878 : : }
879 : :
880 : 5111 : val.uint_val = static_cast<bro_uint_t>(p);
881 : 5111 : }
882 : :
883 : 125 : PortVal::PortVal(uint32 p) : Val(TYPE_PORT)
884 : : {
885 [ - + # # ]: 125 : if ( p >= 65536 * NUM_PORT_SPACES )
886 : : {
887 : 0 : InternalWarning("bad port number");
888 : 0 : p = 0;
889 : : }
890 : :
891 : 125 : val.uint_val = static_cast<bro_uint_t>(p);
892 : 125 : }
893 : :
894 : 6895 : uint32 PortVal::Port() const
895 : : {
896 : 6895 : uint32 p = static_cast<uint32>(val.uint_val);
897 : 6895 : return p & ~PORT_SPACE_MASK;
898 : : }
899 : :
900 : 3572 : int PortVal::IsTCP() const
901 : : {
902 : 3572 : return (val.uint_val & PORT_SPACE_MASK) == TCP_PORT_MASK;
903 : : }
904 : :
905 : 1951 : int PortVal::IsUDP() const
906 : : {
907 : 1951 : return (val.uint_val & PORT_SPACE_MASK) == UDP_PORT_MASK;
908 : : }
909 : :
910 : 5 : int PortVal::IsICMP() const
911 : : {
912 : 5 : return (val.uint_val & PORT_SPACE_MASK) == ICMP_PORT_MASK;
913 : : }
914 : :
915 : 1262 : void PortVal::ValDescribe(ODesc* d) const
916 : : {
917 : 1262 : uint32 p = static_cast<uint32>(val.uint_val);
918 : 1262 : d->Add(p & ~PORT_SPACE_MASK);
919 [ - + ]: 1262 : if ( IsUDP() )
920 : 0 : d->Add("/udp");
921 [ + - ]: 1262 : else if ( IsTCP() )
922 : 1262 : d->Add("/tcp");
923 [ # # ]: 0 : else if ( IsICMP() )
924 : 0 : d->Add("/icmp");
925 : : else
926 : 0 : d->Add("/unknown");
927 : 1262 : }
928 : :
929 : 3 : IMPLEMENT_SERIAL(PortVal, SER_PORT_VAL);
930 : :
931 : 0 : bool PortVal::DoSerialize(SerialInfo* info) const
932 : : {
933 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_PORT_VAL, Val);
934 : 0 : return true;
935 : : }
936 : :
937 : 0 : bool PortVal::DoUnserialize(UnserialInfo* info)
938 : : {
939 [ # # ]: 0 : DO_UNSERIALIZE(Val);
940 : 0 : return true;
941 : : }
942 : :
943 : 43 : AddrVal::AddrVal(const char* text) : Val(TYPE_ADDR)
944 : : {
945 : 43 : const char* colon = strchr(text, ':');
946 : :
947 [ - + # # ]: 43 : if ( colon )
948 : : {
949 : : #ifdef BROv6
950 : : Init(dotted_to_addr6(text));
951 : : #else
952 : 0 : error("bro wasn't compiled with IPv6 support");
953 : 0 : Init(uint32(0));
954 : : #endif
955 : : }
956 : :
957 : : else
958 : 43 : Init(dotted_to_addr(text));
959 : 43 : }
960 : :
961 : 158 : AddrVal::AddrVal(uint32 addr) : Val(TYPE_ADDR)
962 : : {
963 : : // ### perhaps do gethostbyaddr here?
964 : 158 : Init(addr);
965 : 158 : }
966 : :
967 : 4634 : AddrVal::AddrVal(const uint32* addr) : Val(TYPE_ADDR)
968 : : {
969 : 4634 : Init(addr);
970 : 4634 : }
971 : :
972 : 4734 : AddrVal::~AddrVal()
973 : : {
974 : : #ifdef BROv6
975 : : delete [] val.addr_val;
976 : : #endif
977 [ + - ][ # # ]: 4734 : }
[ # # ]
978 : :
979 : 0 : Val* AddrVal::SizeVal() const
980 : : {
981 : : uint32 addr;
982 : :
983 : : #ifdef BROv6
984 : : if ( ! is_v4_addr(val.addr_val) )
985 : : {
986 : : RunTime("|addr| for IPv6 addresses not supported");
987 : : return new Val(0, TYPE_COUNT);
988 : : }
989 : :
990 : : addr = to_v4_addr(val.addr_val);
991 : : #else
992 : 0 : addr = val.addr_val;
993 : : #endif
994 : :
995 : 0 : addr = ntohl(addr);
996 : :
997 : 0 : return new Val(addr, TYPE_COUNT);
998 : : }
999 : :
1000 : 201 : void AddrVal::Init(uint32 addr)
1001 : : {
1002 : : #ifdef BROv6
1003 : : val.addr_val = new uint32[4];
1004 : : val.addr_val[0] = val.addr_val[1] = val.addr_val[2] = 0;
1005 : : val.addr_val[3] = addr;
1006 : : #else
1007 : 201 : val.addr_val = addr;
1008 : : #endif
1009 : 201 : }
1010 : :
1011 : 4634 : void AddrVal::Init(const uint32* addr)
1012 : : {
1013 : : #ifdef BROv6
1014 : : val.addr_val = new uint32[4];
1015 : : val.addr_val[0] = addr[0];
1016 : : val.addr_val[1] = addr[1];
1017 : : val.addr_val[2] = addr[2];
1018 : : val.addr_val[3] = addr[3];
1019 : : #else
1020 : 4634 : val.addr_val = addr[0];
1021 : : #endif
1022 : 4634 : }
1023 : :
1024 : 0 : unsigned int AddrVal::MemoryAllocation() const
1025 : : {
1026 : : #ifdef BROv6
1027 : : return padded_sizeof(*this) + pad_size(4 * sizeof(uint32));
1028 : : #else
1029 : 0 : return padded_sizeof(*this);
1030 : : #endif
1031 : : }
1032 : :
1033 : 3 : IMPLEMENT_SERIAL(AddrVal, SER_ADDR_VAL);
1034 : :
1035 : 0 : bool AddrVal::DoSerialize(SerialInfo* info) const
1036 : : {
1037 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ADDR_VAL, Val);
1038 : 0 : return true;
1039 : : }
1040 : :
1041 : 0 : bool AddrVal::DoUnserialize(UnserialInfo* info)
1042 : : {
1043 [ # # ]: 0 : DO_UNSERIALIZE(Val);
1044 : 0 : return true;
1045 : : }
1046 : :
1047 : 0 : static uint32 parse_dotted(const char* text, int& dots)
1048 : : {
1049 : : int addr[4];
1050 : 0 : uint32 a = 0;
1051 : 0 : dots = 0;
1052 : :
1053 [ # # ]: 0 : if ( sscanf(text, "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) == 4 )
1054 : : {
1055 : : a = (addr[0] << 24) | (addr[1] << 16) |
1056 : 0 : (addr[2] << 8) | addr[3];
1057 : 0 : dots = 3;
1058 : : }
1059 : :
1060 [ # # ]: 0 : else if ( sscanf(text, "%d.%d.%d", addr+0, addr+1, addr+2) == 3 )
1061 : : {
1062 : 0 : a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8);
1063 : 0 : dots = 2;
1064 : : }
1065 : :
1066 [ # # ]: 0 : else if ( sscanf(text, "%d.%d", addr+0, addr+1) == 2 )
1067 : : {
1068 : 0 : a = (addr[0] << 24) | (addr[1] << 16);
1069 : 0 : dots = 1;
1070 : : }
1071 : :
1072 : : else
1073 : 0 : internal_error("scanf failed in parse_dotted()");
1074 : :
1075 [ # # ]: 0 : for ( int i = 0; i <= dots; ++i )
1076 : : {
1077 [ # # ][ # # ]: 0 : if ( addr[i] < 0 || addr[i] > 255 )
1078 : : {
1079 : 0 : error("bad dotted address", text);
1080 : 0 : break;
1081 : : }
1082 : : }
1083 : :
1084 : 0 : return a;
1085 : : }
1086 : :
1087 : 0 : NetVal::NetVal(const char* text) : AddrVal(TYPE_NET)
1088 : : {
1089 : : int dots;
1090 : 0 : uint32 a = parse_dotted(text, dots);
1091 : :
1092 [ # # # # ]: 0 : if ( addr_to_net(a) != a )
1093 : 0 : error("bad net address", text);
1094 : :
1095 : 0 : Init(uint32(htonl(a)));
1096 : 0 : }
1097 : :
1098 : 0 : NetVal::NetVal(uint32 addr) : AddrVal(TYPE_NET)
1099 : : {
1100 : 0 : Init(addr);
1101 : 0 : }
1102 : :
1103 : : #ifdef BROv6
1104 : : NetVal::NetVal(const uint32* addr) : AddrVal(TYPE_NET)
1105 : : {
1106 : : Init(addr);
1107 : : }
1108 : : #endif
1109 : :
1110 : 0 : Val* NetVal::SizeVal() const
1111 : : {
1112 : : uint32 addr;
1113 : :
1114 : : #ifdef BROv6
1115 : : if ( ! is_v4_addr(val.addr_val) )
1116 : : {
1117 : : RunTime("|net| for IPv6 addresses not supported");
1118 : : return new Val(0.0, TYPE_DOUBLE);
1119 : : }
1120 : :
1121 : : addr = to_v4_addr(val.addr_val);
1122 : : #else
1123 : 0 : addr = val.addr_val;
1124 : : #endif
1125 : 0 : addr = ntohl(addr);
1126 : :
1127 [ # # ]: 0 : if ( (addr & 0xFFFFFFFF) == 0L )
1128 : 0 : return new Val(4294967296.0, TYPE_DOUBLE);
1129 : :
1130 [ # # ]: 0 : if ( (addr & 0x00FFFFFF) == 0L )
1131 : 0 : return new Val(double(0xFFFFFF + 1), TYPE_DOUBLE);
1132 : :
1133 [ # # ]: 0 : if ( (addr & 0x0000FFFF) == 0L )
1134 : 0 : return new Val(double(0xFFFF + 1), TYPE_DOUBLE);
1135 : :
1136 [ # # ]: 0 : if ( (addr & 0x000000FF) == 0L )
1137 : 0 : return new Val(double(0xFF + 1), TYPE_DOUBLE);
1138 : :
1139 : 0 : return new Val(1.0, TYPE_DOUBLE);
1140 : : }
1141 : :
1142 : 0 : void NetVal::ValDescribe(ODesc* d) const
1143 : : {
1144 : : #ifdef BROv6
1145 : : d->Add(dotted_net6(val.addr_val));
1146 : : #else
1147 : 0 : d->Add(dotted_net(val.addr_val));
1148 : : #endif
1149 : 0 : }
1150 : :
1151 : 3 : IMPLEMENT_SERIAL(NetVal, SER_NET_VAL);
1152 : :
1153 : 0 : bool NetVal::DoSerialize(SerialInfo* info) const
1154 : : {
1155 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_NET_VAL, AddrVal);
1156 : 0 : return true;
1157 : : }
1158 : :
1159 : 0 : bool NetVal::DoUnserialize(UnserialInfo* info)
1160 : : {
1161 [ # # ]: 0 : DO_UNSERIALIZE(AddrVal);
1162 : 0 : return true;
1163 : : }
1164 : :
1165 : 0 : SubNetVal::SubNetVal(const char* text) : Val(TYPE_SUBNET)
1166 : : {
1167 : 0 : const char* sep = strchr(text, '/');
1168 [ # # # # ]: 0 : if ( ! sep )
1169 : 0 : Internal("separator missing in SubNetVal::SubNetVal");
1170 : :
1171 : 0 : Init(text, atoi(sep+1));
1172 : 0 : }
1173 : :
1174 : 0 : SubNetVal::SubNetVal(const char* text, int width) : Val(TYPE_SUBNET)
1175 : : {
1176 : 0 : Init(text, width);
1177 : 0 : }
1178 : :
1179 : 14 : SubNetVal::SubNetVal(uint32 addr, int width) : Val(TYPE_SUBNET)
1180 : : {
1181 : 14 : Init(addr, width);
1182 : 14 : }
1183 : :
1184 : : #ifdef BROv6
1185 : : SubNetVal::SubNetVal(const uint32* addr, int width) : Val(TYPE_SUBNET)
1186 : : {
1187 : : Init(addr, width);
1188 : : }
1189 : : #endif
1190 : :
1191 : 0 : void SubNetVal::Init(const char* text, int width)
1192 : : {
1193 : : #ifdef BROv6
1194 : : if ( width <= 0 || width > 128 )
1195 : : #else
1196 [ # # ][ # # ]: 0 : if ( width <= 0 || width > 32 )
1197 : : #endif
1198 : 0 : Error("bad subnet width");
1199 : :
1200 : : int dots;
1201 : 0 : uint32 a = parse_dotted(text, dots);
1202 : :
1203 : 0 : Init(uint32(htonl(a)), width);
1204 : 0 : }
1205 : :
1206 : :
1207 : 14 : void SubNetVal::Init(uint32 addr, int width)
1208 : : {
1209 : : #ifdef BROv6
1210 : : Internal("SubNetVal::Init called on 4-byte address w/ BROv6");
1211 : : #else
1212 : 14 : val.subnet_val.net = mask_addr(addr, uint32(width));
1213 : 14 : val.subnet_val.width = width;
1214 : : #endif
1215 : 14 : }
1216 : :
1217 : 0 : void SubNetVal::Init(const uint32* addr, int width)
1218 : : {
1219 : : #ifdef BROv6
1220 : : const uint32* a = mask_addr(addr, uint32(width));
1221 : :
1222 : : val.subnet_val.net[0] = a[0];
1223 : : val.subnet_val.net[1] = a[1];
1224 : : val.subnet_val.net[2] = a[2];
1225 : : val.subnet_val.net[3] = a[3];
1226 : :
1227 : : if ( is_v4_addr(addr) && width <= 32 )
1228 : : val.subnet_val.width = width + 96;
1229 : : else
1230 : : val.subnet_val.width = width;
1231 : : #else
1232 : 0 : Internal("SubNetVal::Init called on 16-byte address w/o BROv6");
1233 : : #endif
1234 : 0 : }
1235 : :
1236 : 0 : Val* SubNetVal::SizeVal() const
1237 : : {
1238 : : int retained;
1239 : : #ifdef BROv6
1240 : : retained = 128 - Width();
1241 : : #else
1242 : 0 : retained = 32 - Width();
1243 : : #endif
1244 : :
1245 : 0 : return new Val(pow(2.0, double(retained)), TYPE_DOUBLE);
1246 : : }
1247 : :
1248 : 0 : void SubNetVal::ValDescribe(ODesc* d) const
1249 : : {
1250 : 0 : d->Add(dotted_addr(val.subnet_val.net, d->Style() == ALTERNATIVE_STYLE));
1251 : 0 : d->Add("/");
1252 : : #ifdef BROv6
1253 : : if ( is_v4_addr(val.subnet_val.net) )
1254 : : d->Add(val.subnet_val.width - 96);
1255 : : else
1256 : : #endif
1257 : 0 : d->Add(val.subnet_val.width);
1258 : 0 : }
1259 : :
1260 : 0 : addr_type SubNetVal::Mask() const
1261 : : {
1262 [ # # ]: 0 : if ( val.subnet_val.width == 0 )
1263 : : {
1264 : : // We need to special-case a mask width of zero, since
1265 : : // the compiler doesn't guarantee that 1 << 32 yields 0.
1266 : : #ifdef BROv6
1267 : : uint32* m = new uint32[4];
1268 : : for ( int i = 0; i < 4; ++i )
1269 : : m[i] = 0;
1270 : :
1271 : : return m;
1272 : : #else
1273 : 0 : return 0;
1274 : : #endif
1275 : : }
1276 : :
1277 : : #ifdef BROv6
1278 : : uint32* m = new uint32[4];
1279 : : uint32* mp = m;
1280 : :
1281 : : uint32 w;
1282 : : for ( w = val.subnet_val.width; w >= 32; w -= 32 )
1283 : : *(mp++) = 0xffffffff;
1284 : :
1285 : : *mp = ~((1 << (32 - w)) - 1);
1286 : :
1287 : : while ( ++mp < m + 4 )
1288 : : *mp = 0;
1289 : :
1290 : : return m;
1291 : :
1292 : : #else
1293 : 0 : return ~((1 << (32 - val.subnet_val.width)) - 1);
1294 : : #endif
1295 : : }
1296 : :
1297 : 0 : bool SubNetVal::Contains(const uint32 addr) const
1298 : : {
1299 : : #ifdef BROv6
1300 : : Internal("SubNetVal::Contains called on 4-byte address w/ BROv6");
1301 : : return false;
1302 : : #else
1303 : 0 : return ntohl(val.subnet_val.net) == (ntohl(addr) & Mask());
1304 : : #endif
1305 : : }
1306 : :
1307 : 0 : bool SubNetVal::Contains(const uint32* addr) const
1308 : : {
1309 : : #ifdef BROv6
1310 : : const uint32* net = val.subnet_val.net;
1311 : : const uint32* a = addr;
1312 : : uint32 m;
1313 : :
1314 : : for ( m = val.subnet_val.width; m > 32; m -= 32 )
1315 : : {
1316 : : if ( *net != *a )
1317 : : return false;
1318 : :
1319 : : ++net;
1320 : : ++a;
1321 : : }
1322 : :
1323 : : uint32 mask = ~((1 << (32 - m)) - 1);
1324 : : return ntohl(*net) == (ntohl(*a) & mask);
1325 : : #else
1326 : 0 : return Contains(addr[3]);
1327 : : #endif
1328 : : }
1329 : :
1330 : 3 : IMPLEMENT_SERIAL(SubNetVal, SER_SUBNET_VAL);
1331 : :
1332 : 0 : bool SubNetVal::DoSerialize(SerialInfo* info) const
1333 : : {
1334 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_SUBNET_VAL, Val);
1335 : 0 : return true;
1336 : : }
1337 : :
1338 : 0 : bool SubNetVal::DoUnserialize(UnserialInfo* info)
1339 : : {
1340 [ # # ]: 0 : DO_UNSERIALIZE(Val);
1341 : 0 : return true;
1342 : : }
1343 : :
1344 : 120151 : StringVal::StringVal(BroString* s) : Val(TYPE_STRING)
1345 : : {
1346 : 120151 : val.string_val = s;
1347 : 120151 : }
1348 : :
1349 : 41018 : StringVal::StringVal(int length, const char* s) : Val(TYPE_STRING)
1350 : : {
1351 : : // The following adds a NUL at the end.
1352 : 41018 : val.string_val = new BroString((const u_char*) s, length, 1);
1353 : 41018 : }
1354 : :
1355 : 27298 : StringVal::StringVal(const char* s) : Val(TYPE_STRING)
1356 : : {
1357 : 27298 : val.string_val = new BroString(s);
1358 : 27298 : }
1359 : :
1360 : 8886 : StringVal* StringVal::ToUpper()
1361 : : {
1362 : 8886 : val.string_val->ToUpper();
1363 : 8886 : return this;
1364 : : }
1365 : :
1366 : 123071 : void StringVal::ValDescribe(ODesc* d) const
1367 : : {
1368 : : // Should reintroduce escapes ? ###
1369 [ - + ]: 123071 : if ( d->WantQuotes() )
1370 : 0 : d->Add("\"");
1371 : 123071 : d->AddBytes(val.string_val);
1372 [ - + ]: 123071 : if ( d->WantQuotes() )
1373 : 0 : d->Add("\"");
1374 : 123071 : }
1375 : :
1376 : 0 : unsigned int StringVal::MemoryAllocation() const
1377 : : {
1378 : 0 : return padded_sizeof(*this) + val.string_val->MemoryAllocation();
1379 : : }
1380 : :
1381 : 3 : IMPLEMENT_SERIAL(StringVal, SER_STRING_VAL);
1382 : :
1383 : 0 : bool StringVal::DoSerialize(SerialInfo* info) const
1384 : : {
1385 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_STRING_VAL, Val);
1386 : 0 : return true;
1387 : : }
1388 : :
1389 : 0 : bool StringVal::DoUnserialize(UnserialInfo* info)
1390 : : {
1391 [ # # ]: 0 : DO_UNSERIALIZE(Val);
1392 : 0 : return true;
1393 : : }
1394 : :
1395 : 220 : PatternVal::PatternVal(RE_Matcher* re) : Val(base_type(TYPE_PATTERN))
1396 : : {
1397 : 220 : val.re_val = re;
1398 : 220 : }
1399 : :
1400 : 0 : PatternVal::~PatternVal()
1401 : : {
1402 [ # # ][ # # ]: 0 : delete AsPattern();
[ # # ]
1403 : 0 : Unref(type); // base_type() ref'd it, so did our base constructor
1404 [ # # ][ # # ]: 0 : }
[ # # ]
1405 : :
1406 : 2 : int PatternVal::AddTo(Val* v, int /* is_first_init */) const
1407 : : {
1408 [ - + ]: 2 : if ( v->Type()->Tag() != TYPE_PATTERN )
1409 : : {
1410 : 0 : v->Error("not a pattern");
1411 : 0 : return 0;
1412 : : }
1413 : :
1414 : 2 : PatternVal* pv = v->AsPatternVal();
1415 : :
1416 : 4 : RE_Matcher* re = new RE_Matcher(AsPattern()->PatternText());
1417 : 2 : re->AddPat(pv->AsPattern()->PatternText());
1418 : 2 : re->Compile();
1419 : :
1420 : 2 : pv->SetMatcher(re);
1421 : :
1422 : 2 : return 1;
1423 : : }
1424 : :
1425 : 2 : void PatternVal::SetMatcher(RE_Matcher* re)
1426 : : {
1427 [ + - ]: 2 : delete AsPattern();
1428 : 2 : val.re_val = re;
1429 : 2 : }
1430 : :
1431 : 0 : void PatternVal::ValDescribe(ODesc* d) const
1432 : : {
1433 : 0 : d->Add("/");
1434 : 0 : d->Add(AsPattern()->PatternText());
1435 : 0 : d->Add("/");
1436 : 0 : }
1437 : :
1438 : 0 : unsigned int PatternVal::MemoryAllocation() const
1439 : : {
1440 : 0 : return padded_sizeof(*this) + val.re_val->MemoryAllocation();
1441 : : }
1442 : :
1443 : 3 : IMPLEMENT_SERIAL(PatternVal, SER_PATTERN_VAL);
1444 : :
1445 : 0 : bool PatternVal::DoSerialize(SerialInfo* info) const
1446 : : {
1447 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_PATTERN_VAL, Val);
1448 : 0 : return AsPattern()->Serialize(info);
1449 : : }
1450 : :
1451 : 0 : bool PatternVal::DoUnserialize(UnserialInfo* info)
1452 : : {
1453 [ # # ]: 0 : DO_UNSERIALIZE(Val);
1454 : :
1455 : 0 : val.re_val = RE_Matcher::Unserialize(info);
1456 : 0 : return val.re_val != 0;
1457 : : }
1458 : :
1459 : 144442 : ListVal::ListVal(TypeTag t)
1460 [ + + ][ # # ]: 144442 : : Val(new TypeList(t == TYPE_ANY ? 0 : base_type(t)))
1461 : : {
1462 : 144442 : tag = t;
1463 : 144442 : }
1464 : :
1465 : 144373 : ListVal::~ListVal()
1466 : : {
1467 [ + + ][ + + ]: 297282 : loop_over_list(vals, i)
[ # # ]
1468 : 152909 : Unref(vals[i]);
1469 : 144373 : Unref(type);
1470 [ + - ][ - + ]: 144373 : }
[ # # ]
1471 : :
1472 : 0 : const char* ListVal::IncludedInString(const char* str) const
1473 : : {
1474 [ # # ]: 0 : if ( tag != TYPE_STRING )
1475 : 0 : Internal("non-string list in ListVal::IncludedInString");
1476 : :
1477 [ # # ]: 0 : loop_over_list(vals, i)
1478 : : {
1479 : 0 : const char* vs = (const char*) (vals[i]->AsString()->Bytes());
1480 : :
1481 : 0 : const char* embedded = strstr(str, vs);
1482 [ # # ]: 0 : if ( embedded )
1483 : 0 : return embedded;
1484 : : }
1485 : :
1486 : 0 : return 0;
1487 : : }
1488 : :
1489 : 0 : RE_Matcher* ListVal::BuildRE() const
1490 : : {
1491 [ # # ]: 0 : if ( tag != TYPE_STRING )
1492 : 0 : Internal("non-string list in ListVal::IncludedInString");
1493 : :
1494 : 0 : RE_Matcher* re = new RE_Matcher();
1495 [ # # ]: 0 : loop_over_list(vals, i)
1496 : : {
1497 : 0 : const char* vs = (const char*) (vals[i]->AsString()->Bytes());
1498 : 0 : re->AddPat(vs);
1499 : : }
1500 : :
1501 : 0 : return re;
1502 : : }
1503 : :
1504 : 153017 : void ListVal::Append(Val* v)
1505 : : {
1506 [ + + ]: 153017 : if ( type->AsTypeList()->IsPure() )
1507 : : {
1508 [ - + ]: 162 : if ( v->Type()->Tag() != tag )
1509 : 0 : Internal("heterogeneous list in ListVal::Append");
1510 : : }
1511 : :
1512 : 153017 : vals.append(v);
1513 : 153017 : type->AsTypeList()->Append(v->Type()->Ref());
1514 : 153017 : }
1515 : :
1516 : 57 : TableVal* ListVal::ConvertToSet() const
1517 : : {
1518 [ - + ]: 57 : if ( tag == TYPE_ANY )
1519 : 0 : Internal("conversion of heterogeneous list to set");
1520 : :
1521 : 57 : TypeList* set_index = new TypeList(type->AsTypeList()->PureType());
1522 : 57 : set_index->Append(base_type(tag));
1523 : 57 : SetType* s = new SetType(set_index, 0);
1524 : 57 : TableVal* t = new TableVal(s);
1525 : :
1526 [ + + ]: 114 : loop_over_list(vals, i)
1527 : 57 : t->Assign(vals[i], 0);
1528 : :
1529 : 57 : return t;
1530 : : }
1531 : :
1532 : 0 : void ListVal::Describe(ODesc* d) const
1533 : : {
1534 [ # # ][ # # ]: 0 : if ( d->IsBinary() || d->IsPortable() )
[ # # ]
1535 : : {
1536 : 0 : type->Describe(d);
1537 : 0 : d->SP();
1538 : 0 : d->Add(vals.length());
1539 : 0 : d->SP();
1540 : : }
1541 : :
1542 [ # # ]: 0 : loop_over_list(vals, i)
1543 : : {
1544 [ # # ]: 0 : if ( i > 0 )
1545 : : {
1546 [ # # ][ # # ]: 0 : if ( d->IsReadable() || d->IsPortable() )
[ # # ]
1547 : : {
1548 : 0 : d->Add(",");
1549 : 0 : d->SP();
1550 : : }
1551 : : }
1552 : :
1553 : 0 : vals[i]->Describe(d);
1554 : : }
1555 : 0 : }
1556 : :
1557 : 3 : IMPLEMENT_SERIAL(ListVal, SER_LIST_VAL);
1558 : :
1559 : 0 : bool ListVal::DoSerialize(SerialInfo* info) const
1560 : : {
1561 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_LIST_VAL, Val);
1562 : :
1563 [ # # ][ # # ]: 0 : if ( ! (SERIALIZE(char(tag)) && SERIALIZE(vals.length())) )
[ # # ]
1564 : 0 : return false;
1565 : :
1566 [ # # ]: 0 : loop_over_list(vals, i)
1567 : : {
1568 [ # # ]: 0 : if ( ! vals[i]->Serialize(info) )
1569 : 0 : return false;
1570 : : }
1571 : :
1572 : 0 : return true;
1573 : : }
1574 : :
1575 : 0 : bool ListVal::DoUnserialize(UnserialInfo* info)
1576 : : {
1577 [ # # ]: 0 : DO_UNSERIALIZE(Val);
1578 : :
1579 : : char t;
1580 : : int len;
1581 : :
1582 [ # # ][ # # ]: 0 : if ( ! (UNSERIALIZE(&t) && UNSERIALIZE(&len)) )
[ # # ]
1583 : 0 : return false;
1584 : :
1585 : 0 : tag = TypeTag(t);
1586 : :
1587 [ # # ]: 0 : while ( len-- )
1588 : : {
1589 : 0 : Val* v = Val::Unserialize(info, TYPE_ANY);
1590 [ # # ]: 0 : if ( ! v )
1591 : 0 : return false;
1592 : :
1593 : 0 : vals.append(v);
1594 : : }
1595 : :
1596 : : // Our dtor will do Unref(type) in addition to Val's dtor.
1597 [ # # ]: 0 : if ( type )
1598 : 0 : type->Ref();
1599 : :
1600 : 0 : return true;
1601 : : }
1602 : :
1603 : 0 : unsigned int ListVal::MemoryAllocation() const
1604 : : {
1605 : 0 : unsigned int size = 0;
1606 [ # # ]: 0 : loop_over_list(vals, i)
1607 : 0 : size += vals[i]->MemoryAllocation();
1608 : :
1609 : : return size + padded_sizeof(*this) + vals.MemoryAllocation() - padded_sizeof(vals)
1610 : 0 : + type->MemoryAllocation();
1611 : : }
1612 : :
1613 : :
1614 : 8093 : TableValTimer::TableValTimer(TableVal* val, double t) : Timer(t, TIMER_TABLE_VAL)
1615 : : {
1616 : 8093 : table = val;
1617 : 8093 : }
1618 : :
1619 : 8021 : TableValTimer::~TableValTimer()
1620 : : {
1621 : 8021 : table->ClearTimer(this);
1622 [ + - ][ # # ]: 8021 : }
[ # # ]
1623 : :
1624 : 7872 : void TableValTimer::Dispatch(double t, int is_expire)
1625 : : {
1626 [ + + ]: 7872 : if ( ! is_expire )
1627 : : {
1628 : 7831 : table->ClearTimer(this);
1629 : 7831 : table->DoExpire(t);
1630 : : }
1631 : 7872 : }
1632 : :
1633 : 28052 : static void table_entry_val_delete_func(void* val)
1634 : : {
1635 : 28052 : TableEntryVal* tv = (TableEntryVal*) val;
1636 : 28052 : tv->Unref();
1637 [ + - ]: 28052 : delete tv;
1638 : 28052 : }
1639 : :
1640 : 14742 : TableVal::TableVal(TableType* t, Attributes* a) : MutableVal(t)
1641 : : {
1642 : 14742 : Init(t);
1643 : 14742 : SetAttrs(a);
1644 : 14742 : }
1645 : :
1646 : 14742 : void TableVal::Init(TableType* t)
1647 : : {
1648 : 14742 : table_type = t;
1649 : 14742 : expire_expr = 0;
1650 : 14742 : expire_time = 0;
1651 : 14742 : expire_cookie = 0;
1652 : 14742 : timer = 0;
1653 : 14742 : def_val = 0;
1654 : :
1655 [ + + ]: 14742 : if ( t->IsSubNetIndex() )
1656 : 24 : subnets = new PrefixTable;
1657 : : else
1658 : 14718 : subnets = 0;
1659 : :
1660 : 14742 : table_hash = new CompositeHash(table_type->Indices());
1661 : 14742 : val.table_val = new PDict(TableEntryVal);
1662 : 14742 : val.table_val->SetDeleteFunc(table_entry_val_delete_func);
1663 : 14742 : }
1664 : :
1665 : 14100 : TableVal::~TableVal()
1666 : : {
1667 [ - + ][ # # ]: 14100 : if ( timer )
[ # # ]
1668 : 0 : timer_mgr->Cancel(timer);
1669 : :
1670 [ + - ][ # # ]: 14100 : delete table_hash;
[ # # ]
1671 [ + - ][ # # ]: 14100 : delete AsTable();
[ # # ]
1672 [ - + ][ # # ]: 14100 : delete subnets;
[ # # ]
1673 : 14100 : Unref(attrs);
1674 : 14100 : Unref(def_val);
1675 : 14100 : Unref(expire_expr);
1676 [ + - ][ # # ]: 14100 : }
[ # # ]
1677 : :
1678 : 1 : void TableVal::RemoveAll()
1679 : : {
1680 : : // Here we take the brute force approach.
1681 [ + - ]: 1 : delete AsTable();
1682 : 1 : val.table_val = new PDict(TableEntryVal);
1683 : 1 : val.table_val->SetDeleteFunc(table_entry_val_delete_func);
1684 : 1 : }
1685 : :
1686 : 0 : int TableVal::RecursiveSize() const
1687 : : {
1688 : 0 : int n = AsTable()->Length();
1689 : :
1690 [ # # # # ]: 0 : if ( Type()->IsSet() ||
[ # # ]
1691 : : const_cast<TableType*>(Type()->AsTableType())->YieldType()->Tag()
1692 : : != TYPE_TABLE )
1693 : 0 : return n;
1694 : :
1695 : 0 : PDict(TableEntryVal)* v = val.table_val;
1696 : 0 : IterCookie* c = v->InitForIteration();
1697 : :
1698 : : TableEntryVal* tv;
1699 [ # # ]: 0 : while ( (tv = v->NextEntry(c)) )
1700 : : {
1701 [ # # ]: 0 : if ( tv->Value() )
1702 : 0 : n += tv->Value()->AsTableVal()->RecursiveSize();
1703 : : }
1704 : :
1705 : 0 : return n;
1706 : : }
1707 : :
1708 : 16382 : void TableVal::SetAttrs(Attributes* a)
1709 : : {
1710 : 16382 : attrs = a;
1711 : :
1712 [ + + ]: 16382 : if ( ! a )
1713 : 14114 : return;
1714 : :
1715 : 2268 : ::Ref(attrs);
1716 : :
1717 : 2268 : CheckExpireAttr(ATTR_EXPIRE_READ);
1718 : 2268 : CheckExpireAttr(ATTR_EXPIRE_WRITE);
1719 : 2268 : CheckExpireAttr(ATTR_EXPIRE_CREATE);
1720 : :
1721 : 2268 : Attr* ef = attrs->FindAttr(ATTR_EXPIRE_FUNC);
1722 [ + + ]: 2268 : if ( ef )
1723 : : {
1724 : 52 : expire_expr = ef->AttrExpr();
1725 : 16382 : expire_expr->Ref();
1726 : : }
1727 : : }
1728 : :
1729 : 6804 : void TableVal::CheckExpireAttr(attr_tag at)
1730 : : {
1731 : 6804 : Attr* a = attrs->FindAttr(at);
1732 : :
1733 [ + + ]: 6804 : if ( a )
1734 : : {
1735 : 262 : Val* timeout = a->AttrExpr()->Eval(0);
1736 [ - + ]: 262 : if ( ! timeout )
1737 : : {
1738 : 0 : a->AttrExpr()->Error("value of timeout not fixed");
1739 : 0 : return;
1740 : : }
1741 : :
1742 : 262 : expire_time = timeout->AsInterval();
1743 : :
1744 [ + + ]: 262 : if ( timer )
1745 : 149 : timer_mgr->Cancel(timer);
1746 : :
1747 : : // As network_time is not necessarily initialized yet,
1748 : : // we set a timer which fires immediately.
1749 : 262 : timer = new TableValTimer(this, 1);
1750 : 6804 : timer_mgr->Add(timer);
1751 : : }
1752 : : }
1753 : :
1754 : 31472 : int TableVal::Assign(Val* index, Val* new_val, Opcode op)
1755 : : {
1756 : 31472 : HashKey* k = ComputeHash(index);
1757 [ - + ]: 31472 : if ( ! k )
1758 : : {
1759 : 0 : Unref(new_val);
1760 : 0 : index->Error("index type doesn't match table", table_type->Indices());
1761 : 0 : return 0;
1762 : : }
1763 : :
1764 : 31472 : return Assign(index, k, new_val, op);
1765 : : }
1766 : :
1767 : 32348 : int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
1768 : : {
1769 : 32348 : int is_set = table_type->IsSet();
1770 : :
1771 [ + + + - ]: 32348 : if ( (is_set && new_val) || (! is_set && ! new_val) )
[ + + ][ - + ]
1772 : 0 : InternalWarning("bad set/table in TableVal::Assign");
1773 : :
1774 : 32348 : BroType* yt = Type()->AsTableType()->YieldType();
1775 : :
1776 [ + + + + ]: 32348 : if ( yt && yt->Tag() == TYPE_TABLE &&
[ + + ][ + + ]
1777 : : new_val->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
1778 : : {
1779 : : // Join two mergeable sets.
1780 : 165 : Val* old = Lookup(index, false);
1781 [ - + # # ]: 165 : if ( old && old->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
[ - + ]
1782 : : {
1783 [ # # ][ # # ]: 0 : if ( LoggingAccess() && op != OP_NONE )
[ # # ]
1784 : : StateAccess::Log(new StateAccess(OP_ASSIGN_IDX,
1785 : 0 : this, index, new_val, old));
1786 : 0 : new_val->AsTableVal()->AddTo(old->AsTableVal(), 0, false);
1787 : 0 : Unref(new_val);
1788 : 0 : return 1;
1789 : : }
1790 : : }
1791 : :
1792 : 32348 : TableEntryVal* new_entry_val = new TableEntryVal(new_val);
1793 : 32348 : TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k, new_entry_val);
1794 : :
1795 [ + + ]: 32348 : if ( subnets )
1796 : : {
1797 [ - + ]: 14 : if ( ! index )
1798 : : {
1799 : 0 : Val* v = RecoverIndex(k);
1800 : 0 : subnets->Insert(v, new_entry_val);
1801 : 0 : Unref(v);
1802 : : }
1803 : : else
1804 : 14 : subnets->Insert(index, new_entry_val);
1805 : : }
1806 : :
1807 [ - + ][ # # ]: 32348 : if ( LoggingAccess() && op != OP_NONE )
[ - + ]
1808 : : {
1809 : 0 : Val* rec_index = 0;
1810 [ # # ]: 0 : if ( ! index )
1811 : 0 : index = rec_index = RecoverIndex(k);
1812 : :
1813 [ # # ]: 0 : if ( new_val )
1814 : : {
1815 : : // A table.
1816 [ # # ]: 0 : if ( new_val->IsMutableVal() )
1817 : 0 : new_val->AsMutableVal()->AddProperties(GetProperties());
1818 : :
1819 : 0 : bool unref_old_val = false;
1820 : : Val* old_val = old_entry_val ?
1821 [ # # ]: 0 : old_entry_val->Value() : 0;
1822 [ # # ][ # # ]: 0 : if ( op == OP_INCR && ! old_val )
1823 : : // If it's an increment, somebody has already
1824 : : // checked that the index is there. If it's
1825 : : // not, that can only be due to using the
1826 : : // default.
1827 : : {
1828 : 0 : old_val = Default(index);
1829 : 0 : unref_old_val = true;
1830 : : }
1831 : :
1832 [ # # ][ # # ]: 0 : assert(op != OP_INCR || old_val);
[ # # ]
1833 : :
1834 : : StateAccess::Log(
1835 : : new StateAccess(
1836 : : op == OP_INCR ?
1837 : : OP_INCR_IDX : OP_ASSIGN_IDX,
1838 [ # # ]: 0 : this, index, new_val, old_val));
1839 : :
1840 [ # # ]: 0 : if ( unref_old_val )
1841 : 0 : Unref(old_val);
1842 : : }
1843 : :
1844 : : else
1845 : : {
1846 : : // A set.
1847 [ # # ][ # # ]: 0 : if ( old_entry_val && remote_check_sync_consistency )
1848 : : {
1849 : 0 : Val* has_old_val = new Val(1, TYPE_INT);
1850 : : StateAccess::Log(
1851 : : new StateAccess(OP_ADD, this, index,
1852 : 0 : has_old_val));
1853 : 0 : Unref(has_old_val);
1854 : : }
1855 : : else
1856 : : StateAccess::Log(
1857 : : new StateAccess(OP_ADD, this,
1858 : 0 : index, 0, 0));
1859 : : }
1860 : :
1861 [ # # ]: 0 : if ( rec_index )
1862 : 0 : Unref(rec_index);
1863 : : }
1864 : :
1865 : : // Keep old expiration time if necessary.
1866 [ + + ][ + + ]: 32348 : if ( old_entry_val && attrs && attrs->FindAttr(ATTR_EXPIRE_CREATE) )
[ - + ][ - + ]
1867 : 0 : new_entry_val->SetExpireAccess(old_entry_val->ExpireAccessTime());
1868 : :
1869 [ + - ]: 32348 : delete k;
1870 [ + + ]: 32348 : if ( old_entry_val )
1871 : : {
1872 : 111 : old_entry_val->Unref();
1873 [ + - ]: 111 : delete old_entry_val;
1874 : : }
1875 : :
1876 : 32348 : Modified();
1877 : 32348 : return 1;
1878 : : }
1879 : :
1880 : 184 : int TableVal::AddTo(Val* val, int is_first_init) const
1881 : : {
1882 : 184 : return AddTo(val, is_first_init, true);
1883 : : }
1884 : :
1885 : 184 : int TableVal::AddTo(Val* val, int is_first_init, bool propagate_ops) const
1886 : : {
1887 [ - + ]: 184 : if ( val->Type()->Tag() != TYPE_TABLE )
1888 : : {
1889 : 0 : val->Error("not a table");
1890 : 0 : return 0;
1891 : : }
1892 : :
1893 : 184 : TableVal* t = val->AsTableVal();
1894 : :
1895 [ - + ]: 184 : if ( ! same_type(type, t->Type()) )
1896 : : {
1897 : 0 : type->Error("table type clash", t->Type());
1898 : 0 : return 0;
1899 : : }
1900 : :
1901 : 184 : const PDict(TableEntryVal)* tbl = AsTable();
1902 : 184 : IterCookie* c = tbl->InitForIteration();
1903 : :
1904 : : HashKey* k;
1905 : : TableEntryVal* v;
1906 [ + + ]: 1060 : while ( (v = tbl->NextEntry(k, c)) )
1907 : : {
1908 [ + + ][ - + ]: 876 : if ( is_first_init && t->AsTable()->Lookup(k) )
[ - + ]
1909 : : {
1910 : 0 : Val* key = table_hash->RecoverVals(k);
1911 : : // ### Shouldn't complain if their values are equal.
1912 : 0 : key->Warn("multiple initializations for index");
1913 : 0 : Unref(key);
1914 : 0 : continue;
1915 : : }
1916 : :
1917 [ + + ]: 876 : if ( type->IsSet() )
1918 : : {
1919 [ + - ][ - + ]: 707 : if ( ! t->Assign(v->Value(), k, 0,
1920 : : propagate_ops ? OP_ASSIGN : OP_NONE) )
1921 : 707 : return 0;
1922 : : }
1923 : : else
1924 : : {
1925 : 169 : v->Ref();
1926 [ + - ][ - + ]: 169 : if ( ! t->Assign(0, k, v->Value(),
1927 : : propagate_ops ? OP_ASSIGN : OP_NONE) )
1928 : 0 : return 0;
1929 : : }
1930 : : }
1931 : :
1932 : 184 : return 1;
1933 : : }
1934 : :
1935 : 0 : int TableVal::RemoveFrom(Val* val) const
1936 : : {
1937 [ # # ]: 0 : if ( val->Type()->Tag() != TYPE_TABLE )
1938 : : {
1939 : 0 : val->Error("not a table");
1940 : 0 : return 0;
1941 : : }
1942 : :
1943 : 0 : TableVal* t = val->AsTableVal();
1944 : :
1945 [ # # ]: 0 : if ( ! same_type(type, t->Type()) )
1946 : : {
1947 : 0 : type->Error("table type clash", t->Type());
1948 : 0 : return 0;
1949 : : }
1950 : :
1951 : 0 : const PDict(TableEntryVal)* tbl = AsTable();
1952 : 0 : IterCookie* c = tbl->InitForIteration();
1953 : :
1954 : : HashKey* k;
1955 : : TableEntryVal* v;
1956 [ # # ]: 0 : while ( (v = tbl->NextEntry(k, c)) )
1957 : : {
1958 : 0 : Val* index = RecoverIndex(k);
1959 : 0 : Unref(index);
1960 : 0 : Unref(t->Delete(k));
1961 [ # # ]: 0 : delete k;
1962 : : }
1963 : :
1964 : 0 : return 1;
1965 : : }
1966 : :
1967 : 2594 : int TableVal::ExpandAndInit(Val* index, Val* new_val)
1968 : : {
1969 : 2594 : BroType* index_type = index->Type();
1970 : :
1971 [ - + ]: 2594 : if ( index_type->IsSet() )
1972 : : {
1973 : 0 : Val* new_index = index->AsTableVal()->ConvertToList();
1974 : 0 : Unref(index);
1975 : 0 : return ExpandAndInit(new_index, new_val);
1976 : : }
1977 : :
1978 [ + + ]: 2594 : if ( index_type->Tag() != TYPE_LIST )
1979 : : // Nothing to expand.
1980 : 925 : return CheckAndAssign(index, new_val);
1981 : :
1982 : 1669 : ListVal* iv = index->AsListVal();
1983 [ - + ]: 1669 : if ( iv->BaseTag() != TYPE_ANY )
1984 : : {
1985 [ # # ]: 0 : if ( table_type->Indices()->Types()->length() != 1 )
1986 : 0 : internal_error("bad singleton list index");
1987 : :
1988 [ # # ]: 0 : for ( int i = 0; i < iv->Length(); ++i )
1989 [ # # ][ # # ]: 0 : if ( ! ExpandAndInit(iv->Index(i), new_val ? new_val->Ref() : 0) )
1990 : 0 : return 0;
1991 : :
1992 : 0 : Unref(new_val);
1993 : 0 : return 1;
1994 : : }
1995 : :
1996 : : else
1997 : : { // Compound table.
1998 : 1669 : val_list* vl = iv->Vals();
1999 [ + + ]: 3678 : loop_over_list(*vl, i)
2000 : : {
2001 : : // ### if CompositeHash::ComputeHash did flattening
2002 : : // of 1-element lists (like ComputeSingletonHash does),
2003 : : // then we could optimize here.
2004 : 2079 : BroType* t = (*vl)[i]->Type();
2005 [ + + + + ]: 2079 : if ( t->IsSet() || t->Tag() == TYPE_LIST )
[ + + ]
2006 : 70 : break;
2007 : : }
2008 : :
2009 [ + + ]: 1669 : if ( i >= vl->length() )
2010 : : // Nothing to expand.
2011 : 1599 : return CheckAndAssign(index, new_val);
2012 : : else
2013 : : {
2014 : 70 : int result = ExpandCompoundAndInit(vl, i, new_val);
2015 : 70 : Unref(new_val);
2016 : 2594 : return result;
2017 : : }
2018 : : }
2019 : : }
2020 : :
2021 : :
2022 : 335 : Val* TableVal::Default(Val* index)
2023 : : {
2024 : 335 : Attr* def_attr = FindAttr(ATTR_DEFAULT);
2025 : :
2026 [ + + ]: 335 : if ( ! def_attr )
2027 : 6 : return 0;
2028 : :
2029 [ + + ]: 329 : if ( ! def_val )
2030 : 48 : def_val = def_attr->AttrExpr()->Eval(0);
2031 : :
2032 [ - + ]: 329 : if ( ! def_val )
2033 : : {
2034 : 0 : RunTime("non-constant default attribute");
2035 : 0 : return 0;
2036 : : }
2037 : :
2038 [ - + ][ # # ]: 329 : if ( def_val->Type()->Tag() != TYPE_FUNC ||
[ + - ]
2039 : : same_type(def_val->Type(), Type()->YieldType()) )
2040 : 329 : return def_val->Ref();
2041 : :
2042 : 0 : const Func* f = def_val->AsFunc();
2043 : 0 : val_list* vl = new val_list();
2044 : :
2045 [ # # ]: 0 : if ( index->Type()->Tag() == TYPE_LIST )
2046 : : {
2047 : 0 : const val_list* vl0 = index->AsListVal()->Vals();
2048 [ # # ]: 0 : loop_over_list(*vl0, i)
2049 : 0 : vl->append((*vl0)[i]->Ref());
2050 : : }
2051 : : else
2052 : 0 : vl->append(index->Ref());
2053 : :
2054 : 0 : Val* result = f->Call(vl);
2055 [ # # ]: 0 : delete vl;
2056 : :
2057 [ # # ]: 0 : if ( ! result )
2058 : : {
2059 : 0 : RunTime("no value returned from &default function");
2060 : 0 : return 0;
2061 : : }
2062 : :
2063 : 335 : return result;
2064 : : }
2065 : :
2066 : 91938 : Val* TableVal::Lookup(Val* index, bool use_default_val)
2067 : : {
2068 : : static Val* last_default = 0;
2069 : :
2070 [ + + ]: 91938 : if ( last_default )
2071 : : {
2072 : 329 : Unref(last_default);
2073 : 329 : last_default = 0;
2074 : : }
2075 : :
2076 [ + + ]: 91938 : if ( subnets )
2077 : : {
2078 : 4207 : TableEntryVal* v = (TableEntryVal*) subnets->Lookup(index);
2079 [ - + ]: 4207 : if ( v )
2080 [ # # ]: 0 : return v->Value() ? v->Value() : this;
2081 : :
2082 [ + - ]: 4207 : if ( ! use_default_val )
2083 : 4207 : return 0;
2084 : :
2085 : 0 : Val* def = Default(index);
2086 : 0 : last_default = def;
2087 : :
2088 : 0 : return def;
2089 : : }
2090 : :
2091 : 87731 : const PDict(TableEntryVal)* tbl = AsTable();
2092 : :
2093 [ + + ]: 87731 : if ( tbl->Length() > 0 )
2094 : : {
2095 : 71093 : HashKey* k = ComputeHash(index);
2096 [ + - ]: 71093 : if ( k )
2097 : : {
2098 : 71093 : TableEntryVal* v = AsTable()->Lookup(k);
2099 [ + - ]: 71093 : delete k;
2100 : :
2101 [ + + ]: 71093 : if ( v )
2102 : : {
2103 [ + + ][ + + ]: 55088 : if ( attrs &&
[ + - ][ + + ]
2104 : : ! (attrs->FindAttr(ATTR_EXPIRE_WRITE) ||
2105 : : attrs->FindAttr(ATTR_EXPIRE_CREATE)) )
2106 : : {
2107 : 29553 : v->SetExpireAccess(network_time);
2108 [ - + # # ]: 29553 : if ( LoggingAccess() && expire_time )
[ - + ]
2109 : 0 : ReadOperation(index, v);
2110 : : }
2111 : :
2112 [ + + ]: 55088 : return v->Value() ? v->Value() : this;
2113 : : }
2114 : : }
2115 : : }
2116 : :
2117 [ + + ]: 32643 : if ( ! use_default_val )
2118 : 32308 : return 0;
2119 : :
2120 : 335 : Val* def = Default(index);
2121 : :
2122 : 335 : last_default = def;
2123 : 91938 : return def;
2124 : : }
2125 : :
2126 : 0 : bool TableVal::UpdateTimestamp(Val* index)
2127 : : {
2128 : : TableEntryVal* v;
2129 : :
2130 [ # # ]: 0 : if ( subnets )
2131 : 0 : v = (TableEntryVal*) subnets->Lookup(index);
2132 : : else
2133 : : {
2134 : 0 : HashKey* k = ComputeHash(index);
2135 [ # # ]: 0 : if ( ! k )
2136 : 0 : return false;
2137 : :
2138 : 0 : v = AsTable()->Lookup(k);
2139 : :
2140 [ # # ]: 0 : delete k;
2141 : : }
2142 : :
2143 [ # # ]: 0 : if ( ! v )
2144 : 0 : return false;
2145 : :
2146 : 0 : v->SetExpireAccess(network_time);
2147 [ # # ]: 0 : if ( attrs->FindAttr(ATTR_EXPIRE_READ) )
2148 : 0 : ReadOperation(index, v);
2149 : :
2150 : 0 : return true;
2151 : : }
2152 : :
2153 : 112 : ListVal* TableVal::RecoverIndex(const HashKey* k) const
2154 : : {
2155 : 112 : return table_hash->RecoverVals(k);
2156 : : }
2157 : :
2158 : 8295 : Val* TableVal::Delete(const Val* index)
2159 : : {
2160 : 8295 : HashKey* k = ComputeHash(index);
2161 [ + - ]: 8295 : TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k) : 0;
2162 [ + + ][ + - ]: 8295 : Val* va = v ? (v->Value() ? v->Value() : this->Ref()) : 0;
2163 : :
2164 [ - + ][ # # ]: 8295 : if ( subnets && ! subnets->Remove(index) )
[ - + ]
2165 : 0 : internal_error( "index not in prefix table" );
2166 : :
2167 [ - + ]: 8295 : if ( LoggingAccess() )
2168 : : {
2169 [ # # ]: 0 : if ( v )
2170 : : {
2171 [ # # ][ # # ]: 0 : if ( v->Value() && remote_check_sync_consistency )
[ # # ]
2172 : : // A table.
2173 : : StateAccess::Log(
2174 : : new StateAccess(OP_DEL, this,
2175 : 0 : index, v->Value()));
2176 : : else
2177 : : {
2178 : : // A set.
2179 : 0 : Val* has_old_val = new Val(1, TYPE_INT);
2180 : : StateAccess::Log(
2181 : : new StateAccess(OP_DEL, this, index,
2182 : 0 : has_old_val));
2183 : 0 : Unref(has_old_val);
2184 : : }
2185 : : }
2186 : : else
2187 : : StateAccess::Log(
2188 : 0 : new StateAccess(OP_DEL, this, index, 0));
2189 : : }
2190 : :
2191 [ + - ]: 8295 : delete k;
2192 [ + + ]: 8295 : delete v;
2193 : :
2194 : 8295 : Modified();
2195 : 8295 : return va;
2196 : : }
2197 : :
2198 : 0 : Val* TableVal::Delete(const HashKey* k)
2199 : : {
2200 : 0 : TableEntryVal* v = AsNonConstTable()->RemoveEntry(k);
2201 [ # # # # ]: 0 : Val* va = v ? (v->Value() ? v->Value() : this->Ref()) : 0;
2202 : :
2203 [ # # ]: 0 : if ( subnets )
2204 : : {
2205 : 0 : Val* index = table_hash->RecoverVals(k);
2206 [ # # ]: 0 : if ( ! subnets->Remove(index) )
2207 : 0 : internal_error( "index not in prefix table" );
2208 : 0 : Unref(index);
2209 : : }
2210 : :
2211 [ # # ]: 0 : delete v;
2212 : :
2213 [ # # ]: 0 : if ( LoggingAccess() )
2214 : 0 : StateAccess::Log(new StateAccess(OP_DEL, this, k));
2215 : :
2216 : 0 : Modified();
2217 : 0 : return va;
2218 : : }
2219 : :
2220 : 1398 : ListVal* TableVal::ConvertToList(TypeTag t) const
2221 : : {
2222 : 1398 : ListVal* l = new ListVal(t);
2223 : :
2224 : 1398 : const PDict(TableEntryVal)* tbl = AsTable();
2225 : 1398 : IterCookie* c = tbl->InitForIteration();
2226 : :
2227 : : HashKey* k;
2228 : : TableEntryVal* v;
2229 [ + + ]: 2891 : while ( (v = tbl->NextEntry(k, c)) )
2230 : : {
2231 : 1493 : ListVal* index = table_hash->RecoverVals(k);
2232 : :
2233 [ + + ]: 1493 : if ( t == TYPE_ANY )
2234 : 1388 : l->Append(index);
2235 : : else
2236 : : {
2237 : : // We're expecting a pure list, flatten the
2238 : : // ListVal.
2239 [ - + ]: 105 : if ( index->Length() != 1 )
2240 : 0 : InternalWarning("bad index in TableVal::ConvertToList");
2241 : 105 : Val* flat_v = index->Index(0)->Ref();
2242 : 105 : Unref(index);
2243 : 105 : l->Append(flat_v);
2244 : : }
2245 : :
2246 [ + - ]: 1493 : delete k;
2247 : : }
2248 : :
2249 : 1398 : return l;
2250 : : }
2251 : :
2252 : 13 : ListVal* TableVal::ConvertToPureList() const
2253 : : {
2254 : 13 : type_list* tl = table_type->Indices()->Types();
2255 [ - + ]: 13 : if ( tl->length() != 1 )
2256 : 0 : InternalWarning("bad index type in TableVal::ConvertToPureList");
2257 : :
2258 : 13 : return ConvertToList((*tl)[0]->Tag());
2259 : : }
2260 : :
2261 : 16 : void TableVal::Describe(ODesc* d) const
2262 : : {
2263 : 16 : const PDict(TableEntryVal)* tbl = AsTable();
2264 : 16 : int n = tbl->Length();
2265 : :
2266 [ + - - + ]: 16 : if ( d->IsBinary() || d->IsPortable() )
[ - + ]
2267 : : {
2268 : 0 : table_type->Describe(d);
2269 : 0 : d->SP();
2270 : 0 : d->Add(n);
2271 : 0 : d->SP();
2272 : : }
2273 : :
2274 [ + - ][ + - ]: 16 : if ( d->IsPortable() || d->IsReadable() )
[ + - ]
2275 : : {
2276 : 16 : d->Add("{");
2277 : 16 : d->PushIndent();
2278 : : }
2279 : :
2280 : 16 : IterCookie* c = tbl->InitForIteration();
2281 : :
2282 [ - + ]: 16 : for ( int i = 0; i < n; ++i )
2283 : : {
2284 : : HashKey* k;
2285 : 0 : TableEntryVal* v = tbl->NextEntry(k, c);
2286 : :
2287 [ # # ]: 0 : if ( ! v )
2288 : 0 : internal_error("hash table underflow in TableVal::Describe");
2289 : :
2290 : 0 : ListVal* vl = table_hash->RecoverVals(k);
2291 : 0 : int dim = vl->Length();
2292 : :
2293 [ # # ]: 0 : if ( i > 0 )
2294 : : {
2295 [ # # ]: 0 : if ( ! d->IsBinary() )
2296 : 0 : d->Add(",");
2297 : :
2298 : 0 : d->NL();
2299 : : }
2300 : :
2301 [ # # ]: 0 : if ( d->IsReadable() )
2302 : : {
2303 [ # # ][ # # ]: 0 : if ( dim != 1 || ! table_type->IsSet() )
[ # # ]
2304 : 0 : d->Add("[");
2305 : : }
2306 : : else
2307 : : {
2308 : 0 : d->Add(dim);
2309 : 0 : d->SP();
2310 : : }
2311 : :
2312 : 0 : vl->Describe(d);
2313 : :
2314 [ # # ]: 0 : delete k;
2315 : 0 : Unref(vl);
2316 : :
2317 [ # # ]: 0 : if ( table_type->IsSet() )
2318 : : { // We're a set, not a table.
2319 [ # # ]: 0 : if ( d->IsReadable() )
2320 [ # # ]: 0 : if ( dim != 1 )
2321 : 0 : d->AddSP("]");
2322 : : }
2323 : : else
2324 : : {
2325 [ # # ]: 0 : if ( d->IsReadable() )
2326 : 0 : d->AddSP("] =");
2327 [ # # ]: 0 : if ( v->Value() )
2328 : 0 : v->Value()->Describe(d);
2329 : : }
2330 : :
2331 [ # # ][ # # ]: 0 : if ( d->IsReadable() && ! d->IsShort() && d->IncludeStats() )
[ # # ][ # # ]
2332 : : {
2333 : 0 : d->Add(" @");
2334 : 0 : d->Add(fmt_access_time(v->ExpireAccessTime()));
2335 : : }
2336 : : }
2337 : :
2338 [ - + ]: 16 : if ( tbl->NextEntry(c) )
2339 : 0 : internal_error("hash table overflow in TableVal::Describe");
2340 : :
2341 [ + - ][ + - ]: 16 : if ( d->IsPortable() || d->IsReadable() )
[ + - ]
2342 : : {
2343 : 16 : d->PopIndent();
2344 : 16 : d->Add("}");
2345 : : }
2346 : 16 : }
2347 : :
2348 : 70 : int TableVal::ExpandCompoundAndInit(val_list* vl, int k, Val* new_val)
2349 : : {
2350 : 70 : Val* ind_k_v = (*vl)[k];
2351 : : ListVal* ind_k = ind_k_v->Type()->IsSet() ?
2352 : : ind_k_v->AsTableVal()->ConvertToList() :
2353 [ + + ]: 70 : ind_k_v->AsListVal();
2354 : :
2355 [ + + ]: 424 : for ( int i = 0; i < ind_k->Length(); ++i )
2356 : : {
2357 : 354 : Val* ind_k_i = ind_k->Index(i);
2358 : 354 : ListVal* expd = new ListVal(TYPE_ANY);
2359 [ + + ]: 1030 : loop_over_list(*vl, j)
2360 : : {
2361 [ + + ]: 676 : if ( j == k )
2362 : 354 : expd->Append(ind_k_i->Ref());
2363 : : else
2364 : 322 : expd->Append((*vl)[j]->Ref());
2365 : : }
2366 : :
2367 [ + + ]: 354 : int success = ExpandAndInit(expd, new_val ? new_val->Ref() : 0);
2368 : 354 : Unref(expd);
2369 : :
2370 [ - + ]: 354 : if ( ! success )
2371 : 0 : return 0;
2372 : : }
2373 : :
2374 [ + + ]: 70 : if ( ind_k_v->Type()->IsSet() )
2375 : 6 : Unref(ind_k);
2376 : :
2377 : 70 : return 1;
2378 : : }
2379 : :
2380 : 2524 : int TableVal::CheckAndAssign(Val* index, Val* new_val, Opcode op)
2381 : : {
2382 : 2524 : Val* v = 0;
2383 [ + + ]: 2524 : if ( subnets )
2384 : : // We need an exact match here.
2385 : 14 : v = (Val*) subnets->Lookup(index, true);
2386 : : else
2387 : 2510 : v = Lookup(index, false);
2388 : :
2389 [ - + ]: 2524 : if ( v )
2390 : 0 : index->Warn("multiple initializations for index");
2391 : :
2392 : 2524 : return Assign(index, new_val, op);
2393 : : }
2394 : :
2395 : 7831 : void TableVal::InitTimer(double delay)
2396 : : {
2397 : 7831 : timer = new TableValTimer(this, network_time + delay);
2398 : 7831 : timer_mgr->Add(timer);
2399 : 7831 : }
2400 : :
2401 : 7831 : void TableVal::DoExpire(double t)
2402 : : {
2403 [ - + ]: 7831 : if ( ! type )
2404 : 0 : return; // FIX ME ###
2405 : :
2406 : 7831 : PDict(TableEntryVal)* tbl = AsNonConstTable();
2407 : :
2408 [ + - ]: 7831 : if ( ! expire_cookie )
2409 : : {
2410 : 7831 : expire_cookie = tbl->InitForIteration();
2411 : 7831 : tbl->MakeRobustCookie(expire_cookie);
2412 : : }
2413 : :
2414 : 7831 : HashKey* k = 0;
2415 : 7831 : TableEntryVal* v = 0;
2416 : :
2417 [ + - ][ + + ]: 18501 : for ( int i = 0; i < table_incremental_step &&
[ + + ]
2418 : : (v = tbl->NextEntry(k, expire_cookie)); ++i )
2419 : : {
2420 [ - + ]: 10670 : if ( v->ExpireAccessTime() == 0 )
2421 : : // This happens when we insert val while network_time
2422 : : // hasn't been initialized yet (e.g. in bro_init()).
2423 : : // We correct the timestamp now.
2424 : 0 : v->SetExpireAccess(network_time);
2425 : :
2426 [ + + ]: 10670 : else if ( v->ExpireAccessTime() + expire_time < t )
2427 : : {
2428 [ + - ]: 134 : Val* val = v ? v->Value() : 0;
2429 : :
2430 [ + + ]: 134 : if ( expire_expr )
2431 : : {
2432 : 80 : Val* idx = RecoverIndex(k);
2433 : 80 : double secs = CallExpireFunc(idx);
2434 : :
2435 : : // It's possible that the user-provided
2436 : : // function modified or deleted the table
2437 : : // value, so look it up again.
2438 : 80 : v = tbl->Lookup(k);
2439 : :
2440 [ - + ]: 80 : if ( ! v )
2441 : : { // user-provided function deleted it
2442 [ # # ]: 0 : delete k;
2443 : 0 : continue;
2444 : : }
2445 : :
2446 [ - + ]: 80 : if ( secs > 0 )
2447 : : {
2448 : : // User doesn't want us to expire
2449 : : // this now.
2450 : 0 : v->SetExpireAccess(network_time - expire_time + secs);
2451 [ # # ]: 0 : delete k;
2452 : 0 : continue;
2453 : : }
2454 : :
2455 : : }
2456 : :
2457 [ - + ]: 134 : if ( subnets )
2458 : : {
2459 : 0 : Val* index = RecoverIndex(k);
2460 [ # # ]: 0 : if ( ! subnets->Remove(index) )
2461 : 0 : internal_error( "index not in prefix table" );
2462 : 0 : Unref(index);
2463 : : }
2464 : :
2465 [ - + ]: 134 : if ( LoggingAccess() )
2466 : : StateAccess::Log(
2467 : 0 : new StateAccess(OP_EXPIRE, this, k));
2468 : :
2469 : 134 : tbl->RemoveEntry(k);
2470 [ + - ]: 134 : delete v;
2471 : 134 : Unref(val);
2472 : 134 : Modified();
2473 : : }
2474 : :
2475 [ + - ]: 10670 : delete k;
2476 : : }
2477 : :
2478 [ + - ]: 7831 : if ( ! v )
2479 : : {
2480 : 7831 : expire_cookie = 0;
2481 : 7831 : InitTimer(table_expire_interval);
2482 : : }
2483 : : else
2484 : 7831 : InitTimer(table_expire_delay);
2485 : : }
2486 : :
2487 : 80 : double TableVal::CallExpireFunc(Val* idx)
2488 : : {
2489 [ - + ]: 80 : if ( ! expire_expr )
2490 : : {
2491 : 0 : Unref(idx);
2492 : 0 : return 0;
2493 : : }
2494 : :
2495 : 80 : val_list* vl = new val_list;
2496 : 80 : vl->append(Ref());
2497 : :
2498 : : // Flatten lists of a single element.
2499 [ + - + - ]: 80 : if ( idx->Type()->Tag() == TYPE_LIST &&
[ + - ]
2500 : : idx->AsListVal()->Length() == 1 )
2501 : : {
2502 : 80 : Val* old = idx;
2503 : 80 : idx = idx->AsListVal()->Index(0);
2504 : 80 : idx->Ref();
2505 : 80 : Unref(old);
2506 : : }
2507 : :
2508 : 80 : vl->append(idx);
2509 : :
2510 : 80 : Val* vs = expire_expr->Eval(0)->AsFunc()->Call(vl);
2511 : 80 : double secs = vs->AsInterval();
2512 : 80 : Unref(vs);
2513 [ + - ]: 80 : delete vl;
2514 : :
2515 : 80 : return secs;
2516 : : }
2517 : :
2518 : 0 : void TableVal::ReadOperation(Val* index, TableEntryVal* v)
2519 : : {
2520 : : // In theory we need to only propagate one update per &read_expire
2521 : : // interval to prevent peers from expiring intervals. To account for
2522 : : // practical issues such as latency, we send one update every half
2523 : : // &read_expire.
2524 [ # # ]: 0 : if ( network_time - v->LastReadUpdate() > expire_time / 2 )
2525 : : {
2526 : 0 : StateAccess::Log(new StateAccess(OP_READ_IDX, this, index));
2527 : 0 : v->SetLastReadUpdate(network_time);
2528 : : }
2529 : 0 : }
2530 : :
2531 : 5 : IMPLEMENT_SERIAL(TableVal, SER_TABLE_VAL);
2532 : :
2533 : : // This is getting rather complex due to the ability to suspend even within
2534 : : // deeply-nested values.
2535 : 1 : bool TableVal::DoSerialize(SerialInfo* info) const
2536 : : {
2537 [ + - ][ - + ]: 1 : DO_SERIALIZE_WITH_SUSPEND(SER_TABLE_VAL, MutableVal);
[ # # ][ + - ]
[ - + ][ - + ]
2538 : :
2539 : : // The current state of the serialization.
2540 : : struct State {
2541 : : IterCookie* c;
2542 : : TableEntryVal* v; // current value
2543 : : bool did_index; // already wrote the val's index
2544 : : }* state;
2545 : :
2546 : : PDict(TableEntryVal)* tbl =
2547 : 1 : const_cast<TableVal*>(this)->AsNonConstTable();
2548 : :
2549 [ + - ]: 1 : if ( info->cont.NewInstance() )
2550 : : {
2551 : : // For simplicity, we disable suspension for the objects
2552 : : // serialized here. (In fact we know that *currently*
2553 : : // they won't even try).
2554 : 1 : DisableSuspend suspend(info);
2555 : :
2556 : 1 : state = new State;
2557 : 1 : state->c = tbl->InitForIteration();
2558 : 1 : tbl->MakeRobustCookie(state->c);
2559 : 1 : state->v = 0;
2560 : 1 : state->did_index = false;
2561 [ - + ]: 1 : info->s->WriteOpenTag(table_type->IsSet() ? "set" : "table");
2562 : :
2563 [ - + ]: 1 : if ( ! SERIALIZE(expire_time) )
2564 : 0 : return false;
2565 : :
2566 [ + - ][ + - ]: 1 : SERIALIZE_OPTIONAL(attrs);
[ - + ][ - + ]
[ - + ][ # # ]
2567 [ + - ][ + - ]: 1 : SERIALIZE_OPTIONAL(expire_expr);
[ - + ][ - + ]
[ - + ][ # # ]
2568 : :
2569 : : // Make sure nobody kills us in between.
2570 [ - + ]: 1 : const_cast<TableVal*>(this)->Ref();
2571 : : }
2572 : :
2573 [ # # ]: 0 : else if ( info->cont.ChildSuspended() )
2574 : 0 : state = (State*) info->cont.RestoreState();
2575 : :
2576 [ # # ]: 0 : else if ( info->cont.Resuming() )
2577 : : {
2578 : 0 : info->cont.Resume();
2579 : 0 : state = (State*) info->cont.RestoreState();
2580 : : }
2581 : : else
2582 : 0 : internal_error("unknown continuation state");
2583 : :
2584 : : HashKey* k;
2585 : 1 : int count = 0;
2586 : :
2587 [ - + ][ # # ]: 1 : assert((!info->cont.ChildSuspended()) || state->v);
[ - + ]
2588 : :
2589 : 0 : while ( true )
2590 : : {
2591 [ + - ]: 1 : if ( ! state->v )
2592 : : {
2593 : 1 : state->v = tbl->NextEntry(k, state->c);
2594 [ + - ]: 1 : if ( ! state->c )
2595 : : {
2596 : : // No next one.
2597 : 1 : SERIALIZE(false);
2598 : : break;
2599 : : }
2600 : :
2601 : : // There's a value coming.
2602 : 0 : SERIALIZE(true);
2603 : :
2604 [ # # ]: 0 : if ( state->v->Value() )
2605 : 0 : state->v->Ref();
2606 : :
2607 : 0 : state->did_index = false;
2608 : : }
2609 : :
2610 : : // Serialize index.
2611 [ # # ]: 0 : if ( ! state->did_index )
2612 : : {
2613 : : // Indices are rather small, so we disable suspension
2614 : : // here again.
2615 : 0 : DisableSuspend suspend(info);
2616 : 0 : info->s->WriteOpenTag("key");
2617 : 0 : ListVal* index = table_hash->RecoverVals(k)->AsListVal();
2618 [ # # ]: 0 : delete k;
2619 : :
2620 [ # # ]: 0 : if ( ! index->Serialize(info) )
2621 : 0 : return false;
2622 : :
2623 : 0 : Unref(index);
2624 : 0 : info->s->WriteCloseTag("key");
2625 : :
2626 : 0 : state->did_index = true;
2627 : :
2628 : : // Start serializing data.
2629 [ # # ]: 0 : if ( ! type->IsSet() )
2630 [ # # ]: 0 : info->s->WriteOpenTag("value");
2631 : : }
2632 : :
2633 [ # # ]: 0 : if ( ! type->IsSet() )
2634 : : {
2635 : 0 : info->cont.SaveState(state);
2636 : 0 : info->cont.SaveContext();
2637 : 0 : bool result = state->v->val->Serialize(info);
2638 : 0 : info->cont.RestoreContext();
2639 : :
2640 [ # # ]: 0 : if ( ! result )
2641 : 0 : return false;
2642 : :
2643 [ # # ]: 0 : if ( info->cont.ChildSuspended() )
2644 : 0 : return true;
2645 : : }
2646 : :
2647 : 0 : double eat = state->v->ExpireAccessTime();
2648 : :
2649 [ # # # # ]: 0 : if ( ! (SERIALIZE(state->v->last_access_time) &&
[ # # ]
2650 : : SERIALIZE(eat)) )
2651 : 0 : return false;
2652 : :
2653 : 0 : info->s->WriteCloseTag("value");
2654 : :
2655 [ # # ]: 0 : if ( state->v->Value() )
2656 : 0 : state->v->Unref();
2657 : 0 : state->v = 0; // Next value.
2658 : :
2659 : : // Suspend if we've done enough for now (which means we
2660 : : // have serialized more than table_incremental_step entries
2661 : : // in a row; if an entry has suspended itself in between,
2662 : : // we start counting from 0).
2663 [ # # ][ # # ]: 0 : if ( info->may_suspend && ++count > table_incremental_step)
[ # # ]
2664 : : {
2665 : 0 : info->cont.SaveState(state);
2666 : 0 : info->cont.Suspend();
2667 : 0 : bro_logger->Log("TableVals serialization suspended right in the middle.");
2668 : 0 : return true;
2669 : : }
2670 : : }
2671 : :
2672 [ - + ]: 1 : info->s->WriteCloseTag(table_type->IsSet() ? "set" : "table");
2673 : 1 : delete state;
2674 : :
2675 : 1 : Unref(const_cast<TableVal*>(this));
2676 : 1 : return true;
2677 : : }
2678 : :
2679 : 0 : bool TableVal::DoUnserialize(UnserialInfo* info)
2680 : : {
2681 [ # # ]: 0 : DO_UNSERIALIZE(MutableVal);
2682 : :
2683 [ # # ]: 0 : if ( ! UNSERIALIZE(&expire_time) )
2684 : 0 : return false;
2685 : :
2686 : 0 : Init((TableType*) type);
2687 : :
2688 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(attrs, Attributes::Unserialize(info));
[ # # ]
2689 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(expire_expr, Expr::Unserialize(info));
[ # # ]
2690 : :
2691 : 0 : while ( true )
2692 : : {
2693 : : // Anymore?
2694 : : bool next;
2695 [ # # ]: 0 : if ( ! UNSERIALIZE(&next) )
2696 : 0 : return false;
2697 : :
2698 [ # # ]: 0 : if ( ! next )
2699 : 0 : break;
2700 : :
2701 : : // Unserialize index.
2702 : : ListVal* index =
2703 : 0 : (ListVal*) Val::Unserialize(info, table_type->Indices());
2704 [ # # ]: 0 : if ( ! index )
2705 : 0 : return false;
2706 : :
2707 : : // Unserialize data.
2708 : : Val* entry;
2709 [ # # ]: 0 : if ( ! table_type->IsSet() )
2710 : : {
2711 : 0 : entry = Val::Unserialize(info, type->YieldType());
2712 [ # # ]: 0 : if ( ! entry )
2713 : 0 : return false;
2714 : : }
2715 : : else
2716 : 0 : entry = 0;
2717 : :
2718 : 0 : TableEntryVal* entry_val = new TableEntryVal(entry);
2719 : :
2720 : : double eat;
2721 : :
2722 [ # # # # ]: 0 : if ( ! UNSERIALIZE(&entry_val->last_access_time) ||
[ # # ]
2723 : : ! UNSERIALIZE(&eat) )
2724 : 0 : return false;
2725 : :
2726 : 0 : entry_val->SetExpireAccess(eat);
2727 : :
2728 : 0 : HashKey* key = ComputeHash(index);
2729 : : TableEntryVal* old_entry_val =
2730 : 0 : AsNonConstTable()->Insert(key, entry_val);
2731 [ # # ]: 0 : assert(! old_entry_val);
2732 : :
2733 [ # # ]: 0 : delete key;
2734 : :
2735 [ # # ]: 0 : if ( subnets )
2736 : 0 : subnets->Insert(index, entry_val);
2737 : :
2738 : 0 : Unref(index);
2739 : : }
2740 : :
2741 : : // If necessary, activate the expire timer.
2742 [ # # ]: 0 : if ( attrs)
2743 : : {
2744 : 0 : CheckExpireAttr(ATTR_EXPIRE_READ);
2745 : 0 : CheckExpireAttr(ATTR_EXPIRE_WRITE);
2746 : 0 : CheckExpireAttr(ATTR_EXPIRE_CREATE);
2747 : : }
2748 : :
2749 : 0 : return true;
2750 : : }
2751 : :
2752 : 606 : bool TableVal::AddProperties(Properties arg_props)
2753 : : {
2754 [ + + ]: 606 : if ( ! MutableVal::AddProperties(arg_props) )
2755 : 588 : return false;
2756 : :
2757 [ + + ][ - + ]: 18 : if ( Type()->IsSet() || ! RecursiveProps(arg_props) )
[ + + ]
2758 : 7 : return true;
2759 : :
2760 : : // For a large table, this could get expensive. So, let's hope
2761 : : // that nobody creates such a table *before* making it persistent
2762 : : // (for example by inserting it into another table).
2763 : : TableEntryVal* v;
2764 : 11 : PDict(TableEntryVal)* tbl = val.table_val;
2765 : 11 : IterCookie* c = tbl->InitForIteration();
2766 [ - + ]: 11 : while ( (v = tbl->NextEntry(c)) )
2767 [ # # ]: 0 : if ( v->Value()->IsMutableVal() )
2768 : 0 : v->Value()->AsMutableVal()->AddProperties(RecursiveProps(arg_props));
2769 : :
2770 : 606 : return true;
2771 : : }
2772 : :
2773 : 0 : bool TableVal::RemoveProperties(Properties arg_props)
2774 : : {
2775 [ # # ]: 0 : if ( ! MutableVal::RemoveProperties(arg_props) )
2776 : 0 : return false;
2777 : :
2778 [ # # ][ # # ]: 0 : if ( Type()->IsSet() || ! RecursiveProps(arg_props) )
[ # # ]
2779 : 0 : return true;
2780 : :
2781 : : // For a large table, this could get expensive. So, let's hope
2782 : : // that nobody creates such a table *before* making it persistent
2783 : : // (for example by inserting it into another table).
2784 : : TableEntryVal* v;
2785 : 0 : PDict(TableEntryVal)* tbl = val.table_val;
2786 : 0 : IterCookie* c = tbl->InitForIteration();
2787 [ # # ]: 0 : while ( (v = tbl->NextEntry(c)) )
2788 [ # # ]: 0 : if ( v->Value()->IsMutableVal() )
2789 : 0 : v->Value()->AsMutableVal()->RemoveProperties(RecursiveProps(arg_props));
2790 : :
2791 : 0 : return true;
2792 : : }
2793 : :
2794 : 0 : unsigned int TableVal::MemoryAllocation() const
2795 : : {
2796 : 0 : unsigned int size = 0;
2797 : :
2798 : 0 : PDict(TableEntryVal)* v = val.table_val;
2799 : 0 : IterCookie* c = v->InitForIteration();
2800 : :
2801 : : TableEntryVal* tv;
2802 [ # # ]: 0 : while ( (tv = v->NextEntry(c)) )
2803 : : {
2804 [ # # ]: 0 : if ( tv->Value() )
2805 : 0 : size += tv->Value()->MemoryAllocation();
2806 : 0 : size += padded_sizeof(TableEntryVal);
2807 : : }
2808 : :
2809 : : return size + padded_sizeof(*this) + val.table_val->MemoryAllocation()
2810 : 0 : + table_hash->MemoryAllocation();
2811 : : }
2812 : :
2813 : 36681 : RecordVal::RecordVal(RecordType* t) : MutableVal(t)
2814 : : {
2815 : 36681 : record_type = t;
2816 : 36681 : int n = record_type->NumFields();
2817 : 36681 : val_list* vl = val.val_list_val = new val_list(n);
2818 : :
2819 : : // Initialize to default values from RecordType (which are nil
2820 : : // by default).
2821 [ + + ][ # # ]: 247670 : for ( int i = 0; i < n; ++i )
2822 : : {
2823 : 210989 : Attributes* a = record_type->FieldDecl(i)->attrs;
2824 [ + + ][ # # ]: 210989 : Attr* def_attr = a ? a->FindAttr(ATTR_DEFAULT) : 0;
2825 [ + + ][ # # ]: 210989 : Val* def = def_attr ? def_attr->AttrExpr()->Eval(0) : 0;
2826 : :
2827 [ + + ][ + + ]: 210989 : if ( ! def && ! (a && a->FindAttr(ATTR_OPTIONAL)) )
[ - + ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
2828 : : {
2829 : 166967 : BroType* type = record_type->FieldDecl(i)->type;
2830 : 166967 : TypeTag tag = type->Tag();
2831 : :
2832 [ + + # # ]: 166967 : if ( tag == TYPE_RECORD )
2833 : 16907 : def = new RecordVal(type->AsRecordType());
2834 : :
2835 [ + + ][ # # ]: 150060 : else if ( tag == TYPE_TABLE )
2836 : 6442 : def = new TableVal(type->AsTableType(), a);
2837 : :
2838 [ - + ][ # # ]: 143618 : else if ( t->Tag() == TYPE_VECTOR )
2839 : 0 : def = new VectorVal(type->AsVectorType());
2840 : : }
2841 : :
2842 [ + + ][ # # ]: 210989 : vl->append(def ? def->Ref() : 0);
2843 : :
2844 : 210989 : Unref(def);
2845 : : }
2846 : 36681 : }
2847 : :
2848 : 36628 : RecordVal::~RecordVal()
2849 : : {
2850 : 36628 : delete_vals(AsNonConstRecord());
2851 [ + - ][ # # ]: 36628 : }
[ # # ]
2852 : :
2853 : 228197 : void RecordVal::Assign(int field, Val* new_val, Opcode op)
2854 : : {
2855 [ + + ][ + + ]: 228197 : if ( Lookup(field) &&
[ - + ][ - + ]
2856 : : record_type->FieldType(field)->Tag() == TYPE_TABLE &&
2857 : : new_val->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
2858 : : {
2859 : : // Join two mergeable sets.
2860 : 0 : Val* old = Lookup(field);
2861 [ # # ]: 0 : if ( old->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
2862 : : {
2863 [ # # ][ # # ]: 0 : if ( LoggingAccess() && op != OP_NONE )
[ # # ]
2864 : : {
2865 : 0 : StringVal* index = new StringVal(Type()->AsRecordType()->FieldName(field));
2866 : 0 : StateAccess::Log(new StateAccess(OP_ASSIGN_IDX, this, index, new_val, old));
2867 : 0 : Unref(index);
2868 : : }
2869 : :
2870 : 0 : new_val->AsTableVal()->AddTo(old->AsTableVal(), 0, false);
2871 : 0 : Unref(new_val);
2872 : 0 : return;
2873 : : }
2874 : : }
2875 : :
2876 : 228197 : Val* old_val = AsNonConstRecord()->replace(field, new_val);
2877 : :
2878 [ - + # # ]: 228197 : if ( LoggingAccess() && op != OP_NONE )
[ - + ]
2879 : : {
2880 [ # # ][ # # ]: 0 : if ( new_val && new_val->IsMutableVal() )
[ # # ]
2881 : 0 : new_val->AsMutableVal()->AddProperties(GetProperties());
2882 : :
2883 : 0 : StringVal* index = new StringVal(Type()->AsRecordType()->FieldName(field));
2884 : : StateAccess::Log(
2885 : : new StateAccess(
2886 : : op == OP_INCR ? OP_INCR_IDX : OP_ASSIGN_IDX,
2887 [ # # ]: 0 : this, index, new_val, old_val));
2888 : 0 : Unref(index); // The logging may keep a cached copy.
2889 : : }
2890 : :
2891 : 228197 : Unref(old_val);
2892 : 228197 : Modified();
2893 : : }
2894 : :
2895 : 553910 : Val* RecordVal::Lookup(int field) const
2896 : : {
2897 : 553910 : return (*AsRecord())[field];
2898 : : }
2899 : :
2900 : 0 : void RecordVal::Describe(ODesc* d) const
2901 : : {
2902 : 0 : const val_list* vl = AsRecord();
2903 : 0 : int n = vl->length();
2904 : :
2905 [ # # # # ]: 0 : if ( d->IsBinary() || d->IsPortable() )
[ # # ]
2906 : : {
2907 : 0 : record_type->Describe(d);
2908 : 0 : d->SP();
2909 : 0 : d->Add(n);
2910 : 0 : d->SP();
2911 : : }
2912 : : else
2913 : 0 : d->Add("[");
2914 : :
2915 [ # # ]: 0 : loop_over_list(*vl, i)
2916 : : {
2917 [ # # ][ # # ]: 0 : if ( ! d->IsBinary() && i > 0 )
[ # # ]
2918 : 0 : d->Add(", ");
2919 : :
2920 : 0 : d->Add(record_type->FieldName(i));
2921 : :
2922 [ # # ]: 0 : if ( ! d->IsBinary() )
2923 : 0 : d->Add("=");
2924 : :
2925 : 0 : Val* v = (*vl)[i];
2926 [ # # ]: 0 : if ( v )
2927 : 0 : v->Describe(d);
2928 : : else
2929 : 0 : d->Add("<uninitialized>");
2930 : : }
2931 : :
2932 [ # # ]: 0 : if ( d->IsReadable() )
2933 : 0 : d->Add("]");
2934 : 0 : }
2935 : :
2936 : 3 : IMPLEMENT_SERIAL(RecordVal, SER_RECORD_VAL);
2937 : :
2938 : 0 : bool RecordVal::DoSerialize(SerialInfo* info) const
2939 : : {
2940 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_RECORD_VAL, MutableVal);
2941 : :
2942 : : // We could use the type name as a tag here.
2943 : 0 : info->s->WriteOpenTag("record");
2944 : :
2945 : : // We don't need to serialize record_type as it's simply the
2946 : : // casted table_type.
2947 : : // FIXME: What about origin?
2948 : :
2949 [ # # ]: 0 : if ( ! SERIALIZE(val.val_list_val->length()) )
2950 : 0 : return false;
2951 : :
2952 [ # # ]: 0 : loop_over_list(*val.val_list_val, i)
2953 : : {
2954 : 0 : info->s->WriteOpenTag(record_type->FieldName(i));
2955 : 0 : Val* v = (*val.val_list_val)[i];
2956 [ # # # # ]: 0 : SERIALIZE_OPTIONAL(v);
[ # # ][ # # ]
[ # # ][ # # ]
2957 : 0 : info->s->WriteCloseTag(record_type->FieldName(i));
2958 : : }
2959 : :
2960 : 0 : info->s->WriteCloseTag("record");
2961 : :
2962 : 0 : return true;
2963 : : }
2964 : :
2965 : 0 : bool RecordVal::DoUnserialize(UnserialInfo* info)
2966 : : {
2967 [ # # ]: 0 : DO_UNSERIALIZE(MutableVal);
2968 : :
2969 : 0 : record_type = (RecordType*) type;
2970 : 0 : origin = 0;
2971 : :
2972 : : int len;
2973 [ # # ]: 0 : if ( ! UNSERIALIZE(&len) )
2974 : : {
2975 : 0 : val.val_list_val = new val_list;
2976 : 0 : return false;
2977 : : }
2978 : :
2979 : 0 : val.val_list_val = new val_list(len);
2980 : :
2981 [ # # ]: 0 : for ( int i = 0; i < len; ++i )
2982 : : {
2983 : : Val* v;
2984 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info));
[ # # ]
2985 : 0 : AsNonConstRecord()->append(v); // correct for v==0, too.
2986 : : }
2987 : :
2988 : 0 : return true;
2989 : : }
2990 : :
2991 : 0 : bool RecordVal::AddProperties(Properties arg_props)
2992 : : {
2993 [ # # ]: 0 : if ( ! MutableVal::AddProperties(arg_props) )
2994 : 0 : return false;
2995 : :
2996 [ # # ]: 0 : if ( ! RecursiveProps(arg_props) )
2997 : 0 : return true;
2998 : :
2999 [ # # ]: 0 : loop_over_list(*val.val_list_val, i)
3000 : : {
3001 : 0 : Val* v = (*val.val_list_val)[i];
3002 [ # # # # ]: 0 : if ( v && v->IsMutableVal() )
[ # # ]
3003 : 0 : v->AsMutableVal()->AddProperties(RecursiveProps(arg_props));
3004 : : }
3005 : 0 : return true;
3006 : : }
3007 : :
3008 : :
3009 : 0 : bool RecordVal::RemoveProperties(Properties arg_props)
3010 : : {
3011 [ # # ]: 0 : if ( ! MutableVal::RemoveProperties(arg_props) )
3012 : 0 : return false;
3013 : :
3014 [ # # ]: 0 : if ( ! RecursiveProps(arg_props) )
3015 : 0 : return true;
3016 : :
3017 [ # # ]: 0 : loop_over_list(*val.val_list_val, i)
3018 : : {
3019 : 0 : Val* v = (*val.val_list_val)[i];
3020 [ # # # # ]: 0 : if ( v && v->IsMutableVal() )
[ # # ]
3021 : 0 : v->AsMutableVal()->RemoveProperties(RecursiveProps(arg_props));
3022 : : }
3023 : 0 : return true;
3024 : : }
3025 : :
3026 : 0 : unsigned int RecordVal::MemoryAllocation() const
3027 : : {
3028 : 0 : unsigned int size = 0;
3029 : :
3030 [ # # ]: 0 : for ( int i = 0; i < type->AsRecordType()->NumFields(); ++i )
3031 : : {
3032 : 0 : Val* v = (*val.val_list_val)[i];
3033 : :
3034 : : // v might be nil for records that don't wind
3035 : : // up being set to a value.
3036 [ # # ]: 0 : if ( v )
3037 : 0 : size += v->MemoryAllocation();
3038 : : }
3039 : :
3040 : 0 : return size + padded_sizeof(*this) + val.val_list_val->MemoryAllocation();
3041 : : }
3042 : :
3043 : 5847 : void EnumVal::ValDescribe(ODesc* d) const
3044 : : {
3045 : 5847 : const char* ename = type->AsEnumType()->Lookup(val.int_val);
3046 : :
3047 [ - + ]: 5847 : if ( ! ename )
3048 : 0 : ename = "<undefined>";
3049 : :
3050 : 5847 : const char* module_offset = strstr(ename, "::");
3051 [ + + ]: 5847 : if ( module_offset )
3052 : 2758 : ename = module_offset + 2;
3053 : :
3054 : 5847 : d->Add(ename);
3055 : 5847 : }
3056 : :
3057 : 3 : IMPLEMENT_SERIAL(EnumVal, SER_ENUM_VAL);
3058 : :
3059 : 0 : bool EnumVal::DoSerialize(SerialInfo* info) const
3060 : : {
3061 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_ENUM_VAL, Val);
3062 : 0 : return true;
3063 : : }
3064 : :
3065 : 0 : bool EnumVal::DoUnserialize(UnserialInfo* info)
3066 : : {
3067 [ # # ]: 0 : DO_UNSERIALIZE(Val);
3068 : 0 : return true;
3069 : : }
3070 : :
3071 : 1835 : VectorVal::VectorVal(VectorType* t) : MutableVal(t)
3072 : : {
3073 : 1835 : vector_type = t->Ref()->AsVectorType();
3074 : 1835 : val.vector_val = new vector<Val*>();
3075 : 1835 : }
3076 : :
3077 : 1821 : VectorVal::~VectorVal()
3078 : : {
3079 [ + + ][ # # ]: 24327 : for ( unsigned int i = 0; i < val.vector_val->size(); ++i )
[ # # ]
3080 : 22506 : Unref((*val.vector_val)[i]);
3081 : :
3082 : 1821 : Unref(vector_type);
3083 : :
3084 [ + - # # ]: 1821 : delete val.vector_val;
[ # # ]
3085 [ + - ][ # # ]: 1821 : }
[ # # ]
3086 : :
3087 : : bool VectorVal::Assign(unsigned int index, Val* element, const Expr* assigner,
3088 : 22601 : Opcode op)
3089 : : {
3090 [ + - ][ - + ]: 22601 : if ( element &&
[ - + ]
3091 : : ! same_type(element->Type(), vector_type->YieldType(), 0) )
3092 : : {
3093 : 0 : Unref(element);
3094 : 0 : return false;
3095 : : }
3096 : :
3097 [ + - ][ - + ]: 22601 : if ( index == 0 || index > (1 << 30) )
3098 : : {
3099 [ # # ]: 0 : if ( assigner )
3100 : : assigner->Error(fmt("index (%d) must be positive",
3101 : 0 : index));
3102 : 0 : Unref(element);
3103 : 0 : return true; // true = "no fatal error"
3104 : : }
3105 : :
3106 : 22601 : BroType* yt = Type()->AsVectorType()->YieldType();
3107 : :
3108 [ + - - + ]: 22601 : if ( yt && yt->Tag() == TYPE_TABLE &&
[ # # ][ - + ]
3109 : : element->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
3110 : : {
3111 : : // Join two mergeable sets.
3112 : 0 : Val* old = Lookup(index);
3113 [ # # # # ]: 0 : if ( old && old->AsTableVal()->FindAttr(ATTR_MERGEABLE) )
[ # # ]
3114 : : {
3115 [ # # ][ # # ]: 0 : if ( LoggingAccess() && op != OP_NONE )
[ # # ]
3116 : : {
3117 : 0 : Val* ival = new Val(index, TYPE_COUNT);
3118 : : StateAccess::Log(new StateAccess(OP_ASSIGN_IDX,
3119 : : this, ival, element,
3120 : 0 : (*val.vector_val)[index - 1]));
3121 : 0 : Unref(ival);
3122 : : }
3123 : :
3124 : 0 : element->AsTableVal()->AddTo(old->AsTableVal(), 0, false);
3125 : 0 : Unref(element);
3126 : 0 : return true;
3127 : : }
3128 : : }
3129 : :
3130 [ - + ]: 22601 : if ( index <= val.vector_val->size() )
3131 : 0 : Unref((*val.vector_val)[index - 1]);
3132 : : else
3133 : 22601 : val.vector_val->resize(index);
3134 : :
3135 [ - + ][ # # ]: 22601 : if ( LoggingAccess() && op != OP_NONE )
[ - + ]
3136 : : {
3137 [ # # ]: 0 : if ( element->IsMutableVal() )
3138 : 0 : element->AsMutableVal()->AddProperties(GetProperties());
3139 : :
3140 : 0 : Val* ival = new Val(index, TYPE_COUNT);
3141 : :
3142 : : StateAccess::Log(new StateAccess(op == OP_INCR ?
3143 : : OP_INCR_IDX : OP_ASSIGN_IDX,
3144 [ # # ]: 0 : this, ival, element, (*val.vector_val)[index - 1]));
3145 : 0 : Unref(ival);
3146 : : }
3147 : :
3148 : : // Note: we do *not* Ref() the element, if any, at this point.
3149 : : // AssignExpr::Eval() already does this; other callers must remember
3150 : : // to do it similarly.
3151 : 22601 : (*val.vector_val)[index - 1] = element;
3152 : :
3153 : 22601 : Modified();
3154 : 22601 : return true;
3155 : : }
3156 : :
3157 : : bool VectorVal::AssignRepeat(unsigned int index, unsigned int how_many,
3158 : 0 : Val* element, const Expr* assigner)
3159 : : {
3160 : 0 : ResizeAtLeast(index + how_many - 1);
3161 : :
3162 [ # # ]: 0 : for ( unsigned int i = index; i < index + how_many; ++i )
3163 [ # # ]: 0 : if ( ! Assign(i, element, assigner) )
3164 : 0 : return false;
3165 : :
3166 : 0 : return true;
3167 : : }
3168 : :
3169 : :
3170 : 45617 : Val* VectorVal::Lookup(unsigned int index) const
3171 : : {
3172 [ + + ][ - + ]: 45617 : if ( index == 0 || index > val.vector_val->size() )
[ + + ]
3173 : 1379 : return 0;
3174 : :
3175 : 45617 : return (*val.vector_val)[index - 1];
3176 : : }
3177 : :
3178 : 0 : unsigned int VectorVal::Resize(unsigned int new_num_elements)
3179 : : {
3180 : 0 : unsigned int oldsize = val.vector_val->size();
3181 : 0 : val.vector_val->reserve(new_num_elements);
3182 : 0 : val.vector_val->resize(new_num_elements);
3183 : 0 : return oldsize;
3184 : : }
3185 : :
3186 : 0 : unsigned int VectorVal::ResizeAtLeast(unsigned int new_num_elements)
3187 : : {
3188 : 0 : unsigned int old_size = val.vector_val->size();
3189 [ # # ]: 0 : if ( new_num_elements <= old_size )
3190 : 0 : return old_size;
3191 : :
3192 : 0 : return Resize(new_num_elements);
3193 : : }
3194 : :
3195 : 13 : bool VectorVal::AddProperties(Properties arg_props)
3196 : : {
3197 [ + - ]: 13 : if ( ! MutableVal::AddProperties(arg_props) )
3198 : 13 : return false;
3199 : :
3200 [ # # ]: 0 : if ( ! RecursiveProps(arg_props) )
3201 : 0 : return true;
3202 : :
3203 [ # # ]: 0 : for ( unsigned int i = 0; i < val.vector_val->size(); ++i )
3204 [ # # ]: 0 : if ( (*val.vector_val)[i]->IsMutableVal() )
3205 : 0 : (*val.vector_val)[i]->AsMutableVal()->AddProperties(RecursiveProps(arg_props));
3206 : :
3207 : 13 : return true;
3208 : : }
3209 : :
3210 : 0 : bool VectorVal::RemoveProperties(Properties arg_props)
3211 : : {
3212 [ # # ]: 0 : if ( ! MutableVal::RemoveProperties(arg_props) )
3213 : 0 : return false;
3214 : :
3215 [ # # ]: 0 : if ( ! RecursiveProps(arg_props) )
3216 : 0 : return true;
3217 : :
3218 [ # # ]: 0 : for ( unsigned int i = 0; i < val.vector_val->size(); ++i )
3219 [ # # ]: 0 : if ( (*val.vector_val)[i]->IsMutableVal() )
3220 : 0 : (*val.vector_val)[i]->AsMutableVal()->RemoveProperties(RecursiveProps(arg_props));
3221 : :
3222 : 0 : return true;
3223 : : }
3224 : :
3225 : 3 : IMPLEMENT_SERIAL(VectorVal, SER_VECTOR_VAL);
3226 : :
3227 : 0 : bool VectorVal::DoSerialize(SerialInfo* info) const
3228 : : {
3229 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_VECTOR_VAL, MutableVal);
3230 : :
3231 : 0 : info->s->WriteOpenTag("vector");
3232 : :
3233 [ # # ]: 0 : if ( ! SERIALIZE(unsigned(val.vector_val->size())) )
3234 : 0 : return false;
3235 : :
3236 [ # # ]: 0 : for ( unsigned int i = 0; i < val.vector_val->size(); ++i )
3237 : : {
3238 : 0 : info->s->WriteOpenTag("value");
3239 : 0 : Val* v = (*val.vector_val)[i];
3240 [ # # # # ]: 0 : SERIALIZE_OPTIONAL(v);
[ # # ][ # # ]
[ # # ][ # # ]
3241 : 0 : info->s->WriteCloseTag("value");
3242 : : }
3243 : :
3244 : 0 : info->s->WriteCloseTag("vector");
3245 : :
3246 : 0 : return true;
3247 : : }
3248 : :
3249 : 0 : bool VectorVal::DoUnserialize(UnserialInfo* info)
3250 : : {
3251 [ # # ]: 0 : DO_UNSERIALIZE(MutableVal);
3252 : :
3253 : 0 : val.vector_val = new vector<Val*>;
3254 : 0 : vector_type = type->Ref()->AsVectorType();
3255 : :
3256 : : int len;
3257 [ # # ]: 0 : if ( ! UNSERIALIZE(&len) )
3258 : 0 : return false;
3259 : :
3260 [ # # ]: 0 : for ( int i = 0; i < len; ++i )
3261 : : {
3262 : : Val* v;
3263 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY));
[ # # ]
3264 : 0 : Assign(i + VECTOR_MIN, v, 0);
3265 : : }
3266 : :
3267 : 0 : return true;
3268 : : }
3269 : :
3270 : 0 : void VectorVal::ValDescribe(ODesc* d) const
3271 : : {
3272 : 0 : d->Add("[");
3273 : :
3274 [ # # ]: 0 : if ( val.vector_val->size() > 0 )
3275 [ # # ]: 0 : for ( unsigned int i = 0; i < (val.vector_val->size() - 1); ++i )
3276 : : {
3277 [ # # ]: 0 : if ( (*val.vector_val)[i] )
3278 : 0 : (*val.vector_val)[i]->Describe(d);
3279 : 0 : d->Add(", ");
3280 : : }
3281 : :
3282 [ # # ][ # # ]: 0 : if ( val.vector_val->size() &&
[ # # ]
3283 : : (*val.vector_val)[val.vector_val->size() - 1] )
3284 : 0 : (*val.vector_val)[val.vector_val->size() - 1]->Describe(d);
3285 : :
3286 : 0 : d->Add("]");
3287 : 0 : }
3288 : :
3289 : :
3290 : 6077 : Val* check_and_promote(Val* v, const BroType* t, int is_init)
3291 : : {
3292 : 6077 : BroType* vt = v->Type();
3293 : :
3294 : 6077 : vt = flatten_type(vt);
3295 : 6077 : t = flatten_type(t);
3296 : :
3297 : 6077 : TypeTag t_tag = t->Tag();
3298 : 6077 : TypeTag v_tag = vt->Tag();
3299 : :
3300 [ + + + + ]: 6077 : if ( ! EitherArithmetic(t_tag, v_tag) ||
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ - + ]
[ + - ][ - + ]
3301 : : /* allow sets as initializers */
3302 : : (is_init && v_tag == TYPE_TABLE) )
3303 : : {
3304 [ + - ]: 4315 : if ( same_type(t, vt, is_init) )
3305 : 4315 : return v;
3306 : :
3307 : 0 : t->Error("type clash", v);
3308 : 0 : Unref(v);
3309 : 0 : return 0;
3310 : : }
3311 : :
3312 [ + + ][ + + ]: 1762 : if ( ! BothArithmetic(t_tag, v_tag) &&
[ + - ][ + + ]
[ + + ][ + + ]
[ + - ][ - + ]
[ + - ][ - + ]
[ # # ][ # # ]
[ + - ][ - + ]
[ - + ]
3313 : : (! IsArithmetic(v_tag) || t_tag != TYPE_TIME || ! v->IsZero()) )
3314 : : {
3315 [ # # ][ # # ]: 0 : if ( t_tag == TYPE_LIST || v_tag == TYPE_LIST )
3316 : 0 : t->Error("list mixed with scalar", v);
3317 : : else
3318 : 0 : t->Error("arithmetic mixed with non-arithmetic", v);
3319 : 0 : Unref(v);
3320 : 0 : return 0;
3321 : : }
3322 : :
3323 [ + + ]: 1762 : if ( v_tag == t_tag )
3324 : 1759 : return v;
3325 : :
3326 [ - + ]: 3 : if ( t_tag != TYPE_TIME )
3327 : : {
3328 : 0 : TypeTag mt = max_type(t_tag, v_tag);
3329 [ # # ]: 0 : if ( mt != t_tag )
3330 : : {
3331 : 0 : t->Error("over-promotion of arithmetic value", v);
3332 : 0 : Unref(v);
3333 : 0 : return 0;
3334 : : }
3335 : : }
3336 : :
3337 : : // Need to promote v to type t.
3338 : 3 : InternalTypeTag it = t->InternalType();
3339 : 3 : InternalTypeTag vit = vt->InternalType();
3340 : :
3341 [ - + ]: 3 : if ( it == vit )
3342 : : // Already has the right internal type.
3343 : 0 : return v;
3344 : :
3345 : : Val* promoted_v;
3346 [ - - + - ]: 3 : switch ( it ) {
3347 : : case TYPE_INTERNAL_INT:
3348 : 0 : promoted_v = new Val(v->CoerceToInt(), t_tag);
3349 : 0 : break;
3350 : :
3351 : : case TYPE_INTERNAL_UNSIGNED:
3352 : 0 : promoted_v = new Val(v->CoerceToUnsigned(), t_tag);
3353 : 0 : break;
3354 : :
3355 : : case TYPE_INTERNAL_DOUBLE:
3356 : 3 : promoted_v = new Val(v->CoerceToDouble(), t_tag);
3357 : 3 : break;
3358 : :
3359 : : default:
3360 : 0 : internal_error("bad internal type in check_and_promote()");
3361 : : Unref(v);
3362 : : return 0;
3363 : : }
3364 : :
3365 : 3 : Unref(v);
3366 : 6077 : return promoted_v;
3367 : : }
3368 : :
3369 : 0 : int same_val(const Val* /* v1 */, const Val* /* v2 */)
3370 : : {
3371 : 0 : internal_error("same_val not implemented");
3372 : : return 0;
3373 : : }
3374 : :
3375 : 0 : bool is_atomic_val(const Val* v)
3376 : : {
3377 [ # # ]: 0 : switch ( v->Type()->InternalType() ) {
3378 : : case TYPE_INTERNAL_INT:
3379 : : case TYPE_INTERNAL_UNSIGNED:
3380 : : case TYPE_INTERNAL_DOUBLE:
3381 : : case TYPE_INTERNAL_STRING:
3382 : : case TYPE_INTERNAL_ADDR:
3383 : : case TYPE_INTERNAL_SUBNET:
3384 : 0 : return true;
3385 : : default:
3386 : 0 : return false;
3387 : : }
3388 : : }
3389 : :
3390 : 0 : int same_atomic_val(const Val* v1, const Val* v2)
3391 : : {
3392 : : // This is a very preliminary implementation of same_val(),
3393 : : // true only for equal, simple atomic values of same type.
3394 [ # # ]: 0 : if ( v1->Type()->Tag() != v2->Type()->Tag() )
3395 : 0 : return 0;
3396 : :
3397 [ # # # # # : 0 : switch ( v1->Type()->InternalType() ) {
# # ]
3398 : : case TYPE_INTERNAL_INT:
3399 : 0 : return v1->InternalInt() == v2->InternalInt();
3400 : : case TYPE_INTERNAL_UNSIGNED:
3401 : 0 : return v1->InternalUnsigned() == v2->InternalUnsigned();
3402 : : case TYPE_INTERNAL_DOUBLE:
3403 : 0 : return v1->InternalDouble() == v2->InternalDouble();
3404 : : case TYPE_INTERNAL_STRING:
3405 : 0 : return Bstr_eq(v1->AsString(), v2->AsString());
3406 : :
3407 : : case TYPE_INTERNAL_ADDR:
3408 : : {
3409 : 0 : const addr_type& a1 = v1->AsAddr();
3410 : 0 : const addr_type& a2 = v2->AsAddr();
3411 : : #ifdef BROv6
3412 : : return addr_eq(a1, a2);
3413 : : #else
3414 : 0 : return addr_eq(&a1, &a2);
3415 : : #endif
3416 : : }
3417 : :
3418 : : case TYPE_INTERNAL_SUBNET:
3419 : 0 : return subnet_eq(v1->AsSubNet(), v2->AsSubNet());
3420 : :
3421 : : default:
3422 : 0 : internal_error("same_atomic_val called for non-atomic value");
3423 : : return 0;
3424 : : }
3425 : :
3426 : : return 0;
3427 : : }
3428 : :
3429 : 6344 : void describe_vals(const val_list* vals, ODesc* d, int offset)
3430 : : {
3431 [ - + ]: 6344 : if ( ! d->IsReadable() )
3432 : : {
3433 : 0 : d->Add(vals->length());
3434 : 0 : d->SP();
3435 : : }
3436 : :
3437 [ + + ]: 12688 : for ( int i = offset; i < vals->length(); ++i )
3438 : : {
3439 [ - + ][ # # ]: 6344 : if ( i > offset && d->IsReadable() )
[ - + ]
3440 : 0 : d->Add(", ");
3441 : :
3442 : 6344 : (*vals)[i]->Describe(d);
3443 : : }
3444 : 6344 : }
3445 : :
3446 : 43566 : void delete_vals(val_list* vals)
3447 : : {
3448 [ + - ]: 43566 : if ( vals )
3449 : : {
3450 [ + + ]: 267195 : loop_over_list(*vals, i)
3451 : 223629 : Unref((*vals)[i]);
3452 [ + - ]: 43566 : delete vals;
3453 : : }
3454 [ + - ][ + - ]: 43572 : }
|