1 /*
2 * Copyright (c) 2001 Mark Fullmer and The Ohio State University
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: flow-capture.c,v 1.78 2004/01/05 17:56:50 maf Exp $
27 */
28
29 #include "ftconfig.h"
30 #include <ftlib.h>
31
32 #include <sys/time.h>
33 #include <sys/types.h>
34 #include <sys/uio.h>
35 #include <sys/socket.h>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <sys/wait.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <signal.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <time.h>
48 #include <syslog.h>
49
50 #if HAVE_STRINGS_H
51 #include <strings.h>
52 #endif
53
54 #if HAVE_STRING_H
55 #include <string.h>
56 #endif
57
58 #ifdef HAVE_LIBWRAP
59 #include <tcpd.h>
60 #endif /* HAVE_LIBWRAP */
61
62 void fterr_exit_handler(int code);
63
64 #define CAPTURE_PIDFILE "/var/run/flow-capture.pid"
65
66 #define SELECT_TIMEOUT 1 /* 1 second */
67
68 struct client_rec {
69 int fd;
70 struct sockaddr_in addr;
71 int flags;
72 time_t conn_time;
73 struct ftio ftio;
74 FT_LIST_ENTRY (client_rec) chain;
75 };
76
77 struct client {
78 FT_LIST_HEAD(clienth, client_rec) list;
79 struct sockaddr_in addr;
80 int fd;
81 int enabled; /* listen socket enabled? */
82 int max; /* max connections */
83 int active; /* active connections */
84 #ifdef HAVE_LIBWRAP
85 struct request_info tcpd;
86 #endif /* HAVE_LIBWRAP */
87 };
88
89 struct rotate {
90 double next; /* time of next rotation */
91 int cur; /* current rotation # */
92 int n; /* number per day */
93 };
94
95 struct file {
96 int fd; /* file descriptor */
97 char name[MAXPATHLEN+1]; /* name */
98 char nname[MAXPATHLEN+1]; /* new name */
99 time_t time;
100 struct ftver ftv;
101 off_t nbytes;
102 uint32_t hdr_nflows;
103 uint32_t hdr_flows_corrupt;
104 uint32_t hdr_flows_lost;
105 uint32_t hdr_flows_reset;
106 };
107
108 int debug;
109 int sig_pipe_flag, sig_quit_flag, sig_hup_flag, sig_chld_flag, sig_term_flag;
110 int reload_flag;
111 void sig_pipe(int);
112 void sig_quit(int);
113 void sig_hup(int);
114 void sig_chld(int);
115 void sig_term(int);
116 pid_t pid;
117 char *pidfile;
118 struct ftnet ftnet;
119
120 void usage(void);
121 int calc_rotate (int next, double *trotate, int *cur);
122 double doubletime(void);
123
main(argc,argv)124 int main(argc, argv)
125 int argc;
126 char **argv;
127 {
128 #ifdef IP_ADD_MEMBERSHIP
129 struct ip_mreq mr;
130 #ifdef IP_ADD_SOURCE_MEMBERSHIP
131 struct ip_mreq_source mrs;
132 #endif
133 #endif
134 fd_set rfd;
135 struct sockaddr_in tmp_addr;
136 struct timeval tv;
137 struct tm *tm;
138 struct ftset ftset;
139 struct ftfile_entries fte;
140 struct client client;
141 struct ftio ftio;
142 struct ftpdu ftpdu;
143 struct ftpeeri ftpi;
144 struct ftver ftv;
145 struct ftchash *ftch;
146 struct ftchash_rec_exp ftch_recexp, *ftch_recexpp;
147 struct rotate rot;
148 struct file cap_file;
149 struct fttag fttag;
150 struct ftfil ftfil;
151 struct ftxlate ftxlate;
152 struct fttag_def *ftd;
153 struct ftfil_def *ftfd;
154 struct ftvar ftvar;
155 struct ftxlate_def *ftxd;
156 struct fts3rec_offsets fo;
157 struct client_rec *client_rec, *client_rec2;
158 pid_t child_pid;
159 time_t tt_now, time_startup;
160 double now;
161 char work_dir[MAXPATHLEN+1], post_rotate_exec[MAXPATHLEN+1];
162 int i, n, tmp_len, enable_unlink, offset, detach, nest, one, max_fd;
163 unsigned int v1, v2;
164 uint32_t hash;
165 char fmt_src_ip[32], fmt_dst_ip[32], fmt_dst_port[32];
166 char xl_rec[FT_IO_MAXREC], *out_rec;
167 const char *tag_fname, *tag_active;
168 const char *filter_fname, *filter_active;
169 const char *xlate_fname, *xlate_active;
170 int stat_interval, stat_next, child_status;
171 int v_flag;
172 int preserve_umask;
173 #ifdef IP_RECVDSTADDR
174 #ifdef CMSG_DATA
175 struct cmsghdr *cmsg;
176 #endif
177 #endif
178
179 time_startup = time(NULL);
180
181 bzero (&rot, sizeof rot);
182 bzero (&cap_file, sizeof cap_file);
183 bzero (&ftnet, sizeof ftnet);
184 bzero (&tv, sizeof tv);
185 bzero (&work_dir, sizeof work_dir);
186 bzero (&post_rotate_exec, sizeof post_rotate_exec);
187 bzero (&fte, sizeof fte);
188 bzero (&client, sizeof client);
189 bzero (&ftpdu, sizeof ftpdu);
190 bzero (&ftv, sizeof ftv);
191 bzero (&fttag, sizeof fttag);
192 bzero (&ftfil, sizeof ftfil);
193 bzero (&ftxlate, sizeof ftxlate);
194 bzero (&ftvar, sizeof ftvar);
195
196 FT_LIST_INIT(&client.list);
197 stat_interval = 0;
198 stat_next = -1;
199 v_flag = 0;
200 reload_flag = 1;
201 preserve_umask = 0;
202
203 tag_fname = FT_PATH_CFG_TAG;
204 tag_active = (char*)0L;
205
206 filter_fname = FT_PATH_CFG_FILTER;
207 filter_active = (char*)0L;
208
209 xlate_fname = FT_PATH_CFG_XLATE;
210 xlate_active = (char*)0L;
211
212 ftfd = (struct ftfil_def*)0L;
213 ftd = (struct fttag_def*)0L;
214 ftxd = (struct ftxlate_def*)0L;
215
216 /* init fterr */
217 fterr_setid(argv[0]);
218 fterr_setexit(fterr_exit_handler);
219
220 /* init var binding */
221 if (ftvar_new(&ftvar) < 0)
222 fterr_errx(1, "ftvar_new(): failed");
223
224 /* defaults + default compression */
225 ftset_init(&ftset, Z_DEFAULT_COMPRESSION);
226
227 /* default timeout waiting for an active fd */
228 tv.tv_sec = SELECT_TIMEOUT;
229
230 /* listen for PDU's */
231 ftnet.loc_addr.sin_family = AF_INET;
232 ftnet.loc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
233 ftnet.loc_addr.sin_port = htons(FT_PORT);
234
235 /* listen for clients */
236 client.addr.sin_family = AF_INET;
237 client.addr.sin_addr.s_addr = htonl(INADDR_ANY);
238 client.addr.sin_port = htons(FT_PORT);
239
240 /* default detach from parent */
241 detach = 1;
242
243 /* default 95 rotations per day, or every 15 minutes */
244 rot.n = 95;
245
246 /* no files initially open */
247 cap_file.fd = -1;
248
249 /* year/month/day nesting */
250 nest = 3;
251
252 /* pidfile */
253 pidfile = CAPTURE_PIDFILE;
254
255 while ((i = getopt(argc, argv,
256 "b:c:C:d:De:E:f:F:hn:N:p:S:t:T:uv:V:w:x:X:z:R:")) != -1)
257
258 switch (i) {
259
260 case 'b': /* output byte order */
261 if (!strcasecmp(optarg, "little"))
262 ftset.byte_order = FT_HEADER_LITTLE_ENDIAN;
263 else if (!strcasecmp(optarg, "big"))
264 ftset.byte_order = FT_HEADER_BIG_ENDIAN;
265 else
266 fterr_errx(1, "expecting \"big\" or \"little\" at -b");
267 break;
268
269 case 'c': /* client enable */
270 client.max = atoi(optarg);
271 break;
272
273 case 'C': /* comment field */
274 ftset.comments = optarg;
275 break;
276
277 case 'D': /* daemonize */
278 detach = 0;
279 pidfile = (char*)0L;
280 break;
281
282 case 'e': /* expire */
283 fte.max_files = atoi(optarg);
284 if (fte.max_files)
285 fte.expiring = 1;
286 break;
287
288 case 'E': /* expire bytes */
289 if ((fte.max_bytes = scan_size(optarg)) == -1)
290 fterr_errx(1, "scan_size(): failed");
291 if (fte.max_bytes)
292 fte.expiring = 1;
293 break;
294
295 case 'f': /* filter fname */
296 filter_fname = optarg;
297 break;
298
299 case 'F': /* filter active */
300 filter_active = optarg;
301 break;
302
303 case 'd': /* debug */
304 debug = atoi(optarg);
305 break;
306
307 case 'h': /* help */
308 usage();
309 exit (0);
310 break;
311
312 case 'n': /* # rotations / day */
313 rot.n = atoi(optarg);
314 /* no more than 1 rotation per minute */
315 if (rot.n > (1440-1))
316 fterr_errx(1, "rotations limited to every 1 minute");
317 break;
318
319 case 'N': /* nesting level */
320 nest = atoi(optarg);
321 if ((nest < -3) || (nest > 3))
322 fterr_errx(1, "-3 <= nesting level <= 3");
323 break;
324
325 case 'p': /* pidfile */
326 if ((optarg[0] == 0) || ((optarg[0] == '-') && (optarg[1] == 0)))
327 pidfile = (char*)0L;
328 else
329 pidfile = optarg;
330 break;
331
332 case 'R': /* Post rotate exec */
333 if (strlen(optarg) > MAXPATHLEN)
334 fterr_errx(1, "Post rotate argument too long");
335 strcpy(post_rotate_exec,optarg);
336 break;
337
338 case 'S': /* stat interval */
339 stat_interval = atoi(optarg);
340 if ((stat_interval < 0) || (stat_interval > 60))
341 fterr_errx(1, "Stat interval must be between 0 and 60.");
342 break;
343
344 case 't': /* tag filename */
345 tag_fname = optarg;
346 break;
347
348 case 'T': /* active tags */
349 tag_active = optarg;
350 /* required for fttag_eval() */
351 ftv.s_version = FT_IO_SVERSION;
352 ftv.d_version = 1005;
353 ftv.set = 1;
354 break;
355
356 case 'u': /* preserve inherited umask */
357 preserve_umask = 1;
358 break;
359
360 case 'v': /* variable */
361 if (ftvar_pset(&ftvar, optarg) < 0)
362 fterr_errx(1, "ftvar_pset(%s): failed", optarg);
363 break;
364
365 case 'V': /* PDU version */
366 v_flag = 1;
367 n = sscanf(optarg, "%u.%u", &v1, &v2);
368 if (n == 1) {
369 ftv.s_version = FT_IO_SVERSION;
370 ftv.d_version = v1;
371 ftv.set = 1;
372 } else if (n == 2) {
373 ftv.s_version = FT_IO_SVERSION;
374 ftv.d_version = v1;
375 ftv.agg_method = v2;
376 ftv.agg_version = 2;
377 ftv.set = 1;
378 } else {
379 fterr_errx(1, "Version scan failed");
380 }
381 break;
382
383 case 'w': /* working directory */
384 if (strlen(optarg) > (MAXPATHLEN))
385 fterr_errx(1, "Pathname too long");
386 strcpy(work_dir, optarg);
387 break;
388
389 case 'x': /* xlate file name */
390 xlate_fname = optarg;
391 break;
392
393 case 'X': /* xlate definition name */
394 xlate_active = optarg;
395 break;
396
397 case 'z': /* compress level */
398 ftset.z_level = atoi(optarg);
399 if ((ftset.z_level < 0) || (ftset.z_level > 9))
400 fterr_errx(1, "Compression level must be between 0 and 9");
401 break;
402
403 default:
404 usage();
405 exit (1);
406 break;
407
408 } /* switch */
409
410 /* disable pidfile if not forking */
411 if (!detach)
412 pidfile = (char*)0L;
413
414 if ((argc - optind) != 1)
415 fterr_errx(1, "Specify localip/remoteip/port.");
416
417 /* tagging forces v1005 */
418 if (v_flag && tag_active && (ftv.d_version != 1005))
419 fterr_errx(1, "Must be v1005 with tagging.");
420
421 if (!work_dir[0])
422 fterr_errx(1, "Specify workdir with -w.");
423
424 ftpi = scan_peeri(argv[optind]);
425
426 ftnet.rem_ip = ftpi.rem_ip;
427 ftnet.loc_ip = ftpi.loc_ip;
428
429 if (ftpi.dst_port)
430 ftnet.dst_port = ftpi.dst_port;
431 else
432 ftnet.dst_port = FT_PORT;
433
434 ftnet.loc_addr.sin_addr.s_addr = htonl(ftpi.loc_ip);
435 ftnet.loc_addr.sin_port = htons(ftnet.dst_port);
436 client.addr.sin_port = htons(ftnet.dst_port);
437
438 /* if debugging is enabled do not unlink any files when aging */
439 if (debug)
440 enable_unlink = 0;
441 else
442 enable_unlink = 1;
443
444 /* daemonize */
445 if (detach) {
446 if ((pid = fork()) == -1) {
447 fterr_err(1, "fork()");
448 } else if (pid) {
449 exit (0); /* parent */
450 }
451
452 if (!preserve_umask)
453 umask(0022);
454
455 setsid();
456
457 for (n = 0; n < 16; ++n)
458 close (n);
459
460 /* enable syslog */
461 fterr_setsyslog(1, LOG_PID|LOG_NDELAY, LOG_LOCAL6);
462
463 /* disable stderr */
464 fterr_setfile(0, (void*)0L);
465
466 }
467
468 /*
469 * configure signal handlers
470 */
471
472 if (mysignal(SIGPIPE, sig_pipe) == SIG_ERR)
473 fterr_err(1, "signal(SIGPIPE)");
474
475 if (mysignal(SIGHUP, sig_hup) == SIG_ERR)
476 fterr_err(1, "signal(SIGHUP)");
477
478 if (mysignal(SIGQUIT, sig_quit) == SIG_ERR)
479 fterr_err(1, "signal(SIGQUIT)");
480
481 if (mysignal(SIGTERM, sig_term) == SIG_ERR)
482 fterr_err(1, "signal(SIGTERM)");
483
484 if (mysignal(SIGCHLD, sig_chld) == SIG_ERR)
485 fterr_err(1, "signal(SIGCHLD)");
486
487 /* sandbox */
488 if (chdir(work_dir) == -1)
489 fterr_err(1, "chdir(%s)", work_dir);
490
491 /*
492 * load directory entries into the file ager
493 */
494 if (fte.expiring)
495 if (ftfile_loaddir(&fte, ".", FT_FILE_SORT|FT_FILE_INIT|FT_FILE_CHECKNAMES))
496 fterr_errx(1, "ftfile_scandir(): failed");
497
498 /* debugging gets a dump of the ager */
499 if (debug)
500 ftfile_dump(&fte);
501
502 /* run the ager once now */
503 if (fte.expiring)
504 if (ftfile_expire(&fte, enable_unlink, (uint32_t)0))
505 fterr_errx(1, "ftfile_export(): failed");
506
507 /* get hostname */
508 if (gethostname((char*)&ftset.hnbuf, FT_HOSTNAME_LEN-1) == -1)
509 fterr_err(1, "gethostname()");
510
511 /* ensure null terminated */
512 ftset.hnbuf[FT_HOSTNAME_LEN-1] = 0;
513
514 /* socket to receive flow pdu exports */
515 if ((ftnet.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
516 fterr_err(1, "socket()");
517
518 if (bigsockbuf(ftnet.fd, SO_RCVBUF, FT_SO_RCV_BUFSIZE) < 0)
519 fterr_err(1, "bigsockbuf()");
520
521 /* multicast capable? */
522 #ifdef IP_ADD_MEMBERSHIP
523
524 if (IN_CLASSD(ftpi.rem_ip)) {
525
526 /* source is the first arg now */
527 ftnet.rem_ip = ftpi.loc_ip;
528 ftnet.loc_ip = ftpi.rem_ip;
529
530 /* socket API usually requires INADDR_ANY
531 * and s/g/port identifier does not have a source interface field
532 * to use here
533 */
534 bzero(&tmp_addr, sizeof tmp_addr);
535 tmp_addr.sin_family = AF_INET;
536 tmp_addr.sin_port = htons(ftnet.dst_port);
537
538 one = 1;
539
540 /* Multicast streams may have multiple receivers */
541 if (setsockopt(ftnet.fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
542 sizeof(one)) < 0)
543 fterr_err(1, "setsockopt(SO_REUSEADDR)");
544
545 if (bind(ftnet.fd, (struct sockaddr*)&tmp_addr,
546 sizeof(struct sockaddr)) < 0)
547 fterr_err(1, "bind(%s)", inet_ntoa(tmp_addr.sin_addr));
548
549 #ifdef IP_ADD_SOURCE_MEMBERSHIP
550
551 /* ssm address? */
552 if (IN_CLASSD_SSM(ftpi.rem_ip)) {
553
554 mrs.imr_sourceaddr.s_addr = htonl(ftpi.loc_ip);
555 mrs.imr_multiaddr.s_addr = htonl(ftpi.rem_ip);
556 mrs.imr_interface.s_addr = INADDR_ANY;
557
558 if (setsockopt(ftnet.fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
559 (char*)&mrs, sizeof(mrs)) < 0)
560 fterr_err(1, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP)");
561
562 }
563
564 goto mcast_done;
565 #endif /* IP_ADD_SOURCE_MEMBERSHIP */
566
567 mr.imr_multiaddr.s_addr = htonl(ftpi.rem_ip);
568 mr.imr_interface.s_addr = INADDR_ANY;
569
570 if (setsockopt(ftnet.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
571 (char *)&mr, sizeof(mr)) < 0)
572 fterr_err(1, "setsockopt(IP_ADD_MEMBERSHIP)");
573
574
575 } else { /* is a multicast group */
576
577 /* unicast bind -- multicast support */
578 if (bind(ftnet.fd, (struct sockaddr*)&ftnet.loc_addr,
579 sizeof(ftnet.loc_addr)) < 0)
580 fterr_err(1, "bind(%s)", inet_ntoa(ftnet.loc_addr.sin_addr));
581
582 } /* not multicast group */
583
584 #ifdef IP_ADD_SOURCE_MEMBERSHIP
585 mcast_done:
586 #endif /* IP_ADD_SOURCE_MEMBERSHIP */
587
588 #else /* IP_ADD_MEMBERSHIP */
589
590 /* unicast bind -- no multicast support */
591 if (bind(ftnet.fd, (struct sockaddr*)&ftnet.loc_addr,
592 sizeof(ftnet.loc_addr)) < 0)
593 fterr_err(1, "bind(%s)", inet_ntoa(ftnet.loc_addr.sin_addr)));
594
595 #endif /* IP_ADD_MEMBERSHIP */
596
597 #ifdef IP_RECVDSTADDR
598 one = 1;
599 /* return the destination IP address */
600 if (setsockopt(ftnet.fd, IPPROTO_IP, IP_RECVDSTADDR, (char *)&one,
601 sizeof(one)) < 0)
602 fterr_err(1, "setsockopt(IP_RECVDSTADDR)");
603 #else
604 #ifdef IP_PKTINFO
605 one = 1;
606 /* return the destination IP address */
607 if (setsockopt(ftnet.fd, IPPROTO_IP, IP_PKTINFO, (char *)&one,
608 sizeof(one)) < 0)
609 fterr_err(1, "setsockopt(IP_PKTINFO)");
610 #endif /* else */
611 #endif /* IP_RECVDSTADDR */
612
613 /* init hash table for demuxing exporters */
614 if (!(ftch = ftchash_new(256, sizeof (struct ftchash_rec_exp), 12, 1)))
615 fterr_errx(1, "ftchash_new(): failed");
616
617 /* If we bind to the socket we are running and can write the pidfile */
618 if (pidfile)
619 write_pidfile(getpid(), pidfile, ftnet.dst_port);
620
621 /* init msg block */
622 ftnet.iov[0].iov_len = sizeof ftpdu.buf;
623 ftnet.iov[0].iov_base = (char*)&ftpdu.buf;
624 ftnet.msg.msg_iov = (struct iovec*)&ftnet.iov;
625 ftnet.msg.msg_iovlen = 1;
626 ftnet.msg.msg_name = &ftnet.rem_addr;
627 ftnet.msg.msg_namelen = sizeof ftnet.rem_addr;
628 ftnet.msg.msg_control = &ftnet.msgip;
629
630 #ifdef CMSG_DATA
631 ftnet.msg.msg_controllen = CMSG_LEN(sizeof(struct sockaddr_storage));
632 #else
633 ftnet.msg.msg_controllen = sizeof ftnet.msgip;
634 #endif
635
636 while (1) {
637
638 FD_ZERO (&rfd);
639 FD_SET (ftnet.fd, &rfd);
640
641 if (client.enabled && client.max) {
642 FD_SET (client.fd, &rfd);
643 max_fd = (client.fd > ftnet.fd) ? client.fd : ftnet.fd;
644 } else {
645 max_fd = ftnet.fd;
646 }
647
648 if (select (max_fd+1, &rfd, (fd_set *)0, (fd_set *)0, &tv) < 0) {
649 if (errno == EINTR) {
650 FD_ZERO (&rfd);
651 } else {
652 fterr_err(1, "select()");
653 }
654 }
655
656 bzero (&tv, sizeof tv);
657 tv.tv_sec = SELECT_TIMEOUT;
658
659 tt_now = now = doubletime();
660
661 /* new TCP client connection ? */
662 if ((client.max) && (FD_ISSET(client.fd, &rfd))) {
663
664 /* too many clients? */
665 if (client.active >= client.max) {
666 /* bye */
667 i = accept(client.fd, (struct sockaddr*)&tmp_addr,
668 (socklen_t*)&tmp_len);
669 close(i);
670 fterr_warnx("Maximum clients exceeded, rejecting connection from %s",
671 inet_ntoa(tmp_addr.sin_addr));
672 goto skip_client;
673 }
674
675 /* allocate a new client record, fail gracefully */
676 if (!(client_rec = (struct client_rec*)malloc(sizeof *client_rec))) {
677 fterr_warn("malloc()");
678 /* bye */
679 tmp_len = sizeof (struct sockaddr_in);
680 i = accept(client.fd, (struct sockaddr*)&client_rec->addr,
681 (socklen_t*)&tmp_len);
682 close(i);
683 goto skip_client;
684 }
685
686 bzero(client_rec, sizeof *client_rec);
687
688 /* link in the new record */
689 FT_LIST_INSERT_HEAD(&client.list, client_rec, chain);
690
691 tmp_len = sizeof (struct sockaddr_in);
692 /* accept() the connection */
693 if ((client_rec->fd = accept(client.fd,
694 (struct sockaddr*)&client_rec->addr, (socklen_t*)&tmp_len)) < 0) {
695 fterr_warn("accept()");
696 FT_LIST_REMOVE(client_rec, chain);
697 free(client_rec);
698 goto skip_client;
699 }
700
701 #ifdef HAVE_LIBWRAP
702
703 request_init(&client.tcpd, RQ_DAEMON, "flow-capture-client", RQ_FILE,
704 client_rec->fd, NULL);
705
706 fromhost(&client.tcpd);
707
708 if (!hosts_access(&client.tcpd)) {
709
710 fterr_warnx("client %s refused by libwrap",
711 inet_ntoa(client_rec->addr.sin_addr));
712
713 close(client_rec->fd);
714
715 FT_LIST_REMOVE(client_rec, chain);
716 free(client_rec);
717
718 goto skip_client;
719
720 }
721
722 #endif /* HAVE_LIBWRAP */
723
724 if (bigsockbuf(client_rec->fd, SO_SNDBUF, FT_SO_SND_BUFSIZE) < 0)
725 fterr_warn("bigsockbuf()");
726
727 /* log it */
728 client_rec->conn_time = tt_now;
729 fterr_info("client connect: ip=%s time=%lu",
730 inet_ntoa(client_rec->addr.sin_addr),
731 (unsigned long)client_rec->conn_time);
732
733 /* ftio_init the stream */
734 if (ftio_init(&client_rec->ftio, client_rec->fd,
735 FT_IO_FLAG_NO_SWAP | FT_IO_FLAG_WRITE) < 0) {
736 fterr_warnx("ftio_init(): failed for client");
737 close(client_rec->fd);
738 FT_LIST_REMOVE(client_rec, chain);
739 free(client_rec);
740 goto skip_client;
741 }
742
743 /* set the version information in the io stream */
744 if (ftio_set_ver(&client_rec->ftio, &ftv) < 0)
745 fterr_errx(1, "ftio_set_ver(): failed");
746
747 ftio_set_comment(&client_rec->ftio, ftset.comments);
748 ftio_set_cap_hostname(&client_rec->ftio, ftset.hnbuf);
749 ftio_set_byte_order(&client_rec->ftio, ftset.byte_order);
750 ftio_set_cap_time(&client_rec->ftio, cap_file.time, 0);
751 ftio_set_debug(&client_rec->ftio, debug);
752
753 /* header first */
754 if ((n = ftio_write_header(&client_rec->ftio)) < 0) {
755 fterr_warnx("ftio_write_header(): failed for client");
756 ftio_close(&client_rec->ftio);
757 FT_LIST_REMOVE(client_rec, chain);
758 free(client_rec);
759 goto skip_client;
760 }
761
762 ++client.active;
763
764 } /* new TCP client */
765
766 skip_client:
767
768 /* stake the zombies */
769
770 if (sig_chld_flag) {
771
772 /* not again */
773 sig_chld_flag = 0;
774
775 while (1) {
776
777 child_pid = wait3(&child_status, WNOHANG, 0);
778
779 /* no more dead children? */
780 if (!child_pid)
781 break;
782
783 /* no more dead children? */
784 if ((child_pid == -1) && (errno == ECHILD))
785 break;
786
787 if (WIFEXITED(child_status)) {
788
789 if (WEXITSTATUS(child_status))
790 fterr_warnx("Child %d exit_status=%d", (int)child_pid,
791 WEXITSTATUS(child_status));
792
793 } else if (WIFSIGNALED(child_status)) {
794
795 fterr_warnx("Child %d signal=%d", (int)child_pid,
796 WTERMSIG(child_status));
797
798 } else {
799
800 fterr_warnx("PID %d exited status=%d", (int)child_pid,
801 child_status);
802
803 }
804
805 } /* buffy */
806
807 } /* sig_chld_flag */
808
809 if (stat_interval) {
810
811 tm = localtime (&tt_now);
812
813 /*
814 * note there is an obscure race condition here if this
815 * code is not reached at least every stat_interval*60 seconds
816 * where up to 1 hour of STAT lines would not show up.
817 * This is highly unlikely and not handled.
818 */
819
820 if ((tm->tm_min == stat_next) || (stat_next == -1)) {
821
822 ftchash_first(ftch);
823
824 while ((ftch_recexpp = ftchash_foreach(ftch))) {
825
826 fmt_ipv4(fmt_src_ip, ftch_recexpp->src_ip, FMT_JUST_LEFT);
827 fmt_ipv4(fmt_dst_ip, ftch_recexpp->dst_ip, FMT_JUST_LEFT);
828
829 fterr_info(
830 "STAT: now=%lu startup=%lu src_ip=%s dst_ip=%s d_ver=%d pkts=%lu flows=%lu lost=%lu reset=%lu filter_drops=%lu",
831 (unsigned long)tt_now, (unsigned long)time_startup,
832 fmt_src_ip, fmt_dst_ip,
833 ftch_recexpp->d_version, (u_long)ftch_recexpp->packets,
834 (u_long)ftch_recexpp->flows, (u_long)ftch_recexpp->lost,
835 (u_long)ftch_recexpp->reset, (u_long)ftch_recexpp->filtered_flows);
836
837 }
838
839 stat_next = (tm->tm_min + (stat_interval - tm->tm_min % stat_interval))
840 % 60;
841
842 }
843
844 } /* stat_inverval */
845
846 /* flag for work later on */
847 ftpdu.ftd.count = 0;
848
849 /* PDU ready */
850 if (FD_ISSET(ftnet.fd, &rfd)) {
851
852 restart_recvmsg:
853
854 if ((ftpdu.bused = recvmsg(ftnet.fd,
855 (struct msghdr*)&ftnet.msg, 0)) < 0) {
856
857 if (errno == EAGAIN)
858 goto restart_recvmsg;
859
860 fterr_err(1, "recvmsg()");
861
862 }
863
864 #ifdef IP_RECVDSTADDR
865 /* got destination IP back? */
866 #ifdef CMSG_DATA
867 for (cmsg = CMSG_FIRSTHDR(&ftnet.msg); cmsg != NULL;
868 cmsg = CMSG_NXTHDR(&ftnet.msg, cmsg)) {
869 if (cmsg->cmsg_level == IPPROTO_IP &&
870 cmsg->cmsg_type == IP_RECVDSTADDR) {
871 memcpy(&ftnet.loc_addr.sin_addr.s_addr,
872 CMSG_DATA(cmsg), sizeof(struct in_addr));
873 break;
874 }
875 }
876 #else
877 if ((ftnet.msgip.hdr.cmsg_level == IPPROTO_IP) &&
878 (ftnet.msgip.hdr.cmsg_type == IP_RECVDSTADDR)) {
879 ftnet.loc_addr.sin_addr.s_addr = ftnet.msgip.ip.s_addr;
880 } else {
881 ftnet.loc_addr.sin_addr.s_addr = 0;
882 }
883 #endif /* CMSG_DATA */
884 #else
885 #ifdef IP_PKTINFO
886 if ((ftnet.msgip.hdr.cmsg_level == IPPROTO_IP) &&
887 (ftnet.msgip.hdr.cmsg_type == IP_PKTINFO)) {
888 ftnet.loc_addr.sin_addr.s_addr = ftnet.msgip.pktinfo.ipi_addr.s_addr;
889 } else {
890 ftnet.loc_addr.sin_addr.s_addr = 0;
891 }
892 #else
893 ftnet.loc_addr.sin_addr.s_addr = 0;
894 #endif
895 #endif /* IP_RECVDSTADDR */
896
897 /* fill in hash key */
898 ftch_recexp.src_ip = htonl(ftnet.rem_addr.sin_addr.s_addr);
899 ftch_recexp.dst_ip = htonl(ftnet.loc_addr.sin_addr.s_addr);
900 ftch_recexp.dst_port = ftnet.dst_port;
901
902 /* verify integrity, get version */
903 if (ftpdu_verify(&ftpdu) < 0) {
904 fmt_ipv4(fmt_src_ip, ftch_recexp.src_ip, FMT_JUST_LEFT);
905 fterr_warnx("ftpdu_verify(): src_ip=%s failed.", fmt_src_ip);
906 ++cap_file.hdr_flows_corrupt;
907 goto skip_pdu_decode;
908 }
909
910 /* rest of hash key */
911 ftch_recexp.d_version = ftpdu.ftv.d_version;
912
913 /* if exporter src IP has been configured then make sure it matches */
914 if (ftnet.rem_ip && (ftnet.rem_ip != ftch_recexp.src_ip)) {
915 fmt_ipv4(fmt_src_ip, ftch_recexp.src_ip, FMT_JUST_LEFT);
916 fterr_warnx("Unexpected PDU: src_ip=%s not configured", fmt_src_ip);
917 ++cap_file.hdr_flows_corrupt;
918 goto skip_pdu_decode;
919 }
920
921 /* first flow or no configured destination version? */
922 if (!ftv.set) {
923
924 /* copy to compare next time */
925 bcopy(&ftpdu.ftv, &ftv, sizeof ftv);
926
927 /* flag struct as configured */
928 ftv.set = 1;
929
930 } else {
931
932 /* translation to/from v8 not possible */
933 if (((ftv.d_version == 8) && (ftpdu.ftv.d_version != 8)) ||
934 ((ftv.d_version != 8) && (ftpdu.ftv.d_version == 8))) {
935 fmt_ipv4(fmt_src_ip, ftch_recexp.dst_ip, FMT_JUST_LEFT);
936 fterr_warnx("Unexpected PDU: src_ip=%s no v8 translation",
937 fmt_src_ip);
938 cap_file.hdr_flows_corrupt ++;
939 goto skip_pdu_decode;
940 }
941
942 /* translation among v8 aggregation methods not possible */
943 if ((ftv.d_version == 8) && ((ftv.agg_method != ftpdu.ftv.agg_method)
944 || (ftv.agg_version != ftpdu.ftv.agg_version))) {
945 fmt_ipv4(fmt_src_ip, ftch_recexp.dst_ip, FMT_JUST_LEFT);
946 fterr_warnx(
947 "Unexpected PDU: src_ip=%s multi v8 oagg=%d agg=%d over=%d ver=%d",
948 fmt_src_ip, (int)ftv.agg_method, (int)ftpdu.ftv.agg_method,
949 (int)ftv.agg_version, (int)ftpdu.ftv.agg_version);
950 cap_file.hdr_flows_corrupt ++;
951 goto skip_pdu_decode;
952 }
953 } /* version processing */
954
955 /* compute 8 bit hash */
956 hash = (ftch_recexp.src_ip & 0xFF);
957 hash ^= (ftch_recexp.src_ip>>24);
958 hash ^= (ftch_recexp.dst_ip & 0xFF);
959 hash ^= (ftch_recexp.dst_ip>>24);
960 hash ^= (ftch_recexp.d_version & 0xFF);
961
962 /* get/create hash table entry */
963 if (!(ftch_recexpp = ftchash_update(ftch, &ftch_recexp, hash)))
964 fterr_errx(1, "ftch_update(): failed");
965
966 /* if the packet count is 0, then this is a new entry */
967 if (ftch_recexpp->packets == 0) {
968
969 fmt_ipv4(fmt_src_ip, ftch_recexp.src_ip, FMT_JUST_LEFT);
970 fmt_ipv4(fmt_dst_ip, ftch_recexp.dst_ip, FMT_JUST_LEFT);
971 fterr_info("New exporter: time=%lu src_ip=%s dst_ip=%s d_version=%d",
972 (u_long)tt_now, fmt_src_ip, fmt_dst_ip, (int)ftpdu.ftv.d_version);
973
974 /* set translation function */
975 if (ftch_recexp.d_version != ftv.d_version)
976 ftch_recexpp->xlate = ftrec_xlate_func(&ftpdu.ftv, &ftv);
977
978 }
979
980 /* verify sequence number */
981 if (ftpdu_check_seq(&ftpdu, &(ftch_recexpp->ftseq)) < 0) {
982 fmt_ipv4(fmt_src_ip, ftch_recexp.src_ip, FMT_JUST_LEFT);
983 fmt_ipv4(fmt_dst_ip, ftch_recexp.dst_ip, FMT_JUST_LEFT);
984 fmt_uint16(fmt_dst_port, ftch_recexp.dst_port, FMT_JUST_LEFT);
985 fterr_warnx(
986 "ftpdu_seq_check(): src_ip=%s dst_ip=%s d_version=%d expecting=%lu received=%lu lost=%lu",
987 fmt_src_ip, fmt_dst_ip, (int)ftpdu.ftv.d_version,
988 (u_long)ftch_recexpp->ftseq.seq_exp,
989 (u_long)ftch_recexpp->ftseq.seq_rcv,
990 (u_long)ftch_recexpp->ftseq.seq_lost);
991
992 /* only count these lost if "lost" is a reasonable number */
993 if (ftch_recexpp->ftseq.seq_lost < FT_SEQ_RESET) {
994 cap_file.hdr_flows_lost += ftch_recexpp->ftseq.seq_lost;
995 ftch_recexpp->lost += ftch_recexpp->ftseq.seq_lost;
996 } else {
997 cap_file.hdr_flows_reset ++;
998 ftch_recexpp->reset ++;
999 }
1000 }
1001
1002 /* decode the pdu */
1003 ftpdu.ftd.byte_order = ftset.byte_order;
1004 ftpdu.ftd.exporter_ip = ftch_recexp.src_ip;
1005 n = fts3rec_pdu_decode(&ftpdu);
1006
1007 /* update the exporter stats */
1008 ftch_recexpp->packets ++;
1009 ftch_recexpp->flows += n;
1010
1011 } /* PDU on receive buffer */
1012
1013 skip_pdu_decode:
1014
1015 /* no current file and pdu version has been set -> create file */
1016 if ((cap_file.fd == -1) && (ftv.d_version)) {
1017
1018 /* calculate the current rotation and next rotate time */
1019 if (calc_rotate(rot.n, &rot.next, &rot.cur) == -1)
1020 fterr_errx(1, "calc_rotate(): failed");
1021
1022 /* remember when file was created */
1023 cap_file.time = (uint32_t)tt_now;
1024
1025 /* remember the version encoded in the filename */
1026 bcopy(&ftv, &cap_file.ftv, sizeof cap_file.ftv);
1027
1028 /* construct the capture file name */
1029 ftfile_pathname(cap_file.name, MAXPATHLEN, nest, cap_file.ftv, 0,
1030 cap_file.time);
1031
1032 /* create directory path for file */
1033 if (ftfile_mkpath(cap_file.time, nest) < 0)
1034 fterr_err(1, "ftfile_mkpath(%s)", cap_file.name);
1035
1036 /* create/open the capture file */
1037 if ((cap_file.fd = open(cap_file.name, O_WRONLY|O_CREAT|O_TRUNC, 0644))
1038 == -1)
1039 fterr_err(1, "open(%s)", cap_file.name);
1040
1041 /* initialize the IO stream */
1042 if (ftio_init(&ftio, cap_file.fd, FT_IO_FLAG_NO_SWAP | FT_IO_FLAG_WRITE |
1043 ((ftset.z_level) ? FT_IO_FLAG_ZINIT : 0) ) < 0)
1044 fterr_errx(1, "ftio_init(): failed");
1045
1046 /* set the version information in the io stream */
1047 if (ftio_set_ver(&ftio, &ftv) < 0)
1048 fterr_errx(1, "ftio_set_ver(): failed");
1049
1050 /* need offsets for filter later */
1051 fts3rec_compute_offsets(&fo, &ftv);
1052
1053 ftio_set_comment(&ftio, ftset.comments);
1054 ftio_set_cap_hostname(&ftio, ftset.hnbuf);
1055 ftio_set_byte_order(&ftio, ftset.byte_order);
1056 ftio_set_z_level(&ftio, ftset.z_level);
1057 ftio_set_cap_time(&ftio, cap_file.time, 0);
1058 ftio_set_debug(&ftio, debug);
1059 ftio_set_corrupt(&ftio, cap_file.hdr_flows_corrupt);
1060 ftio_set_lost(&ftio, cap_file.hdr_flows_lost);
1061 ftio_set_reset(&ftio, cap_file.hdr_flows_reset);
1062 ftio_set_flows_count(&ftio, cap_file.hdr_nflows);
1063
1064 /* ftio_map_load(&ftio, FT_MAP_FILE, ftnet.rem_ip); */
1065
1066 /* header first */
1067 if ((n = ftio_write_header(&ftio)) < 0)
1068 fterr_errx(1, "ftio_write_header(): failed");
1069 else
1070 cap_file.nbytes = n;
1071
1072 } /* create capture file and init new io stream */
1073
1074 /* load filters and tags? */
1075 if (reload_flag && ftv.set) {
1076
1077 /* load tags */
1078 if (tag_active) {
1079
1080 /* not first time through, then free previous tags */
1081 if (ftd) {
1082 fttag_free(&fttag);
1083 fterr_info("Reloading tags.");
1084 }
1085
1086 if (fttag_load(&fttag, &ftvar, tag_fname) < 0)
1087 fterr_errx(1, "fttag_load(): failed");
1088
1089 if (!(ftd = fttag_def_find(&fttag, tag_active)))
1090 fterr_errx(1, "fttag_load(): failed");
1091
1092 } /* tag_active */
1093
1094 /* load filters */
1095 if (filter_active) {
1096
1097 /* not first time through, then free previous filters */
1098 if (ftfd) {
1099 ftfil_free(&ftfil);
1100 fterr_info("Reloading filters.");
1101 }
1102
1103 if (ftfil_load(&ftfil, &ftvar, filter_fname))
1104 fterr_errx(1, "ftfil_load(%s): failed", filter_fname);
1105
1106 if (!(ftfd = ftfil_def_find(&ftfil, filter_active)))
1107 fterr_errx(1, "ftfil_def_find(%s): failed", filter_active);
1108
1109 if (ftfil_def_test_xfields(ftfd, ftrec_xfield(&ftv)))
1110 fterr_errx(1, "Filter references a field not in flow.");
1111
1112 } /* filter_active */
1113
1114 /* load translations */
1115 if (xlate_active) {
1116
1117 /* not first time through, then free previous translations */
1118 if (ftxd) {
1119 ftxlate_free(&ftxlate);
1120 fterr_info("Reloading translations.");
1121 }
1122
1123 if (ftxlate_load(&ftxlate, &ftvar, xlate_fname))
1124 fterr_errx(1, "ftxlate_load(%s): failed", xlate_fname);
1125
1126 if (!(ftxd = ftxlate_def_find(&ftxlate, xlate_active)))
1127 fterr_errx(1, "ftlate_def_find(%s): failed", xlate_active);
1128
1129 if (ftxlate_def_test_xfields(ftxd, ftrec_xfield(&ftv)))
1130 fterr_errx(1, "Xlate references a field not in flow.");
1131
1132 } /* xlate_active */
1133
1134 reload_flag = 0;
1135
1136 } /* reload_flag */
1137
1138 /* if the decode buffer has entries write them out */
1139 for (i = 0, offset = 0; i < ftpdu.ftd.count;
1140 ++i, offset += ftpdu.ftd.rec_size) {
1141
1142 /* translate version? */
1143 if (ftch_recexpp->xlate) {
1144
1145 ftch_recexpp->xlate(ftpdu.ftd.buf+offset, &xl_rec);
1146
1147 out_rec = (char*)&xl_rec;
1148
1149 /* tagging? */
1150 if (tag_active)
1151 fttag_def_eval(ftd, (struct fts3rec_v1005*)out_rec);
1152
1153 } else {
1154
1155 out_rec = (char*)ftpdu.ftd.buf+offset;
1156
1157 }
1158
1159 /* filter? */
1160 if (ftfd)
1161 if (ftfil_def_eval(ftfd, out_rec, &fo) == FT_FIL_MODE_DENY) {
1162 ++ftch_recexpp->filtered_flows;
1163 continue;
1164 }
1165
1166 /* xlate? */
1167 if (ftxd)
1168 if (ftxlate_def_eval(ftxd, out_rec, &fo) != 0)
1169 fterr_errx(1, "ftxlate_def_eval(): failed.");
1170
1171 /* update # of flows stored in capture file */
1172 cap_file.hdr_nflows ++;
1173
1174 if ((n = ftio_write(&ftio, out_rec)) < 0)
1175 fterr_errx(1, "ftio_write(): failed");
1176
1177 /* write to clients */
1178 FT_LIST_FOREACH(client_rec, &client.list, chain) {
1179
1180 if ((n = ftio_write(&client_rec->ftio, out_rec)) < 0) {
1181
1182 fterr_info("Killed client: ip=%s, dtime=%lu",
1183 inet_ntoa(client_rec->addr.sin_addr),
1184 (unsigned long)tt_now - client_rec->conn_time);
1185
1186 ftio_close(&client_rec->ftio);
1187 client_rec2 = client_rec;
1188 client_rec = client_rec->chain.le_next;
1189 FT_LIST_REMOVE(client_rec2, chain);
1190 free(client_rec2);
1191 --client.active;
1192
1193 if (!client_rec)
1194 break;
1195
1196 } /* ftio_write */
1197
1198 } /* foreach client */
1199
1200 /* update # of bytes stored in capture file */
1201 cap_file.nbytes += n;
1202
1203 } /* foreach entry in decode buffer */
1204
1205 /*
1206 * time for a new file ?
1207 */
1208 if ((now > rot.next) || sig_term_flag || sig_quit_flag || sig_hup_flag) {
1209
1210 if (sig_hup_flag)
1211 fterr_info("SIGHUP");
1212
1213 sig_hup_flag = 0; /* re-arm */
1214
1215 if (cap_file.fd != -1) {
1216
1217 ftio_set_cap_time(&ftio, cap_file.time, (uint32_t)tt_now);
1218 ftio_set_corrupt(&ftio, cap_file.hdr_flows_corrupt);
1219 ftio_set_lost(&ftio, cap_file.hdr_flows_lost);
1220 ftio_set_reset(&ftio, cap_file.hdr_flows_reset);
1221 ftio_set_flows_count(&ftio, cap_file.hdr_nflows);
1222
1223 /* re-write header first */
1224 if (ftio_write_header(&ftio) < 0)
1225 fterr_errx(1, "ftio_write_header(): failed");
1226
1227 if ((n = ftio_close(&ftio)) < 0)
1228 fterr_errx(1, "ftio_close(): failed");
1229
1230 cap_file.nbytes += n;
1231
1232 /* construct final version of capture filename */
1233 ftfile_pathname(cap_file.nname, MAXPATHLEN, nest, cap_file.ftv, 1,
1234 cap_file.time);
1235
1236 /* rename working to final */
1237 if (rename(cap_file.name, cap_file.nname) == -1)
1238 fterr_err(1, "rename(%s,%s)", cap_file.name, cap_file.nname);
1239
1240 /* add it to the ager */
1241 if (fte.expiring)
1242 if (ftfile_add_tail(&fte, cap_file.nname, cap_file.nbytes,
1243 cap_file.time))
1244 fterr_errx(1, "ftfile_add_tail(%s): failed", cap_file.name);
1245
1246 /* debugging gets a dump of the ager */
1247 if (debug)
1248 ftfile_dump(&fte);
1249
1250 /* Do the post rotate exec */
1251 if (post_rotate_exec[0]) {
1252
1253 if ((n = fork()) == -1) {
1254
1255 fterr_err(1, "fork()");
1256
1257 } else if (!n) { /* child */
1258
1259 n = execl(post_rotate_exec, post_rotate_exec, cap_file.nname,
1260 NULL);
1261
1262 if (n == -1)
1263 fterr_err(1, "exec(%s)", post_rotate_exec);
1264
1265 _exit(0);
1266 } /* child */
1267 } /* post rotate exec */
1268
1269 /* reset */
1270 bzero(&cap_file, sizeof cap_file);
1271
1272 /* invalidate file descriptor */
1273 cap_file.fd = -1;
1274
1275 /* had enough */
1276 if (sig_quit_flag || sig_term_flag)
1277 goto main_exit;
1278 } /* file open */
1279
1280 } /* time for new file */
1281
1282 /* also need to check sig_quit if no file has been processed yet */
1283 if (sig_quit_flag || sig_term_flag)
1284 goto main_exit;
1285
1286 /*
1287 * If client attachments are enabled, and the flow version has been
1288 * determined setup a listener, but only once.
1289 */
1290 if (ftv.set && client.max && !client.enabled) {
1291
1292 /* socket for listen */
1293 if ((client.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
1294 fterr_err(1, "socket()");
1295
1296 one = 1;
1297
1298 if (setsockopt(client.fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one,
1299 sizeof (one)))
1300 fterr_err(1, "setsockopt(SO_REUSEADDR)");
1301
1302 if (bind(client.fd, (struct sockaddr*)&client.addr, sizeof (client.addr))
1303 < 0)
1304 fterr_err(1, "bind(%s)", inet_ntoa(client.addr.sin_addr));
1305
1306 /* listen for new TCP connections */
1307 if (listen(client.fd, 5) < 0)
1308 fterr_err(1, "listen()");
1309
1310 /* non blocking */
1311 if (fcntl(client.fd, F_SETFL, O_NONBLOCK) < 0)
1312 fterr_err(1, "fcntl()");
1313
1314 client.enabled = 1;
1315
1316 } /* clients enabled */
1317
1318
1319 if (!(cap_file.hdr_nflows % 1001)) {
1320
1321 if (fte.expiring)
1322 if (ftfile_expire(&fte, enable_unlink, cap_file.nbytes))
1323 fterr_errx(1, "ftfile_expire(): failed");
1324
1325 } /* ager run? */
1326
1327 } /* while 1 */
1328
1329 main_exit:
1330
1331 if (pidfile)
1332 unlink_pidfile(pid, pidfile, ftnet.dst_port);
1333
1334 if (sig_quit_flag)
1335 fterr_info("SIGQUIT");
1336
1337 if (sig_term_flag)
1338 fterr_info("SIGTERM");
1339
1340 /* free storage allocated to file entries */
1341 if (fte.expiring)
1342 ftfile_free(&fte);
1343
1344 return 0;
1345
1346 } /* main */
1347
sig_pipe(int signo)1348 void sig_pipe(int signo)
1349 {
1350 sig_pipe_flag = 1;
1351 }
1352
sig_hup(int signo)1353 void sig_hup(int signo)
1354 {
1355 sig_hup_flag = 1;
1356 reload_flag = 1;
1357 }
1358
sig_quit(int signo)1359 void sig_quit(int signo)
1360 {
1361 sig_quit_flag = 1;
1362 }
1363
sig_term(int signo)1364 void sig_term(int signo)
1365 {
1366 sig_term_flag = 1;
1367 }
1368
sig_chld(int signo)1369 void sig_chld(int signo)
1370 {
1371 sig_chld_flag = 1;
1372 }
1373
1374 /* doubletime - like time(2), but returns a double (with fractional seconds)
1375 * This was inspired by the Time::HiRes perl module. E.g.:
1376 * $ perl -MTime::HiRes -le 'print scalar Time::HiRes::time'
1377 * See "perl/CPAN/authors/id/D/DE/DEWEG/Time-HiRes-01.20.tar.gz".
1378 * - Dave Plonka <plonka@doit.wisc.edu>
1379 */
doubletime(void)1380 double doubletime(void) {
1381 double now;
1382 struct timeval tv_now;
1383 if (-1 == gettimeofday(&tv_now, (struct timezone *)0))
1384 return -1;
1385 now = tv_now.tv_sec + (tv_now.tv_usec / 1000000.0);
1386 return now;
1387 }
1388
calc_rotate(int next,double * trotate,int * cur)1389 int calc_rotate (int next, double *trotate, int *cur)
1390 {
1391 double now; /* current time */
1392 time_t tt_now; /* current time */
1393 double irotate; /* interval of next in seconds */
1394 time_t morning; /* start of the day */
1395 struct tm *tm1;
1396
1397 irotate = 86400. / (next+1);
1398
1399 *cur = 0;
1400
1401 if (-1 == (tt_now = now = doubletime()))
1402 return -1;
1403
1404 /* calculate start of the day */
1405 if (!(tm1 = localtime (&tt_now)))
1406 return -1;
1407
1408 tm1->tm_sec = 0;
1409 tm1->tm_min = 0;
1410 tm1->tm_hour = 0;
1411
1412 if ((morning = mktime(tm1)) == -1)
1413 return -1;
1414
1415 if (next)
1416 *trotate = morning + irotate;
1417 else
1418 *trotate = morning + 86400.;
1419
1420 while (now > *trotate) {
1421
1422 ++ *cur;
1423 *trotate += irotate;
1424
1425 }
1426
1427 return 0;
1428
1429 } /* calc_rotate */
1430
fterr_exit_handler(int code)1431 void fterr_exit_handler(int code)
1432 {
1433 if (pid && pidfile)
1434 unlink_pidfile(pid, pidfile, ftnet.dst_port);
1435 exit (code);
1436 } /* fterr_exit_handler */
1437
usage(void)1438 void usage(void) {
1439
1440 fprintf(stderr, "Usage: flow-capture [-hu] [-b big|little]\n");
1441 fprintf(stderr, " [-C comment] [-c flow_clients] [-d debug_level] [-D daemonize]\n");
1442 fprintf(stderr, " [-e expire_count] [-E expire_size[bKMG]] [-n rotations]\n");
1443 fprintf(stderr, " [-N nesting_level] [-p pidfile ] [-R rotate_program]\n");
1444 fprintf(stderr, " [-S stat_interval] [-t tag_fname] [-T tag_active] [-V pdu_version]\n");
1445 fprintf(stderr, " [-z z_level] [-x xlate_fname] [-X xlate_active]\n");
1446 fprintf(stderr, " -w workdir localip/remoteip/port\n");
1447 fprintf(stderr, "Signals:\n");
1448 fprintf(stderr, " SIGHUP - close and rotate current file\n");
1449 fprintf(stderr, " SIGQUIT - close current file and exit\n");
1450
1451 } /* usage */
1452
1453