1 /*
2  * Argus Software.  Argus files - Utilities
3  * Copyright (c) 2000-2015 QoSient, LLC
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21 
22 /*
23  * $Id: //depot/argus/argus/argus/ArgusUtil.c#88 $
24  * $DateTime: 2015/08/06 16:35:55 $
25  * $Change: 3044 $
26  */
27 
28 /* ArgusUtil.c */
29 
30 #ifdef HAVE_CONFIG_H
31 #include "argus_config.h"
32 #endif
33 
34 #define _GNU_SOURCE
35 
36 #if !defined(ArgusUtil)
37 #define ArgusUtil
38 #endif
39 
40 #include <stdlib.h>
41 #include <inttypes.h>
42 #include <stdio.h>
43 #include <math.h>
44 
45 #if defined(HAVE_SYS_VFS_H)
46 #include <sys/vfs.h>
47 #else
48 #include <sys/param.h>
49 #include <sys/mount.h>
50 #endif
51 
52 
53 #if defined(ARGUS_THREADS)
54 #include <pthread.h>
55 #endif
56 
57 #if defined(ARGUS_SASL)
58 #include <sasl/sasl.h>
59 #endif
60 
61 #define Argus_Parser
62 
63 #include <argus_compat.h>
64 #include <argus_parser.h>
65 
66 #include <ArgusModeler.h>
67 #include <argus_dscodepoints.h>
68 #include <argus_encapsulations.h>
69 
70 
71 long long
ArgusTimeDiff(struct timeval * start,struct timeval * stop)72 ArgusTimeDiff (struct timeval *start, struct timeval *stop)
73 {
74    long long retn, stime, etime;
75 
76    stime = (start->tv_sec * 1000000LL) + start->tv_usec;
77    etime = (stop->tv_sec  * 1000000LL) +  stop->tv_usec;
78 
79    retn = stime - etime;
80    return (retn);
81 }
82 
83 unsigned long long
ArgusAbsTimeDiff(struct timeval * start,struct timeval * stop)84 ArgusAbsTimeDiff (struct timeval *start, struct timeval *stop)
85 {
86    unsigned long long retn = 0;
87    struct timeval *t1 = start, *t2 = stop;
88 
89    if ((stop->tv_sec < start->tv_sec) || ((stop->tv_sec == start->tv_sec) &&
90                                           (stop->tv_usec < start->tv_usec))) {
91       t2 = start;
92       t1 = stop;
93    }
94 
95    retn = ((t2->tv_sec * 1000000LL) + t2->tv_usec) -
96           ((t1->tv_sec * 1000000LL) + t1->tv_usec);
97 
98    return (retn);
99 }
100 
101 
102 struct ArgusListStruct *
ArgusNewList()103 ArgusNewList ()
104 {
105    struct ArgusListStruct *retn = NULL;
106 
107    if ((retn = (struct ArgusListStruct *) ArgusCalloc (1, sizeof (struct ArgusListStruct))) != NULL) {
108       retn->start = NULL;
109       retn->count = 0;
110 #if defined(ARGUS_THREADS)
111       pthread_mutex_init(&retn->lock, NULL);
112       pthread_cond_init(&retn->cond, NULL);
113 #endif
114    }
115 
116 #ifdef ARGUSDEBUG
117    ArgusDebug (4, "ArgusNewList () returning %p\n", retn);
118 #endif
119    return (retn);
120 }
121 
122 void
ArgusDeleteList(struct ArgusListStruct * list,int type)123 ArgusDeleteList (struct ArgusListStruct *list, int type)
124 {
125    if (list) {
126 #ifdef ARGUSDEBUG
127       ArgusDebug (4, "ArgusDeleteList (%p, %d) %d items on list\n", list, type, list->count);
128 #endif
129       while (list->start) {
130          struct ArgusListRecord *retn = ArgusPopFrontList(list, ARGUS_LOCK);
131          switch (type) {
132              case ARGUS_RFILE_LIST: {
133                 struct ArgusRfileStruct *rfile = (struct ArgusRfileStruct *) retn;
134                 if (rfile->name != NULL)
135                    free(rfile->name);
136                 ArgusFree(retn);
137                 break;
138              }
139 
140              case ARGUS_WFILE_LIST: {
141                 struct ArgusWfileStruct *wfile = (struct ArgusWfileStruct *) retn;
142                 if (wfile->filename != NULL)
143                    free(wfile->filename);
144                 if (wfile->filter != NULL)
145                    free(wfile->filter);
146                 ArgusFree(retn);
147                 break;
148              }
149 
150              case ARGUS_DEVICE_LIST: {
151                 struct ArgusDeviceStruct *device = (struct ArgusDeviceStruct *) retn;
152                 if (device->name != NULL)
153                    free(device->name);
154                 ArgusFree(retn);
155                 break;
156              }
157 
158              case ARGUS_OUTPUT_LIST:
159                 ArgusFreeListRecord(retn);
160                 break;
161 
162              case ARGUS_EVENT_LIST: {
163                 struct ArgusListObjectStruct *lobj = (struct ArgusListObjectStruct *) retn;
164                 if (lobj->obj != NULL) {
165                    ArgusFree(lobj);
166                 }
167                 ArgusFree(retn);
168                 break;
169             }
170 
171              case ARGUS_BIND_ADDR_LIST: {
172                 struct ArgusBindAddrStruct *baddr = (struct ArgusBindAddrStruct *) retn;
173                 if (baddr->addr != NULL) {
174                    free(baddr->addr);
175                 }
176                 ArgusFree(retn);
177                 break;
178             }
179          }
180       }
181 #if defined(ARGUS_THREADS)
182       pthread_cond_destroy(&list->cond);
183       pthread_mutex_destroy(&list->lock);
184 #endif
185       ArgusFree (list);
186    }
187 
188 #ifdef ARGUSDEBUG
189    ArgusDebug (4, "ArgusDeleteList (%p, %d) returning\n", list, type);
190 #endif
191 }
192 
193 int
ArgusListEmpty(struct ArgusListStruct * list)194 ArgusListEmpty (struct ArgusListStruct *list)
195 {
196    return (list->count == 0);
197 }
198 
199 int
ArgusGetListCount(struct ArgusListStruct * list)200 ArgusGetListCount(struct ArgusListStruct *list)
201 {
202    return (list->count);
203 }
204 
205 
206 int
ArgusPushFrontList(struct ArgusListStruct * list,struct ArgusListRecord * rec,int lstat)207 ArgusPushFrontList(struct ArgusListStruct *list, struct ArgusListRecord *rec, int lstat)
208 {
209    int retn = 0;
210 
211    if (list && rec) {
212 #if defined(ARGUS_THREADS)
213       if (lstat)
214          pthread_mutex_lock(&list->lock);
215 #endif
216       if (list->start) {
217          rec->nxt = list->start;
218       } else {
219          rec->nxt = NULL;
220       }
221       list->start = (struct ArgusListObjectStruct *) rec;
222       if (list->end == NULL)
223          list->end = (struct ArgusListObjectStruct *) rec;
224       list->count++;
225       list->pushed++;
226 #if defined(ARGUS_THREADS)
227       if (lstat)
228          pthread_mutex_unlock(&list->lock);
229 #endif
230       retn++;
231    }
232 
233 #ifdef ARGUSDEBUG
234    ArgusDebug (6, "ArgusPushFrontList (%p, %p, %d) returning %p\n", list, rec, lstat);
235 #endif
236 
237    return (retn);
238 }
239 
240 int
ArgusPushBackList(struct ArgusListStruct * list,struct ArgusListRecord * rec,int lstat)241 ArgusPushBackList(struct ArgusListStruct *list, struct ArgusListRecord *rec, int lstat)
242 {
243    int retn = 0;
244 
245    if (list && rec) {
246       rec->nxt = NULL;
247 
248 #if defined(ARGUS_THREADS)
249       if (lstat)
250          pthread_mutex_lock(&list->lock);
251 #endif
252       if (list->end) {
253          list->end->nxt = (struct ArgusListObjectStruct *) rec;
254       } else {
255          list->start = (struct ArgusListObjectStruct *) rec;
256       }
257       list->end = (struct ArgusListObjectStruct *) rec;
258       list->count++;
259       list->pushed++;
260 #if defined(ARGUS_THREADS)
261       if (lstat)
262          pthread_mutex_unlock(&list->lock);
263 #endif
264       retn++;
265    }
266 
267 #ifdef ARGUSDEBUG
268    ArgusDebug (6, "ArgusPushBackList (%p, %p, %d) returning %d\n", list, rec, lstat, retn);
269 #endif
270 
271    return (retn);
272 }
273 
274 
275 void
ArgusLoadList(struct ArgusListStruct * l1,struct ArgusListStruct * l2)276 ArgusLoadList(struct ArgusListStruct *l1, struct ArgusListStruct *l2)
277 {
278    if (l1 && l2) {
279       int count;
280 #if defined(ARGUS_THREADS)
281       pthread_mutex_lock(&l1->lock);
282       pthread_mutex_lock(&l2->lock);
283 #endif
284       count = l1->count;
285 
286       if (l2->start == NULL)
287          l2->start = l1->start;
288       else
289          l2->end->nxt = l1->start;
290 
291       l2->end = l1->end;
292       l2->count += count;
293 
294       l1->start = NULL;
295       l1->end = NULL;
296       l1->loaded += count;
297       l1->count = 0;
298 
299 #if defined(ARGUS_THREADS)
300       pthread_mutex_unlock(&l2->lock);
301       pthread_mutex_unlock(&l1->lock);
302 #endif
303 
304 #ifdef ARGUSDEBUG
305    ArgusDebug (5, "ArgusLoadList (%p, %p) load %d objects\n", l1, l2, count);
306 #endif
307    }
308 }
309 
310 
311 struct ArgusListRecord *
ArgusPopFrontList(struct ArgusListStruct * list,int lstat)312 ArgusPopFrontList(struct ArgusListStruct *list, int lstat)
313 {
314    struct ArgusListRecord *retn = NULL;
315 
316 #if defined(ARGUS_THREADS)
317    if (lstat)
318       pthread_mutex_lock(&list->lock);
319 #endif
320    if ((retn = (struct ArgusListRecord *) list->start)) {
321       list->start = retn->nxt;
322       list->count--;
323       list->popped++;
324       if (list->start == NULL) {
325          list->end = NULL;
326          if (list->count != 0)
327             ArgusLog (LOG_ERR, "ArgusPopFrontList(%p, %d) list empty count is %d\n", list, lstat, list->count);
328       }
329    }
330 #if defined(ARGUS_THREADS)
331    if (lstat)
332       pthread_mutex_unlock(&list->lock);
333 #endif
334 
335 #ifdef ARGUSDEBUG
336    ArgusDebug (9, "ArgusPopFrontList (%p) returning\n", retn);
337 #endif
338 
339    return (retn);
340 }
341 
342 
343 struct ArgusQueueStruct *
ArgusNewQueue()344 ArgusNewQueue ()
345 {
346    struct ArgusQueueStruct *retn =  NULL;
347 
348    if ((retn = (struct ArgusQueueStruct *) ArgusCalloc (1, sizeof (struct ArgusQueueStruct))) != NULL) {
349       retn->count = 0;
350 #if defined(ARGUS_THREADS)
351       pthread_mutex_init(&retn->lock, NULL);
352 #endif
353       retn->start = NULL;
354       retn->end   = NULL;
355    }
356 
357 #ifdef ARGUSDEBUG
358    ArgusDebug (4, "ArgusNewQueue () returning %p\n", retn);
359 #endif
360 
361    return (retn);
362 }
363 
364 void
ArgusDeleteQueue(struct ArgusQueueStruct * queue)365 ArgusDeleteQueue (struct ArgusQueueStruct *queue)
366 {
367    struct ArgusQueueHeader *obj = NULL;
368 
369    if (queue != NULL) {
370 #if defined(ARGUS_THREADS)
371       pthread_mutex_lock(&queue->lock);
372 #endif
373 
374 #ifdef ARGUSDEBUG
375       if (queue->count > 0)
376          ArgusDebug (1, "ArgusDeleteQueue (%p) contains %d items\n", queue, queue->count);
377 #endif
378       while ((obj = ArgusPopQueue(queue, ARGUS_LOCK)))
379          ArgusFree(obj);
380 
381       if (queue->array != NULL) {
382          ArgusFree(queue->array);
383          queue->array = NULL;
384       }
385 
386 #if defined(ARGUS_THREADS)
387       pthread_mutex_unlock(&queue->lock);
388 #endif
389 
390 #if defined(ARGUS_THREADS)
391       pthread_mutex_destroy(&queue->lock);
392 #endif
393       ArgusFree(queue);
394    }
395 
396 #ifdef ARGUSDEBUG
397    ArgusDebug (4, "ArgusDeleteQueue (%p) returning\n", queue);
398 #endif
399 }
400 
401 
402 
403 int
ArgusGetQueueCount(struct ArgusQueueStruct * queue)404 ArgusGetQueueCount(struct ArgusQueueStruct *queue)
405 {
406 
407 #ifdef ARGUSDEBUG
408    ArgusDebug (10, "ArgusGetQueueCount (%p) returning %d\n", queue, queue->count);
409 #endif
410 
411    return (queue->count);
412 }
413 
414 
415 void
ArgusPushQueue(struct ArgusQueueStruct * queue,struct ArgusQueueHeader * obj,int type)416 ArgusPushQueue(struct ArgusQueueStruct *queue, struct ArgusQueueHeader *obj, int type)
417 {
418 #if defined(ARGUS_THREADS)
419    if (type == ARGUS_LOCK)
420       pthread_mutex_lock(&queue->lock);
421 #endif
422    if ((ArgusAddToQueue (queue, obj, ARGUS_NOLOCK)) > 0) {
423       queue->start = queue->start->prv;
424       queue->end   = queue->start->prv;
425    }
426 
427 #if defined(ARGUS_THREADS)
428    if (type == ARGUS_LOCK)
429       pthread_mutex_unlock(&queue->lock);
430 #endif
431 
432 #ifdef ARGUSDEBUG
433    ArgusDebug (10, "ArgusPushQueue (%p, %p) returning\n", queue, obj);
434 #endif
435 }
436 
437 
438 int
ArgusAddToQueue(struct ArgusQueueStruct * queue,struct ArgusQueueHeader * obj,int type)439 ArgusAddToQueue(struct ArgusQueueStruct *queue, struct ArgusQueueHeader *obj, int type)
440 {
441    int retn = 0;
442 
443    if (queue && obj) {
444       if (obj->queue == NULL) {
445 #if defined(ARGUS_THREADS)
446          if (type == ARGUS_LOCK)
447             pthread_mutex_lock(&queue->lock);
448 #endif
449          if (queue->start != NULL) {
450             obj->prv = queue->start->prv;
451             queue->start->prv = obj;
452             obj->nxt = queue->start;
453             obj->prv->nxt = obj;
454          } else {
455             queue->start = obj;
456             obj->nxt = obj;
457             obj->prv = obj;
458          }
459          queue->end = obj;
460          queue->count++;
461 #if defined(ARGUS_THREADS)
462          if (type == ARGUS_LOCK)
463             pthread_mutex_unlock(&queue->lock);
464 #endif
465          obj->queue = queue;
466 
467          if (ArgusSourceTask->ArgusReadingOffLine)
468             obj->qtime = ArgusModel->ArgusGlobalTime;
469          else
470             gettimeofday(&obj->qtime, 0L);
471          retn = 1;
472 
473       } else
474          ArgusLog (LOG_ERR, "ArgusAddToQueue (%p, %p) obj in queue %p\n", queue, obj, obj->queue);
475    } else
476       ArgusLog (LOG_ERR, "ArgusAddToQueue (%p, %p) parameter error\n", queue, obj);
477 
478 #ifdef ARGUSDEBUG
479    ArgusDebug (10, "ArgusAddToQueue (%p, %p) returning %d\n", queue, obj, retn);
480 #endif
481 
482    return (retn);
483 }
484 
485 
486 struct ArgusQueueHeader *
ArgusPopQueue(struct ArgusQueueStruct * queue,int type)487 ArgusPopQueue (struct ArgusQueueStruct *queue, int type)
488 {
489    struct ArgusQueueHeader *retn = NULL;
490    struct ArgusQueueHeader *obj = NULL;
491 
492    if (queue && queue->count) {
493 #if defined(ARGUS_THREADS)
494       if (type == ARGUS_LOCK)
495          pthread_mutex_lock(&queue->lock);
496 #endif
497       if ((obj = (struct ArgusQueueHeader *) queue->start) != NULL) {
498          queue->count--;
499 
500          if (queue->count) {
501             if (queue->start == obj)
502                queue->start = obj->nxt;
503 
504             obj->prv->nxt = obj->nxt;
505             obj->nxt->prv = obj->prv;
506 
507             queue->end    = queue->start->prv;
508 
509          } else {
510             queue->start = NULL;
511             queue->end   = NULL;
512          }
513       }
514 #if defined(ARGUS_THREADS)
515       if (type == ARGUS_LOCK)
516          pthread_mutex_unlock(&queue->lock);
517 #endif
518 
519       if (obj != NULL) {
520          obj->prv = NULL;
521          obj->nxt = NULL;
522          obj->queue = NULL;
523          retn = obj;
524       }
525    }
526 
527 #ifdef ARGUSDEBUG
528    ArgusDebug (10, "ArgusPopQueue (%p) returning %p\n", queue, retn);
529 #endif
530 
531    return(retn);
532 }
533 
534 struct ArgusQueueHeader *
ArgusPopBackQueue(struct ArgusQueueStruct * queue,int type)535 ArgusPopBackQueue (struct ArgusQueueStruct *queue, int type)
536 {
537    struct ArgusQueueHeader *retn = NULL;
538    struct ArgusQueueHeader *obj = NULL;
539 
540    if (queue && queue->count) {
541 #if defined(ARGUS_THREADS)
542       if (type == ARGUS_LOCK)
543          pthread_mutex_lock(&queue->lock);
544 #endif
545       if ((obj = (struct ArgusQueueHeader *) queue->end) != NULL) {
546          queue->count--;
547 
548          if (queue->count) {
549             if (queue->start == obj)
550                queue->start = obj->nxt;
551 
552             obj->prv->nxt = obj->nxt;
553             obj->nxt->prv = obj->prv;
554 
555             queue->end    = queue->start->prv;
556 
557          } else {
558             queue->start = NULL;
559             queue->end   = NULL;
560          }
561       }
562 #if defined(ARGUS_THREADS)
563       if (type == ARGUS_LOCK)
564          pthread_mutex_unlock(&queue->lock);
565 #endif
566 
567       if (obj != NULL) {
568          obj->prv = NULL;
569          obj->nxt = NULL;
570          obj->queue = NULL;
571          retn = obj;
572       }
573    }
574 
575 #ifdef ARGUSDEBUG
576    ArgusDebug (10, "ArgusPopBackQueue (%p) returning %p\n", queue, retn);
577 #endif
578 
579    return(retn);
580 }
581 
582 
583 struct ArgusQueueHeader *
ArgusRemoveFromQueue(struct ArgusQueueStruct * queue,struct ArgusQueueHeader * obj,int type)584 ArgusRemoveFromQueue(struct ArgusQueueStruct *queue, struct ArgusQueueHeader *obj, int type)
585 {
586    struct ArgusQueueHeader *retn = NULL;
587 
588    if ((queue != NULL) && (obj != NULL)) {
589 #if defined(ARGUS_THREADS)
590       if (type == ARGUS_LOCK)
591          pthread_mutex_lock(&queue->lock);
592 #endif
593       if (obj->queue == queue) {
594          if (queue->count) {
595             queue->count--;
596 
597             if (queue->count) {
598                if (queue->start == obj)
599                   queue->start = obj->nxt;
600 
601                obj->prv->nxt = obj->nxt;
602                obj->nxt->prv = obj->prv;
603 
604                queue->end    = queue->start->prv;
605 
606             } else {
607                queue->start = NULL;
608                queue->end   = NULL;
609             }
610          }
611          obj->prv = NULL;
612          obj->nxt = NULL;
613          obj->queue = NULL;
614          retn = obj;
615       }
616 
617 #if defined(ARGUS_THREADS)
618       if (type == ARGUS_LOCK)
619          pthread_mutex_unlock(&queue->lock);
620 #endif
621    }
622 
623 #ifdef ARGUSDEBUG
624    ArgusDebug (10, "ArgusRemoveFromQueue (%p, %p) returning %p\n", queue, obj, obj);
625 #endif
626 
627    return (retn);
628 }
629 
630 #include <stdio.h>
631 #include <errno.h>
632 
633 
634 void
ArgusProcessQueue(struct ArgusModelerStruct * model,struct ArgusQueueStruct * queue,int status)635 ArgusProcessQueue(struct ArgusModelerStruct *model, struct ArgusQueueStruct *queue, int status)
636 {
637    struct ArgusFlowStruct *obj = NULL;
638 
639    switch (status) {
640       case ARGUS_STOP:
641       case ARGUS_SHUTDOWN:
642 #ifdef ARGUSDEBUG
643          ArgusDebug (3, "ArgusProcessQueue (%p, %d) Shuting Down with %d records\n", queue, status, queue->count);
644 #endif
645          while (queue->count) {
646             if ((obj = (struct ArgusFlowStruct *) ArgusPopBackQueue(queue, ARGUS_LOCK)) != NULL) {
647                if (!(obj->status & ARGUS_RECORD_WRITTEN))
648                   ArgusSendFlowRecord(model, obj, status);
649                ArgusDeleteObject (obj);
650             }
651          }
652          break;
653    }
654 
655 #ifdef ARGUSDEBUG
656    ArgusDebug (8, "ArgusProcessQueue (%p, %d) returning\n", queue, status);
657 #endif
658 }
659 
660 
661 int
ArgusCheckTimeout(struct ArgusModelerStruct * model,struct timeval * ts,struct timeval * timeout)662 ArgusCheckTimeout(struct ArgusModelerStruct *model, struct timeval *ts, struct timeval *timeout)
663 {
664    long long diff = 0, tdiff = 0;
665    int retn;
666 
667    if (timeout->tv_sec < 0)  // if timeout is set to less that zero, then we never timeout.
668       retn = 0;
669    else {
670       if ((timeout->tv_sec > 0) || (timeout->tv_usec > 0)) {
671          diff  = ArgusTimeDiff (&model->ArgusGlobalTime, ts);
672          tdiff = (timeout->tv_sec * 1000000LL + timeout->tv_usec);
673 
674          if (diff >= tdiff)
675             retn = 1;
676          else
677             retn = 0;
678       } else
679          retn = 1;
680    }
681 
682 #ifdef ARGUSDEBUG
683    ArgusDebug (11, "ArgusCheckTimeout (%p, %d.%06d, %d.%06d) diff %f returning %d\n", model, ts->tv_sec, ts->tv_usec,
684                       timeout->tv_sec, timeout->tv_usec, (diff / 1000000.0), retn);
685 #endif
686 
687    return (retn);
688 }
689 
690 
691 
692 void
ArgusDeleteObject(struct ArgusFlowStruct * obj)693 ArgusDeleteObject(struct ArgusFlowStruct *obj)
694 {
695    if (obj) {
696       struct ArgusHashTableHeader *htblhdr;
697       struct ArgusNetworkStruct *net = NULL;
698       struct ArgusQueueStruct *queue;
699 
700       if ((queue = obj->qhdr.queue) != NULL) {
701          if (ArgusRemoveFromQueue (queue, &obj->qhdr, ARGUS_LOCK)) {
702             obj->qhdr.queue = NULL;
703          } else
704             ArgusLog (LOG_ERR, "ArgusDeleteObject: race condition on queue %p\n", queue);
705       }
706 
707       if ((htblhdr = obj->htblhdr) != NULL)  {
708          ArgusRemoveHashEntry(htblhdr);
709          obj->htblhdr = NULL;
710       }
711 
712       if ((net = (struct ArgusNetworkStruct *) obj->dsrs[ARGUS_FRAG_INDEX]) != NULL) {
713          if (net->hdr.subtype == ARGUS_NETWORK_SUBTYPE_FRAG) {
714             struct ArgusFragObject *frag = &net->net_union.frag;
715             struct ArgusFragOffsetStruct *fragOffset = frag->offsets.nxt;
716 
717             while ((fragOffset = frag->offsets.nxt) != NULL) {
718                frag->offsets.nxt = fragOffset->nxt;
719                free(fragOffset);
720             }
721             net->hdr.type = 0;
722          }
723       }
724 
725       if (obj->dsrs[ARGUS_SRCUSERDATA_INDEX] != NULL) {
726          ArgusFree(obj->dsrs[ARGUS_SRCUSERDATA_INDEX]);
727          obj->dsrs[ARGUS_SRCUSERDATA_INDEX] = NULL;
728       }
729 
730       if (obj->dsrs[ARGUS_DSTUSERDATA_INDEX] != NULL) {
731          ArgusFree(obj->dsrs[ARGUS_DSTUSERDATA_INDEX]);
732          obj->dsrs[ARGUS_DSTUSERDATA_INDEX] = NULL;
733       }
734 
735       if (obj->frag.start != NULL) {
736          struct ArgusFlowStruct *frag;
737 
738          while ((frag = (void *) ArgusPopQueue(&obj->frag, ARGUS_LOCK))) {
739             ArgusSendFlowRecord(ArgusModel, frag, ARGUS_TIMEOUT);
740             ArgusDeleteObject(frag);
741          }
742       }
743 
744       ArgusFree(obj);
745       ArgusModel->ArgusTotalClosedFlows++;
746    }
747 
748 #ifdef ARGUSDEBUG
749    ArgusDebug (4, "ArgusDeleteObject (%p) returning\n", obj);
750 #endif
751 }
752 
753 
754 int
ArgusUpdateTime(struct ArgusModelerStruct * model)755 ArgusUpdateTime (struct ArgusModelerStruct *model)
756 {
757    long long ival = model->ival;
758    long long diff;
759    int retn = 0;
760 
761    if (model->ArgusUpdateTimer.tv_sec == 0)
762       model->ArgusUpdateTimer = model->ArgusGlobalTime;
763 
764    diff = ArgusTimeDiff(&model->ArgusGlobalTime, &model->ArgusUpdateTimer);
765 
766    if (diff >= 0) {
767       retn = 1;
768 
769       if (diff > ival)
770          model->ArgusUpdateTimer = model->ArgusGlobalTime;
771 
772       model->ArgusUpdateTimer.tv_sec  += model->ArgusUpdateInterval.tv_sec;
773       model->ArgusUpdateTimer.tv_usec += model->ArgusUpdateInterval.tv_usec;
774 
775       while (model->ArgusUpdateTimer.tv_usec >= 1000000) {
776          model->ArgusUpdateTimer.tv_sec++;
777          model->ArgusUpdateTimer.tv_usec -= 1000000;
778       }
779 
780    } else {
781 
782       if (ArgusSourceTask != NULL) {
783          if (!(ArgusSourceTask->ArgusReadingOffLine)) {
784             if (llabs(diff) > (ival * 2)) {
785 
786 // something is wrong, so try to figure out if ArgusGlobalTime needs to be adjusted.
787 // Must be kernel time bug, so try to reset the ArgusUpdateTimer, and declare
788 // that the timer has popped.  Redefine global timer if needed.
789 
790                unsigned long long tdiff;
791                struct timeval now;
792 
793                retn = 1;
794 
795                gettimeofday(&now, 0L);
796                tdiff =  ArgusAbsTimeDiff(&now, &model->ArgusGlobalTime);
797 
798                if (tdiff > (ival * 2))
799                   model->ArgusGlobalTime = now;
800 
801                model->ArgusUpdateTimer = model->ArgusGlobalTime;
802 
803                model->ArgusUpdateTimer.tv_sec  += model->ArgusUpdateInterval.tv_sec;
804                model->ArgusUpdateTimer.tv_usec += model->ArgusUpdateInterval.tv_usec;
805 
806                while (model->ArgusUpdateTimer.tv_usec >= 1000000) {
807                   model->ArgusUpdateTimer.tv_sec++;
808                   model->ArgusUpdateTimer.tv_usec -= 1000000;
809                }
810             }
811          }
812       }
813    }
814 
815 #ifdef ARGUSDEBUG
816    if (retn) {
817       ArgusDebug (8, "ArgusUpdateTime (%p) global time %d.%06d update %d.%06d returning %d\n",
818                    model, model->ArgusGlobalTime.tv_sec, model->ArgusGlobalTime.tv_usec,
819                    model->ArgusUpdateTimer.tv_sec, model->ArgusUpdateTimer.tv_usec, retn);
820    } else
821       ArgusDebug (8, "ArgusUpdateTime (%p) not time\n", model);
822 #endif
823 
824    return (retn);
825 }
826 
827 struct ArgusHashStats {
828    int n, max;
829 };
830 
831 struct ArgusHashTable *ArgusNewHashTable (size_t, int);
832 struct ArgusHashStats *ArgusHashTableStats = NULL;
833 int ArgusHashTableMax = 0;
834 void ArgusEmptyHashTable (struct ArgusHashTable *);
835 void ArgusDeleteHashTable (struct ArgusHashTable *);
836 
837 struct ArgusHashTable *
ArgusNewHashTable(size_t size,int status)838 ArgusNewHashTable (size_t size, int status)
839 {
840    struct ArgusHashTable *retn = NULL;
841 
842    if ((retn = (struct ArgusHashTable *) ArgusCalloc (1, sizeof(*retn))) == NULL)
843       ArgusLog (LOG_ERR, "ArgusNewHashTable: ArgusCalloc(1, %d) error %s\n", size, strerror(errno));
844 
845    if ((retn->array = (struct ArgusHashTableHeader **) ArgusCalloc (size,
846                                       sizeof (struct ArgusHashTableHeader *))) == NULL)
847       ArgusLog (LOG_ERR, "RaMergeQueue: ArgusCalloc error %s\n", strerror(errno));
848 
849    retn->size = size;
850 #if defined(ARGUS_HASH_DEBUG)
851    if ((retn->status = status) == ARGUSHASHTABLETRACK) {
852       if (ArgusHashTableStats == NULL) {
853          if ((ArgusHashTableStats = (struct ArgusHashStats *) ArgusCalloc (size, sizeof(struct ArgusHashStats))) == NULL)
854             ArgusLog (LOG_ERR, "ArgusHashTableStats: ArgusCalloc(%d, %d) error %s\n",
855                    size, sizeof(struct ArgusStatsObject), strerror(errno));
856       }
857    }
858 #endif
859 #if defined(ARGUS_THREADS)
860    pthread_mutex_init(&retn->lock, NULL);
861 #endif
862 
863 #ifdef ARGUSDEBUG
864    ArgusDebug (4, "ArgusNewHashTable (%d) returning %p\n", size, retn);
865 #endif
866 
867    return (retn);
868 }
869 
870 void
ArgusDeleteHashTable(struct ArgusHashTable * htbl)871 ArgusDeleteHashTable (struct ArgusHashTable *htbl)
872 {
873 
874    if (htbl != NULL) {
875       ArgusEmptyHashTable (htbl);
876 
877       if (htbl->array != NULL)
878          ArgusFree(htbl->array);
879 
880       ArgusFree(htbl);
881    }
882 
883 #ifdef ARGUSDEBUG
884    ArgusDebug (4, "ArgusDeleteHashTable (%p)\n", htbl);
885 #endif
886 }
887 
888 void
ArgusEmptyHashTable(struct ArgusHashTable * htbl)889 ArgusEmptyHashTable (struct ArgusHashTable *htbl)
890 {
891    struct ArgusHashTableHeader *htblhdr = NULL, *tmp;
892    int i, count = 0, bins = 0;
893 
894 #if defined(ARGUS_THREADS)
895    pthread_mutex_lock(&htbl->lock);
896 #endif
897    for (i = 0; i < htbl->size; i++) {
898       if ((htblhdr = htbl->array[i]) != NULL) {
899          htblhdr->prv->nxt = NULL;
900          while ((tmp = htblhdr) != NULL) {
901             htblhdr = htblhdr->nxt;
902             ArgusFree (tmp);
903             htbl->items--;
904             count++;
905          }
906          htbl->array[i] = NULL;
907          htbl->bins--;
908          bins++;
909       }
910    }
911 
912 
913 #if defined(ARGUS_THREADS)
914    pthread_mutex_unlock(&htbl->lock);
915 #endif
916 
917 #ifdef ARGUSDEBUG
918    ArgusDebug (6, "ArgusEmptyHashTable (%p) cleared %d bins %d items\n", htbl, bins, count);
919 #endif
920 }
921 
922 
923 int
ArgusCreateFlowKey(struct ArgusModelerStruct * model,struct ArgusSystemFlow * flow,struct ArgusHashStruct * hstruct)924 ArgusCreateFlowKey (struct ArgusModelerStruct *model, struct ArgusSystemFlow *flow, struct ArgusHashStruct *hstruct)
925 {
926    unsigned int *ptr = (unsigned int *)&flow->flow_un;
927    unsigned int *key = (unsigned int *) hstruct->key;
928    int retn = 0, i, len = flow->hdr.argus_dsrvl8.len - 1;
929 
930    memset (hstruct, 0, sizeof(*hstruct));
931 
932    if (len > 0) {
933       for (i = 0; i < len; i++)
934          *key++ = *ptr++;
935 
936       hstruct->len = len;
937 
938       if (model->ArgusFlowKey & ARGUS_FLOW_KEY_VLAN) {
939          *key++ = model->ArgusThisPacket8021QEncaps & 0x0FFF;
940          hstruct->len++;
941       }
942 
943       if (model->ArgusFlowKey & (ARGUS_FLOW_KEY_LOCAL_MPLS | ARGUS_FLOW_KEY_COMPLETE_MPLS)) {
944          *key++ = model->ArgusThisMplsLabel;
945          hstruct->len++;
946       }
947 
948       if (model->ArgusFlowKey & (ARGUS_FLOW_KEY_LAYER_2 | ARGUS_FLOW_KEY_LAYER_2_MATRIX)) {
949          struct ether_header *ep = model->ArgusThisEpHdr;
950          if (ep) {
951             int klen = (sizeof(*ep) + (sizeof(*key) - 1)) / sizeof(*key);
952             if (model->state & ARGUS_DIRECTION) {
953 #ifndef ETH_ALEN
954 #define ETH_ALEN   6
955 #endif
956                char *kptr = (char *) key;
957                bcopy ((char *)&ep->ether_shost, kptr, ETH_ALEN); kptr += ETH_ALEN;
958                bcopy ((char *)&ep->ether_dhost, kptr, ETH_ALEN); kptr += ETH_ALEN;
959                bcopy ((char *)&ep->ether_type,  kptr, sizeof(ep->ether_type));
960 
961             } else
962                bcopy (ep, key, sizeof(*ep));
963 
964             key += klen;
965             hstruct->len += klen;
966          }
967       }
968 
969       ptr = hstruct->key;
970 
971       for (i = 0; i < hstruct->len; i++)
972          hstruct->hash ^= *ptr++;
973 
974       hstruct->hash ^= hstruct->hash >> 16;
975       hstruct->hash ^= hstruct->hash >> 8;
976    }
977 
978    return (retn);
979 }
980 
981 
982 struct ArgusFlowStruct *
ArgusFindFlow(struct ArgusModelerStruct * model,struct ArgusHashStruct * hstruct)983 ArgusFindFlow (struct ArgusModelerStruct *model, struct ArgusHashStruct *hstruct)
984 {
985    struct ArgusFlowStruct *retn = NULL;
986    struct ArgusHashTableHeader *hashEntry = NULL, *target, *head;
987    struct ArgusHashTable *table = model->ArgusHashTable;
988 
989    if (table && hstruct) {
990       unsigned int hash = hstruct->hash;
991       unsigned int ind = (hash % (table->size - 1)), i;
992 
993       if ((target = table->array[ind]) != NULL) {
994          unsigned int *ptr3 = hstruct->key;
995          int len = hstruct->len;
996          head = target;
997 
998          do {
999             if ((target->hstruct.hash == hash) && (target->hstruct.len == hstruct->len)) {
1000                unsigned int *ptr1 = target->hstruct.key;
1001                unsigned int *ptr2 = ptr3;
1002 
1003                if (len > 0) {
1004                   for (i = 0; i < len; i++)
1005                      if (*ptr1++ != *ptr2++)
1006                         break;
1007                   if (i == len) {
1008                      hashEntry = target;
1009                      break;
1010                   }
1011 
1012                } else
1013                   hashEntry = target;
1014             }
1015 
1016             target = target->nxt;
1017 
1018          } while (target && (target != head) && (hashEntry == NULL));
1019 
1020          if (hashEntry != NULL) {
1021             if (hashEntry != head)
1022                table->array[ind] = hashEntry;
1023             retn = hashEntry->object;
1024          }
1025       }
1026    }
1027 
1028 #ifdef ARGUSDEBUG
1029    ArgusDebug (8, "ArgusFindFlow () returning %p\n", retn);
1030 #endif
1031 
1032    return (retn);
1033 }
1034 
1035 #define ARGUS_HASH_DEBUG	1
1036 
1037 struct ArgusHashTableHeader *
ArgusAddHashEntry(struct ArgusHashTable * table,struct ArgusFlowStruct * flow,struct ArgusHashStruct * hstruct)1038 ArgusAddHashEntry (struct ArgusHashTable *table, struct ArgusFlowStruct *flow, struct ArgusHashStruct *hstruct)
1039 {
1040    struct ArgusHashTableHeader *retn = NULL, *start = NULL;
1041 
1042    if (table != NULL) {
1043       unsigned int hash = hstruct->hash;
1044       int ind;
1045 
1046       retn = &flow->htblbuf;
1047       memcpy(&retn->hstruct, hstruct, sizeof(*hstruct));
1048       retn->object = flow;
1049 
1050       ind = (hash % (table->size - 1));
1051 
1052       if ((start = table->array[ind]) != NULL) {
1053          retn->nxt = start;
1054          retn->prv = start->prv;
1055          retn->prv->nxt = retn;
1056          retn->nxt->prv = retn;
1057       } else {
1058          retn->prv = retn;
1059          retn->nxt = retn;
1060          table->bins++;
1061       }
1062       table->items++;
1063 
1064       table->array[ind] = retn;
1065       retn->htbl = table;
1066 #if defined(ARGUS_HASH_DEBUG)
1067       if (table->status & ARGUSHASHTABLETRACK) {
1068          ArgusHashTableStats[ind].n++;
1069          if (ArgusHashTableStats[ind].max < ArgusHashTableStats[ind].n)
1070             ArgusHashTableStats[ind].max = ArgusHashTableStats[ind].n;
1071 
1072          if (ArgusHashTableMax < ArgusHashTableStats[ind].n)
1073             ArgusHashTableMax = ArgusHashTableStats[ind].n;
1074       }
1075 #endif
1076    }
1077 
1078 #ifdef ARGUSDEBUG
1079    ArgusDebug (6, "ArgusAddHashEntry (%p) returning %p\n", flow, retn);
1080 #endif
1081 
1082    return (retn);
1083 }
1084 
1085 
1086 void
ArgusRemoveHashEntry(struct ArgusHashTableHeader * htblhdr)1087 ArgusRemoveHashEntry (struct ArgusHashTableHeader *htblhdr)
1088 {
1089    if (htblhdr != NULL) {
1090       unsigned int hash = htblhdr->hstruct.hash;
1091       struct ArgusHashTable *table = htblhdr->htbl;
1092 
1093       if (table != NULL) {
1094          int ind = (hash % (table->size - 1));
1095 
1096          htblhdr->prv->nxt = htblhdr->nxt;
1097          htblhdr->nxt->prv = htblhdr->prv;
1098 
1099          if (htblhdr == table->array[ind]) {
1100             if (htblhdr == htblhdr->nxt) {
1101                table->array[ind] = NULL;
1102                table->bins--;
1103             } else
1104                table->array[ind] = htblhdr->nxt;
1105          }
1106 
1107          table->items--;
1108 
1109 #if defined(ARGUS_HASH_DEBUG)
1110          if (table->status & ARGUSHASHTABLETRACK)
1111             ArgusHashTableStats[ind].n--;
1112 #endif
1113       }
1114    }
1115 
1116 #ifdef ARGUSDEBUG
1117    ArgusDebug (6, "ArgusRemoveHashEntry (%p) returning\n", htblhdr);
1118 #endif
1119 }
1120 
1121 
1122 void ArgusZeroRecord (struct ArgusFlowStruct *);
1123 
1124 void
ArgusZeroRecord(struct ArgusFlowStruct * flow)1125 ArgusZeroRecord (struct ArgusFlowStruct *flow)
1126 {
1127    int i;
1128 
1129    flow->status &= ~ARGUS_RECORD_WRITTEN;
1130    flow->status &= ~0xF0;
1131 
1132    for (i = 0; i < ARGUSMAXDSRTYPE; i++) {
1133       if (flow->dsrs[i] != NULL) {
1134          switch (i) {
1135             default:
1136                flow->dsrs[i] = NULL;
1137                break;
1138 
1139             case ARGUS_FLOW_INDEX: {
1140                struct ArgusFlow *tflow = (struct ArgusFlow *)flow->dsrs[i];
1141                tflow->hdr.argus_dsrvl8.qual &= ~ARGUS_FRAGMENT;
1142                break;
1143             }
1144 
1145             case ARGUS_TRANSPORT_INDEX:
1146             case ARGUS_MAC_INDEX:
1147                break;
1148 
1149             case ARGUS_JITTER_INDEX: {
1150                struct ArgusJitterStruct *jit = (void *)flow->dsrs[i];
1151                bzero ((char *)&jit->act, sizeof(struct ArgusJitterObject));
1152                bzero ((char *)&jit->idle, sizeof(struct ArgusJitterObject));
1153                jit->act.src.minval  = -1.0;
1154                jit->idle.src.minval = -1.0;
1155                jit->act.dst.minval  = -1.0;
1156                jit->idle.dst.minval = -1.0;
1157                break;
1158             }
1159 
1160             case ARGUS_IPATTR_INDEX: {
1161                struct ArgusIPAttrStruct *attr = (void *)flow->dsrs[i];
1162                attr->hdr.argus_dsrvl8.qual &= ~(ARGUS_IPATTR_SRC_FRAGMENTS | ARGUS_IPATTR_DST_FRAGMENTS);
1163                attr->src.status = 0; attr->src.options = 0;
1164                attr->dst.status = 0; attr->dst.options = 0;
1165                break;
1166             }
1167 
1168             case ARGUS_TIME_INDEX: {
1169                struct ArgusTimeObject *tim = (void *)flow->dsrs[i];
1170                bzero(&tim->src, sizeof(*tim) - 4);
1171                break;
1172             }
1173 
1174             case ARGUS_METRIC_INDEX: {
1175                struct ArgusMetricStruct *metric = (void *) flow->dsrs[i];
1176                bzero((&metric->hdr + 1), sizeof(*metric) - 4);
1177                break;
1178             }
1179 
1180             case ARGUS_NETWORK_INDEX: {
1181                struct ArgusNetworkStruct *net = NULL;
1182                if ((net = (struct ArgusNetworkStruct *) flow->dsrs[ARGUS_NETWORK_INDEX]) != NULL) {
1183 
1184                   switch (net->hdr.type) {
1185                      case ARGUS_NETWORK_DSR: {
1186                         switch (net->hdr.subtype) {
1187                            case ARGUS_NETWORK_SUBTYPE_FRAG: {
1188                               struct ArgusFragObject *frag = &net->net_union.frag;
1189                               struct ArgusFragOffsetStruct *fragOffset = frag->offsets.nxt;
1190 
1191                               while ((fragOffset = frag->offsets.nxt) != NULL) {
1192                                  frag->offsets.nxt = fragOffset->nxt;
1193                                  free(fragOffset);
1194                               }
1195                               bzero((char *)frag, sizeof(struct ArgusFragObject));
1196                               break;
1197                            }
1198 
1199                            case ARGUS_TCP_INIT:
1200                            case ARGUS_TCP_STATUS:
1201                            case ARGUS_TCP_PERF: {
1202                               struct ArgusTCPObject *tcp = &net->net_union.tcp;
1203                               tcp->src.status &= ~(ARGUS_RESET|ARGUS_PKTS_RETRANS|ARGUS_WINDOW_SHUT|ARGUS_OUTOFORDER|ARGUS_ECN_CONGESTED);
1204                               tcp->dst.status &= ~(ARGUS_RESET|ARGUS_PKTS_RETRANS|ARGUS_WINDOW_SHUT|ARGUS_OUTOFORDER|ARGUS_ECN_CONGESTED);
1205                               tcp->src.retrans  = 0;
1206                               tcp->dst.retrans  = 0;
1207                               tcp->src.flags    = 0;
1208                               tcp->dst.flags    = 0;
1209                               tcp->src.bytes    = 0;
1210                               tcp->dst.bytes    = 0;
1211                               tcp->src.winbytes = 0;
1212                               tcp->dst.winbytes = 0;
1213                               tcp->src.ackbytes = 0;
1214                               tcp->dst.ackbytes = 0;
1215                               tcp->src.seqbase  = tcp->src.seq;
1216                               tcp->dst.seqbase  = tcp->dst.seq;
1217                               break;
1218                            }
1219 
1220                            case ARGUS_RTP_FLOW: {
1221                               struct ArgusRTPObject *rtp = &net->net_union.rtp;
1222                               rtp->sdrop = 0;
1223                               rtp->ddrop = 0;
1224                               break;
1225                            }
1226 
1227                            case ARGUS_ESP_DSR: {
1228                               struct ArgusESPObject *esp = &net->net_union.esp;
1229                               esp->status  = 0;
1230                               esp->lostseq = 0;
1231                               break;
1232                            }
1233                         }
1234                         break;
1235                      }
1236                   }
1237 
1238                   net->hdr.argus_dsrvl8.qual = 0;
1239                }
1240                break;
1241             }
1242 
1243             case ARGUS_SRCUSERDATA_INDEX:
1244             case ARGUS_DSTUSERDATA_INDEX: {
1245                struct ArgusDataStruct *user = (struct ArgusDataStruct *) flow->dsrs[i];
1246                user->count = 0;
1247                memset (user->array, 0, user->size);
1248                break;
1249             }
1250          }
1251       }
1252    }
1253 
1254    memset(&flow->stime.act,  0, sizeof(flow->stime.act));
1255    memset(&flow->stime.idle, 0, sizeof(flow->stime.idle));
1256    memset(&flow->dtime.act,  0, sizeof(flow->dtime.act));
1257    memset(&flow->dtime.idle, 0, sizeof(flow->dtime.idle));
1258 
1259    flow->stime.act.minval  = 0xffffffff;
1260    flow->stime.idle.minval = 0xffffffff;
1261    flow->dtime.act.minval  = 0xffffffff;
1262    flow->dtime.idle.minval = 0xffffffff;
1263 
1264    flow->sipid = 0;
1265    flow->dipid = 0;
1266    flow->skey.n_strokes = 0;
1267 
1268 #ifdef ARGUSDEBUG
1269    ArgusDebug (8, "ArgusZeroRecord (%p) returning\n", flow);
1270 #endif
1271 }
1272 
1273 /*
1274 struct ArgusSocketStruct {
1275    struct ArgusListStruct *ArgusSocketList;
1276    int fd, status, cnt, expectedSize, errornum;
1277    int ArgusLastRecord, ArgusReadState;
1278    struct timeval lastwrite;
1279    struct ArgusRecordStruct *rec;
1280    int length, writen;
1281    struct sockaddr sock;
1282    char *filename;
1283    void *obj;
1284    unsigned char *ptr, buf[ARGUS_MAXRECORD];
1285 };
1286 */
1287 
1288 struct ArgusSocketStruct *
ArgusNewSocket(int fd)1289 ArgusNewSocket (int fd)
1290 {
1291    struct ArgusSocketStruct *retn = NULL;
1292    int flags;
1293 
1294    if ((retn = ((struct ArgusSocketStruct *) ArgusCalloc (1, sizeof (struct ArgusSocketStruct)))) != NULL) {
1295       if ((retn->ArgusSocketList = ArgusNewList()) != NULL) {
1296          retn->fd = fd;
1297          flags = fcntl (fd, F_GETFL, 0);
1298          flags |= O_NONBLOCK;
1299          fcntl (fd, F_SETFL, flags);
1300       } else
1301          ArgusLog(LOG_ERR, "ArgusNewSocket: ArgusNewList failed %s", strerror(errno));
1302    } else
1303       ArgusLog(LOG_ERR, "ArgusNewSocket: ArgusCalloc failed %s", strerror(errno));
1304 
1305 #ifdef ARGUSDEBUG
1306    ArgusDebug (2, "ArgusNewSocket (%d) returning %p\n", fd, retn);
1307 #endif
1308 
1309    return (retn);
1310 }
1311 
1312 void
ArgusDeleteSocket(struct ArgusOutputStruct * output,struct ArgusClientData * client)1313 ArgusDeleteSocket (struct ArgusOutputStruct *output, struct ArgusClientData *client)
1314 {
1315    struct ArgusSocketStruct *asock = client->sock;
1316 
1317    if (asock != NULL) {
1318       struct ArgusListStruct *list = asock->ArgusSocketList;
1319 
1320       while (!(ArgusListEmpty (list)))
1321          if (ArgusWriteOutSocket(output, client) < 0)
1322             break;
1323 
1324 #ifdef ARGUSDEBUG
1325       if (!(ArgusListEmpty (list)))
1326          ArgusDebug(2, "ArgusDeleteSocket: list not empty");
1327 #endif
1328       ArgusDeleteList(asock->ArgusSocketList, ARGUS_OUTPUT_LIST);
1329 
1330       close(asock->fd);
1331       asock->fd = -1;
1332 
1333       if (asock->filename) {
1334          free(asock->filename);
1335          asock->filename = NULL;
1336       }
1337 
1338       ArgusFree (asock);
1339       client->sock = NULL;
1340       client->fd = -1;
1341    }
1342 
1343 #ifdef ARGUSDEBUG
1344    ArgusDebug (2, "ArgusDeleteSocket (%p) returning\n", asock);
1345 #endif
1346 }
1347 
1348 
1349 void
ArgusSetChroot(char * dir)1350 ArgusSetChroot(char *dir)
1351 {
1352    if (chdir(dir) < 0)
1353       ArgusLog(LOG_ERR, "ArgusSetChroot: failed to chdir to \"%s\": %s", dir, strerror(errno));
1354 
1355    if (chroot(dir) < 0)
1356       ArgusLog(LOG_ERR, "ArgusSetChroot: failed to chroot to \"%s\": %s", dir, strerror(errno));
1357 
1358    if (chdir("/") < 0)
1359       ArgusLog(LOG_ERR, "ArgusSetChroot: failed to chdir to \"/\" after chroot: %s", dir, strerror(errno));
1360 
1361 #ifdef ARGUSDEBUG
1362    ArgusDebug (2, "ArgusSetChroot (%s) returning\n", dir);
1363 #endif
1364 }
1365 
1366 
1367 #include <sys/stat.h>
1368 #include <fcntl.h>
1369 
1370 #define ARGUS_MAXERROR		200000
1371 #define ARGUS_MAXWRITENUM	10000
1372 
1373 int ArgusMaxListLength = 100000;
1374 int ArgusCloseFile = 0;
1375 
1376 
1377 extern struct ArgusRecord *ArgusGenerateInitialMar (struct ArgusOutputStruct *);
1378 
1379 int
ArgusWriteSocket(struct ArgusOutputStruct * output,struct ArgusClientData * client,struct ArgusRecordStruct * rec)1380 ArgusWriteSocket (struct ArgusOutputStruct *output, struct ArgusClientData *client, struct ArgusRecordStruct *rec)
1381 {
1382    struct ArgusSocketStruct *asock = client->sock;
1383    struct ArgusListStruct *list = asock->ArgusSocketList;
1384    struct stat statbuf;
1385    int retn = 0, ocnt;
1386 
1387 #if defined(HAVE_SOLARIS)
1388    struct statvfs statfsbuf;
1389 #else
1390    struct statfs statfsbuf;
1391 #endif
1392 
1393       if (ArgusListEmpty (list) && (asock->rec == NULL)) {
1394 #ifdef ARGUSDEBUG
1395          if (asock->writen || asock->length)
1396             ArgusDebug (6, "ArgusWriteSocket: asock stats error %d %d\n", asock->writen, asock->length);
1397 #endif
1398          if (client->host == NULL) {
1399          if (!(output->ArgusWriteStdOut) && (asock->filename)) {
1400             if (asock->lastwrite.tv_sec < output->ArgusModel->ArgusGlobalTime.tv_sec) {
1401                if (((stat (asock->filename, &statbuf)) < 0) || (ArgusCloseFile)) {
1402                   if (asock->fd != -1)
1403                      close(asock->fd);
1404                   if ((asock->fd = open (asock->filename, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK, 0x1a4)) < 0)
1405                      ArgusLog (LOG_ERR, "ArgusWriteSocket: open(%s, flags, 0x1a4) failed %s\n",
1406                         asock->filename, strerror(errno));
1407 #ifdef ARGUSDEBUG
1408                      ArgusDebug (2, "ArgusWriteSocket: created outfile %s\n", asock->filename);
1409 #endif
1410                }
1411 
1412 #if defined(HAVE_SOLARIS)
1413                retn = statvfs (asock->filename, &statfsbuf);
1414 #else
1415                retn = statfs (asock->filename, &statfsbuf);
1416 #endif
1417 
1418                if (retn == 0) {
1419                   if (statfsbuf.f_bfree > 100) {
1420                      if ((stat (asock->filename, &statbuf)) == 0) {
1421                         if (statbuf.st_size == 0) {
1422                            if (output->ArgusInitMar != NULL)
1423                               ArgusFree(output->ArgusInitMar);
1424                            output->ArgusInitMar = ArgusGenerateInitialMar(output);
1425                            ocnt = ntohs(output->ArgusInitMar->hdr.len) * 4;
1426 #ifdef ARGUSDEBUG
1427                            ArgusDebug (6, "ArgusWriteSocket: write initial mar (%d, %p, %d)\n",
1428                               asock->fd, output->ArgusInitMar, ocnt);
1429 #endif
1430                            if (((retn = write (asock->fd, output->ArgusInitMar, ocnt))) < ocnt)
1431                               ArgusLog (LOG_ERR, "ArgusWriteSocket: write %s failed %s\n", asock->filename, strerror(errno));
1432                            ArgusFree(output->ArgusInitMar);
1433                            output->ArgusInitMar = NULL;
1434                         }
1435                      }
1436 
1437                   } else {
1438                      close(asock->fd);
1439                      asock->fd = -1;
1440                   }
1441                }
1442                asock->lastwrite = output->ArgusModel->ArgusGlobalTime;
1443             }
1444          }
1445          }
1446 
1447          if (asock->fd != -1) {
1448             if (ArgusGenerateRecord (output->ArgusModel, rec, 0, (struct ArgusRecord *)&asock->buf)) {
1449                int cnt = ((struct ArgusRecord *)&asock->buf)->hdr.len * 4;
1450 #if defined(_LITTLE_ENDIAN)
1451                ArgusHtoN((struct ArgusRecord *)&asock->buf);
1452 #endif
1453 #ifdef ARGUS_SASL
1454                if (client->sasl_conn) {
1455                   unsigned int outputlen = 0;
1456                   const char *output =  NULL;
1457                   const int *ssfp;
1458                   int result;
1459 
1460                   if ((result = sasl_getprop(client->sasl_conn, SASL_SSF, (const void **) &ssfp)) != SASL_OK)
1461                      ArgusLog (LOG_ERR, "sasl_getprop: error %s\n", sasl_errdetail(client->sasl_conn));
1462 
1463                   if (ssfp && (*ssfp > 0)) {
1464 #ifdef ARGUSDEBUG
1465                      ArgusDebug (6, "ArgusHandleClientData: sasl_encode(%p, %p, %d, %p, %p)\n",
1466                                          client->sasl_conn, rec, cnt, &output, &outputlen);
1467 #endif
1468                      if ((retn = sasl_encode(client->sasl_conn, (const char *) asock->buf, (unsigned int) cnt,
1469                                                                           &output, &outputlen)) == SASL_OK) {
1470 #ifdef ARGUSDEBUG
1471                         ArgusDebug (6, "ArgusHandleClientData: sasl_encode returned %d bytes\n", outputlen);
1472 #endif
1473                         if (outputlen < ARGUS_MAXRECORD) {
1474                            bcopy(output, asock->buf, outputlen);
1475                            cnt = outputlen;
1476                         } else
1477                            ArgusLog (LOG_ERR, "sasl_encode: returned too many bytes %d\n", outputlen);
1478 
1479                      } else
1480                         ArgusLog (LOG_ERR, "sasl_encode: failed returned %d\n", retn);
1481                   }
1482                }
1483 #endif
1484 
1485 #ifdef ARGUSDEBUG
1486                ArgusDebug (4, "ArgusWriteSocket: write record (%d, %p, %d)\n", asock->fd, &asock->buf, cnt);
1487 #endif
1488                if (client->host != NULL) {
1489                   retn = sendto (asock->fd, &asock->buf, cnt, 0, client->host->ai_addr, client->host->ai_addrlen);
1490 #ifdef ARGUSDEBUG
1491                   ArgusDebug (6, "ArgusWriteSocket: sendto (%d, %p, %d, ...) %d\n", asock->fd, &asock->buf, cnt, retn);
1492 #endif
1493                } else {
1494                   retn = write (asock->fd, &asock->buf, cnt);
1495 #ifdef ARGUSDEBUG
1496                   ArgusDebug (6, "ArgusWriteSocket: write (%d, %p, %d, ...) %d\n", asock->fd, &asock->buf, cnt, retn);
1497 #endif
1498                }
1499                if (retn >= 0) {
1500                   asock->status |= ARGUS_WAS_FUNCTIONAL;
1501                   asock->errornum = 0;
1502                   if (retn != cnt) {
1503 #ifdef ARGUSDEBUG
1504                      ArgusDebug (6, "ArgusWriteSocket: write returned %d, scheduled record\n", retn);
1505 #endif
1506                      asock->writen = retn;
1507                      asock->length = cnt;
1508                      asock->rec = ArgusCopyRecordStruct(rec);
1509                   } else {
1510                      asock->writen = 0;
1511                      asock->length = 0;
1512 #ifdef ARGUSDEBUG
1513                      ArgusDebug (6, "ArgusWriteSocket: write successful %d\n", retn);
1514 #endif
1515                   }
1516 
1517                } else {
1518 #ifdef ARGUSDEBUG
1519                   ArgusDebug (6, "ArgusWriteSocket: write returned %d, errno %d\n", retn, errno);
1520 #endif
1521                   asock->writen = 0;
1522                   asock->length = cnt;
1523                   asock->rec = ArgusCopyRecordStruct(rec);
1524 
1525                   switch (errno) {
1526                      case ENOSPC:
1527                         if (asock->filename != NULL) {
1528                            close(asock->fd);
1529                            asock->fd = -1;
1530                            asock->rec = NULL;
1531                            asock->writen = 0;
1532                            asock->length = 0;
1533                            ArgusFreeListRecord(rec);
1534                            while ((rec = (struct ArgusRecordStruct *) ArgusPopFrontList(list, ARGUS_LOCK)) != NULL)
1535                               ArgusFreeListRecord(rec);
1536                         }
1537                         break;
1538 
1539                      case EAGAIN:
1540                      case EINTR:
1541                         retn = 0;
1542                         break;
1543 
1544                      case EPIPE: {
1545                         if (!(asock->status & ARGUS_WAS_FUNCTIONAL)) {
1546                            retn = 0;
1547                         }
1548                         break;
1549                      }
1550 
1551                      default:
1552                         break;
1553                   }
1554                }
1555 
1556             } else {
1557 #ifdef ARGUSDEBUG
1558                ArgusDebug (6, "ArgusWriteSocket: ArgusGenerateRecord returned zero\n");
1559 #endif
1560             }
1561          }
1562 
1563       } else {
1564          if (list->count >= ArgusMaxListLength) {
1565             if (ArgusWriteOutSocket(output, client) < 0) {
1566 #if defined(ARGUS_THREADS)
1567                pthread_mutex_lock(&list->lock);
1568 #endif
1569                if (list->count >= ArgusMaxListLength) {
1570                   struct ArgusRecordStruct *trec;
1571                   int i;
1572 #define ARGUS_MAX_TOSS_RECORD	64
1573                   ArgusLog (LOG_WARNING, "ArgusWriteSocket: ArgusWriteOutSocket tossing records\n");
1574 
1575                   for (i = 0; i < ARGUS_MAX_TOSS_RECORD; i++)
1576                      if ((trec = (struct ArgusRecordStruct *) ArgusPopFrontList(list, ARGUS_NOLOCK)) != NULL)
1577                         ArgusFreeListRecord(trec);
1578                }
1579 #if defined(ARGUS_THREADS)
1580                pthread_mutex_unlock(&list->lock);
1581 #endif
1582             }
1583          }
1584 
1585          if (asock->rec == NULL)
1586             asock->rec = (struct ArgusRecordStruct *) ArgusPopFrontList(list, ARGUS_LOCK);
1587 
1588 #ifdef ARGUSDEBUG
1589          ArgusDebug (6, "ArgusWriteSocket (%p, %p, %p) schedule record\n", output, asock, rec);
1590 #endif
1591          ArgusPushBackList (list, (struct ArgusListRecord *) ArgusCopyRecordStruct(rec), ARGUS_LOCK);
1592          retn = 0;
1593       }
1594 
1595 #ifdef ARGUSDEBUG
1596       ArgusDebug (6, "ArgusWriteSocket (%p, %p, %p) returning %d\n", output, asock, rec, retn);
1597 #endif
1598 
1599    return (retn);
1600 }
1601 
1602 
1603 
1604 #define ARGUS_LISTREPORTLEN	50000
1605 #define ARGUS_LISTREPORTTIME	30
1606 
1607 int
ArgusWriteOutSocket(struct ArgusOutputStruct * output,struct ArgusClientData * client)1608 ArgusWriteOutSocket (struct ArgusOutputStruct *output, struct ArgusClientData *client)
1609 {
1610    struct ArgusSocketStruct *asock = client->sock;
1611    struct ArgusListStruct *list = NULL;
1612    struct ArgusRecordStruct *rec = NULL;
1613    int retn = 0, count = 1, len, ocnt;
1614    struct stat statbuf;
1615    unsigned char *ptr;
1616 
1617    if ((list = asock->ArgusSocketList) != NULL) {
1618       if ((count = ArgusGetListCount(list)) > 0) {
1619          if (count > ARGUS_MAXWRITENUM)
1620             count = ARGUS_MAXWRITENUM;
1621 
1622          if (count == 1)
1623             count = 2;
1624 
1625 #if defined(ARGUS_THREADS)
1626          pthread_mutex_lock(&list->lock);
1627 #endif
1628          while ((asock->fd != -1 ) && count--) {
1629             if ((rec = asock->rec) != NULL) {
1630                ptr = (unsigned char *)&asock->buf;
1631                if (!(asock->writen)) {
1632                   if (!(output->ArgusWriteStdOut) && (asock->filename)) {
1633                      if (asock->lastwrite.tv_sec < output->ArgusModel->ArgusGlobalTime.tv_sec) {
1634                         if (((stat (asock->filename, &statbuf)) < 0) || (ArgusCloseFile)) {
1635                            close(asock->fd);
1636                            if ((asock->fd = open (asock->filename, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK, 0x1a4)) < 0)
1637                               ArgusLog (LOG_ERR, "ArgusWriteSocket: open(%s, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK, 0x1a4) failed %s\n",
1638                                          asock->filename, strerror(errno));
1639 #ifdef ARGUSDEBUG
1640                            ArgusDebug (2, "ArgusWriteOutSocket: created outfile %s\n", asock->filename);
1641 #endif
1642                         }
1643 
1644                         if ((stat (asock->filename, &statbuf)) == 0) {
1645                            if (statbuf.st_size == 0) {
1646                               if (output->ArgusInitMar != NULL)
1647                                  ArgusFree(output->ArgusInitMar);
1648                               output->ArgusInitMar = ArgusGenerateInitialMar(output);
1649                               ocnt = sizeof(struct ArgusRecord);
1650                               if (((retn = write (asock->fd, output->ArgusInitMar, ocnt))) < ocnt)
1651                                  ArgusLog (LOG_ERR, "ArgusWriteSocket: write %s failed %s\n", asock->filename, strerror(errno));
1652                               ArgusFree(output->ArgusInitMar);
1653                               output->ArgusInitMar = NULL;
1654 
1655                            }
1656                         }
1657                         asock->lastwrite = output->ArgusModel->ArgusGlobalTime;
1658                      }
1659                   }
1660                }
1661 
1662                if ((asock->writen < asock->length) && ( asock->writen >= 0)) {
1663                   len = asock->length - asock->writen;
1664 
1665                   if (client->host != NULL) {
1666                      retn = sendto (asock->fd, (unsigned char *)&ptr[asock->writen], len, 0, client->host->ai_addr, client->host->ai_addrlen);
1667 #ifdef ARGUSDEBUG
1668                      ArgusDebug (3, "ArgusWriteSocket: sendto (%d, %p, %d, ...) %d\n", asock->fd, &asock->buf, len, retn);
1669 #endif
1670                   } else {
1671                      retn = write(asock->fd, (unsigned char *)&ptr[asock->writen], len);
1672 #ifdef ARGUSDEBUG
1673                      ArgusDebug (3, "ArgusWriteSocket: write (%d, %p, %d, ...) %d\n", asock->fd, &asock->buf, len, retn);
1674 #endif
1675                   }
1676 
1677                   if (retn >= 0) {
1678                      asock->errornum = 0;
1679                      asock->writen += retn;
1680 
1681                   } else {
1682                      switch (errno) {
1683                         case ENOSPC: {
1684                            if (asock->filename != NULL) {
1685                               close(asock->fd);
1686                               asock->fd = -1;
1687                               asock->rec = NULL;
1688                               asock->writen = 0;
1689                               asock->length = 0;
1690                               ArgusFreeListRecord(rec);
1691                               while ((rec = (struct ArgusRecordStruct *) ArgusPopFrontList(list, ARGUS_NOLOCK)) != NULL)
1692                                  ArgusFreeListRecord(rec);
1693                            }
1694                            break;
1695                         }
1696 
1697                         case EAGAIN:
1698                         case EINTR: {
1699                            if (!(output->ArgusWriteStdOut) && (asock->filename == NULL)) {
1700                               if (asock->errornum++ < ARGUS_MAXERROR) {
1701                                  retn = 0;
1702                               } else {
1703                               }
1704 
1705                            } else {
1706                               retn = 0;
1707                            }
1708                            break;
1709                         }
1710 
1711                         case EPIPE:
1712                            break;
1713 
1714                         default:
1715                            if (asock->errornum++ == 0)
1716                               ArgusLog (LOG_WARNING, "ArgusWriteOutSocket: write() %s\n", strerror(errno));
1717                            break;
1718                      }
1719                   }
1720                }
1721 
1722                if (asock->writen >= asock->length) {
1723                   gettimeofday(&list->outputTime, 0L);
1724                   ArgusFreeListRecord(rec);
1725 
1726 #ifdef ARGUSDEBUG
1727                   ArgusDebug (6, "ArgusWriteOutSocket: rec %p complete, %d count\n", rec, count);
1728 #endif
1729                   asock->rec = NULL;
1730                   asock->writen = 0;
1731                   asock->length = 0;
1732 
1733                   if ((rec = (struct ArgusRecordStruct *) ArgusPopFrontList(list, ARGUS_NOLOCK)) != NULL) {
1734                      if (ArgusGenerateRecord (output->ArgusModel, rec, 0, (struct ArgusRecord *)&asock->buf)) {
1735                         int cnt = ((struct ArgusRecord *)&asock->buf)->hdr.len * 4;
1736 #if defined(_LITTLE_ENDIAN)
1737                         ArgusHtoN((struct ArgusRecord *)&asock->buf);
1738 #endif
1739 #ifdef ARGUS_SASL
1740                         if (client->sasl_conn) {
1741                            unsigned int outputlen = 0;
1742                            const char *output =  NULL;
1743 #ifdef ARGUSDEBUG
1744                            ArgusDebug (3, "ArgusHandleClientData: sasl_encode(%p, %p, %d, %p, %p)\n",
1745                                                                    client->sasl_conn, rec, cnt, &output, &outputlen);
1746 #endif
1747                            if ((retn = sasl_encode(client->sasl_conn, (const char *) asock->buf, (unsigned int) cnt,
1748                                                       &output, &outputlen)) == SASL_OK) {
1749 #ifdef ARGUSDEBUG
1750                               ArgusDebug (3, "ArgusWriteOutSocket: sasl_encode returned %d bytes\n", outputlen);
1751 #endif
1752                               if (outputlen < ARGUS_MAXRECORD) {
1753                                  bcopy(output, asock->buf, outputlen);
1754                                  cnt = outputlen;
1755 
1756                               } else
1757                                  ArgusLog (LOG_ERR, "sasl_encode: returned too many bytes %d\n", outputlen);
1758 
1759                            } else
1760                               ArgusLog (LOG_ERR, "sasl_encode: failed returned %d\n", retn);
1761                         }
1762 #endif
1763                         asock->writen = 0;
1764                         asock->length = cnt;
1765                         asock->rec = rec;
1766 #ifdef ARGUSDEBUG
1767                         ArgusDebug (6, "ArgusWriteOutSocket: posted record %p", rec);
1768 #endif
1769 
1770                      } else {
1771 #ifdef ARGUSDEBUG
1772                         ArgusDebug (6, "ArgusWriteOutSocket: ArgusGenerateRecord error! deleting record");
1773 #endif
1774                         ArgusFreeListRecord(rec);
1775                      }
1776                   } else {
1777 #ifdef ARGUSDEBUG
1778                      ArgusDebug (3, "ArgusWriteOutSocket: list %p is now empty", list);
1779 #endif
1780                   }
1781 
1782                } else {
1783 #ifdef ARGUSDEBUG
1784                   ArgusDebug (6, "ArgusWriteOutSocket: still work to be done for %p, len %d writen %d", rec, asock->length, asock->writen);
1785 #endif
1786                   break;
1787                }
1788 
1789             } else {
1790 #ifdef ARGUSDEBUG
1791                ArgusDebug (6, "ArgusWriteOutSocket: nothing to be done for %p, len %d writen %d", rec, asock->length, asock->writen);
1792 #endif
1793             }
1794          }
1795 
1796 #if defined(ARGUS_THREADS)
1797          pthread_mutex_unlock(&list->lock);
1798 #endif
1799 
1800 #ifdef ARGUSDEBUG
1801          ArgusDebug (9, "ArgusWriteOutSocket(%p): queue empty\n", asock);
1802 #endif
1803 
1804          if (asock->errornum >= ARGUS_MAXERROR) {
1805             ArgusLog (LOG_WARNING, "ArgusWriteOutSocket(%p) maximum errors exceeded %d\n", asock, asock->errornum);
1806             retn = -1;
1807          }
1808 
1809          if ((count = ArgusGetListCount(list)) > ArgusMaxListLength) {
1810             ArgusLog (LOG_WARNING, "ArgusWriteOutSocket(%p) max queue exceeded %d\n", asock, count);
1811             retn = -1;
1812          }
1813 
1814 #ifdef ARGUSDEBUG
1815          if (list) {
1816             ArgusDebug (6, "ArgusWriteOutSocket (%p) %d records waiting. returning %d\n", asock, count, retn);
1817          } else {
1818             ArgusDebug (6, "ArgusWriteOutSocket (%p) no list.  returning %d\n", asock, count, retn);
1819          }
1820 #endif
1821       }
1822 
1823    } else {
1824 #ifdef ARGUSDEBUG
1825       ArgusDebug (6, "ArgusWriteOutSocket (%p, %p) no list returning %d\n", output, client, retn);
1826 #endif
1827    }
1828 
1829 #ifdef ARGUSDEBUG
1830    ArgusDebug (6, "ArgusWriteOutSocket (%p, %p) returning %d\n", output, client, retn);
1831 #endif
1832 
1833    return retn;
1834 }
1835 
1836 
1837 #if !defined(ArgusAddrtoName)
1838 #define ArgusAddrtoName
1839 #endif
1840 
1841 #include <sys/socket.h>
1842 #include <signal.h>
1843 #include <netdb.h>
1844 
1845 #include <argus_namedb.h>
1846 
1847 #ifdef ETHER_SERVICE
1848 struct ether_addr;
1849 
1850 #ifdef HAVE_ETHER_HOSTTON
1851 /*
1852  * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
1853  * ether_hostton()?
1854  */
1855 #ifdef HAVE_NETINET_IF_ETHER_H
1856 struct mbuf;            /* Squelch compiler warnings on some platforms for */
1857 struct rtentry;         /* declarations in <net/if.h> */
1858 #include <net/if.h>     /* for "struct ifnet" in "struct arpcom" on Solaris */
1859 #include <netinet/if_ether.h>
1860 #endif /* HAVE_NETINET_IF_ETHER_H */
1861 #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
1862 #include <netinet/ether.h>
1863 #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
1864 #endif /* HAVE_ETHER_HOSTTON */
1865 #endif
1866 
1867 /*
1868  * hash tables for whatever-to-name translations
1869 
1870 #define HASHNAMESIZE 4096
1871 
1872 struct h6namemem {
1873    struct in6_addr addr;
1874    char *name;
1875    struct h6namemem *nxt;
1876 };
1877 
1878 struct hnamemem {
1879    u_int addr;
1880    char *name;
1881    struct hnamemem *nxt;
1882 };
1883 
1884 struct h6namemem h6nametable[HASHNAMESIZE];
1885 struct hnamemem  hnametable[HASHNAMESIZE];
1886 struct hnamemem  tporttable[HASHNAMESIZE];
1887 struct hnamemem  uporttable[HASHNAMESIZE];
1888 struct hnamemem  eprototable[HASHNAMESIZE];
1889 struct hnamemem  nnametable[HASHNAMESIZE];
1890 struct hnamemem  llcsaptable[HASHNAMESIZE];
1891 
1892 struct enamemem {
1893    u_short e_addr0;
1894    u_short e_addr1;
1895    u_short e_addr2;
1896    char *e_name;
1897    u_char *e_nsap;
1898    struct enamemem *e_nxt;
1899 };
1900 
1901 struct enamemem enametable[HASHNAMESIZE];
1902 struct enamemem nsaptable[HASHNAMESIZE];
1903 
1904 struct protoidmem {
1905    u_int p_oui;
1906    arg_uint16 p_proto;
1907    char *p_name;
1908    struct protoidmem *p_nxt;
1909 };
1910 
1911 struct protoidmem protoidtable[HASHNAMESIZE];
1912  */
1913 
1914 /*
1915  * A faster replacement for inet_ntoa().
1916  */
1917 char *
intoa(u_int addr)1918 intoa(u_int addr)
1919 {
1920    char *cp;
1921    u_int byte;
1922    int n;
1923    static char buf[sizeof(".xxx.xxx.xxx.xxx")];
1924 /*
1925    addr = htonl(addr);
1926 */
1927    cp = &buf[sizeof buf];
1928    *--cp = '\0';
1929 
1930    n = 4;
1931    do {
1932       byte = addr & 0xff;
1933       *--cp = byte % 10 + '0';
1934       byte /= 10;
1935       if (byte > 0) {
1936          *--cp = byte % 10 + '0';
1937          byte /= 10;
1938          if (byte > 0)
1939             *--cp = byte + '0';
1940       }
1941       *--cp = '.';
1942       addr >>= 8;
1943    } while (--n > 0);
1944 
1945    return cp + 1;
1946 }
1947 
1948 /*
1949  * Return a name for the IP address pointed to by ap.  This address
1950  * is assumed to be in network byte order.
1951  */
1952 char *
ArgusGetName(struct ArgusParserStruct * parser,u_char * ap)1953 ArgusGetName(struct ArgusParserStruct *parser, u_char *ap)
1954 {
1955    static struct hnamemem *p;      /* static for longjmp() */
1956    u_int addr;
1957 
1958 #if !defined(TCPDUMP_ALIGN)
1959    addr = *(const u_int *)ap;
1960 #else
1961    /*
1962     * Deal with alignment.
1963     */
1964    switch ((int)ap & 3) {
1965 
1966    case 0:
1967       addr = *(u_int *)ap;
1968       break;
1969 
1970    case 2:
1971       addr = ((u_int)*(u_short *)ap << 16) |
1972          (u_int)*(u_short *)(ap + 2);
1973       break;
1974 
1975    default:
1976       addr = ((u_int)ap[3] << 24) |
1977          ((u_int)ap[2] << 16) |
1978          ((u_int)ap[1] << 8) |
1979          (u_int)ap[0];
1980       break;
1981    }
1982 #endif
1983    p = &parser->hnametable[addr % (HASHNAMESIZE-1)];
1984    for (; p->nxt; p = p->nxt) {
1985       if (p->addr == addr)
1986          if (p->name != NULL)
1987             return (p->name);
1988    }
1989    p->addr = addr;
1990    p->nxt = (struct hnamemem *)calloc(1, sizeof (*p));
1991 
1992    return (intoa(addr));
1993 }
1994 
1995 
1996 #include <sys/socket.h>
1997 #include <arpa/inet.h>
1998 
1999 #if !defined(INET6_ADDRSTRLEN)
2000 #define INET6_ADDRSTRLEN	46
2001 #endif
2002 
2003 #if !defined(AF_INET6)
2004 #define AF_INET6		23
2005 #endif
2006 
2007 char *
ArgusGetV6Name(struct ArgusParserStruct * parser,u_char * ap)2008 ArgusGetV6Name(struct ArgusParserStruct *parser, u_char *ap)
2009 {
2010    struct in6_addr addr;
2011    char ntop_buf[INET6_ADDRSTRLEN];
2012    struct h6namemem *p;      /* static for longjmp() */
2013    const char *cp;
2014 
2015    memcpy(&addr, ap, sizeof(addr));
2016 
2017    p = &parser->h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)];
2018    for (; p->nxt; p = p->nxt) {
2019       if (memcmp(&p->addr, &addr, sizeof(addr)) == 0)
2020          return (p->name);
2021    }
2022    p->addr = addr;
2023    p->nxt = (struct h6namemem *)calloc(1, sizeof (*p));
2024 
2025    if ((cp = inet_ntop(AF_INET6, (const void *) &addr, ntop_buf, sizeof(ntop_buf))) != NULL)
2026       p->name = strdup(cp);
2027 
2028    return (p->name);
2029 }
2030 
2031 struct timeval *
RaMinTime(struct timeval * s1,struct timeval * s2)2032 RaMinTime (struct timeval *s1, struct timeval *s2)
2033 {
2034    struct timeval *retn = s2;
2035 
2036    if ((s1->tv_sec < s2->tv_sec) || ((s1->tv_sec == s2->tv_sec) && (s1->tv_usec < s2->tv_usec)))
2037       retn = s1;
2038 
2039    return (retn);
2040 }
2041 
2042 
2043 struct timeval *
RaMaxTime(struct timeval * s1,struct timeval * s2)2044 RaMaxTime (struct timeval *s1, struct timeval *s2)
2045 {
2046    struct timeval *retn = s2;
2047 
2048    if ((s1->tv_sec > s2->tv_sec) || ((s1->tv_sec == s2->tv_sec) && (s1->tv_usec > s2->tv_usec)))
2049       retn = s1;
2050 
2051    return (retn);
2052 }
2053 
2054 
2055 float
RaDeltaFloatTime(struct timeval * s1,struct timeval * s2)2056 RaDeltaFloatTime (struct timeval *s1, struct timeval *s2)
2057 {
2058    float retn = 0.0;
2059 
2060    if (s1 && s2) {
2061       double v1 = (s1->tv_sec * 1.0) + (s1->tv_usec / 1000000.0);
2062       double v2 = (s2->tv_sec * 1.0) + (s2->tv_usec / 1000000.0);
2063 
2064       retn = v1 - v2;
2065    }
2066 
2067    return (retn);
2068 }
2069 
2070 int
RaDiffTime(struct timeval * s1,struct timeval * s2,struct timeval * diff)2071 RaDiffTime (struct timeval *s1, struct timeval *s2, struct timeval *diff)
2072 {
2073    int retn = 0;
2074 
2075    if (s1 && s2 && diff) {
2076       bzero ((char *)diff, sizeof(*diff));
2077 
2078       double v1 = (s1->tv_sec * 1.0) + (s1->tv_usec / 1000000.0);
2079       double v2 = (s2->tv_sec * 1.0) + (s2->tv_usec / 1000000.0);
2080       double f, i;
2081 
2082       v1 -= v2;
2083 
2084       f = modf(v1, &i);
2085 
2086       diff->tv_sec  = i;
2087       diff->tv_usec = f * 1000000;
2088 
2089       retn = 1;
2090    }
2091 
2092    return (retn);
2093 }
2094 
2095 
2096 long long ArgusDiffTime (struct ArgusTime *, struct ArgusTime *, struct timeval *);
2097 
2098 long long
ArgusDiffTime(struct ArgusTime * s1,struct ArgusTime * s2,struct timeval * diff)2099 ArgusDiffTime (struct ArgusTime *s1, struct ArgusTime *s2, struct timeval *diff)
2100 {
2101    long long v1 = 0, v2 = 0;
2102 
2103    if (s1 && s2 && diff) {
2104       v1 = (s1->tv_sec * 1000000LL) + s1->tv_usec;
2105       v2 = (s2->tv_sec * 1000000LL) + s2->tv_usec;
2106 
2107       v1 -= v2;
2108 
2109       diff->tv_sec  = v1 / 1000000;
2110       diff->tv_usec = v1 % 1000000;
2111    }
2112 
2113    return (v1);
2114 }
2115 
2116 
2117 float
RaGetFloatDuration(struct ArgusRecordStruct * argus)2118 RaGetFloatDuration (struct ArgusRecordStruct *argus)
2119 {
2120    float retn = 0;
2121    int sec = 0, usec = 0;
2122 
2123    if (argus->hdr.type & ARGUS_MAR) {
2124       struct ArgusRecord *rec = (struct ArgusRecord *) &argus->canon;
2125 
2126       sec  = rec->argus_mar.now.tv_sec  - rec->argus_mar.startime.tv_sec;
2127       usec = rec->argus_mar.now.tv_usec - rec->argus_mar.startime.tv_usec;
2128 
2129    } else {
2130       struct ArgusTimeObject *dtime = &argus->canon.time;
2131       struct timeval *stime = NULL, *ltime = NULL;
2132       struct timeval srctime, dsttime;
2133       unsigned int subtype = dtime->hdr.subtype & (ARGUS_TIME_SRC_START | ARGUS_TIME_DST_START |
2134                                                    ARGUS_TIME_SRC_END   | ARGUS_TIME_DST_END);
2135       if (subtype) {
2136          switch (subtype) {
2137             case ARGUS_TIME_SRC_START | ARGUS_TIME_DST_START |
2138                  ARGUS_TIME_SRC_END   | ARGUS_TIME_DST_END: {
2139 
2140                srctime.tv_sec  = dtime->src.start.tv_sec;
2141                srctime.tv_usec = dtime->src.start.tv_usec;
2142                dsttime.tv_sec  = dtime->dst.start.tv_sec;
2143                dsttime.tv_usec = dtime->dst.start.tv_usec;
2144 
2145                stime = RaMinTime(&srctime, &dsttime);
2146 
2147                srctime.tv_sec  = dtime->src.end.tv_sec;
2148                srctime.tv_usec = dtime->src.end.tv_usec;
2149                dsttime.tv_sec  = dtime->dst.end.tv_sec;
2150                dsttime.tv_usec = dtime->dst.end.tv_usec;
2151 
2152                ltime = RaMaxTime(&srctime, &dsttime);
2153                break;
2154             }
2155 
2156             case ARGUS_TIME_SRC_START:
2157             case ARGUS_TIME_SRC_START | ARGUS_TIME_SRC_END: {
2158 
2159                srctime.tv_sec  = dtime->src.start.tv_sec;
2160                srctime.tv_usec = dtime->src.start.tv_usec;
2161                dsttime.tv_sec  = dtime->src.end.tv_sec;
2162                dsttime.tv_usec = dtime->src.end.tv_usec;
2163 
2164                stime = &srctime;
2165                ltime = &dsttime;
2166                break;
2167             }
2168 
2169             case ARGUS_TIME_DST_START:
2170             case ARGUS_TIME_DST_START | ARGUS_TIME_DST_END: {
2171                srctime.tv_sec  = dtime->dst.start.tv_sec;
2172                srctime.tv_usec = dtime->dst.start.tv_usec;
2173                dsttime.tv_sec  = dtime->dst.end.tv_sec;
2174                dsttime.tv_usec = dtime->dst.end.tv_usec;
2175 
2176                stime = &srctime;
2177                ltime = &dsttime;
2178                break;
2179             }
2180 
2181             case ARGUS_TIME_SRC_START | ARGUS_TIME_DST_END: {
2182                srctime.tv_sec  = dtime->src.start.tv_sec;
2183                srctime.tv_usec = dtime->src.start.tv_usec;
2184                dsttime.tv_sec  = dtime->dst.end.tv_sec;
2185                dsttime.tv_usec = dtime->dst.end.tv_usec;
2186 
2187                stime = &srctime;
2188                ltime = &dsttime;
2189                break;
2190             }
2191 
2192             default:
2193                break;
2194          }
2195 
2196       } else {
2197          srctime.tv_sec  = dtime->src.start.tv_sec;
2198          srctime.tv_usec = dtime->src.start.tv_usec;
2199          dsttime.tv_sec  = dtime->src.end.tv_sec;
2200          dsttime.tv_usec = dtime->src.end.tv_usec;
2201 
2202          stime = &srctime;
2203          ltime = &dsttime;
2204       }
2205 
2206 
2207       if (stime && ltime) {
2208          sec  = ltime->tv_sec  - stime->tv_sec;
2209          usec = ltime->tv_usec - stime->tv_usec;
2210       }
2211    }
2212 
2213    retn  = (sec * 1.0) + usec/1000000.0;
2214    return (retn);
2215 }
2216 
2217 
2218 float
RaGetFloatSrcDuration(struct ArgusRecordStruct * argus)2219 RaGetFloatSrcDuration (struct ArgusRecordStruct *argus)
2220 {
2221    float retn = 0.0;
2222    int sec = 0, usec = 0;
2223 
2224    if (argus->hdr.type & ARGUS_MAR) {
2225 
2226    } else {
2227       struct ArgusTimeObject *dtime = &argus->canon.time;
2228       struct ArgusTime *stime = &dtime->src.start;
2229       struct ArgusTime *ltime = &dtime->src.end;
2230 
2231       sec  = ltime->tv_sec  - stime->tv_sec;
2232       usec = ltime->tv_usec - stime->tv_usec;
2233       retn  = (sec * 1.0) + usec/1000000.0;
2234    }
2235 
2236    return (retn);
2237 }
2238 
2239 
2240 float
RaGetFloatDstDuration(struct ArgusRecordStruct * argus)2241 RaGetFloatDstDuration (struct ArgusRecordStruct *argus)
2242 {
2243    float retn = 0.0;
2244    int sec = 0, usec = 0;
2245 
2246    if (argus->hdr.type & ARGUS_MAR) {
2247 
2248    } else {
2249       struct ArgusTimeObject *dtime = &argus->canon.time;
2250       struct ArgusTime *stime = &dtime->dst.start;
2251       struct ArgusTime *ltime = &dtime->dst.end;
2252 
2253       sec  = ltime->tv_sec  - stime->tv_sec;
2254       usec = ltime->tv_usec - stime->tv_usec;
2255       retn  = (sec * 1.0) + usec/1000000.0;
2256    }
2257 
2258    return (retn);
2259 }
2260 
2261 
2262 double
ArgusFetchDuration(struct ArgusRecordStruct * ns)2263 ArgusFetchDuration (struct ArgusRecordStruct *ns)
2264 {
2265    double retn = RaGetFloatDuration(ns);
2266    return (retn);
2267 }
2268 
2269 double
ArgusFetchSrcDuration(struct ArgusRecordStruct * ns)2270 ArgusFetchSrcDuration (struct ArgusRecordStruct *ns)
2271 {
2272    double retn = RaGetFloatSrcDuration(ns);
2273    return (retn);
2274 }
2275 
2276 double
ArgusFetchDstDuration(struct ArgusRecordStruct * ns)2277 ArgusFetchDstDuration (struct ArgusRecordStruct *ns)
2278 {
2279    double retn = RaGetFloatDstDuration(ns);
2280    return (retn);
2281 }
2282 
2283 
2284 double
ArgusFetchSrcLoad(struct ArgusRecordStruct * ns)2285 ArgusFetchSrcLoad (struct ArgusRecordStruct *ns)
2286 {
2287    struct ArgusMetricStruct *m1 = NULL;
2288    float dur = 0.0;
2289    long long cnt1;
2290    double retn = 0.0;
2291 
2292    dur = ArgusFetchSrcDuration(ns);
2293 
2294    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL) {
2295       cnt1 = m1->src.pkts;
2296    } else {
2297       cnt1 = 0;
2298    }
2299 
2300    if (dur > 0.0)
2301       retn = (cnt1 * 1.0)/dur;
2302 
2303    return (retn);
2304 }
2305 
2306 double
ArgusFetchDstLoad(struct ArgusRecordStruct * ns)2307 ArgusFetchDstLoad (struct ArgusRecordStruct *ns)
2308 {
2309    struct ArgusMetricStruct *m1 = NULL;
2310    struct timeval ts1buf, *ts1 = &ts1buf;
2311    struct timeval t1buf, *t1d = &t1buf;
2312    long long cnt1 = 0;
2313    float d1 = 0.0;
2314    double retn = 0;
2315 
2316    ts1->tv_sec  = ns->canon.time.src.start.tv_sec;
2317    ts1->tv_usec = ns->canon.time.src.start.tv_usec;
2318 
2319    t1d->tv_sec  = ns->canon.time.src.end.tv_sec;
2320    t1d->tv_usec = ns->canon.time.src.end.tv_usec;
2321 
2322    t1d->tv_sec  -= ts1->tv_sec; t1d->tv_usec -= ts1->tv_usec;
2323    if (t1d->tv_usec < 0) {t1d->tv_sec--; t1d->tv_usec += 1000000;}
2324    d1 = ((t1d->tv_sec * 1.0) + (t1d->tv_usec/1000000.0));
2325 
2326    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL)
2327       cnt1 = m1->dst.pkts;
2328 
2329    if (d1 > 0.0)
2330       retn = (cnt1 * 1.0)/d1;
2331 
2332    return (retn);
2333 }
2334 
2335 
2336 double
ArgusFetchLoad(struct ArgusRecordStruct * ns)2337 ArgusFetchLoad (struct ArgusRecordStruct *ns)
2338 {
2339    struct ArgusMetricStruct *m1 = NULL;
2340    struct timeval ts1buf, *ts1 = &ts1buf;
2341    struct timeval t1buf, *t1d = &t1buf;
2342    long long cnt1 = 0;
2343    float d1 = 0.0;
2344    double retn = 0;
2345 
2346    ts1->tv_sec  = ns->canon.time.src.start.tv_sec;
2347    ts1->tv_usec = ns->canon.time.src.start.tv_usec;
2348 
2349    t1d->tv_sec  = ns->canon.time.src.end.tv_sec;
2350    t1d->tv_usec = ns->canon.time.src.end.tv_usec;
2351 
2352    t1d->tv_sec  -= ts1->tv_sec; t1d->tv_usec -= ts1->tv_usec;
2353    if (t1d->tv_usec < 0) {t1d->tv_sec--; t1d->tv_usec += 1000000;}
2354    d1 = ((t1d->tv_sec * 1.0) + (t1d->tv_usec/1000000.0));
2355 
2356    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL)
2357       cnt1 = m1->src.pkts + m1->dst.pkts;
2358 
2359    if ((cnt1 > 0) && (d1 > 0.0))
2360       retn = (cnt1 * 1.0)/d1;
2361 
2362    return (retn);
2363 }
2364 
2365 
2366 double
ArgusFetchLoss(struct ArgusRecordStruct * ns)2367 ArgusFetchLoss (struct ArgusRecordStruct *ns)
2368 {
2369    double retn = 0.0;
2370 
2371    if (ns) {
2372       if (ns->hdr.type & ARGUS_MAR) {
2373       } else {
2374          struct ArgusFlow *flow = (struct ArgusFlow *)&ns->canon.flow;
2375          switch (flow->hdr.subtype & 0x3F) {
2376             case ARGUS_FLOW_CLASSIC5TUPLE: {
2377                switch ((flow->hdr.argus_dsrvl8.qual & 0x1F)) {
2378                   case ARGUS_TYPE_IPV4: {
2379                      switch (ns->canon.flow.ip_flow.ip_p) {
2380                         case IPPROTO_UDP: {
2381                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2382                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2383                               retn = (rtp->sdrop + rtp->ddrop) * 1.0;
2384                            }
2385                            break;
2386                         }
2387 
2388                         case IPPROTO_ICMP: {
2389                            break;
2390                         }
2391                         case IPPROTO_TCP: {
2392                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2393 
2394                            if ((tcp != NULL) && (tcp->state != 0)) {
2395                               if (ns->canon.metric.src.pkts)
2396                                  retn = (tcp->src.retrans + tcp->dst.retrans) * 1.0;
2397                            }
2398                            break;
2399                         }
2400                         case IPPROTO_ESP: {
2401                            struct ArgusESPObject *esp = (void *)&ns->canon.net.net_union.esp;
2402                            if (esp != NULL) {
2403                               if (ns->canon.metric.src.pkts)
2404                                  retn = esp->lostseq * 1.0;
2405                            }
2406                            break;
2407                         }
2408                      }
2409                      break;
2410                   }
2411 
2412                   case ARGUS_TYPE_IPV6: {
2413                      switch (flow->ipv6_flow.ip_p) {
2414                         case IPPROTO_UDP: {
2415                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2416                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2417                               retn = (rtp->sdrop + rtp->ddrop) * 1.0;
2418                            }
2419                            break;
2420                         }
2421 
2422                         case IPPROTO_ICMP: {
2423                            break;
2424                         }
2425 
2426                         case IPPROTO_TCP: {
2427                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2428 
2429                            if ((tcp != NULL) && (tcp->state != 0)) {
2430                               if (ns->canon.metric.src.pkts)
2431                                  retn = (tcp->src.retrans + tcp->dst.retrans) * 1.0;
2432                            }
2433                            break;
2434                         }
2435                      }
2436                   }
2437                }
2438                break;
2439             }
2440          }
2441       }
2442    }
2443 
2444    return (retn);
2445 }
2446 
2447 
2448 double
ArgusFetchSrcLoss(struct ArgusRecordStruct * ns)2449 ArgusFetchSrcLoss (struct ArgusRecordStruct *ns)
2450 {
2451    double retn = 0.0;
2452 
2453    if (ns) {
2454       if (ns->hdr.type & ARGUS_MAR) {
2455       } else {
2456          struct ArgusFlow *flow = (struct ArgusFlow *)&ns->canon.flow;
2457          switch (flow->hdr.subtype & 0x3F) {
2458             case ARGUS_FLOW_CLASSIC5TUPLE: {
2459                switch ((flow->hdr.argus_dsrvl8.qual & 0x1F)) {
2460                   case ARGUS_TYPE_IPV4: {
2461                      switch (ns->canon.flow.ip_flow.ip_p) {
2462                         case IPPROTO_UDP: {
2463                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2464                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2465                               retn = rtp->sdrop * 1.0;
2466                            }
2467                            break;
2468                         }
2469 
2470                         case IPPROTO_ICMP: {
2471                            break;
2472                         }
2473                         case IPPROTO_TCP: {
2474                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2475 
2476                            if ((tcp != NULL) && (tcp->state != 0)) {
2477                               if (ns->canon.metric.src.pkts)
2478                                  retn = tcp->src.retrans * 1.0;
2479                            }
2480                            break;
2481                         }
2482                         case IPPROTO_ESP: {
2483                            struct ArgusESPObject *esp = (void *)&ns->canon.net.net_union.esp;
2484                            if (esp != NULL) {
2485                               if (ns->canon.metric.src.pkts)
2486                                  retn = esp->lostseq * 1.0;
2487                            }
2488                            break;
2489                         }
2490                      }
2491                      break;
2492                   }
2493 
2494                   case ARGUS_TYPE_IPV6: {
2495                      switch (flow->ipv6_flow.ip_p) {
2496                         case IPPROTO_UDP: {
2497                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2498                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2499                               retn = rtp->sdrop * 1.0;
2500                            }
2501                            break;
2502                         }
2503 
2504                         case IPPROTO_ICMP: {
2505                            break;
2506                         }
2507 
2508                         case IPPROTO_TCP: {
2509                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2510 
2511                            if ((tcp != NULL) && (tcp->state != 0)) {
2512                               if (ns->canon.metric.src.pkts)
2513                                  retn = tcp->src.retrans * 1.0;
2514                            }
2515                            break;
2516                         }
2517                      }
2518                   }
2519                }
2520                break;
2521             }
2522          }
2523       }
2524    }
2525 
2526    return (retn);
2527 }
2528 
2529 double
ArgusFetchDstLoss(struct ArgusRecordStruct * ns)2530 ArgusFetchDstLoss (struct ArgusRecordStruct *ns)
2531 {
2532    double retn = 0.0;
2533 
2534    if (ns) {
2535       if (ns->hdr.type & ARGUS_MAR) {
2536       } else {
2537          struct ArgusFlow *flow = (struct ArgusFlow *)&ns->canon.flow;
2538          switch (flow->hdr.subtype & 0x3F) {
2539             case ARGUS_FLOW_CLASSIC5TUPLE: {
2540                switch ((flow->hdr.argus_dsrvl8.qual & 0x1F)) {
2541                   case ARGUS_TYPE_IPV4: {
2542                      switch (ns->canon.flow.ip_flow.ip_p) {
2543                         case IPPROTO_UDP: {
2544                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2545                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2546                               retn = rtp->ddrop * 1.0;
2547                            }
2548                         }
2549 
2550                         case IPPROTO_ICMP: {
2551                            break;
2552                         }
2553                         case IPPROTO_TCP: {
2554                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2555 
2556                            if ((tcp != NULL) && (tcp->state != 0)) {
2557                               if (ns->canon.metric.dst.pkts)
2558                                  retn = tcp->dst.retrans * 1.0;
2559                            }
2560                            break;
2561                         }
2562                         case IPPROTO_ESP: {
2563                            struct ArgusESPObject *esp = (void *)&ns->canon.net.net_union.esp;
2564                            if (esp != NULL) {
2565                               if (ns->canon.metric.dst.pkts)
2566                                  retn = esp->lostseq * 1.0;
2567                            }
2568                         }
2569                      }
2570                      break;
2571                   }
2572 
2573                   case ARGUS_TYPE_IPV6: {
2574                      switch (flow->ipv6_flow.ip_p) {
2575                         case IPPROTO_UDP: {
2576                            if (ns->canon.net.hdr.subtype == ARGUS_RTP_FLOW) {
2577                               struct ArgusRTPObject *rtp = (void *)&ns->canon.net.net_union.rtp;
2578                               retn = rtp->ddrop * 1.0;
2579                            }
2580                            break;
2581                         }
2582 
2583                         case IPPROTO_ICMP: {
2584                            break;
2585                         }
2586 
2587                         case IPPROTO_TCP: {
2588                            struct ArgusTCPObject *tcp = (void *)&ns->canon.net.net_union.tcp;
2589 
2590                            if ((tcp != NULL) && (tcp->state != 0)) {
2591                               if (ns->canon.metric.dst.pkts)
2592                                  retn = tcp->dst.retrans * 1.0;
2593                            }
2594                            break;
2595                         }
2596                      }
2597                   }
2598                }
2599                break;
2600             }
2601          }
2602       }
2603    }
2604 
2605    return (retn);
2606 }
2607 
2608 
2609 double
ArgusFetchPercentLoss(struct ArgusRecordStruct * ns)2610 ArgusFetchPercentLoss (struct ArgusRecordStruct *ns)
2611 {
2612    double retn = 0.0;
2613    int pkts = 0;
2614 
2615    if (ns) {
2616       retn = ArgusFetchLoss(ns);
2617       pkts = ns->canon.metric.src.pkts + ns->canon.metric.dst.pkts;
2618       if (pkts > 0) {
2619          retn = (retn * 100.0)/((pkts * 1.0 )+ retn);
2620       } else
2621          retn = 0.0;
2622    }
2623 
2624    return (retn);
2625 }
2626 
2627 double
ArgusFetchPercentSrcLoss(struct ArgusRecordStruct * ns)2628 ArgusFetchPercentSrcLoss (struct ArgusRecordStruct *ns)
2629 {
2630    double retn = 0.0;
2631    int pkts = 0;
2632 
2633    if (ns) {
2634       retn = ArgusFetchSrcLoss(ns);
2635       pkts = ns->canon.metric.src.pkts;
2636       if (pkts > 0) {
2637          retn = (retn * 100.0)/((pkts * 1.0) + retn);
2638       } else
2639          retn = 0.0;
2640    }
2641 
2642    return (retn);
2643 }
2644 
2645 double
ArgusFetchPercentDstLoss(struct ArgusRecordStruct * ns)2646 ArgusFetchPercentDstLoss (struct ArgusRecordStruct *ns)
2647 {
2648    double retn = 0.0;
2649    int pkts = 0;
2650 
2651    if (ns) {
2652       retn = ArgusFetchDstLoss(ns);
2653       pkts = ns->canon.metric.dst.pkts;
2654       if (pkts > 0) {
2655          retn = (retn * 100.0)/((pkts * 1.0) + retn);
2656       } else
2657          retn = 0.0;
2658    }
2659 
2660    return (retn);
2661 }
2662 
2663 
2664 double
ArgusFetchSrcRate(struct ArgusRecordStruct * ns)2665 ArgusFetchSrcRate (struct ArgusRecordStruct *ns)
2666 {
2667    struct ArgusMetricStruct *m1 = NULL;
2668    struct timeval ts1buf, *ts1 = &ts1buf;
2669    struct timeval t1buf, *t1d = &t1buf;
2670    long long cnt1 = 0;
2671    float d1, r1 = 0.0;
2672    double retn = 0;
2673 
2674    ts1->tv_sec  = ns->canon.time.src.start.tv_sec;
2675    ts1->tv_usec = ns->canon.time.src.start.tv_usec;
2676 
2677    t1d->tv_sec  = ns->canon.time.src.end.tv_sec;
2678    t1d->tv_usec = ns->canon.time.src.end.tv_usec;
2679 
2680    t1d->tv_sec  -= ts1->tv_sec; t1d->tv_usec -= ts1->tv_usec;
2681    if (t1d->tv_usec < 0) {t1d->tv_sec--; t1d->tv_usec += 1000000;}
2682    d1 = ((t1d->tv_sec * 1.0) + (t1d->tv_usec/1000000.0));
2683 
2684    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL)
2685       cnt1 = m1->src.bytes * 8;
2686 
2687    if ((cnt1 > 0) && (d1 > 0.0))
2688       r1 = (cnt1 * 1.0)/d1;
2689 
2690    retn = r1;
2691    return (retn);
2692 }
2693 
2694 double
ArgusFetchDstRate(struct ArgusRecordStruct * ns)2695 ArgusFetchDstRate (struct ArgusRecordStruct *ns)
2696 {
2697    struct ArgusMetricStruct *m1 = NULL;
2698    struct timeval ts1buf, *ts1 = &ts1buf;
2699    struct timeval t1buf,  *t1d = &t1buf;
2700    float d1, r1 = 0.0;
2701    long long cnt1 = 0;
2702    double retn = 0;
2703 
2704    ts1->tv_sec  = ns->canon.time.src.start.tv_sec;
2705    ts1->tv_usec = ns->canon.time.src.start.tv_usec;
2706 
2707    t1d->tv_sec  = ns->canon.time.src.end.tv_sec;
2708    t1d->tv_usec = ns->canon.time.src.end.tv_usec;
2709 
2710    t1d->tv_sec  -= ts1->tv_sec; t1d->tv_usec -= ts1->tv_usec;
2711    if (t1d->tv_usec < 0) {t1d->tv_sec--; t1d->tv_usec += 1000000;}
2712    d1 = ((t1d->tv_sec * 1.0) + (t1d->tv_usec/1000000.0));
2713 
2714    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL)
2715       cnt1 = m1->dst.bytes * 8;
2716 
2717    if ((cnt1 > 0) && (d1 > 0.0))
2718       r1 = (cnt1 * 1.0)/d1;
2719 
2720    retn = r1;
2721    return (retn);
2722 }
2723 
2724 double
ArgusFetchRate(struct ArgusRecordStruct * ns)2725 ArgusFetchRate (struct ArgusRecordStruct *ns)
2726 {
2727    struct ArgusMetricStruct *m1 = NULL;
2728    struct timeval ts1buf, *ts1 = &ts1buf;
2729    struct timeval t1buf, *t1d = &t1buf;
2730    long long cnt1 = 0;
2731    float d1, r1 = 0.0;
2732    double retn = 0;
2733 
2734    ts1->tv_sec  = ns->canon.time.src.start.tv_sec;
2735    ts1->tv_usec = ns->canon.time.src.start.tv_usec;
2736 
2737    t1d->tv_sec  = ns->canon.time.src.end.tv_sec;
2738    t1d->tv_usec = ns->canon.time.src.end.tv_usec;
2739 
2740    t1d->tv_sec  -= ts1->tv_sec; t1d->tv_usec -= ts1->tv_usec;
2741    if (t1d->tv_usec < 0) {t1d->tv_sec--; t1d->tv_usec += 1000000;}
2742    d1 = ((t1d->tv_sec * 1.0) + (t1d->tv_usec/1000000.0));
2743 
2744    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL)
2745       cnt1 = (m1->src.bytes + m1->dst.bytes) * 8;
2746 
2747    if ((cnt1 > 0) && (d1 > 0.0))
2748       r1 = (cnt1 * 1.0)/d1;
2749 
2750    retn = r1;
2751    return (retn);
2752 }
2753 
2754 double
ArgusFetchAppByteRatio(struct ArgusRecordStruct * ns)2755 ArgusFetchAppByteRatio (struct ArgusRecordStruct *ns)
2756 {
2757    struct ArgusMetricStruct *m1 = NULL;
2758    double retn =  0.0;
2759 
2760    if ((m1 = (struct ArgusMetricStruct *) ns->dsrs[ARGUS_METRIC_INDEX]) != NULL) {
2761       double nvalue = (m1->src.appbytes - m1->dst.appbytes) * 1.0;
2762       double dvalue = (m1->src.appbytes + m1->dst.appbytes) * 1.0;
2763 
2764       if (dvalue > 0)
2765          retn = nvalue / dvalue;
2766       else
2767          retn = -0.0;
2768    }
2769    return (retn);
2770 }
2771