1 /*
2  * Argus Software.  Argus files - Modeler
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  * Written by Carter Bullard
21  * QoSient, LLC
22  *
23  */
24 
25 /*
26  * $Id: //depot/argus/argus/argus/ArgusOutput.c#81 $
27  * $DateTime: 2015/04/06 10:38:44 $
28  * $Change: 2973 $
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "argus_config.h"
33 #endif
34 
35 #if !defined(ArgusOutput)
36 #define ArgusOutput
37 #endif
38 
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <math.h>
44 
45 #if defined(HAVE_ZLIB_H)
46 #include <zlib.h>
47 #endif
48 
49 #include <argus.h>
50 #include <argus_parser.h>
51 #include <argus_filter.h>
52 
53 #if defined(ARGUS_THREADS)
54 #include <pthread.h>
55 #endif
56 
57 void *ArgusOutputProcess(void *);
58 
59 #if defined(ARGUS_TILERA)
60 extern int ArgusFirstTile;
61 #endif
62 
63 struct timeval *getArgusMarReportInterval(struct ArgusOutputStruct *);
64 void setArgusMarReportInterval(struct ArgusOutputStruct *, char *);
65 
66 struct ArgusRecord *ArgusGenerateInitialMar (struct ArgusOutputStruct *);
67 struct ArgusRecordStruct *ArgusGenerateSupplementalMarRecord (struct ArgusOutputStruct *, unsigned char);
68 struct ArgusRecordStruct *ArgusGenerateStatusMarRecord (struct ArgusOutputStruct *, unsigned char);
69 
70 int RaDiffTime (struct timeval *, struct timeval *, struct timeval *);
71 
72 struct ArgusOutputStruct *
ArgusNewOutput(struct ArgusSourceStruct * src,struct ArgusModelerStruct * model)73 ArgusNewOutput (struct ArgusSourceStruct *src, struct ArgusModelerStruct *model)
74 {
75    struct ArgusOutputStruct *retn = NULL;
76 
77    if ((retn = (struct ArgusOutputStruct *) ArgusCalloc (1, sizeof (struct ArgusOutputStruct))) == NULL)
78      ArgusLog (LOG_ERR, "ArgusNewOutput() ArgusCalloc error %s\n", strerror(errno));
79 
80    gettimeofday (&retn->ArgusGlobalTime, 0L);
81 #if defined(ARGUS_NANOSECONDS)
82    retn->ArgusGlobalTime.tv_usec *= 1000;
83 #endif
84    retn->ArgusStartTime = retn->ArgusGlobalTime;
85 
86    retn->ArgusReportTime.tv_sec   = retn->ArgusGlobalTime.tv_sec + retn->ArgusMarReportInterval.tv_sec;
87    retn->ArgusReportTime.tv_usec += retn->ArgusMarReportInterval.tv_usec;
88    retn->ArgusLastMarUpdateTime   = retn->ArgusGlobalTime;
89 
90    if ((retn->ArgusClients = ArgusNewQueue()) == NULL)
91       ArgusLog (LOG_ERR, "ArgusNewOutput: clients queue %s", strerror(errno));
92 
93    if ((retn->ArgusOutputList = ArgusNewList()) == NULL)
94       ArgusLog (LOG_ERR, "ArgusNewOutput: ArgusNewList %s", strerror(errno));
95 
96    if ((retn->ArgusInputList = ArgusNewList()) == NULL)
97       ArgusLog (LOG_ERR, "ArgusNewOutput: ArgusNewList %s", strerror(errno));
98 
99    retn->ArgusSrc   = src;
100    retn->ArgusModel = model;
101 
102 #if defined(ARGUS_THREADS)
103    pthread_mutex_init(&retn->lock, NULL);
104 #endif
105 
106 #ifdef ARGUSDEBUG
107    ArgusDebug (1, "ArgusNewOutput() returning retn %p\n", retn);
108 #endif
109 
110    return (retn);
111 }
112 
113 
114 #ifdef ARGUS_SASL
115 int iptostring(const struct sockaddr *, socklen_t, char *, unsigned);
116 
117 static int
ArgusSaslLog(void * context,int priority,const char * message)118 ArgusSaslLog (void *context __attribute__((unused)), int priority, const char *message)
119 {
120   const char *label;
121 
122   if (! message)
123     return SASL_BADPARAM;
124 
125   switch (priority) {
126      case SASL_LOG_ERR:  label = "Error"; break;
127      case SASL_LOG_NOTE: label = "Info"; break;
128      default:            label = "Other"; break;
129   }
130 
131 #ifdef ARGUSDEBUG
132   ArgusDebug(1, "ArgusSaslLog %s: %s", label, message);
133 #endif
134 
135   return SASL_OK;
136 }
137 
138 //#ifdef _LP64
139 //#define PLUGINDIR "/usr/lib64/sasl2"
140 //#else
141 
142 #define PLUGINDIR "/usr/local/lib/sasl2"
143 
144 //#endif
145 
146 
147 char *searchpath = NULL;
148 
149 static int
ArgusSaslGetPath(void * context,char ** path)150 ArgusSaslGetPath(void *context __attribute__((unused)), char ** path)
151 {
152   if (! path)
153     return SASL_BADPARAM;
154   if (searchpath)
155     *path = searchpath;
156    else
157     *path = PLUGINDIR;
158 
159 #ifdef ARGUSDEBUG
160   ArgusDebug(2, "SASL path %s", *path);
161 #endif
162 
163   return SASL_OK;
164 }
165 
166 //typedef struct sasl_callback {
167 //    /* Identifies the type of the callback function.
168 //     * Mechanisms must ignore callbacks with id's they don't recognize.
169 //     */
170 //    unsigned long id;
171 //    int (*proc)(void);   /* Callback function.  Types of arguments vary by 'id' */
172 //    void *context;
173 //} sasl_callback_t;
174 
175 typedef int (*funcptr)();
176 
177 static const struct sasl_callback argus_cb[] = {
178     { SASL_CB_LOG, (funcptr)&ArgusSaslLog, NULL },
179     { SASL_CB_LIST_END, NULL, NULL }
180 };
181 #endif
182 
183 void
ArgusInitOutput(struct ArgusOutputStruct * output)184 ArgusInitOutput (struct ArgusOutputStruct *output)
185 {
186    struct ArgusWfileStruct *wfile;
187    extern char *chroot_dir;
188    extern uid_t new_uid;
189    extern gid_t new_gid;
190    int i, len = 0, retn = 0;
191 
192 #if defined(ARGUS_THREADS)
193    extern pthread_attr_t *ArgusAttr;
194 #endif
195 
196    ArgusParser = ArgusNewParser(ArgusProgramName);
197 
198    if (output->ArgusInitMar != NULL)
199       ArgusFree (output->ArgusInitMar);
200 
201    if ((output->ArgusInitMar = ArgusGenerateInitialMar(output)) == NULL)
202       ArgusLog (LOG_ERR, "ArgusInitOutput: ArgusGenerateInitialMar error %s", strerror(errno));
203 
204    len = ntohs(output->ArgusInitMar->hdr.len) * 4;
205 
206    for (i = 0; i < ARGUS_MAXLISTEN; i++)
207       output->ArgusLfd[i] = -1;
208 
209    if (output->ArgusPortNum != 0) {
210       char errbuf[256];
211       if (ArgusEstablishListen (output, errbuf) < 0)
212          ArgusLog (LOG_ERR, "%s", errbuf);
213    }
214 
215    if (chroot_dir != NULL)
216       ArgusSetChroot(chroot_dir);
217 
218    if (new_gid > 0) {
219       if (setegid(new_gid) < 0)
220          ArgusLog (LOG_ERR, "ArgusInitOutput: setgid error %s", strerror(errno));
221    }
222    if (new_uid > 0) {
223       if (seteuid(new_uid) < 0)
224          ArgusLog (LOG_ERR, "ArgusInitOutput: setuid error %s", strerror(errno));
225    }
226 
227    if (output->ArgusWfileList) {
228       struct ArgusListRecord *sfile= output->ArgusWfileList->start->obj;
229       do {
230          if ((wfile = (struct ArgusWfileStruct *) ArgusPopFrontList(output->ArgusWfileList, ARGUS_LOCK)) != NULL) {
231             struct ArgusClientData *client = (void *) ArgusCalloc (1, sizeof(struct ArgusClientData));
232 
233             if (client == NULL)
234                ArgusLog (LOG_ERR, "ArgusInitOutput: ArgusCalloc %s", strerror(errno));
235 
236             if (strcmp (wfile->filename, "-")) {
237                if ((!(strncmp (wfile->filename, "argus-udp://", 12))) ||
238                    (!(strncmp (wfile->filename, "udp://", 6)))) {
239 
240                   char *baddr = strstr (wfile->filename, "udp://");
241                   baddr = &baddr[6];
242 
243 #if defined(HAVE_GETADDRINFO)
244                   struct addrinfo hints, *hp = NULL, *bhp = NULL;
245                   int retn = 0, numerichost = 1;
246                   char *port, *ptr;
247 
248                   if ((port = strchr(baddr, ':')) != NULL) {
249                      *port++ = '\0';
250                   } else {
251                      port = "561";
252                   }
253 
254                   if (output->ArgusBindAddrs || output->ArgusBindPort) {
255                      char *ArgusBindAddr = NULL;
256 
257                      memset(&hints, 0, sizeof(hints));
258                      hints.ai_family   = AF_INET;
259                      hints.ai_socktype = SOCK_DGRAM;
260                      hints.ai_protocol = IPPROTO_UDP;
261                      hints.ai_flags   |= AI_PASSIVE;
262 
263                      if (ArgusBindAddr && (!strcmp(ArgusBindAddr, "any")))
264                         ArgusBindAddr = NULL;
265                      getaddrinfo(ArgusBindAddr, output->ArgusBindPort, NULL, &bhp);
266                   }
267 
268                   memset(&hints, 0, sizeof(hints));
269                   hints.ai_family   = AF_INET;
270                   hints.ai_socktype = SOCK_DGRAM;
271                   hints.ai_protocol = IPPROTO_UDP;
272 
273                   for (ptr = port; *ptr != '\0'; ptr++) {
274                      int c = *ptr;
275                      if (!isdigit(c))
276                         numerichost = 0;
277                   }
278 #if defined(AI_NUMERICHOST)
279                   if (numerichost)
280                      hints.ai_flags |= AI_NUMERICHOST;
281 #endif
282                   if ((retn = getaddrinfo(baddr, port, &hints, &client->host)) != 0) {
283                      switch (retn) {
284                         case EAI_AGAIN:
285                            ArgusLog(LOG_ERR, "dns server not available");
286                            break;
287                         case EAI_NONAME:
288                            ArgusLog(LOG_ERR, "bind address %s unknown", optarg);
289                            break;
290 #if defined(EAI_ADDRFAMILY)
291                         case EAI_ADDRFAMILY:
292                            ArgusLog(LOG_ERR, "bind address %s has no IP address", optarg);
293                            break;
294 #endif
295                         case EAI_SYSTEM:
296                            ArgusLog(LOG_ERR, "bind address %s name server error %s", optarg, strerror(errno));
297                            break;
298                      }
299                   }
300 
301                   hp = client->host;
302 
303                   do {
304                      if ((client->fd = socket (hp->ai_family, hp->ai_socktype, hp->ai_protocol)) >= 0) {
305                         unsigned char ttl = 128;
306                         int ttl_size = sizeof(ttl);
307 
308                         if (setsockopt(client->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, ttl_size) < 0)
309                            ArgusLog (LOG_INFO, "ArgusInitOutput: setsockopt set multicast TTL: %s", strerror(errno));
310 
311                         if (bhp != NULL) {
312 #if defined(SO_REUSEPORT)
313                            int on = 1;
314 #endif
315                            if (bind (client->fd, bhp->ai_addr, sizeof(struct sockaddr_in)) < 0)
316                               ArgusLog (LOG_ERR, "ArgusInitOutput: bind %s", strerror(errno));
317 #if defined(SO_REUSEPORT)
318                            if (setsockopt(client->fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
319                               ArgusLog (LOG_INFO, "ArgusInitOutput: setsockopt set reuseport %s", strerror(errno));
320 #endif
321                         }
322 
323                      } else
324                         ArgusLog (LOG_ERR, "ArgusInitOutput: socket %s: %s", wfile->filename, strerror(errno));
325                      hp = hp->ai_next;
326                   } while (hp != NULL);
327 #endif
328                } else
329                   if ((client->fd = open (wfile->filename, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK, 0x1a4)) < 0)
330                      ArgusLog (LOG_ERR, "ArgusInitOutput: open %s: %s", wfile->filename, strerror(errno));
331             } else {
332                client->fd = 1;
333                output->ArgusWriteStdOut++;
334             }
335 
336             if (wfile->filter != NULL) {
337                if (ArgusFilterCompile (&client->ArgusNFFcode, wfile->filter, 1) < 0)
338                   ArgusLog (LOG_ERR, "ArgusInitOutput: ArgusFilter syntax error: %s", wfile->filter);
339                client->ArgusFilterInitialized++;
340 #ifdef ARGUSDEBUG
341                {
342                   char buf[MAXSTRLEN];
343                   bzero(buf, MAXSTRLEN);
344                   nff_dump(&client->ArgusNFFcode, buf, MAXSTRLEN, 1);
345                   ArgusDebug (5, "ArgusInitOutput: ArgusFilterCompile returned: \n%s\n", buf);
346                }
347 #endif
348             }
349 
350             if ((client->sock = ArgusNewSocket(client->fd)) == NULL)
351                ArgusLog (LOG_ERR, "ArgusInitOutput: ArgusNewSocket error %s", strerror(errno));
352 
353             if (client->host != NULL) {
354                if ((retn = sendto(client->fd, (char *) output->ArgusInitMar, len, 0, client->host->ai_addr, client->host->ai_addrlen)) < 0)
355                   ArgusLog (LOG_ERR, "ArgusInitOutput: sendto(): retn %d %s", retn, strerror(errno));
356 
357             } else {
358                while ((retn = write (client->fd, (char *) output->ArgusInitMar, len)) != len) {
359                   if (!output->ArgusWriteStdOut) {
360                      close (client->fd);
361                      unlink (wfile->filename);
362                   }
363                   ArgusLog (LOG_ERR, "ArgusInitOutput: write(): retn %d %s", retn, strerror(errno));
364                }
365             }
366 
367             if (strcmp(wfile->filename, "/dev/null"))
368                client->sock->filename = strdup(wfile->filename);
369 
370             ArgusAddToQueue(output->ArgusClients, &client->qhdr, ARGUS_LOCK);
371 
372             client->ArgusClientStart++;
373             ArgusPushBackList (output->ArgusWfileList, (struct ArgusListRecord *) wfile, ARGUS_LOCK);
374          }
375       } while (output->ArgusWfileList->start->obj != sfile);
376 
377       ArgusDeleteList(output->ArgusWfileList, ARGUS_WFILE_LIST);
378       output->ArgusWfileList = NULL;
379    }
380 
381    if (new_gid > 0)
382       if (setegid(ArgusGid) < 0)
383          ArgusLog (LOG_ERR, "ArgusInitOutput: setgid error %s", strerror(errno));
384 
385    if (new_uid > 0)
386       if (seteuid(ArgusUid) < 0)
387          ArgusLog (LOG_ERR, "ArgusInitOutput: setuid error %s", strerror(errno));
388 
389 #ifdef ARGUS_SASL
390    if ((retn = sasl_server_init(argus_cb, ArgusProgramName)) != SASL_OK)
391       ArgusLog (LOG_ERR, "ArgusInitOutput() sasl_server_init failed %d\n", retn);
392 #endif /* ARGUS_SASL */
393 
394 #if defined(ARGUS_THREADS)
395    if ((pthread_create(&output->thread, ArgusAttr, ArgusOutputProcess, (void *) output)) != 0)
396       ArgusLog (LOG_ERR, "ArgusInitOutput() pthread_create error %s\n", strerror(errno));
397 
398 #endif /* ARGUS_THREADS */
399 
400 #ifdef ARGUSDEBUG
401    ArgusDebug (1, "ArgusInitOutput() done");
402 #endif
403 }
404 
405 
406 void
ArgusCloseOutput(struct ArgusOutputStruct * output)407 ArgusCloseOutput(struct ArgusOutputStruct *output)
408 {
409 #if defined(ARGUS_THREADS)
410    void *retn = NULL;
411 
412 #ifdef ARGUSDEBUG
413    ArgusDebug (1, "ArgusCloseOutput(%p) scheduling closure after %d records\n", output, output->ArgusInputList->count);
414 #endif
415    if ((output != NULL) && (output->thread != 0)) {
416       output->status |= ARGUS_SHUTDOWN;
417       if (output->thread)
418          pthread_join(output->thread, &retn);
419    } else {
420 #ifdef ARGUSDEBUG
421       ArgusDebug (4, "ArgusCloseOutput(%p) no output or output->thread available\n", output);
422 #endif
423    }
424 #else
425    if (output != NULL) {
426       output->status |= ARGUS_SHUTDOWN;
427 #ifdef ARGUSDEBUG
428       ArgusDebug (2, "ArgusCloseOutput(%p) scheduling closure after writing records\n", output);
429 #endif
430       ArgusOutputProcess(output);
431    }
432 #endif /* ARGUS_THREADS */
433 
434    ArgusDeleteList(output->ArgusInputList, ARGUS_OUTPUT_LIST);
435    ArgusDeleteList(output->ArgusOutputList, ARGUS_OUTPUT_LIST);
436 
437    ArgusDeleteQueue(output->ArgusClients);
438 
439    if (output->ArgusInitMar != NULL)
440       ArgusFree (output->ArgusInitMar);
441 
442    if (ArgusParser != NULL) {
443       ArgusCloseParser(ArgusParser);
444       ArgusFree(ArgusParser);
445       ArgusParser = NULL;
446    }
447 
448 #ifdef ARGUSDEBUG
449    ArgusDebug (1, "ArgusCloseOutput(%p) done\n", output);
450 #endif
451 }
452 
453 
454 void ArgusCheckClientStatus (struct ArgusOutputStruct *, int);
455 int ArgusCheckClientMessage (struct ArgusOutputStruct *, struct ArgusClientData *);
456 int ArgusCongested = 0;
457 
458 int ArgusOutputStatusTime(struct ArgusOutputStruct *);
459 
460 int
ArgusOutputStatusTime(struct ArgusOutputStruct * output)461 ArgusOutputStatusTime(struct ArgusOutputStruct *output)
462 {
463    int retn = 0;
464 
465 
466    if ((output->ArgusReportTime.tv_sec  < output->ArgusGlobalTime.tv_sec) ||
467       ((output->ArgusReportTime.tv_sec == output->ArgusGlobalTime.tv_sec) &&
468        (output->ArgusReportTime.tv_usec < output->ArgusGlobalTime.tv_usec))) {
469 
470       long long dtime = ArgusTimeDiff(&output->ArgusGlobalTime, &output->ArgusReportTime);
471 
472       if (dtime > 1000000)
473          output->ArgusReportTime  = output->ArgusGlobalTime;
474 
475       output->ArgusReportTime.tv_sec  += getArgusMarReportInterval(output)->tv_sec;
476       output->ArgusReportTime.tv_usec += getArgusMarReportInterval(output)->tv_usec;
477 
478       if (output->ArgusReportTime.tv_usec > ARGUS_FRACTION_TIME) {
479          output->ArgusReportTime.tv_sec++;
480          output->ArgusReportTime.tv_usec -= ARGUS_FRACTION_TIME;
481       }
482 
483       retn++;
484    }
485 
486 #ifdef ARGUSDEBUG
487    ArgusDebug (7, "ArgusOutputStatusTime(%p) done", output);
488 #endif
489    return (retn);
490 }
491 
492 
493 
494 void *
ArgusOutputProcess(void * arg)495 ArgusOutputProcess(void *arg)
496 {
497    struct ArgusOutputStruct *output = (struct ArgusOutputStruct *) arg;
498    struct timeval ArgusUpDate = {0, 500000}, ArgusNextUpdate = {0,0};
499    struct ArgusListStruct *list = NULL;
500    int val, count;
501    void *retn = NULL;
502 
503 #if defined(ARGUS_THREADS)
504    sigset_t blocked_signals;
505 #endif /* ARGUS_THREADS */
506 
507 #ifdef ARGUSDEBUG
508 #if defined(ARGUS_THREADS)
509    ArgusDebug (1, "ArgusOutputProcess(%p) starting\n", output);
510 #else
511    ArgusDebug (6, "ArgusOutputProcess(%p) starting\n", output);
512 #endif
513 #endif
514 
515 #if defined(ARGUS_TILERA)
516    bind_proc(ArgusFirstTile + 1);
517 #endif
518 
519 #if defined(ARGUS_THREADS)
520    sigfillset(&blocked_signals);
521    pthread_sigmask(SIG_BLOCK, &blocked_signals, NULL);
522 
523 #if defined(HAVE_SOLARIS)
524    sigignore(SIGPIPE);
525 #else
526    (void) signal (SIGPIPE, SIG_IGN);
527 #endif
528 
529    while ((list = output->ArgusInputList) == NULL) {
530       struct timespec tsbuf = {0, 10000000}, *ts = &tsbuf;
531 #ifdef ARGUSDEBUG
532       ArgusDebug (6, "ArgusOutputProcess(%p) waiting for ArgusOutputList\n", output);
533 #endif
534       nanosleep (ts, NULL);
535    }
536 
537    while (!(output->status & ARGUS_SHUTDOWN) || ((output->status & ARGUS_SHUTDOWN) && !ArgusListEmpty(list))) {
538 #else
539       if ((list = output->ArgusInputList) != NULL) {
540 #endif
541          struct ArgusRecordStruct *rec = NULL;
542 
543          gettimeofday (&output->ArgusGlobalTime, 0L);
544 #if defined(ARGUS_NANOSECONDS)
545          output->ArgusGlobalTime.tv_usec *= 1000;
546 #endif
547 #ifdef ARGUSDEBUG
548          ArgusDebug (6, "ArgusOutputProcess() looping\n");
549 #endif
550 
551     /* check to see if there are any new clients */
552 
553          if ((output->ArgusPortNum != 0) &&
554             ((output->ArgusGlobalTime.tv_sec >  ArgusNextUpdate.tv_sec) ||
555             ((output->ArgusGlobalTime.tv_sec == ArgusNextUpdate.tv_sec) &&
556              (output->ArgusGlobalTime.tv_usec > ArgusNextUpdate.tv_usec)))) {
557 
558             if (output->ArgusListens) {
559                struct timeval wait = {0, 0};
560                fd_set readmask;
561                int i, width = 0;
562 
563                FD_ZERO(&readmask);
564 
565                for (i = 0; i < output->ArgusListens; i++) {
566                   if (output->ArgusLfd[i] != -1) {
567                      FD_SET(output->ArgusLfd[i], &readmask);
568                      width = (output->ArgusLfd[i] > width) ? output->ArgusLfd[i] : width;
569                   }
570                }
571 
572                if (output->ArgusClients) {
573 #ifdef ARGUSDEBUG
574                   ArgusDebug (6, "ArgusOutputProcess() checking for remotes\n");
575 #endif
576 #if defined(ARGUS_THREADS)
577                   pthread_mutex_lock(&output->ArgusClients->lock);
578 #endif
579                   if (output->ArgusClients->count) {
580                      struct ArgusClientData *client = (void *)output->ArgusClients->start;
581 
582                      do {
583                         if (client->sock && !(client->sock->filename)) {
584                            FD_SET(client->fd, &readmask);
585                            width = (client->fd > width) ? client->fd : width;
586                         }
587                         client = (void *) client->qhdr.nxt;
588                      } while (client != (void *)output->ArgusClients->start);
589                   }
590 
591                   if ((val = select (width + 1, &readmask, NULL, NULL, &wait)) >= 0) {
592                      if (val > 0) {
593                         struct ArgusClientData *client = (void *)output->ArgusClients->start;
594                         int done = 0;
595 #ifdef ARGUSDEBUG
596                         ArgusDebug (6, "ArgusOutputProcess() select returned with tasks\n");
597 #endif
598                         for (i = 0; (i < output->ArgusListens) && (!done); i++) {
599                            if (FD_ISSET(output->ArgusLfd[i], &readmask))
600                               ArgusCheckClientStatus(output, output->ArgusLfd[i]);
601 
602                            if (client != NULL) {
603                               do {
604                                  if (client->fd != -1) {
605                                     if (FD_ISSET(client->fd, &readmask)) {
606                                        if (ArgusCheckClientMessage(output, client) < 0) {
607                                           ArgusDeleteSocket(output, client);
608                                        } else {
609                                           done++;
610                                           break;
611                                        }
612                                     }
613                                  }
614                                  client = (void *) client->qhdr.nxt;
615                               } while (client != (void *)output->ArgusClients->start);
616                            }
617                         }
618                      }
619                   }
620 
621 #if defined(ARGUS_THREADS)
622                   pthread_mutex_unlock(&output->ArgusClients->lock);
623 #endif
624 #ifdef ARGUSDEBUG
625                   ArgusDebug (6, "ArgusOutputProcess() done checking for remotes\n");
626 #endif
627                }
628 
629                ArgusNextUpdate.tv_usec += ArgusUpDate.tv_usec;
630                ArgusNextUpdate.tv_sec  += ArgusUpDate.tv_sec;
631 
632                if (ArgusNextUpdate.tv_usec > ARGUS_FRACTION_TIME) {
633                   ArgusNextUpdate.tv_sec++;
634                   ArgusNextUpdate.tv_usec -= ARGUS_FRACTION_TIME;
635                }
636             }
637          }
638 
639 #if defined(ARGUS_THREADS)
640          if (ArgusListEmpty(list)) {
641             struct timeval tvp;
642             struct timespec tsbuf, *ts = &tsbuf;
643             gettimeofday (&tvp, 0L);
644             ts->tv_sec = tvp.tv_sec + 0;
645             ts->tv_nsec = tvp.tv_usec * 1000;
646             ts->tv_nsec += 100000000;
647             while (ts->tv_nsec > 1000000000) {
648                ts->tv_sec++;
649                ts->tv_nsec -= 1000000000;
650             }
651 #ifdef ARGUSDEBUG
652             ArgusDebug (6, "ArgusOutputProcess() waiting for input list\n");
653 #endif
654             if (pthread_mutex_lock(&list->lock)) {
655 #ifdef ARGUSDEBUG
656                ArgusDebug (6, "ArgusOutputProcess() pthread_mutex_lock error %s\n", strerror(errno));
657 #endif
658             }
659 
660             if (pthread_cond_timedwait(&list->cond, &list->lock, ts) == EINVAL) {
661 #ifdef ARGUSDEBUG
662                ArgusDebug (6, "ArgusOutputProcess() pthread_cond_timedwait error bad value\n");
663 #endif
664             }
665 
666             if (pthread_mutex_unlock(&list->lock)) {
667 #ifdef ARGUSDEBUG
668                ArgusDebug (6, "ArgusOutputProcess() pthread_mutex_lock error %s\n", strerror(errno));
669 #endif
670             }
671          }
672 #endif
673 
674          if (ArgusOutputStatusTime(output)) {
675             if ((rec = ArgusGenerateStatusMarRecord(output, ARGUS_STATUS)) != NULL) {
676                if (output->ArgusClients) {
677 #if defined(ARGUS_THREADS)
678                   pthread_mutex_lock(&output->ArgusClients->lock);
679 #endif
680                   if (output->ArgusClients->count) {
681                      struct ArgusClientData *client = (void *)output->ArgusClients->start;
682                      do {
683                         if ((client->fd != -1) && (client->sock != NULL) && client->ArgusClientStart) {
684                            if (ArgusWriteSocket (output, client, rec) < 0) {
685                               ArgusDeleteSocket(output, client);
686                            }
687                         }
688                         client = (void *) client->qhdr.nxt;
689                      } while (client != (void *)output->ArgusClients->start);
690                   }
691 #if defined(ARGUS_THREADS)
692                   pthread_mutex_unlock(&output->ArgusClients->lock);
693 #endif
694                }
695                ArgusFreeListRecord (rec);
696                output->ArgusLastMarUpdateTime   = output->ArgusGlobalTime;
697             }
698          }
699 
700          if (output->ArgusOutputList && !(ArgusListEmpty(list))) {
701             int done = 0;
702             ArgusLoadList(list, output->ArgusOutputList);
703 
704             while (!done && ((rec = (struct ArgusRecordStruct *) ArgusPopFrontList(output->ArgusOutputList, ARGUS_LOCK)) != NULL)) {
705                output->ArgusTotalRecords++;
706                output->ArgusOutputSequence = rec->canon.trans.seqnum;
707                count = 0;
708 #ifdef ARGUSDEBUG
709                ArgusDebug (6, "ArgusOutputProcess() received rec %p totals %lld seq %d\n", rec, output->ArgusTotalRecords, output->ArgusOutputSequence);
710 #endif
711                if (((rec->hdr.type & 0xF0) == ARGUS_MAR) && ((rec->hdr.cause & 0xF0) == ARGUS_STOP)) {
712                   done++;
713                   output->status |= ARGUS_SHUTDOWN;
714                   ArgusFreeListRecord(rec);
715                   if ((rec = ArgusGenerateStatusMarRecord(output, ARGUS_STOP)) == NULL) {
716                   }
717 #ifdef ARGUSDEBUG
718                   ArgusDebug (3, "ArgusOutputProcess(%p) rec %d received as stop record \n", output, output->ArgusTotalRecords);
719 #endif
720                }
721 
722                if (output->ArgusClients) {
723 #if defined(ARGUS_THREADS)
724                   pthread_mutex_lock(&output->ArgusClients->lock);
725 #endif
726                   if (output->ArgusClients->count) {
727                      struct ArgusClientData *client = (void *)output->ArgusClients->start;
728                      int i, ArgusWriteRecord = 0;
729 #ifdef ARGUSDEBUG
730                   ArgusDebug (5, "ArgusOutputProcess() %d client(s) for record %p\n", output->ArgusClients->count, rec);
731 #endif
732                      for (i = 0; i < output->ArgusClients->count; i++) {
733                         if ((client->fd != -1) && (client->sock != NULL) && client->ArgusClientStart) {
734 #ifdef ARGUSDEBUG
735                            ArgusDebug (5, "ArgusOutputProcess() client %p ready fd %d sock %p start %d", client, client->fd, client->sock, client->ArgusClientStart);
736 #endif
737                            ArgusWriteRecord = 1;
738                            if (client->ArgusFilterInitialized) {
739                               bcopy(&rec->hdr, &rec->canon.hdr, sizeof(rec->hdr));
740                               if (!(ArgusFilterRecord ((struct nff_insn *)client->ArgusNFFcode.bf_insns, rec)))
741                                  ArgusWriteRecord = 0;
742                            }
743 
744                            if (ArgusWriteRecord) {
745                               if (ArgusWriteSocket (output, client, rec) < 0) {
746                                  ArgusDeleteSocket(output, client);
747                               } else {
748                                  if (ArgusWriteOutSocket (output, client) < 0) {
749                                     ArgusDeleteSocket(output, client);
750                                  }
751                               }
752                            } else {
753 #ifdef ARGUSDEBUG
754                               ArgusDebug (5, "ArgusOutputProcess() client %p filter blocks fd %d sock %p start %d", client, client->fd, client->sock, client->ArgusClientStart);
755 #endif
756                            }
757 
758                         } else {
759                            struct timeval tvbuf, *tvp = &tvbuf;
760 #ifdef ARGUSDEBUG
761                            ArgusDebug (5, "ArgusOutputProcess() %d client(s) not ready fd %d sock 0x%x start %d", output->ArgusClients->count, client->fd, client->sock, client->ArgusClientStart);
762 #endif
763                            RaDiffTime (&output->ArgusGlobalTime, &client->startime, tvp);
764                            if (tvp->tv_sec >= ARGUS_CLIENT_STARTUP_TIMEOUT) {
765                               if (client->sock != NULL) {
766                                  ArgusDeleteSocket(output, client);
767                                  ArgusLog (LOG_WARNING, "ArgusCheckClientMessage: client %s never started: timed out",
768                                     (client->hostname != NULL) ? client->hostname : "noname");
769                               }
770                               client->ArgusClientStart = 1;
771                            }
772                         }
773                         client = (void *) client->qhdr.nxt;
774                      }
775                   }
776 #if defined(ARGUS_THREADS)
777                   pthread_mutex_unlock(&output->ArgusClients->lock);
778 #endif
779                } else {
780 #ifdef ARGUSDEBUG
781                   ArgusDebug (5, "ArgusOutputProcess() no client for record %p\n", rec);
782 #endif
783                }
784                ArgusFreeListRecord(rec);
785             }
786 
787             if (output->ArgusWriteStdOut)
788                fflush (stdout);
789          }
790 #ifdef ARGUSDEBUG
791          ArgusDebug (6, "ArgusOutputProcess() checking out clients\n");
792 #endif
793 #if defined(ARGUS_THREADS)
794          pthread_mutex_lock(&output->ArgusClients->lock);
795 #endif
796          if ((output->ArgusPortNum != 0) && (output->ArgusClients->count)) {
797             struct ArgusClientData *client = (void *)output->ArgusClients->start;
798             int i;
799 
800             for (i = 0; i < output->ArgusClients->count; i++) {
801                if ((client->fd != -1) && (client->sock != NULL)) {
802                   if (output->status & ARGUS_SHUTDOWN) {
803                      ArgusWriteOutSocket (output, client);
804                      ArgusDeleteSocket(output, client);
805                   } else {
806                      if (ArgusWriteOutSocket (output, client) < 0) {
807                         ArgusDeleteSocket(output, client);
808                      }
809                   }
810                }
811                client = (void *) client->qhdr.nxt;
812             }
813 
814             for (i = 0, count = output->ArgusClients->count; (i < count) && output->ArgusClients->count; i++) {
815                if ((client->fd == -1) && (client->sock == NULL) && client->ArgusClientStart) {
816                   if (ArgusRemoveFromQueue(output->ArgusClients, &client->qhdr, ARGUS_NOLOCK) != NULL)
817                      ArgusFree(client);
818                   i = 0; count = output->ArgusClients->count;
819                   client = (void *)output->ArgusClients->start;
820                } else
821                   client = (void *)client->qhdr.nxt;
822             }
823          }
824 
825 #if defined(ARGUS_THREADS)
826          pthread_mutex_unlock(&output->ArgusClients->lock);
827 #endif
828 #ifdef ARGUSDEBUG
829          ArgusDebug (6, "ArgusOutputProcess() done with clients\n");
830 #endif
831 
832 #if !defined(ARGUS_THREADS)
833       }
834 #else
835    }
836 #endif /* ARGUS_THREADS */
837 
838 #ifdef ARGUSDEBUG
839 #if defined(ARGUS_THREADS)
840    ArgusDebug (6, "ArgusOutputProcess(%p) shuting down %d\n", output, output->ArgusInputList->count);
841 #else
842    ArgusDebug (6, "ArgusOutputProcess(%p) done count %d\n", output, output->ArgusInputList->count);
843 #endif /* ARGUS_THREADS */
844 #endif
845 
846 #if defined(ARGUS_THREADS)
847    {
848       struct ArgusClientData *client;
849       while ((client = (void *) output->ArgusClients->start) != NULL) {
850          if ((client->fd != -1) && (client->sock != NULL))
851             ArgusWriteOutSocket (output, client);
852 
853          ArgusDeleteSocket(output, client);
854          if (ArgusRemoveFromQueue(output->ArgusClients, &client->qhdr, ARGUS_LOCK) != NULL)
855             ArgusFree(client);
856       }
857    }
858 
859 #ifdef ARGUSDEBUG
860    ArgusDebug (1, "ArgusOutputProcess(%p) exiting\n", output);
861 #endif
862    pthread_exit(retn);
863 #endif /* ARGUS_THREADS */
864 
865    return (retn);
866 }
867 
868 
869 #include <netdb.h>
870 
871 int
ArgusEstablishListen(struct ArgusOutputStruct * output,char * errbuf)872 ArgusEstablishListen (struct ArgusOutputStruct *output, char *errbuf)
873 {
874    int port = output->ArgusPortNum;
875    struct ArgusBindAddrStruct *ArgusBindAddrs = NULL;
876    char *baddr = NULL;
877    int s = -1;
878 
879    if (port > 0) {
880       if (output->ArgusListens > 0) {
881          int i = output->ArgusListens;
882          for (i = 0; i < output->ArgusListens; i++) {
883             close(output->ArgusLfd[i]);
884             output->ArgusLfd[i] = -1;
885          }
886       }
887       output->ArgusListens = 0;
888 
889       if (output->ArgusBindAddrs != NULL) {
890          ArgusBindAddrs = (struct ArgusBindAddrStruct *)output->ArgusBindAddrs->start;
891          baddr = ArgusBindAddrs->addr;
892       }
893 
894       do {
895 #if defined(HAVE_GETADDRINFO)
896          {
897             struct addrinfo hints, *host, *hp;
898             char portbuf[32];
899             int retn = 0;
900 
901             memset(&hints, 0, sizeof(hints));
902             if (output->ArgusAddrInfo.ai_socktype || output->ArgusAddrInfo.ai_protocol) {
903                hints.ai_family   = output->ArgusAddrInfo.ai_family;
904                hints.ai_socktype = output->ArgusAddrInfo.ai_socktype;
905                hints.ai_protocol = output->ArgusAddrInfo.ai_protocol;
906             } else {
907                hints.ai_family   = PF_UNSPEC;
908                hints.ai_socktype = SOCK_STREAM;
909                hints.ai_protocol = IPPROTO_TCP;
910                hints.ai_flags    = AI_PASSIVE;
911             }
912 
913             snprintf(portbuf, 32, "%d", port);
914 
915             if ((retn = getaddrinfo(baddr, portbuf, &hints, &host)) != 0) {
916                switch (retn) {
917                   case EAI_AGAIN:
918                      ArgusLog(LOG_ERR, "dns server not available");
919                      break;
920                   case EAI_NONAME:
921                      ArgusLog(LOG_ERR, "bind address %s unknown", optarg);
922                      break;
923 #if defined(EAI_ADDRFAMILY)
924                   case EAI_ADDRFAMILY:
925                      ArgusLog(LOG_ERR, "bind address %s has no IP address", optarg);
926                      break;
927 #endif
928                   case EAI_SYSTEM:
929                      ArgusLog(LOG_ERR, "bind address %s name server error %s", optarg, strerror(errno));
930                      break;
931                }
932             }
933 
934             hp = host;
935 
936             do {
937                retn = -1;
938                if ((s = socket (hp->ai_family, hp->ai_socktype, hp->ai_protocol)) >= 0) {
939                   int flags = fcntl (s, F_GETFL, 0L);
940                   if ((fcntl (s, F_SETFL, flags | O_NDELAY)) >= 0) {
941                      int on = 1;
942                      if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
943                         ArgusLog (LOG_INFO, "ArgusInitOutput: setsockopt set reuseaddr %s", strerror(errno));
944 #ifdef ARGUSDEBUG
945                      if (baddr)
946                         ArgusDebug (1, "ArgusEstablishListen(%p, %p) binding: %s:%d family: %d\n", output, errbuf, baddr, port, hp->ai_family);
947                      else {
948 #if defined(__OpenBSD__)
949                         switch (hp->ai_family) {
950                            case AF_INET6: ((struct sockaddr_in6 *)hp->ai_addr)->sin6_addr = in6addr_any; break;
951                         }
952 #endif
953                         ArgusDebug (1, "ArgusEstablishListen(%d, %p) binding: any:%d family: %d\n", port, errbuf, port, hp->ai_family);
954                      }
955 #endif
956 
957                      if (!(bind (s, hp->ai_addr, hp->ai_addrlen))) {
958                         switch (hp->ai_socktype) {
959                            case SOCK_STREAM:
960                               if ((retn = listen (s, ARGUS_MAXLISTEN)) >= 0) {
961                                  output->ArgusLfd[output->ArgusListens++] = s;
962                               } else {
963                                  snprintf(errbuf, 1024, "%s: ArgusEstablishListen: listen() failure", ArgusProgramName);
964                               }
965                               break;
966 
967                            case SOCK_DGRAM:
968                               retn = 0;
969                               break;
970                         }
971                      } else {
972                         snprintf(errbuf, 256, "%s: ArgusEstablishListen: bind() error", ArgusProgramName);
973                      }
974                   } else
975                      snprintf(errbuf, 256, "%s: ArgusEstablishListen: fcntl() error", ArgusProgramName);
976 
977                   if (retn == -1) {
978                      close (s);
979                      s = -1;
980                   }
981 
982                } else
983                   snprintf(errbuf, 256, "%s: ArgusEstablishListen: socket() error", ArgusProgramName);
984 
985                hp = hp->ai_next;
986 
987             } while ((hp != NULL) && (retn == -1));
988 
989             freeaddrinfo(host);
990          }
991 #else
992          struct sockaddr_in sin;
993          struct hostent *host;
994 
995          sin.sin_addr.s_addr = INADDR_ANY;
996          if (baddr) {
997 #ifdef ARGUSDEBUG
998             ArgusDebug (1, "ArgusEstablishListen(%d, %s, %p)\n", port, baddr, errbuf);
999 #endif
1000             if ((host = gethostbyname (baddr)) != NULL) {
1001                if ((host->h_addrtype == AF_INET) && (host->h_length == 4)) {
1002                   bcopy ((char *) *host->h_addr_list, (char *)&sin.sin_addr.s_addr, host->h_length);
1003                } else
1004                   ArgusLog (LOG_ERR, "ArgusEstablishListen() unsupported bind address %s", baddr);
1005             } else
1006                ArgusLog (LOG_ERR, "ArgusEstablishListen() bind address %s error %s", baddr, strerror(errno));
1007          }
1008 
1009          sin.sin_port = htons((u_short) port);
1010          sin.sin_family = AF_INET;
1011 
1012 #ifdef ARGUSDEBUG
1013          ArgusDebug (1, "ArgusEstablishListen(%p, %p) binding: %d:%d\n", output, errbuf, sin.sin_addr.s_addr, port);
1014 #endif
1015 
1016          if ((s = socket (AF_INET, SOCK_STREAM, 0)) != -1) {
1017             int flags = fcntl (s, F_GETFL, 0L);
1018             if ((fcntl (s, F_SETFL, flags | O_NDELAY)) >= 0) {
1019                int on = 1;
1020                if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
1021                   ArgusLog (LOG_INFO, "ArgusInitOutput: setsockopt set reuseaddr %s", strerror(errno));
1022 
1023                if (!(bind (s, (struct sockaddr *)&sin, sizeof(sin)))) {
1024                   if ((listen (s, ARGUS_MAXLISTEN)) >= 0) {
1025                      output->ArgusLfd[output->ArgusListens++] = s;
1026                   } else {
1027                      close (s);
1028                      s = -1;
1029                      snprintf(errbuf, 1024, "%s: ArgusEstablishListen: listen() failure", ArgusProgramName);
1030                   }
1031                } else {
1032                   close (s);
1033                   s = -1;
1034                   snprintf(errbuf, 256, "%s: ArgusEstablishListen: bind() error", ArgusProgramName);
1035                }
1036             } else
1037                snprintf(errbuf, 256, "%s: ArgusEstablishListen: fcntl() error", ArgusProgramName);
1038          } else
1039             snprintf(errbuf, 256, "%s: ArgusEstablishListen: socket() error", ArgusProgramName);
1040 #endif
1041          if (ArgusBindAddrs) {
1042             if ((ArgusBindAddrs = (struct ArgusBindAddrStruct *)ArgusBindAddrs->nxt) != NULL) {
1043                baddr = ArgusBindAddrs->addr;
1044             } else
1045                baddr = NULL;
1046          }
1047 
1048       } while (baddr != NULL);
1049    }
1050 
1051 #ifdef ARGUSDEBUG
1052    ArgusDebug (2, "ArgusEstablishListen(%p, %p) returning %d\n", output, errbuf, s);
1053 #endif
1054 
1055    return (s);
1056 }
1057 
1058 
1059 int ArgusAuthenticateClient (struct ArgusClientData *);
1060 #ifdef ARGUS_SASL
1061 static sasl_ssf_t extprops_ssf = 0;
1062 static char clienthost[NI_MAXHOST*2+1] = "[local]";
1063 
1064 sasl_security_properties_t *mysasl_secprops(int);
1065 #endif
1066 
1067 
1068 void
ArgusCheckClientStatus(struct ArgusOutputStruct * output,int s)1069 ArgusCheckClientStatus (struct ArgusOutputStruct *output, int s)
1070 {
1071    struct sockaddr from;
1072    int len = sizeof (from), bytes;
1073    int fd;
1074 
1075 #ifdef ARGUS_SASL
1076 #define SASL_SEC_MASK   0x0fff
1077    struct sockaddr_storage localaddr, remoteaddr;
1078    int retn, argus_have_addr = 0;
1079    char localhostname[1024];
1080    sasl_conn_t *conn = NULL;
1081 
1082    socklen_t salen;
1083    sasl_security_properties_t *secprops = NULL;
1084    char localip[60], remoteip[60];
1085 #endif
1086 
1087    if ((fd = accept (s, (struct sockaddr *)&from, (socklen_t *)&len)) > 0) {
1088       int flags = fcntl (fd, F_GETFL, 0L);
1089 
1090       if ((fcntl (fd, F_SETFL, flags | O_NONBLOCK)) >= 0) {
1091          if (ArgusTcpWrapper (fd, &from) >= 0) {
1092 
1093             if (output->ArgusClients && (output->ArgusClients->count < ARGUS_MAXLISTEN)) {
1094                struct ArgusClientData *client = (void *) ArgusCalloc (1, sizeof(struct ArgusClientData));
1095 
1096                if (client == NULL)
1097                   ArgusLog (LOG_ERR, "ArgusCheckClientStatus: ArgusCalloc %s", strerror(errno));
1098 
1099                client->fd = fd;
1100                client->startime = output->ArgusGlobalTime;
1101 #ifdef ARGUSDEBUG
1102                ArgusDebug (2, "ArgusCheckClientStatus() new client\n");
1103 #endif
1104                if ((client->sock = ArgusNewSocket(fd)) == NULL)
1105                   ArgusLog (LOG_ERR, "ArgusInitOutput: ArgusNewSocket error %s", strerror(errno));
1106 
1107                if (output->ArgusInitMar != NULL)
1108                   ArgusFree(output->ArgusInitMar);
1109 
1110                if ((output->ArgusInitMar = ArgusGenerateInitialMar(output)) == NULL)
1111                   ArgusLog (LOG_ERR, "ArgusCheckClientStatus: ArgusGenerateInitialMar error %s", strerror(errno));
1112 
1113 #ifdef ARGUS_SASL
1114 #ifdef ARGUSDEBUG
1115                ArgusDebug (2, "ArgusCheckClientStatus: SASL enabled\n");
1116 #endif
1117                {
1118                char hbuf[NI_MAXHOST];
1119                int niflags;
1120                salen = sizeof(remoteaddr);
1121 
1122                bzero(hbuf, sizeof(hbuf));
1123 
1124                if (getpeername(fd, (struct sockaddr *)&remoteaddr, &salen) == 0 &&
1125                    (remoteaddr.ss_family == AF_INET || remoteaddr.ss_family == AF_INET6)) {
1126                    if (getnameinfo((struct sockaddr *)&remoteaddr, salen, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
1127                        strncpy(clienthost, hbuf, sizeof(hbuf));
1128                    } else {
1129                        clienthost[0] = '\0';
1130                    }
1131                    niflags = NI_NUMERICHOST;
1132 #ifdef NI_WITHSCOPEID
1133                    if (((struct sockaddr *)&remoteaddr)->sa_family == AF_INET6)
1134                        niflags |= NI_WITHSCOPEID;
1135 #endif
1136                    if (getnameinfo((struct sockaddr *)&remoteaddr, salen, hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
1137                        strncpy(hbuf, "unknown", sizeof(hbuf));
1138 
1139                    sprintf(&clienthost[strlen(clienthost)], "[%s]", hbuf);
1140 
1141                    salen = sizeof(localaddr);
1142                    if (getsockname(fd, (struct sockaddr *)&localaddr, &salen) == 0) {
1143                        if(iptostring((struct sockaddr *)&remoteaddr, salen,
1144                                      remoteip, sizeof(remoteip)) == 0
1145                           && iptostring((struct sockaddr *)&localaddr, salen,
1146                                         localip, sizeof(localip)) == 0) {
1147                           argus_have_addr = 1;
1148                        }
1149                    }
1150                }
1151                }
1152 
1153                gethostname(localhostname, 1024);
1154                if (!strchr (localhostname, '.')) {
1155                   char domainname[256];
1156                   strcat (localhostname, ".");
1157                   if (getdomainname (domainname, 256)) {
1158                      snprintf (&localhostname[strlen(localhostname)], 1024 - strlen(localhostname), "%s", domainname);
1159                   }
1160                }
1161 
1162                if ((retn = sasl_server_new("argus", NULL, NULL, localip, remoteip, NULL, 0,
1163                                &client->sasl_conn)) != SASL_OK)
1164                   ArgusLog (LOG_ERR, "ArgusCheckClientStatus: sasl_server_new failed %d", retn);
1165 
1166                conn = client->sasl_conn;
1167 
1168               /* set required security properties here */
1169 
1170                if (extprops_ssf)
1171                   sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops_ssf);
1172 
1173                secprops = mysasl_secprops(0);
1174                sasl_setprop(conn, SASL_SEC_PROPS, secprops);
1175 
1176 
1177               /* set ip addresses */
1178                if (argus_have_addr) {
1179                   sasl_setprop(conn, SASL_IPREMOTEPORT, remoteip);
1180                   if (client->saslprops.ipremoteport != NULL)
1181                      free(client->saslprops.ipremoteport);
1182                   client->saslprops.ipremoteport = strdup(remoteip);
1183 
1184                   sasl_setprop(conn, SASL_IPLOCALPORT, localip);
1185                   if (client->saslprops.iplocalport != NULL)
1186                      free(client->saslprops.iplocalport);
1187                   client->saslprops.iplocalport = strdup(localip);
1188                }
1189 
1190                output->ArgusInitMar->argus_mar.status |= htonl(ARGUS_SASL_AUTHENTICATE);
1191 #endif
1192                len = ntohs(output->ArgusInitMar->hdr.len) * 4;
1193 
1194                if ((bytes = write (client->fd, (char *) output->ArgusInitMar, len)) != len) {
1195                   close (client->fd);
1196                   ArgusLog (LOG_ALERT, "ArgusInitOutput: write(): %s", strerror(errno));
1197                } else {
1198 #ifdef ARGUSDEBUG
1199                   ArgusDebug (2, "ArgusCheckClientStatus: wrote %d bytes to client\n", bytes);
1200 #endif
1201                }
1202 
1203 #ifdef ARGUS_SASL
1204                if (ArgusMaxSsf > 0) {
1205                   int flags = fcntl (fd, F_GETFL, 0);
1206 
1207                   fcntl (fd, F_SETFL, flags & ~O_NONBLOCK);
1208                   if (ArgusAuthenticateClient (client)) {
1209                      ArgusDeleteSocket(output, client);
1210                      ArgusLog (LOG_ALERT, "ArgusCheckClientStatus: ArgusAuthenticateClient failed\n");
1211                   } else {
1212                      ArgusAddToQueue(output->ArgusClients, &client->qhdr, ARGUS_NOLOCK);
1213                      fcntl (fd, F_SETFL, flags);
1214                   }
1215 
1216                } else {
1217                }
1218 #else
1219                ArgusAddToQueue(output->ArgusClients, &client->qhdr, ARGUS_NOLOCK);
1220 #endif
1221             } else {
1222                char buf[256];
1223                struct ArgusRecord *argus = (struct ArgusRecord *) &buf;
1224                if ((argus = ArgusGenerateRecord (output->ArgusModel, NULL, ARGUS_ERROR, (struct ArgusRecord *) &buf)) != NULL) {
1225                   len = argus->hdr.len * 4;
1226                   argus->hdr.len = ntohs(argus->hdr.len);
1227                   argus->hdr.cause |= ARGUS_MAXLISTENEXCD;
1228                   if (write (fd, (char *) argus, len) != len) {
1229                      ArgusLog (LOG_ERR, "ArgusInitOutput: write(): %s", strerror(errno));
1230                   } else {
1231 #ifdef ARGUSDEBUG
1232                      ArgusDebug (2, "ArgusCheckClientStatus: wrote %d bytes to client fd %d\n", len, fd);
1233 #endif
1234                   }
1235                   close(fd);
1236                }
1237             }
1238 
1239          } else {
1240             ArgusLog (LOG_WARNING, "ArgusCheckClientStatus: ArgusTcpWrapper rejects");
1241             close (fd);
1242          }
1243 
1244       } else {
1245          ArgusLog (LOG_WARNING, "ArgusCheckClientStatus: fcntl: %s", strerror(errno));
1246          close (fd);
1247       }
1248 
1249    } else
1250       ArgusLog (LOG_WARNING, "ArgusCheckClientStatus: accept: %s", strerror(errno));
1251 
1252 #ifdef ARGUSDEBUG
1253    ArgusDebug (2, "ArgusCheckClientStatus() returning\n");
1254 #endif
1255 }
1256 
1257 
1258 
1259 #define ARGUSMAXCLIENTCOMMANDS           6
1260 #define RADIUM_START                    0
1261 #define RADIUM_DONE                     1
1262 #define RADIUM_FILTER                   2
1263 #define RADIUM_MODEL                    3
1264 #define RADIUM_PROJECT                  4
1265 #define RADIUM_FILE                     5
1266 
1267 char *ArgusClientCommands[ARGUSMAXCLIENTCOMMANDS] =
1268 {
1269    "START: ",
1270    "DONE: ",
1271    "FILTER: ",
1272    "MODEL: ",
1273    "PROJECT: ",
1274    "FILE: ",
1275 };
1276 
1277 
1278 int
ArgusCheckClientMessage(struct ArgusOutputStruct * output,struct ArgusClientData * client)1279 ArgusCheckClientMessage (struct ArgusOutputStruct *output, struct ArgusClientData *client)
1280 {
1281    int retn = 0, cnt = 0, i, found, fd = client->fd;
1282    char buf[MAXSTRLEN], *ptr = buf;
1283    unsigned int value = 0;
1284 
1285 #ifdef ARGUS_SASL
1286    const char *outputbuf = NULL;
1287    unsigned int outputlen = 0;
1288 #endif /* ARGUS_SASL */
1289 
1290    bzero(buf, MAXSTRLEN);
1291 
1292    if (value == 0)
1293       value = MAXSTRLEN;
1294 
1295    if ((cnt = recv (fd, buf, value, 0)) <= 0) {
1296       if (cnt < 0) {
1297 #ifdef ARGUSDEBUG
1298          ArgusDebug (5, "ArgusCheckClientMessage (%p, %p) recv(%d) returned error %s\n", output, client, fd, strerror(errno));
1299 #endif
1300          return (-1);
1301 
1302       } else {
1303 #ifdef ARGUSDEBUG
1304          ArgusDebug (5, "ArgusCheckClientMessage (%p, %p) recv(%d) returned %d bytes\n", output, client, fd, cnt);
1305 #endif
1306          return(-3);
1307       }
1308 
1309    } else {
1310 #ifdef ARGUSDEBUG
1311       ArgusDebug (6, "ArgusCheckClientMessage (%p, %p) recv(%d) returned %d bytes\n", output, client, fd, cnt);
1312 #endif
1313    }
1314 
1315 #ifdef ARGUS_SASL
1316    if ((client->sasl_conn)) {
1317       const int *ssfp;
1318       int result;
1319 
1320       if ((result = sasl_getprop(client->sasl_conn, SASL_SSF, (const void **) &ssfp)) != SASL_OK)
1321          ArgusLog (LOG_ERR, "sasl_getprop: error %s\n", sasl_errdetail(client->sasl_conn));
1322 
1323       if (ssfp && (*ssfp > 0)) {
1324          if (sasl_decode (client->sasl_conn, buf, cnt, &outputbuf, &outputlen) != SASL_OK) {
1325             ArgusLog (LOG_WARNING, "ArgusCheckClientMessage(%p, %d) sasl_decode (%p, %p, %d, %p, %d) failed",
1326                        client, fd, client->sasl_conn, buf, cnt, &outputbuf, outputlen);
1327             return(-1);
1328          } else {
1329 #ifdef ARGUSDEBUG
1330             ArgusDebug (6, "ArgusCheckClientMessage (%p, %p) sasl_decode(%d) returned %d bytes\n", output, client, fd, outputlen);
1331 #endif
1332          }
1333          if (outputlen > 0) {
1334             if (outputlen < MAXSTRLEN) {
1335                bzero (buf, MAXSTRLEN);
1336                bcopy (outputbuf, buf, outputlen);
1337                cnt = outputlen;
1338             } else
1339                ArgusLog (LOG_ERR, "ArgusCheckClientMessage(%p, %d) sasl_decode returned %d bytes\n", client, fd, outputlen);
1340 
1341          } else {
1342             return (0);
1343          }
1344       }
1345    }
1346 #endif /* ARGUS_SASL */
1347 
1348 #ifdef ARGUSDEBUG
1349    ArgusDebug (2, "ArgusCheckClientMessage (%p, %p) read '%s' from remote\n", output, client, ptr);
1350 #endif
1351 
1352    for (i = 0, found = 0; i < ARGUSMAXCLIENTCOMMANDS; i++) {
1353       if (!(strncmp (ptr, ArgusClientCommands[i], strlen(ArgusClientCommands[i])))) {
1354          found++;
1355          switch (i) {
1356             case RADIUM_START: client->ArgusClientStart++; retn = 0; break;
1357             case RADIUM_DONE:  retn = -4; break;
1358             case RADIUM_FILTER: {
1359                char *reply = NULL;
1360                reply = ArgusFilterCompile (&client->ArgusNFFcode, &ptr[7], 1);
1361                if (reply == NULL) {
1362                   retn = -2;
1363                   if ((cnt = send (fd, "ER", 2, 0)) != 2) {
1364 #ifdef ARGUSDEBUG
1365                      ArgusDebug (4, "ArgusCheckClientMessage: send error %s\n", strerror(errno));
1366 #endif
1367                   }
1368 #ifdef ARGUSDEBUG
1369                   ArgusDebug (3, "ArgusCheckClientMessage: ArgusFilter filter error: %s\n", &ptr[7]);
1370 #endif
1371                } else
1372                if (strcmp(reply, "OK")) {
1373                   retn = -3;
1374                   if ((cnt = send (fd, reply, 2, 0)) != 2)  {
1375 #ifdef ARGUSDEBUG
1376                      ArgusDebug (4, "ArgusCheckClientMessage: send error %s\n", strerror(errno));
1377 #endif
1378                   }
1379                } else {
1380 
1381 #ifdef ARGUSDEBUG
1382                   char buf[MAXSTRLEN];
1383                   bzero(buf, MAXSTRLEN);
1384                   nff_dump(&client->ArgusNFFcode, buf, MAXSTRLEN, 1);
1385                   ArgusDebug (3, "ArgusInitOutput: ArgusFilterCompile returned: \n%s\n", buf);
1386 #endif
1387                   client->ArgusFilterInitialized++;
1388                   if ((cnt = send (fd, "OK", 2, 0)) != 2) {
1389                      retn = -3;
1390 #ifdef ARGUSDEBUG
1391                      ArgusDebug (4, "ArgusCheckClientMessage: send error %s\n", strerror(errno));
1392 #endif
1393                   } else {
1394                      retn = 0;
1395 #ifdef ARGUSDEBUG
1396                      ArgusDebug (4, "ArgusCheckClientMessage: ArgusFilter %s initialized.\n", &ptr[7]);
1397 #endif
1398                   }
1399                }
1400                break;
1401             }
1402 
1403             case RADIUM_PROJECT:
1404             case RADIUM_MODEL:
1405                break;
1406 
1407             case RADIUM_FILE: {
1408 #ifdef ARGUSDEBUG
1409                   ArgusDebug (6, "ArgusCheckClientMessage: ArgusFile %s initialized.\n", &ptr[6]);
1410 #endif
1411                   retn = 0;
1412                }
1413                break;
1414 
1415             default:
1416                ArgusLog (LOG_WARNING, "ArgusCheckClientMessage: received %s",  ptr);
1417                break;
1418          }
1419 
1420          break;
1421       }
1422    }
1423 
1424    if (!found)
1425       ArgusLog (LOG_WARNING, "ArgusCheckClientMessage: received %s",  ptr);
1426 
1427 #ifdef ARGUSDEBUG
1428    ArgusDebug (5, "ArgusCheckClientMessage: returning %d\n", retn);
1429 #endif
1430 
1431    return (retn);
1432 }
1433 
1434 
1435 struct ArgusRecord *
ArgusGenerateInitialMar(struct ArgusOutputStruct * output)1436 ArgusGenerateInitialMar (struct ArgusOutputStruct *output)
1437 {
1438    struct ArgusSourceStruct *ArgusSrc, *aSrc;
1439    struct ArgusRecord *retn;
1440    struct timeval now;
1441    int x, done;
1442 
1443    if ((retn = (struct ArgusRecord *) ArgusCalloc (1, sizeof(struct ArgusRecord))) == NULL)
1444      ArgusLog (LOG_ERR, "ArgusGenerateInitialMar(%p) ArgusCalloc error %s\n", output, strerror(errno));
1445 
1446    retn->hdr.type  = ARGUS_MAR | ARGUS_VERSION;
1447    retn->hdr.cause = ARGUS_START;
1448    retn->hdr.len   = sizeof(struct ArgusRecord) / 4;
1449 
1450    retn->argus_mar.argusid = ARGUS_COOKIE;
1451    retn->argus_mar.thisid  = getArgusID(ArgusSourceTask);
1452 
1453    switch (getArgusIDType(ArgusSourceTask)) {
1454       case ARGUS_TYPE_STRING: retn->argus_mar.status |= ARGUS_IDIS_STRING; break;
1455       case ARGUS_TYPE_INT:    retn->argus_mar.status |= ARGUS_IDIS_INT; break;
1456       case ARGUS_TYPE_IPV4:   retn->argus_mar.status |= ARGUS_IDIS_IPV4; break;
1457    }
1458 
1459    retn->argus_mar.startime.tv_sec  = output->ArgusStartTime.tv_sec;
1460    retn->argus_mar.startime.tv_usec = output->ArgusStartTime.tv_usec;
1461 
1462    gettimeofday (&now, 0L);
1463 
1464    retn->argus_mar.now.tv_sec  = now.tv_sec;
1465    retn->argus_mar.now.tv_usec = now.tv_usec;
1466 
1467    retn->argus_mar.major_version = VERSION_MAJOR;
1468    retn->argus_mar.minor_version = VERSION_MINOR;
1469    retn->argus_mar.reportInterval = getArgusFarReportInterval(output->ArgusModel)->tv_sec;
1470    retn->argus_mar.argusMrInterval = getArgusMarReportInterval(output)->tv_sec;
1471 
1472    if ((ArgusSrc = output->ArgusSrc) != NULL) {
1473       for (x = 0, done = 0; x < ARGUS_MAXINTERFACE && !done; x++) {
1474          if ((aSrc = ArgusSrc->srcs[x]) != NULL) {
1475             if (aSrc->ArgusInterface[0].ArgusLocalNet != 0) {
1476                retn->argus_mar.localnet = aSrc->ArgusInterface[0].ArgusLocalNet;
1477                retn->argus_mar.netmask  = aSrc->ArgusInterface[0].ArgusNetMask;
1478                done = 1;
1479             }
1480          }
1481       }
1482    }
1483 
1484    retn->argus_mar.nextMrSequenceNum = output->ArgusOutputSequence;
1485    retn->argus_mar.record_len = -1;
1486 
1487 #if defined(_LITTLE_ENDIAN)
1488    ArgusHtoN(retn);
1489 #endif
1490 
1491 #ifdef ARGUSDEBUG
1492    ArgusDebug (4, "ArgusGenerateInitialMar() returning\n");
1493 #endif
1494 
1495    return (retn);
1496 }
1497 
1498 // The supplemental mar record is designed to extend the descriptions of the sensors, their inputs,
1499 // providing interfaces, names, interface types, extended argus identifiers (> 4 bytes),
1500 // and stats, if appropriate,
1501 //
1502 // This will be the way we provide long argus id's, IPv6, ethernet, and long strings.
1503 //
1504 // Minimally it should provide the argusid, used in all records, and the list of input descriptions,
1505 // as well as the extended argus id itself.
1506 
1507 
1508 struct ArgusRecordStruct *
ArgusGenerateSupplementalMarRecord(struct ArgusOutputStruct * output,unsigned char status)1509 ArgusGenerateSupplementalMarRecord (struct ArgusOutputStruct *output, unsigned char status)
1510 {
1511    struct ArgusRecordStruct *retn = NULL;
1512    struct ArgusRecord *rec = NULL;
1513 
1514    while ((retn = (struct ArgusRecordStruct *) ArgusMallocListRecord (sizeof(*retn))) == NULL) {
1515       if (output && output->ArgusInputList) {
1516          if ((retn = (struct ArgusRecordStruct *) ArgusPopFrontList(output->ArgusInputList, ARGUS_LOCK)) != NULL) {
1517             ArgusFreeListRecord (retn);
1518          } else
1519             break;
1520       } else
1521          break;
1522    }
1523 
1524    if (retn) {
1525       struct ArgusSourceStruct *ArgusSrc = NULL, *aSrc = NULL;
1526       struct timeval now;
1527 
1528       memset(retn, 0, sizeof(*retn));
1529 
1530       retn->hdr.type    = ARGUS_MAR | ARGUS_VERSION;
1531       retn->hdr.cause   = ARGUS_SUPPLEMENTAL;
1532       retn->hdr.len     = (sizeof(struct ArgusMarSupStruct)/4) + 1;  // have size for one interface, and add as you go
1533 
1534       rec = (struct ArgusRecord *) &retn->canon;
1535       rec->hdr = retn->hdr;
1536 
1537       rec->argus_sup.argusid = getArgusID(ArgusSourceTask);
1538 
1539       switch (getArgusIDType(ArgusSourceTask)) {
1540          case ARGUS_TYPE_STRING: rec->argus_sup.status |= ARGUS_IDIS_STRING; break;
1541          case ARGUS_TYPE_INT:    rec->argus_sup.status |= ARGUS_IDIS_INT; break;
1542          case ARGUS_TYPE_IPV4:   rec->argus_sup.status |= ARGUS_IDIS_IPV4; break;
1543       }
1544 
1545       gettimeofday (&now, 0L);
1546 
1547       rec->argus_sup.startime.tv_sec  = output->ArgusLastMarUpdateTime.tv_sec;
1548       rec->argus_sup.startime.tv_usec = output->ArgusLastMarUpdateTime.tv_usec;
1549 
1550       rec->argus_sup.now.tv_sec  = now.tv_sec;
1551       rec->argus_sup.now.tv_usec = now.tv_usec;
1552 
1553       if ((ArgusSrc = output->ArgusSrc) != NULL) {
1554          int x;
1555          for (x = 0; x < ARGUS_MAXINTERFACE; x++) {
1556             if ((aSrc = ArgusSrc->srcs[x]) != NULL) {
1557                if (aSrc->ArgusInterface[0].ArgusPd != NULL) {
1558                   int i;
1559                   rec->argus_mar.interfaceType = pcap_datalink(aSrc->ArgusInterface[0].ArgusPd);
1560                   rec->argus_mar.interfaceStatus = getArgusInterfaceStatus(aSrc);
1561 
1562                   rec->argus_mar.pktsRcvd  = 0;
1563                   rec->argus_mar.bytesRcvd = 0;
1564                   rec->argus_mar.dropped   = 0;
1565 
1566                   for (i = 0; i < ARGUS_MAXINTERFACE; i++) {
1567                      rec->argus_mar.pktsRcvd  += aSrc->ArgusInterface[i].ArgusTotalPkts -
1568                                                  aSrc->ArgusInterface[i].ArgusLastPkts;
1569                      rec->argus_mar.bytesRcvd += aSrc->ArgusInterface[i].ArgusTotalBytes -
1570                                                  aSrc->ArgusInterface[i].ArgusLastBytes;
1571                      rec->argus_mar.dropped   += aSrc->ArgusInterface[i].ArgusStat.ps_drop -
1572                                                  aSrc->ArgusInterface[i].ArgusLastDrop;
1573 
1574                      aSrc->ArgusInterface[i].ArgusLastPkts  = aSrc->ArgusInterface[i].ArgusTotalPkts;
1575                      aSrc->ArgusInterface[i].ArgusLastDrop  = aSrc->ArgusInterface[i].ArgusStat.ps_drop;
1576                      aSrc->ArgusInterface[i].ArgusLastBytes = aSrc->ArgusInterface[i].ArgusTotalBytes;
1577                   }
1578                }
1579             }
1580          }
1581       }
1582    }
1583 
1584 #ifdef ARGUSDEBUG
1585    ArgusDebug (4, "ArgusGenerateStatusMar(%p, %d) returning 0x%x", output, status, retn);
1586 #endif
1587 
1588    return (retn);
1589 }
1590 
1591 
1592 struct ArgusRecordStruct *
ArgusGenerateStatusMarRecord(struct ArgusOutputStruct * output,unsigned char status)1593 ArgusGenerateStatusMarRecord (struct ArgusOutputStruct *output, unsigned char status)
1594 {
1595    struct ArgusRecordStruct *retn = NULL;
1596    struct ArgusRecord *rec = NULL;
1597 
1598    while ((retn = (struct ArgusRecordStruct *) ArgusMallocListRecord (sizeof(*retn))) == NULL) {
1599       if (output && output->ArgusInputList) {
1600          if ((retn = (struct ArgusRecordStruct *) ArgusPopFrontList(output->ArgusInputList, ARGUS_LOCK)) != NULL) {
1601             ArgusFreeListRecord (retn);
1602          } else
1603             break;
1604       } else
1605          break;
1606    }
1607 
1608    if (retn) {
1609       extern int ArgusAllocTotal, ArgusFreeTotal, ArgusAllocBytes;
1610       struct ArgusSourceStruct *ArgusSrc = NULL, *aSrc = NULL;
1611       struct timeval now;
1612 
1613       memset(retn, 0, sizeof(*retn));
1614 
1615       retn->hdr.type    = ARGUS_MAR | ARGUS_VERSION;
1616       retn->hdr.cause   = status;
1617       retn->hdr.len     = (sizeof(struct ArgusMarStruct)/4) + 1;
1618 
1619       rec = (struct ArgusRecord *) &retn->canon;
1620 
1621       rec->hdr = retn->hdr;
1622       rec->argus_mar.argusid = getArgusID(ArgusSourceTask);
1623       switch (getArgusIDType(ArgusSourceTask)) {
1624          case ARGUS_TYPE_STRING: rec->argus_mar.status |= ARGUS_IDIS_STRING; break;
1625          case ARGUS_TYPE_INT:    rec->argus_mar.status |= ARGUS_IDIS_INT; break;
1626          case ARGUS_TYPE_IPV4:   rec->argus_mar.status |= ARGUS_IDIS_IPV4; break;
1627       }
1628 
1629       gettimeofday (&now, 0L);
1630 
1631       rec->argus_mar.startime.tv_sec  = output->ArgusLastMarUpdateTime.tv_sec;
1632       rec->argus_mar.startime.tv_usec = output->ArgusLastMarUpdateTime.tv_usec;
1633 
1634       rec->argus_mar.now.tv_sec  = now.tv_sec;
1635       rec->argus_mar.now.tv_usec = now.tv_usec;
1636 
1637       rec->argus_mar.major_version = VERSION_MAJOR;
1638       rec->argus_mar.minor_version = VERSION_MINOR;
1639       rec->argus_mar.reportInterval = getArgusFarReportInterval(output->ArgusModel)->tv_sec;
1640       rec->argus_mar.argusMrInterval = getArgusMarReportInterval(ArgusOutputTask)->tv_sec;
1641 
1642       rec->argus_mar.localnet = output->ArgusSrc->ArgusInterface[0].ArgusLocalNet;
1643       rec->argus_mar.netmask = output->ArgusSrc->ArgusInterface[0].ArgusNetMask;
1644 
1645       rec->argus_mar.nextMrSequenceNum = output->ArgusOutputSequence;
1646       rec->argus_mar.record_len = -1;
1647 
1648       if ((ArgusSrc = output->ArgusSrc) != NULL) {
1649          int x;
1650          for (x = 0; x < ARGUS_MAXINTERFACE; x++) {
1651             if ((aSrc = ArgusSrc->srcs[x]) != NULL) {
1652                if (aSrc->ArgusInterface[0].ArgusPd != NULL) {
1653                   int i;
1654                   rec->argus_mar.interfaceType = pcap_datalink(aSrc->ArgusInterface[0].ArgusPd);
1655                   rec->argus_mar.interfaceStatus = getArgusInterfaceStatus(aSrc);
1656 
1657                   rec->argus_mar.pktsRcvd  = 0;
1658                   rec->argus_mar.bytesRcvd = 0;
1659                   rec->argus_mar.dropped   = 0;
1660 
1661                   for (i = 0; i < ARGUS_MAXINTERFACE; i++) {
1662                      rec->argus_mar.pktsRcvd  += aSrc->ArgusInterface[i].ArgusTotalPkts -
1663                                                  aSrc->ArgusInterface[i].ArgusLastPkts;
1664                      rec->argus_mar.bytesRcvd += aSrc->ArgusInterface[i].ArgusTotalBytes -
1665                                                  aSrc->ArgusInterface[i].ArgusLastBytes;
1666                      rec->argus_mar.dropped   += aSrc->ArgusInterface[i].ArgusStat.ps_drop -
1667                                                  aSrc->ArgusInterface[i].ArgusLastDrop;
1668 
1669                      aSrc->ArgusInterface[i].ArgusLastPkts  = aSrc->ArgusInterface[i].ArgusTotalPkts;
1670                      aSrc->ArgusInterface[i].ArgusLastDrop  = aSrc->ArgusInterface[i].ArgusStat.ps_drop;
1671                      aSrc->ArgusInterface[i].ArgusLastBytes = aSrc->ArgusInterface[i].ArgusTotalBytes;
1672                   }
1673                }
1674             }
1675          }
1676       }
1677 
1678       rec->argus_mar.records = output->ArgusTotalRecords - output->ArgusLastRecords;
1679       output->ArgusLastRecords = output->ArgusTotalRecords;
1680 
1681       rec->argus_mar.flows = output->ArgusModel->ArgusTotalNewFlows - output->ArgusModel->ArgusLastNewFlows;
1682       output->ArgusModel->ArgusLastNewFlows = output->ArgusModel->ArgusTotalNewFlows;
1683 
1684       if (output->ArgusModel && output->ArgusModel->ArgusStatusQueue)
1685          rec->argus_mar.queue   = output->ArgusModel->ArgusStatusQueue->count;
1686       else
1687          rec->argus_mar.queue   = 0;
1688 
1689       if (output->ArgusOutputList)
1690          rec->argus_mar.output  = output->ArgusOutputList->count;
1691       else
1692          rec->argus_mar.output  = 0;
1693 
1694       rec->argus_mar.clients = output->ArgusClients->count;
1695 
1696       rec->argus_mar.bufs     = ArgusAllocTotal - ArgusFreeTotal;
1697       rec->argus_mar.bytes    = ArgusAllocBytes;
1698       rec->argus_mar.suserlen = getArgusUserDataLen(ArgusModel);
1699       rec->argus_mar.duserlen = getArgusUserDataLen(ArgusModel);
1700 
1701    }
1702 
1703 #ifdef ARGUSDEBUG
1704    ArgusDebug (4, "ArgusGenerateStatusMarRecord(%p, %d) returning 0x%x", output, status, retn);
1705 #endif
1706 
1707    return (retn);
1708 }
1709 
1710 
1711 struct timeval *
getArgusMarReportInterval(struct ArgusOutputStruct * output)1712 getArgusMarReportInterval(struct ArgusOutputStruct *output) {
1713    return (&output->ArgusMarReportInterval);
1714 }
1715 
1716 
1717 #include <ctype.h>
1718 #include <math.h>
1719 
1720 void
setArgusMarReportInterval(struct ArgusOutputStruct * output,char * value)1721 setArgusMarReportInterval(struct ArgusOutputStruct *output, char *value)
1722 {
1723    struct timeval *tvp = getArgusMarReportInterval(output);
1724 
1725    struct timeval ovalue, now;
1726    double thisvalue = 0.0, iptr, fptr;
1727    int ivalue = 0;
1728    char *ptr = NULL;;
1729 
1730    if (tvp != NULL) {
1731       ovalue = *tvp;
1732       tvp->tv_sec  = 0;
1733       tvp->tv_usec = 0;
1734    } else {
1735       ovalue.tv_sec  = 0;
1736       ovalue.tv_usec = 0;
1737    }
1738 
1739    if (((ptr = strchr (value, '.')) != NULL) || isdigit((int)*value)) {
1740       if (ptr != NULL) {
1741          thisvalue = atof(value);
1742       } else {
1743          if (isdigit((int)*value)) {
1744             ivalue = atoi(value);
1745             thisvalue = ivalue * 1.0;
1746          }
1747       }
1748 
1749       fptr =  modf(thisvalue, &iptr);
1750 
1751       tvp->tv_sec = iptr;
1752       tvp->tv_usec =  fptr * ARGUS_FRACTION_TIME;
1753 
1754       gettimeofday(&now, 0L);
1755 #if defined(ARGUS_NANOSECONDS)
1756       now.tv_usec *= 1000;
1757 #endif
1758       output->ArgusReportTime.tv_sec  = now.tv_sec + tvp->tv_sec;
1759       output->ArgusReportTime.tv_usec = tvp->tv_usec;
1760 
1761    } else
1762       *tvp = ovalue;
1763 
1764 #ifdef ARGUSDEBUG
1765    ArgusDebug (4, "setArgusMarReportInterval(%s) returning\n", value);
1766 #endif
1767 }
1768 
1769 
1770 #if defined HAVE_TCP_WRAPPER
1771 
1772 #if defined(HAVE_SYSLOG_H)
1773 #include <syslog.h>
1774 #endif
1775 
1776 #include <tcpd.h>
1777 
1778 #if !defined(MAXPATHNAMELEN)
1779 #define MAXPATHNAMELEN   BUFSIZ
1780 #endif
1781 
1782 #define PARANOID		1
1783 #define KILL_IP_OPTIONS		1
1784 #define HOSTS_ACCESS		1
1785 
1786 int allow_severity = LOG_INFO;     /* run-time adjustable */
1787 int deny_severity  = LOG_WARNING;   /* ditto */
1788 
1789 void fix_options(struct request_info *);
1790 
1791 #endif
1792 
1793 int
ArgusTcpWrapper(int fd,struct sockaddr * from)1794 ArgusTcpWrapper (int fd, struct sockaddr *from)
1795 {
1796 #if defined(HAVE_TCP_WRAPPER)
1797    int retn = 0;
1798    struct request_info request;
1799 
1800    /*
1801     * Find out the endpoint addresses of this conversation. Host name
1802     * lookups and double checks will be done on demand.
1803     */
1804 
1805    request_init(&request, RQ_DAEMON, ArgusProgramName, RQ_FILE, STDIN_FILENO, 0);
1806    request.fd = fd;
1807    fromhost(&request);
1808 
1809    /*
1810     * Optionally look up and double check the remote host name. Sites
1811     * concerned with security may choose to refuse connections from hosts
1812     * that pretend to have someone elses host name.
1813     */
1814 
1815 #ifdef PARANOID
1816    if (STR_EQ(eval_hostname(request.client), paranoid)) {
1817       ArgusLog (deny_severity, "refused connect from %s", eval_client(&request));
1818       if (request.sink)
1819          request.sink(request.fd);
1820       return -1;
1821    }
1822 #endif
1823 
1824     /*
1825      * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
1826      * socket options at the IP level. They do so for a good reason.
1827      * Unfortunately, we cannot use this with SunOS 4.1.x because the
1828      * getsockopt() system call can panic the system.
1829      */
1830 
1831 #if defined(KILL_IP_OPTIONS)
1832    fix_options(&request);
1833 #endif /* KILL_IP_OPTIONS */
1834 
1835     /*
1836      * Find out and verify the remote host name. Sites concerned with
1837      * security may choose to refuse connections from hosts that pretend to
1838      * have someone elses host name.
1839      */
1840 
1841 #ifdef HOSTS_ACCESS
1842    if (!hosts_access(&request)) {
1843       ArgusLog  (deny_severity, "refused connect from %s", eval_client(&request));
1844       if (request.sink)
1845          request.sink(request.fd);
1846       return -1;
1847    } else
1848 #endif
1849 
1850     /* Report remote client */
1851    ArgusLog  (allow_severity, "connect from %s", eval_client(&request));
1852    return (retn);
1853 
1854 #else
1855    return (1);
1856 #endif /* HAVE_TCP_WRAPPER */
1857 }
1858 
1859 
1860 #if defined(ARGUS_SASL)
1861 /* This creates a structure that defines the allowable
1862  *   security properties
1863  */
1864 #define PROT_BUFSIZE 4096
1865 sasl_security_properties_t *
mysasl_secprops(int flags)1866 mysasl_secprops(int flags)
1867 {
1868     static sasl_security_properties_t ret;
1869 
1870     bzero((char *)&ret, sizeof(ret));
1871 
1872     ret.maxbufsize = PROT_BUFSIZE;
1873     ret.min_ssf = ArgusMinSsf; /* minimum allowable security strength */
1874     ret.max_ssf = ArgusMaxSsf; /* maximum allowable security strength */
1875 
1876     ret.security_flags = flags;
1877 
1878     ret.property_names = NULL;
1879     ret.property_values = NULL;
1880 
1881     return &ret;
1882 }
1883 
1884 int
iptostring(const struct sockaddr * addr,socklen_t addrlen,char * out,unsigned outlen)1885 iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned outlen)
1886 {
1887     char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
1888     int niflags;
1889 
1890     if(!addr || !out) {
1891         errno = EINVAL;
1892         return -1;
1893     }
1894 
1895     niflags = NI_NUMERICHOST | NI_NUMERICSERV;
1896 #ifdef NI_WITHSCOPEID
1897     if (addr->sa_family == AF_INET6)
1898         niflags |= NI_WITHSCOPEID;
1899 #endif
1900     if (getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1901                     niflags) != 0) {
1902         errno = EINVAL;
1903         return -1;
1904     }
1905 
1906     if(outlen < strlen(hbuf) + strlen(pbuf) + 2) {
1907         errno = ENOMEM;
1908         return -1;
1909     }
1910 
1911     snprintf(out, outlen, "%s;%s", hbuf, pbuf);
1912 
1913     return 0;
1914 }
1915 #endif
1916