1 /*
2  * Argus Software
3  * Copyright (c) 2000-2016 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  * rapath - print derivable path information from argus data.
24  *
25  *  The strategy is to take in 'icmpmap' data, and to formulate path information
26  *  for the collection of records received. By classifying all the flow data by
27  *  the tuple {src, dst}, we can track any number of simulataneous traceroutes
28  *  and report on the results in a manner that preserves the granularity of the
29  *  data seen, but provide means to modify that granularity to get interesting
30  *  results.
31  *
32  *  The intermediate nodes
33  *
34  * written by Carter Bullard
35  * QoSient, LLC
36  *
37  * $Id: //depot/argus/clients/examples/rapath/rapath.c#15 $
38  * $DateTime: 2016/06/01 15:17:28 $
39  * $Change: 3148 $
40  */
41 
42 #ifdef HAVE_CONFIG_H
43 #include "argus_config.h"
44 #endif
45 
46 #if defined(CYGWIN)
47 #define USE_IPV6
48 #endif
49 
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <signal.h>
53 #include <ctype.h>
54 
55 #include <argus_compat.h>
56 
57 #include <rabins.h>
58 #include <argus_util.h>
59 #include <argus_client.h>
60 #include <argus_main.h>
61 #include <argus_sort.h>
62 
63 #include <argus_filter.h>
64 #include <argus_cluster.h>
65 
66 #include <math.h>
67 
68 int RaInitialized = 0;
69 int RaPrintThinkMapOutput = 0;
70 int RaPrintSVGOutput = 0;
71 int RaPrintASNum = 0;
72 int RaPrintNode = 0;
73 int RaPrintAddr = 0;
74 int RaPrintTreeNode = 0;
75 int RaPrintDistance = 0;
76 
77 extern int RaHistoStart;
78 extern int RaHistoEnd;
79 
80 struct ArgusQueueStruct *ArgusModelerQueue;
81 
82 int RaCompareArgusStore (const void *, const void *);
83 void RaPackQueue (struct ArgusQueueStruct *);
84 void RaSortQueue (struct ArgusQueueStruct *);
85 void RaProcessQueue(struct ArgusQueueStruct *, unsigned char);
86 
87 #define RAMAP_ETHER_MAC_ADDR            0x1
88 #define RAMAP_IP_ADDR                   0x10
89 
90 #define MAX_OBJ_SIZE            1024
91 unsigned int RaMapHash = 0;
92 unsigned int RaHashSize  = 0;
93 
94 struct RaMapHashTableStruct {
95    int size;
96    struct RaMapHashTableHeader **array;
97 };
98 
99 struct RaMapHashTableHeader {
100    struct ArgusQueueHeader qhdr;
101    struct RaMapHashTableHeader *nxt, *prv;
102    unsigned int hash;
103    int type, len, value, mask, visited;
104    void *obj, *sub;
105 };
106 
107 struct ArgusHashTable *ArgusHashTable;
108 struct RaMapHashTableStruct RaMapAddrTable;
109 struct RaMapHashTableHeader *RaMapFindHashObject (struct RaMapHashTableStruct *, void *, int, int);
110 struct RaMapHashTableHeader *RaMapAddHashEntry (struct RaMapHashTableStruct *, void *, int, int);
111 void RaMapRemoveHashEntry (struct RaMapHashTableStruct *, struct RaMapHashTableHeader *);
112 
113 
114 unsigned int RaMapCalcHash (void *, int, int);
115 
116 struct ArgusAggregatorStruct *ArgusMatrixAggregator = NULL;
117 struct ArgusAggregatorStruct *ArgusFlowAggregator = NULL;
118 
119 
120 char *RaMatrixAggregationConfig[] = {
121    "RACLUSTER_PRESERVE_FIELDS=yes",
122    "                   model=\"srcid saddr daddr\"        status=0   idle=3600\n",
123    NULL,
124 };
125 
126 char *RaPathAggregationConfig[] = {
127    "RACLUSTER_PRESERVE_FIELDS=yes",
128    "filter=\"icmpmap\" model=\"srcid saddr daddr proto sttl inode\"  status=120 idle=3600\n",
129    "                   model=\"srcid saddr daddr proto sttl\"        status=0   idle=3600\n",
130    NULL,
131 };
132 
133 #define ARGUS_RCITEMS    4
134 
135 #define ARGUS_RC_FILTER  0
136 #define ARGUS_RC_MODEL   1
137 #define ARGUS_RC_STATUS  2
138 #define ARGUS_RC_IDLE    3
139 
140 extern char *ArgusAggregatorFields[];
141 
142 void
ArgusClientInit(struct ArgusParserStruct * parser)143 ArgusClientInit (struct ArgusParserStruct *parser)
144 {
145    struct ArgusModeStruct *mode = NULL;
146 
147    parser->RaWriteOut = 0;
148 
149    if (!(parser->RaInitialized)) {
150       if ((mode = parser->ArgusModeList) != NULL) {
151          while (mode) {
152             if (!(strcasecmp (mode->mode, "think")))
153                RaPrintThinkMapOutput++;
154             if (!(strcasecmp (mode->mode, "svg")))
155                RaPrintSVGOutput++;
156             if (!(strcasecmp (mode->mode, "addr"))) {
157                RaPrintAddr = 1;
158                RaPrintNode = 0;
159             }
160             if (!(strcasecmp (mode->mode, "tree")))
161                RaPrintTreeNode = 1;
162 
163             if (!(strcasecmp (mode->mode, "node"))) {
164                RaPrintAddr = 0;
165                RaPrintNode = 1;
166             }
167             if (!(strcasecmp (mode->mode, "aspath"))) {
168                RaPrintASNum++;
169             }
170             if (!(strcasecmp (mode->mode, "asnode"))) {
171                RaPrintASNum++;
172                RaPrintNode++;
173             }
174             if (!(strcasecmp (mode->mode, "dist")))
175                RaPrintDistance = 1;
176             mode = mode->nxt;
177          }
178       }
179 
180       if (!(RaPrintAddr) && !(RaPrintNode) && !(RaPrintASNum))
181          RaPrintNode = 1;
182 
183       if (ArgusParser->RaPrintOptionStrings[0] == NULL) {
184          parser->RaPrintOptionIndex = 0;
185          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("srcid");
186          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("saddr");
187          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("dir");
188          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("daddr");
189          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("inode");
190 
191          if (RaPrintASNum)
192             parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("ias:8");
193 
194          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("sttl");
195          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("mean");
196          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("stddev");
197          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("max");
198          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("min");
199          parser->RaPrintOptionStrings[parser->RaPrintOptionIndex++] = strdup("trans");
200          ArgusProcessSOptions(parser);
201       }
202 
203       if (parser->ArgusFlowModelFile) {
204          if ((parser->ArgusLabeler = ArgusNewLabeler(parser, 0L)) == NULL)
205             ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewLabeler error");
206 
207          RaLabelParseResourceFile (parser, parser->ArgusLabeler, parser->ArgusFlowModelFile);
208          free(parser->ArgusFlowModelFile);
209          parser->ArgusFlowModelFile = NULL;
210       }
211 
212       if ((ArgusFlowAggregator = ArgusParseAggregator(parser, NULL, RaPathAggregationConfig)) == NULL)
213          ArgusLog (LOG_ERR, "ArgusClientInit: ArgusParseAggregator error");
214 
215       if (parser->ArgusMaskList != NULL) {
216          if ((parser->ArgusAggregator = ArgusNewAggregator(parser, NULL, ARGUS_RECORD_AGGREGATOR)) == NULL)
217             ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewAggregator error");
218 
219 // have to see if we need to modify the model definition in our RaPathAggregation Config
220 
221          if (ArgusFlowAggregator->saddrlen != parser->ArgusAggregator->saddrlen) {
222             ArgusFlowAggregator->saddrlen = parser->ArgusAggregator->saddrlen;
223             bcopy(&parser->ArgusAggregator->smask, &ArgusFlowAggregator->smask, sizeof(parser->ArgusAggregator->smask));
224          }
225 
226          if (ArgusFlowAggregator->daddrlen != parser->ArgusAggregator->daddrlen) {
227             ArgusFlowAggregator->daddrlen = parser->ArgusAggregator->daddrlen;
228             bcopy(&parser->ArgusAggregator->dmask, &ArgusFlowAggregator->dmask, sizeof(parser->ArgusAggregator->dmask));
229          }
230 
231       } else {
232          if ((parser->ArgusAggregator = ArgusParseAggregator(parser, NULL, RaMatrixAggregationConfig)) == NULL)
233             ArgusLog (LOG_ERR, "ArgusClientInit: ArgusParseAggregator error");
234       }
235 
236       if ((ArgusSorter = ArgusNewSorter(parser)) == NULL)
237          ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewSorter error %s", strerror(errno));
238 
239       if (parser->vflag)
240          ArgusReverseSortDir++;
241 
242       bzero ((char *) ArgusSorter->ArgusSortAlgorithms, sizeof(ArgusSorter->ArgusSortAlgorithms));
243       ArgusSorter->ArgusSortAlgorithms[0] = ArgusSortAlgorithmTable[ARGUSSORTSRCADDR];
244       ArgusSorter->ArgusSortAlgorithms[1] = ArgusSortAlgorithmTable[ARGUSSORTDSTADDR];
245       ArgusSorter->ArgusSortAlgorithms[2] = ArgusSortAlgorithmTable[ARGUSSORTPROTOCOL];
246       ArgusSorter->ArgusSortAlgorithms[3] = ArgusSortAlgorithmTable[ARGUSSORTSRCTTL];
247       ArgusSorter->ArgusSortAlgorithms[4] = ArgusSortAlgorithmTable[ARGUSSORTTRANSACTIONS];
248       ArgusSorter->ArgusSortAlgorithms[4] = ArgusSortAlgorithmTable[ARGUSSORTMINDURATION];
249 
250       if ((ArgusModelerQueue = ArgusNewQueue()) == NULL)
251          exit(0);
252 
253       if ((ArgusHashTable = ArgusNewHashTable(RABINS_HASHTABLESIZE)) == NULL)
254          ArgusLog (LOG_ERR, "ArgusClientInit: ArgusCalloc error %s\n", strerror(errno));
255 
256       if ((RaMapAddrTable.array = (struct RaMapHashTableHeader **) ArgusCalloc (RA_HASHTABLESIZE,
257                                     sizeof (struct RaMapHashTableHeader *))) != NULL) {
258          RaMapAddrTable.size = RA_HASHTABLESIZE;
259       }
260 
261       parser->RaCumulativeMerge = 1;
262 
263       if (parser->Hflag) {
264          if (!(ArgusHistoMetricParse (parser, parser->ArgusAggregator)))
265             usage();
266       }
267 
268       parser->RaInitialized++;
269    }
270 }
271 
272 
273 void
ArgusClientTimeout()274 ArgusClientTimeout ()
275 {
276 /*
277    RaProcessQueue (ArgusModelerQueue, ARGUS_STATUS);
278 */
279 #ifdef ARGUSDEBUG
280       ArgusDebug (9, "ArgusClientTimeout() done\n");
281 #endif
282 }
283 
284 
285 struct RaPathNode {
286    struct RaPathNode *nxt;
287    struct ArgusQueueStruct *nodes;
288    int as, ttl;
289 };
290 
291 struct RaPathTree {
292 };
293 
294 
295 struct RaPathNode *RaPathBuildPath (struct ArgusQueueStruct *);
296 void RaPathDeletePath (struct RaPathNode *);
297 void RaPrintPath (struct RaPathNode *, char *, int);
298 
299 /*
300    The idea is to build the path tree for a given queue.  The queue
301    should have ArgusRecordStruct's that have unique icmp->osrcaddr
302    elements, sorted by sttl.  These queue elements represent the
303    unique elements to deal with in this path and a path is constructed.
304 
305    Nodes in the path can be single elements,
306 
307 */
308 
309 
310 void RaPathInsertTree (struct RaPathTree *, struct RaPathNode *);
311 void RaPrintPathNodes (struct RaPathNode *, int, char *buf, int);
312 
313 struct RaPathNode *
RaPathBuildPath(struct ArgusQueueStruct * queue)314 RaPathBuildPath (struct ArgusQueueStruct *queue)
315 {
316    struct RaPathNode *path = NULL, *node = NULL;
317    struct ArgusRecordStruct *argus;
318    unsigned int pttl, tttl, as;
319 
320    if (queue->count > 0) {
321       while ((argus = (struct ArgusRecordStruct *) ArgusPopQueue(queue, ARGUS_NOLOCK)) != NULL) {
322          struct ArgusIPAttrStruct *attr = (void *)argus->dsrs[ARGUS_IPATTR_INDEX];
323          struct ArgusAsnStruct *asn = (void *)argus->dsrs[ARGUS_ASN_INDEX];
324 
325          tttl = attr->src.ttl;
326 
327          if (path == NULL) {
328             if ((path = (struct RaPathNode *) ArgusCalloc (1, sizeof (*node))) == NULL)
329                ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno));
330 
331             node = path;
332             node->ttl = tttl;
333 
334             if ((asn !=  NULL) && (asn->hdr.argus_dsrvl8.len > 2))
335                if ((as = asn->inode_as) != 0) {
336                   node->as = as;
337                }
338 
339             if ((node->nodes = ArgusNewQueue()) == NULL)
340                ArgusLog (LOG_ERR, "ArgusNewQueue error %s", strerror(errno));
341 
342             ArgusAddToQueue (node->nodes, &argus->qhdr, ARGUS_NOLOCK);
343 
344          } else {
345             struct ArgusIPAttrStruct *pattr = (void *)((struct ArgusRecordStruct *)node->nodes->start)->dsrs[ARGUS_IPATTR_INDEX];
346 
347             if ((pattr != NULL) && (attr != NULL)) {
348                pttl = pattr->src.ttl;
349 
350                if (pttl == tttl) {
351                   ArgusAddToQueue (node->nodes, &argus->qhdr, ARGUS_NOLOCK);
352 
353                   if ((asn !=  NULL) && (asn->hdr.argus_dsrvl8.len > 2))
354                      if (node->as != asn->inode_as)
355                         node->as = -1;
356                } else {
357                   struct RaPathNode *prv = node;
358 
359                   if ((node = (struct RaPathNode *) ArgusCalloc (1, sizeof (*node))) == NULL)
360                      ArgusLog (LOG_ERR, "ArgusCalloc error %s", strerror(errno));
361 
362                   node->ttl = tttl;
363 
364                   if ((asn !=  NULL) && (asn->hdr.argus_dsrvl8.len > 2))
365                      if ((as = asn->inode_as) != 0)
366                         node->as = as;
367 
368                   prv->nxt = node;
369 
370                   if ((node->nodes = ArgusNewQueue()) == NULL)
371                      ArgusLog (LOG_ERR, "ArgusNewQueue error %s", strerror(errno));
372 
373                   ArgusAddToQueue (node->nodes, &argus->qhdr, ARGUS_NOLOCK);
374                }
375             }
376          }
377       }
378    }
379 
380    return (path);
381 }
382 
383 void
RaPathDeletePath(struct RaPathNode * path)384 RaPathDeletePath (struct RaPathNode *path)
385 {
386    if (path->nxt != NULL)
387       RaPathDeletePath(path->nxt);
388 
389    if (path->nodes != NULL) {
390       ArgusDeleteQueue(path->nodes);
391    }
392    ArgusFree(path);
393 
394    return;
395 }
396 
397 
398 void
RaPathInsertTree(struct RaPathTree * tree,struct RaPathNode * path)399 RaPathInsertTree (struct RaPathTree *tree, struct RaPathNode *path)
400 {
401 }
402 
403 // "as"       AS1 -> AS2 -> AS3
404 // "node"     A -> B -> {C, D} -> F
405 // "node"     [A -> B] -> [{C, D} -> F] -> [G -> H]
406 // "asnode"   AS30496:[A -> B] -> AS6079:[C -> {D,E}] -> AS1257:[F] -> AS11164:[G -> H] -> AS5050:[I] -> AS9:[J -> {K,L}]
407 
408 void
RaPrintPathNodes(struct RaPathNode * tree,int level,char * buf,int len)409 RaPrintPathNodes (struct RaPathNode *tree, int level, char *buf, int len)
410 {
411    struct RaPathNode *path = tree;
412    unsigned short as = 0;
413    int status = 0, shop = 0;
414 
415    while (path != NULL) {
416       struct ArgusQueueStruct *queue = path->nodes;
417       struct ArgusRecordStruct *argus = NULL;
418       int hopcount, multias = 0;
419 
420       if (status == 0) {
421          if (path->as != 0) {
422             if (path->as == -1) {
423                multias = 1;
424             } else {
425                as = path->as;
426 
427                if (RaPrintASNum) {
428                   sprintf (&buf[strlen(buf)], "AS%d", as);
429 
430                   if (RaPrintNode || RaPrintAddr)
431                      sprintf (&buf[strlen(buf)], ":[");
432 
433                } else
434                   sprintf (&buf[strlen(buf)], "[");
435 
436                status++;
437             }
438          }
439          shop = path->ttl;
440          hopcount = 0;
441       }
442 
443       if (queue->count > 1) {
444          if (RaPrintNode || RaPrintAddr) {
445             sprintf (&buf[strlen(buf)], "{");
446             while ((argus = (struct ArgusRecordStruct *) ArgusPopQueue(queue, ARGUS_NOLOCK)) != NULL) {
447                if (multias) {
448                   struct ArgusAsnStruct *asn = (void *)argus->dsrs[ARGUS_ASN_INDEX];
449                   if ((asn != NULL) && (asn->hdr.argus_dsrvl8.len > 2)) {
450                      if (RaPrintASNum) {
451                         if (asn->inode_as > 0) {
452                           sprintf (&buf[strlen(buf)], "AS%d", asn->inode_as);
453                         } else {
454                            sprintf (&buf[strlen(buf)], "%c", argus->autoid);
455                         }
456                      } else
457                         sprintf (&buf[strlen(buf)], ":[");
458                   }
459                }
460 
461                if (RaPrintAddr) {
462                   char inodeStr[256], *inodePtr = inodeStr;
463                   ArgusPrintInode (ArgusParser, inodeStr, argus, 256);
464                   while (*inodePtr == ' ') inodePtr++;
465                   while (inodePtr[strlen(inodePtr) - 1] == ' ') inodePtr[strlen(inodePtr) - 1] = '\0';
466                   sprintf (&buf[strlen(buf)], "%s", inodePtr);
467                } else
468                   sprintf (&buf[strlen(buf)], "%c", argus->autoid);
469 
470                if (multias) {
471                   sprintf (&buf[strlen(buf)], "]");
472                }
473 
474                if (queue->count > 0)
475                   sprintf (&buf[strlen(buf)], ", ");
476 
477                ArgusAddToQueue(ArgusModelerQueue, &argus->qhdr, ARGUS_LOCK);
478             }
479 
480             sprintf (&buf[strlen(buf)], "}");
481             if (RaPrintDistance) {
482                sprintf (&buf[strlen(buf)], ":%d", path->ttl);
483                shop = path->ttl;
484             }
485 
486             while ((argus = (struct ArgusRecordStruct *) ArgusPopQueue(ArgusModelerQueue, ARGUS_LOCK)) != NULL)
487                ArgusAddToQueue(queue, &argus->qhdr, ARGUS_NOLOCK);
488          }
489 
490       } else {
491          argus = (struct ArgusRecordStruct *) queue->start;
492 
493          if (RaPrintAddr) {
494             char inodeStr[256], *inodePtr = inodeStr;
495             ArgusPrintInode (ArgusParser, inodeStr, argus, 256);
496             while (*inodePtr == ' ') inodePtr++;
497             while (inodePtr[strlen(inodePtr) - 1] == ' ') inodePtr[strlen(inodePtr) - 1] = '\0';
498             sprintf (&buf[strlen(buf)], "%s", inodePtr);
499 
500          } else
501          if (RaPrintNode) {
502             sprintf (&buf[strlen(buf)], "%c", argus->autoid);
503          }
504 
505          if (RaPrintDistance) {
506             sprintf (&buf[strlen(buf)], ":%d", path->ttl);
507             shop = path->ttl;
508          }
509       }
510 
511       if ((path = path->nxt) != NULL) {
512          if (status) {
513             if (path->as != as) {
514                if (RaPrintNode || RaPrintAddr)
515                   sprintf (&buf[strlen(buf)], "]");
516 
517                if (RaPrintDistance) {
518                   if ((hopcount - shop) > 0) {
519                      sprintf (&buf[strlen(buf)], ":%d-%d", shop, hopcount);
520                      hopcount = 0;
521                   }
522                }
523 
524                sprintf (&buf[strlen(buf)], " -> ");
525                status--;
526                as = 0;
527 
528             } else {
529                if (RaPrintNode || RaPrintAddr)
530                   sprintf (&buf[strlen(buf)], " -> ");
531                hopcount = path->ttl;
532             }
533 
534          } else
535             if (RaPrintNode || RaPrintAddr)
536                sprintf (&buf[strlen(buf)], " -> ");
537 
538       } else {
539          if (status) {
540             if (RaPrintDistance) {
541                if ((hopcount - shop) > 0)
542                   sprintf (&buf[strlen(buf)], ":%d-%d", shop, hopcount);
543             }
544 
545             if (RaPrintNode || RaPrintAddr)
546                sprintf (&buf[strlen(buf)], "]");
547          }
548       }
549    }
550 }
551 
552 
553 void
RaPrintPath(struct RaPathNode * tree,char * buf,int len)554 RaPrintPath (struct RaPathNode *tree, char *buf, int len)
555 {
556    bzero (buf, len);
557    RaPrintPathNodes(tree, 0, buf, len);
558 }
559 
560 
RaArgusInputComplete(struct ArgusInput * input)561 void RaArgusInputComplete (struct ArgusInput *input) { return; }
562 
563 
564 int RaParseCompleting = 0;
565 struct RaPathTree *RaTreeNode = NULL;
566 
567 void
RaParseComplete(int sig)568 RaParseComplete (int sig)
569 {
570    struct ArgusModeStruct *mode = NULL;
571    int i = 0, x = 0, nflag = ArgusParser->eNflag;
572 
573    if (sig >= 0) {
574       if (!(ArgusParser->RaParseCompleting++)) {
575          struct ArgusAggregatorStruct *agg = ArgusParser->ArgusAggregator;
576 
577          ArgusParser->RaParseCompleting += sig;
578 
579          if (agg != NULL) {
580             if (agg->queue->count) {
581                struct ArgusRecordStruct *tns = NULL, *cns = NULL;
582 
583                if (!(ArgusSorter)) {
584                   if ((ArgusSorter = ArgusNewSorter(ArgusParser)) == NULL)
585                      ArgusLog (LOG_ERR, "RaParseComplete: ArgusNewSorter error %s", strerror(errno));
586 
587                   if ((mode = ArgusParser->ArgusMaskList) != NULL) {
588                      while (mode) {
589                         for (x = 0; x < MAX_SORT_ALG_TYPES; x++) {
590                            if (!strncmp (ArgusSortKeyWords[x], mode->mode, strlen(ArgusSortKeyWords[x]))) {
591                               ArgusSorter->ArgusSortAlgorithms[i++] = ArgusSortAlgorithmTable[x];
592                               break;
593                            }
594                         }
595 
596                         mode = mode->nxt;
597                      }
598                   }
599                }
600 
601                ArgusSortQueue (ArgusSorter, agg->queue);
602                if (nflag == 0)
603                   ArgusParser->eNflag = agg->queue->count;
604                else
605                   ArgusParser->eNflag = nflag > agg->queue->count ? agg->queue->count : nflag;
606 
607                for (i = 0; i < ArgusParser->eNflag; i++) {
608                   tns = (struct ArgusRecordStruct *) agg->queue->array[i];
609 
610                   if (tns->agg != NULL) {
611                      int count = tns->agg->queue->count;
612                      char nodeChar = 'A';
613 
614                      ArgusSortQueue (ArgusSorter, tns->agg->queue);
615 
616                      for (x = 0; x < count; x++) {
617                         cns = (struct ArgusRecordStruct *) tns->agg->queue->array[x];
618                         cns->autoid = nodeChar;
619                         nodeChar = ((nodeChar == 'Z') ? 'a' : nodeChar + 1);
620                      }
621 
622                      if (ArgusParser->Aflag) {
623                         struct RaPathNode *path = RaPathBuildPath (tns->agg->queue);
624                         char RaTreeBuffer[MAXSTRLEN];
625 
626                         if (path) {
627                            char srcId[32], srcAddr[32], dstAddr[32];
628 
629                            if (RaPrintTreeNode)
630                               RaPathInsertTree(RaTreeNode, path);
631 
632                            cns = (struct ArgusRecordStruct *) tns->agg->queue->array[0];
633 
634                            bzero(srcId,   sizeof(srcId));
635                            bzero(srcAddr, sizeof(srcAddr));
636                            bzero(dstAddr, sizeof(dstAddr));
637 
638                            ArgusPrintSourceID (ArgusParser,  srcId, cns, 0);
639                            ArgusPrintSrcAddr (ArgusParser, srcAddr, cns, 0);
640                            ArgusPrintDstAddr (ArgusParser, dstAddr, cns, 0);
641 
642                            RaPrintPath (path, RaTreeBuffer, sizeof(RaTreeBuffer));
643 
644                            srcId[strlen(srcId) - 1] = '\0';
645                            srcAddr[strlen(srcAddr) - 1] = '\0';
646                            dstAddr[strlen(dstAddr) - 1] = '\0';
647 
648                            printf("%s(%s::%s) %s\n", srcId, srcAddr, dstAddr, RaTreeBuffer);
649                            RaPathDeletePath(path);
650                         }
651                      }
652 
653                      for (x = 0; x < count; x++) {
654                         cns = (struct ArgusRecordStruct *) tns->agg->queue->array[x];
655                         RaSendArgusRecord (cns);
656                      }
657                      if (!(ArgusParser->qflag))
658                         printf ("\n");
659                   }
660                }
661                ArgusFree(ArgusParser->ns);
662             }
663          }
664 
665          ArgusDeleteAggregator(ArgusParser, ArgusFlowAggregator);
666          ArgusDeleteHashTable(ArgusHashTable);
667          ArgusDeleteSorter(ArgusSorter);
668          ArgusDeleteQueue(ArgusModelerQueue);
669 
670          if (RaMapAddrTable.array != NULL) {
671             ArgusFree (RaMapAddrTable.array);
672             RaMapAddrTable.array =  NULL;
673          }
674 
675 #ifdef ARGUSDEBUG
676          ArgusDebug (2, "RaParseComplete(caught signal %d)\n", sig);
677 #endif
678          switch (sig) {
679             case SIGHUP:
680             case SIGINT:
681             case SIGTERM:
682             case SIGQUIT: {
683                struct ArgusWfileStruct *wfile = NULL;
684 
685                ArgusShutDown(sig);
686 
687                if (ArgusParser->ArgusWfileList != NULL) {
688                   struct ArgusListObjectStruct *lobj = NULL;
689                   int i, count = ArgusParser->ArgusWfileList->count;
690 
691                   if ((lobj = ArgusParser->ArgusWfileList->start) != NULL) {
692                      for (i = 0; i < count; i++) {
693                         if ((wfile = (struct ArgusWfileStruct *) lobj) != NULL) {
694                            if (wfile->fd != NULL) {
695 #ifdef ARGUSDEBUG
696                               ArgusDebug (2, "RaParseComplete: closing %s\n", wfile->filename);
697 #endif
698                               fflush (wfile->fd);
699                               fclose (wfile->fd);
700                               wfile->fd = NULL;
701                            }
702                         }
703                         lobj = lobj->nxt;
704                      }
705                   }
706                }
707                exit(0);
708                break;
709             }
710          }
711       }
712    }
713 
714    ArgusParser->eNflag = nflag;
715 
716 #ifdef ARGUSDEBUG
717    ArgusDebug (6, "RaParseComplete(%d) done", sig);
718 #endif
719 }
720 
721 void
usage()722 usage ()
723 {
724    extern char version[];
725 
726    fprintf (stdout, "Rapath Version %s\n", version);
727    fprintf (stdout, "usage:  %s \n", ArgusParser->ArgusProgramName);
728    fprintf (stdout, "usage:  %s [-f ralabel.conf] [ra-options] [- filter-expression]\n\n", ArgusParser->ArgusProgramName);
729 
730 
731    fprintf (stdout, "options:  -f <racluster.conf>  read label rules from <ralabel.conf>.\n");
732    fprintf (stdout, "          -A                   print path graph\n");
733 #ifdef ARGUSDEBUG
734    fprintf (stdout, "          -D <level>           specify debug level\n");
735 #endif
736    fprintf (stdout, "          -q                   quiet mode.  Supress printing records.\n");
737    fprintf (stdout, "          -m flow key fields   modify the flow model for path data.\n");
738    fprintf (stdout, "          -M <option>          specify a Mode of operation.\n");
739    fprintf (stdout, "             Available modes:      \n");
740    fprintf (stdout, "               as              print path with AS information\n");
741    fprintf (stdout, "               addr            print path as list of addresses\n");
742    fprintf (stdout, "               node            print path as list of nodes\n");
743    fprintf (stdout, "               dist            print path with hop counts\n");
744    fprintf (stdout, "               tree            print path tree\n");
745 
746    fflush (stdout);
747 
748    exit(1);
749 }
750 
751 void RaProcessThisRecord (struct ArgusParserStruct *, struct ArgusRecordStruct *);
752 void RaPrintArgusPath (struct ArgusRecordStruct *);
753 
754 void
RaProcessRecord(struct ArgusParserStruct * parser,struct ArgusRecordStruct * ns)755 RaProcessRecord (struct ArgusParserStruct *parser, struct ArgusRecordStruct *ns)
756 {
757    struct ArgusFlow *flow = (struct ArgusFlow *) ns->dsrs[ARGUS_FLOW_INDEX];
758    struct ArgusIcmpStruct *icmp = NULL;
759 
760    switch (ns->hdr.type & 0xF0) {
761       case ARGUS_MAR:
762       case ARGUS_EVENT: {
763          break;
764       }
765 
766       case ARGUS_NETFLOW:
767       case ARGUS_FAR: {
768          if (flow != NULL) {
769             switch (flow->hdr.subtype & 0x3F) {
770                case ARGUS_FLOW_LAYER_3_MATRIX:
771                case ARGUS_FLOW_CLASSIC5TUPLE: {
772                   switch (flow->hdr.argus_dsrvl8.qual & 0x1F) {
773                      case ARGUS_TYPE_IPV4: {
774                         if (flow->ip_flow.ip_src > flow->ip_flow.ip_dst) {
775                         }
776                         break;
777                      }
778 
779                      case ARGUS_TYPE_IPV6: {
780                         int i;
781                         for (i = 0; i < 4; i++) {
782                            if (flow->ipv6_flow.ip_src[i] < flow->ipv6_flow.ip_dst[i])
783                               break;
784 
785                            if (flow->ipv6_flow.ip_src[i] > flow->ipv6_flow.ip_dst[i]) {
786                               break;
787                            }
788                         }
789                         break;
790                      }
791                   }
792                   break;
793                }
794                default:
795                   return;
796                   break;
797             }
798 
799             if ((icmp = (struct ArgusIcmpStruct *) ns->dsrs[ARGUS_ICMP_INDEX]) != NULL) {
800                if ((icmp->hdr.argus_dsrvl8.qual & ARGUS_ICMPUNREACH_MAPPED) ||
801                    (icmp->hdr.argus_dsrvl8.qual & ARGUS_ICMPTIMXCED_MAPPED)) {
802 
803                   unsigned int srchost, dsthost, intnode;
804 
805                   srchost = flow->ip_flow.ip_src;
806                   dsthost = flow->ip_flow.ip_dst;
807 
808                   intnode = icmp->osrcaddr;
809 
810                   if ((intnode == srchost) || (intnode == dsthost))
811                      return;
812                }
813 
814                switch (flow->ip_flow.ip_p) {
815                   case IPPROTO_UDP:
816                   case IPPROTO_TCP:
817                      break;
818 
819                   case IPPROTO_ICMP:
820                      break;
821 
822                   default:
823                      break;
824                }
825 
826                RaProcessThisRecord (parser, ns);
827             }
828          }
829          break;
830       }
831    }
832 }
833 
834 
835 void RaUpdateArgusStorePath(struct ArgusRecord *, struct ArgusRecordStruct *);
836 struct ArgusRecordStruct *RaProcessAggregation(struct ArgusParserStruct *, struct ArgusAggregatorStruct *, struct ArgusRecordStruct *);
837 
838 struct ArgusRecordStruct *
RaProcessAggregation(struct ArgusParserStruct * parser,struct ArgusAggregatorStruct * agg,struct ArgusRecordStruct * ns)839 RaProcessAggregation(struct ArgusParserStruct *parser, struct ArgusAggregatorStruct *agg, struct ArgusRecordStruct *ns)
840 {
841    struct ArgusHashStruct *hstruct = NULL;
842    struct ArgusRecordStruct *retn = NULL;
843 
844    if ((agg->rap = RaFlowModelOverRides(agg, ns)) == NULL)
845       agg->rap = agg->drap;
846 
847    ArgusGenerateNewFlow(agg, ns);
848 
849    if ((hstruct = ArgusGenerateHashStruct(agg, ns, (struct ArgusFlow *)&agg->fstruct)) == NULL)
850       ArgusLog (LOG_ERR, "RaProcessThisRecord: ArgusGenerateHashStruct error %s", strerror(errno));
851 
852    if ((retn = ArgusFindRecord(agg->htable, hstruct)) != NULL) {
853       if (parser->Aflag) {
854          if ((retn->status & RA_SVCTEST) != (ns->status & RA_SVCTEST)) {
855             RaSendArgusRecord(retn);
856             ArgusZeroRecord(retn);
857             retn->status &= ~(RA_SVCTEST);
858             retn->status |= (ns->status & RA_SVCTEST);
859          }
860       }
861       ArgusMergeRecords (agg, retn, ns);
862 
863    } else {
864       if (!parser->RaMonMode) {
865          struct ArgusFlow *flow = (struct ArgusFlow *) ns->dsrs[ARGUS_FLOW_INDEX];
866          int tryreverse = 1;
867 
868          if (flow != NULL) {
869             switch (flow->hdr.argus_dsrvl8.qual & 0x1F) {
870                case ARGUS_TYPE_IPV4: {
871                   switch (flow->ip_flow.ip_p) {
872                      case IPPROTO_ESP:
873                         tryreverse = 0;
874                         break;
875                   }
876                }
877             }
878          }
879 
880          if (tryreverse) {
881             if ((hstruct = ArgusGenerateReverseHashStruct(agg, ns, (struct ArgusFlow *)&agg->fstruct)) == NULL)
882                ArgusLog (LOG_ERR, "RaProcessThisRecord: ArgusGenerateHashStruct error %s", strerror(errno));
883 
884             if ((retn = ArgusFindRecord(agg->htable, hstruct)) == NULL) {
885                if ((hstruct = ArgusGenerateHashStruct(agg, ns, (struct ArgusFlow *)&agg->fstruct)) == NULL)
886                   ArgusLog (LOG_ERR, "RaProcessThisRecord: ArgusGenerateHashStruct error %s", strerror(errno));
887 
888             } else {
889                ArgusReverseRecord (ns);
890             }
891          }
892       }
893 
894       if (retn != NULL) {
895          if (parser->Aflag) {
896             if ((retn->status & RA_SVCTEST) != (ns->status & RA_SVCTEST)) {
897                RaSendArgusRecord(retn);
898                ArgusZeroRecord(retn);
899             }
900             retn->status &= ~(RA_SVCTEST);
901             retn->status |= (ns->status & RA_SVCTEST);
902          } else
903             ArgusMergeRecords (agg, retn, ns);
904 
905       } else {
906          retn = ArgusCopyRecordStruct(ns);
907          ArgusAddHashEntry (agg->htable, retn, hstruct);
908          ArgusAddToQueue (agg->queue, &retn->qhdr, ARGUS_NOLOCK);
909       }
910    }
911 
912    return retn;
913 }
914 
915 void
RaProcessThisRecord(struct ArgusParserStruct * parser,struct ArgusRecordStruct * ns)916 RaProcessThisRecord (struct ArgusParserStruct *parser, struct ArgusRecordStruct *ns)
917 {
918    struct ArgusAggregatorStruct *agg  = parser->ArgusAggregator;
919    struct ArgusRecordStruct *tns, *cns;
920    int retn = 0;
921 
922    struct nff_insn *fcode = agg->filter.bf_insns;
923 
924    if ((retn = ArgusFilterRecord (fcode, ns)) != 0) {
925       if ((cns = ArgusCopyRecordStruct(ns)) == NULL)
926          ArgusLog (LOG_ERR, "RaProcessThisRecord: ArgusCopyRecordStruct error %s", strerror(errno));
927 
928       ArgusLabelRecord(parser, cns);
929 
930       if ((tns = RaProcessAggregation(parser, agg, cns)) != NULL) {
931          if (tns->agg == NULL)
932             if ((tns->agg = ArgusCopyAggregator(ArgusFlowAggregator)) == NULL)
933                ArgusLog (LOG_ERR, "RaProcessThisRecod: ArgusCopyAggregator error");
934 
935          if (tns != NULL)
936             RaProcessAggregation(parser, tns->agg, cns);
937       }
938 
939       ArgusDeleteRecordStruct(parser, cns);
940    }
941 }
942 
943 
944 int
RaSendArgusRecord(struct ArgusRecordStruct * argus)945 RaSendArgusRecord(struct ArgusRecordStruct *argus)
946 {
947    struct ArgusRecord *argusrec = NULL;
948    char buf[0x10000], argusbuf[0x10000];
949    int retn = 1;
950 
951    if (argus->status & ARGUS_RECORD_WRITTEN)
952       return (retn);
953 
954    if (ArgusParser->RaAgMode)
955       argus->dsrs[ARGUS_AGR_INDEX] = NULL;
956 
957    if ((argusrec = ArgusGenerateRecord (argus, 0L, argusbuf)) != NULL) {
958 #ifdef _LITTLE_ENDIAN
959       ArgusHtoN(argusrec);
960 #endif
961       if (ArgusParser->ArgusWfileList != NULL) {
962          struct ArgusWfileStruct *wfile = NULL;
963          struct ArgusListObjectStruct *lobj = NULL;
964          int i, count = ArgusParser->ArgusWfileList->count;
965 
966          if ((lobj = ArgusParser->ArgusWfileList->start) != NULL) {
967             for (i = 0; i < count; i++) {
968                if ((wfile = (struct ArgusWfileStruct *) lobj) != NULL) {
969                   int pass = 1;
970                   if (wfile->filterstr) {
971                      struct nff_insn *wfcode = wfile->filter.bf_insns;
972                      pass = ArgusFilterRecord (wfcode, argus);
973                   }
974 
975                   if (pass != 0) {
976                      if ((ArgusParser->exceptfile == NULL) || strcmp(wfile->filename, ArgusParser->exceptfile)) {
977                         ArgusWriteNewLogfile (ArgusParser, argus->input, wfile, argusrec);
978                      }
979                   }
980                }
981                lobj = lobj->nxt;
982             }
983          }
984 
985       } else {
986          if (!ArgusParser->qflag) {
987             if (ArgusParser->Lflag) {
988                if (ArgusParser->RaLabel == NULL)
989                   ArgusParser->RaLabel = ArgusGenerateLabel(ArgusParser, argus);
990 
991                if (!(ArgusParser->RaLabelCounter++ % ArgusParser->Lflag)) {
992                   if (ArgusParser->Aflag && (!(RaPrintAddr)))
993                      printf (" Node %s\n", ArgusParser->RaLabel);
994                   else
995                      printf ("%s\n", ArgusParser->RaLabel);
996                }
997 
998                if (ArgusParser->Lflag < 0)
999                   ArgusParser->Lflag = 0;
1000             }
1001 
1002             *(int *)&buf = 0;
1003             ArgusPrintRecord(ArgusParser, buf, argus, MAXSTRLEN);
1004 
1005             if (ArgusParser->Aflag && (!(RaPrintAddr))) {
1006                int ret = fprintf (stdout, "  %c   %s\n", argus->autoid, buf);
1007                if (ret < 0)
1008                   RaParseComplete(SIGQUIT);
1009             } else
1010                if (fprintf (stdout, "%s\n", buf) < 0)
1011                   RaParseComplete(SIGQUIT);
1012             fflush(stdout);
1013          }
1014       }
1015    }
1016 
1017    argus->status |= ARGUS_RECORD_WRITTEN;
1018    return (retn);
1019 }
1020 
ArgusWindowClose(void)1021 void ArgusWindowClose(void) { }
1022