1
2 /*
3 * Copyright (C) 2012 by Darren Reed.
4 *
5 * See the IPFILTER.LICENCE file for details on licencing.
6 */
7 #include "ipf.h"
8 #include "ipmon.h"
9 #include <sys/ioctl.h>
10 #include <sys/stat.h>
11 #include <syslog.h>
12 #include <ctype.h>
13 #include <fcntl.h>
14 #include <signal.h>
15
16 #if !defined(lint)
17 static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
18 static const char rcsid[] = "@(#)$Id$";
19 #endif
20
21
22 #define STRERROR(x) strerror(x)
23
24 extern int optind;
25 extern char *optarg;
26
27 extern ipmon_saver_t executesaver;
28 extern ipmon_saver_t filesaver;
29 extern ipmon_saver_t nothingsaver;
30 extern ipmon_saver_t snmpv1saver;
31 extern ipmon_saver_t snmpv2saver;
32 extern ipmon_saver_t syslogsaver;
33
34
35 struct flags {
36 int value;
37 char flag;
38 };
39
40 typedef struct logsource {
41 int fd;
42 int logtype;
43 char *file;
44 int regular;
45 size_t size;
46 } logsource_t;
47
48 typedef struct config {
49 int opts;
50 int maxfd;
51 logsource_t logsrc[3];
52 fd_set fdmr;
53 FILE *blog;
54 char *bfile;
55 FILE *log;
56 char *file;
57 char *cfile;
58 } config_t;
59
60 typedef struct icmp_subtype {
61 int ist_val;
62 char *ist_name;
63 } icmp_subtype_t;
64
65 typedef struct icmp_type {
66 int it_val;
67 struct icmp_subtype *it_subtable;
68 size_t it_stsize;
69 char *it_name;
70 } icmp_type_t;
71
72
73 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
74
75
76 struct flags tcpfl[] = {
77 { TH_ACK, 'A' },
78 { TH_RST, 'R' },
79 { TH_SYN, 'S' },
80 { TH_FIN, 'F' },
81 { TH_URG, 'U' },
82 { TH_PUSH,'P' },
83 { TH_ECN, 'E' },
84 { TH_CWR, 'C' },
85 { 0, '\0' }
86 };
87
88 char *reasons[] = {
89 "filter-rule",
90 "log-or-block_1",
91 "pps-rate",
92 "jumbogram",
93 "makefrip-fail",
94 "state_add-fail",
95 "updateipid-fail",
96 "log-or-block_2",
97 "decap-fail",
98 "auth_new-fail",
99 "auth_captured",
100 "coalesce-fail",
101 "pullup-fail",
102 "auth-feedback",
103 "bad-frag",
104 "natv4_out-fail",
105 "natv4_in-fail",
106 "natv6_out-fail",
107 "natv6_in-fail",
108 };
109
110 #if SOLARIS
111 static char *pidfile = "/etc/opt/ipf/ipmon.pid";
112 #else
113 static char *pidfile = "/var/run/ipmon.pid";
114 #endif
115
116 static char line[2048];
117 static int donehup = 0;
118 static void usage(char *);
119 static void handlehup(int);
120 static void flushlogs(char *, FILE *);
121 static void print_log(config_t *, logsource_t *, char *, int);
122 static void print_ipflog(config_t *, char *, int);
123 static void print_natlog(config_t *, char *, int);
124 static void print_statelog(config_t *, char *, int);
125 static int read_log(int, int *, char *, int);
126 static void write_pid(char *);
127 static char *icmpname(u_int, u_int);
128 static char *icmpname6(u_int, u_int);
129 static icmp_type_t *find_icmptype(int, icmp_type_t *, size_t);
130 static icmp_subtype_t *find_icmpsubtype(int, icmp_subtype_t *, size_t);
131 static struct tm *get_tm(time_t);
132
133 char *portlocalname(int, char *, u_int);
134 int main(int, char *[]);
135
136 static void logopts(int, char *);
137 static void init_tabs(void);
138 static char *getlocalproto(u_int);
139 static void openlogs(config_t *conf);
140 static int read_loginfo(config_t *conf);
141 static void initconfig(config_t *conf);
142
143 static char **protocols = NULL;
144 static char **udp_ports = NULL;
145 static char **tcp_ports = NULL;
146
147
148 #define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b))
149
150 #ifndef LOGFAC
151 #define LOGFAC LOG_LOCAL0
152 #endif
153 int logfac = LOGFAC;
154 int ipmonopts = 0;
155 int opts = OPT_NORESOLVE;
156 int use_inet6 = 0;
157
158
159 static icmp_subtype_t icmpunreachnames[] = {
160 { ICMP_UNREACH_NET, "net" },
161 { ICMP_UNREACH_HOST, "host" },
162 { ICMP_UNREACH_PROTOCOL, "protocol" },
163 { ICMP_UNREACH_PORT, "port" },
164 { ICMP_UNREACH_NEEDFRAG, "needfrag" },
165 { ICMP_UNREACH_SRCFAIL, "srcfail" },
166 { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" },
167 { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" },
168 { ICMP_UNREACH_NET, "isolated" },
169 { ICMP_UNREACH_NET_PROHIB, "net_prohib" },
170 { ICMP_UNREACH_NET_PROHIB, "host_prohib" },
171 { ICMP_UNREACH_TOSNET, "tosnet" },
172 { ICMP_UNREACH_TOSHOST, "toshost" },
173 { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" },
174 { -2, NULL }
175 };
176
177 static icmp_subtype_t redirectnames[] = {
178 { ICMP_REDIRECT_NET, "net" },
179 { ICMP_REDIRECT_HOST, "host" },
180 { ICMP_REDIRECT_TOSNET, "tosnet" },
181 { ICMP_REDIRECT_TOSHOST, "toshost" },
182 { -2, NULL }
183 };
184
185 static icmp_subtype_t timxceednames[] = {
186 { ICMP_TIMXCEED_INTRANS, "transit" },
187 { ICMP_TIMXCEED_REASS, "reassem" },
188 { -2, NULL }
189 };
190
191 static icmp_subtype_t paramnames[] = {
192 { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" },
193 { ICMP_PARAMPROB_OPTABSENT, "optmissing" },
194 { ICMP_PARAMPROB_LENGTH, "length" },
195 { -2, NULL }
196 };
197
198 static icmp_type_t icmptypes4[] = {
199 { ICMP_ECHOREPLY, NULL, 0, "echoreply" },
200 { -1, NULL, 0, NULL },
201 { -1, NULL, 0, NULL },
202 { ICMP_UNREACH, icmpunreachnames,
203 IST_SZ(icmpunreachnames),"unreach" },
204 { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" },
205 { ICMP_REDIRECT, redirectnames,
206 IST_SZ(redirectnames), "redirect" },
207 { -1, NULL, 0, NULL },
208 { -1, NULL, 0, NULL },
209 { ICMP_ECHO, NULL, 0, "echo" },
210 { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" },
211 { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" },
212 { ICMP_TIMXCEED, timxceednames,
213 IST_SZ(timxceednames), "timxceed" },
214 { ICMP_PARAMPROB, paramnames,
215 IST_SZ(paramnames), "paramprob" },
216 { ICMP_TSTAMP, NULL, 0, "timestamp" },
217 { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" },
218 { ICMP_IREQ, NULL, 0, "inforeq" },
219 { ICMP_IREQREPLY, NULL, 0, "inforeply" },
220 { ICMP_MASKREQ, NULL, 0, "maskreq" },
221 { ICMP_MASKREPLY, NULL, 0, "maskreply" },
222 { -2, NULL, 0, NULL }
223 };
224
225 static icmp_subtype_t icmpredirect6[] = {
226 { ICMP6_DST_UNREACH_NOROUTE, "noroute" },
227 { ICMP6_DST_UNREACH_ADMIN, "admin" },
228 { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" },
229 { ICMP6_DST_UNREACH_ADDR, "address" },
230 { ICMP6_DST_UNREACH_NOPORT, "noport" },
231 { -2, NULL }
232 };
233
234 static icmp_subtype_t icmptimexceed6[] = {
235 { ICMP6_TIME_EXCEED_TRANSIT, "intransit" },
236 { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" },
237 { -2, NULL }
238 };
239
240 static icmp_subtype_t icmpparamprob6[] = {
241 { ICMP6_PARAMPROB_HEADER, "header" },
242 { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" },
243 { ICMP6_PARAMPROB_OPTION, "option" },
244 { -2, NULL }
245 };
246
247 static icmp_subtype_t icmpquerysubject6[] = {
248 { ICMP6_NI_SUBJ_IPV6, "ipv6" },
249 { ICMP6_NI_SUBJ_FQDN, "fqdn" },
250 { ICMP6_NI_SUBJ_IPV4, "ipv4" },
251 { -2, NULL },
252 };
253
254 static icmp_subtype_t icmpnodeinfo6[] = {
255 { ICMP6_NI_SUCCESS, "success" },
256 { ICMP6_NI_REFUSED, "refused" },
257 { ICMP6_NI_UNKNOWN, "unknown" },
258 { -2, NULL }
259 };
260
261 static icmp_subtype_t icmprenumber6[] = {
262 { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" },
263 { ICMP6_ROUTER_RENUMBERING_RESULT, "result" },
264 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" },
265 { -2, NULL }
266 };
267
268 static icmp_type_t icmptypes6[] = {
269 { 0, NULL, 0, NULL },
270 { ICMP6_DST_UNREACH, icmpredirect6,
271 IST_SZ(icmpredirect6), "unreach" },
272 { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" },
273 { ICMP6_TIME_EXCEEDED, icmptimexceed6,
274 IST_SZ(icmptimexceed6), "timxceed" },
275 { ICMP6_PARAM_PROB, icmpparamprob6,
276 IST_SZ(icmpparamprob6), "paramprob" },
277 { ICMP6_ECHO_REQUEST, NULL, 0, "echo" },
278 { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" },
279 { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6,
280 IST_SZ(icmpquerysubject6), "groupmemberquery" },
281 { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" },
282 { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" },
283 { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" },
284 { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" },
285 { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" },
286 { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" },
287 { ND_REDIRECT, NULL, 0, "redirect" },
288 { ICMP6_ROUTER_RENUMBERING, icmprenumber6,
289 IST_SZ(icmprenumber6), "routerrenumber" },
290 { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" },
291 { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" },
292 { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" },
293 { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" },
294 { ICMP6_NI_QUERY, icmpnodeinfo6,
295 IST_SZ(icmpnodeinfo6), "nodeinforequest" },
296 { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" },
297 { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" },
298 { MLD6_MTRACE, NULL, 0, "mtracerequest" },
299 { -2, NULL, 0, NULL }
300 };
301
302 static icmp_subtype_t *
find_icmpsubtype(int type,icmp_subtype_t * table,size_t tablesz)303 find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz)
304 {
305 icmp_subtype_t *ist;
306
307 if (tablesz < 2)
308 return (NULL);
309
310 if ((type < 0) || (type > table[tablesz - 2].ist_val))
311 return (NULL);
312
313 if (table[type].ist_val == type)
314 return (table + type);
315
316 for (ist = table; ist->ist_val != -2; ist++)
317 if (ist->ist_val == type)
318 return (ist);
319 return (NULL);
320 }
321
322
323 static icmp_type_t *
find_icmptype(int type,icmp_type_t * table,size_t tablesz)324 find_icmptype(int type, icmp_type_t *table, size_t tablesz)
325 {
326 icmp_type_t *it;
327
328 if (tablesz < 2)
329 return (NULL);
330
331 if ((type < 0) || (type > table[tablesz - 2].it_val))
332 return (NULL);
333
334 if (table[type].it_val == type)
335 return (table + type);
336
337 for (it = table; it->it_val != -2; it++)
338 if (it->it_val == type)
339 return (it);
340 return (NULL);
341 }
342
343
344 static void
handlehup(int sig)345 handlehup(int sig)
346 {
347 signal(SIGHUP, handlehup);
348 donehup = 1;
349 }
350
351
352 static void
init_tabs(void)353 init_tabs(void)
354 {
355 struct protoent *p;
356 struct servent *s;
357 char *name, **tab;
358 int port, i;
359
360 if (protocols != NULL) {
361 for (i = 0; i < 256; i++)
362 if (protocols[i] != NULL) {
363 free(protocols[i]);
364 protocols[i] = NULL;
365 }
366 free(protocols);
367 protocols = NULL;
368 }
369 protocols = (char **)malloc(256 * sizeof(*protocols));
370 if (protocols != NULL) {
371 bzero((char *)protocols, 256 * sizeof(*protocols));
372
373 setprotoent(1);
374 while ((p = getprotoent()) != NULL)
375 if (p->p_proto >= 0 && p->p_proto <= 255 &&
376 p->p_name != NULL && protocols[p->p_proto] == NULL)
377 protocols[p->p_proto] = strdup(p->p_name);
378 endprotoent();
379 if (protocols[0])
380 free(protocols[0]);
381 protocols[0] = strdup("ip");
382 }
383
384 if (udp_ports != NULL) {
385 for (i = 0; i < 65536; i++)
386 if (udp_ports[i] != NULL) {
387 free(udp_ports[i]);
388 udp_ports[i] = NULL;
389 }
390 free(udp_ports);
391 udp_ports = NULL;
392 }
393 udp_ports = (char **)malloc(65536 * sizeof(*udp_ports));
394 if (udp_ports != NULL)
395 bzero((char *)udp_ports, 65536 * sizeof(*udp_ports));
396
397 if (tcp_ports != NULL) {
398 for (i = 0; i < 65536; i++)
399 if (tcp_ports[i] != NULL) {
400 free(tcp_ports[i]);
401 tcp_ports[i] = NULL;
402 }
403 free(tcp_ports);
404 tcp_ports = NULL;
405 }
406 tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports));
407 if (tcp_ports != NULL)
408 bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports));
409
410 setservent(1);
411 while ((s = getservent()) != NULL) {
412 if (s->s_proto == NULL)
413 continue;
414 else if (!strcmp(s->s_proto, "tcp")) {
415 port = ntohs(s->s_port);
416 name = s->s_name;
417 tab = tcp_ports;
418 } else if (!strcmp(s->s_proto, "udp")) {
419 port = ntohs(s->s_port);
420 name = s->s_name;
421 tab = udp_ports;
422 } else
423 continue;
424 if ((port < 0 || port > 65535) || (name == NULL))
425 continue;
426 if (tab != NULL)
427 tab[port] = strdup(name);
428 }
429 endservent();
430 }
431
432
433 static char *
getlocalproto(u_int p)434 getlocalproto(u_int p)
435 {
436 static char pnum[4];
437 char *s;
438
439 p &= 0xff;
440 s = protocols ? protocols[p] : NULL;
441 if (s == NULL) {
442 sprintf(pnum, "%u", p);
443 s = pnum;
444 }
445 return (s);
446 }
447
448
449 static int
read_log(int fd,int * lenp,char * buf,int bufsize)450 read_log(int fd, int *lenp, char *buf, int bufsize)
451 {
452 int nr;
453
454 if (bufsize > IPFILTER_LOGSIZE)
455 bufsize = IPFILTER_LOGSIZE;
456
457 nr = read(fd, buf, bufsize);
458 if (!nr)
459 return (2);
460 if ((nr < 0) && (errno != EINTR))
461 return (-1);
462 *lenp = nr;
463 return (0);
464 }
465
466
467 char *
portlocalname(int res,char * proto,u_int port)468 portlocalname(int res, char *proto, u_int port)
469 {
470 static char pname[8];
471 char *s;
472
473 port = ntohs(port);
474 port &= 0xffff;
475 sprintf(pname, "%u", port);
476 if (!res || (ipmonopts & IPMON_PORTNUM))
477 return (pname);
478 s = NULL;
479 if (!strcmp(proto, "tcp"))
480 s = tcp_ports[port];
481 else if (!strcmp(proto, "udp"))
482 s = udp_ports[port];
483 if (s == NULL)
484 s = pname;
485 return (s);
486 }
487
488
489 static char *
icmpname(u_int type,u_int code)490 icmpname(u_int type, u_int code)
491 {
492 static char name[80];
493 icmp_subtype_t *ist;
494 icmp_type_t *it;
495 char *s;
496
497 s = NULL;
498 it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it));
499 if (it != NULL)
500 s = it->it_name;
501
502 if (s == NULL)
503 sprintf(name, "icmptype(%d)/", type);
504 else
505 sprintf(name, "%s/", s);
506
507 ist = NULL;
508 if (it != NULL && it->it_subtable != NULL)
509 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
510
511 if (ist != NULL && ist->ist_name != NULL)
512 strcat(name, ist->ist_name);
513 else
514 sprintf(name + strlen(name), "%d", code);
515
516 return (name);
517 }
518
519 static char *
icmpname6(u_int type,u_int code)520 icmpname6(u_int type, u_int code)
521 {
522 static char name[80];
523 icmp_subtype_t *ist;
524 icmp_type_t *it;
525 char *s;
526
527 s = NULL;
528 it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it));
529 if (it != NULL)
530 s = it->it_name;
531
532 if (s == NULL)
533 sprintf(name, "icmpv6type(%d)/", type);
534 else
535 sprintf(name, "%s/", s);
536
537 ist = NULL;
538 if (it != NULL && it->it_subtable != NULL)
539 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
540
541 if (ist != NULL && ist->ist_name != NULL)
542 strcat(name, ist->ist_name);
543 else
544 sprintf(name + strlen(name), "%d", code);
545
546 return (name);
547 }
548
549
550 void
dumphex(FILE * log,int dopts,char * buf,int len)551 dumphex(FILE *log, int dopts, char *buf, int len)
552 {
553 char hline[80];
554 int i, j, k;
555 u_char *s = (u_char *)buf, *t = (u_char *)hline;
556
557 if (buf == NULL || len == 0)
558 return;
559
560 *hline = '\0';
561
562 for (i = len, j = 0; i; i--, j++, s++) {
563 if (j && !(j & 0xf)) {
564 *t++ = '\n';
565 *t = '\0';
566 if ((dopts & IPMON_SYSLOG))
567 syslog(LOG_INFO, "%s", hline);
568 else if (log != NULL)
569 fputs(hline, log);
570 t = (u_char *)hline;
571 *t = '\0';
572 }
573 sprintf((char *)t, "%02x", *s & 0xff);
574 t += 2;
575 if (!((j + 1) & 0xf)) {
576 s -= 15;
577 sprintf((char *)t, " ");
578 t += 8;
579 for (k = 16; k; k--, s++)
580 *t++ = (isprint(*s) ? *s : '.');
581 s--;
582 }
583
584 if ((j + 1) & 0xf)
585 *t++ = ' ';;
586 }
587
588 if (j & 0xf) {
589 for (k = 16 - (j & 0xf); k; k--) {
590 *t++ = ' ';
591 *t++ = ' ';
592 *t++ = ' ';
593 }
594 sprintf((char *)t, " ");
595 t += 7;
596 s -= j & 0xf;
597 for (k = j & 0xf; k; k--, s++)
598 *t++ = (isprint(*s) ? *s : '.');
599 *t++ = '\n';
600 *t = '\0';
601 }
602 if ((dopts & IPMON_SYSLOG) != 0)
603 syslog(LOG_INFO, "%s", hline);
604 else if (log != NULL) {
605 fputs(hline, log);
606 fflush(log);
607 }
608 }
609
610
611 static struct tm *
get_tm(time_t sec)612 get_tm(time_t sec)
613 {
614 struct tm *tm;
615 time_t t;
616
617 t = sec;
618 tm = localtime(&t);
619 return (tm);
620 }
621
622 static void
print_natlog(config_t * conf,char * buf,int blen)623 print_natlog(config_t *conf, char *buf, int blen)
624 {
625 static u_32_t seqnum = 0;
626 int res, i, len, family;
627 struct natlog *nl;
628 struct tm *tm;
629 iplog_t *ipl;
630 char *proto;
631 int simple;
632 char *t;
633
634 t = line;
635 simple = 0;
636 ipl = (iplog_t *)buf;
637 if (ipl->ipl_seqnum != seqnum) {
638 if ((ipmonopts & IPMON_SYSLOG) != 0) {
639 syslog(LOG_WARNING,
640 "missed %u NAT log entries: %u %u",
641 ipl->ipl_seqnum - seqnum, seqnum,
642 ipl->ipl_seqnum);
643 } else {
644 (void) fprintf(conf->log,
645 "missed %u NAT log entries: %u %u\n",
646 ipl->ipl_seqnum - seqnum, seqnum,
647 ipl->ipl_seqnum);
648 }
649 }
650 seqnum = ipl->ipl_seqnum + ipl->ipl_count;
651
652 nl = (struct natlog *)((char *)ipl + sizeof(*ipl));
653 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
654 tm = get_tm(ipl->ipl_sec);
655 len = sizeof(line);
656
657 if (!(ipmonopts & IPMON_SYSLOG)) {
658 (void) strftime(t, len, "%d/%m/%Y ", tm);
659 i = strlen(t);
660 len -= i;
661 t += i;
662 }
663 (void) strftime(t, len, "%T", tm);
664 t += strlen(t);
665 sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1);
666 t += strlen(t);
667
668 switch (nl->nl_action)
669 {
670 case NL_NEW :
671 strcpy(t, "NAT:NEW");
672 break;
673
674 case NL_FLUSH :
675 strcpy(t, "NAT:FLUSH");
676 break;
677
678 case NL_CLONE :
679 strcpy(t, "NAT:CLONE");
680 break;
681
682 case NL_EXPIRE :
683 strcpy(t, "NAT:EXPIRE");
684 break;
685
686 case NL_DESTROY :
687 strcpy(t, "NAT:DESTROY");
688 break;
689
690 case NL_PURGE :
691 strcpy(t, "NAT:PURGE");
692 break;
693
694 default :
695 sprintf(t, "NAT:Action(%d)", nl->nl_action);
696 break;
697 }
698 t += strlen(t);
699
700
701 switch (nl->nl_type)
702 {
703 case NAT_MAP :
704 strcpy(t, "-MAP ");
705 simple = 1;
706 break;
707
708 case NAT_REDIRECT :
709 strcpy(t, "-RDR ");
710 simple = 1;
711 break;
712
713 case NAT_BIMAP :
714 strcpy(t, "-BIMAP ");
715 simple = 1;
716 break;
717
718 case NAT_MAPBLK :
719 strcpy(t, "-MAPBLOCK ");
720 simple = 1;
721 break;
722
723 case NAT_REWRITE|NAT_MAP :
724 strcpy(t, "-RWR_MAP ");
725 break;
726
727 case NAT_REWRITE|NAT_REDIRECT :
728 strcpy(t, "-RWR_RDR ");
729 break;
730
731 case NAT_ENCAP|NAT_MAP :
732 strcpy(t, "-ENC_MAP ");
733 break;
734
735 case NAT_ENCAP|NAT_REDIRECT :
736 strcpy(t, "-ENC_RDR ");
737 break;
738
739 case NAT_DIVERTUDP|NAT_MAP :
740 strcpy(t, "-DIV_MAP ");
741 break;
742
743 case NAT_DIVERTUDP|NAT_REDIRECT :
744 strcpy(t, "-DIV_RDR ");
745 break;
746
747 default :
748 sprintf(t, "-Type(%d) ", nl->nl_type);
749 break;
750 }
751 t += strlen(t);
752
753 proto = getlocalproto(nl->nl_p[0]);
754
755 family = vtof(nl->nl_v[0]);
756
757 if (simple == 1) {
758 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6),
759 portlocalname(res, proto, (u_int)nl->nl_osrcport));
760 t += strlen(t);
761 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6),
762 portlocalname(res, proto, (u_int)nl->nl_nsrcport));
763 t += strlen(t);
764 sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6),
765 portlocalname(res, proto, (u_int)nl->nl_odstport));
766 } else {
767 sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6),
768 portlocalname(res, proto, (u_int)nl->nl_osrcport));
769 t += strlen(t);
770 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6),
771 portlocalname(res, proto, (u_int)nl->nl_odstport));
772 t += strlen(t);
773 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6),
774 portlocalname(res, proto, (u_int)nl->nl_nsrcport));
775 t += strlen(t);
776 sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6),
777 portlocalname(res, proto, (u_int)nl->nl_ndstport));
778 }
779 t += strlen(t);
780
781 strcpy(t, getlocalproto(nl->nl_p[0]));
782 t += strlen(t);
783
784 if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) {
785 #ifdef USE_QUAD_T
786 # ifdef PRId64
787 sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%"
788 PRId64,
789 # else
790 sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd",
791 # endif
792 #else
793 sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld",
794 #endif
795 nl->nl_pkts[0], nl->nl_pkts[1],
796 nl->nl_bytes[0], nl->nl_bytes[1]);
797 t += strlen(t);
798 }
799
800 *t++ = '\n';
801 *t++ = '\0';
802 if (ipmonopts & IPMON_SYSLOG)
803 syslog(LOG_INFO, "%s", line);
804 else if (conf->log != NULL)
805 (void) fprintf(conf->log, "%s", line);
806 }
807
808
809 static void
print_statelog(config_t * conf,char * buf,int blen)810 print_statelog(config_t *conf, char *buf, int blen)
811 {
812 static u_32_t seqnum = 0;
813 int res, i, len, family;
814 struct ipslog *sl;
815 char *t, *proto;
816 struct tm *tm;
817 iplog_t *ipl;
818
819 t = line;
820 ipl = (iplog_t *)buf;
821 if (ipl->ipl_seqnum != seqnum) {
822 if ((ipmonopts & IPMON_SYSLOG) != 0) {
823 syslog(LOG_WARNING,
824 "missed %u state log entries: %u %u",
825 ipl->ipl_seqnum - seqnum, seqnum,
826 ipl->ipl_seqnum);
827 } else {
828 (void) fprintf(conf->log,
829 "missed %u state log entries: %u %u\n",
830 ipl->ipl_seqnum - seqnum, seqnum,
831 ipl->ipl_seqnum);
832 }
833 }
834 seqnum = ipl->ipl_seqnum + ipl->ipl_count;
835
836 sl = (struct ipslog *)((char *)ipl + sizeof(*ipl));
837 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
838 tm = get_tm(ipl->ipl_sec);
839 len = sizeof(line);
840 if (!(ipmonopts & IPMON_SYSLOG)) {
841 (void) strftime(t, len, "%d/%m/%Y ", tm);
842 i = strlen(t);
843 len -= i;
844 t += i;
845 }
846 (void) strftime(t, len, "%T", tm);
847 t += strlen(t);
848 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec);
849 t += strlen(t);
850
851 family = vtof(sl->isl_v);
852
853 switch (sl->isl_type)
854 {
855 case ISL_NEW :
856 strcpy(t, "STATE:NEW ");
857 break;
858
859 case ISL_CLONE :
860 strcpy(t, "STATE:CLONED ");
861 break;
862
863 case ISL_EXPIRE :
864 if ((sl->isl_p == IPPROTO_TCP) &&
865 (sl->isl_state[0] > IPF_TCPS_ESTABLISHED ||
866 sl->isl_state[1] > IPF_TCPS_ESTABLISHED))
867 strcpy(t, "STATE:CLOSE ");
868 else
869 strcpy(t, "STATE:EXPIRE ");
870 break;
871
872 case ISL_FLUSH :
873 strcpy(t, "STATE:FLUSH ");
874 break;
875
876 case ISL_INTERMEDIATE :
877 strcpy(t, "STATE:INTERMEDIATE ");
878 break;
879
880 case ISL_REMOVE :
881 strcpy(t, "STATE:REMOVE ");
882 break;
883
884 case ISL_KILLED :
885 strcpy(t, "STATE:KILLED ");
886 break;
887
888 case ISL_UNLOAD :
889 strcpy(t, "STATE:UNLOAD ");
890 break;
891
892 default :
893 sprintf(t, "Type: %d ", sl->isl_type);
894 break;
895 }
896 t += strlen(t);
897
898 proto = getlocalproto(sl->isl_p);
899
900 if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) {
901 sprintf(t, "%s,%s -> ",
902 hostname(family, (u_32_t *)&sl->isl_src),
903 portlocalname(res, proto, (u_int)sl->isl_sport));
904 t += strlen(t);
905 sprintf(t, "%s,%s PR %s",
906 hostname(family, (u_32_t *)&sl->isl_dst),
907 portlocalname(res, proto, (u_int)sl->isl_dport), proto);
908 } else if (sl->isl_p == IPPROTO_ICMP) {
909 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
910 t += strlen(t);
911 sprintf(t, "%s PR icmp %d",
912 hostname(family, (u_32_t *)&sl->isl_dst),
913 sl->isl_itype);
914 } else if (sl->isl_p == IPPROTO_ICMPV6) {
915 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
916 t += strlen(t);
917 sprintf(t, "%s PR icmpv6 %d",
918 hostname(family, (u_32_t *)&sl->isl_dst),
919 sl->isl_itype);
920 } else {
921 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
922 t += strlen(t);
923 sprintf(t, "%s PR %s",
924 hostname(family, (u_32_t *)&sl->isl_dst), proto);
925 }
926 t += strlen(t);
927 if (sl->isl_tag != FR_NOLOGTAG) {
928 sprintf(t, " tag %u", sl->isl_tag);
929 t += strlen(t);
930 }
931 if (sl->isl_type != ISL_NEW) {
932 sprintf(t,
933 #ifdef USE_QUAD_T
934 #ifdef PRId64
935 " Forward: Pkts in %" PRId64 " Bytes in %" PRId64
936 " Pkts out %" PRId64 " Bytes out %" PRId64
937 " Backward: Pkts in %" PRId64 " Bytes in %" PRId64
938 " Pkts out %" PRId64 " Bytes out %" PRId64,
939 #else
940 " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd",
941 #endif /* PRId64 */
942 #else
943 " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld",
944 #endif
945 sl->isl_pkts[0], sl->isl_bytes[0],
946 sl->isl_pkts[1], sl->isl_bytes[1],
947 sl->isl_pkts[2], sl->isl_bytes[2],
948 sl->isl_pkts[3], sl->isl_bytes[3]);
949
950 t += strlen(t);
951 }
952
953 *t++ = '\n';
954 *t++ = '\0';
955 if (ipmonopts & IPMON_SYSLOG)
956 syslog(LOG_INFO, "%s", line);
957 else if (conf->log != NULL)
958 (void) fprintf(conf->log, "%s", line);
959 }
960
961
962 static void
print_log(config_t * conf,logsource_t * log,char * buf,int blen)963 print_log(config_t *conf, logsource_t *log, char *buf, int blen)
964 {
965 char *bp, *bpo;
966 iplog_t *ipl;
967 int psize;
968
969 bp = NULL;
970 bpo = NULL;
971
972 while (blen > 0) {
973 ipl = (iplog_t *)buf;
974 if ((u_long)ipl & (sizeof(long)-1)) {
975 if (bp)
976 bpo = bp;
977 bp = (char *)malloc(blen);
978 bcopy((char *)ipl, bp, blen);
979 if (bpo) {
980 free(bpo);
981 bpo = NULL;
982 }
983 buf = bp;
984 continue;
985 }
986
987 psize = ipl->ipl_dsize;
988 if (psize > blen)
989 break;
990
991 if (conf->blog != NULL) {
992 fwrite(buf, psize, 1, conf->blog);
993 fflush(conf->blog);
994 }
995
996 if (log->logtype == IPL_LOGIPF) {
997 if (ipl->ipl_magic == IPL_MAGIC)
998 print_ipflog(conf, buf, psize);
999
1000 } else if (log->logtype == IPL_LOGNAT) {
1001 if (ipl->ipl_magic == IPL_MAGIC_NAT)
1002 print_natlog(conf, buf, psize);
1003
1004 } else if (log->logtype == IPL_LOGSTATE) {
1005 if (ipl->ipl_magic == IPL_MAGIC_STATE)
1006 print_statelog(conf, buf, psize);
1007 }
1008
1009 blen -= psize;
1010 buf += psize;
1011 }
1012 if (bp)
1013 free(bp);
1014 return;
1015 }
1016
1017
1018 static void
print_ipflog(config_t * conf,char * buf,int blen)1019 print_ipflog(config_t *conf, char *buf, int blen)
1020 {
1021 static u_32_t seqnum = 0;
1022 int i, f, lvl, res, len, off, plen, ipoff, defaction;
1023 struct icmp *icmp;
1024 struct icmp *ic;
1025 char *t, *proto;
1026 ip_t *ipc, *ip;
1027 struct tm *tm;
1028 u_32_t *s, *d;
1029 u_short hl, p;
1030 ipflog_t *ipf;
1031 iplog_t *ipl;
1032 tcphdr_t *tp;
1033 #ifdef USE_INET6
1034 struct ip6_ext *ehp;
1035 u_short ehl;
1036 ip6_t *ip6;
1037 int go;
1038 #endif
1039
1040 ipl = (iplog_t *)buf;
1041 if (ipl->ipl_seqnum != seqnum) {
1042 if ((ipmonopts & IPMON_SYSLOG) != 0) {
1043 syslog(LOG_WARNING,
1044 "missed %u ipf log entries: %u %u",
1045 ipl->ipl_seqnum - seqnum, seqnum,
1046 ipl->ipl_seqnum);
1047 } else {
1048 (void) fprintf(conf->log,
1049 "missed %u ipf log entries: %u %u\n",
1050 ipl->ipl_seqnum - seqnum, seqnum,
1051 ipl->ipl_seqnum);
1052 }
1053 }
1054 seqnum = ipl->ipl_seqnum + ipl->ipl_count;
1055
1056 ipf = (ipflog_t *)((char *)buf + sizeof(*ipl));
1057 ip = (ip_t *)((char *)ipf + sizeof(*ipf));
1058 f = ipf->fl_family;
1059 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
1060 t = line;
1061 *t = '\0';
1062 tm = get_tm(ipl->ipl_sec);
1063
1064 len = sizeof(line);
1065 if (!(ipmonopts & IPMON_SYSLOG)) {
1066 (void) strftime(t, len, "%d/%m/%Y ", tm);
1067 i = strlen(t);
1068 len -= i;
1069 t += i;
1070 }
1071 (void) strftime(t, len, "%T", tm);
1072 t += strlen(t);
1073 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec);
1074 t += strlen(t);
1075 if (ipl->ipl_count > 1) {
1076 sprintf(t, "%dx ", ipl->ipl_count);
1077 t += strlen(t);
1078 }
1079 {
1080 char ifname[sizeof(ipf->fl_ifname) + 1];
1081
1082 strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname));
1083 ifname[sizeof(ipf->fl_ifname)] = '\0';
1084 sprintf(t, "%s", ifname);
1085 t += strlen(t);
1086 # if SOLARIS
1087 if (ISALPHA(*(t - 1))) {
1088 sprintf(t, "%d", ipf->fl_unit);
1089 t += strlen(t);
1090 }
1091 # endif
1092 }
1093 if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0'))
1094 strcat(t, " @-1:");
1095 else if (ipf->fl_group[0] == '\0')
1096 (void) strcpy(t, " @0:");
1097 else
1098 sprintf(t, " @%s:", ipf->fl_group);
1099 t += strlen(t);
1100 if (ipf->fl_rule == 0xffffffff)
1101 strcat(t, "-1 ");
1102 else
1103 sprintf(t, "%u ", ipf->fl_rule + 1);
1104 t += strlen(t);
1105
1106 lvl = LOG_NOTICE;
1107
1108 if (ipf->fl_lflags & FI_SHORT) {
1109 *t++ = 'S';
1110 lvl = LOG_ERR;
1111 }
1112
1113 if (FR_ISPASS(ipf->fl_flags)) {
1114 if (ipf->fl_flags & FR_LOGP)
1115 *t++ = 'p';
1116 else
1117 *t++ = 'P';
1118 } else if (FR_ISBLOCK(ipf->fl_flags)) {
1119 if (ipf->fl_flags & FR_LOGB)
1120 *t++ = 'b';
1121 else
1122 *t++ = 'B';
1123 lvl = LOG_WARNING;
1124 } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) {
1125 *t++ = 'L';
1126 lvl = LOG_INFO;
1127 } else if (ipf->fl_flags & FF_LOGNOMATCH) {
1128 *t++ = 'n';
1129 } else {
1130 *t++ = '?';
1131 lvl = LOG_EMERG;
1132 }
1133 if (ipf->fl_loglevel != 0xffff)
1134 lvl = ipf->fl_loglevel;
1135 *t++ = ' ';
1136 *t = '\0';
1137
1138 if (f == AF_INET) {
1139 hl = IP_HL(ip) << 2;
1140 ipoff = ntohs(ip->ip_off);
1141 off = ipoff & IP_OFFMASK;
1142 p = (u_short)ip->ip_p;
1143 s = (u_32_t *)&ip->ip_src;
1144 d = (u_32_t *)&ip->ip_dst;
1145 plen = ntohs(ip->ip_len);
1146 } else
1147 #ifdef USE_INET6
1148 if (f == AF_INET6) {
1149 off = 0;
1150 ipoff = 0;
1151 hl = sizeof(ip6_t);
1152 ip6 = (ip6_t *)ip;
1153 p = (u_short)ip6->ip6_nxt;
1154 s = (u_32_t *)&ip6->ip6_src;
1155 d = (u_32_t *)&ip6->ip6_dst;
1156 plen = hl + ntohs(ip6->ip6_plen);
1157 go = 1;
1158 ehp = (struct ip6_ext *)((char *)ip6 + hl);
1159 while (go == 1) {
1160 switch (p)
1161 {
1162 case IPPROTO_HOPOPTS :
1163 case IPPROTO_MOBILITY :
1164 case IPPROTO_DSTOPTS :
1165 case IPPROTO_ROUTING :
1166 case IPPROTO_AH :
1167 p = ehp->ip6e_nxt;
1168 ehl = 8 + (ehp->ip6e_len << 3);
1169 hl += ehl;
1170 ehp = (struct ip6_ext *)((char *)ehp + ehl);
1171 break;
1172 case IPPROTO_FRAGMENT :
1173 hl += sizeof(struct ip6_frag);
1174 /* FALLTHROUGH */
1175 default :
1176 go = 0;
1177 break;
1178 }
1179 }
1180 } else
1181 #endif
1182 {
1183 goto printipflog;
1184 }
1185 proto = getlocalproto(p);
1186
1187 if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) {
1188 tp = (tcphdr_t *)((char *)ip + hl);
1189 if (!(ipf->fl_lflags & FI_SHORT)) {
1190 sprintf(t, "%s,%s -> ", hostname(f, s),
1191 portlocalname(res, proto, (u_int)tp->th_sport));
1192 t += strlen(t);
1193 sprintf(t, "%s,%s PR %s len %hu %hu",
1194 hostname(f, d),
1195 portlocalname(res, proto, (u_int)tp->th_dport),
1196 proto, hl, plen);
1197 t += strlen(t);
1198
1199 if (p == IPPROTO_TCP) {
1200 *t++ = ' ';
1201 *t++ = '-';
1202 for (i = 0; tcpfl[i].value; i++)
1203 if (tp->th_flags & tcpfl[i].value)
1204 *t++ = tcpfl[i].flag;
1205 if (ipmonopts & IPMON_VERBOSE) {
1206 sprintf(t, " %lu %lu %hu",
1207 (u_long)(ntohl(tp->th_seq)),
1208 (u_long)(ntohl(tp->th_ack)),
1209 ntohs(tp->th_win));
1210 t += strlen(t);
1211 }
1212 }
1213 *t = '\0';
1214 } else {
1215 sprintf(t, "%s -> ", hostname(f, s));
1216 t += strlen(t);
1217 sprintf(t, "%s PR %s len %hu %hu",
1218 hostname(f, d), proto, hl, plen);
1219 }
1220 #if defined(AF_INET6) && defined(IPPROTO_ICMPV6)
1221 } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) {
1222 ic = (struct icmp *)((char *)ip + hl);
1223 sprintf(t, "%s -> ", hostname(f, s));
1224 t += strlen(t);
1225 sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1226 hostname(f, d), hl, plen,
1227 icmpname6(ic->icmp_type, ic->icmp_code));
1228 #endif
1229 } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) {
1230 ic = (struct icmp *)((char *)ip + hl);
1231 sprintf(t, "%s -> ", hostname(f, s));
1232 t += strlen(t);
1233 sprintf(t, "%s PR icmp len %hu %hu icmp %s",
1234 hostname(f, d), hl, plen,
1235 icmpname(ic->icmp_type, ic->icmp_code));
1236 if (ic->icmp_type == ICMP_UNREACH ||
1237 ic->icmp_type == ICMP_SOURCEQUENCH ||
1238 ic->icmp_type == ICMP_PARAMPROB ||
1239 ic->icmp_type == ICMP_REDIRECT ||
1240 ic->icmp_type == ICMP_TIMXCEED) {
1241 ipc = &ic->icmp_ip;
1242 i = ntohs(ipc->ip_len);
1243 /*
1244 * XXX - try to guess endian of ip_len in ICMP
1245 * returned data.
1246 */
1247 if (i > 1500)
1248 i = ipc->ip_len;
1249 ipoff = ntohs(ipc->ip_off);
1250 proto = getlocalproto(ipc->ip_p);
1251
1252 if (!(ipoff & IP_OFFMASK) &&
1253 ((ipc->ip_p == IPPROTO_TCP) ||
1254 (ipc->ip_p == IPPROTO_UDP))) {
1255 tp = (tcphdr_t *)((char *)ipc + hl);
1256 t += strlen(t);
1257 sprintf(t, " for %s,%s -",
1258 HOSTNAMEV4(ipc->ip_src),
1259 portlocalname(res, proto,
1260 (u_int)tp->th_sport));
1261 t += strlen(t);
1262 sprintf(t, " %s,%s PR %s len %hu %hu",
1263 HOSTNAMEV4(ipc->ip_dst),
1264 portlocalname(res, proto,
1265 (u_int)tp->th_dport),
1266 proto, IP_HL(ipc) << 2, i);
1267 } else if (!(ipoff & IP_OFFMASK) &&
1268 (ipc->ip_p == IPPROTO_ICMP)) {
1269 icmp = (icmphdr_t *)((char *)ipc + hl);
1270
1271 t += strlen(t);
1272 sprintf(t, " for %s -",
1273 HOSTNAMEV4(ipc->ip_src));
1274 t += strlen(t);
1275 sprintf(t,
1276 " %s PR icmp len %hu %hu icmp %d/%d",
1277 HOSTNAMEV4(ipc->ip_dst),
1278 IP_HL(ipc) << 2, i,
1279 icmp->icmp_type, icmp->icmp_code);
1280 } else {
1281 t += strlen(t);
1282 sprintf(t, " for %s -",
1283 HOSTNAMEV4(ipc->ip_src));
1284 t += strlen(t);
1285 sprintf(t, " %s PR %s len %hu (%hu)",
1286 HOSTNAMEV4(ipc->ip_dst), proto,
1287 IP_HL(ipc) << 2, i);
1288 t += strlen(t);
1289 if (ipoff & IP_OFFMASK) {
1290 sprintf(t, "(frag %d:%hu@%hu%s%s)",
1291 ntohs(ipc->ip_id),
1292 i - (IP_HL(ipc) << 2),
1293 (ipoff & IP_OFFMASK) << 3,
1294 ipoff & IP_MF ? "+" : "",
1295 ipoff & IP_DF ? "-" : "");
1296 }
1297 }
1298
1299 }
1300 } else {
1301 sprintf(t, "%s -> ", hostname(f, s));
1302 t += strlen(t);
1303 sprintf(t, "%s PR %s len %hu (%hu)",
1304 hostname(f, d), proto, hl, plen);
1305 t += strlen(t);
1306 if (off & IP_OFFMASK)
1307 sprintf(t, " (frag %d:%hu@%hu%s%s)",
1308 ntohs(ip->ip_id),
1309 plen - hl, (off & IP_OFFMASK) << 3,
1310 ipoff & IP_MF ? "+" : "",
1311 ipoff & IP_DF ? "-" : "");
1312 }
1313 t += strlen(t);
1314
1315 printipflog:
1316 if (ipf->fl_flags & FR_KEEPSTATE) {
1317 (void) strcpy(t, " K-S");
1318 t += strlen(t);
1319 }
1320
1321 if (ipf->fl_flags & FR_KEEPFRAG) {
1322 (void) strcpy(t, " K-F");
1323 t += strlen(t);
1324 }
1325
1326 if (ipf->fl_dir == 0)
1327 strcpy(t, " IN");
1328 else if (ipf->fl_dir == 1)
1329 strcpy(t, " OUT");
1330 t += strlen(t);
1331 if (ipf->fl_logtag != 0) {
1332 sprintf(t, " log-tag %d", ipf->fl_logtag);
1333 t += strlen(t);
1334 }
1335 if (ipf->fl_nattag.ipt_num[0] != 0) {
1336 strcpy(t, " nat-tag ");
1337 t += strlen(t);
1338 strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag));
1339 t += strlen(t);
1340 }
1341 if ((ipf->fl_lflags & FI_LOWTTL) != 0) {
1342 strcpy(t, " low-ttl");
1343 t += 8;
1344 }
1345 if ((ipf->fl_lflags & FI_OOW) != 0) {
1346 strcpy(t, " OOW");
1347 t += 4;
1348 }
1349 if ((ipf->fl_lflags & FI_BAD) != 0) {
1350 strcpy(t, " bad");
1351 t += 4;
1352 }
1353 if ((ipf->fl_lflags & FI_NATED) != 0) {
1354 strcpy(t, " NAT");
1355 t += 4;
1356 }
1357 if ((ipf->fl_lflags & FI_BADNAT) != 0) {
1358 strcpy(t, " bad-NAT");
1359 t += 8;
1360 }
1361 if ((ipf->fl_lflags & FI_BADSRC) != 0) {
1362 strcpy(t, " bad-src");
1363 t += 8;
1364 }
1365 if ((ipf->fl_lflags & FI_MULTICAST) != 0) {
1366 strcpy(t, " multicast");
1367 t += 10;
1368 }
1369 if ((ipf->fl_lflags & FI_BROADCAST) != 0) {
1370 strcpy(t, " broadcast");
1371 t += 10;
1372 }
1373 if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) ==
1374 FI_MBCAST) {
1375 strcpy(t, " mbcast");
1376 t += 7;
1377 }
1378 if (ipf->fl_breason != 0) {
1379 strcpy(t, " reason:");
1380 t += 8;
1381 strcpy(t, reasons[ipf->fl_breason]);
1382 t += strlen(reasons[ipf->fl_breason]);
1383 }
1384 *t++ = '\n';
1385 *t++ = '\0';
1386 defaction = 0;
1387 if (conf->cfile != NULL)
1388 defaction = check_action(buf, line, ipmonopts, lvl);
1389
1390 if (defaction == 0) {
1391 if (ipmonopts & IPMON_SYSLOG) {
1392 syslog(lvl, "%s", line);
1393 } else if (conf->log != NULL) {
1394 (void) fprintf(conf->log, "%s", line);
1395 }
1396
1397 if (ipmonopts & IPMON_HEXHDR) {
1398 dumphex(conf->log, ipmonopts, buf,
1399 sizeof(iplog_t) + sizeof(*ipf));
1400 }
1401 if (ipmonopts & IPMON_HEXBODY) {
1402 dumphex(conf->log, ipmonopts, (char *)ip,
1403 ipf->fl_plen + ipf->fl_hlen);
1404 } else if ((ipmonopts & IPMON_LOGBODY) &&
1405 (ipf->fl_flags & FR_LOGBODY)) {
1406 dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen,
1407 ipf->fl_plen);
1408 }
1409 }
1410 }
1411
1412
1413 static void
usage(char * prog)1414 usage(char *prog)
1415 {
1416 fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n"
1417 "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n"
1418 "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n"
1419 "\t[ <filename> ]\n", prog);
1420 exit(1);
1421 }
1422
1423
1424 static void
write_pid(char * file)1425 write_pid(char *file)
1426 {
1427 FILE *fp = NULL;
1428 int fd;
1429
1430 if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) {
1431 fp = fdopen(fd, "w");
1432 if (fp == NULL) {
1433 close(fd);
1434 fprintf(stderr,
1435 "unable to open/create pid file: %s\n", file);
1436 return;
1437 }
1438 fprintf(fp, "%d", getpid());
1439 fclose(fp);
1440 }
1441 }
1442
1443
1444 static void
flushlogs(char * file,FILE * log)1445 flushlogs(char *file, FILE *log)
1446 {
1447 int fd, flushed = 0;
1448
1449 if ((fd = open(file, O_RDWR)) == -1) {
1450 (void) fprintf(stderr, "%s: open: %s\n",
1451 file, STRERROR(errno));
1452 exit(1);
1453 }
1454
1455 if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
1456 printf("%d bytes flushed from log buffer\n",
1457 flushed);
1458 fflush(stdout);
1459 } else
1460 ipferror(fd, "SIOCIPFFB");
1461 (void) close(fd);
1462
1463 if (flushed) {
1464 if (ipmonopts & IPMON_SYSLOG) {
1465 syslog(LOG_INFO, "%d bytes flushed from log\n",
1466 flushed);
1467 } else if ((log != stdout) && (log != NULL)) {
1468 fprintf(log, "%d bytes flushed from log\n", flushed);
1469 }
1470 }
1471 }
1472
1473
1474 static void
logopts(int turnon,char * options)1475 logopts(int turnon, char *options)
1476 {
1477 int flags = 0;
1478 char *s;
1479
1480 for (s = options; *s; s++)
1481 {
1482 switch (*s)
1483 {
1484 case 'N' :
1485 flags |= IPMON_NAT;
1486 break;
1487 case 'S' :
1488 flags |= IPMON_STATE;
1489 break;
1490 case 'I' :
1491 flags |= IPMON_FILTER;
1492 break;
1493 default :
1494 fprintf(stderr, "Unknown log option %c\n", *s);
1495 exit(1);
1496 }
1497 }
1498
1499 if (turnon)
1500 ipmonopts |= flags;
1501 else
1502 ipmonopts &= ~(flags);
1503 }
1504
1505 static void
initconfig(config_t * conf)1506 initconfig(config_t *conf)
1507 {
1508 int i;
1509
1510 memset(conf, 0, sizeof(*conf));
1511
1512 conf->log = stdout;
1513 conf->maxfd = -1;
1514
1515 for (i = 0; i < 3; i++) {
1516 conf->logsrc[i].fd = -1;
1517 conf->logsrc[i].logtype = -1;
1518 conf->logsrc[i].regular = -1;
1519 }
1520
1521 conf->logsrc[0].file = IPL_NAME;
1522 conf->logsrc[1].file = IPNAT_NAME;
1523 conf->logsrc[2].file = IPSTATE_NAME;
1524
1525 add_doing(&executesaver);
1526 add_doing(&snmpv1saver);
1527 add_doing(&snmpv2saver);
1528 add_doing(&syslogsaver);
1529 add_doing(&filesaver);
1530 add_doing(¬hingsaver);
1531 }
1532
1533
1534 int
main(int argc,char * argv[])1535 main(int argc, char *argv[])
1536 {
1537 int doread, c, make_daemon = 0;
1538 char *prog;
1539 config_t config;
1540
1541 prog = strrchr(argv[0], '/');
1542 if (prog == NULL)
1543 prog = argv[0];
1544 else
1545 prog++;
1546
1547 initconfig(&config);
1548
1549 while ((c = getopt(argc, argv,
1550 "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1)
1551 switch (c)
1552 {
1553 case 'a' :
1554 ipmonopts |= IPMON_LOGALL;
1555 config.logsrc[0].logtype = IPL_LOGIPF;
1556 config.logsrc[1].logtype = IPL_LOGNAT;
1557 config.logsrc[2].logtype = IPL_LOGSTATE;
1558 break;
1559 case 'b' :
1560 ipmonopts |= IPMON_LOGBODY;
1561 break;
1562 case 'B' :
1563 config.bfile = optarg;
1564 config.blog = fopen(optarg, "a");
1565 break;
1566 case 'C' :
1567 config.cfile = optarg;
1568 break;
1569 case 'D' :
1570 make_daemon = 1;
1571 break;
1572 case 'f' : case 'I' :
1573 ipmonopts |= IPMON_FILTER;
1574 config.logsrc[0].logtype = IPL_LOGIPF;
1575 config.logsrc[0].file = optarg;
1576 break;
1577 case 'F' :
1578 flushlogs(config.logsrc[0].file, config.log);
1579 flushlogs(config.logsrc[1].file, config.log);
1580 flushlogs(config.logsrc[2].file, config.log);
1581 break;
1582 case 'L' :
1583 logfac = fac_findname(optarg);
1584 if (logfac == -1) {
1585 fprintf(stderr,
1586 "Unknown syslog facility '%s'\n",
1587 optarg);
1588 exit(1);
1589 }
1590 break;
1591 case 'n' :
1592 ipmonopts |= IPMON_RESOLVE;
1593 opts &= ~OPT_NORESOLVE;
1594 break;
1595 case 'N' :
1596 ipmonopts |= IPMON_NAT;
1597 config.logsrc[1].logtype = IPL_LOGNAT;
1598 config.logsrc[1].file = optarg;
1599 break;
1600 case 'o' : case 'O' :
1601 logopts(c == 'o', optarg);
1602 if (ipmonopts & IPMON_FILTER)
1603 config.logsrc[0].logtype = IPL_LOGIPF;
1604 if (ipmonopts & IPMON_NAT)
1605 config.logsrc[1].logtype = IPL_LOGNAT;
1606 if (ipmonopts & IPMON_STATE)
1607 config.logsrc[2].logtype = IPL_LOGSTATE;
1608 break;
1609 case 'p' :
1610 ipmonopts |= IPMON_PORTNUM;
1611 break;
1612 case 'P' :
1613 pidfile = optarg;
1614 break;
1615 case 's' :
1616 ipmonopts |= IPMON_SYSLOG;
1617 config.log = NULL;
1618 break;
1619 case 'S' :
1620 ipmonopts |= IPMON_STATE;
1621 config.logsrc[2].logtype = IPL_LOGSTATE;
1622 config.logsrc[2].file = optarg;
1623 break;
1624 case 't' :
1625 ipmonopts |= IPMON_TAIL;
1626 break;
1627 case 'v' :
1628 ipmonopts |= IPMON_VERBOSE;
1629 break;
1630 case 'x' :
1631 ipmonopts |= IPMON_HEXBODY;
1632 break;
1633 case 'X' :
1634 ipmonopts |= IPMON_HEXHDR;
1635 break;
1636 default :
1637 case 'h' :
1638 case '?' :
1639 usage(argv[0]);
1640 }
1641
1642 if (ipmonopts & IPMON_SYSLOG)
1643 openlog(prog, LOG_NDELAY|LOG_PID, logfac);
1644
1645 init_tabs();
1646 if (config.cfile)
1647 if (load_config(config.cfile) == -1) {
1648 unload_config();
1649 exit(1);
1650 }
1651
1652 /*
1653 * Default action is to only open the filter log file.
1654 */
1655 if ((config.logsrc[0].logtype == -1) &&
1656 (config.logsrc[0].logtype == -1) &&
1657 (config.logsrc[0].logtype == -1))
1658 config.logsrc[0].logtype = IPL_LOGIPF;
1659
1660 openlogs(&config);
1661
1662 if (!(ipmonopts & IPMON_SYSLOG)) {
1663 config.file = argv[optind];
1664 config.log = config.file ? fopen(config.file, "a") : stdout;
1665 if (config.log == NULL) {
1666 (void) fprintf(stderr, "%s: fopen: %s\n",
1667 argv[optind], STRERROR(errno));
1668 exit(1);
1669 /* NOTREACHED */
1670 }
1671 setvbuf(config.log, NULL, _IONBF, 0);
1672 } else {
1673 config.log = NULL;
1674 }
1675
1676 if (make_daemon &&
1677 ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) {
1678 #ifdef BSD
1679 daemon(0, !(ipmonopts & IPMON_SYSLOG));
1680 #else
1681 int pid;
1682
1683 switch (fork())
1684 {
1685 case -1 :
1686 (void) fprintf(stderr, "%s: fork() failed: %s\n",
1687 argv[0], STRERROR(errno));
1688 exit(1);
1689 /* NOTREACHED */
1690 case 0 :
1691 break;
1692 default :
1693 exit(0);
1694 }
1695
1696 setsid();
1697 if ((ipmonopts & IPMON_SYSLOG))
1698 close(2);
1699 #endif /* !BSD */
1700 close(0);
1701 close(1);
1702 write_pid(pidfile);
1703 }
1704
1705 signal(SIGHUP, handlehup);
1706
1707 for (doread = 1; doread; )
1708 doread = read_loginfo(&config);
1709
1710 unload_config();
1711
1712 return (0);
1713 /* NOTREACHED */
1714 }
1715
1716
1717 static void
openlogs(config_t * conf)1718 openlogs(config_t *conf)
1719 {
1720 logsource_t *l;
1721 struct stat sb;
1722 int i;
1723
1724 for (i = 0; i < 3; i++) {
1725 l = &conf->logsrc[i];
1726 if (l->logtype == -1)
1727 continue;
1728 if (!strcmp(l->file, "-"))
1729 l->fd = 0;
1730 else {
1731 if ((l->fd= open(l->file, O_RDONLY)) == -1) {
1732 (void) fprintf(stderr,
1733 "%s: open: %s\n", l->file,
1734 STRERROR(errno));
1735 exit(1);
1736 /* NOTREACHED */
1737 }
1738
1739 if (fstat(l->fd, &sb) == -1) {
1740 (void) fprintf(stderr, "%d: fstat: %s\n",
1741 l->fd, STRERROR(errno));
1742 exit(1);
1743 /* NOTREACHED */
1744 }
1745
1746 l->regular = !S_ISCHR(sb.st_mode);
1747 if (l->regular)
1748 l->size = sb.st_size;
1749
1750 FD_SET(l->fd, &conf->fdmr);
1751 if (l->fd > conf->maxfd)
1752 conf->maxfd = l->fd;
1753 }
1754 }
1755 }
1756
1757
1758 static int
read_loginfo(config_t * conf)1759 read_loginfo(config_t *conf)
1760 {
1761 iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1];
1762 int n, tr, nr, i;
1763 logsource_t *l;
1764 fd_set fdr;
1765
1766 fdr = conf->fdmr;
1767
1768 n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL);
1769 if (n == 0)
1770 return (1);
1771 if (n == -1) {
1772 if (errno == EINTR)
1773 return (1);
1774 return (-1);
1775 }
1776
1777 for (i = 0, nr = 0; i < 3; i++) {
1778 l = &conf->logsrc[i];
1779
1780 if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr))
1781 continue;
1782
1783 tr = 0;
1784 if (l->regular) {
1785 tr = (lseek(l->fd, 0, SEEK_CUR) < l->size);
1786 if (!tr && !(ipmonopts & IPMON_TAIL))
1787 return (0);
1788 }
1789
1790 n = 0;
1791 tr = read_log(l->fd, &n, (char *)buf, sizeof(buf));
1792 if (donehup) {
1793 if (conf->file != NULL) {
1794 if (conf->log != NULL) {
1795 fclose(conf->log);
1796 conf->log = NULL;
1797 }
1798 conf->log = fopen(conf->file, "a");
1799 }
1800
1801 if (conf->bfile != NULL) {
1802 if (conf->blog != NULL) {
1803 fclose(conf->blog);
1804 conf->blog = NULL;
1805 }
1806 conf->blog = fopen(conf->bfile, "a");
1807 }
1808
1809 init_tabs();
1810 if (conf->cfile != NULL)
1811 load_config(conf->cfile);
1812 donehup = 0;
1813 }
1814
1815 switch (tr)
1816 {
1817 case -1 :
1818 if (ipmonopts & IPMON_SYSLOG)
1819 syslog(LOG_CRIT, "read: %m\n");
1820 else {
1821 ipferror(l->fd, "read");
1822 }
1823 return (0);
1824 case 1 :
1825 if (ipmonopts & IPMON_SYSLOG)
1826 syslog(LOG_CRIT, "aborting logging\n");
1827 else if (conf->log != NULL)
1828 fprintf(conf->log, "aborting logging\n");
1829 return (0);
1830 case 2 :
1831 break;
1832 case 0 :
1833 nr += tr;
1834 if (n > 0) {
1835 print_log(conf, l, (char *)buf, n);
1836 if (!(ipmonopts & IPMON_SYSLOG))
1837 fflush(conf->log);
1838 }
1839 break;
1840 }
1841 }
1842
1843 if (!nr && (ipmonopts & IPMON_TAIL))
1844 sleep(1);
1845
1846 return (1);
1847 }
1848